@@ -104,8 +104,8 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
104
104
}
105
105
}
106
106
107
- /**
108
- * Append offset fields to companion objects.
107
+
108
+ /** Append offset fields to companion objects
109
109
*/
110
110
override def transformTemplate (template : Template )(using Context ): Tree = {
111
111
val cls = ctx.owner.asClass
@@ -122,10 +122,10 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
122
122
case _ => prefix ::: stats
123
123
}
124
124
125
- /**
126
- * Make an eager val that would implement synthetic module .
127
- * Eager val ensures thread safety and has less code generated.
128
- */
125
+ /** Make an eager val that would implement synthetic module.
126
+ * Eager val ensures thread safety and has less code generated .
127
+ *
128
+ */
129
129
def transformSyntheticModule (tree : ValOrDefDef )(using Context ): Thicket = {
130
130
val sym = tree.symbol
131
131
val holderSymbol = newSymbol(sym.owner, LazyLocalName .fresh(sym.asTerm.name),
@@ -135,8 +135,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
135
135
Thicket (field, getter)
136
136
}
137
137
138
- /**
139
- * Desugar a local `lazy val x: Int = <RHS>` into:
138
+ /** Desugar a local `lazy val x: Int = <RHS>` into:
140
139
*
141
140
* ```
142
141
* val x$lzy = new scala.runtime.LazyInt()
@@ -276,75 +275,47 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
276
275
}
277
276
278
277
/**
279
- * Create a threadsafe lazy accessor equivalent to the following code:
278
+ * Create a threadsafe lazy accessor and function that computes the field's value. `Evaluating` and
279
+ * `NullValue` are represented by `object`s and `Waiting` by a class that allows awaiting the completion
280
+ * of the evaluation. Note that since tail-recursive functions are transformed *before* lazy-vals,
281
+ * this implementation does involve explicit while loop. `PatternMatcher` is coming before `LazyVals`,
282
+ * therefore the pattern matching is implemented using if-s.
283
+ *
280
284
* ```
281
285
* private @volatile var _x: AnyRef = null
282
- * @tailrec def x: A =
283
- * _x match
284
- * case current: A =>
285
- * current
286
- * case NullValue => null
287
- * case null =>
288
- * if CAS(_x, null, Evaluating) then
289
- * var result: AnyRef = null // here, we need `AnyRef` to possibly assign `NullValue`
290
- * try
291
- * result = rhs
292
- * nullable = null // if the field is nullable; see `CollectNullableFields`
293
- * finally
294
- * if result == null then result = NullValue // drop if A is non-nullable
295
- * if !CAS(_x, Evaluating, result) then
296
- * val lock = _x.asInstanceOf[Waiting]
297
- * CAS(_x, lock, result)
298
- * lock.release()
299
- * x
300
- * case Evaluating =>
301
- * CAS(_x, Evaluating, new Waiting)
302
- * x
303
- * case current: Waiting =>
304
- * current.awaitRelease()
305
- * x
306
- * ```
307
- * Where `Evaluating` and `NullValue` are represented by `object`s and `Waiting` by a class that
308
- * allows awaiting the completion of the evaluation. Note that since tail-recursive
309
- * functions are transformed *before* lazy-vals, this implementation directly implements
310
- * the resulting loop. `PatternMatcher` coming before `LazyVals`, the pattern matching block
311
- * is implemented using if-s. Additionally, the code can be optimized to be better inlined by
312
- * introducing separate function for computing the lazy value and awaiting it. That is:
313
- *
314
- * ```
315
- * private var _x: AnyRef = null
316
286
*
317
287
* def x: A =
318
- * if !(_x == null || _x.isInstanceOf[LazyValControlState]) then
319
- * return _x.asInstanceOf[A]
320
- * else if _x == NullValue then
321
- * return null
288
+ * val result = _x
289
+ * if result.isInstanceOf[A] then
290
+ * result // possible unboxing applied here
291
+ * else if result.eq(NullValue) then
292
+ * null // possible unboxing applied here
322
293
* else
323
- * return x_compute()
294
+ * return x_compute() // possible unboxing applied here
324
295
*
325
296
* private def x_compute() =
326
297
* while <EmptyTree> do
327
298
* val current: AnyRef = _x
328
- * if current == null then
299
+ * if current.eq( null) then
329
300
* if CAS(_x, null, Evaluating) then
330
301
* var resultNullable: AnyRef = null
331
302
* var result: AnyRef = null
332
303
* try
333
304
* resultNullable = rhs
334
- * nullable = null
335
- * if resultNullable == null then
305
+ * nullable = null // nulls out the nullable fields used only in initialization
306
+ * if resultNullable.eq( null) then
336
307
* result = NullValue
337
308
* else
338
309
* result = resultNullable
339
- * return result
340
310
* finally
341
311
* if !CAS(_x, Evaluating, result) then
342
312
* val lock = _x.asInstanceOf[Waiting]
343
313
* CAS(_x, lock, result)
344
314
* lock.release()
315
+ * return resultNullable
345
316
* else
346
317
* if current.isInstanceOf[LazyValControlState] then
347
- * if current.isInstanceOf[ Evaluating] then // To avoid creating Waiting instance
318
+ * if current.eq( Evaluating) then // To avoid creating Waiting instance
348
319
* CAS(current, Evaluating, new Waiting)
349
320
* else if current.isInstanceOf[Waiting] then
350
321
* current.asInstanceOf[Waiting].await()
@@ -353,7 +324,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
353
324
* return current.asInstanceOf[A]
354
325
* end while
355
326
* * ```
356
- *
327
+ *
357
328
* @param memberDef the transformed lazy field member definition
358
329
* @param claz the class containing this lazy val field
359
330
* @param target the target synthetic field
@@ -469,7 +440,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
469
440
Return (ref(current), lazyInitMethodSymbol)
470
441
)
471
442
472
- val initBody = Block (ValDef (current, ref(target)) :: Nil , If (ref(current).equal (nullLiteral), initialize, ifNotUninitialized).withType(defn.UnitType ))
443
+ val initBody = Block (ValDef (current, ref(target)) :: Nil , If (ref(current).select(defn. Object_eq ).appliedTo (nullLiteral), initialize, ifNotUninitialized).withType(defn.UnitType ))
473
444
val initMainLoop = WhileDo (EmptyTree , initBody) // becomes: while (true) do { body }
474
445
val initMethodDef = DefDef (lazyInitMethodSymbol, initMainLoop)
475
446
(accessorDef, initMethodDef)
0 commit comments