diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/ATNConfigSet.java b/runtime/Java/src/org/antlr/v4/runtime/atn/ATNConfigSet.java index c23e9475e..a643c07af 100755 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/ATNConfigSet.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/ATNConfigSet.java @@ -31,7 +31,6 @@ package org.antlr.v4.runtime.atn; import org.antlr.v4.runtime.misc.Array2DHashSet; import org.antlr.v4.runtime.misc.IntervalSet; -import org.antlr.v4.runtime.misc.Nullable; import java.util.ArrayList; import java.util.Collection; @@ -300,25 +299,20 @@ public class ATNConfigSet implements Set { public ATNConfigSet(ATNConfigSet old, PredictionContextCache contextCache) { this(old.fullCtx); - addAll(old, contextCache); + addAll(old); this.uniqueAlt = old.uniqueAlt; this.conflictingAlts = old.conflictingAlts; this.hasSemanticContext = old.hasSemanticContext; this.dipsIntoOuterContext = old.dipsIntoOuterContext; } - @Override - public boolean add(ATNConfig e) { - return add(e, null); - } - /** Adding a new config means merging contexts with existing configs for * (s, i, pi, _) * We use (s,i,pi) as key */ - public boolean add(ATNConfig config, @Nullable PredictionContextCache contextCache) { + @Override + public boolean add(ATNConfig config) { if ( readonly ) throw new IllegalStateException("This set is readonly"); - contextCache = null; // TODO: costs time to cache and saves essentially no RAM if ( config.semanticContext!=SemanticContext.NONE ) { hasSemanticContext = true; } @@ -330,11 +324,10 @@ public class ATNConfigSet implements Set { // a previous (s,i,pi,_), merge with it and save result boolean rootIsWildcard = !fullCtx; PredictionContext merged = - PredictionContext.merge(existing.context, config.context, contextCache, rootIsWildcard); + PredictionContext.merge(existing.context, config.context, rootIsWildcard); // no need to check for existing.context, config.context in cache // since only way to create new graphs is "call rule" and here. We // cache at both places. - if ( contextCache!=null ) merged = contextCache.add(merged); existing.reachesIntoOuterContext = Math.max(existing.reachesIntoOuterContext, config.reachesIntoOuterContext); existing.context = merged; // replace context; no need to alt mapping @@ -384,17 +377,8 @@ public class ATNConfigSet implements Set { } } - @Override - public boolean addAll(Collection c) { - return addAll(c, null); - } - - public boolean addAll(Collection coll, - PredictionContextCache contextCache) - { - for (ATNConfig c : coll) { - add(c, contextCache); - } + public boolean addAll(Collection coll) { + for (ATNConfig c : coll) add(c); return false; } diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/ATNSimulator.java b/runtime/Java/src/org/antlr/v4/runtime/atn/ATNSimulator.java index d5e13d344..0f56db603 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/ATNSimulator.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/ATNSimulator.java @@ -50,28 +50,23 @@ public abstract class ATNSimulator { * to use only cached nodes/graphs in addDFAState(). We don't want to * fill this during closure() since there are lots of contexts that * pop up but are not used ever again. It also greatly slows down closure(). + * + * This cache makes a huge difference in memory and a little bit in speed. + * For the Java grammar on java.*, it dropped the memory requirements + * at the end from 25M to 16M. We don't store any of the full context + * graphs in the DFA because they are limited to local context only, + * but apparently there's a lot of repetition there as well. We optimize + * the config contexts before storing the config set in the DFA states + * by literally rebuilding them with cached subgraphs only. + * + * I tried a cache for use during closure operations, that was + * whacked after each adaptivePredict(). It cost a little bit + * more time I think and doesn't save on the overall footprint + * so it's not worth the complexity. */ protected final PredictionContextCache sharedContextCache = new PredictionContextCache("shared DFA state context cache"); - /** This context cache tracks all context graphs used during a single - * ATN-based prediction operation. There will be significant context graph - * sharing among ATNConfigSets because all sets are derived from the - * same starting context. - * - * This cache is blown away after each adaptivePredict() - * because we cache everything within ATNConfigSets that become DFA - * states in sharedContextCache. (Sam thinks of this as an analogy to - * the nursery in a generational GC; then, sharedContextCache would be - * the mature generation.) - * - * In Sam's version, this is a parameter passed down through all of - * the methods, but it gets pretty unwieldy as there are already - * a crapload of parameters. Consequently, I'm using a field as a - * "parameter" despite it being generally poor coding style. - */ - protected PredictionContextCache contextCache; - static { ERROR = new DFAState(new ATNConfigSet()); ERROR.stateNumber = Integer.MAX_VALUE; diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/ArrayPredictionContext.java b/runtime/Java/src/org/antlr/v4/runtime/atn/ArrayPredictionContext.java index 78302d291..8c605c1c0 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/ArrayPredictionContext.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/ArrayPredictionContext.java @@ -1,7 +1,5 @@ package org.antlr.v4.runtime.atn; -import org.antlr.v4.runtime.misc.NotNull; - import java.util.Arrays; import java.util.Iterator; @@ -126,7 +124,6 @@ public class ArrayPredictionContext extends PredictionContext { */ @Override public PredictionContext popAll(int invokingState, - @NotNull PredictionContextCache contextCache, boolean fullCtx) { int index = Arrays.binarySearch(this.invokingStates, invokingState); @@ -135,7 +132,7 @@ public class ArrayPredictionContext extends PredictionContext { } PredictionContext newCtx = - this.parents[index].popAll(invokingState, contextCache, fullCtx); + this.parents[index].popAll(invokingState, fullCtx); for (int i = 0; i < this.invokingStates.length; i++) { if (i == index) continue; PredictionContext next; @@ -145,10 +142,9 @@ public class ArrayPredictionContext extends PredictionContext { else { next = new SingletonPredictionContext(this.parents[i], this.invokingStates[i]); - if ( contextCache!=null ) next = contextCache.add(next); } boolean rootIsWildcard = fullCtx; - newCtx = merge(newCtx, next, contextCache, rootIsWildcard); + newCtx = merge(newCtx, next, rootIsWildcard); } return newCtx; diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java b/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java index 78b413a8b..7ab1660e0 100755 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/ParserATNSimulator.java @@ -235,7 +235,6 @@ public class ParserATNSimulator extends ATNSimulator { throw nvae; } finally { - contextCache = null; // wack the cache input.seek(index); input.release(m); } @@ -268,7 +267,6 @@ public class ParserATNSimulator extends ATNSimulator { if ( dfa_debug ) System.out.println("ctx sensitive state "+outerContext+" in "+s); boolean loopsSimulateTailRecursion = true; boolean fullCtx = true; -// contextCache = new PredictionContextCache("predict ctx cache built in execDFA"); ATNConfigSet s0_closure = computeStartState(dfa.atnStartState, outerContext, greedy, loopsSimulateTailRecursion, @@ -280,7 +278,6 @@ public class ParserATNSimulator extends ATNSimulator { outerContext, ATN.INVALID_ALT_NUMBER, greedy); - contextCache = null; return fullCtxSet.uniqueAlt; } if ( s.isAcceptState ) { @@ -312,9 +309,7 @@ public class ParserATNSimulator extends ATNSimulator { " at DFA state "+s.stateNumber); } -// contextCache = new PredictionContextCache("predict ctx cache built in execDFA"); alt = execATN(dfa, s, input, startIndex, outerContext); - contextCache = null; // this adds edge even if next state is accept for // same alt; e.g., s0-A->:s1=>2-B->:s2=>2 // TODO: This next stuff kills edge, but extra states remain. :( @@ -625,7 +620,7 @@ public class ParserATNSimulator extends ATNSimulator { Transition trans = c.state.transition(ti); ATNState target = getReachableTarget(trans, t); if ( target!=null ) { - intermediate.add(new ATNConfig(c, target), contextCache); + intermediate.add(new ATNConfig(c, target)); } } } @@ -873,7 +868,7 @@ public class ParserATNSimulator extends ATNSimulator { // don't see past end of a rule for any nongreedy decision if ( debug ) System.out.println("NONGREEDY at stop state of "+ getRuleName(config.state.ruleIndex)); - configs.add(config, contextCache); + configs.add(config); return; } // We hit rule end. If we have context info, use it @@ -917,7 +912,6 @@ public class ParserATNSimulator extends ATNSimulator { { config.context = new SingletonPredictionContext(config.context, config.state.stateNumber); - if ( contextCache!=null ) config.context = contextCache.add(config.context); // alter config; it's ok, since all calls to closure pass in a fresh config for us to chase if ( debug ) System.out.println("Loop back; push "+config.state.stateNumber+", stack="+config.context); } @@ -926,7 +920,6 @@ public class ParserATNSimulator extends ATNSimulator { LoopEndState end = (LoopEndState)config.state; // pop all the way back until we don't see the loopback state anymore config.context = config.context.popAll(end.loopBackStateNumber, - contextCache, configs.fullCtx); if ( debug ) System.out.println(" becomes "+config.context); } @@ -949,7 +942,7 @@ public class ParserATNSimulator extends ATNSimulator { ATNState p = config.state; // optimization if ( !p.onlyHasEpsilonTransitions() ) { - configs.add(config, contextCache); + configs.add(config); if ( config.semanticContext!=null && config.semanticContext!= SemanticContext.NONE ) { configs.hasSemanticContext = true; } @@ -1086,7 +1079,6 @@ public class ParserATNSimulator extends ATNSimulator { } PredictionContext newContext = new SingletonPredictionContext(config.context, config.state.stateNumber); - if ( contextCache!=null ) newContext = contextCache.add(newContext); return new ATNConfig(config, t.target, newContext); } diff --git a/runtime/Java/src/org/antlr/v4/runtime/atn/PredictionContext.java b/runtime/Java/src/org/antlr/v4/runtime/atn/PredictionContext.java index 5a1b458d4..755316363 100644 --- a/runtime/Java/src/org/antlr/v4/runtime/atn/PredictionContext.java +++ b/runtime/Java/src/org/antlr/v4/runtime/atn/PredictionContext.java @@ -72,7 +72,6 @@ public abstract class PredictionContext implements Iterable M @@ -277,7 +265,7 @@ public abstract class PredictionContext implements Iterable a'[x,y] PredictionContext mergedParent = - merge(a_parent, b_parent, contextCache, rootIsWildcard); + merge(a_parent, b_parent, rootIsWildcard); mergedParents[k] = mergedParent; mergedInvokingStates[k] = payload; } @@ -325,7 +313,6 @@ public abstract class PredictionContext implements Iterable