Example usage for org.objectweb.asm Type getArgumentsAndReturnSizes

List of usage examples for org.objectweb.asm Type getArgumentsAndReturnSizes

Introduction

In this page you can find the example usage for org.objectweb.asm Type getArgumentsAndReturnSizes.

Prototype

public static int getArgumentsAndReturnSizes(final String methodDescriptor) 

Source Link

Document

Computes the size of the arguments and of the return value of a method.

Usage

From source file:com.google.devtools.build.android.desugar.BytecodeTypeInference.java

License:Open Source License

@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
    if (opcode == Opcodes.INVOKESPECIAL && "<init>".equals(name)) {
        int argumentSize = (Type.getArgumentsAndReturnSizes(desc) >> 2);
        InferredType receiverType = getTypeOfOperandFromTop(argumentSize - 1);
        if (receiverType.isUninitialized()) {
            InferredType realType = InferredType.createNonUninitializedType('L' + owner + ';');
            replaceUninitializedTypeInStack(receiverType, realType);
        }//from www. java  2  s  .  c o m
    }
    switch (opcode) {
    case Opcodes.INVOKESPECIAL:
    case Opcodes.INVOKEVIRTUAL:
    case Opcodes.INVOKESTATIC:
    case Opcodes.INVOKEINTERFACE:
        popDescriptor(desc);
        if (opcode != Opcodes.INVOKESTATIC) {
            pop(); // Pop receiver.
        }
        pushDescriptor(desc);
        break;
    default:
        throw new RuntimeException(String.format("Unhandled opcode %s, owner=%s, name=%s, desc=%s, itf=%s",
                opcode, owner, name, desc, itf));
    }
    super.visitMethodInsn(opcode, owner, name, desc, itf);
}

From source file:com.google.devtools.build.android.desugar.BytecodeTypeInference.java

License:Open Source License

private final void popDescriptor(String desc) {
    char c = desc.charAt(0);
    switch (c) {//from   ww w.jav  a2s. c o m
    case '(':
        int argumentSize = (Type.getArgumentsAndReturnSizes(desc) >> 2) - 1;
        if (argumentSize > 0) {
            pop(argumentSize);
        }
        break;
    case 'J':
    case 'D':
        pop(2);
        break;
    default:
        pop(1);
        break;
    }
}

From source file:edu.ubc.mirrors.holograms.HologramMethodGenerator.java

License:Open Source License

@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
    // Various special cases here to adjust for the fact that Object and Throwable
    // are still in the hierarchy and have some methods with incompatible types.

    Type stringHologramType = getHologramType(String.class);
    if (name.equals("toString") && desc.equals(Type.getMethodDescriptor(stringHologramType))) {
        desc = Type.getMethodDescriptor(Type.getType(String.class));
        if (owner.equals(Type.getInternalName(Hologram.class))) {
            owner = OBJECT_TYPE.getInternalName();
            // Handle calling Object.toString() with an invokespecial opcode, 
            // which doesn't work any more since we've changed the superclass.
            if (opcode == Opcodes.INVOKESPECIAL) {
                opcode = Opcodes.INVOKESTATIC;
                owner = objectHologramType.getInternalName();
                name = "hologramToString";
                desc = Type.getMethodDescriptor(stringType, hologramType);
            }/*w  w w.jav  a2 s  .  c om*/
        }

        super.visitMethodInsn(opcode, owner, name, desc);

        getClassMirror(this.owner);
        invokestatic(objectHologramType.getInternalName(), "makeStringHologram",
                Type.getMethodDescriptor(hologramType, stringType, classMirrorType));
        checkcast(stringHologramType);
        return;
    }

    if (name.equals("getClass") && desc.equals(Type.getMethodDescriptor(getHologramType(Class.class)))) {
        invokeinterface(Type.getInternalName(Hologram.class), "getMirror",
                Type.getMethodDescriptor(objectMirrorType));
        invokeinterface(objectMirrorType.getInternalName(), "getClassMirror",
                Type.getMethodDescriptor(Type.getType(ClassMirror.class)));

        invokestatic(objectHologramType.getInternalName(), "make",
                Type.getMethodDescriptor(hologramType, objectMirrorType));
        checkcast(getHologramType(Class.class));
        return;
    }

    if (owner.equals(Type.getInternalName(Hologram.class))) {
        if (name.equals("<init>") && this.owner.equals(getHologramType(Throwable.class))) {
            owner = Type.getInternalName(Throwable.class);
        } else if (name.equals("<init>") || name.equals("toString")) {
            owner = objectHologramType.getInternalName();
        } else {
            owner = OBJECT_TYPE.getInternalName();
        }
    }

    if (name.equals("clone")) {
        if (desc.equals(Type.getMethodDescriptor(hologramType))) {
            desc = Type.getMethodDescriptor(OBJECT_TYPE);

            // Object.clone() on an array type is legal since array types
            // are treated specially by the JVM, but the mirror interfaces 
            // are not granted the same leeway.
            Object t = stackType(0);
            if (t instanceof String) {
                String internalName = (String) t;
                Type type = Type.getObjectType(internalName);
                if (HologramClassGenerator.getOriginalType(type).getSort() == Type.ARRAY) {
                    owner = internalName;
                }
            }
        }
        if (owner.equals(Type.getType(ObjectArrayMirror.class).getInternalName())
                || (owner.startsWith("hologramarray") && !owner.startsWith("hologramarrayimpl"))) {
            String originalName = getOriginalInternalClassName(owner);
            owner = getHologramType(Type.getObjectType(originalName), true).getInternalName();
            checkcast(Type.getObjectType(owner));
        }
    }

    //        if (owner.equals(getHologramType(Throwable.class).getInternalName())) {
    //            if (name.equals("<init>") && desc.equals(Type.getMethodDescriptor(Type.VOID_TYPE, getHologramType(String.class)))) {
    //                desc = Type.getMethodDescriptor(Type.VOID_TYPE, objectHologramType);
    //            }
    //        }

    if (owner.equals(hologramThrowableType.getInternalName()) && name.equals("fillInStackTrace")
            && desc.equals(Type.getMethodDescriptor(hologramThrowableType))) {
        desc = Type.getMethodDescriptor(throwableType);
        owner = throwableType.getInternalName();
    }

    if (name.equals("equals")
            && desc.equals(Type.getMethodDescriptor(Type.BOOLEAN_TYPE, Type.getType(Hologram.class)))) {
        desc = Type.getMethodDescriptor(Type.BOOLEAN_TYPE, OBJECT_TYPE);
    }

    if (name.equals("<init>") && !owner.equals(Type.getInternalName(Throwable.class))) {
        int argsSize = Type.getArgumentsAndReturnSizes(desc) >> 2;
        desc = HologramClassGenerator.addMirrorParam(desc);

        Object targetType = stackType(argsSize - 1);
        if (targetType.equals(Opcodes.UNINITIALIZED_THIS)) {
            // If the target is an uninitialized this (i.e. we're calling super(...)
            // or this(...)), pass along the extra mirror argument
            load((methodType.getArgumentsAndReturnSizes() >> 2) - 1, instanceMirrorType);
        } else if (targetType instanceof Label) {
            // If the target is just uninitialized (i.e. we're calling <init> after
            // a new), create the mirror
            getClassMirror(Type.getObjectType(owner));
            invokeinterface(classMirrorType.getInternalName(), "newRawInstance",
                    Type.getMethodDescriptor(instanceMirrorType));
        } else {
            // Shouldn't happen
            throw new RuntimeException("Calling <init> on already initialized type: " + targetType);
        }
    }

    super.visitMethodInsn(opcode, owner, name, desc);

    if (owner.equals(Type.getInternalName(Throwable.class)) && name.equals("getStackTraceElement")) {
        Type steType = Type.getType(StackTraceElement.class);
        invokestatic(Type.getInternalName(ObjectHologram.class), "cleanStackTraceElement",
                Type.getMethodDescriptor(steType, steType));
    }
}

From source file:org.jephyr.easyflow.instrument.ContinuationMethodAdapter.java

License:Open Source License

@Override
public void visitEnd() {
    List<MethodInsnNode> nodes = findNodes();

    if (nodes.isEmpty()) {
        accept(mv);//  w  ww . j a v  a 2s  .co  m
        return;
    }

    int implVarIndex = maxLocals;
    maxLocals += 1;

    Object[] initialLocals = appendValue(ensureSize(frames.get(instructions.getFirst()).locals, implVarIndex),
            "org/jephyr/continuation/easyflow/ContinuationImpl");

    updateFrames(implVarIndex);
    addMonitorHooks(implVarIndex);

    LabelNode labelNode = newLabelNode();

    instructions.insert(labelNode);

    if (!isNextFrameNode(labelNode)) {
        instructions.insert(labelNode, newFrameNode(initialLocals, EMPTY_OBJECTS));
    }

    addInvocationEndedHook(implVarIndex, labelNode);

    instructions.insertBefore(labelNode,
            new MethodInsnNode(INVOKESTATIC, "org/jephyr/continuation/easyflow/ContinuationImpl", "currentImpl",
                    "()Lorg/jephyr/continuation/easyflow/ContinuationImpl;", false));
    instructions.insertBefore(labelNode, new VarInsnNode(ASTORE, implVarIndex));

    instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
    instructions.insertBefore(labelNode, new JumpInsnNode(IFNULL, labelNode));

    instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
    instructions.insertBefore(labelNode, new MethodInsnNode(INVOKEVIRTUAL,
            "org/jephyr/continuation/easyflow/ContinuationImpl", "isSuspended", "()Z", false));

    LabelNode labelNode1 = newLabelNode();

    instructions.insertBefore(labelNode, new JumpInsnNode(IFEQ, labelNode1));

    LabelNode defaultLabelNode = newLabelNode();
    int size = nodes.size();
    int length = size - 1;
    LabelNode[] labelNodes = new LabelNode[length];

    for (int i = 0; i < length; i++) {
        labelNodes[i] = newLabelNode();
    }

    if (length > 0) {
        instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
        instructions.insertBefore(labelNode, new MethodInsnNode(INVOKEVIRTUAL,
                "org/jephyr/continuation/easyflow/ContinuationImpl", "popInt", "()I", false));
        instructions.insertBefore(labelNode,
                new TableSwitchInsnNode(0, length - 1, defaultLabelNode, labelNodes));
    } else {
        instructions.insertBefore(labelNode, new JumpInsnNode(GOTO, defaultLabelNode));
    }

    updateMaxStack(1);

    Type returnType = Type.getReturnType(desc);

    for (int i = 0; i < size; i++) {
        MethodInsnNode node = nodes.get(i);
        Frame frame = frames.get(node);
        Object[] locals = frame.locals;
        Object[] stack = frame.stack;

        // resume

        LabelNode labelNode2 = i < length ? labelNodes[i] : defaultLabelNode;
        instructions.insertBefore(labelNode, labelNode2);
        instructions.insert(labelNode2, newFrameNode(initialLocals, EMPTY_OBJECTS));

        int intCount = length > 0 ? 1 : 0;
        int floatCount = 0;
        int longCount = 0;
        int doubleCount = 0;
        int objectCount = 0;

        for (int j = 0, n = locals.length; j < n; j++) {
            Object value = locals[j];
            if (value == INTEGER) {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "popInt", "()I", false));
                instructions.insertBefore(labelNode, new VarInsnNode(ISTORE, j));
                updateMaxStack(1);
                intCount++;
            } else if (value == FLOAT) {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "popFloat", "()F", false));
                instructions.insertBefore(labelNode, new VarInsnNode(FSTORE, j));
                updateMaxStack(1);
                floatCount++;
            } else if (value == LONG) {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "popLong", "()J", false));
                instructions.insertBefore(labelNode, new VarInsnNode(LSTORE, j));
                updateMaxStack(2);
                longCount++;
            } else if (value == DOUBLE) {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "popDouble", "()D", false));
                instructions.insertBefore(labelNode, new VarInsnNode(DSTORE, j));
                updateMaxStack(2);
                doubleCount++;
            } else if (value == NULL) {
                instructions.insertBefore(labelNode, new InsnNode(ACONST_NULL));
                instructions.insertBefore(labelNode, new VarInsnNode(ASTORE, j));
                updateMaxStack(1);
            } else if (value instanceof String) {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode,
                        new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                                "popObject", "()Ljava/lang/Object;", false));
                instructions.insertBefore(labelNode, new TypeInsnNode(CHECKCAST, (String) value));
                instructions.insertBefore(labelNode, new VarInsnNode(ASTORE, j));
                updateMaxStack(1);
                objectCount++;
            } else if (value != TOP) {
                throw new IllegalStateException();
            }
        }

        int sizes = Type.getArgumentsAndReturnSizes(node.desc);
        int argSize = sizes >> 2;
        boolean invokeStatic = node.getOpcode() == INVOKESTATIC;
        if (invokeStatic) {
            argSize -= 1;
        }

        int stackSize = 0;

        for (int j = 0, n = stack.length - argSize; j < n; j++) {
            Object value = stack[j];
            if (value == INTEGER) {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "popInt", "()I", false));
                stackSize += 1;
                intCount++;
            } else if (value == FLOAT) {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "popFloat", "()F", false));
                stackSize += 1;
                floatCount++;
            } else if (value == LONG) {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "popLong", "()J", false));
                stackSize += 2;
                longCount++;
            } else if (value == DOUBLE) {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "popDouble", "()D", false));
                stackSize += 2;
                doubleCount++;
            } else if (value == NULL) {
                instructions.insertBefore(labelNode, new InsnNode(ACONST_NULL));
                stackSize += 1;
            } else if (value instanceof String) {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode,
                        new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                                "popObject", "()Ljava/lang/Object;", false));
                instructions.insertBefore(labelNode, new TypeInsnNode(CHECKCAST, (String) value));
                stackSize += 1;
                objectCount++;
            } else if (value != TOP) {
                throw new IllegalStateException();
            }
        }

        updateMaxStack(stackSize);

        int targetVarIndex;
        int objVarIndex;
        int argsVarIndex;

        if (invokeStatic) {
            targetVarIndex = -1;
            objVarIndex = -1;
            argsVarIndex = -1;

            for (Type type : Type.getArgumentTypes(node.desc)) {
                instructions.insertBefore(labelNode, newPushDefaultNode(type));
                stackSize += type.getSize();
            }
        } else if (node.owner.equals("java/lang/reflect/Method") && node.name.equals("invoke")
                && node.desc.equals("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")) {
            int varIndex = implVarIndex + 1;

            if (stack[stack.length - 3] == NULL) {
                targetVarIndex = -1;
            } else {
                targetVarIndex = varIndex;
                varIndex++;
            }

            if (stack[stack.length - 2] == NULL) {
                objVarIndex = -1;
            } else {
                objVarIndex = varIndex;
                varIndex++;
            }

            if (stack[stack.length - 1] == NULL) {
                argsVarIndex = -1;
            } else {
                argsVarIndex = varIndex;
                varIndex++;
            }

            if (maxLocals < varIndex) {
                maxLocals = varIndex;
            }

            if (targetVarIndex == -1) {
                instructions.insertBefore(labelNode, new InsnNode(ACONST_NULL));
            } else {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode,
                        new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                                "popObject", "()Ljava/lang/Object;", false));
                instructions.insertBefore(labelNode, new TypeInsnNode(CHECKCAST, "java/lang/reflect/Method"));
                instructions.insertBefore(labelNode, new VarInsnNode(ASTORE, targetVarIndex));
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, targetVarIndex));
                objectCount++;
            }

            if (objVarIndex == -1) {
                instructions.insertBefore(labelNode, new InsnNode(ACONST_NULL));
            } else {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode,
                        new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                                "popObject", "()Ljava/lang/Object;", false));
                instructions.insertBefore(labelNode,
                        new TypeInsnNode(CHECKCAST, (String) stack[stack.length - 2]));
                instructions.insertBefore(labelNode, new VarInsnNode(ASTORE, objVarIndex));
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, objVarIndex));
                objectCount++;
            }

            if (targetVarIndex == -1) {
                instructions.insertBefore(labelNode, new InsnNode(ACONST_NULL));
            } else {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, targetVarIndex));
            }

            instructions.insertBefore(labelNode, new MethodInsnNode(INVOKEVIRTUAL, "java/lang/reflect/Method",
                    "getParameterTypes", "()[Ljava/lang/Class;", false));

            instructions.insertBefore(labelNode,
                    new MethodInsnNode(INVOKESTATIC, "org/jephyr/continuation/easyflow/ContinuationImpl",
                            "getDefaultArguments", "([Ljava/lang/Class;)[Ljava/lang/Object;", false));
            stackSize += 3;
        } else {
            targetVarIndex = -1;
            objVarIndex = -1;
            argsVarIndex = -1;

            Object value = stack[stack.length - argSize];
            if (value == NULL) {
                instructions.insertBefore(labelNode, new InsnNode(ACONST_NULL));
                instructions.insertBefore(labelNode, new VarInsnNode(ASTORE, implVarIndex + 1));
                instructions.insertBefore(labelNode, new InsnNode(ACONST_NULL));
            } else {
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode,
                        new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                                "popObject", "()Ljava/lang/Object;", false));
                instructions.insertBefore(labelNode, new VarInsnNode(ASTORE, implVarIndex + 1));
                instructions.insertBefore(labelNode, new VarInsnNode(ALOAD, implVarIndex + 1));
                instructions.insertBefore(labelNode, new TypeInsnNode(CHECKCAST, (String) value));
            }
            stackSize += 1;

            for (Type type : Type.getArgumentTypes(node.desc)) {
                instructions.insertBefore(labelNode, newPushDefaultNode(type));
                stackSize += type.getSize();
            }

            objectCount++;
        }

        updateMaxStack(stackSize);

        LabelNode labelNode3 = newLabelNode();

        instructions.insertBefore(labelNode, new JumpInsnNode(GOTO, labelNode3));

        // invocation starting

        if (invokeStatic) {
            instructions.insertBefore(node, new VarInsnNode(ALOAD, implVarIndex));
            instructions.insertBefore(node, new JumpInsnNode(IFNULL, labelNode3));

            instructions.insertBefore(node, new VarInsnNode(ALOAD, implVarIndex));
            instructions.insertBefore(node, new LdcInsnNode(Type.getType('L' + node.owner + ';')));
            instructions.insertBefore(node, new LdcInsnNode(node.name));
            instructions.insertBefore(node, new LdcInsnNode(node.desc));
            instructions.insertBefore(node,
                    new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                            "staticInvocationStarting",
                            "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;)V", false));

            instructions.insertBefore(node, labelNode3);
            instructions.insert(labelNode3, newFrameNode(appendValue(ensureSize(locals, implVarIndex),
                    "org/jephyr/continuation/easyflow/ContinuationImpl"), stack));
        } else if (node.owner.equals("java/lang/reflect/Method") && node.name.equals("invoke")
                && node.desc.equals("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")) {
            instructions.insertBefore(node, new VarInsnNode(ALOAD, implVarIndex));

            LabelNode labelNode4 = newLabelNode();

            instructions.insertBefore(node, new JumpInsnNode(IFNULL, labelNode4));

            instructions.insertBefore(node,
                    argsVarIndex == -1 ? new InsnNode(POP) : new VarInsnNode(ASTORE, argsVarIndex));
            instructions.insertBefore(node,
                    objVarIndex == -1 ? new InsnNode(POP) : new VarInsnNode(ASTORE, objVarIndex));
            instructions.insertBefore(node,
                    targetVarIndex == -1 ? new InsnNode(POP) : new VarInsnNode(ASTORE, targetVarIndex));

            instructions.insertBefore(node, new VarInsnNode(ALOAD, implVarIndex));
            instructions.insertBefore(node,
                    targetVarIndex == -1 ? new InsnNode(ACONST_NULL) : new VarInsnNode(ALOAD, targetVarIndex));
            instructions.insertBefore(node,
                    objVarIndex == -1 ? new InsnNode(ACONST_NULL) : new VarInsnNode(ALOAD, objVarIndex));
            instructions.insertBefore(node,
                    new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                            "reflectiveInvocationStarting", "(Ljava/lang/reflect/Method;Ljava/lang/Object;)V",
                            false));

            instructions.insertBefore(node,
                    targetVarIndex == -1 ? new InsnNode(ACONST_NULL) : new VarInsnNode(ALOAD, targetVarIndex));
            instructions.insertBefore(node,
                    objVarIndex == -1 ? new InsnNode(ACONST_NULL) : new VarInsnNode(ALOAD, objVarIndex));
            instructions.insertBefore(node,
                    argsVarIndex == -1 ? new InsnNode(ACONST_NULL) : new VarInsnNode(ALOAD, argsVarIndex));

            instructions.insertBefore(node, new JumpInsnNode(GOTO, labelNode3));

            instructions.insertBefore(node, labelNode4);
            instructions.insert(labelNode4, newFrameNode(appendValue(ensureSize(locals, implVarIndex),
                    "org/jephyr/continuation/easyflow/ContinuationImpl"), stack));

            if (targetVarIndex != -1) {
                instructions.insertBefore(node, new InsnNode(ACONST_NULL));
                instructions.insertBefore(node, new VarInsnNode(ASTORE, targetVarIndex));
            }

            if (objVarIndex != -1) {
                instructions.insertBefore(node, new InsnNode(ACONST_NULL));
                instructions.insertBefore(node, new VarInsnNode(ASTORE, objVarIndex));
            }

            instructions.insertBefore(node, labelNode3);

            Object[] locals1 = appendValue(ensureSize(locals, implVarIndex),
                    "org/jephyr/continuation/easyflow/ContinuationImpl");

            if (targetVarIndex != -1) {
                locals1 = appendValue(locals1, "java/lang/reflect/Method");
            }

            if (objVarIndex != -1) {
                locals1 = appendValue(locals1, "java/lang/Object");
            }

            instructions.insert(labelNode3, newFrameNode(locals1, stack));
        } else {
            instructions.insertBefore(node, new VarInsnNode(ALOAD, implVarIndex));

            LabelNode labelNode4 = newLabelNode();

            instructions.insertBefore(node, new JumpInsnNode(IFNULL, labelNode4));

            targetVarIndex = implVarIndex + 1;
            int varIndex = targetVarIndex + 1;

            for (int j = stack.length - 1, k = stack.length - argSize + 1; j >= k; j--) {
                Object value = stack[j];
                if (value == INTEGER) {
                    instructions.insertBefore(node, new VarInsnNode(ISTORE, varIndex));
                    varIndex += 1;
                } else if (value == FLOAT) {
                    instructions.insertBefore(node, new VarInsnNode(FSTORE, varIndex));
                    varIndex += 1;
                } else if (value == DOUBLE) {
                    instructions.insertBefore(node, new VarInsnNode(DSTORE, varIndex));
                    varIndex += 2;
                } else if (value == LONG) {
                    instructions.insertBefore(node, new VarInsnNode(LSTORE, varIndex));
                    varIndex += 2;
                } else if (value == NULL) {
                    instructions.insertBefore(node, new InsnNode(POP));
                } else if (value instanceof String) {
                    instructions.insertBefore(node, new VarInsnNode(ASTORE, varIndex));
                    varIndex += 1;
                }
            }

            if (maxLocals < varIndex) {
                maxLocals = varIndex;
            }

            instructions.insertBefore(node, new VarInsnNode(ASTORE, targetVarIndex));
            instructions.insertBefore(node, new VarInsnNode(ALOAD, targetVarIndex));

            for (int j = stack.length - argSize + 1, n = stack.length; j < n; j++) {
                Object value = stack[j];
                if (value == INTEGER) {
                    varIndex -= 1;
                    instructions.insertBefore(node, new VarInsnNode(ILOAD, varIndex));
                } else if (value == FLOAT) {
                    varIndex -= 1;
                    instructions.insertBefore(node, new VarInsnNode(FLOAD, varIndex));
                } else if (value == DOUBLE) {
                    varIndex -= 2;
                    instructions.insertBefore(node, new VarInsnNode(DLOAD, varIndex));
                } else if (value == LONG) {
                    varIndex -= 2;
                    instructions.insertBefore(node, new VarInsnNode(LLOAD, varIndex));
                } else if (value == NULL) {
                    instructions.insertBefore(node, new InsnNode(ACONST_NULL));
                } else if (value instanceof String) {
                    varIndex -= 1;
                    instructions.insertBefore(node, new VarInsnNode(ALOAD, varIndex));
                }
            }

            instructions.insertBefore(node, new VarInsnNode(ALOAD, implVarIndex));
            instructions.insertBefore(node, new VarInsnNode(ALOAD, targetVarIndex));
            instructions.insertBefore(node, new LdcInsnNode(node.name));
            instructions.insertBefore(node, new LdcInsnNode(node.desc));
            instructions.insertBefore(node,
                    new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                            "invocationStarting", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V",
                            false));

            instructions.insertBefore(node, new JumpInsnNode(GOTO, labelNode3));

            instructions.insertBefore(node, labelNode4);
            instructions.insert(labelNode4, newFrameNode(appendValue(ensureSize(locals, implVarIndex),
                    "org/jephyr/continuation/easyflow/ContinuationImpl"), stack));

            instructions.insertBefore(node, new InsnNode(ACONST_NULL));
            instructions.insertBefore(node, new VarInsnNode(ASTORE, targetVarIndex));

            instructions.insertBefore(node, labelNode3);
            instructions.insert(labelNode3,
                    newFrameNode(
                            appendValues(ensureSize(locals, implVarIndex),
                                    "org/jephyr/continuation/easyflow/ContinuationImpl", "java/lang/Object"),
                            stack));
        }

        updateMaxStack(stack.length + 4);

        // suspend

        Frame frame1 = findNextFrame(frames, node);
        Object[] stack1 = frame1.stack;
        int stackSize1 = stack1.length;

        LabelNode labelNode4 = newLabelNode();

        instructions.insert(node, labelNode4);

        if (!isNextFrameNode(labelNode4)) {
            instructions.insert(labelNode4, newFrameNode(appendValue(ensureSize(frame1.locals, implVarIndex),
                    "org/jephyr/continuation/easyflow/ContinuationImpl"), stack1));
        }

        instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
        instructions.insertBefore(labelNode4, new JumpInsnNode(IFNULL, labelNode4));

        instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
        instructions.insertBefore(labelNode4, new MethodInsnNode(INVOKEVIRTUAL,
                "org/jephyr/continuation/easyflow/ContinuationImpl", "isSuspending", "()Z", false));
        instructions.insertBefore(labelNode4, new JumpInsnNode(IFEQ, labelNode4));

        int returnSize = sizes & 0x03;
        if (returnSize == 1) {
            instructions.insertBefore(labelNode4, new InsnNode(POP));
            stackSize1 -= 1;
        } else if (returnSize == 2) {
            instructions.insertBefore(labelNode4, new InsnNode(POP2));
            stackSize1 -= 2;
        }

        if (intCount > 0) {
            instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
            instructions.insertBefore(labelNode4, newPushNode(intCount));
            instructions.insertBefore(labelNode4, new MethodInsnNode(INVOKEVIRTUAL,
                    "org/jephyr/continuation/easyflow/ContinuationImpl", "ensureIntStackSize", "(I)V", false));
            updateMaxStack(stackSize1 + 1);
        }

        if (floatCount > 0) {
            instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
            instructions.insertBefore(labelNode4, newPushNode(floatCount));
            instructions.insertBefore(labelNode4,
                    new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                            "ensureFloatStackSize", "(I)V", false));
            updateMaxStack(stackSize1 + 1);
        }

        if (longCount > 0) {
            instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
            instructions.insertBefore(labelNode4, newPushNode(longCount));
            instructions.insertBefore(labelNode4, new MethodInsnNode(INVOKEVIRTUAL,
                    "org/jephyr/continuation/easyflow/ContinuationImpl", "ensureLongStackSize", "(I)V", false));
            updateMaxStack(stackSize1 + 1);
        }

        if (doubleCount > 0) {
            instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
            instructions.insertBefore(labelNode4, newPushNode(doubleCount));
            instructions.insertBefore(labelNode4,
                    new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                            "ensureDoubleStackSize", "(I)V", false));
            updateMaxStack(stackSize1 + 1);
        }

        if (objectCount > 0) {
            instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
            instructions.insertBefore(labelNode4, newPushNode(objectCount));
            instructions.insertBefore(labelNode4,
                    new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                            "ensureObjectStackSize", "(I)V", false));
            updateMaxStack(stackSize1 + 1);
        }

        if (!invokeStatic) {
            if (node.owner.equals("java/lang/reflect/Method") && node.name.equals("invoke")
                    && node.desc.equals("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")) {
                if (objVarIndex != -1) {
                    instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                    instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, objVarIndex));
                    instructions.insertBefore(labelNode4,
                            new MethodInsnNode(INVOKEVIRTUAL,
                                    "org/jephyr/continuation/easyflow/ContinuationImpl", "pushObject",
                                    "(Ljava/lang/Object;)V", false));
                    updateMaxStack(stackSize1 + 2);
                }
                if (targetVarIndex != -1) {
                    instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                    instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, targetVarIndex));
                    instructions.insertBefore(labelNode4,
                            new MethodInsnNode(INVOKEVIRTUAL,
                                    "org/jephyr/continuation/easyflow/ContinuationImpl", "pushObject",
                                    "(Ljava/lang/Object;)V", false));
                    updateMaxStack(stackSize1 + 2);
                }
            } else if (stack[stack.length - argSize] != NULL) {
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, targetVarIndex));
                instructions.insertBefore(labelNode4,
                        new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                                "pushObject", "(Ljava/lang/Object;)V", false));
                updateMaxStack(stackSize1 + 2);
            }
        }

        for (int j = stack.length - argSize - 1; j >= 0; j--) {
            Object value = stack[j];
            if (value == INTEGER) {
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode4, new InsnNode(SWAP));
                instructions.insertBefore(labelNode4, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "pushInt", "(I)V", false));
                updateMaxStack(stackSize1 + 1);
                stackSize1 -= 1;
            } else if (value == FLOAT) {
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode4, new InsnNode(SWAP));
                instructions.insertBefore(labelNode4, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "pushFloat", "(F)V", false));
                updateMaxStack(stackSize1 + 1);
                stackSize1 -= 1;
            } else if (value == LONG) {
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode4, new InsnNode(DUP_X2));
                instructions.insertBefore(labelNode4, new InsnNode(POP));
                instructions.insertBefore(labelNode4, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "pushLong", "(J)V", false));
                updateMaxStack(stackSize1 + 2);
                stackSize1 -= 2;
            } else if (value == DOUBLE) {
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode4, new InsnNode(DUP_X2));
                instructions.insertBefore(labelNode4, new InsnNode(POP));
                instructions.insertBefore(labelNode4, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "pushDouble", "(D)V", false));
                updateMaxStack(stackSize1 + 2);
                stackSize1 -= 2;
            } else if (value == NULL) {
                instructions.insertBefore(labelNode4, new InsnNode(POP));
                stackSize1 -= 1;
            } else if (value instanceof String) {
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode4, new InsnNode(SWAP));
                instructions.insertBefore(labelNode4,
                        new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                                "pushObject", "(Ljava/lang/Object;)V", false));
                updateMaxStack(stackSize1 + 1);
                stackSize1 -= 1;
            }
        }

        for (int j = locals.length - 1; j >= 0; j--) {
            Object value = locals[j];
            if (value == INTEGER) {
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode4, new VarInsnNode(ILOAD, j));
                instructions.insertBefore(labelNode4, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "pushInt", "(I)V", false));
                updateMaxStack(stackSize1 + 2);
            } else if (value == FLOAT) {
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode4, new VarInsnNode(FLOAD, j));
                instructions.insertBefore(labelNode4, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "pushFloat", "(F)V", false));
                updateMaxStack(stackSize1 + 2);
            } else if (value == LONG) {
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode4, new VarInsnNode(LLOAD, j));
                instructions.insertBefore(labelNode4, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "pushLong", "(J)V", false));
                updateMaxStack(stackSize1 + 3);
            } else if (value == DOUBLE) {
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode4, new VarInsnNode(DLOAD, j));
                instructions.insertBefore(labelNode4, new MethodInsnNode(INVOKEVIRTUAL,
                        "org/jephyr/continuation/easyflow/ContinuationImpl", "pushDouble", "(D)V", false));
                updateMaxStack(stackSize1 + 3);
            } else if (value instanceof String) {
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
                instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, j));
                instructions.insertBefore(labelNode4,
                        new MethodInsnNode(INVOKEVIRTUAL, "org/jephyr/continuation/easyflow/ContinuationImpl",
                                "pushObject", "(Ljava/lang/Object;)V", false));
                updateMaxStack(stackSize1 + 2);
            }
        }

        if (length > 0) {
            instructions.insertBefore(labelNode4, new VarInsnNode(ALOAD, implVarIndex));
            instructions.insertBefore(labelNode4, newPushNode(i));
            instructions.insertBefore(labelNode4, new MethodInsnNode(INVOKEVIRTUAL,
                    "org/jephyr/continuation/easyflow/ContinuationImpl", "pushInt", "(I)V", false));
            updateMaxStack(stackSize1 + 2);
        }

        int returnSize1 = returnType.getSize();
        if (returnSize1 > 0) {
            instructions.insertBefore(labelNode4, newPushDefaultNode(returnType));
            updateMaxStack(stackSize1 + returnSize1);
        }

        instructions.insertBefore(labelNode4, new InsnNode(returnType.getOpcode(IRETURN)));
    }

    instructions.insertBefore(labelNode, labelNode1);
    instructions.insert(labelNode1, newFrameNode(initialLocals, EMPTY_OBJECTS));

    addInvocationStartedHook(implVarIndex, labelNode);

    accept(mv);
}

From source file:org.jephyr.easyflow.instrument.NewRelocatorMethodAdapter.java

License:Open Source License

private static int getInvokeDelta(String desc) {
    int sizes = Type.getArgumentsAndReturnSizes(desc);
    return (sizes & 0x03) - (sizes >> 2);
}

From source file:org.jephyr.easyflow.instrument.NewRelocatorMethodAdapter.java

License:Open Source License

private int handleInvokeSpecial(MethodInsnNode node, int stackSize) {
    int stackSize1 = stackSize;
    int sizes = Type.getArgumentsAndReturnSizes(node.desc);
    int argSize = sizes >> 2;

    if (node.name.charAt(0) == '<') {
        Frame frame = frames.get(node);
        Object[] locals = frame.locals;
        Object[] stack = frame.stack;
        AbstractInsnNode newNode = (AbstractInsnNode) stack[stack.length - argSize];

        boolean noLocalNews = true;
        for (Object value : locals) {
            if (value == newNode) {
                noLocalNews = false;/*from   w w w  .jav a 2s  . c o  m*/
                break;
            }
        }

        int stackNewCount = 0;
        for (Object value : stack) {
            if (value == newNode) {
                stackNewCount++;
            }
        }

        if (noLocalNews && stackNewCount == 2 && stack[stack.length - argSize - 1] == newNode) {
            if (argSize == 1) {
                instructions.insertBefore(node, new TypeInsnNode(NEW, node.owner));
                instructions.insertBefore(node, new InsnNode(DUP));
                stackSize1 += 2;
                updateMaxStack(stackSize1);
            } else if (argSize == 2 || argSize >= 4 && isLong(stack[stack.length - argSize + 2])) {
                int varIndex = locals.length;

                for (int i = stack.length - 1, k = stack.length - argSize + 2; i >= k; i--) {
                    Object value = stack[i];
                    if (value == INTEGER) {
                        instructions.insertBefore(node, new VarInsnNode(ISTORE, varIndex));
                        stackSize1 -= 1;
                        varIndex += 1;
                    } else if (value == FLOAT) {
                        instructions.insertBefore(node, new VarInsnNode(FSTORE, varIndex));
                        stackSize1 -= 1;
                        varIndex += 1;
                    } else if (value == DOUBLE) {
                        instructions.insertBefore(node, new VarInsnNode(DSTORE, varIndex));
                        stackSize1 -= 2;
                        varIndex += 2;
                    } else if (value == LONG) {
                        instructions.insertBefore(node, new VarInsnNode(LSTORE, varIndex));
                        stackSize1 -= 2;
                        varIndex += 2;
                    } else if (value == NULL) {
                        instructions.insertBefore(node, new InsnNode(POP));
                        stackSize1 -= 1;
                    } else if (value instanceof String) {
                        instructions.insertBefore(node, new VarInsnNode(ASTORE, varIndex));
                        stackSize1 -= 1;
                        varIndex += 1;
                    }
                }

                if (maxLocals < varIndex) {
                    maxLocals = varIndex;
                }

                instructions.insertBefore(node, new TypeInsnNode(NEW, node.owner));
                instructions.insertBefore(node, new InsnNode(DUP));
                instructions.insertBefore(node, new InsnNode(DUP2_X1));
                instructions.insertBefore(node, new InsnNode(POP2));
                stackSize1 += 2;
                updateMaxStack(stackSize1 + 2);

                for (int i = stack.length - argSize + 2, n = stack.length; i < n; i++) {
                    Object value = stack[i];
                    if (value == INTEGER) {
                        varIndex -= 1;
                        instructions.insertBefore(node, new VarInsnNode(ILOAD, varIndex));
                        stackSize1 += 1;
                    } else if (value == FLOAT) {
                        varIndex -= 1;
                        instructions.insertBefore(node, new VarInsnNode(FLOAD, varIndex));
                        stackSize1 += 1;
                    } else if (value == DOUBLE) {
                        varIndex -= 2;
                        instructions.insertBefore(node, new VarInsnNode(DLOAD, varIndex));
                        stackSize1 += 2;
                    } else if (value == LONG) {
                        varIndex -= 2;
                        instructions.insertBefore(node, new VarInsnNode(LLOAD, varIndex));
                        stackSize1 += 2;
                    } else if (value == NULL) {
                        instructions.insertBefore(node, new InsnNode(ACONST_NULL));
                        stackSize1 += 1;
                    } else if (value instanceof String) {
                        varIndex -= 1;
                        instructions.insertBefore(node, new VarInsnNode(ALOAD, varIndex));
                        stackSize1 += 1;
                    }
                }

                updateMaxStack(stackSize1);
            } else {
                int varIndex = locals.length;

                for (int i = stack.length - 1, k = stack.length - argSize + 3; i >= k; i--) {
                    Object value = stack[i];
                    if (value == INTEGER) {
                        instructions.insertBefore(node, new VarInsnNode(ISTORE, varIndex));
                        stackSize1 -= 1;
                        varIndex += 1;
                    } else if (value == FLOAT) {
                        instructions.insertBefore(node, new VarInsnNode(FSTORE, varIndex));
                        stackSize1 -= 1;
                        varIndex += 1;
                    } else if (value == DOUBLE) {
                        instructions.insertBefore(node, new VarInsnNode(DSTORE, varIndex));
                        stackSize1 -= 2;
                        varIndex += 2;
                    } else if (value == LONG) {
                        instructions.insertBefore(node, new VarInsnNode(LSTORE, varIndex));
                        stackSize1 -= 2;
                        varIndex += 2;
                    } else if (value == NULL) {
                        instructions.insertBefore(node, new InsnNode(POP));
                        stackSize1 -= 1;
                    } else if (value instanceof String) {
                        instructions.insertBefore(node, new VarInsnNode(ASTORE, varIndex));
                        stackSize1 -= 1;
                        varIndex += 1;
                    }
                }

                if (maxLocals < varIndex) {
                    maxLocals = varIndex;
                }

                instructions.insertBefore(node, new TypeInsnNode(NEW, node.owner));
                instructions.insertBefore(node, new InsnNode(DUP));
                instructions.insertBefore(node, new InsnNode(DUP2_X2));
                instructions.insertBefore(node, new InsnNode(POP2));
                stackSize1 += 2;
                updateMaxStack(stackSize1 + 2);

                for (int i = stack.length - argSize + 3, n = stack.length; i < n; i++) {
                    Object value = stack[i];
                    if (value == INTEGER) {
                        varIndex -= 1;
                        instructions.insertBefore(node, new VarInsnNode(ILOAD, varIndex));
                        stackSize1 += 1;
                    } else if (value == FLOAT) {
                        varIndex -= 1;
                        instructions.insertBefore(node, new VarInsnNode(FLOAD, varIndex));
                        stackSize1 += 1;
                    } else if (value == DOUBLE) {
                        varIndex -= 2;
                        instructions.insertBefore(node, new VarInsnNode(DLOAD, varIndex));
                        stackSize1 += 2;
                    } else if (value == LONG) {
                        varIndex -= 2;
                        instructions.insertBefore(node, new VarInsnNode(LLOAD, varIndex));
                        stackSize1 += 2;
                    } else if (value == NULL) {
                        instructions.insertBefore(node, new InsnNode(ACONST_NULL));
                        stackSize1 += 1;
                    } else if (value instanceof String) {
                        varIndex -= 1;
                        instructions.insertBefore(node, new VarInsnNode(ALOAD, varIndex));
                        stackSize1 += 1;
                    }
                }

                updateMaxStack(stackSize1);
            }
        } else {
            int k = 0;
            for (Object value : stack) {
                if (value == newNode) {
                    break;
                }
                k++;
            }

            int newVarIndex = locals.length;
            int varIndex = newVarIndex + 1;

            for (int i = stack.length - 1; i >= k; i--) {
                Object value = stack[i];
                if (value == INTEGER) {
                    instructions.insertBefore(node, new VarInsnNode(ISTORE, varIndex));
                    stackSize1 -= 1;
                    varIndex += 1;
                } else if (value == FLOAT) {
                    instructions.insertBefore(node, new VarInsnNode(FSTORE, varIndex));
                    stackSize1 -= 1;
                    varIndex += 1;
                } else if (value == DOUBLE) {
                    instructions.insertBefore(node, new VarInsnNode(DSTORE, varIndex));
                    stackSize1 -= 2;
                    varIndex += 2;
                } else if (value == LONG) {
                    instructions.insertBefore(node, new VarInsnNode(LSTORE, varIndex));
                    stackSize1 -= 2;
                    varIndex += 2;
                } else if (value == NULL) {
                    instructions.insertBefore(node, new InsnNode(POP));
                    stackSize1 -= 1;
                } else if (value instanceof String) {
                    instructions.insertBefore(node, new VarInsnNode(ASTORE, varIndex));
                    stackSize1 -= 1;
                    varIndex += 1;
                }
            }

            if (maxLocals < varIndex) {
                maxLocals = varIndex;
            }

            instructions.insertBefore(node, new TypeInsnNode(NEW, node.owner));
            instructions.insertBefore(node, new VarInsnNode(ASTORE, newVarIndex));

            for (int i = 0; i < newVarIndex; i++) {
                if (locals[i] == newNode) {
                    instructions.insertBefore(node, new VarInsnNode(ALOAD, newVarIndex));
                    instructions.insertBefore(node, new VarInsnNode(ASTORE, i));
                }
            }

            updateMaxStack(stackSize1 + 1);

            for (int i = k, n = stack.length; i < n; i++) {
                Object value = stack[i];
                if (value == INTEGER) {
                    varIndex -= 1;
                    instructions.insertBefore(node, new VarInsnNode(ILOAD, varIndex));
                    stackSize1 += 1;
                } else if (value == FLOAT) {
                    varIndex -= 1;
                    instructions.insertBefore(node, new VarInsnNode(FLOAD, varIndex));
                    stackSize1 += 1;
                } else if (value == DOUBLE) {
                    varIndex -= 2;
                    instructions.insertBefore(node, new VarInsnNode(DLOAD, varIndex));
                    stackSize1 += 2;
                } else if (value == LONG) {
                    varIndex -= 2;
                    instructions.insertBefore(node, new VarInsnNode(LLOAD, varIndex));
                    stackSize1 += 2;
                } else if (value == NULL) {
                    instructions.insertBefore(node, new InsnNode(ACONST_NULL));
                    stackSize1 += 1;
                } else if (value instanceof String) {
                    varIndex -= 1;
                    instructions.insertBefore(node, new VarInsnNode(ALOAD, varIndex));
                    stackSize1 += 1;
                } else if (value == newNode) {
                    instructions.insertBefore(node, new VarInsnNode(ALOAD, newVarIndex));
                    stackSize1 += 1;
                }
            }

            updateMaxStack(stackSize1);
        }
    }

    stackSize1 += (sizes & 0x03) - argSize;
    updateMaxStack(stackSize1);

    return stackSize1;
}

From source file:pl.clareo.coroutines.core.ClassTransformer.java

License:Apache License

private static String getCoroutineName(MethodNode method) {
    // little name mangling, let's feel like we were writing C++ compiler
    // :-)//w ww  .  j a  v a  2  s. c  o m
    StringBuilder sb = new StringBuilder(method.name);
    int descHash = abs(Type.getArgumentsAndReturnSizes(method.desc));
    sb.append(descHash);
    Type[] argsTypes = Type.getArgumentTypes(method.desc);
    for (Type t : argsTypes) {
        if (t.getSort() == Type.OBJECT) {
            String argClassname = t.getClassName();
            sb.append('_').append(abs(argClassname.hashCode()));
        } else {
            sb.append('_').append(t.getSort());
        }
    }
    return sb.toString();
}

From source file:pl.clareo.coroutines.core.ClassTransformer.java

License:Apache License

@SuppressWarnings("unchecked")
void transform() {
    for (MethodNode coroutine : coroutines) {
        if (log.isLoggable(Level.FINEST)) {
            log.finest("Generating method for coroutine " + coroutine.name + coroutine.desc);
        }//from  ww  w.  j  a va  2  s . com
        String coroutineName = getCoroutineName(coroutine);
        MethodTransformer methodTransformer = new MethodTransformer(coroutine, thisType);
        MethodNode coroutineImpl = methodTransformer.transform(coroutineName, generateDebugCode);
        thisNode.methods.add(coroutineImpl);
        /*
         * generate co iterators and method stubs
         */
        log.finest("Generating CoIterator implementation and method stubs");
        String baseCoIteratorName;
        Map<String, Object> annotation = getCoroutineAnnotationValues(coroutine);
        if (getBoolean(annotation, "threadLocal")) {
            baseCoIteratorName = Type.getInternalName(ThreadLocalCoIterator.class);
        } else {
            baseCoIteratorName = Type.getInternalName(SingleThreadedCoIterator.class);
        }
        String coIteratorClassName = "pl/clareo/coroutines/core/CoIterator" + num;
        ClassNode coIteratorClass = new ClassNode();
        coIteratorClass.version = Opcodes.V1_6;
        coIteratorClass.access = Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER;
        coIteratorClass.name = coIteratorClassName;
        coIteratorClass.superName = baseCoIteratorName;
        if (generateDebugCode) {
            /*
             * If debugging code is emitted create field keeping JDK logger
             */
            FieldNode loggerField = new FieldNode(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC,
                    "logger", "Ljava/util/logging/Logger;", null, null);
            coIteratorClass.fields.add(loggerField);
            MethodNode clinit = new MethodNode();
            clinit.access = Opcodes.ACC_STATIC;
            clinit.name = "<clinit>";
            clinit.desc = "()V";
            clinit.exceptions = Collections.EMPTY_LIST;
            String loggerName = thisType.getClassName();
            InsnList clinitCode = clinit.instructions;
            clinitCode.add(new LdcInsnNode(loggerName));
            clinitCode.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/util/logging/Logger", "getLogger",
                    "(Ljava/lang/String;)Ljava/util/logging/Logger;"));
            clinitCode.add(new FieldInsnNode(Opcodes.PUTSTATIC, coIteratorClassName, "logger",
                    "Ljava/util/logging/Logger;"));
            clinitCode.add(new InsnNode(Opcodes.RETURN));
            clinit.maxStack = 1;
            clinit.maxLocals = 0;
            coIteratorClass.methods.add(clinit);
        }
        /*
         * Generate constructor
         */
        MethodNode init = new MethodNode();
        init.access = Opcodes.ACC_PUBLIC;
        init.name = "<init>";
        init.desc = CO_ITERATOR_CONSTRUCTOR_DESCRIPTOR;
        init.exceptions = Collections.EMPTY_LIST;
        InsnList initCode = init.instructions;
        initCode.add(new VarInsnNode(Opcodes.ALOAD, 0));
        initCode.add(new VarInsnNode(Opcodes.ALOAD, 1));
        initCode.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, baseCoIteratorName, "<init>",
                CO_ITERATOR_CONSTRUCTOR_DESCRIPTOR));
        initCode.add(new InsnNode(Opcodes.RETURN));
        init.maxStack = 2;
        init.maxLocals = 2;
        coIteratorClass.methods.add(init);
        /*
         * Generate overriden call to coroutine
         */
        MethodNode call = new MethodNode();
        call.access = Opcodes.ACC_PROTECTED;
        call.name = "call";
        call.desc = CALL_METHOD_DESCRIPTOR;
        call.exceptions = Collections.EMPTY_LIST;
        InsnList callCode = call.instructions;
        /*
         * if debug needed generate call details
         */
        if (generateDebugCode) {
            String coroutineId = "Coroutine " + coroutine.name;
            callCode.add(loggingInstructions(coIteratorClassName, "logger", Level.FINER,
                    coroutineId + " call. Caller sent: ", 2));
            callCode.add(new FrameNode(Opcodes.F_SAME, 0, EMPTY_LOCALS, 0, EMPTY_STACK));
            callCode.add(loggingInstructions(coIteratorClassName, "logger", Level.FINEST,
                    coroutineId + " state ", 1));
            callCode.add(new FrameNode(Opcodes.F_SAME, 0, EMPTY_LOCALS, 0, EMPTY_STACK));
        }
        /*
         * push call arguments: this (if not static), frame, input, output
         */
        boolean isStatic = (coroutine.access & Opcodes.ACC_STATIC) != 0;
        if (!isStatic) {
            callCode.add(new VarInsnNode(Opcodes.ALOAD, 1));
            callCode.add(
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FRAME_NAME, "getThis", "()Ljava/lang/Object;"));
            callCode.add(new TypeInsnNode(Opcodes.CHECKCAST, thisType.getInternalName()));
        }
        callCode.add(new VarInsnNode(Opcodes.ALOAD, 1));
        callCode.add(new InsnNode(Opcodes.ACONST_NULL));
        callCode.add(new VarInsnNode(Opcodes.ALOAD, 2));
        callCode.add(new MethodInsnNode(isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL,
                thisType.getInternalName(), coroutineName, COROUTINE_METHOD_DESCRIPTOR));
        // stack: *
        if (!generateDebugCode) {
            callCode.add(new InsnNode(Opcodes.ARETURN));
        } else {
            // save result display suspension point (two more locals
            // needed)
            callCode.add(new VarInsnNode(Opcodes.ASTORE, 3));
            callCode.add(new VarInsnNode(Opcodes.ALOAD, 1));
            callCode.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FRAME_NAME, "getLineOfCode", "()I"));
            callCode.add(box_int(Type.INT));
            callCode.add(new VarInsnNode(Opcodes.ASTORE, 4));
            callCode.add(loggingInstructions(coIteratorClassName, "logger", Level.FINER,
                    "Coroutine suspended at line ", 4, ". Yielded:", 3));
            callCode.add(new FrameNode(Opcodes.F_APPEND, 2,
                    new Object[] { "java/lang/Object", "java/lang/Integer" }, 0, EMPTY_STACK));
            callCode.add(new VarInsnNode(Opcodes.ALOAD, 3));
            callCode.add(new InsnNode(Opcodes.ARETURN));
        }
        coIteratorClass.methods.add(call);
        // if debugging code is emitted it needs space for two
        // additional locals and 5 stack operand
        if (generateDebugCode) {
            call.maxStack = 5;
            call.maxLocals = 5;
        } else {
            if (isStatic) {
                call.maxStack = 3;
            } else {
                call.maxStack = 4;
            }
            call.maxLocals = 3;
        }
        /*
         * CoIterator created - define it in the runtime and verify if
         * needed
         */
        if (log.isLoggable(Level.FINEST)) {
            log.finest("Generated class " + coIteratorClassName);
        }
        ClassWriter cw = new ClassWriter(0);
        coIteratorClass.accept(cw);
        byte[] classBytes = cw.toByteArray();
        try {
            CoroutineInstrumentator.dumpClass(coIteratorClassName, classBytes);
        } catch (IOException e) {
            throw new CoroutineGenerationException("Unable to write class " + coIteratorClassName, e);
        }
        /*
         * start generating method - new method is named as the method in
         * user code, it: returns instance of appropriate CoIterator (see
         * above), saves arguments of call
         */
        if (log.isLoggable(Level.FINEST)) {
            log.finest("Instrumenting method " + coroutine.name);
        }
        InsnList code = coroutine.instructions;
        code.clear();
        /*
         * create new Frame
         */
        boolean isDebugFramePossible = generateDebugCode && coroutine.localVariables != null;
        if (isDebugFramePossible) {
            code.add(createDebugFrame(coroutine));
        } else {
            code.add(createFrame(coroutine));
        }
        /*
         * save frame in the first, and locals array in the second local
         * variable
         */
        int argsSize = Type.getArgumentsAndReturnSizes(coroutine.desc) >> 2;
        if (isStatic) {
            argsSize -= 1;
        }
        code.add(new VarInsnNode(Opcodes.ASTORE, argsSize));
        code.add(new VarInsnNode(Opcodes.ALOAD, argsSize));
        code.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FRAME_NAME, "getLocals", "()[Ljava/lang/Object;"));
        int localsArrayIndex = argsSize + 1;
        code.add(new VarInsnNode(Opcodes.ASTORE, localsArrayIndex));
        /*
         * save all call arguments (along with this if this method is not
         * static) into locals array
         */
        Type[] argsTypes = Type.getArgumentTypes(coroutine.desc);
        if (!isStatic) {
            code.add(saveloc(localsArrayIndex, 0, 0, JAVA_LANG_OBJECT));
            code.add(savelocs(localsArrayIndex, 1, 1, argsTypes));
        } else {
            code.add(savelocs(localsArrayIndex, 0, 0, argsTypes));
        }
        /*
         * create CoIterator instance with saved frame, make initial call to
         * next if needed and return to caller
         */
        code.add(new TypeInsnNode(Opcodes.NEW, coIteratorClassName));
        code.add(new InsnNode(Opcodes.DUP));
        code.add(new VarInsnNode(Opcodes.ALOAD, argsSize));
        code.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, coIteratorClassName, "<init>",
                CO_ITERATOR_CONSTRUCTOR_DESCRIPTOR));
        if (!getBoolean(annotation, "generator", true)) {
            code.add(new InsnNode(Opcodes.DUP));
            code.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, coIteratorClassName, "next",
                    "()Ljava/lang/Object;"));
            code.add(new InsnNode(Opcodes.POP));
        }
        code.add(new InsnNode(Opcodes.ARETURN));
        /*
         * end method generation; maxs can be statically determined 3
         * operands on stack (call to frame setLocals and CoIterator
         * constructor) + 1 if any argument is long or double (debug frame
         * needs 7 operands for variable names creation); locals = argsSize
         * + 1 reference to frame + 1 array of locals
         */
        if (isDebugFramePossible) {
            coroutine.maxStack = 7;
        } else {
            boolean isCategory2ArgumentPresent = false;
            for (Type argType : argsTypes) {
                int sort = argType.getSort();
                if (sort == Type.LONG || sort == Type.DOUBLE) {
                    isCategory2ArgumentPresent = true;
                    break;
                }
            }
            coroutine.maxStack = isCategory2ArgumentPresent ? 4 : 3;
        }
        coroutine.maxLocals = localsArrayIndex + 1;
        coroutine.localVariables.clear();
        coroutine.tryCatchBlocks.clear();
        num++;
    }
}