Example usage for org.objectweb.asm Opcodes POP

List of usage examples for org.objectweb.asm Opcodes POP

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes POP.

Prototype

int POP

To view the source code for org.objectweb.asm Opcodes POP.

Click Source Link

Usage

From source file:asmlib.Type.java

License:Open Source License

/** Mtodo que retorna o opcode certo para o tipo de varivel que se quer fazer pop na stack.
  * Opcodes disponveis:/*from ww  w. j ava 2  s .c  om*/
  * - POP2 para long, double
  * - POP para todos os restantes
  **/
public int getPopInsn() {
    if (getNumberSlots() == 1) {
        return Opcodes.POP;
    } else {
        return Opcodes.POP2;
    }
}

From source file:asmlib.Util.java

License:Open Source License

/** Generates code needed to swap the two types received, when they are at the top of the stack,
  * even if one or both of them occupy two slots (are longs or doubles).
  **//*from w  w w  . j  a v a  2 s .c  om*/
public static void swap(MethodVisitor mv, Type stackTop, Type belowTop) {
    if (stackTop.getNumberSlots() == 1) {
        if (belowTop.getNumberSlots() == 1) {
            // Top = 1, below = 1
            mv.visitInsn(Opcodes.SWAP);
        } else {
            // Top = 1, below = 2
            mv.visitInsn(Opcodes.DUP_X2);
            mv.visitInsn(Opcodes.POP);
        }
    } else {
        if (belowTop.getNumberSlots() == 1) {
            // Top = 2, below = 1
            mv.visitInsn(Opcodes.DUP2_X1);
        } else {
            // Top = 2, below = 2
            mv.visitInsn(Opcodes.DUP2_X2);
        }
        mv.visitInsn(Opcodes.POP2);
    }
}

From source file:br.usp.each.saeg.badua.core.internal.instr.ClassInstrumenter.java

License:Open Source License

@Override
public void visitEnd() {
    // not instrument interfaces or
    // classes with probe count equals to zero
    if (interfaceType || classProbeCount == 0) {
        super.visitEnd();
        return;//from ww  w.  j a va  2s  . c o  m
    }

    final FieldVisitor fv = cv.visitField(InstrSupport.DATAFIELD_ACC, InstrSupport.DATAFIELD_NAME,
            InstrSupport.DATAFIELD_DESC, null, null);
    fv.visitEnd();

    final MethodVisitor mv = cv.visitMethod(InstrSupport.DATAMETHOD_ACC, InstrSupport.DATAMETHOD_NAME,
            InstrSupport.DATAMETHOD_DESC, null, null);
    mv.visitCode();

    // Load the value of the static data field:
    mv.visitFieldInsn(Opcodes.GETSTATIC, className, InstrSupport.DATAFIELD_NAME, InstrSupport.DATAFIELD_DESC);
    mv.visitInsn(Opcodes.DUP);

    // Stack[1]: [J
    // Stack[0]: [J

    // Skip initialization when we already have a data array:
    final Label alreadyInitialized = new Label();
    mv.visitJumpInsn(Opcodes.IFNONNULL, alreadyInitialized);

    // Stack[0]: [J

    mv.visitInsn(Opcodes.POP);
    mv.visitLdcInsn(classId);
    InstrSupport.push(mv, classProbeCount);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, InstrSupport.RUNTIME_OWNER, InstrSupport.RUNTIME_NAME,
            InstrSupport.RUNTIME_DESC, false);

    // Stack[0]: [J

    mv.visitInsn(Opcodes.DUP);

    // Stack[1]: [J
    // Stack[0]: [J

    mv.visitFieldInsn(Opcodes.PUTSTATIC, className, InstrSupport.DATAFIELD_NAME, InstrSupport.DATAFIELD_DESC);

    // Stack[0]: [J

    if (withFrames) {
        mv.visitFrame(Opcodes.F_NEW, 0, new Object[] {}, 1, new Object[] { InstrSupport.DATAFIELD_DESC });
    }
    mv.visitLabel(alreadyInitialized);
    mv.visitInsn(Opcodes.ARETURN);

    mv.visitMaxs(3, 0);
    mv.visitEnd();

    super.visitEnd();
}

From source file:br.usp.each.saeg.badua.core.internal.instr.InstrSupport.java

License:Open Source License

public static void swap(final MethodVisitor mv, final Type stackTop, final Type belowTop) {
    if (stackTop.getSize() == 1) {
        if (belowTop.getSize() == 1) {
            // Top = 1, below = 1
            mv.visitInsn(Opcodes.SWAP);//  www .  j a v  a  2s.c  o  m
        } else {
            // Top = 1, below = 2
            mv.visitInsn(Opcodes.DUP_X2);
            mv.visitInsn(Opcodes.POP);
        }
    } else {
        if (belowTop.getSize() == 1) {
            // Top = 2, below = 1
            mv.visitInsn(Opcodes.DUP2_X1);
        } else {
            // Top = 2, below = 2
            mv.visitInsn(Opcodes.DUP2_X2);
        }
        mv.visitInsn(Opcodes.POP2);
    }
}

From source file:bytecode.InstructionExporter.java

License:Apache License

/**
 * Outputs stack operations (SWAP, DUP, etc.).
 *
 * @param instruction Stack operation./*from  w w w  . j  ava2 s .  c o m*/
 * @return            <code>null</code>
 */
@Override
public Void visit(StackOperation instruction) {
    switch (instruction.getSort()) {
    case SWAP:
        mv.visitInsn(Opcodes.SWAP);
        break;
    case POP:
        mv.visitInsn(Opcodes.POP);
        break;
    case POP2:
        mv.visitInsn(Opcodes.POP2);
        break;
    case DUP:
        mv.visitInsn(Opcodes.DUP);
        break;
    case DUP2:
        mv.visitInsn(Opcodes.DUP2);
        break;
    case DUP_X1:
        mv.visitInsn(Opcodes.DUP_X1);
        break;
    case DUP_X2:
        mv.visitInsn(Opcodes.DUP_X2);
        break;
    case DUP2_X1:
        mv.visitInsn(Opcodes.DUP2_X1);
        break;
    case DUP2_X2:
        mv.visitInsn(Opcodes.DUP2_X2);
        break;
    }

    return null;
}

From source file:bytecode.MethodImporter.java

License:Apache License

/**
 * Imports instructions with no immediate operands.
 *
 * @param opcode Opcode./*  w w  w.j ava  2s. c om*/
 */
@Override
public void visitInsn(final int opcode) {
    Producer a, b, c, d;
    Type top;

    switch (opcode) {
    // Constants
    case Opcodes.ACONST_NULL:
        createConstant(null);
        break;
    case Opcodes.ICONST_M1:
        createConstant(new Integer(-1));
        break;
    case Opcodes.ICONST_0:
        createConstant(new Integer(0));
        break;
    case Opcodes.ICONST_1:
        createConstant(new Integer(1));
        break;
    case Opcodes.ICONST_2:
        createConstant(new Integer(2));
        break;
    case Opcodes.ICONST_3:
        createConstant(new Integer(3));
        break;
    case Opcodes.ICONST_4:
        createConstant(new Integer(4));
        break;
    case Opcodes.ICONST_5:
        createConstant(new Integer(5));
        break;
    case Opcodes.LCONST_0:
        createConstant(new Long(0));
        break;
    case Opcodes.LCONST_1:
        createConstant(new Long(1));
        break;
    case Opcodes.FCONST_0:
        createConstant(new Float(0.0f));
        break;
    case Opcodes.FCONST_1:
        createConstant(new Float(1.0f));
        break;
    case Opcodes.FCONST_2:
        createConstant(new Float(2.0f));
        break;
    case Opcodes.DCONST_0:
        createConstant(new Double(0.0f));
        break;
    case Opcodes.DCONST_1:
        createConstant(new Double(1.0f));
        break;

    // Binary Operations
    case Opcodes.IADD:
        createArithmetic(Arithmetic.Operator.ADD, Type.INT);
        break;
    case Opcodes.LADD:
        createArithmetic(Arithmetic.Operator.ADD, Type.LONG);
        break;
    case Opcodes.FADD:
        createArithmetic(Arithmetic.Operator.ADD, Type.FLOAT);
        break;
    case Opcodes.DADD:
        createArithmetic(Arithmetic.Operator.ADD, Type.DOUBLE);
        break;
    case Opcodes.ISUB:
        createArithmetic(Arithmetic.Operator.SUB, Type.INT);
        break;
    case Opcodes.LSUB:
        createArithmetic(Arithmetic.Operator.SUB, Type.LONG);
        break;
    case Opcodes.FSUB:
        createArithmetic(Arithmetic.Operator.SUB, Type.FLOAT);
        break;
    case Opcodes.DSUB:
        createArithmetic(Arithmetic.Operator.SUB, Type.DOUBLE);
        break;
    case Opcodes.IMUL:
        createArithmetic(Arithmetic.Operator.MUL, Type.INT);
        break;
    case Opcodes.LMUL:
        createArithmetic(Arithmetic.Operator.MUL, Type.LONG);
        break;
    case Opcodes.FMUL:
        createArithmetic(Arithmetic.Operator.MUL, Type.FLOAT);
        break;
    case Opcodes.DMUL:
        createArithmetic(Arithmetic.Operator.MUL, Type.DOUBLE);
        break;
    case Opcodes.IDIV:
        createArithmetic(Arithmetic.Operator.DIV, Type.INT);
        break;
    case Opcodes.LDIV:
        createArithmetic(Arithmetic.Operator.DIV, Type.LONG);
        break;
    case Opcodes.FDIV:
        createArithmetic(Arithmetic.Operator.DIV, Type.FLOAT);
        break;
    case Opcodes.DDIV:
        createArithmetic(Arithmetic.Operator.DIV, Type.DOUBLE);
        break;
    case Opcodes.IREM:
        createArithmetic(Arithmetic.Operator.REM, Type.INT);
        break;
    case Opcodes.LREM:
        createArithmetic(Arithmetic.Operator.REM, Type.LONG);
        break;
    case Opcodes.FREM:
        createArithmetic(Arithmetic.Operator.REM, Type.FLOAT);
        break;
    case Opcodes.DREM:
        createArithmetic(Arithmetic.Operator.REM, Type.DOUBLE);
        break;
    case Opcodes.IAND:
        createArithmetic(Arithmetic.Operator.AND, Type.INT);
        break;
    case Opcodes.LAND:
        createArithmetic(Arithmetic.Operator.AND, Type.LONG);
        break;
    case Opcodes.IOR:
        createArithmetic(Arithmetic.Operator.OR, Type.INT);
        break;
    case Opcodes.LOR:
        createArithmetic(Arithmetic.Operator.OR, Type.LONG);
        break;
    case Opcodes.IXOR:
        createArithmetic(Arithmetic.Operator.XOR, Type.INT);
        break;
    case Opcodes.LXOR:
        createArithmetic(Arithmetic.Operator.XOR, Type.LONG);
        break;
    case Opcodes.ISHL:
        createArithmetic(Arithmetic.Operator.SHL, Type.INT);
        break;
    case Opcodes.LSHL:
        createArithmetic(Arithmetic.Operator.SHL, Type.LONG);
        break;
    case Opcodes.ISHR:
        createArithmetic(Arithmetic.Operator.SHR, Type.INT);
        break;
    case Opcodes.LSHR:
        createArithmetic(Arithmetic.Operator.SHR, Type.LONG);
        break;
    case Opcodes.IUSHR:
        createArithmetic(Arithmetic.Operator.USHR, Type.INT);
        break;
    case Opcodes.LUSHR:
        createArithmetic(Arithmetic.Operator.USHR, Type.LONG);
        break;

    case Opcodes.LCMP:
        createCompare(false, Type.LONG);
        break;
    case Opcodes.FCMPL:
        createCompare(false, Type.FLOAT);
        break;
    case Opcodes.FCMPG:
        createCompare(true, Type.FLOAT);
        break;
    case Opcodes.DCMPL:
        createCompare(false, Type.DOUBLE);
        break;
    case Opcodes.DCMPG:
        createCompare(true, Type.DOUBLE);
        break;
    case Opcodes.INEG:
        createNegate();
        break;
    case Opcodes.LNEG:
        createNegate();
        break;
    case Opcodes.FNEG:
        createNegate();
        break;
    case Opcodes.DNEG:
        createNegate();
        break;
    case Opcodes.I2L:
        createConvert(Type.LONG);
        break;
    case Opcodes.I2F:
        createConvert(Type.FLOAT);
        break;
    case Opcodes.I2D:
        createConvert(Type.DOUBLE);
        break;
    case Opcodes.I2B:
        createConvert(Type.BYTE);
        break;
    case Opcodes.I2C:
        createConvert(Type.CHAR);
        break;
    case Opcodes.I2S:
        createConvert(Type.SHORT);
        break;
    case Opcodes.L2I:
        createConvert(Type.INT);
        break;
    case Opcodes.L2F:
        createConvert(Type.FLOAT);
        break;
    case Opcodes.L2D:
        createConvert(Type.DOUBLE);
        break;
    case Opcodes.F2I:
        createConvert(Type.INT);
        break;
    case Opcodes.F2L:
        createConvert(Type.LONG);
        break;
    case Opcodes.F2D:
        createConvert(Type.DOUBLE);
        break;
    case Opcodes.D2I:
        createConvert(Type.INT);
        break;
    case Opcodes.D2F:
        createConvert(Type.FLOAT);
        break;
    case Opcodes.D2L:
        createConvert(Type.LONG);
        break;
    case Opcodes.IALOAD:
        createArrayRead(Type.INT);
        break;
    case Opcodes.LALOAD:
        createArrayRead(Type.LONG);
        break;
    case Opcodes.FALOAD:
        createArrayRead(Type.FLOAT);
        break;
    case Opcodes.DALOAD:
        createArrayRead(Type.DOUBLE);
        break;
    case Opcodes.AALOAD:
        createArrayRead(Type.getFreshRef());
        break;
    case Opcodes.BALOAD:
        createArrayRead(Type.BYTE);
        break;
    case Opcodes.CALOAD:
        createArrayRead(Type.CHAR);
        break;
    case Opcodes.SALOAD:
        createArrayRead(Type.SHORT);
        break;
    case Opcodes.IASTORE:
        createArrayWrite(Type.INT);
        break;
    case Opcodes.LASTORE:
        createArrayWrite(Type.LONG);
        break;
    case Opcodes.FASTORE:
        createArrayWrite(Type.FLOAT);
        break;
    case Opcodes.DASTORE:
        createArrayWrite(Type.DOUBLE);
        break;
    case Opcodes.AASTORE:
        createArrayWrite(Type.getFreshRef());
        break;
    case Opcodes.BASTORE:
        createArrayWrite(Type.BYTE);
        break;
    case Opcodes.CASTORE:
        createArrayWrite(Type.CHAR);
        break;
    case Opcodes.SASTORE:
        createArrayWrite(Type.SHORT);
        break;
    case Opcodes.IRETURN:
        createReturn(Type.INT);
        break;
    case Opcodes.LRETURN:
        createReturn(Type.LONG);
        break;
    case Opcodes.FRETURN:
        createReturn(Type.FLOAT);
        break;
    case Opcodes.DRETURN:
        createReturn(Type.DOUBLE);
        break;
    case Opcodes.ARETURN:
        createReturn(Type.REF);
        break;
    case Opcodes.RETURN:
        createReturn(null);
        break;
    case Opcodes.ATHROW:
        createThrow();
        break;

    // Array Length
    case Opcodes.ARRAYLENGTH:
        ordered.add(stack.push(new ArrayLength(stack.pop())));
        break;

    // Swap
    case Opcodes.SWAP:
        a = stack.pop();
        b = stack.pop();

        stack.push(a);
        stack.push(b);

        ordered.add(new StackOperation(StackOperation.Sort.SWAP));

        break;

    // Duplicates
    case Opcodes.DUP:
        stack.push(stack.peek());
        ordered.add(new StackOperation(StackOperation.Sort.DUP));
        break;
    case Opcodes.DUP2:
        top = stack.peek().getType();

        // Type 2 Values
        if (top.getSize() == 2) {
            stack.push(stack.peek());
            // Type 1 Values
        } else {
            b = stack.pop();
            a = stack.pop();

            stack.push(a);
            stack.push(b);
            stack.push(a);
            stack.push(b);
        }

        ordered.add(new StackOperation(StackOperation.Sort.DUP2));

        break;
    case Opcodes.DUP_X1:
        b = stack.pop();
        a = stack.pop();

        stack.push(b);
        stack.push(a);
        stack.push(b);

        ordered.add(new StackOperation(StackOperation.Sort.DUP_X1));

        break;
    case Opcodes.DUP_X2:
        top = stack.peek().getType();

        // Type 2 Values
        if (top.getSize() == 2) {
            b = stack.pop();
            a = stack.pop();

            stack.push(b);
            stack.push(a);
            stack.push(b);
            // Type 1 Values
        } else {
            c = stack.pop();
            b = stack.pop();
            a = stack.pop();

            stack.push(c);
            stack.push(a);
            stack.push(b);
            stack.push(c);
        }

        ordered.add(new StackOperation(StackOperation.Sort.DUP_X2));

        break;

    // Pops
    case Opcodes.POP:
        stack.pop();
        ordered.add(new StackOperation(StackOperation.Sort.POP));
        break;
    case Opcodes.POP2:
        top = stack.peek().getType();

        // Type 2 Values
        if (top.getSize() == 2) {
            stack.pop();
            // Type 1 Values
        } else {
            stack.pop();
            stack.pop();
        }

        ordered.add(new StackOperation(StackOperation.Sort.POP2));

        break;

    // TODO: DUP2_X1, DUP2_X2, MONITORENTER, MONITOREXIT
    case Opcodes.MONITORENTER:
        throw new RuntimeException("visitInsn: MONITORENTER");
    case Opcodes.MONITOREXIT:
        throw new RuntimeException("visitInsn: MONITOREXIT");
    case Opcodes.DUP2_X1:
        throw new RuntimeException("visitInsn: DUP2_X1");
    case Opcodes.DUP2_X2:
        throw new RuntimeException("visitInsn: DUP2_X2");
    default:
        throw new RuntimeException("visitInsn: " + opcode);
    }
}

From source file:Client.JClassPatcher.java

License:Open Source License

private void patchRenderer(ClassNode node) {
    Logger.Info("Patching renderer (" + node.name + ".class)");

    Iterator<MethodNode> methodNodeList = node.methods.iterator();
    while (methodNodeList.hasNext()) {
        MethodNode methodNode = methodNodeList.next();

        // Renderer present hook
        if (methodNode.desc.equals("(Ljava/awt/Graphics;III)V")) {
            AbstractInsnNode findNode = methodNode.instructions.getFirst();
            FieldInsnNode imageNode = null;

            while (findNode.getOpcode() != Opcodes.POP) {
                findNode = findNode.getNext();
                if (findNode == null) {
                    Logger.Error("Unable to find present hook");
                    break;
                }/*from   w  ww  .  j  a  va  2s .c o m*/
            }

            while (findNode.getOpcode() != Opcodes.INVOKESPECIAL) {
                if (findNode.getOpcode() == Opcodes.GETFIELD)
                    imageNode = (FieldInsnNode) findNode;

                AbstractInsnNode prev = findNode.getPrevious();
                methodNode.instructions.remove(findNode);
                findNode = prev;
            }

            methodNode.instructions.insert(findNode, new MethodInsnNode(Opcodes.INVOKESTATIC, "Game/Renderer",
                    "present", "(Ljava/awt/Graphics;Ljava/awt/Image;)V", false));
            methodNode.instructions.insert(findNode,
                    new FieldInsnNode(Opcodes.GETFIELD, node.name, imageNode.name, imageNode.desc));
            methodNode.instructions.insert(findNode, new VarInsnNode(Opcodes.ALOAD, 0));
            methodNode.instructions.insert(findNode, new VarInsnNode(Opcodes.ALOAD, 1));
        } else if (methodNode.name.equals("a") && methodNode.desc.equals("(IILjava/lang/String;IIBI)V")) {
            AbstractInsnNode start = methodNode.instructions.getFirst();
            while (start != null) {
                if (start.getOpcode() == Opcodes.ALOAD && start.getNext().getOpcode() == Opcodes.ILOAD
                        && start.getNext().getNext().getOpcode() == Opcodes.INVOKEVIRTUAL
                        && start.getNext().getNext().getNext().getOpcode() == Opcodes.ISTORE) {
                    break;
                }

                start = start.getNext();
            }
            start = start.getPrevious();

            LabelNode finishLabel = ((JumpInsnNode) start.getPrevious().getPrevious()).label;
            LabelNode failLabel = new LabelNode();

            methodNode.instructions.insertBefore(start, new IntInsnNode(Opcodes.BIPUSH, 126));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ALOAD, 3));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10));
            methodNode.instructions.insertBefore(start,
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C"));
            methodNode.instructions.insertBefore(start, new JumpInsnNode(Opcodes.IF_ICMPNE, failLabel));

            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.ICONST_5));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.IADD));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ALOAD, 3));
            methodNode.instructions.insertBefore(start,
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "length", "()I"));
            methodNode.instructions.insertBefore(start, new JumpInsnNode(Opcodes.IF_ICMPGE, failLabel));

            methodNode.instructions.insertBefore(start, new IntInsnNode(Opcodes.BIPUSH, 126));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ALOAD, 3));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.ICONST_5));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.IADD));
            methodNode.instructions.insertBefore(start,
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/String", "charAt", "(I)C"));
            methodNode.instructions.insertBefore(start, new JumpInsnNode(Opcodes.IF_ICMPNE, failLabel));

            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ALOAD, 3));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.ICONST_1));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.IADD));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ILOAD, 10));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.ICONST_5));
            methodNode.instructions.insertBefore(start, new InsnNode(Opcodes.IADD));
            methodNode.instructions.insertBefore(start, new MethodInsnNode(Opcodes.INVOKEVIRTUAL,
                    "java/lang/String", "substring", "(II)Ljava/lang/String;"));
            methodNode.instructions.insertBefore(start, new MethodInsnNode(Opcodes.INVOKESTATIC,
                    "java/lang/Integer", "parseInt", "(Ljava/lang/String;)I"));
            methodNode.instructions.insertBefore(start, new VarInsnNode(Opcodes.ISTORE, 4));
            methodNode.instructions.insertBefore(start, new IincInsnNode(10, 5));

            methodNode.instructions.insertBefore(start, new JumpInsnNode(Opcodes.GOTO, finishLabel));

            methodNode.instructions.insertBefore(start, failLabel);
        }
    }
}

From source file:Client.JClassPatcher.java

License:Open Source License

/**
 * TODO: Complete JavaDoc/*  ww w  .j av  a2s. co  m*/
 * 
 * @param methodNode
 * @param owner The class of the variable to be hooked
 * @param var The variable to be hooked
 * @param desc
 * @param newClass The class the hooked variable will be stored in
 * @param newVar The variable name the hooked variable will be stored in
 * @param newDesc
 * @param canRead Specifies if the hooked variable should be readable
 * @param canWrite Specifies if the hooked variable should be writable
 */
private void hookClassVariable(MethodNode methodNode, String owner, String var, String desc, String newClass,
        String newVar, String newDesc, boolean canRead, boolean canWrite) {
    Iterator<AbstractInsnNode> insnNodeList = methodNode.instructions.iterator();
    while (insnNodeList.hasNext()) {
        AbstractInsnNode insnNode = insnNodeList.next();

        int opcode = insnNode.getOpcode();
        if (opcode == Opcodes.GETFIELD || opcode == Opcodes.PUTFIELD) {
            FieldInsnNode field = (FieldInsnNode) insnNode;
            if (field.owner.equals(owner) && field.name.equals(var) && field.desc.equals(desc)) {
                if (opcode == Opcodes.GETFIELD && canWrite) {
                    methodNode.instructions.insert(insnNode,
                            new FieldInsnNode(Opcodes.GETSTATIC, newClass, newVar, newDesc));
                    methodNode.instructions.insert(insnNode, new InsnNode(Opcodes.POP));
                } else if (opcode == Opcodes.PUTFIELD && canRead) {
                    methodNode.instructions.insertBefore(insnNode, new InsnNode(Opcodes.DUP_X1));
                    methodNode.instructions.insert(insnNode,
                            new FieldInsnNode(Opcodes.PUTSTATIC, newClass, newVar, newDesc));
                }
            }
        }
    }
}

From source file:co.cask.cdap.app.runtime.spark.SparkRunnerClassLoader.java

License:Apache License

/**
 * Define the akka.remote.Remoting by rewriting usages of scala.concurrent.ExecutionContext.Implicits.global
 * to Remoting.system().dispatcher() in the shutdown() method for fixing the Akka thread/permgen leak bug in
 * https://github.com/akka/akka/issues/17729
 *///w w  w  .j  av  a2 s . c  o m
private Class<?> defineAkkaRemoting(String name, InputStream byteCodeStream)
        throws IOException, ClassNotFoundException {
    final Type dispatcherReturnType = determineAkkaDispatcherReturnType();
    if (dispatcherReturnType == null) {
        LOG.warn("Failed to determine ActorSystem.dispatcher() return type. "
                + "No rewriting of akka.remote.Remoting class. ClassLoader leakage might happen in SDK.");
        return findClass(name);
    }

    ClassReader cr = new ClassReader(byteCodeStream);
    ClassWriter cw = new ClassWriter(0);

    cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                String[] exceptions) {
            // Call super so that the method signature is registered with the ClassWriter (parent)
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);

            // Only rewrite the shutdown() method
            if (!"shutdown".equals(name)) {
                return mv;
            }

            return new MethodVisitor(Opcodes.ASM5, mv) {
                @Override
                public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
                    // Detect if it is making call "import scala.concurrent.ExecutionContext.Implicits.global",
                    // which translate to Java code as
                    // scala.concurrent.ExecutionContext$Implicits$.MODULE$.global()
                    // hence as bytecode
                    // GETSTATIC scala/concurrent/ExecutionContext$Implicits$.MODULE$ :
                    //           Lscala/concurrent/ExecutionContext$Implicits$;
                    // INVOKEVIRTUAL scala/concurrent/ExecutionContext$Implicits$.global
                    //           ()Lscala/concurrent/ExecutionContextExecutor;
                    if (opcode == Opcodes.INVOKEVIRTUAL && "global".equals(name)
                            && "scala/concurrent/ExecutionContext$Implicits$".equals(owner)
                            && Type.getMethodDescriptor(EXECUTION_CONTEXT_EXECUTOR_TYPE).equals(desc)) {
                        // Discard the GETSTATIC result from the stack by popping it
                        super.visitInsn(Opcodes.POP);
                        // Make the call "import system.dispatch", which translate to Java code as
                        // this.system().dispatcher()
                        // hence as bytecode
                        // ALOAD 0 (load this)
                        // INVOKEVIRTUAL akka/remote/Remoting.system ()Lakka/actor/ExtendedActorSystem;
                        // INVOKEVIRTUAL akka/actor/ExtendedActorSystem.dispatcher ()Lscala/concurrent/ExecutionContextExecutor;
                        Type extendedActorSystemType = Type.getObjectType("akka/actor/ExtendedActorSystem");
                        super.visitVarInsn(Opcodes.ALOAD, 0);
                        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "akka/remote/Remoting", "system",
                                Type.getMethodDescriptor(extendedActorSystemType), false);
                        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, extendedActorSystemType.getInternalName(),
                                "dispatcher", Type.getMethodDescriptor(dispatcherReturnType), false);
                    } else {
                        // For other instructions, just call parent to deal with it
                        super.visitMethodInsn(opcode, owner, name, desc, itf);
                    }
                }
            };
        }
    }, ClassReader.EXPAND_FRAMES);

    byte[] byteCode = cw.toByteArray();
    return defineClass(name, byteCode, 0, byteCode.length);
}

From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java

License:Open Source License

public void accept(MethodVisitor mv, boolean hasAnnotation) {
    db.log(LogLevel.INFO, "Instrumenting method %s#%s%s", className, mn.name, mn.desc);

    mv.visitAnnotation(ALREADY_INSTRUMENTED_DESC, true);
    final boolean handleProxyInvocations = HANDLE_PROXY_INVOCATIONS & hasSuspendableSuperCalls;
    mv.visitCode();/*from w w  w .  j a  v a 2 s  .co  m*/

    Label lMethodStart = new Label();
    Label lMethodStart2 = new Label();
    Label lMethodEnd = new Label();
    Label lCatchSEE = new Label();
    Label lCatchUTE = new Label();
    Label lCatchAll = new Label();
    Label[] lMethodCalls = new Label[numCodeBlocks - 1];

    for (int i = 1; i < numCodeBlocks; i++)
        lMethodCalls[i - 1] = new Label();

    mv.visitInsn(Opcodes.ACONST_NULL);
    mv.visitVarInsn(Opcodes.ASTORE, lvarInvocationReturnValue);

    //        if (verifyInstrumentation) {
    //            mv.visitInsn(Opcodes.ICONST_0);
    //            mv.visitVarInsn(Opcodes.ISTORE, lvarSuspendableCalled);
    //        }
    mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchSEE, EXCEPTION_NAME);
    if (handleProxyInvocations)
        mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchUTE, UNDECLARED_THROWABLE_NAME);

    // Prepare visitTryCatchBlocks for InvocationTargetException.
    // With reflective invocations, the SuspendExecution exception will be wrapped in InvocationTargetException. We need to catch it and unwrap it.
    // Note that the InvocationTargetException will be regenrated on every park, adding further overhead on top of the reflective call.
    // This must be done here, before all other visitTryCatchBlock, because the exception's handler
    // will be matched according to the order of in which visitTryCatchBlock has been called. Earlier calls take precedence.
    Label[][] refInvokeTryCatch = new Label[numCodeBlocks - 1][];
    for (int i = 1; i < numCodeBlocks; i++) {
        FrameInfo fi = codeBlocks[i];
        AbstractInsnNode in = mn.instructions.get(fi.endInstruction);
        if (mn.instructions.get(fi.endInstruction) instanceof MethodInsnNode) {
            MethodInsnNode min = (MethodInsnNode) in;
            if (isReflectInvocation(min.owner, min.name)) {
                Label[] ls = new Label[3];
                for (int k = 0; k < 3; k++)
                    ls[k] = new Label();
                refInvokeTryCatch[i - 1] = ls;
                mv.visitTryCatchBlock(ls[0], ls[1], ls[2], "java/lang/reflect/InvocationTargetException");
            }
        }
    }

    for (Object o : mn.tryCatchBlocks) {
        TryCatchBlockNode tcb = (TryCatchBlockNode) o;
        if (EXCEPTION_NAME.equals(tcb.type) && !hasAnnotation) // we allow catch of SuspendExecution in method annotated with @Suspendable.
            throw new UnableToInstrumentException("catch for SuspendExecution", className, mn.name, mn.desc);
        if (handleProxyInvocations && UNDECLARED_THROWABLE_NAME.equals(tcb.type)) // we allow catch of SuspendExecution in method annotated with @Suspendable.
            throw new UnableToInstrumentException("catch for UndeclaredThrowableException", className, mn.name,
                    mn.desc);
        //          if (INTERRUPTED_EXCEPTION_NAME.equals(tcb.type))
        //              throw new UnableToInstrumentException("catch for " + InterruptedException.class.getSimpleName(), className, mn.name, mn.desc);

        tcb.accept(mv);
    }

    if (mn.visibleParameterAnnotations != null)
        dumpParameterAnnotations(mv, mn.visibleParameterAnnotations, true);

    if (mn.invisibleParameterAnnotations != null)
        dumpParameterAnnotations(mv, mn.invisibleParameterAnnotations, false);

    if (mn.visibleAnnotations != null) {
        for (Object o : mn.visibleAnnotations) {
            AnnotationNode an = (AnnotationNode) o;
            an.accept(mv.visitAnnotation(an.desc, true));
        }
    }

    mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchAll, null);

    mv.visitMethodInsn(Opcodes.INVOKESTATIC, STACK_NAME, "getStack", "()L" + STACK_NAME + ";");
    mv.visitInsn(Opcodes.DUP);
    mv.visitVarInsn(Opcodes.ASTORE, lvarStack);

    // println(mv, "STACK: ", lvarStack);
    // dumpStack(mv);
    if (DUAL) {
        mv.visitJumpInsn(Opcodes.IFNULL, lMethodStart);
        mv.visitVarInsn(Opcodes.ALOAD, lvarStack);
    }

    emitStoreResumed(mv, true); // we'll assume we have been resumed

    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "nextMethodEntry", "()I");
    mv.visitTableSwitchInsn(1, numCodeBlocks - 1, lMethodStart2, lMethodCalls);

    mv.visitLabel(lMethodStart2);

    // the following code handles the case of an instrumented method called not as part of a suspendable code path
    // isFirstInStack will return false in that case.
    mv.visitVarInsn(Opcodes.ALOAD, lvarStack);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "isFirstInStackOrPushed", "()Z");
    mv.visitJumpInsn(Opcodes.IFNE, lMethodStart); // if true
    mv.visitInsn(Opcodes.ACONST_NULL);
    mv.visitVarInsn(Opcodes.ASTORE, lvarStack);

    mv.visitLabel(lMethodStart);

    emitStoreResumed(mv, false); // no, we have not been resumed

    dumpCodeBlock(mv, 0, 0);

    for (int i = 1; i < numCodeBlocks; i++) {
        FrameInfo fi = codeBlocks[i];

        MethodInsnNode min = (MethodInsnNode) (mn.instructions.get(fi.endInstruction));
        if (isYieldMethod(min.owner, min.name)) { // special case - call to yield
            if (min.getOpcode() != Opcodes.INVOKESTATIC)
                throw new UnableToInstrumentException("invalid call to suspending method.", className, mn.name,
                        mn.desc);

            final int numYieldArgs = TypeAnalyzer.getNumArguments(min.desc);
            final boolean yieldReturnsValue = (Type.getReturnType(min.desc) != Type.VOID_TYPE);

            emitStoreState(mv, i, fi, numYieldArgs); // we preserve the arguments for the call to yield on the operand stack
            emitStoreResumed(mv, false); // we have not been resumed
            // emitSuspendableCalled(mv);

            min.accept(mv); // we call the yield method
            if (yieldReturnsValue)
                mv.visitInsn(Opcodes.POP); // we ignore the returned value...
            mv.visitLabel(lMethodCalls[i - 1]); // we resume AFTER the call

            final Label afterPostRestore = new Label();
            mv.visitVarInsn(Opcodes.ILOAD, lvarResumed);
            mv.visitJumpInsn(Opcodes.IFEQ, afterPostRestore);
            emitPostRestore(mv);
            mv.visitLabel(afterPostRestore);

            emitRestoreState(mv, i, fi, numYieldArgs);
            if (yieldReturnsValue)
                mv.visitVarInsn(Opcodes.ILOAD, lvarResumed); // ... and replace the returned value with the value of resumed

            dumpCodeBlock(mv, i, 1); // skip the call
        } else {
            final Label lbl = new Label();
            if (DUAL) {
                mv.visitVarInsn(Opcodes.ALOAD, lvarStack);
                mv.visitJumpInsn(Opcodes.IFNULL, lbl);
            }

            // normal case - call to a suspendable method - resume before the call
            emitStoreState(mv, i, fi, 0);
            emitStoreResumed(mv, false); // we have not been resumed
            // emitPreemptionPoint(mv, PREEMPTION_CALL);

            mv.visitLabel(lMethodCalls[i - 1]);
            emitRestoreState(mv, i, fi, 0);

            if (DUAL)
                mv.visitLabel(lbl);

            if (isReflectInvocation(min.owner, min.name)) {
                // We catch the InvocationTargetException and unwrap it if it wraps a SuspendExecution exception.
                Label[] ls = refInvokeTryCatch[i - 1];
                final Label startTry = ls[0];
                final Label endTry = ls[1];
                final Label startCatch = ls[2];
                final Label endCatch = new Label();
                final Label notSuspendExecution = new Label();

                // mv.visitTryCatchBlock(startTry, endTry, startCatch, "java/lang/reflect/InvocationTargetException");
                mv.visitLabel(startTry); // try {
                min.accept(mv); //   method.invoke()
                mv.visitVarInsn(Opcodes.ASTORE, lvarInvocationReturnValue); // save return value
                mv.visitLabel(endTry); // }
                mv.visitJumpInsn(Opcodes.GOTO, endCatch);
                mv.visitLabel(startCatch); // catch(InvocationTargetException ex) {
                mv.visitInsn(Opcodes.DUP);
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause",
                        "()Ljava/lang/Throwable;");
                mv.visitTypeInsn(Opcodes.INSTANCEOF, EXCEPTION_NAME);
                mv.visitJumpInsn(Opcodes.IFEQ, notSuspendExecution);
                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause",
                        "()Ljava/lang/Throwable;");
                mv.visitLabel(notSuspendExecution);
                mv.visitInsn(Opcodes.ATHROW);
                mv.visitLabel(endCatch);

                mv.visitVarInsn(Opcodes.ALOAD, lvarInvocationReturnValue); // restore return value
                dumpCodeBlock(mv, i, 1); // skip the call
            } else {
                // emitSuspendableCalled(mv);
                dumpCodeBlock(mv, i, 0);
            }
        }
    }

    mv.visitLabel(lMethodEnd);

    if (handleProxyInvocations) {
        mv.visitLabel(lCatchUTE);
        mv.visitInsn(Opcodes.DUP);

        // println(mv, "CTCH: ");
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;");
        // println(mv, "CAUSE: ");
        mv.visitTypeInsn(Opcodes.INSTANCEOF, EXCEPTION_NAME);
        mv.visitJumpInsn(Opcodes.IFEQ, lCatchAll);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;");
        mv.visitJumpInsn(Opcodes.GOTO, lCatchSEE);
    }

    mv.visitLabel(lCatchAll);
    emitPopMethod(mv);
    mv.visitLabel(lCatchSEE);

    // println(mv, "THROW: ");
    mv.visitInsn(Opcodes.ATHROW); // rethrow shared between catchAll and catchSSE

    if (mn.localVariables != null) {
        for (Object o : mn.localVariables)
            ((LocalVariableNode) o).accept(mv);
    }

    mv.visitMaxs(mn.maxStack + ADD_OPERANDS, mn.maxLocals + NUM_LOCALS + additionalLocals);
    mv.visitEnd();
}