@@ -60,6 +60,8 @@ class Semantic {
60
60
*/
61
61
case class Objekt (val fields : mutable.Map [Symbol , Value ]) {
62
62
var allFieldsInitialized : Boolean = false
63
+
64
+ val promotedValues = mutable.Set .empty[Value ]
63
65
}
64
66
65
67
/** Abstract heap stores abstract objects
@@ -219,7 +221,7 @@ class Semantic {
219
221
if target.isPrimaryConstructor then
220
222
val cls = target.owner.asClass
221
223
val tpl = cls.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
222
- eval(tpl, thisRef, cls, cacheResult = true )
224
+ eval(tpl, thisRef, cls, cacheResult = true )( using heap, ctx, trace.add(tpl))
223
225
else
224
226
val rhs = target.defTree.asInstanceOf [ValOrDefDef ].rhs
225
227
eval(rhs, thisRef, target.owner.asClass, cacheResult = true )
@@ -317,19 +319,22 @@ class Semantic {
317
319
case Cold => false
318
320
319
321
case warm : Warm =>
320
- warm.outer.canDirectlyPromote
322
+ heap.promotedValues.contains(warm)
323
+ || warm.outer.canDirectlyPromote
321
324
322
325
case thisRef : ThisRef =>
323
- heap.allFieldsInitialized || {
326
+ heap.promotedValues.contains(thisRef) || {
324
327
// If we have all fields initialized, then we can promote This to hot.
325
- heap. allFieldsInitialized = thisRef.klass.appliedRef.fields.forall { denot =>
328
+ val allFieldsInitialized = thisRef.klass.appliedRef.fields.forall { denot =>
326
329
val sym = denot.symbol
327
330
sym.isOneOf(Flags .Lazy | Flags .Deferred ) || heap.fields.contains(sym)
328
331
}
329
- heap.allFieldsInitialized
332
+ if allFieldsInitialized then heap.promotedValues += thisRef
333
+ allFieldsInitialized
330
334
}
331
335
332
- case fun : Fun => false
336
+ case fun : Fun =>
337
+ heap.promotedValues.contains(fun)
333
338
334
339
case RefSet (refs) =>
335
340
refs.forall(_.canDirectlyPromote)
@@ -348,8 +353,13 @@ class Semantic {
348
353
else PromoteThis (source, trace) :: Nil
349
354
350
355
case warm : Warm =>
351
- if warm.outer.canDirectlyPromote then Nil
352
- else warm.tryPromote(msg, source)
356
+ if warm.canDirectlyPromote then Nil
357
+ else {
358
+ heap.promotedValues += warm
359
+ val errors = warm.tryPromote(msg, source)
360
+ if errors.nonEmpty then heap.promotedValues -= warm
361
+ errors
362
+ }
353
363
354
364
case Fun (body, thisV, klass) =>
355
365
val res = eval(body, thisV, klass)
@@ -374,6 +384,9 @@ class Semantic {
374
384
* 2. for each concrete field `f` of the warm object:
375
385
* promote the field value
376
386
*
387
+ * TODO: we need to revisit whether this is needed once make the
388
+ * system more flexible in other dimentions: e.g. leak to
389
+ * methods or constructors, or use ownership for creating cold data structures.
377
390
*/
378
391
def tryPromote (msg : String , source : Tree ): Contextual [List [Error ]] = log(" promote " + warm.show, printer) {
379
392
val classRef = warm.klass.appliedRef
@@ -388,15 +401,15 @@ class Semantic {
388
401
val f = denot.symbol
389
402
if ! f.isOneOf(Flags .Deferred | Flags .Private | Flags .Protected ) && f.hasSource then
390
403
val res = warm.select(f, source)
391
- buffer ++= res.ensureHot(msg, source).errors
404
+ buffer ++= res.ensureHot(msg, source)( using heap, ctx, trace.add(f.defTree)) .errors
392
405
buffer.nonEmpty
393
406
}
394
407
395
408
buffer.nonEmpty || methods.exists { denot =>
396
409
val m = denot.symbol
397
410
if ! m.isConstructor && m.hasSource then
398
- val res = warm.call(m, superType = NoType , source = source)
399
- buffer ++= res.ensureHot(msg, source).errors
411
+ val res = warm.call(m, superType = NoType , source = source)( using heap, ctx, trace.add(m.defTree))
412
+ buffer ++= res.ensureHot(msg, source)( using heap, ctx, trace.add(m.defTree)) .errors
400
413
buffer.nonEmpty
401
414
}
402
415
@@ -480,7 +493,7 @@ class Semantic {
480
493
481
494
val cls = tref.classSymbol.asClass
482
495
val res = outerValue(tref, thisV, klass, tpt)
483
- (res ++ errors).instantiate(cls, ctor, expr)
496
+ (res ++ errors).instantiate(cls, ctor, expr)( using heap, ctx, trace.add(expr))
484
497
485
498
case Call (ref, argss) =>
486
499
// check args
@@ -705,7 +718,7 @@ class Semantic {
705
718
706
719
// follow constructor
707
720
if ! cls.defTree.isEmpty then
708
- val res2 = thisV.call(ctor, superType = NoType , source)
721
+ val res2 = thisV.call(ctor, superType = NoType , source)( using heap, ctx, trace.add(source))
709
722
errorBuffer ++= res2.errors
710
723
711
724
// parents
0 commit comments