Skip to content

Commit ed8b3f0

Browse files
committed
Merge pull request #706 from dotty-staging/fix-676
Generate less code for lazy vals
2 parents d07e5d1 + 688feee commit ed8b3f0

File tree

1 file changed

+43
-13
lines changed

1 file changed

+43
-13
lines changed

src/dotty/tools/dotc/transform/LazyVals.scala

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,35 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
4646
* before this phase starts processing same tree */
4747
override def runsAfter = Set(classOf[Mixin])
4848

49-
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
50-
if (!(tree.symbol is Flags.Lazy) || tree.symbol.owner.is(Flags.Trait)) tree
51-
else {
52-
val isField = tree.symbol.owner.isClass
53-
54-
if (isField) {
55-
if (tree.symbol.isVolatile || tree.symbol.is(Flags.Module)) transformMemberDefVolatile(tree)
56-
else transformMemberDefNonVolatile(tree)
57-
}
58-
else transformLocalDef(tree)
49+
override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree =
50+
transformLazyVal(tree)
51+
52+
53+
override def transformValDef(tree: tpd.ValDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
54+
transformLazyVal(tree)
55+
}
56+
57+
def transformLazyVal(tree: ValOrDefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
58+
val sym = tree.symbol
59+
if (!(sym is Flags.Lazy) || sym.owner.is(Flags.Trait) || (sym.isStatic && sym.is(Flags.Module))) tree
60+
else {
61+
62+
val isField = sym.owner.isClass
63+
64+
if (isField) {
65+
if (sym.isVolatile ||
66+
(sym.is(Flags.Module) && !sym.is(Flags.Synthetic)))
67+
// module class is user-defined.
68+
// Should be threadsafe, to mimic safety guaranteed by global object
69+
transformMemberDefVolatile(tree)
70+
else if (sym.is(Flags.Module)) { // synthetic module
71+
transformSyntheticModule(tree)
72+
}
73+
else transformMemberDefNonVolatile(tree)
5974
}
75+
else transformLocalDef(tree)
6076
}
77+
}
6178

6279

6380
/** Append offset fields to companion objects
@@ -78,11 +95,24 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
7895
case _ => prefix ::: stats
7996
}
8097

98+
/** Make an eager val that would implement synthetic module.
99+
* Eager val ensures thread safety and has less code generated.
100+
*
101+
*/
102+
def transformSyntheticModule(tree: ValOrDefDef)(implicit ctx: Context) = {
103+
val sym = tree.symbol
104+
val holderSymbol = ctx.newSymbol(sym.owner, sym.asTerm.name ++ nme.LAZY_LOCAL,
105+
Flags.Synthetic, sym.info.widen.resultType).enteredAfter(this)
106+
val field = ValDef(holderSymbol, tree.rhs.changeOwnerAfter(sym, holderSymbol, this))
107+
val getter = DefDef(sym.asTerm, ref(holderSymbol))
108+
Thicket(field, getter)
109+
}
110+
81111
/** Replace a local lazy val inside a method,
82112
* with a LazyHolder from
83113
* dotty.runtime(eg dotty.runtime.LazyInt)
84114
*/
85-
def transformLocalDef(x: DefDef)(implicit ctx: Context) = {
115+
def transformLocalDef(x: ValOrDefDef)(implicit ctx: Context) = {
86116
val valueInitter = x.rhs
87117
val holderName = ctx.freshName(x.name ++ StdNames.nme.LAZY_LOCAL).toTermName
88118
val initName = ctx.freshName(x.name ++ StdNames.nme.LAZY_LOCAL_INIT).toTermName
@@ -172,7 +202,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
172202
If(cond, init, exp)
173203
}
174204

175-
def transformMemberDefNonVolatile(x: DefDef)(implicit ctx: Context) = {
205+
def transformMemberDefNonVolatile(x: ValOrDefDef)(implicit ctx: Context) = {
176206
val claz = x.symbol.owner.asClass
177207
val tpe = x.tpe.widen.resultType.widen
178208
assert(!(x.mods is Flags.Mutable))
@@ -293,7 +323,7 @@ class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
293323
DefDef(methodSymbol, Block(resultDef :: retryDef :: flagDef :: cycle :: Nil, ref(resultSymbol)))
294324
}
295325

296-
def transformMemberDefVolatile(x: DefDef)(implicit ctx: Context) = {
326+
def transformMemberDefVolatile(x: ValOrDefDef)(implicit ctx: Context) = {
297327
assert(!(x.mods is Flags.Mutable))
298328

299329
val tpe = x.tpe.widen.resultType.widen

0 commit comments

Comments
 (0)