Skip to content

Commit b4b2b85

Browse files
committed
Make LazyVals implement non-static modules. Move LV after erasure.
1 parent 836ab2f commit b4b2b85

File tree

2 files changed

+39
-40
lines changed

2 files changed

+39
-40
lines changed

src/dotty/tools/dotc/Compiler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,15 @@ class Compiler {
5151
List(new PatternMatcher,
5252
new ExplicitOuter,
5353
new Splitter),
54-
List(new LazyVals,
55-
new SeqLiterals,
54+
List(new SeqLiterals,
5655
new InterceptedMethods,
5756
new Literalize,
5857
new Getters,
5958
new ElimByName,
6059
new ResolveSuper),
6160
List(new Erasure),
6261
List(new Mixin,
62+
new LazyVals,
6363
new Memoize,
6464
new CapturedVars,
6565
new Constructors),

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

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,17 @@ import dotty.tools.dotc.core.Denotations.SingleDenotation
2121
import dotty.tools.dotc.core.SymDenotations.SymDenotation
2222
import dotty.tools.dotc.core.DenotTransformers.{SymTransformer, IdentityDenotTransformer, DenotTransformer}
2323

24-
class LazyVals extends MiniPhaseTransform with SymTransformer {
24+
class LazyVals extends MiniPhaseTransform with IdentityDenotTransformer {
2525

2626
import tpd._
2727

28-
29-
def transformSym(d: SymDenotation)(implicit ctx: Context): SymDenotation = {
30-
if (d is(Flags.Lazy, butNot = Flags.ModuleVal | Flags.Method)) {
31-
// Method flag is set on lazy vals coming from Unpickler. They are already methods and shouldn't be transformed twice
32-
d.copySymDenotation(
33-
initFlags = d.flags | Flags.Method,
34-
info = ExprType(d.info))
35-
}
36-
else d
37-
}
38-
3928
def transformer = new LazyVals
4029

4130
val containerFlags = Flags.Synthetic | Flags.Mutable | Flags.Lazy
4231
val initFlags = Flags.Synthetic | Flags.Method
4332

33+
val containerFlagsMask = Flags.Lazy | Flags.Accessor
34+
4435
/** this map contains mutable state of transformation: OffsetDefs to be appended to companion object definitions,
4536
* and number of bits currently used */
4637
class OffsetInfo(var defs: List[Tree], var ord:Int)
@@ -52,16 +43,22 @@ class LazyVals extends MiniPhaseTransform with SymTransformer {
5243
* before this phase starts processing same tree */
5344
// override def ensureAfter: Set[String] = Set("mixin")
5445

55-
override def transformValDef(tree: ValDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
56-
if (!(tree.mods is Flags.Lazy) || (tree.mods is Flags.ModuleVal)) tree
46+
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
47+
if (!(tree.symbol is Flags.Lazy)) tree
5748
else {
58-
val isField = tree.symbol.owner.isClass
59-
60-
if (isField) {
61-
if (tree.symbol.isVolatile) transformFieldValDefVolatile(tree)
62-
else transformFieldValDefNonVolatile(tree)
49+
if (tree.symbol is Flags.Module) {
50+
val field = ctx.newSymbol(tree.symbol.owner, tree.symbol.name ++ StdNames.nme.MODULE_VAR_SUFFIX, containerFlags, tree.symbol.info.resultType, coord = tree.symbol.pos)
51+
tpd.This(tree.symbol.enclosingClass.asClass).select(defn.Object_synchronized).appliedTo(
52+
mkDefNonThreadSafeNonNullable(field, tree.rhs).ensureConforms(tree.tpe.widen.resultType.widen))
53+
} else {
54+
val isField = tree.symbol.owner.isClass
55+
56+
if (isField) {
57+
if (tree.symbol.isVolatile) transformFieldValDefVolatile(tree)
58+
else transformFieldValDefNonVolatile(tree)
59+
}
60+
else transformLocalValDef(tree)
6361
}
64-
else transformLocalValDef(tree)
6562
}
6663
}
6764

@@ -82,12 +79,11 @@ class LazyVals extends MiniPhaseTransform with SymTransformer {
8279
* with a LazyHolder from
8380
* dotty.runtime(eg dotty.runtime.LazyInt)
8481
*/
85-
def transformLocalValDef(x: ValDef)(implicit ctx: Context) = x match {
86-
case ValDef(name, tpt, _) =>
82+
def transformLocalValDef(x: DefDef)(implicit ctx: Context) = {
8783
val valueInitter = x.rhs
88-
val holderName = ctx.freshName(name.toString + StdNames.nme.LAZY_LOCAL).toTermName
89-
val initName = ctx.freshName(name.toString + StdNames.nme.LAZY_LOCAL_INIT).toTermName
90-
val tpe = x.tpe.widen
84+
val holderName = ctx.freshName(x.name ++ StdNames.nme.LAZY_LOCAL).toTermName
85+
val initName = ctx.freshName(x.name ++ StdNames.nme.LAZY_LOCAL_INIT).toTermName
86+
val tpe = x.tpe.widen.resultType.widen
9187

9288
val holderType =
9389
if (tpe isRef defn.IntClass) "LazyInt"
@@ -124,7 +120,12 @@ class LazyVals extends MiniPhaseTransform with SymTransformer {
124120

125121

126122
override def transformStats(trees: List[tpd.Tree])(implicit ctx: Context, info: TransformerInfo): List[tpd.Tree] = {
127-
val (holders, stats) = trees.partition { _.symbol.flags == containerFlags}
123+
val (holders, stats) =
124+
atGroupEnd { implicit ctx: Context =>
125+
trees.partition {
126+
_.symbol.flags == containerFlags
127+
}
128+
}
128129
holders:::stats
129130
}
130131

@@ -162,29 +163,28 @@ class LazyVals extends MiniPhaseTransform with SymTransformer {
162163
If(cond, init, exp)
163164
}
164165

165-
def transformFieldValDefNonVolatile(x: ValDef)(implicit ctx: Context) = x match {
166-
case ValDef(name, tpt, _) if (x.mods is Flags.Lazy) =>
166+
def transformFieldValDefNonVolatile(x: DefDef)(implicit ctx: Context) = {
167167
val claz = x.symbol.owner.asClass
168-
val tpe = x.tpe.widen
168+
val tpe = x.tpe.widen.resultType.widen
169169
assert(!(x.mods is Flags.Mutable))
170-
val containerName = ctx.freshName(name.toString + StdNames.nme.LAZY_LOCAL).toTermName
171-
val containerSymbol = ctx.newSymbol(claz, containerName, (x.mods &~ Flags.Lazy | containerFlags).flags, tpe, coord = x.symbol.coord).enteredAfter(this)
170+
val containerName = ctx.freshName(x.name ++ StdNames.nme.LAZY_LOCAL).toTermName
171+
val containerSymbol = ctx.newSymbol(claz, containerName, (x.mods &~ containerFlagsMask | containerFlags).flags, tpe, coord = x.symbol.coord).enteredAfter(this)
172172

173173
val containerTree = ValDef(containerSymbol, initValue(tpe))
174174
if (x.tpe.isNotNull && tpe <:< defn.AnyRefType) { // can use 'null' value instead of flag
175175
val slowPath = DefDef(x.symbol.asTerm, mkDefNonThreadSafeNonNullable(containerSymbol, x.rhs))
176176
Thicket(List(containerTree, slowPath))
177177
}
178178
else {
179-
val flagName = ctx.freshName(name.toString + StdNames.nme.BITMAP_PREFIX).toTermName
179+
val flagName = ctx.freshName(x.name ++ StdNames.nme.BITMAP_PREFIX).toTermName
180180
val flagSymbol = ctx.newSymbol(x.symbol.owner, flagName, containerFlags, defn.BooleanType)
181181
val flag = ValDef(flagSymbol, Literal(Constants.Constant(false)))
182182
val slowPath = DefDef(x.symbol.asTerm, mkNonThreadSafeDef(ref(containerSymbol), ref(flagSymbol), x.rhs))
183183
Thicket(List(containerTree, flag, slowPath))
184184
}
185185
}
186186

187-
/** Create non-threadsafe lazy accessor equivalent to such code
187+
/** Create a threadsafe lazy accessor equivalent to such code
188188
*
189189
* def methodSymbol(): Int = {
190190
* val result: Int = 0
@@ -280,11 +280,10 @@ class LazyVals extends MiniPhaseTransform with SymTransformer {
280280
DefDef(methodSymbol, Block(resultDef :: retryDef :: flagDef :: cycle :: Nil, ref(resultSymbol)))
281281
}
282282

283-
def transformFieldValDefVolatile(x: ValDef)(implicit ctx: Context) = x match {
284-
case ValDef(name, tpt, _) if (x.mods is Flags.Lazy) =>
283+
def transformFieldValDefVolatile(x: DefDef)(implicit ctx: Context) = {
285284
assert(!(x.mods is Flags.Mutable))
286285

287-
val tpe = x.tpe.widen
286+
val tpe = x.tpe.widen.resultType.widen
288287
val claz = x.symbol.owner.asClass
289288
val thiz = This(claz)(ctx.fresh.setOwner(claz))
290289
val companion = claz.companionModule
@@ -323,8 +322,8 @@ class LazyVals extends MiniPhaseTransform with SymTransformer {
323322
appendOffsetDefs += (companion.name.moduleClassName -> new OffsetInfo(List(offsetTree), ord))
324323
}
325324

326-
val containerName = ctx.freshName(name.toString + StdNames.nme.LAZY_LOCAL).toTermName
327-
val containerSymbol = ctx.newSymbol(claz, containerName, (x.mods &~ Flags.Lazy | containerFlags).flags, tpe, coord = x.symbol.coord).enteredAfter(this)
325+
val containerName = ctx.freshName(x.name ++ StdNames.nme.LAZY_LOCAL).toTermName
326+
val containerSymbol = ctx.newSymbol(claz, containerName, (x.mods &~ containerFlagsMask | containerFlags).flags, tpe, coord = x.symbol.coord).enteredAfter(this)
328327
val containerTree = ValDef(containerSymbol, initValue(tpe))
329328

330329
val offset = Select(ref(companion), offsetSymbol.name)

0 commit comments

Comments
 (0)