mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
StateMerger: merge ranges if two states differ only by single variable range (speeds up testLongDisjunctionsNotComplex)
This commit is contained in:
@@ -253,6 +253,52 @@ class StateMerger {
|
||||
return new ArrayList<>(new LinkedHashSet<>(states));
|
||||
}
|
||||
}
|
||||
// For every variable with more than one range, try to union range info and see if some states could be merged after that
|
||||
for (Map.Entry<DfaVariableValue, Map<LongRangeSet, LongRangeSet>> entry : ranges.entrySet()) {
|
||||
if (entry.getValue().size() > 1) {
|
||||
class Record {
|
||||
final DfaMemoryStateImpl myState;
|
||||
final LongRangeSet myRange;
|
||||
|
||||
Record(DfaMemoryStateImpl state, LongRangeSet range) {
|
||||
myState = state;
|
||||
myRange = range;
|
||||
}
|
||||
|
||||
Record union(Record other) {
|
||||
return new Record(myState, myRange.union(other.myRange));
|
||||
}
|
||||
}
|
||||
|
||||
Map<DfaMemoryStateImpl, Record> merged = new LinkedHashMap<>();
|
||||
DfaVariableValue var = entry.getKey();
|
||||
for (DfaMemoryStateImpl state : states) {
|
||||
DfaVariableState variableState = state.getVariableState(var);
|
||||
LongRangeSet range = variableState.getRange();
|
||||
if (range == null) {
|
||||
range = Objects.requireNonNull(LongRangeSet.fromType(var.getVariableType()));
|
||||
}
|
||||
merged.merge(copyWithoutVar(state, var), new Record(state, range), Record::union);
|
||||
}
|
||||
if(merged.size() < states.size()) {
|
||||
List<DfaMemoryStateImpl> updated = new ArrayList<>(merged.size());
|
||||
for (Record record : merged.values()) {
|
||||
DfaMemoryStateImpl state = record.myState;
|
||||
DfaVariableState variableState = state.getVariableState(var);
|
||||
if(!record.myRange.equals(variableState.getRange())) {
|
||||
state.flushVariable(var);
|
||||
state.setRange(var, record.myRange);
|
||||
}
|
||||
updated.add(state);
|
||||
}
|
||||
states = updated;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
return states;
|
||||
}
|
||||
if (states.size() <= MAX_RANGE_STATES || ranges.isEmpty()) return null;
|
||||
// If there are too many states, try to drop range information from some variable
|
||||
DfaVariableValue lastVar = Collections.max(ranges.keySet(), Comparator.comparingInt(DfaVariableValue::getID));
|
||||
|
||||
+18
@@ -79,6 +79,19 @@ public abstract class LongRangeSet {
|
||||
*/
|
||||
public abstract LongRangeSet intersect(LongRangeSet other);
|
||||
|
||||
/**
|
||||
* Merge current set with other
|
||||
*
|
||||
* @param other other set to merge with
|
||||
* @return a new set
|
||||
*/
|
||||
public LongRangeSet union(LongRangeSet other) {
|
||||
if(other.isEmpty() || other == this) return this;
|
||||
if(other.contains(this)) return other;
|
||||
// TODO: optimize
|
||||
return Range.LONG_RANGE.subtract(Range.LONG_RANGE.subtract(this).intersect(Range.LONG_RANGE.subtract(other)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a minimal value contained in the set
|
||||
* @throws NoSuchElementException if set is empty
|
||||
@@ -266,6 +279,11 @@ public abstract class LongRangeSet {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LongRangeSet union(LongRangeSet other) {
|
||||
return other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long min() {
|
||||
throw new NoSuchElementException();
|
||||
|
||||
@@ -11,7 +11,7 @@ package test.deadcode;
|
||||
import java.io.IOException;
|
||||
|
||||
public class aaa {
|
||||
int a;
|
||||
Object a;
|
||||
int b;
|
||||
|
||||
void x(int i, Object o) {
|
||||
|
||||
Reference in New Issue
Block a user