summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan@lightbend.com>2016-08-31 16:54:11 +0200
committerAdriaan Moors <adriaan@lightbend.com>2016-09-01 01:31:17 +0200
commit743f0d2c2a33bc8ab0c1f7bee796865672ba2fcc (patch)
tree9f7d44074ffb05806cb697102572460d01d36283 /src
parentc0763b05dac2e3d12301e828f4f1aaf83b4e41ac (diff)
downloadscala-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() } ```
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/transform/Fields.scala14
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))
)
}
}