caching more operations in mergeCache, updated comments, added null chk in front of mergeCache ops.
This commit is contained in:
parent
5455813145
commit
b160a3b14d
|
@ -103,10 +103,21 @@ import java.util.Set;
|
|||
simple. By launching multiple threads, we can improve the speed of
|
||||
parsing across a large number of files.
|
||||
|
||||
This strategy is complex because we bounce back and forth from
|
||||
the ATN to the DFA, simultaneously performing predictions and
|
||||
extending the DFA according to previously unseen input
|
||||
sequences.
|
||||
There is no strict ordering between the amount of input used by
|
||||
SLL vs LL, which makes it really hard to build a cache for full
|
||||
context. Let's say that we have input A B C that leads to an SLL
|
||||
conflict with full context X. That implies that using X we
|
||||
might only use A B but we could also use A B C D to resolve
|
||||
conflict. Input A B C D could predict alternative 1 in one
|
||||
position in the input and A B C E could predict alternative 2 in
|
||||
another position in input. The conflicting SLL configurations
|
||||
could still be non-unique in the full context prediction, which
|
||||
would lead us to requiring more input than the original A B C. To
|
||||
make a prediction cache work, we have to track the exact input used
|
||||
during the previous prediction. That amounts to a cache that maps X
|
||||
to a specific DFA for that context.
|
||||
|
||||
AVOIDING FULL CONTEXT PREDICTION
|
||||
|
||||
We avoid doing full context retry when the outer context is empty,
|
||||
we did not dip into the outer context by falling off the end of the
|
||||
|
@ -263,6 +274,9 @@ public class ParserATNSimulator<Symbol extends Token> extends ATNSimulator {
|
|||
* Don't keep around as it wastes huge amounts of memory. DoubleKeyMap
|
||||
* isn't synchronized but we're ok since two threads shouldn't reuse same
|
||||
* parser/atnsim object because it can only handle one input at a time.
|
||||
* This maps graphs a and b to merged result c. (a,b)->c. We can avoid
|
||||
* the merge if we ever see a and b again. Note that (b,a)->c should
|
||||
* also be examined during cache lookup.
|
||||
*/
|
||||
protected DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache;
|
||||
|
||||
|
|
|
@ -156,8 +156,18 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
boolean rootIsWildcard,
|
||||
DoubleKeyMap<PredictionContext,PredictionContext,PredictionContext> mergeCache)
|
||||
{
|
||||
if ( mergeCache!=null ) {
|
||||
PredictionContext previous = mergeCache.get(a,b);
|
||||
if ( previous!=null ) return previous;
|
||||
previous = mergeCache.get(b,a);
|
||||
if ( previous!=null ) return previous;
|
||||
}
|
||||
|
||||
PredictionContext rootMerge = mergeRoot(a, b, rootIsWildcard);
|
||||
if ( rootMerge!=null ) return rootMerge;
|
||||
if ( rootMerge!=null ) {
|
||||
if ( mergeCache!=null ) mergeCache.put(a, b, rootMerge);
|
||||
return rootMerge;
|
||||
}
|
||||
|
||||
if ( a.invokingState==b.invokingState ) { // a == b
|
||||
PredictionContext parent = merge(a.parent, b.parent, rootIsWildcard, mergeCache);
|
||||
|
@ -169,6 +179,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
// of those graphs. dup a, a' points at merged array
|
||||
// new joined parent so create new singleton pointing to it, a'
|
||||
PredictionContext a_ = new SingletonPredictionContext(parent, a.invokingState);
|
||||
if ( mergeCache!=null ) mergeCache.put(a, b, a_);
|
||||
return a_;
|
||||
}
|
||||
else { // a != b payloads differ
|
||||
|
@ -190,6 +201,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
}
|
||||
PredictionContext[] parents = {singleParent, singleParent};
|
||||
PredictionContext a_ = new ArrayPredictionContext(parents, payloads);
|
||||
if ( mergeCache!=null ) mergeCache.put(a, b, a_);
|
||||
return a_;
|
||||
}
|
||||
// parents differ and can't merge them. Just pack together
|
||||
|
@ -203,6 +215,7 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
parents = new PredictionContext[] {b.parent, a.parent};
|
||||
}
|
||||
PredictionContext a_ = new ArrayPredictionContext(parents, payloads);
|
||||
if ( mergeCache!=null ) mergeCache.put(a, b, a_);
|
||||
return a_;
|
||||
}
|
||||
}
|
||||
|
@ -248,6 +261,8 @@ public abstract class PredictionContext implements Iterable<SingletonPredictionC
|
|||
if ( mergeCache!=null ) {
|
||||
PredictionContext previous = mergeCache.get(a,b);
|
||||
if ( previous!=null ) return previous;
|
||||
previous = mergeCache.get(b,a);
|
||||
if ( previous!=null ) return previous;
|
||||
}
|
||||
|
||||
// merge sorted payloads a + b => M
|
||||
|
|
Loading…
Reference in New Issue