Class EpsilonClosure

java.lang.Object
org.antlr.v4.runtime.atn.EpsilonClosure

final class EpsilonClosure extends Object
Epsilon-closure engine for adaptive LL(*) prediction.

Owns the busy set, the predicate vs non-predicate control split, and double-buffered intermediate config sets for breadth-first rule-transition merging. Recursive edge walking stays here so ParserATNSimulator remains orchestration-focused rather than absorbing more allocation policy.

PERF: Intermediate config-set buffers and the closure busy set are retained on this instance. A single ParserATNSimulator (and therefore one EpsilonClosure) is used by one parser thread at a time during adaptivePredict, so reuse is safe. Ownership of cleanup is a single try/finally around each close(org.antlr.v4.runtime.atn.ATNConfigSet, org.antlr.v4.runtime.atn.ATNConfigSet, boolean, boolean, org.antlr.v4.runtime.atn.PredictionContextCache, boolean): drop config-graph references after the call while retaining set capacity for the next prediction.

PERF: The busy set is exposed only as Set<ATNConfig> (see OpenAddressedHashSet) so the protected ParserATNSimulator.closure(ATNConfig, ATNConfigSet, ATNConfigSet, Set, boolean, boolean, PredictionContextCache, int, boolean) SPI stays free of HPPC types. Storage remains an open-addressed HPPC table behind the adapter: right-recursion and EOF* guards avoid java.util.HashMap.Node<K extends Object,V extends Object> allocation on every insert, and the flat key array is reused across predictions. Config iteration on the BFS layers is index-based (ATNConfigSet.get(int)) to avoid Iterator objects on the hot path.

Package-private: only ParserATNSimulator constructs and uses this type. Transition target computation is delegated back to the simulator (ParserATNSimulator.getEpsilonTarget(org.antlr.v4.runtime.atn.ATNConfig, org.antlr.v4.runtime.atn.Transition, boolean, boolean, org.antlr.v4.runtime.atn.PredictionContextCache, boolean)) so semantic-predicate and rule-transition policy remain in one place.