optimizing constant expressions in profile parsing
This commit is contained in:
parent
ef73d468c0
commit
de0acb77c5
4 changed files with 117 additions and 15 deletions
|
@ -91,8 +91,8 @@ public final class ProfileCache {
|
||||||
|
|
||||||
meta.readMetaData(new File(profileDir, "lookups.dat"));
|
meta.readMetaData(new File(profileDir, "lookups.dat"));
|
||||||
|
|
||||||
rc.expctxWay.parseFile(profileFile, "global");
|
rc.expctxWay.parseFile(profileFile, "global", rc.keyValues);
|
||||||
rc.expctxNode.parseFile(profileFile, "global");
|
rc.expctxNode.parseFile(profileFile, "global", rc.keyValues);
|
||||||
|
|
||||||
rc.readGlobalConfig();
|
rc.readGlobalConfig();
|
||||||
|
|
||||||
|
|
|
@ -108,16 +108,6 @@ public final class RoutingContext {
|
||||||
|
|
||||||
public void readGlobalConfig() {
|
public void readGlobalConfig() {
|
||||||
BExpressionContext expctxGlobal = expctxWay; // just one of them...
|
BExpressionContext expctxGlobal = expctxWay; // just one of them...
|
||||||
|
|
||||||
if (keyValues != null) {
|
|
||||||
// add parameter to context
|
|
||||||
for (Map.Entry<String, String> e : keyValues.entrySet()) {
|
|
||||||
float f = Float.parseFloat(e.getValue());
|
|
||||||
expctxWay.setVariableValue(e.getKey(), f, true);
|
|
||||||
expctxNode.setVariableValue(e.getKey(), f, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setModel(expctxGlobal._modelClass);
|
setModel(expctxGlobal._modelClass);
|
||||||
|
|
||||||
carMode = 0.f != expctxGlobal.getVariableValue("validForCars", 0.f);
|
carMode = 0.f != expctxGlobal.getVariableValue("validForCars", 0.f);
|
||||||
|
|
|
@ -32,7 +32,7 @@ final class BExpression {
|
||||||
private BExpression op3;
|
private BExpression op3;
|
||||||
private float numberValue;
|
private float numberValue;
|
||||||
private int variableIdx;
|
private int variableIdx;
|
||||||
private int lookupNameIdx;
|
private int lookupNameIdx = -1;
|
||||||
private int[] lookupValueIdxArray;
|
private int[] lookupValueIdxArray;
|
||||||
|
|
||||||
// Parse the expression and all subexpression
|
// Parse the expression and all subexpression
|
||||||
|
@ -41,6 +41,50 @@ final class BExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BExpression parse(BExpressionContext ctx, int level, String optionalToken) throws Exception {
|
private static BExpression parse(BExpressionContext ctx, int level, String optionalToken) throws Exception {
|
||||||
|
BExpression e = parseRaw(ctx, level, optionalToken);
|
||||||
|
if (e == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to simplify the expression
|
||||||
|
if (ASSIGN_EXP == e.typ) {
|
||||||
|
ctx.lastAssignedExpression.set(e.variableIdx, e.op1);
|
||||||
|
} else if (VARIABLE_EXP == e.typ) {
|
||||||
|
BExpression ae = ctx.lastAssignedExpression.get(e.variableIdx);
|
||||||
|
if (ae != null && ae.typ == NUMBER_EXP) {
|
||||||
|
e = ae;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
e = e.tryCollapse();
|
||||||
|
e = e.tryEvaluateConstant();
|
||||||
|
}
|
||||||
|
if (level == 0) {
|
||||||
|
// mark the used lookups after the
|
||||||
|
// expression is collapsed to not mark
|
||||||
|
// lookups as used that appear in the profile
|
||||||
|
// but are de-activated by constant expressions
|
||||||
|
e.markLookupIdxUsed(ctx);
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markLookupIdxUsed(BExpressionContext ctx) {
|
||||||
|
if (lookupNameIdx >= 0) {
|
||||||
|
ctx.markLookupIdxUsed(lookupNameIdx);
|
||||||
|
}
|
||||||
|
if (op1 != null) {
|
||||||
|
op1.markLookupIdxUsed(ctx);
|
||||||
|
}
|
||||||
|
if (op2 != null) {
|
||||||
|
op2.markLookupIdxUsed(ctx);
|
||||||
|
}
|
||||||
|
if (op3 != null) {
|
||||||
|
op3.markLookupIdxUsed(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BExpression parseRaw(BExpressionContext ctx, int level, String optionalToken) throws Exception {
|
||||||
|
|
||||||
boolean brackets = false;
|
boolean brackets = false;
|
||||||
String operator = ctx.parseToken();
|
String operator = ctx.parseToken();
|
||||||
if (optionalToken != null && optionalToken.equals(operator)) {
|
if (optionalToken != null && optionalToken.equals(operator)) {
|
||||||
|
@ -64,6 +108,8 @@ final class BExpression {
|
||||||
|
|
||||||
BExpression exp = new BExpression();
|
BExpression exp = new BExpression();
|
||||||
int nops = 3;
|
int nops = 3;
|
||||||
|
BExpression op1Replacement = null;
|
||||||
|
|
||||||
boolean ifThenElse = false;
|
boolean ifThenElse = false;
|
||||||
|
|
||||||
if ("switch".equals(operator)) {
|
if ("switch".equals(operator)) {
|
||||||
|
@ -110,6 +156,16 @@ final class BExpression {
|
||||||
exp.variableIdx = ctx.getVariableIdx(variable, true);
|
exp.variableIdx = ctx.getVariableIdx(variable, true);
|
||||||
if (exp.variableIdx < ctx.getMinWriteIdx())
|
if (exp.variableIdx < ctx.getMinWriteIdx())
|
||||||
throw new IllegalArgumentException("cannot assign to readonly variable " + variable);
|
throw new IllegalArgumentException("cannot assign to readonly variable " + variable);
|
||||||
|
|
||||||
|
// possibly replace the value to assign by an injected value
|
||||||
|
if (ctx.keyValues != null) {
|
||||||
|
String v = ctx.keyValues.get(variable);
|
||||||
|
if (v != null) {
|
||||||
|
op1Replacement = new BExpression();
|
||||||
|
op1Replacement.typ = NUMBER_EXP;
|
||||||
|
op1Replacement.numberValue = Float.parseFloat(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if ("not".equals(operator)) {
|
} else if ("not".equals(operator)) {
|
||||||
exp.typ = NOT_EXP;
|
exp.typ = NOT_EXP;
|
||||||
} else {
|
} else {
|
||||||
|
@ -124,7 +180,6 @@ final class BExpression {
|
||||||
if (exp.lookupNameIdx < 0) {
|
if (exp.lookupNameIdx < 0) {
|
||||||
throw new IllegalArgumentException("unknown lookup name: " + name);
|
throw new IllegalArgumentException("unknown lookup name: " + name);
|
||||||
}
|
}
|
||||||
ctx.markLookupIdxUsed(exp.lookupNameIdx);
|
|
||||||
StringTokenizer tk = new StringTokenizer(values, "|");
|
StringTokenizer tk = new StringTokenizer(values, "|");
|
||||||
int nt = tk.countTokens();
|
int nt = tk.countTokens();
|
||||||
int nt2 = nt == 0 ? 1 : nt;
|
int nt2 = nt == 0 ? 1 : nt;
|
||||||
|
@ -177,6 +232,9 @@ final class BExpression {
|
||||||
// parse operands
|
// parse operands
|
||||||
if (nops > 0) {
|
if (nops > 0) {
|
||||||
exp.op1 = BExpression.parse(ctx, level + 1, exp.typ == ASSIGN_EXP ? "=" : null);
|
exp.op1 = BExpression.parse(ctx, level + 1, exp.typ == ASSIGN_EXP ? "=" : null);
|
||||||
|
if (op1Replacement != null) {
|
||||||
|
exp.op1 = op1Replacement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (nops > 1) {
|
if (nops > 1) {
|
||||||
if (ifThenElse) checkExpectedToken(ctx, "then");
|
if (ifThenElse) checkExpectedToken(ctx, "then");
|
||||||
|
@ -245,6 +303,50 @@ final class BExpression {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to collapse the expression
|
||||||
|
// if logically possible
|
||||||
|
public BExpression tryCollapse() {
|
||||||
|
switch (typ) {
|
||||||
|
case OR_EXP:
|
||||||
|
return NUMBER_EXP == op1.typ ?
|
||||||
|
(op1.numberValue != 0.f ? op1 : op2)
|
||||||
|
: (NUMBER_EXP == op2.typ ?
|
||||||
|
(op2.numberValue != 0.f ? op2 : op1)
|
||||||
|
: this);
|
||||||
|
case AND_EXP:
|
||||||
|
return NUMBER_EXP == op1.typ ?
|
||||||
|
(op1.numberValue == 0.f ? op1 : op2)
|
||||||
|
: (NUMBER_EXP == op2.typ ?
|
||||||
|
(op2.numberValue == 0.f ? op2 : op1)
|
||||||
|
: this);
|
||||||
|
case ADD_EXP:
|
||||||
|
return NUMBER_EXP == op1.typ ?
|
||||||
|
(op1.numberValue == 0.f ? op2 : this)
|
||||||
|
: (NUMBER_EXP == op2.typ ?
|
||||||
|
(op2.numberValue == 0.f ? op1 : this)
|
||||||
|
: this);
|
||||||
|
case SWITCH_EXP:
|
||||||
|
return NUMBER_EXP == op1.typ ?
|
||||||
|
(op1.numberValue == 0.f ? op3 : op2) : this;
|
||||||
|
default:
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to evaluate the expression
|
||||||
|
// if all operands are constant
|
||||||
|
public BExpression tryEvaluateConstant() {
|
||||||
|
if (op1 != null && NUMBER_EXP == op1.typ
|
||||||
|
&& (op2 == null || NUMBER_EXP == op2.typ)
|
||||||
|
&& (op3 == null || NUMBER_EXP == op3.typ)) {
|
||||||
|
BExpression exp = new BExpression();
|
||||||
|
exp.typ = NUMBER_EXP;
|
||||||
|
exp.numberValue = evaluate(null);
|
||||||
|
return exp;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private float max(float v1, float v2) {
|
private float max(float v1, float v2) {
|
||||||
return v1 > v2 ? v1 : v2;
|
return v1 > v2 ? v1 : v2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,9 @@ public abstract class BExpressionContext implements IByteArrayUnifier {
|
||||||
|
|
||||||
private Map<String, Integer> variableNumbers = new HashMap<>();
|
private Map<String, Integer> variableNumbers = new HashMap<>();
|
||||||
|
|
||||||
|
List<BExpression> lastAssignedExpression = new ArrayList<>();
|
||||||
|
Map<String, String> keyValues;
|
||||||
|
|
||||||
private float[] variableData;
|
private float[] variableData;
|
||||||
|
|
||||||
|
|
||||||
|
@ -769,6 +772,12 @@ public abstract class BExpressionContext implements IByteArrayUnifier {
|
||||||
return foreignContext.getOutputVariableIndex(name, true);
|
return foreignContext.getOutputVariableIndex(name, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void parseFile(File file, String readOnlyContext, Map<String, String> keyValues) {
|
||||||
|
this.keyValues = keyValues;
|
||||||
|
parseFile(file, readOnlyContext);
|
||||||
|
this.keyValues = null;
|
||||||
|
}
|
||||||
|
|
||||||
public void parseFile(File file, String readOnlyContext) {
|
public void parseFile(File file, String readOnlyContext) {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
throw new IllegalArgumentException("profile " + file + " does not exist");
|
throw new IllegalArgumentException("profile " + file + " does not exist");
|
||||||
|
@ -785,8 +794,8 @@ public abstract class BExpressionContext implements IByteArrayUnifier {
|
||||||
}
|
}
|
||||||
linenr = 1;
|
linenr = 1;
|
||||||
minWriteIdx = variableData == null ? 0 : variableData.length;
|
minWriteIdx = variableData == null ? 0 : variableData.length;
|
||||||
|
|
||||||
expressionList = _parseFile(file);
|
expressionList = _parseFile(file);
|
||||||
|
lastAssignedExpression = null;
|
||||||
|
|
||||||
// determine the build-in variable indices
|
// determine the build-in variable indices
|
||||||
String[] varNames = getBuildInVariableNames();
|
String[] varNames = getBuildInVariableNames();
|
||||||
|
@ -857,6 +866,7 @@ public abstract class BExpressionContext implements IByteArrayUnifier {
|
||||||
if (create) {
|
if (create) {
|
||||||
num = variableNumbers.size();
|
num = variableNumbers.size();
|
||||||
variableNumbers.put(name, num);
|
variableNumbers.put(name, num);
|
||||||
|
lastAssignedExpression.add(null);
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue