Class ResolutionMemo
- All Implemented Interfaces:
Serializable
The memo lets a ModuleScope answer a resolution WITHOUT taking the global
SharedThreadContext lock. Measured motivation: workers spend 90-94% of the front-end
phases BLOCKED on that lock, and roughly half its cost is not the critical section at all but the
handoff - waking a parked thread (SCALE-LAB-NOTEBOOK.md F29).
Only NEGATIVE results are memoised. A positive result would hand out a cached
ISymbol reference, and symbols are plain mutable objects that later phases still populate;
caching one widens the window in which a reader can observe a partially-built symbol. Negatives
carry no such reference, so the only question is whether "absent" is still true - which is exactly
what the generation counter answers. Negatives are also the bulk of the traffic: most resolutions
fail (F30).
How a negative stays sound. Each module NAME has a generation counter, incremented whenever a symbol or reference is defined into a scope of that name. A negative entry records the generation of the scope its answer depended on, sampled before the locked lookup. A later reader discards the entry if that generation has moved. So:
- in a phase that defines nothing into the scope, negatives stay valid for the whole phase;
- in a phase that defines, they are invalidated the instant something could change the answer, degrading gracefully to no caching at all.
Sample the generation BEFORE the lookup, never after. Read it after and a define that lands during the lookup yields an entry tagged with a generation newer than the answer it holds - a stale negative that later readers would trust.
One instance per CompilableProgram, so concurrent compiles (the test
suite runs many) cannot see each other's entries. Never static.
- See Also:
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final StringThe scope key standing for the implicitly imported modules searched by every module (org.ek9.lang, org.ek9.math). -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidvoidcountHit()voidvoidvoidvoidRecord that something was defined into a scope of this module name, invalidating any negative that was answered from it.longgeneration(String scopeKey) The current generation of a scope.booleanisActive()voidsetActive(boolean active) Enable or disable the memo.stats()Hit rate over the calls the memo was actually eligible to answer.static boolean
-
Field Details
-
IMPLICIT_SCOPES
The scope key standing for the implicitly imported modules searched by every module (org.ek9.lang, org.ek9.math). A define into either bumps this too.- See Also:
-
-
Constructor Details
-
ResolutionMemo
public ResolutionMemo()
-
-
Method Details
-
statsEnabled
public static boolean statsEnabled() -
countHit
public void countHit() -
countMiss
public void countMiss() -
countStale
public void countStale() -
countNotMemoisable
public void countNotMemoisable() -
countFound
public void countFound() -
stats
Hit rate over the calls the memo was actually eligible to answer. -
defined
Record that something was defined into a scope of this module name, invalidating any negative that was answered from it. -
generation
The current generation of a scope. Sample this BEFORE the locked lookup whose result you intend to memoise. -
isActive
public boolean isActive() -
setActive
public void setActive(boolean active) Enable or disable the memo. Callers clear their per-scope entries when this changes, because a negative recorded in one phase says nothing about the next.
-