diff options
author | Adriaan Moors <adriaan@lightbend.com> | 2016-08-31 16:54:11 +0200 |
---|---|---|
committer | Adriaan Moors <adriaan@lightbend.com> | 2016-09-01 01:31:17 +0200 |
commit | 743f0d2c2a33bc8ab0c1f7bee796865672ba2fcc (patch) | |
tree | 9f7d44074ffb05806cb697102572460d01d36283 | |
parent | c0763b05dac2e3d12301e828f4f1aaf83b4e41ac (diff) | |
download | scala-743f0d2c2a33bc8ab0c1f7bee796865672ba2fcc.tar.gz scala-743f0d2c2a33bc8ab0c1f7bee796865672ba2fcc.tar.bz2 scala-743f0d2c2a33bc8ab0c1f7bee796865672ba2fcc.zip |
Lazy val without local.
Now `synchronized` is erased specially to avoid boxing,
we can drop that work around.
Note that this does add an extra cast and getter
call on the slow path, but that likely doesn't matter.
```
class C { def foo = {lazy val x = {println("a"); "A" }; x } }
```
becomes
```
def foo(): String = {
lazy <artifact> val x$lzy: scala.runtime.LazyRef[String] = new scala.runtime.LazyRef[String]();
<artifact> private def x$lzycompute(): String =
x$lzy.synchronized[String]{
if (x$lzy.initialized())
x$lzy.value() // NOTE: gets an `.asInstanceOf[String]` after erasure
else
{
x$lzy.value_=({
scala.Predef.println("a");
"A"
});
x$lzy.initialized_=(true);
x$lzy.value() // NOTE: gets an `.asInstanceOf[String]` after erasure
}
}
lazy def x(): String =
if (x$lzy.initialized())
x$lzy.value() // NOTE: gets an `.asInstanceOf[String]` after erasure
else
x$lzycompute();
x()
}
```
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Fields.scala | 14 |
1 files changed, 4 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Fields.scala b/src/compiler/scala/tools/nsc/transform/Fields.scala index 3403c35152..3529fbd0eb 100644 --- a/src/compiler/scala/tools/nsc/transform/Fields.scala +++ b/src/compiler/scala/tools/nsc/transform/Fields.scala @@ -573,17 +573,11 @@ abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransfor if (isUnit) gen.mkSynchronized(Ident(holderSym))(mkChecked(alreadyComputed = UNIT, compute = Block(List(rhsAtComputer, setInitialized), UNIT))) else { - // we write to a local var outside of the synchronized block to avoid boxing/unboxing (synchronized method is polymorphic) - val resVarSym = computerSym.newVariable(localLazyName, pos, ARTIFACT) setInfo lazyValType + val valueSetter = Select(Ident(holderSym), valueGetter.setterIn(refClass)) - val alreadyComputed = Assign(Ident(resVarSym), getValue) - val storeComputed = Apply(Select(Ident(holderSym), valueGetter.setterIn(refClass)), Ident(resVarSym) :: Nil) - val compute = Block(List(Assign(Ident(resVarSym), rhsAtComputer), storeComputed), setInitialized) - - Block( - mkTypedValDef(resVarSym) :: - gen.mkSynchronized(Ident(holderSym))(mkChecked(alreadyComputed, compute)) :: Nil, - Ident(resVarSym) + gen.mkSynchronized(Ident(holderSym))(mkChecked( + alreadyComputed = getValue, + compute = Block(Apply(valueSetter, rhsAtComputer :: Nil) :: setInitialized :: Nil, getValue)) ) } } |