Skip to content

Commit 7bc99ab

Browse files
committed
(feat) Introduce EvalMode option, and improve logic operator performance in asm mode
1 parent 1f0278c commit 7bc99ab

28 files changed

+330
-63
lines changed

src/main/java/com/googlecode/aviator/AviatorEvaluator.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,6 @@ public final class AviatorEvaluator {
4646
*/
4747
public static final int EVAL = 1;
4848

49-
/**
50-
* Evaluate expression in interpret mode.
51-
*/
52-
public static final int INTERPRET = 2;
53-
5449
/**
5550
* Aviator version
5651
*/

src/main/java/com/googlecode/aviator/AviatorEvaluatorInstance.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import com.googlecode.aviator.annotation.ImportScope;
5252
import com.googlecode.aviator.asm.Opcodes;
5353
import com.googlecode.aviator.code.CodeGenerator;
54+
import com.googlecode.aviator.code.EvalCodeGenerator;
5455
import com.googlecode.aviator.code.InterpretCodeGenerator;
5556
import com.googlecode.aviator.code.NoneCodeGenerator;
5657
import com.googlecode.aviator.code.OptimizeCodeGenerator;
@@ -1499,6 +1500,10 @@ private Expression innerCompile(final String expression, final String sourceFile
14991500
return exp;
15001501
}
15011502

1503+
private EvalMode getEvalMode() {
1504+
return getOptionValue(Options.EVAL_MODE).evalMode;
1505+
}
1506+
15021507
private int getOptimizeLevel() {
15031508
return getOptionValue(Options.OPTIMIZE_LEVEL).number;
15041509
}
@@ -1510,19 +1515,28 @@ public CodeGenerator newCodeGenerator(final String sourceFile, final boolean cac
15101515

15111516
}
15121517

1518+
public EvalCodeGenerator newEvalCodeGenerator(final AviatorClassLoader classLoader,
1519+
final String sourceFile) {
1520+
switch (getEvalMode()) {
1521+
case ASM:
1522+
return new ASMCodeGenerator(this, sourceFile, classLoader, this.traceOutputStream);
1523+
case INTERPRETER:
1524+
return new InterpretCodeGenerator(this, sourceFile, classLoader);
1525+
default:
1526+
throw new IllegalArgumentException("Unknown eval mode: " + getEvalMode());
1527+
1528+
}
1529+
}
1530+
15131531
public CodeGenerator newCodeGenerator(final AviatorClassLoader classLoader,
15141532
final String sourceFile) {
15151533
switch (getOptimizeLevel()) {
15161534
case AviatorEvaluator.COMPILE:
1517-
ASMCodeGenerator asmCodeGenerator =
1518-
new ASMCodeGenerator(this, sourceFile, classLoader, this.traceOutputStream);
1519-
asmCodeGenerator.start();
1520-
return asmCodeGenerator;
1535+
final EvalCodeGenerator codeGen = newEvalCodeGenerator(classLoader, sourceFile);
1536+
codeGen.start();
1537+
return codeGen;
15211538
case AviatorEvaluator.EVAL:
15221539
return new OptimizeCodeGenerator(this, sourceFile, classLoader, this.traceOutputStream);
1523-
case AviatorEvaluator.INTERPRET:
1524-
// TODO
1525-
return new InterpretCodeGenerator(this, sourceFile, classLoader);
15261540
default:
15271541
throw new IllegalArgumentException("Unknow option " + getOptimizeLevel());
15281542
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.googlecode.aviator;
2+
3+
/**
4+
* Expression engine evaluate mode
5+
*
6+
* @author dennis(killme2008@gmail.com)
7+
* @since 5.3
8+
*/
9+
public enum EvalMode {
10+
/**
11+
* Generate JVM byecode by ASM and eval it by JVM.
12+
*/
13+
ASM,
14+
/**
15+
* Interpreter mode.
16+
*/
17+
INTERPRETER
18+
}

src/main/java/com/googlecode/aviator/InterpretExpression.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ public Object executeDirectly(final Map<String, Object> env) {
4040
IR ir = null;
4141
while ((ir = ctx.getPc()) != null) {
4242
if (trace) {
43-
RuntimeUtils.printlnTrace(env, " " + ir + " <Stack, " + ctx.getOperands() + ">");
43+
RuntimeUtils.printlnTrace(env, " " + ir + " <Stack, " + ctx.getOperands() + ">");
4444
}
45-
// System.out.println(ir + " " + ctx.getOperands());
4645
ir.eval(ctx);
4746
if (ir instanceof JumpIR) {
4847
if (ir != ctx.getPc()) {
48+
// jump successfully, we don't move pc to next.
4949
continue;
5050
}
5151
}
@@ -54,7 +54,7 @@ public Object executeDirectly(final Map<String, Object> env) {
5454
}
5555
}
5656

57-
assert (ctx.getOperands().size() <= 1);
57+
// assert (ctx.getOperands().size() <= 1);
5858
AviatorObject result = ctx.peek();
5959
if (result == null) {
6060
return null;

src/main/java/com/googlecode/aviator/Options.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,11 @@ public enum Options {
108108
* allowed (default); Empty ALLOWED_CLASS_SET or ASSIGNABLE_ALLOWED_CLASS_SET means forbidding all
109109
* classes.
110110
*/
111-
ASSIGNABLE_ALLOWED_CLASS_SET;
111+
ASSIGNABLE_ALLOWED_CLASS_SET,
112+
/**
113+
* Script engine evaluate mode, default is ASM mode.
114+
*/
115+
EVAL_MODE;
112116

113117

114118
/**
@@ -123,6 +127,12 @@ public static class Value {
123127
public int number;
124128
public Set<Feature> featureSet;
125129
public Set<Class<?>> classes;
130+
public EvalMode evalMode;
131+
132+
public Value(final EvalMode evalMode) {
133+
super();
134+
this.evalMode = evalMode;
135+
}
126136

127137
public Value() {
128138
super();
@@ -191,6 +201,8 @@ public Object intoObject(final Value val) {
191201
case ALLOWED_CLASS_SET:
192202
case ASSIGNABLE_ALLOWED_CLASS_SET:
193203
return val.classes;
204+
case EVAL_MODE:
205+
return val.evalMode;
194206
}
195207
throw new IllegalArgumentException("Fail to cast value " + val + " for option " + this);
196208
}
@@ -217,8 +229,6 @@ public Value intoValue(final Object val) {
217229
int level = (int) val;
218230
if (level == AviatorEvaluator.EVAL) {
219231
return EVAL_VALUE;
220-
} else if (level == AviatorEvaluator.INTERPRET) {
221-
return INTERPRET_VALUE;
222232
} else {
223233
return COMPILE_VALUE;
224234
}
@@ -232,6 +242,8 @@ public Value intoValue(final Object val) {
232242
return new Value((Set<Feature>) val);
233243
case MATH_CONTEXT:
234244
return new Value((MathContext) val);
245+
case EVAL_MODE:
246+
return new Value((EvalMode) val);
235247
}
236248
throw new IllegalArgumentException("Fail to cast value " + val + " for option " + this);
237249
}
@@ -253,12 +265,14 @@ public boolean isValidValue(final Object val) {
253265
return val instanceof Set;
254266
case OPTIMIZE_LEVEL:
255267
final int level = ((Integer) val).intValue();
256-
return val instanceof Integer && (level == AviatorEvaluator.EVAL
257-
|| level == AviatorEvaluator.COMPILE || level == AviatorEvaluator.INTERPRET);
268+
return val instanceof Integer
269+
&& (level == AviatorEvaluator.EVAL || level == AviatorEvaluator.COMPILE);
258270
case MAX_LOOP_COUNT:
259271
return val instanceof Long || val instanceof Integer;
260272
case MATH_CONTEXT:
261273
return val instanceof MathContext;
274+
case EVAL_MODE:
275+
return val instanceof EvalMode;
262276
}
263277
return false;
264278
}
@@ -275,12 +289,14 @@ public boolean isValidValue(final Object val) {
275289

276290
public static final Value COMPILE_VALUE = new Value(AviatorEvaluator.COMPILE);
277291

278-
public static final Value INTERPRET_VALUE = new Value(AviatorEvaluator.INTERPRET);
279-
280292
private static final Value FULL_FEATURE_SET = new Value(Feature.getFullFeatures());
281293
private static final boolean TRACE_EVAL_DEFAULT_VAL =
282294
Boolean.parseBoolean(System.getProperty("aviator.trace_eval", "false"));
283295

296+
public static final Value ASM_MODE = new Value(EvalMode.ASM);
297+
298+
public static final Value INTERPRETER_MODE = new Value(EvalMode.INTERPRETER);
299+
284300
public static final Value NULL_CLASS_SET = Value.fromClasses(null);
285301

286302

@@ -327,6 +343,8 @@ public Value getDefaultValueObject() {
327343
case ALLOWED_CLASS_SET:
328344
case ASSIGNABLE_ALLOWED_CLASS_SET:
329345
return NULL_CLASS_SET;
346+
case EVAL_MODE:
347+
return ASM_MODE;
330348
}
331349
return null;
332350
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.googlecode.aviator.code;
2+
3+
import java.util.Map;
4+
import java.util.Set;
5+
import com.googlecode.aviator.lexer.token.Token;
6+
import com.googlecode.aviator.parser.AviatorClassLoader;
7+
import com.googlecode.aviator.parser.VariableMeta;
8+
import com.googlecode.aviator.runtime.LambdaFunctionBootstrap;
9+
10+
public interface EvalCodeGenerator extends CodeGenerator {
11+
void start();
12+
13+
void initVariables(final Map<String, VariableMeta/* counter */> vars);
14+
15+
void initConstants(final Set<Token<?>> constants);
16+
17+
void initMethods(final Map<String, Integer/* counter */> methods);
18+
19+
void setLambdaBootstraps(final Map<String, LambdaFunctionBootstrap> lambdaBootstraps);
20+
21+
AviatorClassLoader getClassLoader();
22+
23+
void genNewLambdaCode(final LambdaFunctionBootstrap bootstrap);
24+
}

src/main/java/com/googlecode/aviator/code/InterpretCodeGenerator.java

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import com.googlecode.aviator.Options;
1818
import com.googlecode.aviator.code.asm.ASMCodeGenerator.MethodMetaData;
1919
import com.googlecode.aviator.code.interpreter.IR;
20+
import com.googlecode.aviator.code.interpreter.ir.AssertTypeIR;
21+
import com.googlecode.aviator.code.interpreter.ir.AssertTypeIR.AssertTypes;
2022
import com.googlecode.aviator.code.interpreter.ir.BranchIfIR;
2123
import com.googlecode.aviator.code.interpreter.ir.BranchUnlessIR;
2224
import com.googlecode.aviator.code.interpreter.ir.ClearIR;
@@ -28,6 +30,7 @@
2830
import com.googlecode.aviator.code.interpreter.ir.OperatorIR;
2931
import com.googlecode.aviator.code.interpreter.ir.PopIR;
3032
import com.googlecode.aviator.code.interpreter.ir.SendIR;
33+
import com.googlecode.aviator.code.interpreter.ir.SourceInfo;
3134
import com.googlecode.aviator.code.interpreter.ir.VisitLabelIR;
3235
import com.googlecode.aviator.exception.CompileExpressionErrorException;
3336
import com.googlecode.aviator.lexer.token.Token;
@@ -47,7 +50,7 @@
4750
* @author dennis(killme2008@gmail.com)
4851
*
4952
*/
50-
public class InterpretCodeGenerator implements CodeGenerator {
53+
public class InterpretCodeGenerator implements EvalCodeGenerator {
5154
private final List<IR> instruments = new ArrayList<>();
5255
private final AviatorEvaluatorInstance instance;
5356

@@ -132,6 +135,47 @@ private Label makeLabel() {
132135
return new Label(this.labelNum++);
133136
}
134137

138+
139+
140+
@Override
141+
public void start() {
142+
// TODO Auto-generated method stub
143+
144+
}
145+
146+
@Override
147+
public void initVariables(final Map<String, VariableMeta> vars) {
148+
// TODO Auto-generated method stub
149+
150+
}
151+
152+
@Override
153+
public void initConstants(final Set<Token<?>> constants) {
154+
// TODO Auto-generated method stub
155+
156+
}
157+
158+
@Override
159+
public void initMethods(final Map<String, Integer> methods) {
160+
// TODO Auto-generated method stub
161+
162+
}
163+
164+
@Override
165+
public void setLambdaBootstraps(final Map<String, LambdaFunctionBootstrap> lambdaBootstraps) {
166+
this.lambdaBootstraps = lambdaBootstraps;
167+
}
168+
169+
@Override
170+
public AviatorClassLoader getClassLoader() {
171+
return this.classLoader;
172+
}
173+
174+
@Override
175+
public void genNewLambdaCode(final LambdaFunctionBootstrap bootstrap) {
176+
this.instruments.add(new NewLambdaIR(bootstrap.getName()));
177+
}
178+
135179
public InterpretCodeGenerator(final AviatorEvaluatorInstance instance, final String sourceFile,
136180
final AviatorClassLoader classLoader) {
137181
super();
@@ -218,13 +262,16 @@ public void onDiv(final Token<?> lookhead) {
218262

219263
@Override
220264
public void onAndLeft(final Token<?> lookhead) {
265+
this.instruments.add(new AssertTypeIR(AssertTypes.Bool));
221266
Label label = makeLabel();
222267
pushLabel0(label);
223-
this.instruments.add(new BranchUnlessIR(label));
268+
this.instruments
269+
.add(new BranchUnlessIR(label, new SourceInfo(this.sourceFile, lookhead.getLineNo())));
224270
}
225271

226272
@Override
227273
public void onAndRight(final Token<?> lookhead) {
274+
this.instruments.add(new AssertTypeIR(AssertTypes.Bool));
228275
Label label = popLabel0();
229276
visitLabel(label);
230277
}
@@ -235,13 +282,15 @@ public void onTernaryBoolean(final Token<?> lookhead) {
235282
pushLabel0(label0);
236283
Label label1 = makeLabel();
237284
pushLabel1(label1);
238-
this.instruments.add(new BranchUnlessIR(label0));
285+
this.instruments
286+
.add(new BranchUnlessIR(label0, new SourceInfo(this.sourceFile, lookhead.getLineNo())));
239287
this.instruments.add(PopIR.INSTANCE);
240288
}
241289

242290
@Override
243291
public void onTernaryLeft(final Token<?> lookhead) {
244-
this.instruments.add(new GotoIR(peekLabel1()));
292+
this.instruments
293+
.add(new GotoIR(peekLabel1(), new SourceInfo(this.sourceFile, lookhead.getLineNo())));
245294

246295
this.instruments.add(PopIR.INSTANCE);
247296
Label label0 = popLabel0();
@@ -262,13 +311,16 @@ public void onTernaryEnd(final Token<?> lookhead) {
262311

263312
@Override
264313
public void onJoinLeft(final Token<?> lookhead) {
314+
this.instruments.add(new AssertTypeIR(AssertTypes.Bool));
265315
Label label = makeLabel();
266316
pushLabel0(label);
267-
this.instruments.add(new BranchIfIR(label));
317+
this.instruments
318+
.add(new BranchIfIR(label, new SourceInfo(this.sourceFile, lookhead.getLineNo())));
268319
}
269320

270321
@Override
271322
public void onJoinRight(final Token<?> lookhead) {
323+
this.instruments.add(new AssertTypeIR(AssertTypes.Bool));
272324
Label label = popLabel0();
273325
visitLabel(label);
274326
}
@@ -416,7 +468,7 @@ public void onMethodInvoke(final Token<?> lookhead) {
416468

417469
this.instruments.add(new SendIR(methodMetaData.methodName, methodMetaData.parameterCount,
418470
methodMetaData.token.getMeta(Constants.UNPACK_ARGS, false), methodMetaData.funcId,
419-
this.sourceFile, methodMetaData.token.getLineNo()));
471+
new SourceInfo(this.sourceFile, methodMetaData.token.getLineNo())));
420472
}
421473

422474
@Override
@@ -454,7 +506,7 @@ public void onLambdaBodyEnd(final Token<?> lookhead) {
454506
this.lambdaBootstraps = new LinkedHashMap<String, LambdaFunctionBootstrap>();
455507
}
456508
this.lambdaBootstraps.put(bootstrap.getName(), bootstrap);
457-
this.instruments.add(new NewLambdaIR(bootstrap.getName()));
509+
genNewLambdaCode(bootstrap);
458510
this.parser.restoreScope(this.lambdaGenerator.getScopeInfo());
459511
this.lambdaGenerator = null;
460512
this.parser.setCodeGenerator(this.parentCodeGenerator);

0 commit comments

Comments
 (0)