Example usage for org.objectweb.asm MethodVisitor visitLookupSwitchInsn

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

Introduction

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

Prototype

public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) 

Source Link

Document

Visits a LOOKUPSWITCH instruction.

Usage

From source file:com.sun.fortress.compiler.environments.TopLevelEnvGen.java

License:Open Source License

private static void putRawHelper(MethodVisitor mv, String className, EnvironmentClass environmentClass,
        Relation<String, Integer> hashCodeRelation, List<Integer> sortedCodes, Label notFound) {

    int[] codes = new int[sortedCodes.size()];
    Label[] labels = new Label[sortedCodes.size()];
    for (int i = 0; i < codes.length; i++) {
        codes[i] = sortedCodes.get(i);/* w ww. ja  v a2 s .com*/
        Label label = new Label();
        labels[i] = label;
    }
    mv.visitVarInsn(Opcodes.ILOAD, 3);
    mv.visitLookupSwitchInsn(notFound, codes, labels);
    for (int i = 0; i < codes.length; i++) {
        mv.visitLabel(labels[i]);
        putRawBaseCase(mv, className, hashCodeRelation, environmentClass, codes[i], notFound);
    }

}

From source file:com.yahoo.yqlplus.engine.internal.compiler.CodeEmitter.java

public void emitIntegerSwitch(Map<Integer, Label> labels, Label defaultCase) {
    // TODO: we should see if the labels are dense, and if so use TABLESWITCH
    MethodVisitor mv = getMethodVisitor();
    List<Integer> codes = Lists.newArrayList(labels.keySet());
    Collections.sort(codes);/*from w ww .  java 2s. co m*/
    int[] k = new int[codes.size()];
    Label[] kl = new Label[codes.size()];
    for (int i = 0; i < k.length; ++i) {
        k[i] = codes.get(i);
        kl[i] = labels.get(i);
    }
    mv.visitLookupSwitchInsn(defaultCase, k, kl);
    mv.visitJumpInsn(GOTO, defaultCase);
}

From source file:com.yahoo.yqlplus.engine.internal.compiler.CodeEmitter.java

public void emitStringSwitch(Map<String, Label> labels, Label defaultCase, boolean caseInsensitive) {
    MethodVisitor mv = getMethodVisitor();
    if (caseInsensitive) {
        mv.visitFieldInsn(GETSTATIC, "java/util/Locale", "ENGLISH", "Ljava/util/Locale;");
        mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "toUpperCase",
                "(Ljava/util/Locale;)Ljava/lang/String;", false);
    }//from   w  w  w.  ja  v a  2s .co  m
    mv.visitInsn(DUP);
    AssignableValue tmp = allocate(String.class);
    tmp.write(BaseTypeAdapter.STRING).generate(this);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "hashCode", "()I", false);
    Multimap<Integer, SwitchLabel> keys = ArrayListMultimap.create();
    for (Map.Entry<String, Label> e : labels.entrySet()) {
        String name = e.getKey();
        if (caseInsensitive) {
            name = name.toUpperCase(Locale.ENGLISH);
        }
        keys.put(name.hashCode(), new SwitchLabel(name, e.getValue()));
    }
    List<Integer> codes = Lists.newArrayList(keys.keySet());
    Collections.sort(codes);
    int[] k = new int[codes.size()];
    Label[] kl = new Label[codes.size()];
    for (int i = 0; i < k.length; ++i) {
        k[i] = codes.get(i);
        kl[i] = new Label();
    }
    mv.visitLookupSwitchInsn(defaultCase, k, kl);
    for (int i = 0; i < k.length; ++i) {
        mv.visitLabel(kl[i]);
        for (SwitchLabel switchLabel : keys.get(k[i])) {
            mv.visitLdcInsn(switchLabel.name);
            tmp.read().generate(this);
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
            mv.visitJumpInsn(IFNE, switchLabel.label);
        }
        mv.visitJumpInsn(GOTO, defaultCase);
    }
}

From source file:kilim.analysis.MethodWeaver.java

License:Open Source License

/**
 * Generate code for only those catch blocks that are reachable
 * from one or more pausable blocks. fiber.pc tells us which
 * nested call possibly caused an exception, fiber.status tells us
 * whether there is any state that needs to be restored, and
 * fiber.curState gives us access to that state. 
 * /*  w  w  w.  ja v  a 2 s .c  om*/
 * ; Figure out which pausable method could have caused this.
 * 
 * switch (fiber.upEx()) {
 *    0: goto NORMAL_EXCEPTION_HANDLING;
 *    2: goto RESTORE_F
 * }
 * RESTORE_F:
 *   if (fiber.curStatus == HAS_STATE) {
 *      restore variables from the state. don't restore stack
 *      goto NORMAL_EXCEPTION_HANDLING
 *   }
 * ... other RESTOREs
 * 
 * NORMAL_EXCEPTION_HANDLING:
 */
private void genException(MethodVisitor mv, BasicBlock bb, List<CallWeaver> cwList) {
    mv.visitLabel(bb.startLabel);
    Label resumeLabel = new Label();
    VMType.loadVar(mv, VMType.TOBJECT, getFiberVar());
    mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "upEx", "()I");
    // fiber.pc is on stack
    Label[] labels = new Label[cwList.size()];
    int[] keys = new int[cwList.size()];
    for (int i = 0; i < cwList.size(); i++) {
        labels[i] = new Label();
        keys[i] = callWeavers.indexOf(cwList.get(i)) + 1;
    }

    mv.visitLookupSwitchInsn(resumeLabel, keys, labels);
    int i = 0;
    for (CallWeaver cw : cwList) {
        if (i > 0) {
            // This is the jump (to normal exception handling) for the previous
            // switch case.
            mv.visitJumpInsn(GOTO, resumeLabel);
        }
        mv.visitLabel(labels[i]);
        cw.genRestoreEx(mv, labels[i]);
        i++;
    }

    // Consume the first instruction because we have already consumed the
    // corresponding label. (The standard visitInstructions code does a 
    // visitLabel before visiting the instruction itself)
    mv.visitLabel(resumeLabel);
    bb.getInstruction(bb.startPos).accept(mv);
}

From source file:mt.swift.Deserializer.java

License:Apache License

private void compileDeserializeMethod(StructureType type, ClassVisitor writer, String targetClassName,
        Class targetClass) {/* w  w  w.ja va2 s. c o  m*/
    MethodVisitor methodVisitor = writer.visitMethod(
            ACC_PUBLIC, "deserialize", "(L" + Util.getInternalName(Deserializer.class)
                    + ";Lcom/facebook/thrift/protocol/TProtocol;)L" + targetClassName + ";",
            null, new String[] { "com/facebook/thrift/TException" });

    FrameRegisterManager context = new FrameRegisterManager();
    context.bindSlot("this", 0);
    context.bindSlot("deserializer", 1);
    context.bindSlot("protocol", 2);
    context.newSlot("target");
    context.newSlot("tfield");

    methodVisitor.visitCode();

    // <target> result = new <target>()
    methodVisitor.visitTypeInsn(NEW, targetClassName);
    methodVisitor.visitInsn(DUP);
    methodVisitor.visitMethodInsn(INVOKESPECIAL, targetClassName, "<init>", "()V");
    methodVisitor.visitVarInsn(ASTORE, context.getSlot("target"));

    // protocol.readStructBegin()
    methodVisitor.visitVarInsn(ALOAD, context.getSlot("protocol"));
    methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "com/facebook/thrift/protocol/TProtocol", "readStructBegin",
            "()Lcom/facebook/thrift/protocol/TStruct;");
    methodVisitor.visitInsn(POP); // discard return value

    // while (true)
    Label whileLabel = new Label();
    methodVisitor.visitLabel(whileLabel);

    // TField tfield = protocol.readFieldBegin()
    methodVisitor.visitVarInsn(ALOAD, context.getSlot("protocol"));
    methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "com/facebook/thrift/protocol/TProtocol", "readFieldBegin",
            "()Lcom/facebook/thrift/protocol/TField;");
    methodVisitor.visitVarInsn(ASTORE, context.getSlot("tfield"));

    // tfield.type
    methodVisitor.visitVarInsn(ALOAD, context.getSlot("tfield"));
    methodVisitor.visitFieldInsn(GETFIELD, "com/facebook/thrift/protocol/TField", "type", "B");

    methodVisitor.visitFieldInsn(GETSTATIC, "com/facebook/thrift/protocol/TType", "STOP", "B");

    // if (tfield.type == TType.STOP) { break; }
    Label endWhile = new Label();
    methodVisitor.visitJumpInsn(IF_ICMPEQ, endWhile);

    // tfield.id
    methodVisitor.visitVarInsn(ALOAD, context.getSlot("tfield"));
    methodVisitor.visitFieldInsn(GETFIELD, "com/facebook/thrift/protocol/TField", "id", "S");

    List<Field> fields = new ArrayList<Field>(type.getFields());
    int[] ids = new int[fields.size()];
    Label[] labels = new Label[fields.size()];
    for (int i = 0; i < fields.size(); ++i) {
        ids[i] = fields.get(i).getId();
        labels[i] = new Label();
    }

    Label fieldSkipped = new Label();

    methodVisitor.visitLookupSwitchInsn(fieldSkipped, ids, labels);

    for (int i = 0; i < fields.size(); ++i) {
        Field field = fields.get(i);

        methodVisitor.visitLabel(labels[i]);

        // if (tfield.type == ###)
        methodVisitor.visitVarInsn(ALOAD, context.getSlot("tfield"));
        methodVisitor.visitFieldInsn(GETFIELD, "com/facebook/thrift/protocol/TField", "type", "B");
        methodVisitor.visitIntInsn(BIPUSH, field.getType().getTType());
        methodVisitor.visitJumpInsn(IF_ICMPNE, fieldSkipped);

        methodVisitor.visitVarInsn(ALOAD, context.getSlot("target"));
        if (Map.class.isAssignableFrom(targetClass)) {
            methodVisitor.visitLdcInsn(field.getName());
            generateReadElement(methodVisitor, context, field.getType());
            generateAddToMap(targetClassName, methodVisitor, context, field);
        } else {
            generateReadElement(methodVisitor, context, field.getType());
            generateSetTargetField(targetClassName, methodVisitor, context, field);
        }

        methodVisitor.visitJumpInsn(GOTO, whileLabel);
    }

    methodVisitor.visitLabel(fieldSkipped);
    methodVisitor.visitVarInsn(ALOAD, context.getSlot("protocol"));
    methodVisitor.visitVarInsn(ALOAD, context.getSlot("tfield"));
    methodVisitor.visitFieldInsn(GETFIELD, "com/facebook/thrift/protocol/TField", "type", "B");
    methodVisitor.visitMethodInsn(INVOKESTATIC, "com/facebook/thrift/protocol/TProtocolUtil", "skip",
            "(Lcom/facebook/thrift/protocol/TProtocol;B)V");

    // end while
    methodVisitor.visitJumpInsn(GOTO, whileLabel);

    methodVisitor.visitLabel(endWhile);

    // protocol.readStructEnd()
    methodVisitor.visitVarInsn(ALOAD, context.getSlot("protocol"));
    methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "com/facebook/thrift/protocol/TProtocol", "readStructEnd",
            "()V");

    // return result
    methodVisitor.visitVarInsn(ALOAD, context.getSlot("target"));
    methodVisitor.visitInsn(ARETURN);

    methodVisitor.visitMaxs(1, 1); // TODO: what should these be?
    methodVisitor.visitEnd();
}

From source file:net.sf.sveditor.core.db.persistence.JITPersistenceDelegateFactory.java

License:Open Source License

private void buildItemDispatchMethods(ClassWriter cw) {
    String classname = "SVDBPersistenceDelegate";
    String full_classname = transform_cls(fTargetPkg) + "/" + classname;

    Label labels[] = new Label[SVDBItemType.values().length];
    int indexes[] = new int[SVDBItemType.values().length];
    Label dflt, endcase;//w w  w  . j av a  2  s  .c  o  m

    for (int i = 0; i < SVDBItemType.values().length; i++) {
        indexes[i] = i;
    }

    // writeItem Dispatch method
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "writeSVDBItem",
            "(L" + getClassName(ISVDBItemBase.class) + ";)V", null, new String[] { fDBWriteException });
    for (int i = 0; i < SVDBItemType.values().length; i++) {
        labels[i] = new Label();
    }
    dflt = new Label();
    endcase = new Label();

    // Retrieve the object type
    mv.visitVarInsn(ALOAD, WRITE_OBJ_VAR);
    mv.visitMethodInsn(INVOKEINTERFACE, getClassName(ISVDBItemBase.class), "getType",
            "()L" + getClassName(SVDBItemType.class) + ";");
    mv.visitMethodInsn(INVOKEVIRTUAL, getClassName(SVDBItemType.class), "ordinal", "()I");
    mv.visitLookupSwitchInsn(dflt, indexes, labels);
    for (SVDBItemType t : SVDBItemType.values()) {
        Class c = fTypeClassMap.get(t);
        mv.visitLabel(labels[t.ordinal()]);

        mv.visitVarInsn(ALOAD, THIS_VAR);
        mv.visitVarInsn(ALOAD, WRITE_OBJ_VAR);
        mv.visitTypeInsn(CHECKCAST, getClassName(c));
        mv.visitMethodInsn(INVOKESPECIAL, full_classname, "write" + t.name(), "(L" + getClassName(c) + ";)V");
        mv.visitJumpInsn(GOTO, endcase);
    }
    mv.visitLabel(dflt);
    mv.visitLabel(endcase);
    mv.visitInsn(RETURN);
    mv.visitMaxs(16, 16);
    mv.visitEnd();

    // readItem dispatch method
    mv = cw.visitMethod(
            ACC_PUBLIC, "readSVDBItem", "(L" + getClassName(SVDBItemType.class) + ";L"
                    + getClassName(ISVDBChildItem.class) + ";)L" + getClassName(ISVDBItemBase.class) + ";",
            null, new String[] { fDBWriteException });
    for (int i = 0; i < SVDBItemType.values().length; i++) {
        labels[i] = new Label();
    }
    dflt = new Label();
    endcase = new Label();

    mv.visitVarInsn(ALOAD, 1); // object type
    mv.visitMethodInsn(INVOKEVIRTUAL, getClassName(SVDBItemType.class), "ordinal", "()I");
    mv.visitLookupSwitchInsn(dflt, indexes, labels);
    for (SVDBItemType t : SVDBItemType.values()) {
        Class c = fTypeClassMap.get(t);
        mv.visitLabel(labels[t.ordinal()]);

        mv.visitVarInsn(ALOAD, THIS_VAR);
        mv.visitVarInsn(ALOAD, 2); // parent
        mv.visitMethodInsn(INVOKESPECIAL, full_classname, "read" + t.name(),
                "(L" + getClassName(ISVDBChildItem.class) + ";)" + "L" + getClassName(c) + ";");
        mv.visitJumpInsn(GOTO, endcase);
    }
    mv.visitLabel(dflt);
    mv.visitInsn(ACONST_NULL);
    mv.visitLabel(endcase);
    mv.visitInsn(ARETURN);
    mv.visitMaxs(16, 16);
    mv.visitEnd();
}

From source file:net.sf.sveditor.core.db.persistence.JITPersistenceDelegateFactory.java

License:Open Source License

private void buildObjectDispatchMethods(ClassWriter cw) {
    String classname = "SVDBPersistenceDelegate";
    String full_classname = transform_cls(fTargetPkg) + "/" + classname;
    int idx;// www.ja v a 2 s. c o  m

    Label labels[] = new Label[fClassList.size()];
    int indexes[] = new int[fClassList.size()];
    Label dflt, endcase;

    for (int i = 0; i < fClassList.size(); i++) {
        indexes[i] = i;
    }

    // writeItem Dispatch method
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "writeObject",
            "(L" + getClassName(Class.class) + ";" + "L" + getClassName(Object.class) + ";)V", null,
            new String[] { fDBWriteException });
    for (int i = 0; i < fClassList.size(); i++) {
        labels[i] = new Label();
    }
    dflt = new Label();
    endcase = new Label();

    // Find the object index
    mv.visitVarInsn(ALOAD, THIS_VAR);
    mv.visitFieldInsn(GETFIELD, fBaseClass, "fObjectTypeList", "L" + getClassName(List.class) + ";");

    // Class parameter
    // fObjectList field
    mv.visitVarInsn(ALOAD, 1); // cls parameter
    mv.visitMethodInsn(INVOKEINTERFACE, getClassName(List.class), "indexOf",
            "(L" + getClassName(Object.class) + ";)I");
    // Index now on the stack 
    mv.visitLookupSwitchInsn(dflt, indexes, labels);
    idx = 0;
    for (Class c : fClassList) {
        mv.visitLabel(labels[idx]);

        mv.visitVarInsn(ALOAD, THIS_VAR);
        mv.visitVarInsn(ALOAD, 2); // object
        mv.visitTypeInsn(CHECKCAST, getClassName(c));
        mv.visitMethodInsn(INVOKESPECIAL, full_classname, "write" + getClassLeafName(c),
                "(L" + getClassName(c) + ";)V");
        mv.visitJumpInsn(GOTO, endcase);
        idx++;
    }
    mv.visitLabel(dflt);
    mv.visitVarInsn(ALOAD, THIS_VAR);
    mv.visitVarInsn(ALOAD, 2); // object
    mv.visitMethodInsn(INVOKESPECIAL, full_classname, "writeObjectErr",
            "(L" + getClassName(Object.class) + ";)V");

    mv.visitLabel(endcase);
    mv.visitInsn(RETURN);
    mv.visitMaxs(16, 16);
    mv.visitEnd();

    // readItem dispatch method
    mv = cw.visitMethod(
            ACC_PUBLIC, "readObject", "(L" + getClassName(ISVDBChildItem.class) + ";" + "L"
                    + getClassName(Class.class) + ";" + "L" + getClassName(Object.class) + ";)V",
            null, new String[] { fDBWriteException });
    for (int i = 0; i < fClassList.size(); i++) {
        labels[i] = new Label();
    }
    dflt = new Label();
    endcase = new Label();

    // Find the object index
    mv.visitVarInsn(ALOAD, THIS_VAR);
    mv.visitFieldInsn(GETFIELD, fBaseClass, "fObjectTypeList", "L" + getClassName(List.class) + ";");

    // Class parameter
    // fObjectList field
    mv.visitVarInsn(ALOAD, 2); // cls parameter
    mv.visitMethodInsn(INVOKEINTERFACE, getClassName(List.class), "indexOf",
            "(L" + getClassName(Object.class) + ";)I");

    mv.visitLookupSwitchInsn(dflt, indexes, labels);
    idx = 0;
    for (Class c : fClassList) {
        mv.visitLabel(labels[idx]);

        // 
        mv.visitVarInsn(ALOAD, THIS_VAR);
        mv.visitVarInsn(ALOAD, 1); // parent
        mv.visitVarInsn(ALOAD, 3); // object
        mv.visitTypeInsn(CHECKCAST, getClassName(c));
        mv.visitMethodInsn(INVOKESPECIAL, full_classname, "read" + getClassLeafName(c),
                "(L" + getClassName(ISVDBChildItem.class) + ";" + "L" + getClassName(c) + ";)V");
        mv.visitJumpInsn(GOTO, endcase);
        idx++;
    }
    mv.visitLabel(dflt);
    mv.visitVarInsn(ALOAD, THIS_VAR);
    mv.visitVarInsn(ALOAD, 3); // object
    mv.visitMethodInsn(INVOKESPECIAL, full_classname, "readObjectErr",
            "(L" + getClassName(Object.class) + ";)V");
    mv.visitLabel(endcase);
    mv.visitInsn(RETURN);
    mv.visitMaxs(4, 4);
    mv.visitEnd();
}

From source file:org.ballerinalang.nativeimpl.jvm.methodvisitor.VisitLookupSwitchInsn.java

License:Open Source License

public static void visitLookupSwitchInsn(Strand strand, ObjectValue oMv, ObjectValue oDefaultLabel,
        ArrayValue oKeys, ArrayValue oLabels) {
    MethodVisitor mv = ASMUtil.getRefArgumentNativeData(oMv);
    Label defaultLabel = ASMUtil.getRefArgumentNativeData(oDefaultLabel);
    long[] lKeys = oKeys.getLongArray();
    int[] iKeys = Arrays.stream(lKeys).mapToInt(l -> ((int) l)).toArray();
    Label[] labels = convertToLabel(oLabels);
    mv.visitLookupSwitchInsn(defaultLabel, iKeys, labels);
}

From source file:org.codehaus.aspectwerkz.transform.inlining.compiler.AbstractJoinPointCompiler.java

License:Open Source License

/**
 * Create the proceed() method./*from w w  w. j  ava2s.c  o m*/
 *
 * @param input a slightly different CompilerInput since jp index, is changed and caller and callee are meaningless
 *              in the proceed() method.
 */
private void createProceedMethod(CompilerInput input) {

    MethodVisitor cv = m_cw.visitMethod(ACC_PUBLIC | ACC_FINAL, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE,
            null, new String[] { THROWABLE_CLASS_NAME });

    if (m_isThisAdvisable) {
        createAroundInterceptorInvocations(cv);
    }

    incrementStackFrameCounter(cv);

    // set up the labels
    Label tryLabel = new Label();
    Label defaultCaseLabel = new Label();
    Label gotoLabel = new Label();
    Label handlerLabel = new Label();
    Label endLabel = new Label();

    int nrOfCases = m_aroundAdviceMethodInfos.length;
    if (m_isThisAdvisable) {
        nrOfCases++;
    }

    Label[] caseLabels = new Label[nrOfCases];
    Label[] returnLabels = new Label[nrOfCases];
    int[] caseNumbers = new int[nrOfCases];
    for (int i = 0; i < caseLabels.length; i++) {
        caseLabels[i] = new Label();
        caseNumbers[i] = i;
    }
    for (int i = 0; i < returnLabels.length; i++) {
        returnLabels[i] = new Label();
    }

    // start try-catch block
    cv.visitLabel(tryLabel);

    // start the switch block and set the stackframe as the param to the switch
    cv.visitVarInsn(ALOAD, 0);
    cv.visitFieldInsn(GETFIELD, m_joinPointClassName, STACK_FRAME_COUNTER_FIELD_NAME, I);
    cv.visitLookupSwitchInsn(defaultCaseLabel, caseNumbers, caseLabels);

    // add one case for each around advice invocation
    for (int i = 0; i < m_aroundAdviceMethodInfos.length; i++) {
        cv.visitLabel(caseLabels[i]);

        // gather advice info
        AdviceMethodInfo adviceInfo = m_aroundAdviceMethodInfos[i];

        Label endInstanceOflabel = beginRuntimeCheck(cv, input, adviceInfo.getAdviceInfo());

        // get the aspect instance
        adviceInfo.getAspectInfo().getAspectModel().loadAspect(cv, input, adviceInfo.getAspectInfo());

        // load the arguments to the advice
        adviceInfo.getAspectInfo().getAspectModel().createAroundAdviceArgumentHandling(cv, input,
                m_argumentTypes, adviceInfo);

        // invoke the advice method
        cv.visitMethodInsn(INVOKEVIRTUAL, adviceInfo.getAspectInfo().getAspectClassName(),
                adviceInfo.getAdviceInfo().getMethodName(), adviceInfo.getAdviceInfo().getMethodSignature());
        cv.visitVarInsn(ASTORE, 1);

        // we need to handle the case when the advice was skipped due to runtime check
        // that is : if (runtimeCheck) { ret = advice() } else { ret = proceed() }
        if (endInstanceOflabel != null) {
            Label elseInstanceOfLabel = new Label();
            cv.visitJumpInsn(GOTO, elseInstanceOfLabel);
            endRuntimeCheck(cv, adviceInfo.getAdviceInfo(), endInstanceOflabel);
            cv.visitVarInsn(ALOAD, 0);
            cv.visitMethodInsn(INVOKESPECIAL, m_joinPointClassName, PROCEED_METHOD_NAME,
                    PROCEED_METHOD_SIGNATURE);
            cv.visitVarInsn(ASTORE, 1);
            cv.visitLabel(elseInstanceOfLabel);
        }

        cv.visitLabel(returnLabels[i]);

        cv.visitVarInsn(ALOAD, 1);
        cv.visitInsn(ARETURN);
    }

    if (m_isThisAdvisable) {
        int delegationCaseIndex = caseLabels.length - 1;
        cv.visitLabel(caseLabels[delegationCaseIndex]);
        cv.visitVarInsn(ALOAD, 0);
        cv.visitInsn(ICONST_0);
        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, INTERCEPTOR_INDEX_FIELD_NAME, I);
        cv.visitVarInsn(ALOAD, 0);
        cv.visitMethodInsn(INVOKEVIRTUAL, m_joinPointClassName, PROCEED_METHOD_NAME, PROCEED_METHOD_SIGNATURE);

        cv.visitLabel(returnLabels[delegationCaseIndex]);

        cv.visitInsn(ARETURN);
    }

    // invoke the target join point in the default case
    cv.visitLabel(defaultCaseLabel);

    AsmHelper.prepareWrappingOfPrimitiveType(cv, Type.getReturnType(m_calleeMemberDesc));

    createJoinPointInvocation(cv);

    Type m_returnType = null;
    if (m_joinPointType != JoinPointType.CONSTRUCTOR_CALL_INT) {
        m_returnType = Type.getReturnType(m_calleeMemberDesc);
    } else {
        m_returnType = Type.getType(m_calleeClassSignature);
    }
    AsmHelper.wrapPrimitiveType(cv, m_returnType);
    cv.visitVarInsn(ASTORE, 1);

    // store it in Rtti return value
    addReturnedValueToJoinPoint(cv, input, 1, true);

    // set it as the CALLEE instance for ctor call - TODO refactor somewhere else
    if (m_joinPointType == JoinPointType.CONSTRUCTOR_CALL_INT) {
        cv.visitVarInsn(ALOAD, 0);
        cv.visitVarInsn(ALOAD, 1);
        cv.visitFieldInsn(PUTFIELD, m_joinPointClassName, CALLEE_INSTANCE_FIELD_NAME, m_calleeClassSignature);
    }

    cv.visitLabel(gotoLabel);

    cv.visitVarInsn(ALOAD, 1);
    cv.visitInsn(ARETURN);

    // finally clause
    cv.visitLabel(handlerLabel);
    cv.visitVarInsn(ASTORE, 2);
    cv.visitLabel(endLabel);

    cv.visitVarInsn(ALOAD, 2);
    cv.visitInsn(ATHROW);

    // set up the label table
    cv.visitTryCatchBlock(tryLabel, returnLabels[0], handlerLabel, null);
    for (int i = 1; i < caseLabels.length; i++) {
        Label caseLabel = caseLabels[i];
        Label returnLabel = returnLabels[i];
        cv.visitTryCatchBlock(caseLabel, returnLabel, handlerLabel, null);
    }
    cv.visitTryCatchBlock(defaultCaseLabel, gotoLabel, handlerLabel, null);
    cv.visitTryCatchBlock(handlerLabel, endLabel, handlerLabel, null);
    cv.visitMaxs(0, 0);
}

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  . ja  v  a2  s  .  co  m*/
    // 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);
}