Search in sources :

Example 1 with MethodVisitor

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);
}
Also used : CodeFlow(org.springframework.expression.spel.CodeFlow) ClassWriter(org.springframework.asm.ClassWriter) MethodVisitor(org.springframework.asm.MethodVisitor) Nullable(org.springframework.lang.Nullable)

Example 2 with MethodVisitor

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();
    }
}
Also used : MethodVisitor(org.springframework.asm.MethodVisitor)

Aggregations

MethodVisitor (org.springframework.asm.MethodVisitor)2 ClassWriter (org.springframework.asm.ClassWriter)1 CodeFlow (org.springframework.expression.spel.CodeFlow)1 Nullable (org.springframework.lang.Nullable)1