@@ -257,11 +257,24 @@ object Semantic {
257257 *
258258 * The fact that objects of `ThisRef` are stored in heap is just an engineering convenience.
259259 * 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`.
260272 */
261273 private var heap : Heap = Map .empty
262274
263275 /** Used to revert heap to last stable heap. */
264276 private var heapStable : Heap = Map .empty
277+ def stableHeapContains (ref : Ref ) = heapStable.contains(ref)
265278
266279 def hasChanged = changed
267280
@@ -272,6 +285,11 @@ object Semantic {
272285 if current.contains(value, expr) then current(value)(expr)
273286 else stable(value)(expr)
274287
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+ */
275293 def assume (value : Value , expr : Tree , cacheResult : Boolean )(fun : => Result ): Contextual [Result ] =
276294 val assumeValue : Value =
277295 if last.contains(value, expr) then
@@ -330,6 +348,7 @@ object Semantic {
330348 this .heap = this .heapStable
331349
332350 def updateObject (ref : Ref , obj : Objekt ) =
351+ assert(! this .heapStable.contains(ref))
333352 this .heap = this .heap.updated(ref, obj)
334353
335354 def containsObject (ref : Ref ) = heap.contains(ref)
0 commit comments