diff options
author | Adriaan Moors <adriaan@lightbend.com> | 2016-09-02 19:25:46 +0200 |
---|---|---|
committer | Adriaan Moors <adriaan@lightbend.com> | 2016-09-02 19:53:20 +0200 |
commit | c1bd0eadd3412643f95b63d27519b369eabb755d (patch) | |
tree | 1453c7bbe92b18c070365b0cad88cfecd632d93a /src/compiler/scala/tools/nsc/transform/Fields.scala | |
parent | 50462a45dcbe91ef43652c235721b7a7ec0c8bb2 (diff) | |
download | scala-c1bd0eadd3412643f95b63d27519b369eabb755d.tar.gz scala-c1bd0eadd3412643f95b63d27519b369eabb755d.tar.bz2 scala-c1bd0eadd3412643f95b63d27519b369eabb755d.zip |
More elegant holders for local lazy vals.
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/Fields.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Fields.scala | 42 |
1 files changed, 18 insertions, 24 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Fields.scala b/src/compiler/scala/tools/nsc/transform/Fields.scala index 3529fbd0eb..a383b65192 100644 --- a/src/compiler/scala/tools/nsc/transform/Fields.scala +++ b/src/compiler/scala/tools/nsc/transform/Fields.scala @@ -528,10 +528,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor * def x$lzycompute(): Int = * x$lzy.synchronized { * if (x$lzy.initialized()) x$lzy.value() - * else { - * x$lzy.initialized = true - * x$lzy.value = rhs - * } + * else x$lzy.initialize(rhs) // for a Unit-typed lazy val, this becomes `{ rhs ; x$lzy.initialize() }` to avoid passing around BoxedUnit * } * def x(): Int = if (x$lzy.initialized()) x$lzy.value() else x$lzycompute() * ``` @@ -543,6 +540,7 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor val lazyValType = lazyVal.tpe.resultType val refClass = lazyHolders.getOrElse(lazyValType.typeSymbol, LazyRefClass) + val isUnit = refClass == LazyUnitClass val refTpe = if (refClass != LazyRefClass) refClass.tpe else appliedType(refClass.typeConstructor, List(lazyValType)) val lazyName = lazyVal.name.toTermName @@ -556,33 +554,29 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor // Must be marked LAZY to allow forward references, as in `def test2 { println(s.length) ; lazy val s = "abc" } val holderSym = owner.newValue(localLazyName, pos, LAZY | ARTIFACT) setInfo refTpe - val initializedGetter = refTpe.member(nme.initialized) - val isUnit = refClass == LazyUnitClass - val valueGetter = if (isUnit) NoSymbol else refTpe.member(nme.value) - def getValue = if (isUnit) UNIT else Apply(Select(Ident(holderSym), valueGetter), Nil) + val initializedSym = refTpe.member(nme.initialized) + val initializeSym = refTpe.member(nme.initialize) + + // LazyUnit does not have a `value` member + val valueSym = if (isUnit) NoSymbol else refTpe.member(nme.value) - def mkChecked(alreadyComputed: Tree, compute: Tree) = If(Ident(holderSym) DOT initializedGetter, alreadyComputed, compute) + def initialized = Select(Ident(holderSym), initializedSym) + def initialize = Select(Ident(holderSym), initializeSym) + def getValue = if (isUnit) UNIT else Apply(Select(Ident(holderSym), valueSym), Nil) val computerSym = owner.newMethod(lazyName append nme.LAZY_SLOW_SUFFIX, pos, ARTIFACT | PRIVATE) setInfo MethodType(Nil, lazyValType) val rhsAtComputer = rhs.changeOwner(lazyVal -> computerSym) - val computer = mkAccessor(computerSym) { - val setInitialized = Apply(Select(Ident(holderSym), initializedGetter.setterIn(refClass)), TRUE :: Nil) - - if (isUnit) - gen.mkSynchronized(Ident(holderSym))(mkChecked(alreadyComputed = UNIT, compute = Block(List(rhsAtComputer, setInitialized), UNIT))) - else { - val valueSetter = Select(Ident(holderSym), valueGetter.setterIn(refClass)) - - gen.mkSynchronized(Ident(holderSym))(mkChecked( - alreadyComputed = getValue, - compute = Block(Apply(valueSetter, rhsAtComputer :: Nil) :: setInitialized :: Nil, getValue)) - ) - } - } - val accessor = mkAccessor(lazyVal)(mkChecked(getValue, Apply(Ident(computerSym), Nil))) + val computer = mkAccessor(computerSym)(gen.mkSynchronized(Ident(holderSym))( + If(initialized, getValue, + if (isUnit) Block(rhsAtComputer :: Nil, Apply(initialize, Nil)) + else Apply(initialize, rhsAtComputer :: Nil)))) + + val accessor = mkAccessor(lazyVal)( + If(initialized, getValue, + Apply(Ident(computerSym), Nil))) // do last! // remove STABLE: prevent replacing accessor call of type Unit by BoxedUnit.UNIT in erasure |