List of usage examples for org.objectweb.asm Opcodes DUP_X2
int DUP_X2
To view the source code for org.objectweb.asm Opcodes DUP_X2.
Click Source Link
From source file:org.jboss.byteman.agent.adapter.RuleGeneratorAdapter.java
License:Open Source License
/** * Generates a DUP_X2 instruction. */ public void dupX2() { visitInsn(Opcodes.DUP_X2); }
From source file:org.jboss.byteman.agent.adapter.RuleTriggerMethodAdapter.java
License:Open Source License
/** * stack an argument array containing all the values which need to be bound to parameters or local variables * in the rule or a null pointer if no bindings are required. this method also inserts a copy of the array * below the initial two top entries if any of the bindings can potentially be updated by the rule, allowing * the updated values to be written back on return from the call to the rule engine. * @param saveSlot a local variable slot containing either the return value which the trigger method is about * to return or the Throwable the method is about to throw. this is only valid if, respectively, the rule * location is AT EXIT/AFTER INVOKE or AT THROW and the rule body contains a reference to the return value ($!) * or throwable value ($@)./*from w ww. ja v a 2 s . c o m*/ * @return true if the rule may update the argument array and hence if a copy of the array has been inserted * below the initial two top entries otherwise false. */ private boolean doArgLoad(int saveSlot) { if (callArrayBindings.size() == 0) { push((org.objectweb.asm.Type) null); return false; } // create the array used to pass the bindings int arraySize = callArrayBindings.size(); push(arraySize); Type objectType = Type.getType(Object.class); newArray(objectType); // check if any of the bindings gets updated. if so we need to stash a copy of the bindings array // below the key and owner so we can pull out the updated values and update local var/param slots // once the call ahs completed boolean doUpdates = false; for (int i = 0; i < arraySize; i++) { Binding binding = callArrayBindings.get(i); if (binding.isUpdated()) { doUpdates = true; break; } } if (doUpdates) { // insert copy of array below first two call arguments // [.. key owner bindings ] ==> [.. bindings key owner bindings ] mv.visitInsn(Opcodes.DUP_X2); } // now install required values into bindings array for (int i = 0; i < arraySize; i++) { Binding binding = callArrayBindings.get(i); dup(); push(i); if (binding.isParam()) { int idx = binding.getIndex() - 1; loadArg(idx); box(argumentTypes[idx]); } else if (binding.isLocalVar()) { int idx = binding.getLocalIndex(); loadLocal(idx); box(getLocalType(idx)); } else if (binding.isParamCount()) { int count = argumentTypes.length; push(count); box(Type.INT_TYPE); } else if (binding.isParamArray()) { int count = argumentTypes.length; push(count + 1); newArray(objectType); dup(); push(0); if ((access & Opcodes.ACC_STATIC) == 0) { loadThis(); } else { push((Type) null); } arrayStore(objectType); for (int idx = 0; idx < count; idx++) { dup(); push(idx + 1); loadArg(idx); box(argumentTypes[idx]); arrayStore(objectType); } } else if (binding.isInvokeParamArray()) { loadLocal(saveSlot); } else if (binding.isTriggerClass()) { String triggerClassName = TypeHelper.internalizeClass(getTriggerClassName()); visitLdcInsn(triggerClassName); } else if (binding.isTriggerMethod()) { String triggerMethodName = name + TypeHelper.internalizeDescriptor(descriptor); visitLdcInsn(triggerMethodName); } else if (binding.isThrowable() | binding.isReturn()) { loadLocal(saveSlot); box(saveValueType); } arrayStore(objectType); } return doUpdates; }
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 ww w . j a v a 2 s. co 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);//from w ww . j a v a 2 s .co m } 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 {//from www . j a v a 2 s. c o m // 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); } } }
From source file:org.jboss.byteman.rule.expression.FieldExpression.java
License:Open Source License
@Override public void compileAssign(MethodVisitor mv, CompileContext compileContext) throws CompileException { if (indirectStatic != null) { // this is just wrapping a static field expression so compile it indirectStatic.compileAssign(mv, compileContext); } else {// w w w. j a va2 s. c o m // make sure we are at the right source line compileContext.notifySourceLine(line); int currentStack = compileContext.getStackCount(); int size = (type.getNBytes() > 4 ? 2 : 1); // copy the value so we leave it as a result if (size == 1) { // this means at the maximum we add 1 to the current stack // [.. val] ==> [.. val val] mv.visitInsn(Opcodes.DUP); } else { // [.. val1 val2] ==> [.. val1 val2 val1 val2] mv.visitInsn(Opcodes.DUP2); } compileContext.addStackCount(size); // compile the owner expression and swap with the value owner.compile(mv, compileContext); if (size == 1) { // [.. val val owner] ==> [.. val owner val] mv.visitInsn(Opcodes.SWAP); } else { // we have to use a DUP_X2 and a POP to insert the owner below the two word value // i.e. [.. val1 val2 val1 val2] ==> [.. val1 val2 val1 val2 owner] ==> // [.. val1 val2 owner val1 val2 owner] ==> [.. val1 val2 owner val1 val2] mv.visitInsn(Opcodes.DUP_X2); compileContext.addStackCount(1); mv.visitInsn(Opcodes.POP); compileContext.addStackCount(-1); } if (isPublicField) { // now compile a field update String ownerType = Type.internalName(field.getDeclaringClass()); String fieldName = field.getName(); String fieldType = Type.internalName(field.getType(), true); mv.visitFieldInsn(Opcodes.PUTFIELD, ownerType, fieldName, fieldType); // we removed the owner and the value compileContext.addStackCount(-(1 + size)); } else { // since this is a private field we need to do the update using reflection // box the value to an object if necessary if (type.isPrimitive()) { compileBox(Type.boxType(type), mv, compileContext); } // stack the helper and then dupx2 it so it goes under the owner and value // [.. val(s) owner valObj ==> val(s) owner valObj helper ] mv.visitVarInsn(Opcodes.ALOAD, 0); // [.. val(s) owner valObj helper ==> val(s) helper owner valObj helper ] mv.visitInsn(Opcodes.DUP_X2); // stack now has 2 more words so count them compileContext.addStackCount(2); // now pop the redundant top word and stack the field index instead // [.. val(s) helper owner valObj helper ==> val(s) helper owner valObj index ] mv.visitInsn(Opcodes.POP); mv.visitLdcInsn(fieldIndex); // use the HelperAdapter method setAccessibleField to set the field value mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.internalName(HelperAdapter.class), "setAccessibleField", "(Ljava/lang/Object;Ljava/lang/Object;I)V"); // we popped four args compileContext.addStackCount(-4); } // check the stack height is ok if (compileContext.getStackCount() != currentStack) { throw new CompileException("FieldExpression.compileAssign : invalid stack height " + compileContext.getStackCount() + " expecting " + (currentStack)); } } }
From source file:org.jboss.byteman.rule.expression.Variable.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); int currentStack = compileContext.getStackCount(); int size = ((type.getNBytes() > 4) ? 2 : 1); int max;// w w w . java 2 s. 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) { // [... val1 val2 ==> ... val1 val2 val1 val2] mv.visitInsn(Opcodes.DUP2); } else { // [... val ==> ... val val] 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 // [... val1 val2 val1 val2 helper ==> ... val1 val2 helper val1 val2 helper] mv.visitInsn(Opcodes.DUP_X2); // [... val1 val2 helper val1 val2 helper ==> ... val1 val2 helper val1 val2] mv.visitInsn(Opcodes.POP); } else { // we can just swap the two values // [... val val helper ==> ... val helper val] mv.visitInsn(Opcodes.SWAP); } // stack the name for the variable and swap below the value mv.visitLdcInsn(name); if (size == 2) { // use a DUP_X2 to push a copy below the value then pop the redundant value // [... val1 val2 helper val1 val2 name ==> [... val1 val2 helper name val1 val2 name] mv.visitInsn(Opcodes.DUP_X2); // this is the high water mark compileContext.addStackCount(5); // [... val1 val2 helper name val1 val2 name ==> [... val1 val2 helper name val1 val2] mv.visitInsn(Opcodes.POP); compileContext.addStackCount(-1); // and now we have the desired arrangement for the call[.. val1 val2 helper name val1 val2] } 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 // [... val helper val name ==> ... val helper name val] mv.visitInsn(Opcodes.SWAP); // and now we have the desired arrangement for the call[.. val helper name val] } // 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); } }
From source file:org.mbte.groovypp.compiler.bytecode.BytecodeExpr.java
License:Apache License
public void swapObjectWith(ClassNode type, MethodVisitor mv) { if (type == long_TYPE || type == double_TYPE) { mv.visitInsn(Opcodes.DUP_X2); mv.visitInsn(Opcodes.POP);/*from w ww. ja v a 2 s. com*/ } else { mv.visitInsn(Opcodes.SWAP); } }
From source file:org.mbte.groovypp.compiler.bytecode.BytecodeExpr.java
License:Apache License
public static void dup_x2(ClassNode type, MethodVisitor mv) { if (type == double_TYPE || type == long_TYPE) mv.visitInsn(Opcodes.DUP2_X2);/*from w w w.j av a2 s. com*/ else mv.visitInsn(Opcodes.DUP_X2); }
From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java
License:Open Source License
/** * @param type/* www .j a v a 2s . c o m*/ * @return the DUP_X2 or DUP2_X2 instruction, depending on type. */ private static int getDupX2OpCode(JavaTypeName type) { switch (type.getTag()) { case JavaTypeName.BOOLEAN_TAG: case JavaTypeName.BYTE_TAG: case JavaTypeName.SHORT_TAG: case JavaTypeName.CHAR_TAG: case JavaTypeName.INT_TAG: case JavaTypeName.FLOAT_TAG: case JavaTypeName.ARRAY_TAG: case JavaTypeName.OBJECT_TAG: return Opcodes.DUP_X2; case JavaTypeName.LONG_TAG: case JavaTypeName.DOUBLE_TAG: return Opcodes.DUP2_X2; case JavaTypeName.VOID_TAG: default: { throw new IllegalArgumentException("invalid type: " + type); } } }