turn on local context cache.

This commit is contained in:
Terence Parr 2012-07-27 20:53:10 -07:00
parent 14372f2515
commit 8279c3da11
3 changed files with 41 additions and 60 deletions

View File

@ -144,7 +144,6 @@ import java.util.Set;
*/ */
public class ATNConfigSet implements Set<ATNConfig> { public class ATNConfigSet implements Set<ATNConfig> {
// TODO: convert to long like Sam? use list and map from config to ctx?
/* /*
The reason that we need this is because we don't want the hash map to use The reason that we need this is because we don't want the hash map to use
the standard hash code and equals. We need all configurations with the same the standard hash code and equals. We need all configurations with the same
@ -152,53 +151,28 @@ public class ATNConfigSet implements Set<ATNConfig> {
the number of objects associated with ATNConfigs. The other solution is to the number of objects associated with ATNConfigs. The other solution is to
use a hash table that lets us specify the equals/hashcode operation. use a hash table that lets us specify the equals/hashcode operation.
*/ */
public static class Key { public static class ConfigHashSet extends Array2DHashSet<ATNConfig> {
ATNState state; public ConfigHashSet() {
int alt; super(16,2);
SemanticContext semanticContext;
public Key(ATNState state, int alt, SemanticContext semanticContext) {
this.state = state;
this.alt = alt;
this.semanticContext = semanticContext;
}
public Key(ATNConfig c) {
this(c.state, c.alt, c.semanticContext);
} }
@Override @Override
public boolean equals(Object obj) { public int hashCode(ATNConfig o) {
if ( obj==this ) return true;
if ( this.hashCode() != obj.hashCode() ) return false;
if ( !(obj instanceof Key) ) return false;
Key key = (Key)obj;
return this.state.stateNumber==key.state.stateNumber
&& this.alt==key.alt
&& this.semanticContext.equals(key.semanticContext);
}
@Override
public int hashCode() {
int hashCode = 7; int hashCode = 7;
hashCode = 5 * hashCode + state.stateNumber; hashCode = 31 * hashCode + o.state.stateNumber;
hashCode = 5 * hashCode + alt; hashCode = 31 * hashCode + o.alt;
hashCode = 5 * hashCode + semanticContext.hashCode(); hashCode = 31 * hashCode + o.semanticContext.hashCode();
return hashCode; return hashCode;
} }
}
public static class ConfigHashSet extends Array2DHashSet<ATNConfig> {
public int hashCode(ATNConfig o) {
return o.hashCode();
}
@Override
public boolean equals(ATNConfig a, ATNConfig b) { public boolean equals(ATNConfig a, ATNConfig b) {
if ( a==null && b==null ) return true;
if ( a==null || b==null ) return false;
if ( a==b ) return true; if ( a==b ) return true;
if ( a==null || b==null ) return false;
if ( hashCode(a) != hashCode(b) ) return false; if ( hashCode(a) != hashCode(b) ) return false;
return a.equals(b); return a.state.stateNumber==b.state.stateNumber
&& a.alt==b.alt
&& b.semanticContext.equals(b.semanticContext);
} }
} }
@ -264,10 +238,8 @@ public class ATNConfigSet implements Set<ATNConfig> {
if ( config.semanticContext!=SemanticContext.NONE ) { if ( config.semanticContext!=SemanticContext.NONE ) {
hasSemanticContext = true; hasSemanticContext = true;
} }
Key key = new Key(config); ATNConfig existing = configLookup.put(config);
ATNConfig existing = configLookup.get(config); if ( existing==config ) { // we added this new one
if ( existing==null ) { // nothing there yet; easy, just add
configLookup.add(config);
configs.add(config); // track order here configs.add(config); // track order here
return true; return true;
} }
@ -346,8 +318,8 @@ public class ATNConfigSet implements Set<ATNConfig> {
public boolean equals(Object o) { public boolean equals(Object o) {
// System.out.print("equals " + this + ", " + o+" = "); // System.out.print("equals " + this + ", " + o+" = ");
ATNConfigSet other = (ATNConfigSet)o; ATNConfigSet other = (ATNConfigSet)o;
boolean same = configLookup!=null && boolean same = configs!=null &&
configLookup.equals(other.configLookup) && configs.equals(other.configs) && // includes stack context
this.fullCtx == other.fullCtx && this.fullCtx == other.fullCtx &&
this.uniqueAlt == other.uniqueAlt && this.uniqueAlt == other.uniqueAlt &&
this.conflictingAlts == other.conflictingAlts && this.conflictingAlts == other.conflictingAlts &&

View File

@ -206,7 +206,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
public int predictATN(@NotNull DFA dfa, @NotNull TokenStream input, public int predictATN(@NotNull DFA dfa, @NotNull TokenStream input,
@Nullable ParserRuleContext<?> outerContext) @Nullable ParserRuleContext<?> outerContext)
{ {
contextCache = new PredictionContextCache("predict ctx cache"); //contextCache = new PredictionContextCache("predict ctx cache");
if ( outerContext==null ) outerContext = ParserRuleContext.EMPTY; if ( outerContext==null ) outerContext = ParserRuleContext.EMPTY;
if ( debug || debug_list_atn_decisions ) { if ( debug || debug_list_atn_decisions ) {
System.out.println("predictATN decision "+dfa.decision+ System.out.println("predictATN decision "+dfa.decision+
@ -268,7 +268,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
if ( dfa_debug ) System.out.println("ctx sensitive state "+outerContext+" in "+s); if ( dfa_debug ) System.out.println("ctx sensitive state "+outerContext+" in "+s);
boolean loopsSimulateTailRecursion = true; boolean loopsSimulateTailRecursion = true;
boolean fullCtx = true; boolean fullCtx = true;
contextCache = new PredictionContextCache("predict ctx cache built in execDFA"); // contextCache = new PredictionContextCache("predict ctx cache built in execDFA");
ATNConfigSet s0_closure = ATNConfigSet s0_closure =
computeStartState(dfa.atnStartState, outerContext, computeStartState(dfa.atnStartState, outerContext,
greedy, loopsSimulateTailRecursion, greedy, loopsSimulateTailRecursion,
@ -312,7 +312,7 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
" at DFA state "+s.stateNumber); " at DFA state "+s.stateNumber);
} }
contextCache = new PredictionContextCache("predict ctx cache built in execDFA"); // contextCache = new PredictionContextCache("predict ctx cache built in execDFA");
alt = execATN(dfa, s, input, startIndex, outerContext); alt = execATN(dfa, s, input, startIndex, outerContext);
contextCache = null; contextCache = null;
// this adds edge even if next state is accept for // this adds edge even if next state is accept for

View File

@ -7,9 +7,9 @@ import java.util.Set;
/** Set impl with closed hashing (open addressing). */ /** Set impl with closed hashing (open addressing). */
public class Array2DHashSet<T> implements Set<T> { public class Array2DHashSet<T> implements Set<T> {
public static final int INITAL_CAPACITY = 4; public static final int INITAL_CAPACITY = 16; // must be power of 2
public static final int INITAL_BUCKET_CAPACITY = 2; public static final int INITAL_BUCKET_CAPACITY = 8;
public static final double LOAD_FACTOR = 0.8; public static final double LOAD_FACTOR = 0.75;
protected T[][] buckets; protected T[][] buckets;
@ -19,9 +19,15 @@ public class Array2DHashSet<T> implements Set<T> {
protected int threshold = (int)(INITAL_CAPACITY * LOAD_FACTOR); // when to expand protected int threshold = (int)(INITAL_CAPACITY * LOAD_FACTOR); // when to expand
protected int currentPrime = 1; // jump by 4 primes each expand or whatever protected int currentPrime = 1; // jump by 4 primes each expand or whatever
protected int initialBucketCapacity = INITAL_BUCKET_CAPACITY;
public Array2DHashSet() { public Array2DHashSet() {
buckets = (T[][])new Object[INITAL_CAPACITY][]; this(INITAL_CAPACITY, INITAL_BUCKET_CAPACITY);
}
public Array2DHashSet(int initialCapacity, int initialBucketCapacity) {
buckets = (T[][])new Object[initialCapacity][];
this.initialBucketCapacity = initialBucketCapacity;
} }
/** Add o to set if not there; return existing value if already there. */ /** Add o to set if not there; return existing value if already there. */
@ -33,12 +39,14 @@ public class Array2DHashSet<T> implements Set<T> {
protected T put_(T o) { protected T put_(T o) {
int b = getBucket(o); int b = getBucket(o);
T[] bucket = buckets[b]; T[] bucket = buckets[b];
// NEW BUCKET
if ( bucket==null ) { if ( bucket==null ) {
buckets[b] = (T[])new Object[INITAL_BUCKET_CAPACITY]; buckets[b] = (T[])new Object[initialBucketCapacity];
buckets[b][0] = o; buckets[b][0] = o;
n++; n++;
return o; return o;
} }
// LOOK FOR IT IN BUCKET
for (int i=0; i<bucket.length; i++) { for (int i=0; i<bucket.length; i++) {
T existing = bucket[i]; T existing = bucket[i];
if ( existing==null ) { // empty slot; not there, add. if ( existing==null ) { // empty slot; not there, add.
@ -46,14 +54,14 @@ public class Array2DHashSet<T> implements Set<T> {
n++; n++;
return o; return o;
} }
if ( existing.equals(o) ) return existing; if ( equals(existing,o) ) return existing; // found existing, quit
} }
// full bucket, expand and add to end // FULL BUCKET, expand and add to end
T[] old = bucket; T[] old = bucket;
bucket = (T[])new Object[old.length * 2]; bucket = (T[])new Object[old.length * 2];
buckets[b] = bucket; buckets[b] = bucket;
System.arraycopy(old, 0, bucket, 0, old.length); System.arraycopy(old, 0, bucket, 0, old.length);
bucket[old.length] = o; bucket[old.length] = o; // add to end
n++; n++;
return o; return o;
} }
@ -65,7 +73,7 @@ public class Array2DHashSet<T> implements Set<T> {
if ( bucket==null ) return null; // no bucket if ( bucket==null ) return null; // no bucket
for (T e : bucket) { for (T e : bucket) {
if ( e==null ) return null; // empty slot; not there if ( e==null ) return null; // empty slot; not there
if ( e.equals(o) ) return e; if ( equals(e,o) ) return e;
} }
return null; return null;
} }
@ -83,7 +91,7 @@ public class Array2DHashSet<T> implements Set<T> {
if ( bucket==null ) continue; if ( bucket==null ) continue;
for (T o : bucket) { for (T o : bucket) {
if ( o==null ) break; if ( o==null ) break;
h += o.hashCode(); h += hashCode(o);
} }
} }
return h; return h;
@ -95,7 +103,8 @@ public class Array2DHashSet<T> implements Set<T> {
if ( !(o instanceof Array2DHashSet) || o==null ) return false; if ( !(o instanceof Array2DHashSet) || o==null ) return false;
Array2DHashSet<T> other = (Array2DHashSet<T>)o; Array2DHashSet<T> other = (Array2DHashSet<T>)o;
if ( other.size() != size() ) return false; if ( other.size() != size() ) return false;
return containsAll(other); boolean same = this.containsAll(other) && other.containsAll(this);
return same;
} }
protected void expand() { protected void expand() {
@ -209,7 +218,7 @@ public class Array2DHashSet<T> implements Set<T> {
for (int i=0; i<bucket.length; i++) { for (int i=0; i<bucket.length; i++) {
T e = bucket[i]; T e = bucket[i];
if ( e==null ) return false; // empty slot; not there if ( e==null ) return false; // empty slot; not there
if ( e.equals(o) ) { // found it if ( equals(e,(T)o) ) { // found it
// shift all elements to the right down one // shift all elements to the right down one
// for (int j=i; j<bucket.length-1; j++) bucket[j] = bucket[j+1]; // for (int j=i; j<bucket.length-1; j++) bucket[j] = bucket[j+1];
System.arraycopy(bucket, i+1, bucket, i, bucket.length-i-1); System.arraycopy(bucket, i+1, bucket, i, bucket.length-i-1);