@@ -10,14 +10,16 @@ import core.Decorators._
10
10
import core .StdNames .nme
11
11
import core .Names ._
12
12
import core .NameKinds .TempResultName
13
+ import core .Constants ._
13
14
import ast .Trees ._
14
15
import util .Store
15
16
import collection .mutable
16
17
17
18
/** This phase translates variables that are captured in closures to
18
19
* heap-allocated refs.
19
20
*/
20
- class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisPhase =>
21
+ class CapturedVars extends MiniPhase with IdentityDenotTransformer :
22
+ thisPhase =>
21
23
import ast .tpd ._
22
24
23
25
/** the following two members override abstract members in Transform */
@@ -45,6 +47,9 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisPhase =
45
47
46
48
val boxedRefClasses : collection.Set [Symbol ] =
47
49
refClassKeys.flatMap(k => Set (refClass(k), volatileRefClass(k)))
50
+
51
+ val objectRefClasses : collection.Set [Symbol ] =
52
+ Set (refClass(defn.ObjectClass ), volatileRefClass(defn.ObjectClass ))
48
53
}
49
54
50
55
private var myRefInfo : RefInfo = null
@@ -123,32 +128,42 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer { thisPhase =
123
128
}
124
129
125
130
/** If assignment is to a boxed ref type, e.g.
126
- *
127
- * intRef.elem = expr
128
- *
129
- * rewrite using a temporary var to
130
- *
131
- * val ev$n = expr
132
- * intRef.elem = ev$n
133
- *
134
- * That way, we avoid the problem that `expr` might contain a `try` that would
135
- * run on a non-empty stack (which is illegal under JVM rules). Note that LiftTry
136
- * has already run before, so such `try`s would not be eliminated.
137
- *
138
- * Also: If the ref type lhs is followed by a cast (can be an artifact of nested translation),
139
- * drop the cast.
140
- */
141
- override def transformAssign (tree : Assign )(using Context ): Tree = {
142
- def recur (lhs : Tree ): Tree = lhs match {
143
- case TypeApply (Select (qual, nme.asInstanceOf_), _) =>
144
- val Select (_, nme.elem) = qual
131
+ *
132
+ * intRef.elem = expr
133
+ *
134
+ * rewrite using a temporary var to
135
+ *
136
+ * val ev$n = expr
137
+ * intRef.elem = ev$n
138
+ *
139
+ * That way, we avoid the problem that `expr` might contain a `try` that would
140
+ * run on a non-empty stack (which is illegal under JVM rules). Note that LiftTry
141
+ * has already run before, so such `try`s would not be eliminated.
142
+ *
143
+ * If the ref type lhs is followed by a cast (can be an artifact of nested translation),
144
+ * drop the cast.
145
+ *
146
+ * If the ref type is `ObjectRef` or `VolatileObjectRef`, immediately assign `null`
147
+ * to the temporary to make the underlying target of the reference available for
148
+ * garbage collection. Nullification is omitted if the `expr` is already `null`.
149
+ *
150
+ * var ev$n: RHS = expr
151
+ * objRef.elem = ev$n
152
+ * ev$n = null.asInstanceOf[RHS]
153
+ */
154
+ override def transformAssign (tree : Assign )(using Context ): Tree =
155
+ def absolved : Boolean = tree.rhs match
156
+ case Literal (Constant (null )) | Typed (Literal (Constant (null )), _) => true
157
+ case _ => false
158
+ def recur (lhs : Tree ): Tree = lhs match
159
+ case TypeApply (Select (qual@ Select (_, nme.elem), nme.asInstanceOf_), _) =>
145
160
recur(qual)
146
161
case Select (_, nme.elem) if refInfo.boxedRefClasses.contains(lhs.symbol.maybeOwner) =>
147
- val tempDef = transformFollowing(SyntheticValDef (TempResultName .fresh(), tree.rhs))
148
- transformFollowing(Block (tempDef :: Nil , cpy.Assign (tree)(lhs, ref(tempDef.symbol))))
162
+ val tempDef = transformFollowing(SyntheticValDef (TempResultName .fresh(), tree.rhs, flags = Mutable ))
163
+ val update = cpy.Assign (tree)(lhs, ref(tempDef.symbol))
164
+ def reset = cpy.Assign (tree)(ref(tempDef.symbol), nullLiteral.cast(tempDef.symbol.info))
165
+ val res = if refInfo.objectRefClasses(lhs.symbol.maybeOwner) && ! absolved then reset else unitLiteral
166
+ transformFollowing(Block (tempDef :: update :: Nil , res))
149
167
case _ =>
150
168
tree
151
- }
152
169
recur(tree.lhs)
153
- }
154
- }
0 commit comments