List of usage examples for org.objectweb.asm MethodVisitor visitLookupSwitchInsn
public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels)
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); }