use of org.springframework.asm.MethodVisitor in project spring-framework by spring-projects.
the class SpelCompiler method createExpressionClass.
/**
* Generate the class that encapsulates the compiled expression and define it.
* The generated class will be a subtype of CompiledExpression.
* @param expressionToCompile the expression to be compiled
* @return the expression call, or {@code null} if the decision was to opt out of
* compilation during code generation
*/
@Nullable
private Class<? extends CompiledExpression> createExpressionClass(SpelNodeImpl expressionToCompile) {
// Create class outline 'spel/ExNNN extends org.springframework.expression.spel.CompiledExpression'
String className = "spel/Ex" + getNextSuffix();
String evaluationContextClass = "org/springframework/expression/EvaluationContext";
ClassWriter cw = new ExpressionClassWriter();
cw.visit(V1_8, ACC_PUBLIC, className, null, "org/springframework/expression/spel/CompiledExpression", null);
// Create default constructor
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "org/springframework/expression/spel/CompiledExpression", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
// Create getValue() method
mv = cw.visitMethod(ACC_PUBLIC, "getValue", "(Ljava/lang/Object;L" + evaluationContextClass + ";)Ljava/lang/Object;", null, new String[] { "org/springframework/expression/EvaluationException" });
mv.visitCode();
CodeFlow cf = new CodeFlow(className, cw);
// Ask the expression AST to generate the body of the method
try {
expressionToCompile.generateCode(mv, cf);
} catch (IllegalStateException ex) {
if (logger.isDebugEnabled()) {
logger.debug(expressionToCompile.getClass().getSimpleName() + ".generateCode opted out of compilation: " + ex.getMessage());
}
return null;
}
CodeFlow.insertBoxIfNecessary(mv, cf.lastDescriptor());
if ("V".equals(cf.lastDescriptor())) {
mv.visitInsn(ACONST_NULL);
}
mv.visitInsn(ARETURN);
// not supplied due to COMPUTE_MAXS
mv.visitMaxs(0, 0);
mv.visitEnd();
cw.visitEnd();
cf.finish();
byte[] data = cw.toByteArray();
// dump(expressionToCompile.toStringAST(), clazzName, data);
return loadClass(StringUtils.replace(className, "/", "."), data);
}
use of org.springframework.asm.MethodVisitor in project spring-framework by spring-projects.
the class CodeFlow method finish.
/**
* Called after the main expression evaluation method has been generated, this
* method will callback any registered FieldAdders or ClinitAdders to add any
* extra information to the class representing the compiled expression.
*/
public void finish() {
if (this.fieldAdders != null) {
for (FieldAdder fieldAdder : this.fieldAdders) {
fieldAdder.generateField(this.classWriter, this);
}
}
if (this.clinitAdders != null) {
MethodVisitor mv = this.classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, "<clinit>", "()V", null, null);
mv.visitCode();
// to 0 because there is no 'this' in a clinit
this.nextFreeVariableId = 0;
for (ClinitAdder clinitAdder : this.clinitAdders) {
clinitAdder.generateCode(mv, this);
}
mv.visitInsn(RETURN);
// not supplied due to COMPUTE_MAXS
mv.visitMaxs(0, 0);
mv.visitEnd();
}
}
Aggregations