@@ -257,11 +257,24 @@ object Semantic {
257
257
*
258
258
* The fact that objects of `ThisRef` are stored in heap is just an engineering convenience.
259
259
* Technically, we can also store the object directly in `ThisRef`.
260
+ *
261
+ * The heap contains objects of two conceptually distinct kinds.
262
+ * - Objects that are also in `heapStable`
263
+ * are flow-insensitive views of already initialized objects that are cached for reuse in analysis of later
264
+ * classes. These objects and their fields should never change; this is enforced using assertions.
265
+ * - Objects that are not (yet) in `heapStable` are the flow-sensitive abstract state of objects being analyzed
266
+ * in the current iteration of the analysis of the current class. Their fields do change flow-sensitively: more
267
+ * fields are added as fields become initialized. These objects are valid only within the current iteration and
268
+ * are removed when moving to a new iteration of analyzing the current class. When the analysis of a class
269
+ * reaches a fixed point, these now stable flow-sensitive views of the object at the end of the constructor
270
+ * of the analyzed class now become the flow-insensitive views of already initialized objects and can therefore
271
+ * be added to `heapStable`.
260
272
*/
261
273
private var heap : Heap = Map .empty
262
274
263
275
/** Used to revert heap to last stable heap. */
264
276
private var heapStable : Heap = Map .empty
277
+ def stableHeapContains (ref : Ref ) = heapStable.contains(ref)
265
278
266
279
def hasChanged = changed
267
280
@@ -272,6 +285,11 @@ object Semantic {
272
285
if current.contains(value, expr) then current(value)(expr)
273
286
else stable(value)(expr)
274
287
288
+ /** Copy the value of `(value, expr)` from the last cache to the current cache
289
+ * (assuming it's `Hot` if it doesn't exist in the cache).
290
+ *
291
+ * Then, runs `fun` and update the caches if the values change.
292
+ */
275
293
def assume (value : Value , expr : Tree , cacheResult : Boolean )(fun : => Result ): Contextual [Result ] =
276
294
val assumeValue : Value =
277
295
if last.contains(value, expr) then
@@ -330,6 +348,7 @@ object Semantic {
330
348
this .heap = this .heapStable
331
349
332
350
def updateObject (ref : Ref , obj : Objekt ) =
351
+ assert(! this .heapStable.contains(ref))
333
352
this .heap = this .heap.updated(ref, obj)
334
353
335
354
def containsObject (ref : Ref ) = heap.contains(ref)
0 commit comments