Java Code Examples for org.springframework.expression.spel.CodeFlow#insertBoxIfNecessary()

The following examples show how to use org.springframework.expression.spel.CodeFlow#insertBoxIfNecessary() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: SpelNodeImpl.java    From lams with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Ask an argument to generate its bytecode and then follow it up
 * with any boxing/unboxing/checkcasting to ensure it matches the expected parameter descriptor.
 */
protected static void generateCodeForArgument(MethodVisitor mv, CodeFlow cf, SpelNodeImpl argument, String paramDesc) {
	cf.enterCompilationScope();
	argument.generateCode(mv, cf);
	String lastDesc = cf.lastDescriptor();
	boolean primitiveOnStack = CodeFlow.isPrimitive(lastDesc);
	// Check if need to box it for the method reference?
	if (primitiveOnStack && paramDesc.charAt(0) == 'L') {
		CodeFlow.insertBoxIfNecessary(mv, lastDesc.charAt(0));
	}
	else if (paramDesc.length() == 1 && !primitiveOnStack) {
		CodeFlow.insertUnboxInsns(mv, paramDesc.charAt(0), lastDesc);
	}
	else if (!paramDesc.equals(lastDesc)) {
		// This would be unnecessary in the case of subtyping (e.g. method takes Number but Integer passed in)
		CodeFlow.insertCheckCast(mv, paramDesc);
	}
	cf.exitCompilationScope();
}
 
Example 2
Source File: Elvis.java    From spring4-understanding with Apache License 2.0 6 votes vote down vote up
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
	// exit type descriptor can be null if both components are literal expressions
	computeExitTypeDescriptor();
	this.children[0].generateCode(mv, cf);
	Label elseTarget = new Label();
	Label endOfIf = new Label();
	mv.visitInsn(DUP);
	mv.visitJumpInsn(IFNULL, elseTarget);
	mv.visitJumpInsn(GOTO, endOfIf);
	mv.visitLabel(elseTarget);
	mv.visitInsn(POP);
	this.children[1].generateCode(mv, cf);
	if (!CodeFlow.isPrimitive(this.exitTypeDescriptor)) {
		CodeFlow.insertBoxIfNecessary(mv, cf.lastDescriptor().charAt(0));
	}
	mv.visitLabel(endOfIf);
	cf.pushDescriptor(this.exitTypeDescriptor);
}
 
Example 3
Source File: OperatorInstanceof.java    From java-technology-stack with MIT License 6 votes vote down vote up
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
	getLeftOperand().generateCode(mv, cf);
	CodeFlow.insertBoxIfNecessary(mv, cf.lastDescriptor());
	Assert.state(this.type != null, "No type available");
	if (this.type.isPrimitive()) {
		// always false - but left operand code always driven
		// in case it had side effects
		mv.visitInsn(POP);
		mv.visitInsn(ICONST_0); // value of false
	}
	else {
		mv.visitTypeInsn(INSTANCEOF, Type.getInternalName(this.type));
	}
	cf.pushDescriptor(this.exitTypeDescriptor);
}
 
Example 4
Source File: SpelNodeImpl.java    From spring4-understanding with Apache License 2.0 6 votes vote down vote up
/**
 * Ask an argument to generate its bytecode and then follow it up
 * with any boxing/unboxing/checkcasting to ensure it matches the expected parameter descriptor.
 */
protected static void generateCodeForArgument(MethodVisitor mv, CodeFlow cf, SpelNodeImpl argument, String paramDesc) {
	cf.enterCompilationScope();
	argument.generateCode(mv, cf);
	boolean primitiveOnStack = CodeFlow.isPrimitive(cf.lastDescriptor());
	// Check if need to box it for the method reference?
	if (primitiveOnStack && paramDesc.charAt(0) == 'L') {
		CodeFlow.insertBoxIfNecessary(mv, cf.lastDescriptor().charAt(0));
	}
	else if (paramDesc.length() == 1 && !primitiveOnStack) {
		CodeFlow.insertUnboxInsns(mv, paramDesc.charAt(0), cf.lastDescriptor());
	}
	else if (!cf.lastDescriptor().equals(paramDesc)) {
		// This would be unnecessary in the case of subtyping (e.g. method takes Number but Integer passed in)
		CodeFlow.insertCheckCast(mv, paramDesc);
	}
	cf.exitCompilationScope();
}
 
Example 5
Source File: Elvis.java    From lams with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
	// exit type descriptor can be null if both components are literal expressions
	computeExitTypeDescriptor();
	this.children[0].generateCode(mv, cf);
	CodeFlow.insertBoxIfNecessary(mv, cf.lastDescriptor().charAt(0));
	Label elseTarget = new Label();
	Label endOfIf = new Label();
	mv.visitInsn(DUP);
	mv.visitJumpInsn(IFNULL, elseTarget);
	// Also check if empty string, as per the code in the interpreted version
	mv.visitInsn(DUP);
	mv.visitLdcInsn("");
	mv.visitInsn(SWAP);
	mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z",false);
	mv.visitJumpInsn(IFEQ, endOfIf);  // if not empty, drop through to elseTarget
	mv.visitLabel(elseTarget);
	mv.visitInsn(POP);
	this.children[1].generateCode(mv, cf);
	if (!CodeFlow.isPrimitive(this.exitTypeDescriptor)) {
		CodeFlow.insertBoxIfNecessary(mv, cf.lastDescriptor().charAt(0));
	}
	mv.visitLabel(endOfIf);
	cf.pushDescriptor(this.exitTypeDescriptor);
}
 
Example 6
Source File: OpNE.java    From java-technology-stack with MIT License 5 votes vote down vote up
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
	cf.loadEvaluationContext(mv);
	String leftDesc = getLeftOperand().exitTypeDescriptor;
	String rightDesc = getRightOperand().exitTypeDescriptor;
	boolean leftPrim = CodeFlow.isPrimitive(leftDesc);
	boolean rightPrim = CodeFlow.isPrimitive(rightDesc);

	cf.enterCompilationScope();
	getLeftOperand().generateCode(mv, cf);
	cf.exitCompilationScope();
	if (leftPrim) {
		CodeFlow.insertBoxIfNecessary(mv, leftDesc.charAt(0));
	}
	cf.enterCompilationScope();
	getRightOperand().generateCode(mv, cf);
	cf.exitCompilationScope();
	if (rightPrim) {
		CodeFlow.insertBoxIfNecessary(mv, rightDesc.charAt(0));
	}

	String operatorClassName = Operator.class.getName().replace('.', '/');
	String evaluationContextClassName = EvaluationContext.class.getName().replace('.', '/');
	mv.visitMethodInsn(INVOKESTATIC, operatorClassName, "equalityCheck",
			"(L" + evaluationContextClassName + ";Ljava/lang/Object;Ljava/lang/Object;)Z", false);

	// Invert the boolean
	Label notZero = new Label();
	Label end = new Label();
	mv.visitJumpInsn(IFNE, notZero);
	mv.visitInsn(ICONST_1);
	mv.visitJumpInsn(GOTO, end);
	mv.visitLabel(notZero);
	mv.visitInsn(ICONST_0);
	mv.visitLabel(end);

	cf.pushDescriptor("Z");
}
 
Example 7
Source File: OpNE.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
	cf.loadEvaluationContext(mv);
	String leftDesc = getLeftOperand().exitTypeDescriptor;
	String rightDesc = getRightOperand().exitTypeDescriptor;
	boolean leftPrim = CodeFlow.isPrimitive(leftDesc);
	boolean rightPrim = CodeFlow.isPrimitive(rightDesc);

	cf.enterCompilationScope();
	getLeftOperand().generateCode(mv, cf);
	cf.exitCompilationScope();
	if (leftPrim) {
		CodeFlow.insertBoxIfNecessary(mv, leftDesc.charAt(0));
	}
	cf.enterCompilationScope();
	getRightOperand().generateCode(mv, cf);
	cf.exitCompilationScope();
	if (rightPrim) {
		CodeFlow.insertBoxIfNecessary(mv, rightDesc.charAt(0));
	}

	String operatorClassName = Operator.class.getName().replace('.', '/');
	String evaluationContextClassName = EvaluationContext.class.getName().replace('.', '/');
	mv.visitMethodInsn(INVOKESTATIC, operatorClassName, "equalityCheck",
			"(L" + evaluationContextClassName + ";Ljava/lang/Object;Ljava/lang/Object;)Z", false);

	// Invert the boolean
	Label notZero = new Label();
	Label end = new Label();
	mv.visitJumpInsn(IFNE, notZero);
	mv.visitInsn(ICONST_1);
	mv.visitJumpInsn(GOTO, end);
	mv.visitLabel(notZero);
	mv.visitInsn(ICONST_0);
	mv.visitLabel(end);

	cf.pushDescriptor("Z");
}
 
Example 8
Source File: InlineList.java    From spring4-understanding with Apache License 2.0 5 votes vote down vote up
void generateClinitCode(String clazzname, String constantFieldName, MethodVisitor mv, CodeFlow codeflow, boolean nested) {
	mv.visitTypeInsn(NEW, "java/util/ArrayList");
	mv.visitInsn(DUP);
	mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V", false);
	if (!nested) {
		mv.visitFieldInsn(PUTSTATIC, clazzname, constantFieldName, "Ljava/util/List;");
	}
	int childcount = getChildCount();		
	for (int c=0; c < childcount; c++) {
		if (!nested) {
			mv.visitFieldInsn(GETSTATIC, clazzname, constantFieldName, "Ljava/util/List;");
		}
		else {
			mv.visitInsn(DUP);
		}
		// The children might be further lists if they are not constants. In this
		// situation do not call back into generateCode() because it will register another clinit adder.
		// Instead, directly build the list here:
		if (children[c] instanceof InlineList) {
			((InlineList)children[c]).generateClinitCode(clazzname, constantFieldName, mv, codeflow, true);
		}
		else {
			children[c].generateCode(mv, codeflow);
			if (CodeFlow.isPrimitive(codeflow.lastDescriptor())) {
				CodeFlow.insertBoxIfNecessary(mv, codeflow.lastDescriptor().charAt(0));
			}
		}
		mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true);
		mv.visitInsn(POP);
	}
}
 
Example 9
Source File: OpEQ.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
	cf.loadEvaluationContext(mv);
	String leftDesc = getLeftOperand().exitTypeDescriptor;
	String rightDesc = getRightOperand().exitTypeDescriptor;
	boolean leftPrim = CodeFlow.isPrimitive(leftDesc);
	boolean rightPrim = CodeFlow.isPrimitive(rightDesc);

	cf.enterCompilationScope();
	getLeftOperand().generateCode(mv, cf);
	cf.exitCompilationScope();
	if (leftPrim) {
		CodeFlow.insertBoxIfNecessary(mv, leftDesc.charAt(0));
	}
	cf.enterCompilationScope();
	getRightOperand().generateCode(mv, cf);
	cf.exitCompilationScope();
	if (rightPrim) {
		CodeFlow.insertBoxIfNecessary(mv, rightDesc.charAt(0));
	}

	String operatorClassName = Operator.class.getName().replace('.', '/');
	String evaluationContextClassName = EvaluationContext.class.getName().replace('.', '/');
	mv.visitMethodInsn(INVOKESTATIC, operatorClassName, "equalityCheck",
			"(L" + evaluationContextClassName + ";Ljava/lang/Object;Ljava/lang/Object;)Z", false);
	cf.pushDescriptor("Z");
}
 
Example 10
Source File: Ternary.java    From spring-analysis-note with MIT License 5 votes vote down vote up
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
	// May reach here without it computed if all elements are literals
	computeExitTypeDescriptor();
	cf.enterCompilationScope();
	this.children[0].generateCode(mv, cf);
	String lastDesc = cf.lastDescriptor();
	Assert.state(lastDesc != null, "No last descriptor");
	if (!CodeFlow.isPrimitive(lastDesc)) {
		CodeFlow.insertUnboxInsns(mv, 'Z', lastDesc);
	}
	cf.exitCompilationScope();
	Label elseTarget = new Label();
	Label endOfIf = new Label();
	mv.visitJumpInsn(IFEQ, elseTarget);
	cf.enterCompilationScope();
	this.children[1].generateCode(mv, cf);
	if (!CodeFlow.isPrimitive(this.exitTypeDescriptor)) {
		lastDesc = cf.lastDescriptor();
		Assert.state(lastDesc != null, "No last descriptor");
		CodeFlow.insertBoxIfNecessary(mv, lastDesc.charAt(0));
	}
	cf.exitCompilationScope();
	mv.visitJumpInsn(GOTO, endOfIf);
	mv.visitLabel(elseTarget);
	cf.enterCompilationScope();
	this.children[2].generateCode(mv, cf);
	if (!CodeFlow.isPrimitive(this.exitTypeDescriptor)) {
		lastDesc = cf.lastDescriptor();
		Assert.state(lastDesc != null, "No last descriptor");
		CodeFlow.insertBoxIfNecessary(mv, lastDesc.charAt(0));
	}
	cf.exitCompilationScope();
	mv.visitLabel(endOfIf);
	cf.pushDescriptor(this.exitTypeDescriptor);
}
 
Example 11
Source File: InlineList.java    From java-technology-stack with MIT License 5 votes vote down vote up
void generateClinitCode(String clazzname, String constantFieldName, MethodVisitor mv, CodeFlow codeflow, boolean nested) {
	mv.visitTypeInsn(NEW, "java/util/ArrayList");
	mv.visitInsn(DUP);
	mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V", false);
	if (!nested) {
		mv.visitFieldInsn(PUTSTATIC, clazzname, constantFieldName, "Ljava/util/List;");
	}
	int childCount = getChildCount();
	for (int c = 0; c < childCount; c++) {
		if (!nested) {
			mv.visitFieldInsn(GETSTATIC, clazzname, constantFieldName, "Ljava/util/List;");
		}
		else {
			mv.visitInsn(DUP);
		}
		// The children might be further lists if they are not constants. In this
		// situation do not call back into generateCode() because it will register another clinit adder.
		// Instead, directly build the list here:
		if (this.children[c] instanceof InlineList) {
			((InlineList)this.children[c]).generateClinitCode(clazzname, constantFieldName, mv, codeflow, true);
		}
		else {
			this.children[c].generateCode(mv, codeflow);
			String lastDesc = codeflow.lastDescriptor();
			if (CodeFlow.isPrimitive(lastDesc)) {
				CodeFlow.insertBoxIfNecessary(mv, lastDesc.charAt(0));
			}
		}
		mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true);
		mv.visitInsn(POP);
	}
}
 
Example 12
Source File: OperatorInstanceof.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
	getLeftOperand().generateCode(mv, cf);
	CodeFlow.insertBoxIfNecessary(mv, cf.lastDescriptor());
	if (this.type.isPrimitive()) {
		// always false - but left operand code always driven
		// in case it had side effects
		mv.visitInsn(POP);
		mv.visitInsn(ICONST_0); // value of false
	} 
	else {
		mv.visitTypeInsn(INSTANCEOF, Type.getInternalName(this.type));
	}
	cf.pushDescriptor(this.exitTypeDescriptor);
}
 
Example 13
Source File: Elvis.java    From spring-analysis-note with MIT License 5 votes vote down vote up
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
	// exit type descriptor can be null if both components are literal expressions
	computeExitTypeDescriptor();
	cf.enterCompilationScope();
	this.children[0].generateCode(mv, cf);
	String lastDesc = cf.lastDescriptor();
	Assert.state(lastDesc != null, "No last descriptor");
	CodeFlow.insertBoxIfNecessary(mv, lastDesc.charAt(0));
	cf.exitCompilationScope();
	Label elseTarget = new Label();
	Label endOfIf = new Label();
	mv.visitInsn(DUP);
	mv.visitJumpInsn(IFNULL, elseTarget);
	// Also check if empty string, as per the code in the interpreted version
	mv.visitInsn(DUP);
	mv.visitLdcInsn("");
	mv.visitInsn(SWAP);
	mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z",false);
	mv.visitJumpInsn(IFEQ, endOfIf);  // if not empty, drop through to elseTarget
	mv.visitLabel(elseTarget);
	mv.visitInsn(POP);
	cf.enterCompilationScope();
	this.children[1].generateCode(mv, cf);
	if (!CodeFlow.isPrimitive(this.exitTypeDescriptor)) {
		lastDesc = cf.lastDescriptor();
		Assert.state(lastDesc != null, "No last descriptor");
		CodeFlow.insertBoxIfNecessary(mv, lastDesc.charAt(0));
	}
	cf.exitCompilationScope();
	mv.visitLabel(endOfIf);
	cf.pushDescriptor(this.exitTypeDescriptor);
}
 
Example 14
Source File: OpEQ.java    From spring-analysis-note with MIT License 5 votes vote down vote up
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
	cf.loadEvaluationContext(mv);
	String leftDesc = getLeftOperand().exitTypeDescriptor;
	String rightDesc = getRightOperand().exitTypeDescriptor;
	boolean leftPrim = CodeFlow.isPrimitive(leftDesc);
	boolean rightPrim = CodeFlow.isPrimitive(rightDesc);

	cf.enterCompilationScope();
	getLeftOperand().generateCode(mv, cf);
	cf.exitCompilationScope();
	if (leftPrim) {
		CodeFlow.insertBoxIfNecessary(mv, leftDesc.charAt(0));
	}
	cf.enterCompilationScope();
	getRightOperand().generateCode(mv, cf);
	cf.exitCompilationScope();
	if (rightPrim) {
		CodeFlow.insertBoxIfNecessary(mv, rightDesc.charAt(0));
	}

	String operatorClassName = Operator.class.getName().replace('.', '/');
	String evaluationContextClassName = EvaluationContext.class.getName().replace('.', '/');
	mv.visitMethodInsn(INVOKESTATIC, operatorClassName, "equalityCheck",
			"(L" + evaluationContextClassName + ";Ljava/lang/Object;Ljava/lang/Object;)Z", false);
	cf.pushDescriptor("Z");
}
 
Example 15
Source File: InlineList.java    From spring-analysis-note with MIT License 5 votes vote down vote up
void generateClinitCode(String clazzname, String constantFieldName, MethodVisitor mv, CodeFlow codeflow, boolean nested) {
	mv.visitTypeInsn(NEW, "java/util/ArrayList");
	mv.visitInsn(DUP);
	mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V", false);
	if (!nested) {
		mv.visitFieldInsn(PUTSTATIC, clazzname, constantFieldName, "Ljava/util/List;");
	}
	int childCount = getChildCount();
	for (int c = 0; c < childCount; c++) {
		if (!nested) {
			mv.visitFieldInsn(GETSTATIC, clazzname, constantFieldName, "Ljava/util/List;");
		}
		else {
			mv.visitInsn(DUP);
		}
		// The children might be further lists if they are not constants. In this
		// situation do not call back into generateCode() because it will register another clinit adder.
		// Instead, directly build the list here:
		if (this.children[c] instanceof InlineList) {
			((InlineList)this.children[c]).generateClinitCode(clazzname, constantFieldName, mv, codeflow, true);
		}
		else {
			this.children[c].generateCode(mv, codeflow);
			String lastDesc = codeflow.lastDescriptor();
			if (CodeFlow.isPrimitive(lastDesc)) {
				CodeFlow.insertBoxIfNecessary(mv, lastDesc.charAt(0));
			}
		}
		mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true);
		mv.visitInsn(POP);
	}
}
 
Example 16
Source File: SpelCompiler.java    From spring4-understanding with Apache License 2.0 4 votes vote down vote up
/**
 * 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
 */
@SuppressWarnings("unchecked")
private Class<? extends CompiledExpression> createExpressionClass(SpelNodeImpl expressionToCompile) {
	// Create class outline 'spel/ExNNN extends org.springframework.expression.spel.CompiledExpression'
	String clazzName = "spel/Ex" + getNextSuffix();
	ClassWriter cw = new ExpressionClassWriter();
	cw.visit(V1_5, ACC_PUBLIC, clazzName, 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;Lorg/springframework/expression/EvaluationContext;)Ljava/lang/Object;", null,
			new String[ ]{"org/springframework/expression/EvaluationException"});
	mv.visitCode();

	CodeFlow cf = new CodeFlow(clazzName, 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);

	mv.visitMaxs(0, 0);  // not supplied due to COMPUTE_MAXS
	mv.visitEnd();
	cw.visitEnd();

	cf.finish();

	byte[] data = cw.toByteArray();
	// TODO need to make this conditionally occur based on a debug flag
	// dump(expressionToCompile.toStringAST(), clazzName, data);
	return (Class<? extends CompiledExpression>) this.ccl.defineClass(clazzName.replaceAll("/", "."), data);
}
 
Example 17
Source File: OpEQ.java    From spring4-understanding with Apache License 2.0 4 votes vote down vote up
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
	String leftDesc = getLeftOperand().exitTypeDescriptor;
	String rightDesc = getRightOperand().exitTypeDescriptor;
	Label elseTarget = new Label();
	Label endOfIf = new Label();
	boolean leftPrim = CodeFlow.isPrimitive(leftDesc);
	boolean rightPrim = CodeFlow.isPrimitive(rightDesc);

	DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc,
			this.leftActualDescriptor, this.rightActualDescriptor);
	
	if (dc.areNumbers && dc.areCompatible) {
		char targetType = dc.compatibleType;
		
		getLeftOperand().generateCode(mv, cf);
		if (!leftPrim) {
			CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
		}
	
		cf.enterCompilationScope();
		getRightOperand().generateCode(mv, cf);
		cf.exitCompilationScope();
		if (!rightPrim) {
			CodeFlow.insertUnboxInsns(mv, targetType, rightDesc);
		}
		// assert: SpelCompiler.boxingCompatible(leftDesc, rightDesc)
		if (targetType=='D') {
			mv.visitInsn(DCMPL);
			mv.visitJumpInsn(IFNE, elseTarget);
		}
		else if (targetType=='F') {
			mv.visitInsn(FCMPL);		
			mv.visitJumpInsn(IFNE, elseTarget);
		}
		else if (targetType=='J') {
			mv.visitInsn(LCMP);		
			mv.visitJumpInsn(IFNE, elseTarget);
		}
		else if (targetType=='I' || targetType=='Z') {
			mv.visitJumpInsn(IF_ICMPNE, elseTarget);		
		}
		else {
			throw new IllegalStateException("Unexpected descriptor "+leftDesc);
		}
	}
	else {
		getLeftOperand().generateCode(mv, cf);
		if (leftPrim) {
			CodeFlow.insertBoxIfNecessary(mv, leftDesc.charAt(0));
		}
		getRightOperand().generateCode(mv, cf);
		if (rightPrim) {
			CodeFlow.insertBoxIfNecessary(mv, rightDesc.charAt(0));
		}
		Label leftNotNull = new Label();
		mv.visitInsn(DUP_X1); // Dup right on the top of the stack
		mv.visitJumpInsn(IFNONNULL,leftNotNull);
		// Right is null!
		mv.visitInsn(SWAP);
		mv.visitInsn(POP); // remove it
		Label rightNotNull = new Label();
		mv.visitJumpInsn(IFNONNULL, rightNotNull);
		// Left is null too
		mv.visitInsn(ICONST_1);
		mv.visitJumpInsn(GOTO, endOfIf);
		mv.visitLabel(rightNotNull);
		mv.visitInsn(ICONST_0);
		mv.visitJumpInsn(GOTO,endOfIf);
		mv.visitLabel(leftNotNull);
		mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false);
		mv.visitLabel(endOfIf);
		cf.pushDescriptor("Z");
		return;
	}
	mv.visitInsn(ICONST_1);
	mv.visitJumpInsn(GOTO,endOfIf);
	mv.visitLabel(elseTarget);
	mv.visitInsn(ICONST_0);
	mv.visitLabel(endOfIf);
	cf.pushDescriptor("Z");
}
 
Example 18
Source File: SpelCompiler.java    From java-technology-stack with MIT License 4 votes vote down vote up
/**
 * 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();
	ClassWriter cw = new ExpressionClassWriter();
	cw.visit(V1_5, 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;Lorg/springframework/expression/EvaluationContext;)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);

	mv.visitMaxs(0, 0);  // not supplied due to COMPUTE_MAXS
	mv.visitEnd();
	cw.visitEnd();

	cf.finish();

	byte[] data = cw.toByteArray();
	// TODO need to make this conditionally occur based on a debug flag
	// dump(expressionToCompile.toStringAST(), clazzName, data);
	return loadClass(StringUtils.replace(className, "/", "."), data);
}
 
Example 19
Source File: SpelCompiler.java    From lams with GNU General Public License v2.0 4 votes vote down vote up
/**
 * 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
 */
@SuppressWarnings("unchecked")
private Class<? extends CompiledExpression> createExpressionClass(SpelNodeImpl expressionToCompile) {
	// Create class outline 'spel/ExNNN extends org.springframework.expression.spel.CompiledExpression'
	String clazzName = "spel/Ex" + getNextSuffix();
	ClassWriter cw = new ExpressionClassWriter();
	cw.visit(V1_5, ACC_PUBLIC, clazzName, 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;Lorg/springframework/expression/EvaluationContext;)Ljava/lang/Object;", null,
			new String[ ]{"org/springframework/expression/EvaluationException"});
	mv.visitCode();

	CodeFlow cf = new CodeFlow(clazzName, 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);

	mv.visitMaxs(0, 0);  // not supplied due to COMPUTE_MAXS
	mv.visitEnd();
	cw.visitEnd();

	cf.finish();

	byte[] data = cw.toByteArray();
	// TODO need to make this conditionally occur based on a debug flag
	// dump(expressionToCompile.toStringAST(), clazzName, data);
	return (Class<? extends CompiledExpression>) this.ccl.defineClass(clazzName.replaceAll("/", "."), data);
}
 
Example 20
Source File: MethodReference.java    From lams with GNU General Public License v2.0 4 votes vote down vote up
@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
	CachedMethodExecutor executorToCheck = this.cachedExecutor;
	if (executorToCheck == null || !(executorToCheck.get() instanceof ReflectiveMethodExecutor)) {
		throw new IllegalStateException("No applicable cached executor found: " + executorToCheck);
	}

	ReflectiveMethodExecutor methodExecutor = (ReflectiveMethodExecutor) executorToCheck.get();
	Method method = methodExecutor.getMethod();
	boolean isStaticMethod = Modifier.isStatic(method.getModifiers());
	String descriptor = cf.lastDescriptor();

	if (descriptor == null) {
		if (!isStaticMethod) {
			// Nothing on the stack but something is needed
			cf.loadTarget(mv);
		}
	}
	else {
		if (isStaticMethod) {
			// Something on the stack when nothing is needed
			mv.visitInsn(POP);
		}
	}
	
	if (CodeFlow.isPrimitive(descriptor)) {
		CodeFlow.insertBoxIfNecessary(mv, descriptor.charAt(0));
	}

	String classDesc = (Modifier.isPublic(method.getDeclaringClass().getModifiers()) ?
			method.getDeclaringClass().getName().replace('.', '/') :
			methodExecutor.getPublicDeclaringClass().getName().replace('.', '/'));
	if (!isStaticMethod) {
		if (descriptor == null || !descriptor.substring(1).equals(classDesc)) {
			CodeFlow.insertCheckCast(mv, "L" + classDesc);
		}
	}

	generateCodeForArguments(mv, cf, method, this.children);
	mv.visitMethodInsn((isStaticMethod ? INVOKESTATIC : INVOKEVIRTUAL), classDesc, method.getName(),
			CodeFlow.createSignatureDescriptor(method), method.getDeclaringClass().isInterface());
	cf.pushDescriptor(this.exitTypeDescriptor);
}