Example usage for org.objectweb.asm Opcodes ANEWARRAY

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

Introduction

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

Prototype

int ANEWARRAY

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

Click Source Link

Usage

From source file:com.offbynull.coroutines.instrumenter.LocalsStateGenerators.java

License:Open Source License

/**
 * Generates instructions to save the local variables table.
 * @param markerType debug marker type//www.  j a  v a2 s . c  o  m
 * @param storageVars variables to store locals in to
 * @param frame execution frame at the instruction where the local variables table is to be saved
 * @return instructions to save the local variables table in to an array
 * @throws NullPointerException if any argument is {@code null}
 */
public static InsnList saveLocals(MarkerType markerType, StorageVariables storageVars,
        Frame<BasicValue> frame) {
    Validate.notNull(markerType);
    Validate.notNull(storageVars);
    Validate.notNull(frame);

    Variable intsVar = storageVars.getIntStorageVar();
    Variable floatsVar = storageVars.getFloatStorageVar();
    Variable longsVar = storageVars.getLongStorageVar();
    Variable doublesVar = storageVars.getDoubleStorageVar();
    Variable objectsVar = storageVars.getObjectStorageVar();

    int intsCounter = 0;
    int floatsCounter = 0;
    int longsCounter = 0;
    int doublesCounter = 0;
    int objectsCounter = 0;

    StorageSizes storageSizes = computeSizes(frame);

    InsnList ret = new InsnList();

    // Create storage arrays and save them in respective storage vars
    ret.add(merge(debugMarker(markerType, "Saving locals"), mergeIf(intsVar != null, () -> 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(floatsVar != null,
                    () -> 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(longsVar != null, () -> 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(doublesVar != null, () -> 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(objectsVar != null,
                    () -> 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 locals
    for (int i = 0; i < frame.getLocals(); i++) {
        BasicValue basicValue = frame.getLocal(i);
        Type type = basicValue.getType();

        // If type == null, basicValue is pointing to uninitialized var -- basicValue.toString() will return '.'. This means that this
        // slot contains nothing to save. So, skip this slot if we encounter it.
        if (type == null) {
            ret.add(debugMarker(markerType, "Skipping uninitialized value at " + i));
            continue;
        }

        // 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. 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));
            continue;
        }

        // Place item in to appropriate storage array
        switch (type.getSort()) {
        case Type.BOOLEAN:
        case Type.BYTE:
        case Type.SHORT:
        case Type.CHAR:
        case Type.INT:
            ret.add(debugMarker(markerType,
                    "Inserting int at LVT index " + i + " to storage index " + intsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, intsVar.getIndex())); // [int[]]
            ret.add(new LdcInsnNode(intsCounter)); // [int[], idx]
            ret.add(new VarInsnNode(Opcodes.ILOAD, i)); // [int[], idx, val]
            ret.add(new InsnNode(Opcodes.IASTORE)); // []
            intsCounter++;
            break;
        case Type.FLOAT:
            ret.add(debugMarker(markerType,
                    "Inserting float at LVT index " + i + " to storage index " + floatsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, floatsVar.getIndex())); // [float[]]
            ret.add(new LdcInsnNode(floatsCounter)); // [float[], idx]
            ret.add(new VarInsnNode(Opcodes.FLOAD, i)); // [float[], idx, val]
            ret.add(new InsnNode(Opcodes.FASTORE)); // []
            floatsCounter++;
            break;
        case Type.LONG:
            ret.add(debugMarker(markerType,
                    "Inserting long at LVT index " + i + " to storage index " + longsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, longsVar.getIndex())); // [long[]]
            ret.add(new LdcInsnNode(longsCounter)); // [long[], idx]
            ret.add(new VarInsnNode(Opcodes.LLOAD, i)); // [long[], idx, val]
            ret.add(new InsnNode(Opcodes.LASTORE)); // []
            longsCounter++;
            break;
        case Type.DOUBLE:
            ret.add(debugMarker(markerType,
                    "Inserting double at LVT index " + i + " to storage index " + doublesCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, doublesVar.getIndex())); // [double[]]
            ret.add(new LdcInsnNode(doublesCounter)); // [double[], idx]
            ret.add(new VarInsnNode(Opcodes.DLOAD, i)); // [double[], idx, val]
            ret.add(new InsnNode(Opcodes.DASTORE)); // []
            doublesCounter++;
            break;
        case Type.ARRAY:
        case Type.OBJECT:
            ret.add(debugMarker(markerType,
                    "Inserting object at LVT index " + i + " to storage index " + objectsCounter));
            ret.add(new VarInsnNode(Opcodes.ALOAD, objectsVar.getIndex())); // [Object[]]
            ret.add(new LdcInsnNode(objectsCounter)); // [Object[], idx]
            ret.add(new VarInsnNode(Opcodes.ALOAD, i)); // [Object[], idx, val]
            ret.add(new InsnNode(Opcodes.AASTORE)); // []
            objectsCounter++;
            break;
        case Type.METHOD:
        case Type.VOID:
        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  w  w . j a va 2  s . c om
 * 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.offbynull.coroutines.instrumenter.PackStateGenerators.java

License:Open Source License

public static InsnList packStorageArrays(MarkerType markerType, Frame<BasicValue> frame, Variable containerVar,
        StorageVariables localsStorageVars, StorageVariables operandStackStorageVars) {
    Validate.notNull(markerType);/*from w ww.  j  a  v  a2  s.c o m*/
    Validate.notNull(frame);
    Validate.notNull(containerVar);
    Validate.notNull(localsStorageVars);
    Validate.notNull(operandStackStorageVars);

    Variable localsIntsVar = localsStorageVars.getIntStorageVar();
    Variable localsFloatsVar = localsStorageVars.getFloatStorageVar();
    Variable localsLongsVar = localsStorageVars.getLongStorageVar();
    Variable localsDoublesVar = localsStorageVars.getDoubleStorageVar();
    Variable localsObjectsVar = localsStorageVars.getObjectStorageVar();
    Variable stackIntsVar = operandStackStorageVars.getIntStorageVar();
    Variable stackFloatsVar = operandStackStorageVars.getFloatStorageVar();
    Variable stackLongsVar = operandStackStorageVars.getLongStorageVar();
    Variable stackDoublesVar = operandStackStorageVars.getDoubleStorageVar();
    Variable stackObjectsVar = operandStackStorageVars.getObjectStorageVar();

    StorageSizes stackSizes = OperandStackStateGenerators.computeSizes(frame, 0, frame.getStackSize());
    StorageSizes localsSizes = LocalsStateGenerators.computeSizes(frame);

    // Why are we using size > 0 vs checking to see if var != null?
    //
    // REMEMBER THAT the analyzer will determine the variable slots to create for storage array based on its scan of EVERY
    // continuation/suspend point in the method. Imagine the method that we're instrumenting is this...
    //
    // public void example(Continuation c, String arg1) {
    //     String var1 = "hi";
    //     c.suspend();     
    //
    //     System.out.println(var1);
    //     int var2 = 5;
    //     c.suspend();
    //
    //     System.out.println(var1 + var2);
    // }
    //
    // There are two continuation/suspend points. The analyzer determines that method will need to assign variable slots for
    // localsObjectsVar+localsIntsVar. All the other locals vars will be null.
    //
    // If we ended up using var != null instead of size > 0, things would mess up on the first suspend(). The only variable initialized
    // at the first suspend is var1. As such, LocalStateGenerator ONLY CREATES AN ARRAY FOR localsObjectsVar. It doesn't touch
    // localsIntsVar because, at the first suspend(), var2 is UNINITALIZED. Nothing has been set to that variable slot.
    //
    //
    // The same thing applies to the operand stack. It doesn't make sense to create arrays for operand stack types that don't exist yet
    // at a continuation point, even though they may exist at other continuation points furhter down

    // Storage arrays in to locals container
    return merge(
            debugMarker(markerType, "Packing storage arrays for locals and operand stack in to an Object[]"),
            new LdcInsnNode(10), new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object"),
            new VarInsnNode(Opcodes.ASTORE, containerVar.getIndex()),
            mergeIf(localsSizes.getIntsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting locals ints in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(0), // [Object[], 0]
                            new VarInsnNode(Opcodes.ALOAD, localsIntsVar.getIndex()), // [Object[], 0, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(localsSizes.getFloatsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting locals floats in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(1), // [Object[], 1]
                            new VarInsnNode(Opcodes.ALOAD, localsFloatsVar.getIndex()), // [Object[], 1, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(localsSizes.getLongsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting locals longs in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(2), // [Object[], 2]
                            new VarInsnNode(Opcodes.ALOAD, localsLongsVar.getIndex()), // [Object[], 2, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(localsSizes.getDoublesSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting locals doubles in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(3), // [Object[], 3]
                            new VarInsnNode(Opcodes.ALOAD, localsDoublesVar.getIndex()), // [Object[], 3, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(localsSizes.getObjectsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting locals objects in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(4), // [Object[], 4]
                            new VarInsnNode(Opcodes.ALOAD, localsObjectsVar.getIndex()), // [Object[], 4, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(stackSizes.getIntsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting stack ints in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(5), // [Object[], 5]
                            new VarInsnNode(Opcodes.ALOAD, stackIntsVar.getIndex()), // [Object[], 5, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(stackSizes.getFloatsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting stack floats in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(6), // [Object[], 6]
                            new VarInsnNode(Opcodes.ALOAD, stackFloatsVar.getIndex()), // [Object[], 6, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(stackSizes.getLongsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting stack longs in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(7), // [Object[], 7]
                            new VarInsnNode(Opcodes.ALOAD, stackLongsVar.getIndex()), // [Object[], 7, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(stackSizes.getDoublesSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting stack doubles in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(8), // [Object[], 8]
                            new VarInsnNode(Opcodes.ALOAD, stackDoublesVar.getIndex()), // [Object[], 8, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }),
            mergeIf(stackSizes.getObjectsSize() > 0,
                    () -> new Object[] { debugMarker(markerType, "Putting stack objects in to container"),
                            new VarInsnNode(Opcodes.ALOAD, containerVar.getIndex()), // [Object[]]
                            new LdcInsnNode(9), // [Object[], 9]
                            new VarInsnNode(Opcodes.ALOAD, stackObjectsVar.getIndex()), // [Object[], 9, val]
                            new InsnNode(Opcodes.AASTORE), // []
                    }));
}

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 av a 2s  .c  o m
    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);
    }
}

From source file:com.sun.fortress.runtimeSystem.InstantiatingClassloader.java

License:Open Source License

/**
 * @param rttiClassName//  ww  w  .  j a  v  a 2s . c o  m
 * @param sparams_size
 */
static public void emitDictionaryAndFactoryForGenericRTTIclass(ManglingClassWriter cw, String rttiClassName,
        int sparams_size, final Naming.XlationData xldata) {

    // Push nulls for opr parameters in the factory call.
    List<Boolean> spks;
    int type_sparams_size = sparams_size;
    if (xldata != null) {
        spks = xldata.isOprKind();
        sparams_size = spks.size();
    } else {
        spks = new InfiniteList<Boolean>(false);
    }

    // FIELD
    // static, initialized to Map-like thing
    cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_FINAL, "DICTIONARY", Naming.RTTI_MAP_DESC, null, null);

    // CLINIT
    // factory, consulting map, optionally invoking constructor.
    MethodVisitor mv = cw.visitNoMangleMethod(ACC_STATIC, "<clinit>", "()V", null, null);
    mv.visitCode();
    // new
    mv.visitTypeInsn(NEW, Naming.RTTI_MAP_TYPE);
    // init
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESPECIAL, Naming.RTTI_MAP_TYPE, "<init>", "()V");
    // store
    mv.visitFieldInsn(PUTSTATIC, rttiClassName, "DICTIONARY", Naming.RTTI_MAP_DESC);

    mv.visitInsn(RETURN);
    mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);
    mv.visitEnd();

    // FACTORY

    boolean useSparamsArray = sparams_size > 6;
    int sparamsArrayIndex = sparams_size;

    String fact_sig = Naming.rttiFactorySig(type_sparams_size);
    String init_sig = InstantiatingClassloader.jvmSignatureForOnePlusNTypes("java/lang/Class",
            type_sparams_size, Naming.RTTI_CONTAINER_TYPE, "V");
    String get_sig;
    String put_sig;
    String getClass_sig;
    if (useSparamsArray) {
        get_sig = Naming.makeMethodDesc(Naming.RTTI_CONTAINER_ARRAY_DESC, Naming.RTTI_CONTAINER_DESC);
        put_sig = Naming.makeMethodDesc(Naming.RTTI_CONTAINER_ARRAY_DESC + Naming.RTTI_CONTAINER_DESC,
                Naming.RTTI_CONTAINER_DESC);
        getClass_sig = Naming.makeMethodDesc(NamingCzar.descString + Naming.RTTI_CONTAINER_ARRAY_DESC,
                NamingCzar.descClass);
    } else {
        get_sig = InstantiatingClassloader.jvmSignatureForNTypes(sparams_size, Naming.RTTI_CONTAINER_TYPE,
                Naming.RTTI_CONTAINER_DESC);
        put_sig = InstantiatingClassloader.jvmSignatureForNTypes(sparams_size + 1, Naming.RTTI_CONTAINER_TYPE,
                Naming.RTTI_CONTAINER_DESC);
        getClass_sig = InstantiatingClassloader.jvmSignatureForOnePlusNTypes(NamingCzar.internalString,
                sparams_size, Naming.RTTI_CONTAINER_TYPE, NamingCzar.descClass);
    }

    mv = cw.visitNoMangleMethod(ACC_PUBLIC + ACC_STATIC, Naming.RTTI_FACTORY, fact_sig, null, null);
    mv.visitCode();
    /* 
     * First arg is java class, necessary for creation of type.
     * 
     * rCN x = DICTIONARY.get(args)
     * if  x == null then
     *   x = new rCN(args)
     *   x = DICTIONARY.put(args, x)
     * end
     * return x
     */

    // object
    mv.visitFieldInsn(GETSTATIC, rttiClassName, "DICTIONARY", Naming.RTTI_MAP_DESC);
    // push args
    int l = sparams_size;
    if (useSparamsArray) {
        mv.visitLdcInsn(sparams_size);
        mv.visitTypeInsn(Opcodes.ANEWARRAY, Naming.RTTI_CONTAINER_TYPE);
        mv.visitVarInsn(Opcodes.ASTORE, sparamsArrayIndex);
        InstantiatingClassloader.pushArgsIntoArray(mv, 0, l, sparamsArrayIndex, spks);
    } else {
        InstantiatingClassloader.pushArgs(mv, 0, l, spks);
    }
    // invoke Dictionary.get
    mv.visitMethodInsn(INVOKEVIRTUAL, Naming.RTTI_MAP_TYPE, "get", get_sig);
    Label not_null = new Label();
    mv.visitInsn(DUP);
    mv.visitJumpInsn(IFNONNULL, not_null);
    mv.visitInsn(POP); // discard dup'd null
    // doing it all on the stack -- (unless too many static params, then use an array for human coded stuff)
    // 1) first push the dictionary and args (array if used) 
    // 2) create new RTTI object
    // 3) push args again (array if used) and create the class for this object
    // 4) push the args again (never array) to init RTTI object
    // 5) add to dictionary

    //1)
    mv.visitFieldInsn(GETSTATIC, rttiClassName, "DICTIONARY", Naming.RTTI_MAP_DESC);

    if (useSparamsArray) {
        mv.visitVarInsn(ALOAD, sparamsArrayIndex);
    } else {
        InstantiatingClassloader.pushArgs(mv, 0, l, spks);
    }

    // 2) invoke constructor
    mv.visitTypeInsn(NEW, rttiClassName);
    mv.visitInsn(DUP);

    // 3) create class for this object
    String stem = Naming.rttiClassToBaseClass(rttiClassName);
    if (true || xldata == null) {
        // NOT symbolic (and a problem if we pretend that it is)
        mv.visitLdcInsn(stem);
    } else {
        RTHelpers.symbolicLdc(mv, stem);
    }
    if (useSparamsArray) {
        mv.visitVarInsn(ALOAD, sparamsArrayIndex);
    } else {
        InstantiatingClassloader.pushArgs(mv, 0, l, spks);
    }

    //(mv, "before getRTTIclass");
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, Naming.RT_HELPERS, "getRTTIclass", getClass_sig);
    //eep(mv, "after getRTTIclass");

    // 4) init RTTI object (do not use array)
    // NOTE only pushing type_sparams here.
    InstantiatingClassloader.pushArgs(mv, 0, type_sparams_size);
    mv.visitMethodInsn(INVOKESPECIAL, rttiClassName, "<init>", init_sig);
    // 5) add to dictionary
    mv.visitMethodInsn(INVOKEVIRTUAL, Naming.RTTI_MAP_TYPE, "putIfNew", put_sig);

    mv.visitLabel(not_null);
    mv.visitInsn(ARETURN);

    mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);
    mv.visitEnd();
}

From source file:com.trigersoft.jaque.expression.ExpressionMethodVisitor.java

License:Apache License

@Override
public void visitTypeInsn(int opcode, String type) {
    Class<?> resultType = _classVisitor.getClass(Type.getObjectType(type));
    Expression e;/*w w w.j  a v  a  2 s.  c  o m*/
    switch (opcode) {
    case Opcodes.NEW:
        e = Expression.constant(null, resultType);
        break;
    case Opcodes.CHECKCAST:
        if (resultType == Object.class)
            // there is no point in casting to object
            return;
        // TODO
        return;
    case Opcodes.ANEWARRAY:
    default:
        throw notLambda(opcode);
    case Opcodes.INSTANCEOF:
        e = Expression.instanceOf(_exprStack.pop(), resultType);
        break;
    }

    _exprStack.push(e);
}

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

public void emitNewArray(TypeWidget elementType, BytecodeExpression e) {
    MethodVisitor mv = getMethodVisitor();
    exec(e);// www .j  a v a  2  s .c  o m
    cast(BaseTypeAdapter.INT32, e.getType());
    switch (elementType.getJVMType().getSort()) {
    case Type.BYTE:
        mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BYTE);
        break;
    case Type.BOOLEAN:
        mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_BOOLEAN);
        break;
    case Type.SHORT:
        mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_SHORT);
        break;
    case Type.INT:
        mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_INT);
        break;
    case Type.CHAR:
        mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_CHAR);
        break;
    case Type.FLOAT:
        mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_FLOAT);
        break;
    case Type.LONG:
        mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_LONG);
        break;
    case Type.DOUBLE:
        mv.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_DOUBLE);
        break;
    case Type.OBJECT:
        mv.visitTypeInsn(Opcodes.ANEWARRAY, elementType.getJVMType().getInternalName());
        break;
    default:
        throw new UnsupportedOperationException("unknown sort for newArray" + elementType.getJVMType());
    }

}

From source file:de.thetaphi.forbiddenapis.ClassScanner.java

License:Apache License

@Override
public MethodVisitor visitMethod(final int access, final String name, final String desc, String signature,
        String[] exceptions) {/*  w w  w.j  a v  a  2 s .c  o m*/
    currentGroupId++;
    if (classSuppressed) {
        return null;
    }
    return new MethodVisitor(Opcodes.ASM5) {
        private final Method myself = new Method(name, desc);
        private final boolean isDeprecated = (access & Opcodes.ACC_DEPRECATED) != 0;
        private int lineNo = -1;

        {
            // only check signature, if method is not synthetic
            if ((access & Opcodes.ACC_SYNTHETIC) == 0) {
                reportMethodViolation(checkDescriptor(desc), "method declaration");
            }
            if (this.isDeprecated) {
                maybeSuppressCurrentGroup(DEPRECATED_TYPE);
                reportMethodViolation(checkType(DEPRECATED_TYPE), "deprecation on method declaration");
            }
        }

        private String checkMethodAccess(String owner, Method method) {
            String violation = checkClassUse(owner, "class/interface");
            if (violation != null) {
                return violation;
            }
            final String printout = forbiddenMethods.get(owner + '\000' + method);
            if (printout != null) {
                return "Forbidden method invocation: " + printout;
            }
            final ClassSignature c = lookup.lookupRelatedClass(owner);
            if (c != null && !c.methods.contains(method)) {
                if (c.superName != null && (violation = checkMethodAccess(c.superName, method)) != null) {
                    return violation;
                }
                // JVM spec says: interfaces after superclasses
                if (c.interfaces != null) {
                    for (String intf : c.interfaces) {
                        if (intf != null && (violation = checkMethodAccess(intf, method)) != null) {
                            return violation;
                        }
                    }
                }
            }
            return null;
        }

        private String checkFieldAccess(String owner, String field) {
            String violation = checkClassUse(owner, "class/interface");
            if (violation != null) {
                return violation;
            }
            final String printout = forbiddenFields.get(owner + '\000' + field);
            if (printout != null) {
                return "Forbidden field access: " + printout;
            }
            final ClassSignature c = lookup.lookupRelatedClass(owner);
            if (c != null && !c.fields.contains(field)) {
                if (c.interfaces != null) {
                    for (String intf : c.interfaces) {
                        if (intf != null && (violation = checkFieldAccess(intf, field)) != null) {
                            return violation;
                        }
                    }
                }
                // JVM spec says: superclasses after interfaces
                if (c.superName != null && (violation = checkFieldAccess(c.superName, field)) != null) {
                    return violation;
                }
            }
            return null;
        }

        private String checkHandle(Handle handle, boolean checkLambdaHandle) {
            switch (handle.getTag()) {
            case Opcodes.H_GETFIELD:
            case Opcodes.H_PUTFIELD:
            case Opcodes.H_GETSTATIC:
            case Opcodes.H_PUTSTATIC:
                return checkFieldAccess(handle.getOwner(), handle.getName());
            case Opcodes.H_INVOKEVIRTUAL:
            case Opcodes.H_INVOKESTATIC:
            case Opcodes.H_INVOKESPECIAL:
            case Opcodes.H_NEWINVOKESPECIAL:
            case Opcodes.H_INVOKEINTERFACE:
                final Method m = new Method(handle.getName(), handle.getDesc());
                if (checkLambdaHandle && handle.getOwner().equals(internalMainClassName)
                        && handle.getName().startsWith(LAMBDA_METHOD_NAME_PREFIX)) {
                    // as described in <http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html>,
                    // we will record this metafactory call as "lambda" invokedynamic,
                    // so we can assign the called lambda with the same groupId like *this* method:
                    lambdas.put(m, currentGroupId);
                }
                return checkMethodAccess(handle.getOwner(), m);
            }
            return null;
        }

        private String checkConstant(Object cst, boolean checkLambdaHandle) {
            if (cst instanceof Type) {
                return checkType((Type) cst);
            } else if (cst instanceof Handle) {
                return checkHandle((Handle) cst, checkLambdaHandle);
            }
            return null;
        }

        @Override
        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
            if (this.isDeprecated && DEPRECATED_DESCRIPTOR.equals(desc)) {
                // don't report 2 times!
                return null;
            }
            final Type type = Type.getType(desc);
            maybeSuppressCurrentGroup(type);
            reportMethodViolation(checkAnnotationDescriptor(type, visible), "annotation on method declaration");
            return null;
        }

        @Override
        public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
            reportMethodViolation(checkAnnotationDescriptor(Type.getType(desc), visible),
                    "parameter annotation on method declaration");
            return null;
        }

        @Override
        public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc,
                boolean visible) {
            reportMethodViolation(checkAnnotationDescriptor(Type.getType(desc), visible),
                    "type annotation on method declaration");
            return null;
        }

        @Override
        public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String desc,
                boolean visible) {
            reportMethodViolation(checkAnnotationDescriptor(Type.getType(desc), visible),
                    "annotation in method body");
            return null;
        }

        @Override
        public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start,
                Label[] end, int[] index, String desc, boolean visible) {
            reportMethodViolation(checkAnnotationDescriptor(Type.getType(desc), visible),
                    "annotation in method body");
            return null;
        }

        @Override
        public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String desc,
                boolean visible) {
            reportMethodViolation(checkAnnotationDescriptor(Type.getType(desc), visible),
                    "annotation in method body");
            return null;
        }

        @Override
        public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
            reportMethodViolation(checkMethodAccess(owner, new Method(name, desc)), "method body");
        }

        @Override
        public void visitFieldInsn(int opcode, String owner, String name, String desc) {
            reportMethodViolation(checkFieldAccess(owner, name), "method body");
        }

        @Override
        public void visitTypeInsn(int opcode, String type) {
            if (opcode == Opcodes.ANEWARRAY) {
                reportMethodViolation(checkType(Type.getObjectType(type)), "method body");
            }
        }

        @Override
        public void visitMultiANewArrayInsn(String desc, int dims) {
            reportMethodViolation(checkDescriptor(desc), "method body");
        }

        @Override
        public void visitLdcInsn(Object cst) {
            reportMethodViolation(checkConstant(cst, false), "method body");
        }

        @Override
        public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
            final boolean isLambdaMetaFactory = LAMBDA_META_FACTORY_INTERNALNAME.equals(bsm.getOwner());
            reportMethodViolation(checkHandle(bsm, false), "method body");
            for (final Object cst : bsmArgs) {
                reportMethodViolation(checkConstant(cst, isLambdaMetaFactory), "method body");
            }
        }

        private String getHumanReadableMethodSignature() {
            final Type[] args = Type.getType(myself.getDescriptor()).getArgumentTypes();
            final StringBuilder sb = new StringBuilder(myself.getName()).append('(');
            boolean comma = false;
            for (final Type t : args) {
                if (comma)
                    sb.append(',');
                sb.append(t.getClassName());
                comma = true;
            }
            sb.append(')');
            return sb.toString();
        }

        private void reportMethodViolation(String violation, String where) {
            if (violation != null) {
                violations.add(new ForbiddenViolation(currentGroupId, myself, violation,
                        String.format(Locale.ENGLISH, "%s of '%s'", where, getHumanReadableMethodSignature()),
                        lineNo));
            }
        }

        @Override
        public void visitLineNumber(int lineNo, Label start) {
            this.lineNo = lineNo;
        }
    };
}

From source file:de.tuberlin.uebb.jbop.optimizer.array.LocalArrayLengthInliner.java

License:Open Source License

/**
 * Registers values for local arrays that are created via NEWARRAY / ANEWARRAY or MULTIANEWARRAY.
 * //from  w  w w  .  ja v a 2  s . c om
 * @param currentNode
 *          the current node
 * @param knownArrays
 *          the known arrays
 * @return true, if successful
 */
@Override
protected int registerAdditionalValues(final AbstractInsnNode currentNode, //
        final Map<Integer, Object> knownArrays) {
    final int opcode = currentNode.getOpcode();
    if (!((opcode == Opcodes.NEWARRAY) || (opcode == Opcodes.ANEWARRAY)
            || (opcode == Opcodes.MULTIANEWARRAY))) {
        return 0;
    }
    int dims = 1;
    if (currentNode.getOpcode() == Opcodes.MULTIANEWARRAY) {
        final MultiANewArrayInsnNode node = (MultiANewArrayInsnNode) currentNode;
        dims = node.dims;
    }
    final int sizes[] = new int[dims];
    AbstractInsnNode previous = currentNode;
    for (int i = 0; i < dims; ++i) {
        previous = NodeHelper.getPrevious(previous);
        if (!NodeHelper.isIntNode(previous)) {
            return 0;
        }
        try {
            final int value = NodeHelper.getNumberValue(previous).intValue();
            sizes[i] = value;
        } catch (final NotANumberException nane) {
            return 0;
        }
    }
    final AbstractInsnNode next = NodeHelper.getNext(currentNode);
    if (!(next instanceof VarInsnNode)) {
        return 0;
    }
    final int index = ((VarInsnNode) next).var;
    knownArrays.put(Integer.valueOf(index), Array.newInstance(Object.class, sizes));
    return 2;
}

From source file:de.tuberlin.uebb.jbop.optimizer.ClassNodeBuilder.java

License:Open Source License

/**
 * Initializes a classField of type Array in the default lastConstructor with the given length.
 * (eg: if fieldType of field "field" is "double[]", field = new double[length] is called).
 * /*from   w  ww .  j a va 2  s.  c o m*/
 * @param length
 *          the length
 * @return the abstract optimizer test
 */
public ClassNodeBuilder initArray(final int... length) {
    if (isInterface) {
        return this;
    }
    final InsnList list = new InsnList();
    list.add(new VarInsnNode(Opcodes.ALOAD, 0));
    final AbstractInsnNode node;
    if (length.length == 1) {
        final Type elementType = Type.getType(lastField.desc).getElementType();
        list.add(NodeHelper.getInsnNodeFor(Integer.valueOf(length[0])));
        if (elementType.getDescriptor().startsWith("L")) {
            node = new TypeInsnNode(Opcodes.ANEWARRAY, elementType.getInternalName());
        } else {
            node = new IntInsnNode(Opcodes.NEWARRAY, getSort(elementType));
        }
    } else {
        for (final int currentLength : length) {
            list.add(NodeHelper.getInsnNodeFor(Integer.valueOf(currentLength)));
        }
        node = new MultiANewArrayInsnNode(lastField.desc, length.length);
    }
    list.add(node);
    list.add(new VarInsnNode(Opcodes.ASTORE, constructorVarIndex));
    list.add(new VarInsnNode(Opcodes.ALOAD, constructorVarIndex));
    lastConstructorVarIndex = constructorVarIndex;
    constructorVarIndex++;
    list.add(new FieldInsnNode(Opcodes.PUTFIELD, classNode.name, lastField.name, lastField.desc));
    addToConstructor(list);
    return this;
}