@@ -33,7 +33,6 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
33
33
*/
34
34
class OldOffsetInfo (defs : List [Tree ], var ord : Int ) extends OffsetInfo (defs)
35
35
private val appendOffsetDefs = mutable.Map .empty[Symbol , OffsetInfo ]
36
- private val oldAppendOffsetDefs = mutable.Map .empty[Symbol , OldOffsetInfo ]
37
36
38
37
override def phaseName : String = LazyVals .name
39
38
@@ -59,9 +58,6 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
59
58
else nullables.toList
60
59
}
61
60
62
- private inline def isOldLazyVals (using ctx : Context ): Boolean =
63
- import dotty .tools .dotc .config .ScalaRelease ._
64
- ctx.scalaRelease <= Release3_1
65
61
66
62
private def initBlock (stats : List [Tree ])(using Context ): Block = stats match
67
63
case Nil => throw new IllegalArgumentException (" trying to create an empty Block" )
@@ -127,7 +123,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
127
123
override def transformTemplate (template : Template )(using Context ): Tree = {
128
124
val cls = ctx.owner.asClass
129
125
130
- ( if isOldLazyVals then oldAppendOffsetDefs else appendOffsetDefs) .get(cls) match {
126
+ appendOffsetDefs.get(cls) match {
131
127
case None => template
132
128
case Some (data) =>
133
129
data.defs.foreach(_.symbol.addAnnotation(Annotation (defn.ScalaStaticAnnot )))
@@ -295,12 +291,7 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
295
291
296
292
def transformMemberDefThreadSafe (x : ValOrDefDef )(using Context ): Thicket = {
297
293
assert(! (x.symbol is Mutable ))
298
- // generate old code for compatibility
299
- // TODO find more meaningful names than old/new
300
- if isOldLazyVals then
301
- transformMemberDefThreadSafeOld(x)
302
- else
303
- transformMemberDefThreadSafeNew(x)
294
+ transformMemberDefThreadSafeNew(x)
304
295
}
305
296
306
297
/**
@@ -309,8 +300,6 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
309
300
* private @volatile var _x: AnyRef = null
310
301
* @tailrec def x: A =
311
302
* _x match
312
- * case current: A =>
313
- * current
314
303
* case null =>
315
304
* if CAS(_x, null, Evaluating) then
316
305
* var result: AnyRef = null // here, we need `AnyRef` to possibly assign `NULL`
@@ -331,6 +320,8 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
331
320
* current.awaitRelease()
332
321
* x
333
322
* case NULL => null
323
+ * case current: A =>
324
+ * current
334
325
* ```
335
326
* Where `Evaluating` and `NULL` are represented by `object`s and `Waiting` by a class that
336
327
* allows awaiting the completion of the evaluation. Note that since tail-recursive
@@ -359,11 +350,11 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
359
350
* if current.isInstanceOf[Evaluating] then
360
351
* CAS(current, Evaluating, new Waiting)
361
352
* else if current.isInstanceOf[NULL] then
362
- * null
353
+ * return null
363
354
* else if current.isInstanceOf[Waiting] then
364
355
* current.asInstanceOf[Waiting].awaitRelease()
365
356
* else
366
- * current.asInstanceOf[A]
357
+ * return current.asInstanceOf[A]
367
358
* end while
368
359
* ```
369
360
*
@@ -476,23 +467,24 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
476
467
containerSymbol.setFlag(JavaStatic )
477
468
val getOffset =
478
469
if stat then
479
- Select (ref(helperModule), lazyNme.RLazyVals .getStaticOffset )
470
+ Select (ref(helperModule), lazyNme.RLazyVals .getStaticFieldOffset )
480
471
else
481
- Select (ref(helperModule), lazyNme.RLazyVals .getOffset )
472
+ Select (ref(helperModule), lazyNme.RLazyVals .getOffsetStatic )
482
473
val containerTree = ValDef (containerSymbol, nullLiteral)
483
- def staticOrFieldOff : Tree = getOffset.appliedTo(thizClass, Literal (Constant (containerName.toString)))
484
474
485
475
// create an offset for this lazy val
486
476
appendOffsetDefs.get(claz) match
487
477
case Some (info) =>
488
478
offsetSymbol = newSymbol(claz, offsetName(info.defs.size), Synthetic , defn.LongType ).enteredAfter(this )
489
479
offsetSymbol.nn.addAnnotation(Annotation (defn.ScalaStaticAnnot ))
490
- val offsetTree = ValDef (offsetSymbol.nn, staticOrFieldOff)
480
+ val fieldTree = thizClass.select(lazyNme.RLazyVals .getDeclaredField).appliedTo(Literal (Constant (containerName.toString)))
481
+ val offsetTree = ValDef (offsetSymbol.nn, getOffset.appliedTo(fieldTree))
491
482
info.defs = offsetTree :: info.defs
492
483
case None =>
493
484
offsetSymbol = newSymbol(claz, offsetName(0 ), Synthetic , defn.LongType ).enteredAfter(this )
494
485
offsetSymbol.nn.addAnnotation(Annotation (defn.ScalaStaticAnnot ))
495
- val offsetTree = ValDef (offsetSymbol.nn, staticOrFieldOff)
486
+ val fieldTree = thizClass.select(lazyNme.RLazyVals .getDeclaredField).appliedTo(Literal (Constant (containerName.toString)))
487
+ val offsetTree = ValDef (offsetSymbol.nn, getOffset.appliedTo(fieldTree))
496
488
appendOffsetDefs += (claz -> new OffsetInfo (List (offsetTree)))
497
489
498
490
val waiting = requiredClass(s " $runtimeModule. ${lazyNme.RLazyVals .waiting}" )
@@ -513,171 +505,6 @@ class LazyVals extends MiniPhase with IdentityDenotTransformer {
513
505
ref(waiting), evaluating, nullValued, swapOver)
514
506
Thicket (containerTree, accessor)
515
507
}
516
-
517
- /** Create a threadsafe lazy accessor equivalent to such code
518
- * ```
519
- * def methodSymbol(): Int = {
520
- * while (true) {
521
- * val flag = LazyVals.get(this, bitmap_offset)
522
- * val state = LazyVals.STATE(flag, <field-id>)
523
- *
524
- * if (state == <state-3>) {
525
- * return value_0
526
- * } else if (state == <state-0>) {
527
- * if (LazyVals.CAS(this, bitmap_offset, flag, <state-1>, <field-id>)) {
528
- * try {
529
- * val result = <RHS>
530
- * value_0 = result
531
- * nullable = null
532
- * LazyVals.setFlag(this, bitmap_offset, <state-3>, <field-id>)
533
- * return result
534
- * }
535
- * catch {
536
- * case ex =>
537
- * LazyVals.setFlag(this, bitmap_offset, <state-0>, <field-id>)
538
- * throw ex
539
- * }
540
- * }
541
- * } else /* if (state == <state-1> || state == <state-2>) */ {
542
- * LazyVals.wait4Notification(this, bitmap_offset, flag, <field-id>)
543
- * }
544
- * }
545
- * }
546
- * ```
547
- */
548
- def mkThreadSafeDefOld (methodSymbol : TermSymbol ,
549
- claz : ClassSymbol ,
550
- ord : Int ,
551
- target : Symbol ,
552
- rhs : Tree ,
553
- tp : Type ,
554
- offset : Tree ,
555
- getFlag : Tree ,
556
- stateMask : Tree ,
557
- casFlag : Tree ,
558
- setFlagState : Tree ,
559
- waitOnLock : Tree )(using Context ): DefDef = {
560
- val initState = Literal (Constant (0 ))
561
- val computeState = Literal (Constant (1 ))
562
- val computedState = Literal (Constant (3 ))
563
-
564
- val thiz = This (claz)
565
- val fieldId = Literal (Constant (ord))
566
-
567
- val flagSymbol = newSymbol(methodSymbol, lazyNme.flag, Synthetic , defn.LongType )
568
- val flagDef = ValDef (flagSymbol, getFlag.appliedTo(thiz, offset))
569
- val flagRef = ref(flagSymbol)
570
-
571
- val stateSymbol = newSymbol(methodSymbol, lazyNme.state, Synthetic , defn.LongType )
572
- val stateDef = ValDef (stateSymbol, stateMask.appliedTo(ref(flagSymbol), Literal (Constant (ord))))
573
- val stateRef = ref(stateSymbol)
574
-
575
- val compute = {
576
- val resultSymbol = newSymbol(methodSymbol, lazyNme.result, Synthetic , tp)
577
- val resultRef = ref(resultSymbol)
578
- val stats = (
579
- ValDef (resultSymbol, rhs) ::
580
- ref(target).becomes(resultRef) ::
581
- (nullOut(nullableFor(methodSymbol)) :+
582
- setFlagState.appliedTo(thiz, offset, computedState, fieldId))
583
- )
584
- Block (stats, Return (resultRef, methodSymbol))
585
- }
586
-
587
- val retryCase = {
588
- val caseSymbol = newSymbol(methodSymbol, nme.DEFAULT_EXCEPTION_NAME , Synthetic | Case , defn.ThrowableType )
589
- val triggerRetry = setFlagState.appliedTo(thiz, offset, initState, fieldId)
590
- CaseDef (
591
- Bind (caseSymbol, ref(caseSymbol)),
592
- EmptyTree ,
593
- Block (List (triggerRetry), Throw (ref(caseSymbol)))
594
- )
595
- }
596
-
597
- val initialize = If (
598
- casFlag.appliedTo(thiz, offset, flagRef, computeState, fieldId),
599
- Try (compute, List (retryCase), EmptyTree ),
600
- unitLiteral
601
- )
602
-
603
- val condition = If (
604
- stateRef.equal(computedState),
605
- Return (ref(target), methodSymbol),
606
- If (
607
- stateRef.equal(initState),
608
- initialize,
609
- waitOnLock.appliedTo(thiz, offset, flagRef, fieldId)
610
- )
611
- )
612
-
613
- val loop = WhileDo (EmptyTree , Block (List (flagDef, stateDef), condition))
614
- DefDef (methodSymbol, loop)
615
- }
616
-
617
- def transformMemberDefThreadSafeOld (x : ValOrDefDef )(using Context ): Thicket = {
618
- val tpe = x.tpe.widen.resultType.widen
619
- val claz = x.symbol.owner.asClass
620
- val thizClass = Literal (Constant (claz.info))
621
- val helperModule = requiredModule(" scala.runtime.LazyVals" )
622
- val getOffset = Select (ref(helperModule), lazyNme.RLazyVals .getOffset)
623
- val getOffsetStatic = Select (ref(helperModule), lazyNme.RLazyVals .getOffsetStatic)
624
- var offsetSymbol : TermSymbol | Null = null
625
- var flag : Tree = EmptyTree
626
- var ord = 0
627
-
628
- def offsetName (id : Int ) = s " ${StdNames .nme.LAZY_FIELD_OFFSET }${if (x.symbol.owner.is(Module )) " _m_" else " " }$id" .toTermName
629
-
630
- // compute or create appropriate offsetSymbol, bitmap and bits used by current ValDef
631
- oldAppendOffsetDefs.get(claz) match {
632
- case Some (info) =>
633
- val flagsPerLong = (64 / scala.runtime.LazyVals .BITS_PER_LAZY_VAL ).toInt
634
- info.ord += 1
635
- ord = info.ord % flagsPerLong
636
- val id = info.ord / flagsPerLong
637
- val offsetById = offsetName(id)
638
- if (ord != 0 ) // there are unused bits in already existing flag
639
- offsetSymbol = claz.info.decl(offsetById)
640
- .suchThat(sym => sym.is(Synthetic ) && sym.isTerm)
641
- .symbol.asTerm
642
- else { // need to create a new flag
643
- offsetSymbol = newSymbol(claz, offsetById, Synthetic , defn.LongType ).enteredAfter(this )
644
- offsetSymbol.nn.addAnnotation(Annotation (defn.ScalaStaticAnnot ))
645
- val flagName = LazyBitMapName .fresh(id.toString.toTermName)
646
- val flagSymbol = newSymbol(claz, flagName, containerFlags, defn.LongType ).enteredAfter(this )
647
- flag = ValDef (flagSymbol, Literal (Constant (0L )))
648
- val fieldTree = thizClass.select(lazyNme.RLazyVals .getDeclaredField).appliedTo(Literal (Constant (flagName.toString)))
649
- val offsetTree = ValDef (offsetSymbol.nn, getOffsetStatic.appliedTo(fieldTree))
650
- info.defs = offsetTree :: info.defs
651
- }
652
-
653
- case None =>
654
- offsetSymbol = newSymbol(claz, offsetName(0 ), Synthetic , defn.LongType ).enteredAfter(this )
655
- offsetSymbol.nn.addAnnotation(Annotation (defn.ScalaStaticAnnot ))
656
- val flagName = LazyBitMapName .fresh(" 0" .toTermName)
657
- val flagSymbol = newSymbol(claz, flagName, containerFlags, defn.LongType ).enteredAfter(this )
658
- flag = ValDef (flagSymbol, Literal (Constant (0L )))
659
- val fieldTree = thizClass.select(lazyNme.RLazyVals .getDeclaredField).appliedTo(Literal (Constant (flagName.toString)))
660
- val offsetTree = ValDef (offsetSymbol.nn, getOffsetStatic.appliedTo(fieldTree))
661
- appendOffsetDefs += (claz -> new OffsetInfo (List (offsetTree), ord))
662
- }
663
-
664
- val containerName = LazyLocalName .fresh(x.name.asTermName)
665
- val containerSymbol = newSymbol(claz, containerName, x.symbol.flags &~ containerFlagsMask | containerFlags, tpe, coord = x.symbol.coord).enteredAfter(this )
666
-
667
- val containerTree = ValDef (containerSymbol, defaultValue(tpe))
668
-
669
- val offset = ref(offsetSymbol.nn)
670
- val getFlag = Select (ref(helperModule), lazyNme.RLazyVals .get)
671
- val setFlag = Select (ref(helperModule), lazyNme.RLazyVals .setFlag)
672
- val wait = Select (ref(helperModule), lazyNme.RLazyVals .wait4Notification)
673
- val state = Select (ref(helperModule), lazyNme.RLazyVals .state)
674
- val cas = Select (ref(helperModule), lazyNme.RLazyVals .cas)
675
-
676
- val accessor = mkThreadSafeDefOld(x.symbol.asTerm, claz, ord, containerSymbol, x.rhs, tpe, offset, getFlag, state, cas, setFlag, wait)
677
- if (flag eq EmptyTree )
678
- Thicket (containerTree, accessor)
679
- else Thicket (containerTree, flag, accessor)
680
- }
681
508
}
682
509
683
510
object LazyVals {
@@ -694,15 +521,14 @@ object LazyVals {
694
521
val evaluating : TermName = N .evaluating.toTermName
695
522
val nullValued : TermName = N .nullValued.toTermName
696
523
val objCas : TermName = N .objCas.toTermName
697
- val getOffset : TermName = N .getOffset.toTermName
698
- val getStaticOffset : TermName = N .getStaticOffset.toTermName
524
+ val getStaticFieldOffset : TermName = N .getStaticFieldOffset.toTermName
699
525
val get : TermName = N .get.toTermName
700
526
val setFlag : TermName = N .setFlag.toTermName
701
527
val wait4Notification : TermName = N .wait4Notification.toTermName
702
528
val state : TermName = N .state.toTermName
703
529
val cas : TermName = N .cas.toTermName
704
530
val getOffset : TermName = N .getOffset.toTermName
705
- val getOffsetStatic : TermName = " getOffsetStatic" .toTermName
531
+ val getOffsetStatic : TermName = N . getOffsetStatic.toTermName
706
532
val getDeclaredField : TermName = " getDeclaredField" .toTermName
707
533
708
534
}
0 commit comments