List of usage examples for org.objectweb.asm Opcodes SWAP
int SWAP
To view the source code for org.objectweb.asm Opcodes SWAP.
Click Source Link
From source file:org.hua.ast.visitors.BytecodeGeneratorASTVisitor.java
/** * Assumes top of stack contains two strings *//* www.ja v a2 s .c o m*/ private void handleStringOperator(ASTNode node, Operator op) throws ASTVisitorException { if (op.equals(Operator.PLUS)) { mn.instructions.add(new TypeInsnNode(Opcodes.NEW, "java/lang/StringBuilder")); mn.instructions.add(new InsnNode(Opcodes.DUP)); mn.instructions.add( new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V", false)); mn.instructions.add(new InsnNode(Opcodes.SWAP)); mn.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false)); mn.instructions.add(new InsnNode(Opcodes.SWAP)); mn.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false)); mn.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false)); } else if (op.isRelational()) { LabelNode trueLabelNode = new LabelNode(); switch (op) { case EQUAL: mn.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false)); mn.instructions.add(new JumpInsnNode(Opcodes.IFNE, trueLabelNode)); break; case NOT_EQUAL: mn.instructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false)); mn.instructions.add(new JumpInsnNode(Opcodes.IFEQ, trueLabelNode)); break; default: ASTUtils.error(node, "Operator not supported on strings"); break; } mn.instructions.add(new InsnNode(Opcodes.ICONST_0)); LabelNode endLabelNode = new LabelNode(); mn.instructions.add(new JumpInsnNode(Opcodes.GOTO, endLabelNode)); mn.instructions.add(trueLabelNode); mn.instructions.add(new InsnNode(Opcodes.ICONST_1)); mn.instructions.add(endLabelNode); } else { ASTUtils.error(node, "Operator not recognized"); } }
From source file:org.hua.ast.visitors.BytecodeGeneratorASTVisitor.java
@Override public void visit(BinaryExpression node) throws ASTVisitorException { node.getExpression1().accept(this); Type expr1Type = ASTUtils.getSafeType(node.getExpression1()); node.getExpression2().accept(this); Type expr2Type = ASTUtils.getSafeType(node.getExpression2()); Type maxType = TypeUtils.maxType(expr1Type, expr2Type); // cast top of stack to max if (!maxType.equals(expr2Type)) { widen(maxType, expr2Type); }/*from w ww .ja v a 2s. co m*/ System.out.println("^^^^^^^^^^^^^^^^^^^ binary op: " + node.getOperator()); System.out.println(" type1: " + expr1Type + " type2: " + expr2Type); System.out.println(" max type: " + !maxType.equals(expr1Type)); // cast second from top to max if (!maxType.equals(expr1Type)) { System.out.println("not to be dispalyed"); LocalIndexPool lip = ASTUtils.getSafeLocalIndexPool(node); int localIndex = -1; if (expr2Type.equals(Type.DOUBLE_TYPE) || expr1Type.equals(Type.DOUBLE_TYPE)) { localIndex = lip.getLocalIndex(expr2Type); mn.instructions.add(new VarInsnNode(expr2Type.getOpcode(Opcodes.ISTORE), localIndex)); } else { mn.instructions.add(new InsnNode(Opcodes.SWAP)); } widen(maxType, expr1Type); if (expr2Type.equals(Type.DOUBLE_TYPE) || expr1Type.equals(Type.DOUBLE_TYPE)) { mn.instructions.add(new VarInsnNode(expr2Type.getOpcode(Opcodes.ILOAD), localIndex)); lip.freeLocalIndex(localIndex, expr2Type); } else { mn.instructions.add(new InsnNode(Opcodes.SWAP)); } } // if (ASTUtils.isBooleanExpression(node)) { handleBooleanOperator(node, node.getOperator(), maxType); } else if (maxType.equals(TypeUtils.STRING_TYPE)) { mn.instructions.add(new InsnNode(Opcodes.SWAP)); handleStringOperator(node, node.getOperator()); } else { handleNumberOperator(node, node.getOperator(), maxType); } }
From source file:org.jacoco.core.internal.instr.FrameTracker.java
License:Open Source License
@Override public void visitInsn(final int opcode) { final Object t1, t2, t3, t4; switch (opcode) { case Opcodes.NOP: case Opcodes.RETURN: break;//from ww w . j a v a2 s.c om case Opcodes.ARETURN: case Opcodes.ATHROW: case Opcodes.FRETURN: case Opcodes.IRETURN: case Opcodes.MONITORENTER: case Opcodes.MONITOREXIT: case Opcodes.POP: pop(1); break; case Opcodes.DRETURN: case Opcodes.LRETURN: case Opcodes.POP2: pop(2); break; case Opcodes.AASTORE: case Opcodes.BASTORE: case Opcodes.CASTORE: case Opcodes.FASTORE: case Opcodes.IASTORE: case Opcodes.SASTORE: pop(3); break; case Opcodes.LASTORE: case Opcodes.DASTORE: pop(4); break; case Opcodes.ICONST_M1: case Opcodes.ICONST_0: case Opcodes.ICONST_1: case Opcodes.ICONST_2: case Opcodes.ICONST_3: case Opcodes.ICONST_4: case Opcodes.ICONST_5: push(Opcodes.INTEGER); break; case Opcodes.ARRAYLENGTH: case Opcodes.F2I: case Opcodes.I2B: case Opcodes.I2C: case Opcodes.I2S: case Opcodes.INEG: pop(1); push(Opcodes.INTEGER); break; case Opcodes.BALOAD: case Opcodes.CALOAD: case Opcodes.D2I: case Opcodes.FCMPG: case Opcodes.FCMPL: case Opcodes.IADD: case Opcodes.IALOAD: case Opcodes.IAND: case Opcodes.IDIV: case Opcodes.IMUL: case Opcodes.IOR: case Opcodes.IREM: case Opcodes.ISHL: case Opcodes.ISHR: case Opcodes.ISUB: case Opcodes.IUSHR: case Opcodes.IXOR: case Opcodes.L2I: case Opcodes.SALOAD: pop(2); push(Opcodes.INTEGER); break; case Opcodes.DCMPG: case Opcodes.DCMPL: case Opcodes.LCMP: pop(4); push(Opcodes.INTEGER); break; case Opcodes.FCONST_0: case Opcodes.FCONST_1: case Opcodes.FCONST_2: push(Opcodes.FLOAT); break; case Opcodes.FNEG: case Opcodes.I2F: pop(1); push(Opcodes.FLOAT); break; case Opcodes.D2F: case Opcodes.FADD: case Opcodes.FALOAD: case Opcodes.FDIV: case Opcodes.FMUL: case Opcodes.FREM: case Opcodes.FSUB: case Opcodes.L2F: pop(2); push(Opcodes.FLOAT); break; case Opcodes.LCONST_0: case Opcodes.LCONST_1: push(Opcodes.LONG); push(Opcodes.TOP); break; case Opcodes.F2L: case Opcodes.I2L: pop(1); push(Opcodes.LONG); push(Opcodes.TOP); break; case Opcodes.D2L: case Opcodes.LALOAD: case Opcodes.LNEG: pop(2); push(Opcodes.LONG); push(Opcodes.TOP); break; case Opcodes.LSHL: case Opcodes.LSHR: case Opcodes.LUSHR: pop(3); push(Opcodes.LONG); push(Opcodes.TOP); break; case Opcodes.LADD: case Opcodes.LAND: case Opcodes.LDIV: case Opcodes.LMUL: case Opcodes.LOR: case Opcodes.LREM: case Opcodes.LSUB: case Opcodes.LXOR: pop(4); push(Opcodes.LONG); push(Opcodes.TOP); break; case Opcodes.DCONST_0: case Opcodes.DCONST_1: push(Opcodes.DOUBLE); push(Opcodes.TOP); break; case Opcodes.F2D: case Opcodes.I2D: pop(1); push(Opcodes.DOUBLE); push(Opcodes.TOP); break; case Opcodes.DALOAD: case Opcodes.DNEG: case Opcodes.L2D: pop(2); push(Opcodes.DOUBLE); push(Opcodes.TOP); break; case Opcodes.DADD: case Opcodes.DDIV: case Opcodes.DMUL: case Opcodes.DREM: case Opcodes.DSUB: pop(4); push(Opcodes.DOUBLE); push(Opcodes.TOP); break; case Opcodes.ACONST_NULL: push(Opcodes.NULL); break; case Opcodes.AALOAD: pop(1); t1 = pop(); push(Type.getType(((String) t1).substring(1))); break; case Opcodes.DUP: t1 = pop(); push(t1); push(t1); break; case Opcodes.DUP_X1: t1 = pop(); t2 = pop(); push(t1); push(t2); push(t1); break; case Opcodes.DUP_X2: t1 = pop(); t2 = pop(); t3 = pop(); push(t1); push(t3); push(t2); push(t1); break; case Opcodes.DUP2: t1 = pop(); t2 = pop(); push(t2); push(t1); push(t2); push(t1); break; case Opcodes.DUP2_X1: t1 = pop(); t2 = pop(); t3 = pop(); push(t2); push(t1); push(t3); push(t2); push(t1); break; case Opcodes.DUP2_X2: t1 = pop(); t2 = pop(); t3 = pop(); t4 = pop(); push(t2); push(t1); push(t4); push(t3); push(t2); push(t1); break; case Opcodes.SWAP: t1 = pop(); t2 = pop(); push(t1); push(t2); break; default: throw new IllegalArgumentException(); } mv.visitInsn(opcode); }
From source file:org.jacoco.core.runtime.LoggerRuntime.java
License:Open Source License
public int generateDataAccessor(final long classid, final String classname, final int probecount, final MethodVisitor mv) { // The data accessor performs the following steps: ////from www. j av a 2 s. c om // final Object[] args = new Object[3]; // args[0] = Long.valueOf(classid); // args[1] = classname; // args[2] = Integer.valueOf(probecount); // Logger.getLogger(CHANNEL).log(Level.INFO, key, args); // final byte[] probedata = (byte[]) args[0]; // // Note that local variable 'args' is used at two places. As were not // allowed to allocate local variables we have to keep this value with // DUP and SWAP operations on the operand stack. // 1. Create parameter array: RuntimeData.generateArgumentArray(classid, classname, probecount, mv); // Stack[0]: [Ljava/lang/Object; mv.visitInsn(Opcodes.DUP); // Stack[1]: [Ljava/lang/Object; // Stack[0]: [Ljava/lang/Object; // 2. Call Logger: mv.visitLdcInsn(CHANNEL); mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/util/logging/Logger", "getLogger", "(Ljava/lang/String;)Ljava/util/logging/Logger;"); // Stack[2]: Ljava/util/logging/Logger; // Stack[1]: [Ljava/lang/Object; // Stack[0]: [Ljava/lang/Object; mv.visitInsn(Opcodes.SWAP); // Stack[2]: [Ljava/lang/Object; // Stack[1]: Ljava/util/logging/Logger; // Stack[0]: [Ljava/lang/Object; mv.visitFieldInsn(Opcodes.GETSTATIC, "java/util/logging/Level", "INFO", "Ljava/util/logging/Level;"); // Stack[3]: Ljava/util/logging/Level; // Stack[2]: [Ljava/lang/Object; // Stack[1]: Ljava/util/logging/Logger; // Stack[0]: [Ljava/lang/Object; mv.visitInsn(Opcodes.SWAP); // Stack[3]: [Ljava/lang/Object; // Stack[2]: Ljava/util/logging/Level; // Stack[1]: Ljava/util/logging/Logger; // Stack[0]: [Ljava/lang/Object; mv.visitLdcInsn(key); // Stack[4]: Ljava/lang/String; // Stack[3]: [Ljava/lang/Object; // Stack[2]: Ljava/util/logging/Level; // Stack[1]: Ljava/util/logging/Logger; // Stack[0]: [Ljava/lang/Object; mv.visitInsn(Opcodes.SWAP); // Stack[4]: [Ljava/lang/Object; // Stack[3]: Ljava/lang/String; // Stack[2]: Ljava/util/logging/Level; // Stack[1]: Ljava/util/logging/Logger; // Stack[0]: [Ljava/lang/Object; mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/logging/Logger", "log", "(Ljava/util/logging/Level;Ljava/lang/String;[Ljava/lang/Object;)V"); // Stack[0]: [Ljava/lang/Object; // 3. Load data structure from parameter array: mv.visitInsn(Opcodes.ICONST_0); mv.visitInsn(Opcodes.AALOAD); mv.visitTypeInsn(Opcodes.CHECKCAST, InstrSupport.DATAFIELD_DESC); // Stack[0]: [Z return 5; // Maximum local stack size is 5 }
From source file:org.jacoco.core.runtime.URLStreamHandlerRuntime.java
License:Open Source License
public int generateDataAccessor(final long classid, final String classname, final int probecount, final MethodVisitor mv) { // The data accessor performs the following steps: ///* w w w . jav a 2 s. c o m*/ // final URL url = new URL(protocol, null, ""); // final URLConnection connection = url.openConnection(); // final Object[] args = new Object[3]; // args[0] = Long.valueOf(classid); // args[1] = classname; // args[2] = Integer.valueOf(probecount); // connection.equals(args); // final byte[] probedata = (byte[]) args[0]; RuntimeData.generateArgumentArray(classid, classname, probecount, mv); mv.visitInsn(Opcodes.DUP); // Stack[1]: [Ljava/lang/Object; // Stack[0]: [Ljava/lang/Object; mv.visitTypeInsn(Opcodes.NEW, "java/net/URL"); mv.visitInsn(Opcodes.DUP); mv.visitLdcInsn(protocol); mv.visitInsn(Opcodes.ACONST_NULL); mv.visitLdcInsn(""); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/net/URL", "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); // Stack[2]: [Ljava/net/URL; // Stack[1]: [Ljava/lang/Object; // Stack[0]: [Ljava/lang/Object; mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/net/URL", "openConnection", "()Ljava/net/URLConnection;"); // Stack[2]: [Ljava/net/URLConnection; // Stack[1]: [Ljava/lang/Object; // Stack[0]: [Ljava/lang/Object; mv.visitInsn(Opcodes.SWAP); // Stack[2]: [Ljava/lang/Object; // Stack[1]: [Ljava/net/URLConnection; // Stack[0]: [Ljava/lang/Object; mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z"); // Stack[1]: Z; // Stack[0]: [Ljava/lang/Object; mv.visitInsn(Opcodes.POP); // Stack[0]: [Ljava/lang/Object; mv.visitInsn(Opcodes.ICONST_0); mv.visitInsn(Opcodes.AALOAD); mv.visitTypeInsn(Opcodes.CHECKCAST, InstrSupport.DATAFIELD_DESC); return 7; }
From source file:org.jboss.arquillian.extension.jacoco.container.ArquillianRuntime.java
License:Apache License
public int generateDataAccessor(long classid, String classname, int probecount, MethodVisitor mv) { // 1. Create parameter array: generateArgumentArray(classid, classname, probecount, mv); // stack[0]: [Ljava/lang/Object; mv.visitInsn(Opcodes.DUP);/*from w ww.j a v a2 s . c o m*/ // stack[1]: [Ljava/lang/Object; // stack[0]: [Ljava/lang/Object; // 2. Invoke ArquillianRuntime: mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jboss/arquillian/extension/jacoco/container/ArquillianRuntime", "getInstance", "()Lorg/jboss/arquillian/extension/jacoco/container/ArquillianRuntime;"); // stack[2]: LArquillianRuntime; // stack[1]: [Ljava/lang/Object; // stack[0]: [Ljava/lang/Object; mv.visitInsn(Opcodes.SWAP); // stack[2]: [Ljava/lang/Object; // stack[1]: LArquillianRuntime; // stack[0]: [Ljava/lang/Object; // 3. Invoke ArquillianRuntime swapExecutionData, gets the boolean[] in Object[0]: mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/jboss/arquillian/extension/jacoco/container/ArquillianRuntime", "swapExecutionData", "([Ljava/lang/Object;)V"); // Stack[0]: [Ljava/lang/Object; mv.visitInsn(Opcodes.ICONST_0); mv.visitInsn(Opcodes.AALOAD); mv.visitTypeInsn(Opcodes.CHECKCAST, InstrSupport.DATAFIELD_DESC); // Stack[0]: [Z; return 5; }
From source file:org.jboss.byteman.agent.adapter.RuleGeneratorAdapter.java
License:Open Source License
/** * Generates a SWAP instruction. */ public void swap() { visitInsn(Opcodes.SWAP); }
From source file:org.jboss.byteman.agent.adapter.RuleTriggerMethodAdapter.java
License:Open Source License
/** * plant code to copy back any updated values from the argument array to the relevant local variable slots *///from w w w . ja va2 s .c o m private void doArgUpdate() { // at entry the top of the stack contains the object array // for an AT EXIT rule the entry below this is the return value Type objectType = Type.getType(Object.class); int arraySize = callArrayBindings.size(); int lastUpdated = -1; int returnIdx = -1; // identify which is the last index we will need to update. n.b. if we find a return value we will // update that last for (int i = 0; i < arraySize; i++) { Binding binding = callArrayBindings.get(i); if (binding.isUpdated()) { lastUpdated = i; if (binding.isReturn()) { returnIdx = i; } } } // if the return value is updated it gets done last if (returnIdx >= 0) { lastUpdated = returnIdx; } // write back all other args then stack new return value and drop old one for (int i = 0; i < arraySize; i++) { Binding binding = callArrayBindings.get(i); if (binding.isUpdated() && !binding.isReturn()) { // if this is the last update then we consume the arguments array // otherwise we need to copy it if (i != lastUpdated) { dup(); } push(i); arrayLoad(objectType); if (binding.isParam()) { int idx = binding.getIndex() - 1; unbox(argumentTypes[idx]); storeArg(idx); } else if (binding.isLocalVar()) { int idx = binding.getLocalIndex(); unbox(getLocalType(idx)); storeLocal(idx); } } } // if we had a return value to process then the args array will still be on top of the stack above // the old return value if (returnIdx >= 0) { // get rid of old return value remembering to use the correct type for $! // which varies depending if this is an AT EXIT or AFTER CALL rule if (saveValueType.getSize() == 2) { mv.visitInsn(Opcodes.DUP_X2); mv.visitInsn(Opcodes.POP); mv.visitInsn(Opcodes.POP2); } else { mv.visitInsn(Opcodes.SWAP); mv.visitInsn(Opcodes.POP); } push(returnIdx); arrayLoad(objectType); // use the correct type for $! which varies depending if this is an AT EXIT or AFTER CALL rule unbox(saveValueType); } }
From source file:org.jboss.byteman.rule.expression.ArrayExpression.java
License:Open Source License
@Override public void compileAssign(MethodVisitor mv, CompileContext compileContext) throws CompileException { // make sure we are at the right source line compileContext.notifySourceLine(line); Type valueType = arrayRef.getType().getBaseType(); int currentStack = compileContext.getStackCount(); boolean isTwoWords = (valueType.getNBytes() > 4); int toPop = 0; int size = (isTwoWords ? 2 : 1); // value to be assigned is TOS and will already be coerced to the correct value type // copy it so we can install the copy and leave the original as a a return value on the stack if (isTwoWords) { // [... val1 val2 ==> ... val1 val2 val1 val2] mv.visitInsn(Opcodes.DUP2);// w w w. j av a2 s . c om } else { // [... val ==> ... val val] mv.visitInsn(Opcodes.DUP); } compileContext.addStackCount(size); // compile load of array reference -- adds 1 to stack height arrayRef.compile(mv, compileContext); // for each index expression compile the expression and the do an array load Iterator<Expression> iterator = idxList.iterator(); while (iterator.hasNext()) { Expression idxExpr = iterator.next(); if (iterator.hasNext()) { // dereference the array to get an embedded array // compile expression index -- adds 1 to height idxExpr.compile(mv, compileContext); // make sure the index is an integer compileTypeConversion(idxExpr.getType(), Type.I, mv, compileContext); // fetch embedded array pop 2 and add 1 mv.visitInsn(Opcodes.AALOAD); compileContext.addStackCount(-1); valueType = valueType.getBaseType(); } else { if (isTwoWords) { // stack is [..., val1, val2, val1, val2, aref ] and we want [..., val1, val2, aref, val1, val2 ] mv.visitInsn(Opcodes.DUP_X2); // ==> [..., val1, val2, aref. val1, val2, aref ] compileContext.addStackCount(1); mv.visitInsn(Opcodes.POP); // ==> [..., val1, val2, aref. val1, val2 ] compileContext.addStackCount(-1); } else { // stack is [..., val, val, aref ] and we want [..., val, aref, val ] mv.visitInsn(Opcodes.SWAP); } // compile expression index -- adds 1 to height idxExpr.compile(mv, compileContext); // make sure the index is an integer compileTypeConversion(idxExpr.getType(), Type.I, mv, compileContext); if (isTwoWords) { // stack is [..., val1, val2, aref, val1, val2, idx] and we want [..., val1, val2, aref, idx, val1, val2 ] mv.visitInsn(Opcodes.DUP_X2); // ==> [..., val1, val2, aref, idx, val1, val2, idx] compileContext.addStackCount(1); mv.visitInsn(Opcodes.POP); // ==> [..., val1, val2, aref, idx, val1, val2 ] compileContext.addStackCount(-1); } else { // stack is [..., val, aref, val, idx] and we want [..., val, aref, idx, val ] mv.visitInsn(Opcodes.SWAP); } // now we can do the array store if (valueType.isObject() || valueType.isArray()) { // compile load object - pops 3 mv.visitInsn(Opcodes.AASTORE); toPop = -3; } else if (valueType == Type.Z || valueType == Type.B) { // compile load byte - pops 3 mv.visitInsn(Opcodes.BASTORE); toPop = -3; } else if (valueType == Type.S) { // compile load short - pops 3 mv.visitInsn(Opcodes.SASTORE); toPop = -3; } else if (valueType == Type.C) { // compile load char - pops 3 mv.visitInsn(Opcodes.CASTORE); toPop = -3; } else if (valueType == Type.I) { // compile load int - pops 3 mv.visitInsn(Opcodes.IASTORE); toPop = -3; } else if (valueType == Type.J) { // compile load long - pops 4 mv.visitInsn(Opcodes.LASTORE); toPop = -4; } else if (valueType == Type.F) { // compile load float - pops 3 mv.visitInsn(Opcodes.FASTORE); toPop = -3; } else if (valueType == Type.D) { // compile load double - pops 4 mv.visitInsn(Opcodes.DASTORE); toPop = -4; } compileContext.addStackCount(toPop); if (iterator.hasNext()) { assert valueType.isArray(); valueType = valueType.getBaseType(); } } } // check stack height if (compileContext.getStackCount() != currentStack) { throw new CompileException("ArrayExpression.compile : invalid stack height " + compileContext.getStackCount() + " expecting " + currentStack); } // we needed room for an aray and an index or for a one or two word result // but the recursive evaluations will have made sure the max stack is big enough // so there is no need to update the maximum stack height }
From source file:org.jboss.byteman.rule.expression.DollarExpression.java
License:Open Source License
@Override public void compileAssign(MethodVisitor mv, CompileContext compileContext) throws CompileException { // make sure we are at the right source line compileContext.notifySourceLine(line); String targetName = binding.getName(); int currentStack = compileContext.getStackCount(); int size = ((type.getNBytes() > 4) ? 2 : 1); if (index == HELPER_IDX) { // not allowed to reassign the helper binding throw new CompileException("DollarExpression.compileAssign : invalid assignment to helper binding $$"); } else {//w ww . j a v a 2s .c om // value to be assigned is TOS and will already be coerced to the correct value type // copy it so we leave it as a a return value on the stack if (size == 2) { mv.visitInsn(Opcodes.DUP2); } else { mv.visitInsn(Opcodes.DUP); } // stack the current helper then insert it below the value mv.visitVarInsn(Opcodes.ALOAD, 0); if (size == 2) { // use a DUP_X2 to push a copy below the value then pop the redundant value mv.visitInsn(Opcodes.DUP_X2); mv.visitInsn(Opcodes.POP); } else { // we can just swap the two values mv.visitInsn(Opcodes.SWAP); } // stack the name for the variable and swap below the value mv.visitLdcInsn(targetName); if (size == 2) { // use a DUP_X2 to push a copy below the value then pop the redundant value mv.visitInsn(Opcodes.DUP_X2); // this is the high water mark // at this point the stack has gone from [ .. val1 val2] to [.. val1 val2 helper name val1 val2 name] compileContext.addStackCount(5); mv.visitInsn(Opcodes.POP); compileContext.addStackCount(-1); } else { // this is the high water mark // at this point the stack has gone from [ .. val] to [.. val helper val name] compileContext.addStackCount(3); // we can just swap the two values mv.visitInsn(Opcodes.SWAP); } // ensure we have an object compileObjectConversion(type, Type.OBJECT, mv, compileContext); // call the setBinding method mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.internalName(HelperAdapter.class), "setBinding", "(Ljava/lang/String;Ljava/lang/Object;)V"); // the call will remove 3 from the stack height compileContext.addStackCount(-3); // ok, the stack height should be as it was if (compileContext.getStackCount() != currentStack) { throw new CompileException("variable.compileAssignment : invalid stack height " + compileContext.getStackCount() + " expecting " + currentStack); } } }