Example usage for org.objectweb.asm Opcodes JSR

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

Introduction

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

Prototype

int JSR

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

Click Source Link

Usage

From source file:bytecode.MethodImporter.java

License:Apache License

/**
 * Imports branch instructions, both conditional and unconditional.
 *
 * @param opcode Opcode./*from   w  w w .  j  av  a  2s .  c om*/
 * @param label  Destination of branch.
 */
@Override
public void visitJumpInsn(final int opcode, final Label label) {
    BasicBlock section = getBasicBlock(label);

    switch (opcode) {
    // Unconditional Branch
    case Opcodes.GOTO:
        finishBlock(section);
        setCurrent(null);
        break;

    // Zero Test
    case Opcodes.IFEQ:
        createZeroCondition(Condition.Operator.EQ, section);
        break;
    case Opcodes.IFNE:
        createZeroCondition(Condition.Operator.NE, section);
        break;
    case Opcodes.IFLT:
        createZeroCondition(Condition.Operator.LT, section);
        break;
    case Opcodes.IFGE:
        createZeroCondition(Condition.Operator.GE, section);
        break;
    case Opcodes.IFGT:
        createZeroCondition(Condition.Operator.GT, section);
        break;
    case Opcodes.IFLE:
        createZeroCondition(Condition.Operator.LE, section);
        break;

    // Integer Comparison
    case Opcodes.IF_ICMPEQ:
        createCondition(Condition.Operator.EQ, section);
        break;
    case Opcodes.IF_ICMPNE:
        createCondition(Condition.Operator.NE, section);
        break;
    case Opcodes.IF_ICMPLT:
        createCondition(Condition.Operator.LT, section);
        break;
    case Opcodes.IF_ICMPGE:
        createCondition(Condition.Operator.GE, section);
        break;
    case Opcodes.IF_ICMPGT:
        createCondition(Condition.Operator.GT, section);
        break;
    case Opcodes.IF_ICMPLE:
        createCondition(Condition.Operator.LE, section);
        break;

    // Reference Comparisons
    case Opcodes.IF_ACMPEQ:
        createCondition(Condition.Operator.EQ, section);
        break;
    case Opcodes.IF_ACMPNE:
        createCondition(Condition.Operator.NE, section);
        break;
    case Opcodes.IFNULL:
        createNullCondition(Condition.Operator.EQ, section);
        break;
    case Opcodes.IFNONNULL:
        createNullCondition(Condition.Operator.NE, section);
        break;

    // TODO: JSR (paired with RET)
    case Opcodes.JSR:
        System.err.println("visitJumpInsn: JSR");
    }
}

From source file:com.codename1.tools.translator.bytecodes.Jump.java

License:Open Source License

@Override
public void appendInstruction(StringBuilder b, List<Instruction> instructions) {
    b.append("    ");

    switch (opcode) {
    case Opcodes.IFEQ:
        b.append("if(POP_INT() == 0) /* IFEQ */ ");
        break;/*from ww  w.j a va  2  s  .  c o  m*/
    case Opcodes.IFNE:
        b.append("if(POP_INT() != 0) /* IFNE */ ");
        break;
    case Opcodes.IFLT:
        b.append("if(POP_INT() < 0) /* IFLT */ ");
        break;
    case Opcodes.IFGE:
        b.append("if(POP_INT() >= 0) /* IFGE */ ");
        break;
    case Opcodes.IFGT:
        b.append("if(POP_INT() > 0) /* IFGT */ ");
        break;
    case Opcodes.IFLE:
        b.append("if(POP_INT() <= 0) /* IFLE */ ");
        break;
    case Opcodes.IF_ICMPEQ:
        b.append("SP-=2; if((*SP).data.i == SP[1].data.i) /* IF_ICMPEQ */ ");
        break;
    case Opcodes.IF_ICMPNE:
        b.append("SP-=2; if((*SP).data.i != SP[1].data.i) /* IF_ICMPNE */ ");
        break;
    case Opcodes.IF_ICMPLT:
        b.append("SP-=2; if((*SP).data.i < SP[1].data.i) /* IF_ICMPLT */ ");
        break;
    case Opcodes.IF_ICMPGE:
        b.append("SP-=2; if((*SP).data.i >= SP[1].data.i) /* IF_ICMPGE */ ");
        break;
    case Opcodes.IF_ICMPGT:
        b.append("SP-=2; if((*SP).data.i > SP[1].data.i) /* IF_ICMPGT */ ");
        break;
    case Opcodes.IF_ICMPLE:
        b.append("SP-=2; if((*SP).data.i <= SP[1].data.i) /* IF_ICMPLE */ ");
        break;
    case Opcodes.IF_ACMPEQ:
        b.append("SP-=2; if((*SP).data.o == SP[1].data.o) /* IF_ACMPEQ */ ");
        break;
    case Opcodes.IF_ACMPNE:
        b.append("SP-=2; if((*SP).data.o != SP[1].data.o) /* IF_ACMPNE */ ");
        break;
    case Opcodes.GOTO:
        // this space intentionally left blank
        break;
    case Opcodes.JSR:
        b.append("/* JSR TODO */");
        /*b.append("PUSH_")
        b.append("goto label_");
        b.append(label.toString());
        b.append(";\n");
        b.append("JSR_RETURN_LABEL_");
        b.append(jsrCounter);
        b.append(":");
        jsrCounter++;*/
        return;
    case Opcodes.IFNULL:
        b.append("if(POP_OBJ() == JAVA_NULL) /* IFNULL */ ");
        break;
    case Opcodes.IFNONNULL:
        b.append("if(POP_OBJ() != JAVA_NULL) /* IFNONNULL */ ");
        break;
    }

    if (TryCatch.isTryCatchInMethod()) {
        b.append("JUMP_TO(label_");
        b.append(label.toString());
        b.append(", ");
        b.append(LabelInstruction.getLabelCatchDepth(label, instructions));
        b.append(");\n");
    } else {
        b.append("goto label_");
        b.append(label.toString());
        b.append(";\n");
    }
}

From source file:com.google.devtools.build.android.desugar.BytecodeTypeInference.java

License:Open Source License

@Override
public void visitJumpInsn(int opcode, Label label) {
    switch (opcode) {
    case Opcodes.IFEQ:
    case Opcodes.IFNE:
    case Opcodes.IFLT:
    case Opcodes.IFGE:
    case Opcodes.IFGT:
    case Opcodes.IFLE:
        pop();/*w  w  w  . j  av  a 2s . com*/
        break;
    case Opcodes.IF_ICMPEQ:
    case Opcodes.IF_ICMPNE:
    case Opcodes.IF_ICMPLT:
    case Opcodes.IF_ICMPGE:
    case Opcodes.IF_ICMPGT:
    case Opcodes.IF_ICMPLE:
    case Opcodes.IF_ACMPEQ:
    case Opcodes.IF_ACMPNE:
        pop(2);
        break;
    case Opcodes.GOTO:
        break;
    case Opcodes.JSR:
        throw new RuntimeException("The JSR instruction is not supported.");
    case Opcodes.IFNULL:
    case Opcodes.IFNONNULL:
        pop(1);
        break;
    default:
        throw new RuntimeException("Unhandled opcode " + opcode);
    }
    super.visitJumpInsn(opcode, label);
}

From source file:com.google.test.metric.asm.MethodVisitorBuilder.java

License:Apache License

public void visitJumpInsn(final int opcode, final Label label) {
    if (opcode == Opcodes.GOTO) {
        recorder.add(new Runnable() {
            public void run() {
                block.addOp(new Transform(lineNumber, "GOTO", null, null, null));
                block.unconditionalGoto(label);
            }/* www .  ja  va2  s  . c o  m*/
        });
    } else if (opcode == Opcodes.JSR) {
        recorder.add(new Runnable() {
            public void run() {
                block.jumpSubroutine(label, lineNumber);
            }
        });
    } else {
        recorder.add(new Runnable() {
            public void run() {
                cyclomaticComplexity.add(lineNumber);
                switch (opcode) {
                case Opcodes.IFEQ:
                    if1("IFEQ");
                    break;
                case Opcodes.IFNE:
                    if1("IFNE");
                    break;
                case Opcodes.IFLT:
                    if1("IFLT");
                    break;
                case Opcodes.IFGE:
                    if1("IFGE");
                    break;
                case Opcodes.IFGT:
                    if1("IFGT");
                    break;
                case Opcodes.IFLE:
                    if1("IFLE");
                    break;
                case Opcodes.IFNONNULL:
                    if1("IFNONNULL");
                    break;
                case Opcodes.IFNULL:
                    if1("IFNULL");
                    break;
                case Opcodes.IF_ACMPEQ:
                    if2("IF_ACMPEQ");
                    break;
                case Opcodes.IF_ACMPNE:
                    if2("IF_ACMPNE");
                    break;
                case Opcodes.IF_ICMPEQ:
                    if2("IF_ICMPEQ");
                    break;
                case Opcodes.IF_ICMPGE:
                    if2("IF_ICMPGE");
                    break;
                case Opcodes.IF_ICMPGT:
                    if2("IF_ICMPGT");
                    break;
                case Opcodes.IF_ICMPLE:
                    if2("IF_ICMPLE");
                    break;
                case Opcodes.IF_ICMPLT:
                    if2("IF_ICMPLT");
                    break;
                case Opcodes.IF_ICMPNE:
                    if2("IF_ICMPNE");
                    break;
                default:
                    throw new UnsupportedOperationException("" + opcode);
                }
                block.conditionalGoto(label);
            }

            private void if1(String name) {
                block.addOp(new Transform(lineNumber, name, JavaType.INT, null, null));
            }

            private void if2(String name) {
                block.addOp(new Transform(lineNumber, name, JavaType.INT, JavaType.INT, null));
            }
        });
    }
}

From source file:com.mebigfatguy.junitflood.jvm.OperandStack.java

License:Apache License

public void performJumpInsn(int opcode, Label label) {
    switch (opcode) {
    case Opcodes.IFEQ:
    case Opcodes.IFNE:
    case Opcodes.IFLT:
    case Opcodes.IFGE:
    case Opcodes.IFGT:
    case Opcodes.IFLE:
    case Opcodes.IFNULL:
    case Opcodes.IFNONNULL:
        pop();//from w  w w  .  j  a  va 2s .  c o m
        break;

    case Opcodes.IF_ICMPEQ:
    case Opcodes.IF_ICMPNE:
    case Opcodes.IF_ICMPLT:
    case Opcodes.IF_ICMPGE:
    case Opcodes.IF_ICMPGT:
    case Opcodes.IF_ICMPLE:
    case Opcodes.IF_ACMPEQ:
    case Opcodes.IF_ACMPNE:
        pop2();
        break;

    case Opcodes.GOTO:
        //nop
        break;

    case Opcodes.JSR:
        //nop -- a fudge
        break;
    }
}

From source file:com.offbynull.coroutines.instrumenter.Instrumenter.java

License:Open Source License

/**
 * Instruments a class.//w  w w.j ava 2s  . c  o  m
 * @param input class file contents
 * @return instrumented class
 * @throws IllegalArgumentException if the class could not be instrumented for some reason
 * @throws NullPointerException if any argument is {@code null}
 */
public byte[] instrument(byte[] input) {
    Validate.notNull(input);
    Validate.isTrue(input.length > 0);

    // Read class as tree model -- because we're using SimpleClassNode, JSR blocks get inlined
    ClassReader cr = new ClassReader(input);
    ClassNode classNode = new SimpleClassNode();
    cr.accept(classNode, 0);

    // Is this class an interface? if so, skip it
    if ((classNode.access & Opcodes.ACC_INTERFACE) == Opcodes.ACC_INTERFACE) {
        return input.clone();
    }

    // Has this class already been instrumented? if so, skip it
    if (classNode.interfaces.contains(INSTRUMENTED_CLASS_TYPE.getInternalName())) {
        return input.clone();
    }

    // Find methods that need to be instrumented. If none are found, skip
    List<MethodNode> methodNodesToInstrument = findMethodsWithParameter(classNode.methods,
            CONTINUATION_CLASS_TYPE);
    if (methodNodesToInstrument.isEmpty()) {
        return input.clone();
    }

    // Add the "Instrumented" interface to this class so if we ever come back to it, we can skip it
    classNode.interfaces.add(INSTRUMENTED_CLASS_TYPE.getInternalName());

    // Instrument each method that was returned
    for (MethodNode methodNode : methodNodesToInstrument) {
        // Check if method is constructor -- we cannot instrument constructor
        Validate.isTrue(!"<init>".equals(methodNode.name), "Instrumentation of constructors not allowed");

        // Check for JSR blocks -- Emitted for finally blocks in older versions of the JDK. Should never happen since we already inlined
        // these blocks before coming to this point. This is a sanity check.
        Validate.isTrue(searchForOpcodes(methodNode.instructions, Opcodes.JSR).isEmpty(),
                "JSR instructions not allowed");

        // Find invocations of continuation points
        List<AbstractInsnNode> suspendInvocationInsnNodes = findInvocationsOf(methodNode.instructions,
                CONTINUATION_SUSPEND_METHOD);
        List<AbstractInsnNode> invokeInvocationInsnNodes = findInvocationsWithParameter(methodNode.instructions,
                CONTINUATION_CLASS_TYPE);

        // If there are no continuation points, we don't need to instrument this method. It'll be like any other normal method
        // invocation because it won't have the potential to pause or call in to another method that may potentially pause.
        if (suspendInvocationInsnNodes.isEmpty() && invokeInvocationInsnNodes.isEmpty()) {
            continue;
        }

        // Check for continuation points that use invokedynamic instruction, which are currently only used by lambdas. See comments in
        // validateNoInvokeDynamic to see why we need to do this.
        validateNoInvokeDynamic(suspendInvocationInsnNodes);
        validateNoInvokeDynamic(invokeInvocationInsnNodes);

        // Analyze method
        Frame<BasicValue>[] frames;
        try {
            frames = new Analyzer<>(new SimpleVerifier(classRepo)).analyze(classNode.name, methodNode);
        } catch (AnalyzerException ae) {
            throw new IllegalArgumentException("Analyzer failed to analyze method", ae);
        }

        // Manage arguments and additional local variables that we need for instrumentation
        int contArgIdx = getLocalVariableIndexOfContinuationParameter(methodNode);

        VariableTable varTable = new VariableTable(classNode, methodNode);
        Variable contArg = varTable.getArgument(contArgIdx); // Continuation argument
        Variable methodStateVar = varTable.acquireExtra(MethodState.class); // var shared between monitor and flow instrumentation
        Variable tempObjVar = varTable.acquireExtra(Object.class); // var shared between monitor and flow instrumentation

        // Generate code to deal with suspending around synchronized blocks
        MonitorInstrumentationVariables monitorInstrumentationVariables = new MonitorInstrumentationVariables(
                varTable, methodStateVar, tempObjVar);
        MonitorInstrumentationInstructions monitorInstrumentationLogic = new MonitorInstrumentationGenerator(
                methodNode, monitorInstrumentationVariables).generate();

        // Generate code to deal with flow control (makes use of some of the code generated in monitorInstrumentationLogic)
        FlowInstrumentationVariables flowInstrumentationVariables = new FlowInstrumentationVariables(varTable,
                contArg, methodStateVar, tempObjVar);
        FlowInstrumentationInstructions flowInstrumentationInstructions = new FlowInstrumentationGenerator(
                methodNode, suspendInvocationInsnNodes, invokeInvocationInsnNodes, frames,
                monitorInstrumentationLogic, flowInstrumentationVariables).generate();

        // Apply generated code
        applyInstrumentationLogic(methodNode, flowInstrumentationInstructions, monitorInstrumentationLogic);
    }

    // Write tree model back out as class
    ClassWriter cw = new SimpleClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES, classRepo);
    classNode.accept(cw);
    return cw.toByteArray();
}

From source file:com.offbynull.coroutines.instrumenter.MethodAnalyzer.java

License:Open Source License

public MethodAttributes analyze(ClassNode classNode, MethodNode methodNode, InstrumentationSettings settings) {
    ///////////////////////////////////////////////////////////////////////////////////////////
    // VALIDATE INPUTS
    ///////////////////////////////////////////////////////////////////////////////////////////

    Validate.notNull(classNode);//from   w  w w  . j  a v  a 2  s .  c  om
    Validate.notNull(methodNode);
    Validate.notNull(settings);

    // Sanity check to make sure class
    Validate.isTrue(classNode.methods.contains(methodNode), "Method does not belong to class");

    // Check if method is constructor -- we cannot instrument constructor
    Validate.isTrue(!"<init>".equals(methodNode.name), "Instrumentation of constructors not allowed");

    // Check for JSR blocks -- Emitted for finally blocks in older versions of the JDK. Should never happen since we already inlined
    // these blocks before coming to this point. This is a sanity check.
    Validate.isTrue(searchForOpcodes(methodNode.instructions, Opcodes.JSR).isEmpty(),
            "JSR instructions not allowed");

    ///////////////////////////////////////////////////////////////////////////////////////////
    // FIND SUSPEND / CONTINUATION INVOCATIONS + ALSO FIND SYNCHRONIZATION INSTRUCTIONS
    ///////////////////////////////////////////////////////////////////////////////////////////

    // Find invocations of continuation invocation/suspend
    List<AbstractInsnNode> suspendInvocationInsnNodes = findInvocationsOf(methodNode.instructions,
            CONTINUATION_SUSPEND_METHOD);
    List<AbstractInsnNode> contInvocationInsnNodes = findInvocationsWithParameter(methodNode.instructions,
            CONTINUATION_CLASS_TYPE);

    // If there are no continuation points, we don't need to instrument this method. It'll be like any other normal method
    // invocation because it won't have the potential to pause or call in to another method that may potentially pause.
    if (suspendInvocationInsnNodes.isEmpty() && contInvocationInsnNodes.isEmpty()) {
        return null;
    }

    // Check for continuation points that use invokedynamic instruction, which are currently only used by lambdas. See comments in
    // validateNoInvokeDynamic to see why we need to do this.
    validateNoInvokeDynamic(suspendInvocationInsnNodes);
    validateNoInvokeDynamic(contInvocationInsnNodes);

    // Find MONITORENTER/MONITOREXIT instructions
    List<AbstractInsnNode> monitorInsnNodes = searchForOpcodes(methodNode.instructions, Opcodes.MONITORENTER,
            Opcodes.MONITOREXIT);

    ///////////////////////////////////////////////////////////////////////////////////////////
    // COMPUTE FRAMES FOR INSTRUCTIONS
    ///////////////////////////////////////////////////////////////////////////////////////////

    // Compute frames for each instruction in the method
    Frame<BasicValue>[] frames;
    try {
        frames = new Analyzer<>(new SimpleVerifier(classInfoRepo)).analyze(classNode.name, methodNode);
    } catch (AnalyzerException ae) {
        throw new IllegalArgumentException("Analyzer failed to analyze method", ae);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // CREATE SUSPEND/CONTINUATION/SYNCHRONIZATION OBJECTS
    ///////////////////////////////////////////////////////////////////////////////////////////

    List<ContinuationPoint> continuationPoints = new LinkedList<>();
    // Create SuspendContinuationPoint objects for suspend points

    for (AbstractInsnNode suspendInvocationInsnNode : suspendInvocationInsnNodes) {
        int instructionIndex = methodNode.instructions.indexOf(suspendInvocationInsnNode);
        Frame<BasicValue> frame = frames[instructionIndex];

        LineNumberNode lineNumberNode = findLineNumberForInstruction(methodNode.instructions,
                suspendInvocationInsnNode);
        Integer lineNumber = lineNumberNode != null ? lineNumberNode.line : null;

        SuspendContinuationPoint suspendPoint = new SuspendContinuationPoint(lineNumber,
                (MethodInsnNode) suspendInvocationInsnNode, frame);
        continuationPoints.add(suspendPoint);
    }

    // Create NormalInvokeContinuationPoint / TryCatchInvokeContinuationPoint objects for suspend points
    for (AbstractInsnNode contInvocationInsnNode : contInvocationInsnNodes) {
        int instructionIndex = methodNode.instructions.indexOf(contInvocationInsnNode);
        boolean withinTryCatch = findTryCatchBlockNodesEncompassingInstruction(methodNode.instructions,
                methodNode.tryCatchBlocks, contInvocationInsnNode).size() > 0;
        Frame<BasicValue> frame = frames[instructionIndex];

        LineNumberNode lineNumberNode = findLineNumberForInstruction(methodNode.instructions,
                contInvocationInsnNode);
        Integer lineNumber = lineNumberNode != null ? lineNumberNode.line : null;

        ContinuationPoint continuationPoint;
        if (withinTryCatch) {
            continuationPoint = new TryCatchInvokeContinuationPoint(lineNumber,
                    (MethodInsnNode) contInvocationInsnNode, frame);
        } else {
            continuationPoint = new NormalInvokeContinuationPoint(lineNumber,
                    (MethodInsnNode) contInvocationInsnNode, frame);
        }
        continuationPoints.add(continuationPoint);
    }

    // Create SynchronizationPoint objects for MONITORENTER/MONITOREXIT opcodes
    List<SynchronizationPoint> synchPoints = new LinkedList<>();
    for (AbstractInsnNode monitorInsnNode : monitorInsnNodes) {
        int instructionIndex = methodNode.instructions.indexOf(monitorInsnNode);
        Frame<BasicValue> frame = frames[instructionIndex];

        SynchronizationPoint synchPoint = new SynchronizationPoint((InsnNode) monitorInsnNode, frame);
        synchPoints.add(synchPoint);
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // DETERMINE TYPES RETURNED FROM SUSPEND / CONTINUATION POINTS
    ///////////////////////////////////////////////////////////////////////////////////////////

    // For each non-suspend invocation node found, see what the return type is and figure out if it's in a try/catch block.
    //
    // The return type scanning is needed because the instrumenter needs to temporarily cache the results of the invocation. The
    // variable slots for these caches are assigned lower on in the code.
    //
    // The try/catch information is needed because the instrumenter needs to temporarily cache a throwable if the invocation throws one.
    // The variable slot for the throwable is assigned lower on in the code.
    TypeTracker invocationReturnTypes = new TypeTracker();
    boolean invocationFoundWrappedInTryCatch = false;
    for (AbstractInsnNode invokeInsnNode : contInvocationInsnNodes) {
        if (findTryCatchBlockNodesEncompassingInstruction(methodNode.instructions, methodNode.tryCatchBlocks,
                invokeInsnNode).size() > 0) {
            invocationFoundWrappedInTryCatch = true;
        }

        Type returnType = getReturnTypeOfInvocation(invokeInsnNode);
        if (returnType.getSort() != Type.VOID) {
            invocationReturnTypes.trackType(returnType);
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // DETERMINE TYPES ON THE LOCAL VARIABLES TABE AT SUSPEND / CONTINUATION POINTS
    ///////////////////////////////////////////////////////////////////////////////////////////

    // For each invocation node found, see whats on the locals.
    //
    // We need on scan the types on the locals because the instrumenter needs to know which extra variable slots to allot to the
    // storage containers for those types. The variable slots for these storage containers are assigned lower on in the code.
    TypeTracker localsTypes = new TypeTracker();
    for (AbstractInsnNode invokeInsnNode : union(contInvocationInsnNodes, suspendInvocationInsnNodes)) {
        int instructionIndex = methodNode.instructions.indexOf(invokeInsnNode);
        Frame<BasicValue> frame = frames[instructionIndex];

        for (int i = 0; i < frame.getLocals(); i++) {
            BasicValue basicValue = frame.getLocal(i);
            Type type = basicValue.getType();

            // If type == null, basicValue is pointing to uninitialized var -- basicValue.toString() will return '.'. This means that
            // this slot contains nothing to save. We don't store anything in this case so skip this slot if we encounter it.
            //
            // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would
            // 'raise' the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null
            // at this point in the code so we can avoid saving it. When we load it back up, we can simply push a null in to that slot,
            // thereby keeping the same 'Lnull;' type.
            if (type == null || "Lnull;".equals(type.getDescriptor())) {
                continue;
            }

            localsTypes.trackType(type);
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // DETERMINE TYPES ON THE OPERAND STACK AT SUSPEND / CONTINUATION POINTS
    ///////////////////////////////////////////////////////////////////////////////////////////

    // For each invocation node found, see whats on the operand stack.
    //
    // We need on scan the types on the operand stack because the instrumenter needs to know which extra variable slots to allot to the
    // storage containers for those types. The variable slots for these storage containers are assigned lower on in the code.
    TypeTracker operandStackTypes = new TypeTracker();
    for (AbstractInsnNode invokeInsnNode : union(contInvocationInsnNodes, suspendInvocationInsnNodes)) {
        int instructionIndex = methodNode.instructions.indexOf(invokeInsnNode);
        Frame<BasicValue> frame = frames[instructionIndex];

        for (int i = 0; i < frame.getStackSize(); i++) {
            BasicValue basicValue = frame.getStack(i);
            Type type = basicValue.getType();

            // If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would
            // 'raise' the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null
            // at this point in the code so we can avoid saving it. When we load it back up, we can simply push a null in to that slot,
            // thereby keeping the same 'Lnull;' type.
            if ("Lnull;".equals(type.getDescriptor())) {
                continue;
            }

            operandStackTypes.trackType(type);
        }
    }

    ///////////////////////////////////////////////////////////////////////////////////////////
    // DETERMINE WHICH INDEX IN LOCAL VARIABLE TABLE CONTAINS CONTINUATION OBJECT
    ///////////////////////////////////////////////////////////////////////////////////////////

    // Find index of continuation object
    int contArgIdx = getLocalVariableIndexOfContinuationParameter(methodNode);

    ///////////////////////////////////////////////////////////////////////////////////////////
    // CALCULATE EXTRA VARIABLES REQUIRED BY INSTRUMENTATION
    ///////////////////////////////////////////////////////////////////////////////////////////

    VariableTable varTable = new VariableTable(classNode, methodNode);

    // Create variable for the continuation object passed in as arg + variable for storing/loading method state
    Variable continuationArgVar = varTable.getArgument(contArgIdx);
    Variable methodStateVar = varTable.acquireExtra(MethodState.class);
    CoreVariables coreVars = new CoreVariables(continuationArgVar, methodStateVar);

    // Create variables for storing/loading locals -- only create ones we need
    StorageVariables localsStorageVars = allocateStorageVariableSlots(varTable, localsTypes);

    // Create variables for storing/loading operand stack -- only create ones we need
    StorageVariables stackStorageVars = allocateStorageVariableSlots(varTable, operandStackTypes);

    // Create variables to locals and operand stack storage containers -- these must exist
    StorageContainerVariables storageContainerVars = allocateStorageContainerVariableSlots(varTable);

    // Create variables to cache return values and thrown exceptions of invocations -- only create ones we need
    CacheVariables cacheVars = allocateCacheVariableSlots(varTable, invocationReturnTypes,
            invocationFoundWrappedInTryCatch);

    // Create variables to for holding on to monitors -- only create if we need them
    LockVariables lockVars = allocateLockVariableSlots(varTable, !synchPoints.isEmpty());

    ///////////////////////////////////////////////////////////////////////////////////////////
    // RETURN RESULTS OF ANALYSIS
    ///////////////////////////////////////////////////////////////////////////////////////////

    MethodSignature signature = new MethodSignature(classNode.name, methodNode.name,
            Type.getMethodType(methodNode.desc));

    return new MethodAttributes(signature, settings, continuationPoints, synchPoints, coreVars, cacheVars,
            storageContainerVars, localsStorageVars, stackStorageVars, lockVars);
}

From source file:com.trigersoft.jaque.expression.ExpressionMethodVisitor.java

License:Apache License

@Override
public void visitJumpInsn(int opcode, Label label) {
    int etype;/*from   w  w w  . j  a  v a  2 s .co  m*/
    switch (opcode) {
    case Opcodes.GOTO:

        go(label);

        return;
    default:
    case Opcodes.JSR:
        throw notLambda(opcode);
    case Opcodes.IFEQ:
        etype = ExpressionType.NotEqual; // Equal
        pushZeroConstantOrReduce();
        break;
    case Opcodes.IFNE:
        etype = ExpressionType.Equal; // NotEqual
        pushZeroConstantOrReduce();
        break;
    case Opcodes.IFLT:
        etype = ExpressionType.GreaterThanOrEqual; // LessThan
        pushZeroConstantOrReduce();
        break;
    case Opcodes.IFGE:
        etype = ExpressionType.LessThan; // GreaterThanOrEqual
        pushZeroConstantOrReduce();
        break;
    case Opcodes.IFGT:
        etype = ExpressionType.LessThanOrEqual; // GreaterThan
        pushZeroConstantOrReduce();
        break;
    case Opcodes.IFLE:
        etype = ExpressionType.GreaterThan; // LessThanOrEqual
        pushZeroConstantOrReduce();
        break;
    case Opcodes.IF_ICMPEQ:
    case Opcodes.IF_ACMPEQ: // ??
        etype = ExpressionType.NotEqual; // Equal
        break;
    case Opcodes.IF_ICMPNE:
    case Opcodes.IF_ACMPNE: // ??
        etype = ExpressionType.Equal; // NotEqual
        break;
    case Opcodes.IF_ICMPLT:
        etype = ExpressionType.GreaterThanOrEqual; // LessThan
        break;
    case Opcodes.IF_ICMPGE:
        etype = ExpressionType.LessThan; // GreaterThanOrEqual
        break;
    case Opcodes.IF_ICMPGT:
        etype = ExpressionType.LessThanOrEqual; // GreaterThan
        break;
    case Opcodes.IF_ICMPLE:
        etype = ExpressionType.GreaterThan; // LessThanOrEqual
        break;
    case Opcodes.IFNULL:
    case Opcodes.IFNONNULL:
        Expression e = Expression.isNull(_exprStack.pop());
        if (opcode == Opcodes.IFNULL) // IFNONNULL
            e = Expression.logicalNot(e);

        branch(label, e);

        return;
    }

    Expression second = _exprStack.pop();
    Expression first = _exprStack.pop();
    Expression e = Expression.binary(etype, first, second);

    branch(label, e);
}

From source file:com.xruby.compiler.codegen.RubyCompilerImpl.java

License:BSD License

public Object visitPrepareEnsure1() {
    Label label = new Label();
    MethodGenerator mg = cg_.getMethodGenerator();
    mg.visitJumpInsn(Opcodes.JSR, mg.getEnsureLabelManager().getCurrentFinally());
    return label;
}

From source file:com.xruby.compiler.codegen.RubyCompilerImpl.java

License:BSD License

public void visitEnsure(int exception_var) {
    if (exception_var >= 0) {
        MethodGenerator mg = cg_.getMethodGenerator();
        Label l = mg.getEnsureLabelManager().getCurrentFinally();
        if (null != l) {
            mg.visitJumpInsn(Opcodes.JSR, l);
        }//from www . j a  va2 s .  co  m
        mg.loadLocal(exception_var);
        mg.throwException();
    } else {
        invokeFinallyIfExist();
    }
}