List of usage examples for org.objectweb.asm Opcodes POP
int POP
To view the source code for org.objectweb.asm Opcodes POP.
Click Source Link
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
/** * Generates instructions to pop an item off the stack. * @return instructions for a pop//from w w w . j a v a 2s . c o m */ public static InsnList pop() { InsnList ret = new InsnList(); ret.add(new InsnNode(Opcodes.POP)); return ret; }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
/** * Generates instructions to pop {@code count} items off the stack. * @param count number of items to pop/*from w w w .j av a2 s .co m*/ * @return instructions for a pop * @throws IllegalArgumentException if any numeric argument is negative */ public static InsnList pop(int count) { Validate.isTrue(count >= 0); InsnList ret = new InsnList(); for (int i = 0; i < count; i++) { ret.add(new InsnNode(Opcodes.POP)); } return ret; }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
/** * For each element in an object array, performs an action. * @param counterVar parameter used to keep track of count in loop * @param arrayLenVar parameter used to keep track of array length * @param array object array instruction list -- must leave an array on top of the stack * @param action action to perform on each element -- element will be at top of stack and must be consumed by these instructions * @return instructions instruction list to perform some action if two ints are equal * @throws NullPointerException if any argument is {@code null} *//*from www . ja v a2s . co m*/ public static InsnList forEach(Variable counterVar, Variable arrayLenVar, InsnList array, InsnList action) { Validate.notNull(counterVar); Validate.notNull(arrayLenVar); Validate.notNull(array); Validate.notNull(action); Validate.isTrue(counterVar.getType().equals(Type.INT_TYPE)); Validate.isTrue(arrayLenVar.getType().equals(Type.INT_TYPE)); InsnList ret = new InsnList(); LabelNode doneLabelNode = new LabelNode(); LabelNode loopLabelNode = new LabelNode(); // put zero in to counterVar ret.add(new LdcInsnNode(0)); // int ret.add(new VarInsnNode(Opcodes.ISTORE, counterVar.getIndex())); // // load array we'll be traversing over ret.add(array); // object[] // put array length in to arrayLenVar ret.add(new InsnNode(Opcodes.DUP)); // object[], object[] ret.add(new InsnNode(Opcodes.ARRAYLENGTH)); // object[], int ret.add(new VarInsnNode(Opcodes.ISTORE, arrayLenVar.getIndex())); // object[] // loopLabelNode: test if counterVar == arrayLenVar, if it does then jump to doneLabelNode ret.add(loopLabelNode); ret.add(new VarInsnNode(Opcodes.ILOAD, counterVar.getIndex())); // object[], int ret.add(new VarInsnNode(Opcodes.ILOAD, arrayLenVar.getIndex())); // object[], int, int ret.add(new JumpInsnNode(Opcodes.IF_ICMPEQ, doneLabelNode)); // object[] // load object from object[] ret.add(new InsnNode(Opcodes.DUP)); // object[], object[] ret.add(new VarInsnNode(Opcodes.ILOAD, counterVar.getIndex())); // object[], object[], int ret.add(new InsnNode(Opcodes.AALOAD)); // object[], object // call action ret.add(action); // object[] // increment counter var and goto loopLabelNode ret.add(new IincInsnNode(counterVar.getIndex(), 1)); // object[] ret.add(new JumpInsnNode(Opcodes.GOTO, loopLabelNode)); // object[] // doneLabelNode: pop object[] off of stack ret.add(doneLabelNode); ret.add(new InsnNode(Opcodes.POP)); // return ret; }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
/** * Generates instructions to save the operand stack to an object array. * @param arrayStackVar variable that the object array containing operand stack is stored * @param tempObjectVar variable to use for temporary objects * @param frame execution frame at the instruction where the operand stack is to be saved * @return instructions to save the operand stack in to an array and save it to the local variables table * @throws NullPointerException if any argument is {@code null} * @throws IllegalArgumentException if variables have the same index, or if variables have been released, or if variables are of wrong * type//from ww w.j ava 2 s.c om */ public static InsnList saveOperandStack(Variable arrayStackVar, Variable tempObjectVar, Frame<BasicValue> frame) { Validate.notNull(arrayStackVar); Validate.notNull(tempObjectVar); Validate.notNull(frame); Validate.isTrue(arrayStackVar.getType().equals(Type.getType(Object[].class))); Validate.isTrue(tempObjectVar.getType().equals(Type.getType(Object.class))); validateLocalIndicies(arrayStackVar.getIndex(), tempObjectVar.getIndex()); InsnList ret = new InsnList(); // Create stack storage array and save it in local vars table ret.add(new LdcInsnNode(frame.getStackSize())); ret.add(new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object")); ret.add(new VarInsnNode(Opcodes.ASTORE, arrayStackVar.getIndex())); // Save the stack for (int i = frame.getStackSize() - 1; i >= 0; 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 (but we still need to do a POP to get rid of 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())) { ret.add(new InsnNode(Opcodes.POP)); continue; } // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack. switch (type.getSort()) { case Type.BOOLEAN: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;")); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.BYTE: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.SHORT: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.CHAR: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.INT: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.FLOAT: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.LONG: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.DOUBLE: ret.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false)); ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.ARRAY: case Type.OBJECT: ret.add(new VarInsnNode(Opcodes.ASTORE, tempObjectVar.getIndex())); break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } // Store item in to stack storage array ret.add(new VarInsnNode(Opcodes.ALOAD, arrayStackVar.getIndex())); ret.add(new LdcInsnNode(i)); ret.add(new VarInsnNode(Opcodes.ALOAD, tempObjectVar.getIndex())); ret.add(new InsnNode(Opcodes.AASTORE)); } // Restore the stack 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 there's no specific value to load up from the array. Instead we push a null in to that slot, thereby // keeping the same 'Lnull;' type originally assigned to that slot (it doesn't make sense to do a CHECKCAST because 'null' is // not a real class and can never be a real class -- null is a reserved word in Java). if (type.getSort() == Type.OBJECT && "Lnull;".equals(type.getDescriptor())) { ret.add(new InsnNode(Opcodes.ACONST_NULL)); continue; } // Load item from stack storage array ret.add(new VarInsnNode(Opcodes.ALOAD, arrayStackVar.getIndex())); ret.add(new LdcInsnNode(i)); ret.add(new InsnNode(Opcodes.AALOAD)); // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack. switch (type.getSort()) { case Type.BOOLEAN: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Boolean")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false)); break; case Type.BYTE: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Byte")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false)); break; case Type.SHORT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Short")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false)); break; case Type.CHAR: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Character")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false)); break; case Type.INT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Integer")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false)); break; case Type.FLOAT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Float")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false)); break; case Type.LONG: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Long")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false)); break; case Type.DOUBLE: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, "java/lang/Double")); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false)); break; case Type.ARRAY: case Type.OBJECT: ret.add(new TypeInsnNode(Opcodes.CHECKCAST, basicValue.getType().getInternalName())); break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } } return ret; }
From source file:com.offbynull.coroutines.instrumenter.ContinuationGenerators.java
License:Open Source License
/** * Generates instructions to pop the result of the method off the stack. This will only generate instructions if the method being * invoked generates a return value.// w w w. j a v a 2 s . c om * @param invokeInsnNode instruction for the method that was invoked (can either be of type {@link MethodInsnNode} or * {@link InvokeDynamicInsnNode} -- this is used to determine how many items to pop off the stack * @return instructions for a pop (only if the method being invoked generates a return value) * @throws IllegalArgumentException if {@code invokeInsnNode} isn't of type {@link MethodInsnNode} or {@link InvokeDynamicInsnNode} * @throws NullPointerException if any argument is {@code null} */ private static InsnList popMethodResult(AbstractInsnNode invokeInsnNode) { Validate.notNull(invokeInsnNode); Type returnType = getReturnTypeOfInvocation(invokeInsnNode); InsnList ret = new InsnList(); switch (returnType.getSort()) { case Type.LONG: case Type.DOUBLE: ret.add(new InsnNode(Opcodes.POP2)); break; case Type.VOID: break; case Type.METHOD: throw new IllegalStateException(); // this should never happen default: ret.add(new InsnNode(Opcodes.POP)); break; } return ret; }
From source file:com.offbynull.coroutines.instrumenter.generators.DebugGenerators.java
License:Open Source License
/** * Generates instructions for generating marker instructions. These marker instructions are meant to be is useful for debugging * instrumented code. For example, you can spot a specific portion of instrumented code by looking for specific markers in the assembly * output./*w w w .j a va 2s. c o m*/ * @param markerType marker type (determines what kind of instructions are generated) * @param text text to print out * @return instructions to call System.out.println with a string constant * @throws NullPointerException if any argument is {@code null} */ public static InsnList debugMarker(MarkerType markerType, String text) { Validate.notNull(markerType); Validate.notNull(text); InsnList ret = new InsnList(); switch (markerType) { case NONE: break; case CONSTANT: ret.add(new LdcInsnNode(text)); ret.add(new InsnNode(Opcodes.POP)); break; case STDOUT: ret.add(new FieldInsnNode(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;")); ret.add(new LdcInsnNode(text)); ret.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false)); break; default: throw new IllegalStateException(); } return ret; }
From source file:com.offbynull.coroutines.instrumenter.OperandStackStateGenerators.java
License:Open Source License
/** * Generates instructions to save a certain number of items from the top of the operand stack. * <p>// w ww .ja va2s . com * The instructions generated here expect the operand stack to be fully loaded. The stack items specified by {@code frame} must actually * all be on the operand stack. * <p> * REMEMBER: The items aren't returned to the operand stack after they've been saved (they have been popped off the stack). If you want * them back on the operand stack, reload using * {@code loadOperandStack(markerType, storageVars, frame, frame.getStackSize() - count, frame.getStackSize() - count, count)}. * @param markerType debug marker type * @param storageVars variables to store operand stack in to * @param frame execution frame at the instruction where the operand stack is to be saved * @param count number of items to store from the stack * @return instructions to save the operand stack to the storage variables * @throws NullPointerException if any argument is {@code null} * @throws IllegalArgumentException if {@code size} is larger than the number of items in the stack at {@code frame} (or is negative), * or if {@code count} is larger than {@code top} (or is negative) */ public static InsnList saveOperandStack(MarkerType markerType, StorageVariables storageVars, Frame<BasicValue> frame, int count) { Validate.notNull(markerType); Validate.notNull(storageVars); Validate.notNull(frame); Validate.isTrue(count >= 0); Validate.isTrue(count <= frame.getStackSize()); Variable intsVar = storageVars.getIntStorageVar(); Variable floatsVar = storageVars.getFloatStorageVar(); Variable longsVar = storageVars.getLongStorageVar(); Variable doublesVar = storageVars.getDoubleStorageVar(); Variable objectsVar = storageVars.getObjectStorageVar(); StorageSizes storageSizes = computeSizes(frame, frame.getStackSize() - count, count); int intsCounter = storageSizes.getIntsSize() - 1; int floatsCounter = storageSizes.getFloatsSize() - 1; int longsCounter = storageSizes.getLongsSize() - 1; int doublesCounter = storageSizes.getDoublesSize() - 1; int objectsCounter = storageSizes.getObjectsSize() - 1; InsnList ret = new InsnList(); // Create stack storage arrays and save them ret.add(merge(debugMarker(markerType, "Saving operand stack (" + count + " items)"), mergeIf(storageSizes.getIntsSize() > 0, () -> new Object[] { debugMarker(markerType, "Generating ints container (" + storageSizes.getIntsSize() + ")"), new LdcInsnNode(storageSizes.getIntsSize()), new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_INT), new VarInsnNode(Opcodes.ASTORE, intsVar.getIndex()) }), mergeIf(storageSizes.getFloatsSize() > 0, () -> new Object[] { debugMarker(markerType, "Generating floats container (" + storageSizes.getFloatsSize() + ")"), new LdcInsnNode(storageSizes.getFloatsSize()), new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_FLOAT), new VarInsnNode(Opcodes.ASTORE, floatsVar.getIndex()) }), mergeIf(storageSizes.getLongsSize() > 0, () -> new Object[] { debugMarker(markerType, "Generating longs container (" + storageSizes.getLongsSize() + ")"), new LdcInsnNode(storageSizes.getLongsSize()), new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_LONG), new VarInsnNode(Opcodes.ASTORE, longsVar.getIndex()) }), mergeIf(storageSizes.getDoublesSize() > 0, () -> new Object[] { debugMarker(markerType, "Generating doubles container (" + storageSizes.getDoublesSize() + ")"), new LdcInsnNode(storageSizes.getDoublesSize()), new IntInsnNode(Opcodes.NEWARRAY, Opcodes.T_DOUBLE), new VarInsnNode(Opcodes.ASTORE, doublesVar.getIndex()) }), mergeIf(storageSizes.getObjectsSize() > 0, () -> new Object[] { debugMarker(markerType, "Generating objects container (" + storageSizes.getObjectsSize() + ")"), new LdcInsnNode(storageSizes.getObjectsSize()), new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object"), new VarInsnNode(Opcodes.ASTORE, objectsVar.getIndex()) }))); // Save the stack int start = frame.getStackSize() - 1; int end = frame.getStackSize() - count; for (int i = start; i >= end; 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 (but we still need to do a POP to get rid of 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())) { ret.add(debugMarker(markerType, "Skipping null value at " + i)); ret.add(new InsnNode(Opcodes.POP)); continue; } // Convert the item to an object (if not already an object) and stores it in local vars table. Item removed from stack. switch (type.getSort()) { case Type.BOOLEAN: case Type.BYTE: case Type.SHORT: case Type.CHAR: case Type.INT: ret.add(debugMarker(markerType, "Popping/storing int at " + i + " to storage index " + intsCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, intsVar.getIndex())); // [val, int[]] ret.add(new InsnNode(Opcodes.SWAP)); // [int[], val] ret.add(new LdcInsnNode(intsCounter)); // [int[], val, idx] ret.add(new InsnNode(Opcodes.SWAP)); // [int[], idx, val] ret.add(new InsnNode(Opcodes.IASTORE)); // [] intsCounter--; break; case Type.FLOAT: ret.add(debugMarker(markerType, "Popping/storing float at " + i + " to storage index " + floatsCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, floatsVar.getIndex())); // [val, float[]] ret.add(new InsnNode(Opcodes.SWAP)); // [float[], val] ret.add(new LdcInsnNode(floatsCounter)); // [float[], val, idx] ret.add(new InsnNode(Opcodes.SWAP)); // [float[], idx, val] ret.add(new InsnNode(Opcodes.FASTORE)); // [] floatsCounter--; break; case Type.LONG: ret.add(debugMarker(markerType, "Popping/storing long at " + i + " to storage index " + longsCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, longsVar.getIndex())); // [val_PART1, val_PART2, long[]] ret.add(new LdcInsnNode(longsCounter)); // [val_PART1, val_PART2, long[], idx] ret.add(new InsnNode(Opcodes.DUP2_X2)); // [long[], idx, val_PART1, val_PART2, long[], idx] ret.add(new InsnNode(Opcodes.POP2)); // [long[], idx, val_PART1, val_PART2] ret.add(new InsnNode(Opcodes.LASTORE)); // [] longsCounter--; break; case Type.DOUBLE: ret.add(debugMarker(markerType, "Popping/storing double at " + i + " to storage index " + doublesCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, doublesVar.getIndex())); // [val_PART1, val_PART2, double[]] ret.add(new LdcInsnNode(doublesCounter)); // [val_PART1, val_PART2, double[], idx] ret.add(new InsnNode(Opcodes.DUP2_X2)); // [double[], idx, val_PART1, val_PART2, double[], idx] ret.add(new InsnNode(Opcodes.POP2)); // [double[], idx, val_PART1, val_PART2] ret.add(new InsnNode(Opcodes.DASTORE)); // [] doublesCounter--; break; case Type.ARRAY: case Type.OBJECT: ret.add(debugMarker(markerType, "Popping/storing object at " + i + " to storage index " + objectsCounter)); ret.add(new VarInsnNode(Opcodes.ALOAD, objectsVar.getIndex())); // [val, object[]] ret.add(new InsnNode(Opcodes.SWAP)); // [object[], val] ret.add(new LdcInsnNode(objectsCounter)); // [object[], val, idx] ret.add(new InsnNode(Opcodes.SWAP)); // [object[], idx, val] ret.add(new InsnNode(Opcodes.AASTORE)); // [] objectsCounter--; break; case Type.METHOD: case Type.VOID: default: throw new IllegalArgumentException(); } } // At this point, the storage array will contain the saved operand stack AND THE STACK WILL HAVE count ITEMS POPPED OFF OF IT. // // Reload using... // --------------- // ret.add(debugMarker(markerType, "Reloading stack items")); // InsnList reloadInsnList = loadOperandStack(markerType, storageVars, frame, // frame.getStackSize() - count, // frame.getStackSize() - count, // count); // ret.add(reloadInsnList); return ret; }
From source file:com.sun.fortress.compiler.environments.TopLevelEnvGen.java
License:Open Source License
private static void writeDumpMethod(ClassWriter cw, String className, EnvSymbolNames symbolNames) { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "dump", "(Ljava/lang/Appendable;)Ljava/lang/Appendable;", null, new String[] { "java/io/IOException" }); mv.visitCode();//from ww w . ja va 2 s . c o m Label l0 = new Label(); mv.visitLabel(l0); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, className, "within", Type.getType(HasAt.class).getDescriptor()); Label l1 = new Label(); mv.visitJumpInsn(Opcodes.IFNULL, l1); Label l2 = new Label(); mv.visitLabel(l2); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, className, "within", Type.getType(HasAt.class).getDescriptor()); mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.getType(HasAt.class).getInternalName(), "at", "()Ljava/lang/String;"); mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Appendable", "append", "(Ljava/lang/CharSequence;)Ljava/lang/Appendable;"); mv.visitInsn(Opcodes.POP); Label l3 = new Label(); mv.visitLabel(l3); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitLdcInsn("\n"); mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Appendable", "append", "(Ljava/lang/CharSequence;)Ljava/lang/Appendable;"); mv.visitInsn(Opcodes.POP); Label l4 = new Label(); mv.visitJumpInsn(Opcodes.GOTO, l4); mv.visitLabel(l1); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitLdcInsn("Not within anything.\n"); mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Appendable", "append", "(Ljava/lang/CharSequence;)Ljava/lang/Appendable;"); mv.visitInsn(Opcodes.POP); mv.visitLabel(l4); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, className, "verboseDump", "Z"); Label l5 = new Label(); mv.visitJumpInsn(Opcodes.IFEQ, l5); int linebreaks = dumpFields(mv, className, EnvironmentClass.FVALUE, symbolNames, 0); dumpFields(mv, className, EnvironmentClass.FTYPE, symbolNames, linebreaks); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitLdcInsn("\n"); mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Appendable", "append", "(Ljava/lang/CharSequence;)Ljava/lang/Appendable;"); mv.visitInsn(Opcodes.POP); mv.visitLabel(l5); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitInsn(Opcodes.ARETURN); Label l9 = new Label(); mv.visitLabel(l9); mv.visitLocalVariable("this", Naming.internalToDesc(className), null, l0, l9, 0); mv.visitLocalVariable("a", "Ljava/lang/Appendable;", null, l0, l9, 1); // See comment above on ClassWriter.COMPUTE_FRAMES mv.visitMaxs(2, 2); mv.visitEnd(); }
From source file:com.sun.fortress.compiler.environments.TopLevelEnvGen.java
License:Open Source License
private static int dumpFields(MethodVisitor mv, String className, EnvironmentClass eClass, EnvSymbolNames symbolNames, int linebreaks) { for (String fieldName : symbolNames.getSymbolNames(eClass)) { Label l6 = new Label(); mv.visitLabel(l6);// w w w . jav a2 s. c o m mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitLdcInsn("(" + fieldName + " = "); mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Appendable", "append", "(Ljava/lang/CharSequence;)Ljava/lang/Appendable;"); mv.visitInsn(Opcodes.POP); Label l7 = new Label(); mv.visitLabel(l7); mv.visitVarInsn(Opcodes.ALOAD, 0); String idString = fieldName + eClass.namespace(); mv.visitFieldInsn(Opcodes.GETFIELD, className, Naming.mangleIdentifier(idString), eClass.descriptor()); Label l8 = new Label(); mv.visitJumpInsn(Opcodes.IFNULL, l8); Label l9 = new Label(); mv.visitLabel(l9); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitFieldInsn(Opcodes.GETFIELD, className, Naming.mangleIdentifier(idString), eClass.descriptor()); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, eClass.internalName(), "toString", "()Ljava/lang/String;"); mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Appendable", "append", "(Ljava/lang/CharSequence;)Ljava/lang/Appendable;"); mv.visitInsn(Opcodes.POP); Label afterNull = new Label(); mv.visitJumpInsn(Opcodes.GOTO, afterNull); mv.visitLabel(l8); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitLdcInsn("null"); mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Appendable", "append", "(Ljava/lang/CharSequence;)Ljava/lang/Appendable;"); mv.visitInsn(Opcodes.POP); mv.visitLabel(afterNull); mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitLdcInsn(") "); mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Appendable", "append", "(Ljava/lang/CharSequence;)Ljava/lang/Appendable;"); mv.visitInsn(Opcodes.POP); linebreaks = (linebreaks + 1) % 5; if (linebreaks == 0) { mv.visitVarInsn(Opcodes.ALOAD, 1); mv.visitLdcInsn("\n"); mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Appendable", "append", "(Ljava/lang/CharSequence;)Ljava/lang/Appendable;"); mv.visitInsn(Opcodes.POP); } } return linebreaks; }
From source file:com.sun.fortress.compiler.OverloadSet.java
License:Open Source License
public void generateCall(MethodVisitor mv, int firstArgIndex, int one_if_method_closure) { if (!splitDone) { throw new CompilerError("Must split overload set before generating call(s)"); }//from w w w . j a v a 2 s. c om int l = specificDispatchOrder.length; TaggedFunctionName[] functionsToCall = new TaggedFunctionName[l]; for (int i = 0; i < l; i++) { functionsToCall[i] = getFunctionToCall(specificDispatchOrder[i]); } // create type structures for parameter types. TypeStructure[][] type_structures = new TypeStructure[l][]; MultiMap[] spmaps = new MultiMap[l]; TypeStructure[] return_type_structures = new TypeStructure[l]; for (int i = 0; i < l; i++) { TaggedFunctionName f = functionsToCall[i]; Functional eff = f.getF(); List<Param> parameters = f.getParameters(); MultiMap<String, TypeStructure> spmap = new MultiMap<String, TypeStructure>(); spmaps[i] = spmap; List<StaticParam> staticParams = staticParametersOf(f.getF()); Type rt = oa.getRangeType(eff); return_type_structures[i] = makeTypeStructure(rt, null, 1, 0, staticParams, eff); // skip parameters -- no 'this' for ordinary functions if (parameters.size() == 1 && oa.getDomainType(eff) instanceof TupleType) { TupleType tt = (TupleType) oa.getDomainType(eff); List<Type> tl = tt.getElements(); int storeAtIndex = tl.size(); // DRC back this out + firstArgIndex; // little dubious here, not sure we are getting the // right type structures for generic methods. what about 'self' TypeStructure[] f_type_structures = new TypeStructure[tl.size()]; type_structures[i] = f_type_structures; for (int j = 0; j < tl.size(); j++) { Type t = STypesUtil.insertStaticParams(tl.get(j), tt.getInfo().getStaticParams()); TypeStructure type_structure = makeTypeStructure(t, spmap, 1, storeAtIndex, staticParams, eff); f_type_structures[j] = type_structure; storeAtIndex = type_structure.successorIndex; } } else { int storeAtIndex = parameters.size(); // DRC back this out + firstArgIndex; TypeStructure[] f_type_structures = new TypeStructure[parameters.size()]; type_structures[i] = f_type_structures; for (int j = 0; j < parameters.size(); j++) { if (j != selfIndex()) { Type t = oa.getParamType(eff, j); TypeStructure type_structure = makeTypeStructure(t, spmap, 1, storeAtIndex, staticParams, eff); f_type_structures[j] = type_structure; storeAtIndex = type_structure.successorIndex; } } } } for (int i = 0; i < l; i++) { TaggedFunctionName f = functionsToCall[i]; TypeStructure[] f_type_structures = type_structures[i]; Label lookahead = null; boolean infer = false; List<StaticParam> staticParams = staticParametersOf(f.getF()); boolean last_case = i == l - 1; /* Trust the static checker; no need to verify * applicability of the last one. * Also, static parameters will be provided by static checker for the last one */ // Will need lookahead for the next one. lookahead = new Label(); // if this was a generic method that needs inference, we need to include the receiver argument // in the inference even if the firstArgIndex is 1 so that we can include it in inference // and dispatch //KBN-WIP is there a cleaner way to do this? int offset = (f_type_structures.length == specificDispatchOrder[i].getParameters().size()) ? firstArgIndex : 0; for (int j = 0; j < f_type_structures.length; j++) { if (j != selfIndex()) { //inference needed if the type structure contains generics TODO: do generics not appearing in the parameters make sense? probably not, but might need to deal with them. if (f_type_structures[j].containsTypeVariables) infer = true; } } if (infer || !last_case) for (int j = 0; j < f_type_structures.length; j++) { // Load actual parameter if (j != selfIndex()) { mv.visitVarInsn(Opcodes.ALOAD, j + offset); f_type_structures[j].emitInstanceOf(mv, lookahead, true); } } //Runtime inference for some cases if (infer) { @SuppressWarnings("unchecked") MultiMap<String, TypeStructure> staticTss = spmaps[i]; int localCount = f_type_structures[f_type_structures.length - 1].successorIndex; //counter for use storing stuff such as lower bounds //create type structures for lower bounds Map<StaticParam, TypeStructure> lowerBounds = new HashMap<StaticParam, TypeStructure>(); for (StaticParam sp : staticParams) lowerBounds.put(sp, makeParamTypeStructure(sp, localCount++, TypeStructure.COVARIANT)); //gather different types of bounds into Multimaps for use later MultiMap<StaticParam, StaticParam> relativeLowerBounds = new MultiMap<StaticParam, StaticParam>(); //form X :> Y MultiMap<StaticParam, Type> genericUpperBounds = new MultiMap<StaticParam, Type>(); //form X <: GenericStem[\ ... \] where Y appears in ... MultiMap<StaticParam, Type> concreteUpperBounds = new MultiMap<StaticParam, Type>(); //form X <: T where T contains no type variables for (int outer = 0; outer < staticParams.size(); outer++) { StaticParam outerSP = staticParams.get(outer); for (BaseType bt : outerSP.getExtendsClause()) { if (bt instanceof VarType) { // outerSP <: bt so outerSP will provide a lower bound on BT String varName = ((VarType) bt).getName().getText(); boolean found = false; for (int inner = 0; inner < outer && !found; inner++) { StaticParam innerSP = staticParams.get(inner); if (varName.equals(innerSP.getName().getText())) { relativeLowerBounds.putItem(innerSP, outerSP); // outerSP provides a lower bound on innerSP found = true; } } if (!found) throw new CompilerError( "Bad Scoping of static parameters found during runtime inference codegen:" + varName + " not declared before used in a bound"); } else if (bt instanceof AnyType) { //figure out if concrete or generic //do nothing - no need to add meaningless upper bound } else if (bt instanceof NamedType) { if (isGeneric(bt)) genericUpperBounds.putItem(outerSP, bt); else concreteUpperBounds.putItem(outerSP, bt); } } } //infer and load RTTIs for (int j = 0; j < staticParams.size(); j++) { StaticParam sp = staticParams.get(staticParams.size() - 1 - j); //reverse order due to left to right scoping Set<TypeStructure> instances = staticTss.get(sp.getName().getText()); //sort static parameters by their variance and put into //arrays using their local variable number List<Integer> invariantInstances = new ArrayList<Integer>(); List<Integer> covariantInstances = new ArrayList<Integer>(); List<Integer> contravariantInstances = new ArrayList<Integer>(); if (instances != null) for (TypeStructure ts : instances) { switch (ts.variance) { case TypeStructure.INVARIANT: invariantInstances.add(ts.localIndex); break; case TypeStructure.CONTRAVARIANT: contravariantInstances.add(ts.localIndex); break; case TypeStructure.COVARIANT: covariantInstances.add(ts.localIndex); break; default: throw new CompilerError("Unexpected Variance on TypeStructure during " + "generic instantiation analysis for overload dispatch"); } } // if any invariant instances, we must use that RTTI and check that //1) any other invariant instances are the same type (each subtypes the other) //2) any covariant instances are subtypes of the invariant instance //3) any contravariant instances are supertypes of the invariant instance if (invariantInstances.size() > 0) { //a valid instantiation must use the runtime type //of all invariant instances (which must all be the same) //thus, wlog, we can use the first invariant instance int RTTItoUse = invariantInstances.get(0); //1) for each other invariant instance, they must be the same //which we test by checking that each subtypes the other for (int k = 1; k < invariantInstances.size(); k++) { int RTTIcompare = invariantInstances.get(k); //RTTItoUse.runtimeSupertypeOf(RTTIcompare) mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); mv.visitVarInsn(Opcodes.ALOAD, RTTIcompare); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail //RTTIcompare.runtimeSupertypeOf(RTTItoUse) mv.visitVarInsn(Opcodes.ALOAD, RTTIcompare); mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail } //2) for each covariant instance, the runtime type (RTTIcompare) must be a // subtype of the instantiated type (RTTItoUse) for (int RTTIcompare : covariantInstances) { //RTTItoUse.runtimeSupertypeOf(RTTIcompare) mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); mv.visitVarInsn(Opcodes.ALOAD, RTTIcompare); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail } //3) for each contravariant instance, the instantiated type (RTTItoUse) must be a // subtype of the runtime type (RTTIcompare) for (int RTTIcompare : contravariantInstances) { //RTTIcompare.runtimeSupertypeOf(RTTItoUse) mv.visitVarInsn(Opcodes.ALOAD, RTTIcompare); mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail } //check lower bounds given by other variables Set<StaticParam> relativeLB = relativeLowerBounds.get(sp); if (relativeLB != null) for (StaticParam lb : relativeLB) { //RTTItoUse.runtimeSupertypeOf(otherLB) int otherOffset = lowerBounds.get(lb).localIndex; mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); mv.visitVarInsn(Opcodes.ALOAD, otherOffset); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail } //verify meets upper bounds Set<Type> concreteUB = concreteUpperBounds.get(sp); if (concreteUB != null) for (Type cub : concreteUB) { //transform into RTTI generateRTTIfromStaticType(mv, cub); mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail } //generate more bounds for generic upper bounds Set<Type> genericUB = genericUpperBounds.get(sp); if (genericUB != null) for (Type gub : genericUB) { TypeStructure newTS = makeTypeStructure(gub, staticTss, TypeStructure.COVARIANT, localCount, staticParams, null); localCount = newTS.successorIndex; mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); newTS.emitInstanceOf(mv, lookahead, false); //fail if RTTItoUse doesn't have this structure } //checks out, so store the RTTI we will use into the lower bound for this parameter mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse); int index = lowerBounds.get(sp).localIndex; mv.visitVarInsn(Opcodes.ASTORE, index); } else if (contravariantInstances.size() == 0) { //we can do inference for covariant-only occurrences boolean started = false; if (covariantInstances.size() > 0) { started = true; mv.visitVarInsn(Opcodes.ALOAD, covariantInstances.get(0)); for (int k = 1; k < covariantInstances.size(); k++) { mv.visitVarInsn(Opcodes.ALOAD, covariantInstances.get(k)); //TODO: allow unions joinStackNoUnion(mv, lookahead); //fails if cannot join w/o union } } //incorporate lower bounds Set<StaticParam> relativeLB = relativeLowerBounds.get(sp); if (relativeLB != null) for (StaticParam lb : relativeLB) { mv.visitVarInsn(Opcodes.ALOAD, lowerBounds.get(lb).localIndex); if (started) { //join it in //TODO: allow unions joinStackNoUnion(mv, lookahead); } else { //start with this lower bound started = true; } } if (started) { //verify meets upper bounds Set<Type> concreteUB = concreteUpperBounds.get(sp); if (concreteUB != null) for (Type cub : concreteUB) { Label cleanup = new Label(); Label next = new Label(); mv.visitInsn(Opcodes.DUP); generateRTTIfromStaticType(mv, cub); //transform concrete bound into RTTI mv.visitInsn(Opcodes.SWAP); // LB <: CUB mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG); mv.visitJumpInsn(Opcodes.IFEQ, cleanup); mv.visitJumpInsn(Opcodes.GOTO, next); mv.visitLabel(cleanup); mv.visitInsn(Opcodes.POP); mv.visitJumpInsn(Opcodes.GOTO, lookahead); mv.visitLabel(next); } //checks out, so store to lower bound of sp int index = lowerBounds.get(sp).localIndex; mv.visitVarInsn(Opcodes.ASTORE, index); //generate more bounds for generic upper bounds Set<Type> genericUB = genericUpperBounds.get(sp); if (genericUB != null) for (Type gub : genericUB) { TypeStructure newTS = makeTypeStructure(gub, staticTss, TypeStructure.COVARIANT, localCount, staticParams, null); localCount = newTS.successorIndex; mv.visitVarInsn(Opcodes.ALOAD, index); newTS.emitInstanceOf(mv, lookahead, false); //fail if candidate doesn't have this structure } } else { //Bottom is ok - no need to check upper bounds //or generate lower bounds mv.visitFieldInsn(Opcodes.GETSTATIC, Naming.RT_VALUES_PKG + "VoidRTTI", Naming.RTTI_SINGLETON, Naming.RTTI_CONTAINER_DESC); int index = lowerBounds.get(sp).localIndex; mv.visitVarInsn(Opcodes.ASTORE, index); } } else { //otherwise, we might need to do inference which is not implemented yet throw new CompilerError("non-invariant inference with contravariance not implemented"); } } //load instance cache table to avoid classloader when possible String tableName = this.generateClosureTableName(specificDispatchOrder[i]); //use original function for table name String tableOwner = this.generateClosureTableOwner(f); mv.visitFieldInsn(Opcodes.GETSTATIC, tableOwner, tableName, Naming.CACHE_TABLE_DESC); //load template class name String arrow = this.instanceArrowSchema(f); //NamingCzar.makeArrowDescriptor(f.getParameters(), f.getReturnType(),f.tagA); String functionName = this.functionName(f); String templateClass = Naming.genericFunctionPkgClass(Naming.dotToSep(f.tagA.getText()), functionName, Naming.LEFT_OXFORD + Naming.RIGHT_OXFORD, arrow); if (otherOverloadKeys.contains(templateClass)) { templateClass = Naming.genericFunctionPkgClass(Naming.dotToSep(f.tagA.getText()), NamingCzar.mangleAwayFromOverload(functionName), Naming.LEFT_OXFORD + Naming.RIGHT_OXFORD, arrow); //templateClass = NamingCzar.mangleAwayFromOverload(templateClass); } mv.visitLdcInsn(templateClass); String ic_sig; if (staticParams.size() > 6) { //use an array //load the function: RThelpers.loadClosureClass:(BAlongTree,String,RTTI[]) String paramList = Naming.CACHE_TABLE_DESC + NamingCzar.descString + Naming.RTTI_CONTAINER_ARRAY_DESC; ic_sig = Naming.makeMethodDesc(paramList, Naming.internalToDesc(NamingCzar.internalObject)); mv.visitLdcInsn(staticParams.size()); mv.visitTypeInsn(Opcodes.ANEWARRAY, Naming.RTTI_CONTAINER_TYPE); //dup array enough times to store RTTIs into it //know need at least 6 more mv.visitInsn(Opcodes.DUP); //first one to get arrays as top two elts on stack for (int numDups = staticParams.size() - 1; numDups > 0; numDups = numDups / 2) mv.visitInsn(Opcodes.DUP2); if (staticParams.size() % 2 == 0) mv.visitInsn(Opcodes.DUP); //if even, started halving with an odd number, so needs one last //store parameters into array for (int k = 0; k < staticParams.size(); k++) { int index = lowerBounds.get(staticParams.get(k)).localIndex; mv.visitLdcInsn(k); //index is the static param number mv.visitVarInsn(Opcodes.ALOAD, index); mv.visitInsn(Opcodes.AASTORE); } //array left on stack } else { //load the function: RTHelpers.loadClosureClass:(BAlongTree,(String,RTTI)^n)Object ic_sig = InstantiatingClassloader.jvmSignatureForOnePlusNTypes( Naming.CACHE_TABLE_TYPE + ";L" + NamingCzar.internalString, staticParams.size(), Naming.RTTI_CONTAINER_TYPE, Naming.internalToDesc(NamingCzar.internalObject)); //load parameter RTTIs for (int k = 0; k < staticParams.size(); k++) { int index = lowerBounds.get(staticParams.get(k)).localIndex; mv.visitVarInsn(Opcodes.ALOAD, index); } } mv.visitMethodInsn(Opcodes.INVOKESTATIC, Naming.RT_HELPERS, "loadClosureClass", ic_sig); //cast to object arrow int numParams = f.getParameters().size(); String objectAbstractArrow = NamingCzar.objectAbstractArrowTypeForNParams(numParams); InstantiatingClassloader.generalizedCastTo(mv, objectAbstractArrow); //if a method parameters converted //loadThisForMethods(mv); //load parameters for (int j = 0; j < f_type_structures.length; j++) { // Load actual parameter if (j != selfIndex()) { mv.visitVarInsn(Opcodes.ALOAD, j); // DRC back this out+ one_if_method_closure); // + firstArgIndex); KBN if a method, parameters already converted //no cast needed here - done by apply method } } //call apply method String objectArrow = NamingCzar.objectArrowTypeForNParams(numParams); String applySig = InstantiatingClassloader.jvmSignatureForNTypes(numParams, NamingCzar.internalObject, Naming.internalToDesc(NamingCzar.internalObject)); mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, objectArrow, Naming.APPLY_METHOD, applySig); //cast to correct return type Type f_return = f.getReturnType(); if (f_return instanceof BottomType) { CodeGen.castToBottom(mv); } else { String returnType = NamingCzar.makeBoxedTypeName(f_return, f.tagA); InstantiatingClassloader.generalizedCastTo(mv, returnType); } } else { //no inferences needed loadThisForMethods(mv); for (int j = 0; j < f_type_structures.length; j++) { // Load actual parameter if (j != selfIndex()) { mv.visitVarInsn(Opcodes.ALOAD, j + firstArgIndex); InstantiatingClassloader.generalizedCastTo(mv, f_type_structures[j].fullname); } } String sig = jvmSignatureFor(f); invokeParticularMethod(mv, f, sig); Type f_return = f.getReturnType(); if (f_return instanceof BottomType) { CodeGen.castToBottom(mv); } } mv.visitInsn(Opcodes.ARETURN); if (lookahead != null) mv.visitLabel(lookahead); } }