Example usage for org.objectweb.asm MethodVisitor visitJumpInsn

List of usage examples for org.objectweb.asm MethodVisitor visitJumpInsn

Introduction

In this page you can find the example usage for org.objectweb.asm MethodVisitor visitJumpInsn.

Prototype

public void visitJumpInsn(final int opcode, final Label label) 

Source Link

Document

Visits a jump instruction.

Usage

From source file:org.codehaus.groovy.classgen.asm.BinaryIntExpressionHelper.java

License:Apache License

/**
 * writes a std compare. This involves the tokens IF_ICMPEQ, IF_ICMPNE, 
 * IF_ICMPEQ, IF_ICMPNE, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE and IF_ICMPLT
 * @param type the token type/*from   ww  w . j  a  v a2  s .c  o m*/
 * @return true if a successful std compare write
 */
protected boolean writeStdCompare(int type, boolean simulate) {
    type = type - COMPARE_NOT_EQUAL;
    // look if really compare
    if (type < 0 || type > 7)
        return false;

    if (!simulate) {
        MethodVisitor mv = getController().getMethodVisitor();
        OperandStack operandStack = getController().getOperandStack();
        // operands are on the stack already
        int bytecode = stdCompareCodes[type];
        Label l1 = new Label();
        mv.visitJumpInsn(bytecode, l1);
        mv.visitInsn(ICONST_1);
        Label l2 = new Label();
        mv.visitJumpInsn(GOTO, l2);
        mv.visitLabel(l1);
        mv.visitInsn(ICONST_0);
        mv.visitLabel(l2);
        operandStack.replace(ClassHelper.boolean_TYPE, 2);
    }
    return true;
}

From source file:org.codehaus.groovy.classgen.asm.BinaryIntExpressionHelper.java

License:Apache License

/**
 * writes the spaceship operator, type should be COMPARE_TO
 * @param type the token type//from w w  w  .  j  a v a2s.  c  o m
 * @return true if a successful spaceship operator write
 */
protected boolean writeSpaceship(int type, boolean simulate) {
    if (type != COMPARE_TO)
        return false;
    /*  
       we will actually do
             
      (x < y) ? -1 : ((x == y) ? 0 : 1)
      which is the essence of what the call with Integers would do
      this compiles to something along
              
      <x>
      <y>
      IF_ICMPGE L1
      ICONST_M1
      GOTO L2
      L1
      <x>
      <y>
      IF_ICMPNE L3
      ICONST_0
      GOTO L2
      L3
      ICONST_1
      L2
              
      since the operators are already on the stack and we don't want
      to load them again, we will instead duplicate them. This will
      require some pop actions in the branches!
              
      DUP2          (operands: IIII) 
      IF_ICMPGE L1  (operands: II)
      ICONST_M1     (operands: III)
      GOTO L2
      L1
      -----         (operands: II)
      IF_ICMPNE L3  (operands: -)
      ICONST_0      (operands: I)
      GOTO L2
      L3
      - jump from L1 branch to here (operands: -)
      ICONST_1      (operands: I)
      L2  
      - if jump from GOTO L2 we have III, but need only I
      - if from L3 branch we get only I
              
      this means we have to pop of II before loading -1
              
    */
    if (!simulate) {
        MethodVisitor mv = getController().getMethodVisitor();
        // duplicate int arguments
        mv.visitInsn(DUP2);

        Label l1 = new Label();
        mv.visitJumpInsn(IF_ICMPGE, l1);
        // no jump, so -1, need to pop off surplus II
        mv.visitInsn(POP2);
        mv.visitInsn(ICONST_M1);
        Label l2 = new Label();
        mv.visitJumpInsn(GOTO, l2);

        mv.visitLabel(l1);
        Label l3 = new Label();
        mv.visitJumpInsn(IF_ICMPNE, l3);
        mv.visitInsn(ICONST_0);
        mv.visitJumpInsn(GOTO, l2);

        mv.visitLabel(l3);
        mv.visitInsn(ICONST_1);

        getController().getOperandStack().replace(ClassHelper.int_TYPE, 2);
    }
    return true;
}

From source file:org.codehaus.groovy.classgen.asm.BytecodeHelper.java

License:Apache License

/**
 * Negate a boolean on stack./*w w w  .  j  a  v a 2 s  .  c  om*/
 */
public static void negateBoolean(MethodVisitor mv) {
    // code to negate the primitive boolean
    Label endLabel = new Label();
    Label falseLabel = new Label();
    mv.visitJumpInsn(IFNE, falseLabel);
    mv.visitInsn(ICONST_1);
    mv.visitJumpInsn(GOTO, endLabel);
    mv.visitLabel(falseLabel);
    mv.visitInsn(ICONST_0);
    mv.visitLabel(endLabel);
}

From source file:org.codehaus.groovy.classgen.asm.BytecodeHelper.java

License:Apache License

/**
 * Converts a primitive type to boolean.
 *
 * @param mv method visitor// w  w w  . j ava2  s  .  co  m
 * @param type primitive type to convert
 */
public static void convertPrimitiveToBoolean(MethodVisitor mv, ClassNode type) {
    if (type == boolean_TYPE) {
        return;
    }
    // Special handling is done for floating point types in order to
    // handle checking for 0 or NaN values.
    if (type == double_TYPE) {
        convertDoubleToBoolean(mv);
        return;
    } else if (type == float_TYPE) {
        convertFloatToBoolean(mv);
        return;
    }
    Label trueLabel = new Label();
    Label falseLabel = new Label();
    // Convert long to int for IFEQ comparison using LCMP
    if (type == long_TYPE) {
        mv.visitInsn(LCONST_0);
        mv.visitInsn(LCMP);
    }
    // This handles byte, short, char and int
    mv.visitJumpInsn(IFEQ, falseLabel);
    mv.visitInsn(ICONST_1);
    mv.visitJumpInsn(GOTO, trueLabel);
    mv.visitLabel(falseLabel);
    mv.visitInsn(ICONST_0);
    mv.visitLabel(trueLabel);
}

From source file:org.codehaus.groovy.classgen.asm.BytecodeHelper.java

License:Apache License

private static void convertDoubleToBoolean(MethodVisitor mv) {
    Label trueLabel = new Label();
    Label falseLabel = new Label();
    Label falseLabelWithPop = new Label();
    mv.visitInsn(DUP2); // will need the extra for isNaN call if required
    mv.visitInsn(DCONST_0);//from w w w . j a v a  2  s.c  o m
    mv.visitInsn(DCMPL);
    mv.visitJumpInsn(IFEQ, falseLabelWithPop);
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "isNaN", "(D)Z", false);
    mv.visitJumpInsn(IFNE, falseLabel);
    mv.visitInsn(ICONST_1);
    mv.visitJumpInsn(GOTO, trueLabel);
    mv.visitLabel(falseLabelWithPop);
    mv.visitInsn(POP2);
    mv.visitLabel(falseLabel);
    mv.visitInsn(ICONST_0);
    mv.visitLabel(trueLabel);
}

From source file:org.codehaus.groovy.classgen.asm.BytecodeHelper.java

License:Apache License

private static void convertFloatToBoolean(MethodVisitor mv) {
    Label trueLabel = new Label();
    Label falseLabel = new Label();
    Label falseLabelWithPop = new Label();
    mv.visitInsn(DUP); // will need the extra for isNaN call if required
    mv.visitInsn(FCONST_0);/*from w ww .j  a va 2s  .  c  o  m*/
    mv.visitInsn(FCMPL);
    mv.visitJumpInsn(IFEQ, falseLabelWithPop);
    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "isNaN", "(F)Z", false);
    mv.visitJumpInsn(IFNE, falseLabel);
    mv.visitInsn(ICONST_1);
    mv.visitJumpInsn(GOTO, trueLabel);
    mv.visitLabel(falseLabelWithPop);
    mv.visitInsn(POP);
    mv.visitLabel(falseLabel);
    mv.visitInsn(ICONST_0);
    mv.visitLabel(trueLabel);
}

From source file:org.codehaus.groovy.classgen.asm.CallSiteWriter.java

License:Apache License

private void generateGetCallSiteArray() {
    int visibility = (controller.getClassNode() instanceof InterfaceHelperClassNode) ? MOD_PUBSS : MOD_PRIVSS;
    MethodVisitor mv = controller.getClassVisitor().visitMethod(visibility, GET_CALLSITE_METHOD,
            GET_CALLSITE_DESC, null, null);
    controller.setMethodVisitor(mv);// w w w  . ja va  2s .c o m
    mv.visitCode();
    mv.visitFieldInsn(GETSTATIC, controller.getInternalClassName(), "$callSiteArray",
            "Ljava/lang/ref/SoftReference;");
    Label l0 = new Label();
    mv.visitJumpInsn(IFNULL, l0);
    mv.visitFieldInsn(GETSTATIC, controller.getInternalClassName(), "$callSiteArray",
            "Ljava/lang/ref/SoftReference;");
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/ref/SoftReference", "get", "()Ljava/lang/Object;", false);
    mv.visitTypeInsn(CHECKCAST, "org/codehaus/groovy/runtime/callsite/CallSiteArray");
    mv.visitInsn(DUP);
    mv.visitVarInsn(ASTORE, 0);
    Label l1 = new Label();
    mv.visitJumpInsn(IFNONNULL, l1);
    mv.visitLabel(l0);
    mv.visitMethodInsn(INVOKESTATIC, controller.getInternalClassName(), "$createCallSiteArray",
            "()Lorg/codehaus/groovy/runtime/callsite/CallSiteArray;", false);
    mv.visitVarInsn(ASTORE, 0);
    mv.visitTypeInsn(NEW, "java/lang/ref/SoftReference");
    mv.visitInsn(DUP);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/ref/SoftReference", "<init>", "(Ljava/lang/Object;)V", false);
    mv.visitFieldInsn(PUTSTATIC, controller.getInternalClassName(), "$callSiteArray",
            "Ljava/lang/ref/SoftReference;");
    mv.visitLabel(l1);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, "org/codehaus/groovy/runtime/callsite/CallSiteArray", "array",
            "[Lorg/codehaus/groovy/runtime/callsite/CallSite;");
    mv.visitInsn(ARETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}

From source file:org.codehaus.groovy.classgen.asm.InvocationWriter.java

License:Apache License

private void makeMOPBasedConstructorCall(final List<ConstructorNode> constructors,
        final ConstructorCallExpression call, final ClassNode callNode) {
    MethodVisitor mv = controller.getMethodVisitor();
    OperandStack operandStack = controller.getOperandStack();
    call.getArguments().visit(controller.getAcg());
    // keep Object[] on stack
    mv.visitInsn(DUP);// w w  w .j av a  2 s . com
    // to select the constructor we need also the number of
    // available constructors and the class we want to make
    // the call on
    BytecodeHelper.pushConstant(mv, -1);
    controller.getAcg().visitClassExpression(new ClassExpression(callNode));
    operandStack.remove(1);
    // removes one Object[] leaves the int containing the
    // call flags and the constructor number
    selectConstructorAndTransformArguments.call(mv);
    //load "this"
    if (controller.isConstructor()) {
        mv.visitVarInsn(ALOAD, 0);
    } else {
        mv.visitTypeInsn(NEW, BytecodeHelper.getClassInternalName(callNode));
    }
    mv.visitInsn(SWAP);
    TreeMap<Integer, ConstructorNode> sortedConstructors = new TreeMap<>();
    for (ConstructorNode constructor : constructors) {
        String typeDescriptor = BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE,
                constructor.getParameters());
        int hash = BytecodeHelper.hashCode(typeDescriptor);
        ConstructorNode sameHashNode = sortedConstructors.put(hash, constructor);
        if (sameHashNode != null) {
            controller.getSourceUnit()
                    .addError(new SyntaxException(
                            "Unable to compile class " + controller.getClassNode().getName()
                                    + " due to hash collision in constructors",
                            call.getLineNumber(), call.getColumnNumber()));
        }
    }
    Label[] targets = new Label[constructors.size()];
    int[] indices = new int[constructors.size()];
    Iterator<Integer> hashIt = sortedConstructors.keySet().iterator();
    Iterator<ConstructorNode> constructorIt = sortedConstructors.values().iterator();
    for (int i = 0, n = targets.length; i < n; i += 1) {
        targets[i] = new Label();
        indices[i] = hashIt.next();
    }

    // create switch targets
    Label defaultLabel = new Label();
    Label afterSwitch = new Label();
    mv.visitLookupSwitchInsn(defaultLabel, indices, targets);
    for (Label target : targets) {
        mv.visitLabel(target);
        // to keep the stack height, we need to leave
        // one Object[] on the stack as last element. At the
        // same time, we need the Object[] on top of the stack
        // to extract the parameters.
        if (controller.isConstructor()) {
            // in this case we need one "this", so a SWAP will exchange
            // "this" and Object[], a DUP_X1 will then copy the Object[]
            /// to the last place in the stack:
            //     Object[],this -SWAP-> this,Object[]
            //     this,Object[] -DUP_X1-> Object[],this,Object[]
            mv.visitInsn(SWAP);
            mv.visitInsn(DUP_X1);
        } else {
            // in this case we need two "this" in between and the Object[]
            // at the bottom of the stack as well as on top for our invokeSpecial
            // So we do DUP_X1, DUP2_X1, POP
            //     Object[],this -DUP_X1-> this,Object[],this
            //     this,Object[],this -DUP2_X1-> Object[],this,this,Object[],this
            //     Object[],this,this,Object[],this -POP->  Object[],this,this,Object[]
            mv.visitInsn(DUP_X1);
            mv.visitInsn(DUP2_X1);
            mv.visitInsn(POP);
        }

        ConstructorNode cn = constructorIt.next();
        String descriptor = BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, cn.getParameters());

        // unwrap the Object[] and make transformations if needed
        // that means, to duplicate the Object[], make a cast with possible
        // unboxing and then swap it with the Object[] for each parameter
        // vargs need special attention and transformation though
        Parameter[] parameters = cn.getParameters();
        int lengthWithoutVargs = parameters.length;
        if (parameters.length > 0 && parameters[parameters.length - 1].getType().isArray()) {
            lengthWithoutVargs -= 1;
        }
        for (int p = 0; p < lengthWithoutVargs; p += 1) {
            loadAndCastElement(operandStack, mv, parameters, p);
        }
        if (parameters.length > lengthWithoutVargs) {
            ClassNode type = parameters[lengthWithoutVargs].getType();
            BytecodeHelper.pushConstant(mv, lengthWithoutVargs);
            controller.getAcg().visitClassExpression(new ClassExpression(type));
            operandStack.remove(1);
            castToVargsArray.call(mv);
            BytecodeHelper.doCast(mv, type);
        } else {
            // at the end we remove the Object[]
            // the vargs case simply the last swap so no pop is needed
            mv.visitInsn(POP);
        }
        // make the constructor call
        mv.visitMethodInsn(INVOKESPECIAL, BytecodeHelper.getClassInternalName(callNode), "<init>", descriptor,
                false);
        mv.visitJumpInsn(GOTO, afterSwitch);
    }
    mv.visitLabel(defaultLabel);
    // this part should never be reached!
    mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
    mv.visitInsn(DUP);
    mv.visitLdcInsn(
            "This class has been compiled with a super class which is binary incompatible with the current super class found on classpath. You should recompile this class with the new version.");
    mv.visitMethodInsn(INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>", "(Ljava/lang/String;)V",
            false);
    mv.visitInsn(ATHROW);
    mv.visitLabel(afterSwitch);

    // For a special constructor call inside a constructor we don't need
    // any result object on the stack, for outside the constructor we do.
    // to keep the stack height for the able we kept one object as dummy
    // result on the stack, which we can remove now if inside a constructor.
    if (!controller.isConstructor()) {
        // in case we are not in a constructor we have an additional
        // object on the stack, the result of our constructor call
        // which we want to keep, so we swap with the dummy object and
        // do normal removal of it. In the end, the call result will be
        // on the stack then
        mv.visitInsn(SWAP);
        operandStack.push(callNode); // for call result
    }
    mv.visitInsn(POP);
}

From source file:org.codehaus.groovy.classgen.asm.OptimizingStatementWriter.java

License:Apache License

private FastPathData writeGuards(final StatementMeta meta, final Statement statement) {
    if (fastPathBlocked || controller.isFastPath() || meta == null || !meta.optimize)
        return null;

    controller.getAcg().onLineNumber(statement, null);
    MethodVisitor mv = controller.getMethodVisitor();
    FastPathData fastPathData = new FastPathData();
    Label slowPath = new Label();

    for (int i = 0, n = guards.length; i < n; i += 1) {
        if (meta.involvedTypes[i]) {
            guards[i].call(mv);// w ww.j  a v  a 2  s .com
            mv.visitJumpInsn(IFEQ, slowPath);
        }
    }

    // meta class check with boolean holder
    String owner = BytecodeHelper.getClassInternalName(controller.getClassNode());
    MethodNode mn = controller.getMethodNode();
    if (mn != null) {
        mv.visitFieldInsn(GETSTATIC, owner, Verifier.STATIC_METACLASS_BOOL, "Z");
        mv.visitJumpInsn(IFNE, slowPath);
    }

    // standard metaclass check
    disabledStandardMetaClass.call(mv);
    mv.visitJumpInsn(IFNE, slowPath);

    // other guards here
    mv.visitJumpInsn(GOTO, fastPathData.pathStart);
    mv.visitLabel(slowPath);

    return fastPathData;
}

From source file:org.codehaus.groovy.classgen.asm.OptimizingStatementWriter.java

License:Apache License

private void writeFastPathPrelude(final FastPathData meta) {
    MethodVisitor mv = controller.getMethodVisitor();
    mv.visitJumpInsn(GOTO, meta.afterPath);
    mv.visitLabel(meta.pathStart);/*from   w w  w. j  av  a  2 s  . c o  m*/
    controller.switchToFastPath();
}