/** * Visits a method instruction. A method instruction is an instruction that invokes a method. * * @param opcode the opcode of the type instruction to be visited. This opcode is either * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE. * @param owner the internal name of the method's owner class (see {@link * Type#getInternalName()}). * @param name the method's name. * @param descriptor the method's descriptor (see {@link Type}). * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead. */ @Deprecated public void visitMethodInsn( final int opcode, final String owner, final String name, final String descriptor) { if (api >= Opcodes.ASM5) { boolean isInterface = opcode == Opcodes.INVOKEINTERFACE; visitMethodInsn(opcode, owner, name, descriptor, isInterface); return; } if (mv != null) { mv.visitMethodInsn(opcode, owner, name, descriptor); } }
switch (ch) { case 'Z': mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); break; case 'B': mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); break; case 'C': mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false); break; case 'D': mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); break; case 'F': mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); break; case 'I': mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); break; case 'J': mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); break; case 'S': mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); break; case 'L':
/** * Visits a method instruction. A method instruction is an instruction that invokes a method. * * @param opcode the opcode of the type instruction to be visited. This opcode is either * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE. * @param owner the internal name of the method's owner class (see {@link * Type#getInternalName()}). * @param name the method's name. * @param descriptor the method's descriptor (see {@link Type}). * @param isInterface if the method's owner class is an interface. */ public void visitMethodInsn( final int opcode, final String owner, final String name, final String descriptor, final boolean isInterface) { if (api < Opcodes.ASM5) { if (isInterface != (opcode == Opcodes.INVOKEINTERFACE)) { throw new IllegalArgumentException("INVOKESPECIAL/STATIC on interfaces requires ASM5"); } visitMethodInsn(opcode, owner, name, descriptor); return; } if (mv != null) { mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface); } }
/** * If the codeflow shows the last expression evaluated to java.lang.Boolean then * insert the necessary instructions to unbox that to a boolean primitive. * @param mv the visitor into which new instructions should be inserted */ public void unboxBooleanIfNecessary(MethodVisitor mv) { if ("Ljava/lang/Boolean".equals(lastDescriptor())) { mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false); } }
@Override public void generateCode(MethodVisitor mv, CodeFlow cf) { Method method = this.method; Assert.state(method != null, "No method handle"); String classDesc = method.getDeclaringClass().getName().replace('.', '/'); generateCodeForArguments(mv, cf, method, this.children); mv.visitMethodInsn(INVOKESTATIC, classDesc, method.getName(), CodeFlow.createSignatureDescriptor(method), false); cf.pushDescriptor(this.exitTypeDescriptor); }
mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "doubleValue", "()D", false); break; case 'F': mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "floatValue", "()F", false); break; case 'J': mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "longValue", "()J", false); break; case 'I': mv.visitTypeInsn(CHECKCAST, "java/lang/Number"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Number", "intValue", "()I", false); break;
@Override public void generateCode(MethodVisitor mv, CodeFlow cf) { ReflectiveConstructorExecutor executor = ((ReflectiveConstructorExecutor) this.cachedExecutor); Assert.state(executor != null, "No cached executor"); Constructor<?> constructor = executor.getConstructor(); String classDesc = constructor.getDeclaringClass().getName().replace('.', '/'); mv.visitTypeInsn(NEW, classDesc); mv.visitInsn(DUP); // children[0] is the type of the constructor, don't want to include that in argument processing SpelNodeImpl[] arguments = new SpelNodeImpl[this.children.length - 1]; System.arraycopy(this.children, 1, arguments, 0, this.children.length - 1); generateCodeForArguments(mv, cf, constructor, arguments); mv.visitMethodInsn(INVOKESPECIAL, classDesc, "<init>", CodeFlow.createSignatureDescriptor(constructor), false); cf.pushDescriptor(this.exitTypeDescriptor); }
@Override public void generateCode(String propertyName, MethodVisitor mv, CodeFlow cf) { String descriptor = cf.lastDescriptor(); if (descriptor == null || !descriptor.equals("Ljava/util/Map")) { if (descriptor == null) { cf.loadTarget(mv); } CodeFlow.insertCheckCast(mv, "Ljava/util/Map"); } mv.visitLdcInsn(propertyName); mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get","(Ljava/lang/Object;)Ljava/lang/Object;",true); }
@Override public void generateCode(String propertyName, MethodVisitor mv, CodeFlow cf) { boolean isStatic = Modifier.isStatic(this.member.getModifiers()); String descriptor = cf.lastDescriptor(); String classDesc = this.member.getDeclaringClass().getName().replace('.', '/'); if (!isStatic) { if (descriptor == null) { cf.loadTarget(mv); } if (descriptor == null || !classDesc.equals(descriptor.substring(1))) { mv.visitTypeInsn(CHECKCAST, classDesc); } } else { if (descriptor != null) { // A static field/method call will not consume what is on the stack, // it needs to be popped off. mv.visitInsn(POP); } } if (this.member instanceof Method) { mv.visitMethodInsn((isStatic ? INVOKESTATIC : INVOKEVIRTUAL), classDesc, this.member.getName(), CodeFlow.createSignatureDescriptor((Method) this.member), false); } else { mv.visitFieldInsn((isStatic ? GETSTATIC : GETFIELD), classDesc, this.member.getName(), CodeFlow.toJvmDescriptor(((Field) this.member).getType())); } } }
@Override public void generateCode(MethodVisitor mv, CodeFlow cf) { if (this.name.equals(ROOT)) { mv.visitVarInsn(ALOAD,1); } else { mv.visitVarInsn(ALOAD, 2); mv.visitLdcInsn(this.name); mv.visitMethodInsn(INVOKEINTERFACE, "org/springframework/expression/EvaluationContext", "lookupVariable", "(Ljava/lang/String;)Ljava/lang/Object;",true); } CodeFlow.insertCheckCast(mv, this.exitTypeDescriptor); cf.pushDescriptor(this.exitTypeDescriptor); }
@Override public void generateCode(String propertyName, MethodVisitor mv, CodeFlow cf) { String descriptor = cf.lastDescriptor(); if (descriptor == null || !descriptor.equals("Ljava/util/Map")) { if (descriptor == null) { cf.loadTarget(mv); } CodeFlow.insertCheckCast(mv, "Ljava/util/Map"); } mv.visitLdcInsn(propertyName); mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get","(Ljava/lang/Object;)Ljava/lang/Object;",true); }
/** * Walk through a possible tree of nodes that combine strings and append * them all to the same (on stack) StringBuilder. */ private void walk(MethodVisitor mv, CodeFlow cf, @Nullable SpelNodeImpl operand) { if (operand instanceof OpPlus) { OpPlus plus = (OpPlus)operand; walk(mv, cf, plus.getLeftOperand()); walk(mv, cf, plus.getRightOperand()); } else if (operand != null) { cf.enterCompilationScope(); operand.generateCode(mv,cf); if (!"Ljava/lang/String".equals(cf.lastDescriptor())) { mv.visitTypeInsn(CHECKCAST, "java/lang/String"); } cf.exitCompilationScope(); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); } }
@Override public void generateCode(String propertyName, MethodVisitor mv, CodeFlow cf) { if (method == null) { try { method = Payload2.class.getDeclaredMethod("getField", String.class); } catch (Exception ex) { } } String descriptor = cf.lastDescriptor(); String memberDeclaringClassSlashedDescriptor = method.getDeclaringClass().getName().replace('.','/'); if (descriptor == null) { cf.loadTarget(mv); } if (descriptor == null || !memberDeclaringClassSlashedDescriptor.equals(descriptor.substring(1))) { mv.visitTypeInsn(CHECKCAST, memberDeclaringClassSlashedDescriptor); } mv.visitLdcInsn(propertyName); mv.visitMethodInsn(INVOKEVIRTUAL, memberDeclaringClassSlashedDescriptor, method.getName(), CodeFlow.createSignatureDescriptor(method), false); } }
@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"); }
@Override public void generateCode(String propertyName, MethodVisitor mv, CodeFlow cf) { String descriptor = cf.lastDescriptor(); if (descriptor == null) { cf.loadTarget(mv); } mv.visitLdcInsn(propertyName); mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get","(Ljava/lang/Object;)Ljava/lang/Object;",true); } }
mv.visitTypeInsn(NEW, "java/lang/StringBuilder"); mv.visitInsn(DUP); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V", false); walk(mv, cf, getLeftOperand()); walk(mv, cf, getRightOperand()); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
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;"); mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true); mv.visitInsn(POP);
mv.visitMethodInsn(INVOKESTATIC, operatorClassName, "equalityCheck", "(L" + evaluationContextClassName + ";Ljava/lang/Object;Ljava/lang/Object;)Z", false);
mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "org/springframework/expression/spel/CompiledExpression", "<init>", "()V", false); mv.visitInsn(RETURN);
mv.visitLdcInsn(""); mv.visitInsn(SWAP); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z",false);