Example usage for org.objectweb.asm Opcodes GOTO

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

Introduction

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

Prototype

int GOTO

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

Click Source Link

Usage

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

private static boolean encodeThenStatementElseStatement(Label trueContinuation, Label falseContinuation,
        JavaStatement thenStatement, JavaStatement elseStatement, GenerationContext context)
        throws JavaGenerationException {

    MethodVisitor mv = context.getMethodVisitor();

    if (trueContinuation != null) {
        mv.visitLabel(trueContinuation);
    }// w w  w  . j  av  a 2 s  . c  o  m

    //in general the "then" part will have its own inner scope, but we optimize this out in the case of ExpressionStatements which
    //can't introduce new variables.
    GenerationContext thenContext = (thenStatement instanceof JavaStatement.ExpressionStatement) ? context
            : new GenerationContext(context);

    boolean thenIsTerminating = encodeStatement(thenStatement, thenContext);
    context.addJumpReturnLabelInfo(thenContext);

    if (elseStatement.emptyStatement()) {
        //don't bother to encode the goto skipping over the else part if there is not else part.

        mv.visitLabel(falseContinuation);

        //the if-then-else is not terminating, because the else part, which is just {}, is not terminating
        return false;
    }

    Label label2 = null;
    if (!thenIsTerminating) {
        label2 = new Label();
        context.addStatementJumpLabel(label2);

        mv.visitJumpInsn(Opcodes.GOTO, label2);
    }

    mv.visitLabel(falseContinuation);

    //in general the "else" part will have its own inner scope, but we optimize this out in the case of ExpressionStatements which
    //can't introduce new variables.
    GenerationContext elseContext = (elseStatement instanceof JavaStatement.ExpressionStatement) ? context
            : new GenerationContext(context);
    boolean elseIsTerminating = encodeStatement(elseStatement, elseContext);
    context.addJumpReturnLabelInfo(elseContext);

    if (!thenIsTerminating) {
        mv.visitLabel(label2);
    }

    return thenIsTerminating && elseIsTerminating;
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

private static boolean encodeTryCatchStatement(JavaStatement.Block block, GenerationContext context)
        throws JavaGenerationException {

    MethodVisitor mv = context.getMethodVisitor();

    List<JavaExceptionHandler> exceptionHandlers = block.getExceptionHandlers();

    if (exceptionHandlers.isEmpty()) {
        throw new IllegalStateException();
    }//from   w w  w. j  a v  a  2  s  .  co m

    // Spawn a child context for the try block.
    GenerationContext tryBlockContext = new GenerationContext(context);

    boolean isTerminating = false; // starts out false (for the case with no statements..)

    Label tryStartLabel = new Label();
    mv.visitLabel(tryStartLabel);

    // Append the instructions comprising the block's component statements.
    int nStatements = block.getNBlockStatements();
    for (int i = 0; i < nStatements; i++) {
        JavaStatement blockStatement = block.getNthBlockStatement(i);

        // skip comments.
        if (blockStatement instanceof Comment) {
            continue;
        }

        // is terminating if the last statement is terminating. 
        isTerminating = encodeStatement(blockStatement, tryBlockContext);
        context.addJumpReturnLabelInfo(tryBlockContext);
    }

    // Add an instruction to jump to after the exception handlers, if the statement block isn't terminating.
    Label tryCatchEndLabel = new Label();
    context.addStatementJumpLabel(tryCatchEndLabel);
    if (!isTerminating) {
        mv.visitJumpInsn(Opcodes.GOTO, tryCatchEndLabel);
    }

    Label tryEndLabel = new Label();
    mv.visitLabel(tryEndLabel);

    // Add exception handlers as necessary.      

    // Now set handlers to handle any exceptions.
    for (int i = 0, nExceptionHandlers = exceptionHandlers.size(); i < nExceptionHandlers; ++i) {

        JavaExceptionHandler eh = exceptionHandlers.get(i);

        JavaTypeName exceptionType = JavaTypeName.make(eh.getExceptionClass()); // exception class is a non-array reference type.  

        //encode the start of the catch block.
        Label catchLabel = new Label();
        mv.visitLabel(catchLabel);

        // Create a child context for the catch block.
        GenerationContext catchContext = new GenerationContext(context);

        // The thrown exception object will be the only item on the stack.  
        // Store it into a new local variable.
        String exceptionVarName = eh.getExceptionVarName();
        int exceptionVarIndex = catchContext.addLocalVar(exceptionVarName, exceptionType);
        mv.visitVarInsn(Opcodes.ASTORE, exceptionVarIndex);

        boolean catchIsTerminating = encodeStatement(eh.getHandlerCode(), catchContext);
        context.addJumpReturnLabelInfo(catchContext);

        if (!catchIsTerminating) {
            mv.visitJumpInsn(Opcodes.GOTO, tryCatchEndLabel);
        }

        // In the end, we're only terminating if all the catch blocks are terminating.
        isTerminating &= catchIsTerminating;

        //encode the try/catch block. This can be done in any order, any time after all labels passed as arguments have been visited,
        //  between visitCode() and visitMaxs().
        encodeTryCatchBlock(tryStartLabel, tryEndLabel, catchLabel, exceptionType, tryBlockContext);
    }

    //mark the end of the whole try/catch code
    mv.visitLabel(tryCatchEndLabel);

    return isTerminating;
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

private static boolean encodeUnconditionalLoop(JavaStatement.UnconditionalLoop ul, GenerationContext context)
        throws JavaGenerationException {

    //implemented as:
    //label label1:
    //{ body statements}
    //goto label1

    MethodVisitor mv = context.getMethodVisitor();
    Label label1 = new Label();
    mv.visitLabel(label1);/*from w w w . j  a  v  a  2  s  .  c om*/

    context.addStatementJumpLabel(ul.getLabel(), label1);

    //the body defines a new scope.
    GenerationContext bodyContext = new GenerationContext(context);

    boolean bodyIsTerminating = encodeStatement(ul.getBody(), bodyContext);
    context.addJumpReturnLabelInfo(bodyContext);

    if (!bodyIsTerminating) {
        mv.visitJumpInsn(Opcodes.GOTO, label1);
    }

    return true;
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

/**
 * Encode a method invocation that is wrapped in a synchronized block.
 *   See Sun bug id #4414101 for a discussion of this generated code.
 * /*from   ww w .jav  a2  s  . c  om*/
 * @param smi - the SynchronizedMethodInvocation object.
 * @param context - the context of the code generation.
 * @return - true if the SynchronizedMethodInvocation is terminating.
 * @throws JavaGenerationException
 */
private static boolean encodeSynchronizedMethodInvocation(JavaStatement.SynchronizedMethodInvocation smi,
        GenerationContext context) throws JavaGenerationException {

    MethodVisitor mv = context.getMethodVisitor();

    // Get the JavaExpression for the object to synchronize on and generate the bytecode. 
    JavaExpression objectToSynchOn = smi.getSynchronizingObject();
    encodeExpr(objectToSynchOn, context);

    // The object to synchronize on is now on the stack.  Duplicate it, 
    // move one to storage as a local variable, and to MONITORENTER on the other. 
    mv.visitInsn(Opcodes.DUP);

    int mutexIndex = context.addLocalVar("$mutex", JavaTypeName.OBJECT);
    mv.visitVarInsn(Opcodes.ASTORE, mutexIndex);

    mv.visitInsn(Opcodes.MONITORENTER);

    // We need to wrap the method invocation in a try/catch block so 
    // the monitor can be exited properly if the method invocation throws
    // an exception.
    Label tryCatchStart = new Label();
    mv.visitLabel(tryCatchStart);

    // Note: if this is generalized to handle any synchronized statement (for example, a synchronized block), 
    //   then the scope of entries in the exception table here will have to be modified to exclude return instructions.
    //   See encodeTryCatchStatement() for how to do this.
    //   Here, the only statement in the try block is a single expressionStatement, which has no return instructions, 
    //     so we don't have to worry about handling this case.

    // Get the method invocation and generate the corresponding bytecode.
    MethodInvocation methodInvocation = smi.getMethodInvocation();
    encodeExpr(methodInvocation, context);

    // Load the mutex object back onto the stack and do MonitorExit.
    mv.visitVarInsn(Opcodes.ALOAD, mutexIndex);
    mv.visitInsn(Opcodes.MONITOREXIT);

    // Label the end of the try block around the method invocation.
    Label tryEnd = new Label();
    mv.visitLabel(tryEnd);

    // At this point we want to code an instruction to jump past the exception handling
    // code.
    Label tryCatchEnd = new Label();
    mv.visitJumpInsn(Opcodes.GOTO, tryCatchEnd);

    // Label the start of the exception handling code.
    Label catchStart = new Label();
    mv.visitLabel(catchStart);

    // The exception is on the stack.  Store it as a local.
    int exceptionIndex = context.addLocalVar("exception", JavaTypeName.OBJECT);
    mv.visitVarInsn(Opcodes.ASTORE, exceptionIndex);

    // Retrieve the mutex object and do MONITOREXIT.
    mv.visitVarInsn(Opcodes.ALOAD, mutexIndex);
    mv.visitInsn(Opcodes.MONITOREXIT);

    // Label the end of the exception handling code that deals with the monitor.
    Label exceptionMonitorExitEnd = new Label();
    mv.visitLabel(exceptionMonitorExitEnd);

    // Retrieve the exception and throw it.
    mv.visitVarInsn(Opcodes.ALOAD, exceptionIndex);
    mv.visitInsn(Opcodes.ATHROW);

    // Vist the label to mark the end of the try/catch.
    mv.visitLabel(tryCatchEnd);

    // Set up the try/catch block to catch exceptions thrown by the method invocation
    // and handle exiting the monitor.
    mv.visitTryCatchBlock(tryCatchStart, tryEnd, catchStart, null);

    // Set up a try catch block so that if an exception is thrown by trying to exit 
    // the monitor in the case of an exception from the method invocation we will keep trying to 
    // exit the monitor.
    mv.visitTryCatchBlock(catchStart, exceptionMonitorExitEnd, catchStart, null);

    return false;
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

private static boolean encodeLabelledContinue(JavaStatement.LabelledContinue lc, GenerationContext context) {

    MethodVisitor mv = context.getMethodVisitor();
    Label label = context.getNamedStatementJumpLabel(lc.getLabel());
    if (label == null) {
        throw new IllegalStateException("label to continue to cannot be null.");
    }/*from   ww  w .j a  v a2s.  com*/

    // Label the goto instruction and the instruction after the goto.
    // This instruction will be excluded from relevant ranges covered in the exception table.

    // Add a label for the goto instruction.
    Label gotoLabel = new Label();
    mv.visitLabel(gotoLabel);

    // Visit the goto instruction.
    mv.visitJumpInsn(Opcodes.GOTO, label);

    // Add a label following the goto instruction.
    Label afterGotoLabel = new Label();
    mv.visitLabel(afterGotoLabel);

    context.addJumpReturnLabelInfo(new JumpReturnLabelInfo(gotoLabel, afterGotoLabel, label));

    return true;
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

private static JavaTypeName encodeThenTrueElseFalse(Label trueContinuation, Label falseContinuation,
        GenerationContext context) {//from  w  w w .java2 s.co m

    MethodVisitor mv = context.getMethodVisitor();

    mv.visitLabel(trueContinuation);
    mv.visitInsn(Opcodes.ICONST_1);
    Label nextLabel = new Label();
    mv.visitJumpInsn(Opcodes.GOTO, nextLabel);
    mv.visitLabel(falseContinuation);
    mv.visitInsn(Opcodes.ICONST_0);
    mv.visitLabel(nextLabel);

    return JavaTypeName.BOOLEAN;
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

private static JavaTypeName encodeThenExprElseExpr(Label trueContinuation, Label falseContinuation,
        JavaExpression thenExpr, JavaExpression elseExpr, GenerationContext context)
        throws JavaGenerationException {

    MethodVisitor mv = context.getMethodVisitor();

    if (trueContinuation != null) {
        mv.visitLabel(trueContinuation);
    }//from  w  w w .j  a  v  a 2s . co  m

    //encode the then-part expression
    JavaTypeName thenType = encodeExpr(thenExpr, context);
    Label nextLabel = new Label();
    mv.visitJumpInsn(Opcodes.GOTO, nextLabel);
    mv.visitLabel(falseContinuation);

    //encode the else-part expression
    JavaTypeName elseType = encodeExpr(elseExpr, context);
    mv.visitLabel(nextLabel);

    //The Java language specification section 15.25 defines the rules for the return types of ternary operators.
    //These are complicated, and we don't support this. The basic case supported is when both static types are the same.
    //There is a hack to support the case when the 2 types are different:
    //This case happens a bit in our code generation. The proper fix would be to not create this situation during code generation.

    if (thenType.equals(elseType)) {
        return thenType;

    } else if (thenType.equals(JavaTypeName.RTVALUE)) {
        //this is a hack, see the above comment
        return thenType;

    } else if (elseType.equals(JavaTypeName.RTVALUE)) {
        //this is a hack, see the above comment
        return elseType;

    } else {
        throw new JavaGenerationException(
                "The '?' operator must have then parts and else parts of exactly the same static types.");
    }
}

From source file:org.sonar.java.bytecode.cfg.BytecodeCFGBuilderTest.java

License:Open Source License

@Test
public void visited_label_should_be_assigned_to_true_successor() throws Exception {
    Label label0 = new Label();
    Label label1 = new Label();
    BytecodeCFG cfg = new Instructions().visitVarInsn(Opcodes.ALOAD, 0).visitJumpInsn(Opcodes.IFNULL, label0)
            .visitJumpInsn(Opcodes.IFEQ, label0).visitInsn(Opcodes.ICONST_0).visitJumpInsn(Opcodes.GOTO, label1)
            .visitLabel(label0).visitInsn(Opcodes.ICONST_1).visitLabel(label1).visitInsn(Opcodes.IRETURN).cfg();

    BytecodeCFG.Block block3 = cfg.blocks.get(3);
    assertThat(block3.terminator.opcode).isEqualTo(Opcodes.IFEQ);
    assertThat(block3.falseSuccessor()).isNotNull().isSameAs(cfg.blocks.get(4));
    assertThat(block3.trueSuccessor()).isNotNull().isSameAs(cfg.blocks.get(2));
    assertThat(block3.successors).hasSize(2);
    assertThat(block3.successors()).hasSize(2);
}

From source file:org.sonar.java.bytecode.cfg.BytecodeCFGBuilderTest.java

License:Open Source License

@Test
public void goto_successors() throws Exception {
    Label label0 = new Label();
    Label label1 = new Label();
    BytecodeCFG cfg = new Instructions().visitVarInsn(Opcodes.ALOAD, 0).visitJumpInsn(Opcodes.IFNULL, label0)
            .visitVarInsn(Opcodes.ALOAD, 0).visitJumpInsn(Opcodes.IFNULL, label1).visitVarInsn(Opcodes.ALOAD, 0)
            .visitVarInsn(Opcodes.ALOAD, 0).visitJumpInsn(Opcodes.IFEQ, label0).visitInsn(Opcodes.ICONST_0)
            .visitJumpInsn(Opcodes.GOTO, label1).visitLabel(label0).visitInsn(Opcodes.ICONST_1)
            .visitLabel(label1).visitInsn(Opcodes.IRETURN).cfg();
    assertThat(cfg.blocks.get(6).successors).containsExactly(cfg.blocks.get(4));
}

From source file:org.sonar.java.bytecode.se.BytecodeEGWalkerExecuteTest.java

License:Open Source License

@Test
public void test_invalid_branch_instruction() {
    assertThatThrownBy(() -> walker.branchingState(new Instruction(Opcodes.GOTO), ProgramState.EMPTY_STATE))
            .isInstanceOf(IllegalStateException.class);
}