Skip to content

Commit 37258d0

Browse files
committed
Cache safely promoted potentials
1 parent 27f0fda commit 37258d0

File tree

2 files changed

+44
-34
lines changed

2 files changed

+44
-34
lines changed

compiler/src/dotty/tools/dotc/transform/init/Checker.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class Checker extends MiniPhase {
5252
thisClass = cls,
5353
fieldsInited = mutable.Set.empty,
5454
parentsInited = mutable.Set.empty,
55+
safePromoted = mutable.Set.empty,
5556
env = baseEnv.withCtx(ctx.withOwner(cls))
5657
)
5758

compiler/src/dotty/tools/dotc/transform/init/Checking.scala

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ object Checking {
3535
thisClass: ClassSymbol, // the concrete class of `this`
3636
fieldsInited: mutable.Set[Symbol],
3737
parentsInited: mutable.Set[ClassSymbol],
38+
safePromoted: mutable.Set[Potential], // Potentials that can be safely promoted
3839
env: Env
3940
) {
4041

@@ -161,40 +162,7 @@ object Checking {
161162
implicit val state2: State = state.withVisited(eff)
162163

163164
eff match {
164-
case Promote(pot) =>
165-
pot match {
166-
case pot: ThisRef =>
167-
// If we have all fields initialized, then we can promote This to hot.
168-
val classRef = state.thisClass.info.asInstanceOf[ClassInfo].appliedRef
169-
val allFieldsInited = classRef.fields.forall { denot =>
170-
val sym = denot.symbol
171-
sym.isOneOf(Flags.Lazy | Flags.Deferred) || state.fieldsInited.contains(sym)
172-
}
173-
if (allFieldsInited)
174-
Errors.empty
175-
else
176-
PromoteThis(pot, eff.source, state2.path).toErrors
177-
case _: Cold =>
178-
PromoteCold(eff.source, state2.path).toErrors
179-
180-
case pot @ Warm(cls, outer) =>
181-
val errors = state.test { check(Promote(outer)(eff.source)) }
182-
if (errors.isEmpty) Errors.empty
183-
else PromoteWarm(pot, eff.source, state2.path).toErrors
184-
185-
case Fun(pots, effs) =>
186-
val errs1 = state.test { effs.flatMap { check(_) } }
187-
val errs2 = state.test { pots.flatMap { pot => check(Promote(pot)(eff.source))(state.copy(path = Vector.empty)) } }
188-
if (errs1.nonEmpty || errs2.nonEmpty)
189-
UnsafePromotion(pot, eff.source, state2.path, errs1 ++ errs2).toErrors
190-
else
191-
Errors.empty
192-
193-
case pot =>
194-
val (pots, effs) = expand(pot)
195-
val effs2 = pots.map(Promote(_)(eff.source))
196-
(effs2 ++ effs).flatMap(check(_))
197-
}
165+
case Promote(pot) => checkPromote(pot, eff.source)
198166

199167
case FieldAccess(pot, field) =>
200168

@@ -279,6 +247,47 @@ object Checking {
279247
}
280248
}
281249

250+
private def checkPromote(pot: Potential, source: Tree)(implicit state: State): Errors =
251+
if (state.safePromoted.contains(pot)) Errors.empty
252+
else
253+
val errs = pot match {
254+
case pot: ThisRef =>
255+
// If we have all fields initialized, then we can promote This to hot.
256+
val classRef = state.thisClass.info.asInstanceOf[ClassInfo].appliedRef
257+
val allFieldsInited = classRef.fields.forall { denot =>
258+
val sym = denot.symbol
259+
sym.isOneOf(Flags.Lazy | Flags.Deferred) || state.fieldsInited.contains(sym)
260+
}
261+
if (allFieldsInited)
262+
Errors.empty
263+
else
264+
PromoteThis(pot, source, state.path).toErrors
265+
case _: Cold =>
266+
PromoteCold(source, state.path).toErrors
267+
268+
case pot @ Warm(cls, outer) =>
269+
val errors = state.test { checkPromote(outer, source) }
270+
if (errors.isEmpty) Errors.empty
271+
else PromoteWarm(pot, source, state.path).toErrors
272+
273+
case Fun(pots, effs) =>
274+
val errs1 = state.test { effs.flatMap { check(_) } }
275+
val errs2 = state.test { pots.flatMap { pot => checkPromote(pot, source)(state.copy(path = Vector.empty)) } }
276+
if (errs1.nonEmpty || errs2.nonEmpty)
277+
UnsafePromotion(pot, source, state.path, errs1 ++ errs2).toErrors
278+
else
279+
Errors.empty
280+
281+
case pot =>
282+
val (pots, effs) = expand(pot)
283+
val effs2 = pots.map(Promote(_)(source))
284+
(effs2 ++ effs).flatMap(check(_))
285+
}
286+
// If we can safely promote, then we don't need to check again
287+
if (errs.isEmpty)
288+
state.safePromoted += pot
289+
errs
290+
282291
private def expand(pot: Potential)(implicit state: State): Summary = trace("expand " + pot.show, init, sum => Summary.show(sum.asInstanceOf[Summary])) {
283292
pot match {
284293
case MethodReturn(pot1, sym) =>

0 commit comments

Comments
 (0)