Example usage for org.objectweb.asm.tree.analysis BasicValue UNINITIALIZED_VALUE

List of usage examples for org.objectweb.asm.tree.analysis BasicValue UNINITIALIZED_VALUE

Introduction

In this page you can find the example usage for org.objectweb.asm.tree.analysis BasicValue UNINITIALIZED_VALUE.

Prototype

BasicValue UNINITIALIZED_VALUE

To view the source code for org.objectweb.asm.tree.analysis BasicValue UNINITIALIZED_VALUE.

Click Source Link

Document

An uninitialized value.

Usage

From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java

License:Open Source License

private void emitRestoreState(MethodVisitor mv, int idx, FrameInfo fi, int numArgsPreserved) {
    Frame f = frames[fi.endInstruction];

    // restore local vars
    for (int i = firstLocal; i < f.getLocals(); i++) {
        BasicValue v = (BasicValue) f.getLocal(i);
        if (!isNullType(v)) {
            int slotIdx = fi.localSlotIndices[i];
            assert slotIdx >= 0 && slotIdx < fi.numSlots;
            emitRestoreValue(mv, v, lvarStack, slotIdx, i);
            mv.visitVarInsn(v.getType().getOpcode(Opcodes.ISTORE), i);
        } else if (v != BasicValue.UNINITIALIZED_VALUE) {
            mv.visitInsn(Opcodes.ACONST_NULL);
            mv.visitVarInsn(Opcodes.ASTORE, i);
        }//w w w  .  j a  v  a  2s . c om
    }

    // restore operand stack
    for (int i = 0; i < f.getStackSize() - numArgsPreserved; i++) {
        BasicValue v = (BasicValue) f.getStack(i);
        if (!isOmitted(v)) {
            if (!isNullType(v)) {
                int slotIdx = fi.stackSlotIndices[i];
                assert slotIdx >= 0 && slotIdx < fi.numSlots;
                emitRestoreValue(mv, v, lvarStack, slotIdx, -1);
            } else {
                mv.visitInsn(Opcodes.ACONST_NULL);
            }
        }
    }

    if (fi.lAfter != null) {
        fi.lAfter.accept(mv);
    }
}

From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java

License:Open Source License

static boolean isNullType(BasicValue v) {
    return (v == BasicValue.UNINITIALIZED_VALUE)
            || (v.isReference() && v.getType().getInternalName().equals("null"));
}

From source file:com.android.build.gradle.internal.incremental.ConstructorBuilder.java

License:Apache License

/**
 * Deconstruct a constructor into its components and adds the necessary code to link the components
 * later. This code is not valid java, but it can be expressed in bytecode. In essence for this constructor:
 * <pre>{@code//  www.  j ava2 s. com
 *   <init>(int x) {
 *     int a = 2;
 *     super(int b = 3, x = 1, expr2() ? 3 : a++)
 *     doSomething(x + a)
 *   }
 * }</pre>
 * it creates two parts:
 * <pre>{@code
 *   Object[] init$args(Clazz this, int x, Object[] locals) { // this is always null here
 *     int a = locals[0];
 *     int b = 3;
 *     Object[] args = new Object[3];
 *     args[0] = b;
 *     args[1] = (x = 1)
 *     args[2] = expr2() ? 3 : a++;
 *     locals = new Object[3]; // The arguments + the locals
 *     locals[0] = NULL;
 *     locals[1] = x;
 *     locals[2] = new Object[2];
 *     locals[2][0] = a;
 *     locals[2][1] = b;
 *     return new Object[] {locals, "myclass.<init>(I;I;)V", args};
 *   }
 *
 *   void init$body(int x, Object[] locals) {
 *     int a = locals[0];
 *     int b = locals[1];
 *     doSomething(x + a);
 *   }
 * }</pre>
 *
 * @param owner the owning class.
 * @param method the constructor method.
 */
@NonNull
public static Constructor build(@NonNull String owner, @NonNull MethodNode method) {
    // Basic interpreter uses BasicValue.REFERENCE_VALUE for all object types. However
    // we need to distinguish one in particular. The value of the local variable 0, ie. the
    // uninitialized this. By doing it this way we ensure that whenever there is a ALOAD_0
    // a LocalValue instance will be on the stack.
    BasicInterpreter interpreter = new BasicInterpreter() {
        boolean done = false;

        @Override
        // newValue is called first to initialize the frame values of all the local variables
        // we intercept the first one to create our own special value.
        public BasicValue newValue(Type type) {
            if (type == null) {
                return BasicValue.UNINITIALIZED_VALUE;
            } else if (type.getSort() == Type.VOID) {
                return null;
            } else {
                // If this is the first value created (i.e. the first local variable)
                // we use a special marker.
                BasicValue ret = done ? super.newValue(type) : new LocalValue(type);
                done = true;
                return ret;
            }
        }
    };

    Analyzer analyzer = new Analyzer(interpreter);
    AbstractInsnNode[] instructions = method.instructions.toArray();
    try {
        Frame[] frames = analyzer.analyze(owner, method);
        if (frames.length != instructions.length) {
            // Should never happen.
            throw new IllegalStateException("The number of frames is not equals to the number of instructions");
        }
        int stackAtThis = -1;
        boolean poppedThis = false;
        int firstLocal = 1;
        for (Type type : Type.getArgumentTypes(method.desc)) {
            firstLocal += type.getSize();
        }

        LinkedHashSet<LocalVariable> variables = new LinkedHashSet<LocalVariable>();
        VarInsnNode lastThis = null;
        int localsAtLastThis = 0;
        // Records the most recent line number encountered. For javac, there should always be
        // a line number node before the call of interest to this(...) or super(...). For robustness,
        // -1 is recorded as a sentinel to indicate this assumption didn't hold. Upstream consumers
        // should check for -1 and recover in a reasonable way (for example, don't set the line
        // number in generated code).
        int recentLine = -1;
        for (int i = 0; i < instructions.length; i++) {
            AbstractInsnNode insn = instructions[i];
            Frame frame = frames[i];
            if (frame.getStackSize() < stackAtThis) {
                poppedThis = true;
            }
            if (insn instanceof MethodInsnNode) {
                // TODO: Do we need to check that the stack is empty after this super call?
                MethodInsnNode methodhInsn = (MethodInsnNode) insn;
                Type[] types = Type.getArgumentTypes(methodhInsn.desc);
                Value value = frame.getStack(frame.getStackSize() - types.length - 1);
                if (value instanceof LocalValue && methodhInsn.name.equals("<init>")) {
                    if (poppedThis) {
                        throw new IllegalStateException("Unexpected constructor structure.");
                    }
                    return split(owner, method, lastThis, methodhInsn, recentLine,
                            new ArrayList<LocalVariable>(variables), localsAtLastThis);
                }
            } else if (insn instanceof VarInsnNode) {
                VarInsnNode var = (VarInsnNode) insn;
                if (var.var == 0) {
                    lastThis = var;
                    localsAtLastThis = variables.size();
                    stackAtThis = frame.getStackSize();
                    poppedThis = false;
                }
                Type type = ByteCodeUtils.getTypeForStoreOpcode(var.getOpcode());
                if (type != null && var.var >= firstLocal) {
                    // Variables are equals based on their number, so they will be added
                    // to the set only if they are new, and in the order they are seen.
                    variables.add(new LocalVariable(type, var.var));
                }
            } else if (insn instanceof LineNumberNode) {
                // Record the most recent line number encountered so that call to this(...)
                // or super(...) has line number information. Ultimately used to emit a line
                // number in the generated code.
                LineNumberNode lineNumberNode = (LineNumberNode) insn;
                recentLine = lineNumberNode.line;
            }
        }
        throw new IllegalStateException("Unexpected constructor structure.");
    } catch (AnalyzerException e) {
        throw new IllegalStateException(e);
    }
}

From source file:com.android.build.gradle.internal.incremental.ConstructorDelegationDetector.java

License:Apache License

/**
 * Deconstruct a constructor into its components and adds the necessary code to link the components
 * later. The generated bytecode does not correspond exactly to this code, but in essence, for
 * a constructor of this form:/*from w ww .  j av a2 s .c o  m*/
 * <p/>
 * <code>
 *   <init>(int x) {
 *     super(x = 1, expr2() ? 3 : 7)
 *     doSomething(x)
 *   }
 * </code>
 * <p/>
 * it creates the two parts:
 * <code>
 *   Object[] init$args(Object[] locals, int x) {
 *     Object[] args = new Object[2];
 *     args[0] = (x = 1)
 *     args[1] = expr2() ? 3 : 7;
 *     locals[0] = x;
 *     return new Object[] {"myclass.<init>(I;I;)V", args};
 *   }
 *
 *   void init$body(int x) {
 *     doSomething(x);
 *   }
 * </code>
 *
 * @param owner the owning class.
 * @param method the constructor method.
 */
@NonNull
public static Constructor deconstruct(@NonNull String owner, @NonNull MethodNode method) {
    // Basic interpreter uses BasicValue.REFERENCE_VALUE for all object types. However
    // we need to distinguish one in particular. The value of the local variable 0, ie. the
    // uninitialized this. By doing it this way we ensure that whenever there is a ALOAD_0
    // a LocalValue instance will be on the stack.
    BasicInterpreter interpreter = new BasicInterpreter() {
        boolean done = false;

        @Override
        // newValue is called first to initialize the frame values of all the local variables
        // we intercept the first one to create our own special value.
        public BasicValue newValue(Type type) {
            if (type == null) {
                return BasicValue.UNINITIALIZED_VALUE;
            } else if (type.getSort() == Type.VOID) {
                return null;
            } else {
                // If this is the first value created (i.e. the first local variable)
                // we use a special marker.
                BasicValue ret = done ? super.newValue(type) : new LocalValue(type);
                done = true;
                return ret;
            }
        }
    };

    Analyzer analyzer = new Analyzer(interpreter);
    AbstractInsnNode[] instructions = method.instructions.toArray();
    try {
        Frame[] frames = analyzer.analyze(owner, method);
        if (frames.length != instructions.length) {
            // Should never happen.
            throw new IllegalStateException("The number of frames is not equals to the number of instructions");
        }
        VarInsnNode lastThis = null;
        int stackAtThis = -1;
        boolean poppedThis = false;
        // Records the most recent line number encountered. For javac, there should always be
        // a line number node before the call of interest to this(...) or super(...). For robustness,
        // -1 is recorded as a sentinel to indicate this assumption didn't hold. Upstream consumers
        // should check for -1 and recover in a reasonable way (for example, don't set the line
        // number in generated code).
        int recentLine = -1;
        for (int i = 0; i < instructions.length; i++) {
            AbstractInsnNode insn = instructions[i];
            Frame frame = frames[i];
            if (frame.getStackSize() < stackAtThis) {
                poppedThis = true;
            }
            if (insn instanceof MethodInsnNode) {
                // TODO: Do we need to check that the stack is empty after this super call?
                MethodInsnNode methodhInsn = (MethodInsnNode) insn;
                Type[] types = Type.getArgumentTypes(methodhInsn.desc);
                Value value = frame.getStack(frame.getStackSize() - types.length - 1);
                if (value instanceof LocalValue && methodhInsn.name.equals("<init>")) {
                    if (poppedThis) {
                        throw new IllegalStateException("Unexpected constructor structure.");
                    }
                    return split(owner, method, lastThis, methodhInsn, recentLine);
                }
            } else if (insn instanceof VarInsnNode) {
                VarInsnNode var = (VarInsnNode) insn;
                if (var.var == 0) {
                    lastThis = var;
                    stackAtThis = frame.getStackSize();
                    poppedThis = false;
                }
            } else if (insn instanceof LineNumberNode) {
                // Record the most recent line number encountered so that call to this(...)
                // or super(...) has line number information. Ultimately used to emit a line
                // number in the generated code.
                LineNumberNode lineNumberNode = (LineNumberNode) insn;
                recentLine = lineNumberNode.line;
            }
        }
        throw new IllegalStateException("Unexpected constructor structure.");
    } catch (AnalyzerException e) {
        throw new IllegalStateException(e);
    }
}

From source file:com.android.build.gradle.internal2.incremental.ConstructorBuilder.java

License:Apache License

/**
 * Deconstruct a constructor into its components and adds the necessary code to link the components
 * later. This code is not valid java, but it can be expressed in bytecode. In essence for this constructor:
 * <pre>{@code/*from www .  jav a 2 s . c  om*/
 *   <init>(int x) {
 *     int a = 2;
 *     super(int b = 3, x = 1, expr2() ? 3 : a++)
 *     doSomething(x + a)
 *   }
 * }</pre>
 * it creates two parts:
 * <pre>{@code
 *   Object[] init$args(Clazz this, int x, Object[] locals) { // this is always null here
 *     int a = locals[0];
 *     int b = 3;
 *     Object[] args = new Object[3];
 *     args[0] = b;
 *     args[1] = (x = 1)
 *     args[2] = expr2() ? 3 : a++;
 *     locals = new Object[3]; // The arguments + the locals
 *     locals[0] = NULL;
 *     locals[1] = x;
 *     locals[2] = new Object[2];
 *     locals[2][0] = a;
 *     locals[2][1] = b;
 *     return new Object[] {locals, "myclass.<init>(I;I;)V", args};
 *   }
 *
 *   void init$body(int x, Object[] locals) {
 *     int a = locals[0];
 *     int b = locals[1];
 *     doSomething(x + a);
 *   }
 * }</pre>
 *
 * @param owner the owning class.
 * @param method the constructor method.
 */
@NonNull
public static Constructor build(@NonNull String owner, @NonNull MethodNode method) {
    // Basic interpreter uses BasicValue.REFERENCE_VALUE for all object types. However
    // we need to distinguish one in particular. The value of the local variable 0, ie. the
    // uninitialized this. By doing it this way we ensure that whenever there is a ALOAD_0
    // a LocalValue instance will be on the stack.
    BasicInterpreter interpreter = new BasicInterpreter() {
        boolean done = false;

        @Override
        // newValue is called first to initialize the frame values of all the local variables
        // we intercept the first one to create our own special value.
        public BasicValue newValue(Type type) {
            if (type == null) {
                return BasicValue.UNINITIALIZED_VALUE;
            } else if (type.getSort() == Type.VOID) {
                return null;
            } else {
                // If this is the first value created (i.e. the first local variable)
                // we use a special marker.
                BasicValue ret = done ? super.newValue(type) : new LocalValue(type);
                done = true;
                return ret;
            }
        }
    };

    Analyzer analyzer = new Analyzer(interpreter);
    AbstractInsnNode[] instructions = method.instructions.toArray();
    try {
        Frame[] frames = analyzer.analyze(owner, method);
        if (frames.length != instructions.length) {
            // Should never happen.
            throw new IllegalStateException("The number of frames is not equals to the number of instructions");
        }
        int stackAtThis = -1;
        boolean poppedThis = false;
        int firstLocal = 1;
        for (Type type : Type.getArgumentTypes(method.desc)) {
            firstLocal += type.getSize();
        }

        LinkedHashSet<LocalVariable> variables = new LinkedHashSet<LocalVariable>();
        VarInsnNode lastThis = null;
        int localsAtLastThis = 0;
        // Records the most recent line number encountered. For javac, there should always be
        // a line number node before the call of interest to this(...) or super(...). For robustness,
        // -1 is recorded as a sentinel to indicate this assumption didn't hold. Upstream consumers
        // should check for -1 and recover in a reasonable way (for example, don't set the line
        // number in generated code).
        int recentLine = -1;
        for (int i = 0; i < instructions.length; i++) {
            AbstractInsnNode insn = instructions[i];
            Frame frame = frames[i];
            if (frame.getStackSize() < stackAtThis) {
                poppedThis = true;
            }
            if (insn instanceof MethodInsnNode) {
                // TODO: Do we need to check that the stack is empty after this super call?
                MethodInsnNode methodhInsn = (MethodInsnNode) insn;
                Type[] types = Type.getArgumentTypes(methodhInsn.desc);
                Value value = frame.getStack(frame.getStackSize() - types.length - 1);
                if (value instanceof LocalValue && methodhInsn.name.equals(ByteCodeUtils.CONSTRUCTOR)) {
                    if (poppedThis) {
                        throw new IllegalStateException("Unexpected constructor structure.");
                    }
                    return split(owner, method, lastThis, methodhInsn, recentLine,
                            new ArrayList<LocalVariable>(variables), localsAtLastThis);
                }
            } else if (insn instanceof VarInsnNode) {
                VarInsnNode var = (VarInsnNode) insn;
                if (var.var == 0) {
                    lastThis = var;
                    localsAtLastThis = variables.size();
                    stackAtThis = frame.getStackSize();
                    poppedThis = false;
                }
                Type type = ByteCodeUtils.getTypeForStoreOpcode(var.getOpcode());
                if (type != null && var.var >= firstLocal) {
                    // Variables are equals based on their number, so they will be added
                    // to the set only if they are new, and in the order they are seen.
                    variables.add(new LocalVariable(type, var.var));
                }
            } else if (insn instanceof LineNumberNode) {
                // Record the most recent line number encountered so that call to this(...)
                // or super(...) has line number information. Ultimately used to emit a line
                // number in the generated code.
                LineNumberNode lineNumberNode = (LineNumberNode) insn;
                recentLine = lineNumberNode.line;
            }
        }
        throw new IllegalStateException("Unexpected constructor structure.");
    } catch (AnalyzerException e) {
        throw new IllegalStateException(e);
    }
}

From source file:com.android.tools.lint.checks.ViewTagDetector.java

License:Apache License

@Override
public void checkCall(@NonNull ClassContext context, @NonNull ClassNode classNode, @NonNull MethodNode method,
        @NonNull MethodInsnNode call) {// w w w.  j  av  a  2 s .  co m
    // The leak behavior is fixed in ICS:
    // http://code.google.com/p/android/issues/detail?id=18273
    if (context.getMainProject().getMinSdk() >= 14) {
        return;
    }

    String owner = call.owner;
    String desc = call.desc;
    if (owner.equals("android/view/View") //$NON-NLS-1$
            && desc.equals("(ILjava/lang/Object;)V")) { //$NON-NLS-1$
        Analyzer analyzer = new Analyzer(new BasicInterpreter() {
            @Override
            public BasicValue newValue(Type type) {
                if (type == null) {
                    return BasicValue.UNINITIALIZED_VALUE;
                } else if (type.getSort() == Type.VOID) {
                    return null;
                } else {
                    return new BasicValue(type);
                }
            }
        });
        try {
            Frame[] frames = analyzer.analyze(classNode.name, method);
            InsnList instructions = method.instructions;
            Frame frame = frames[instructions.indexOf(call)];
            if (frame.getStackSize() < 3) {
                return;
            }
            BasicValue stackValue = (BasicValue) frame.getStack(2);
            Type type = stackValue.getType();
            if (type == null) {
                return;
            }

            String internalName = type.getInternalName();
            String className = type.getClassName();
            LintDriver driver = context.getDriver();

            SdkInfo sdkInfo = context.getClient().getSdkInfo(context.getMainProject());
            String objectType = null;
            while (className != null) {
                if (className.equals("android.view.View")) { //$NON-NLS-1$
                    objectType = "views";
                    break;
                } else if (className.endsWith("ViewHolder")) { //$NON-NLS-1$
                    objectType = "view holders";
                    break;
                } else if (className.endsWith("Cursor") //$NON-NLS-1$
                        && className.startsWith("android.")) { //$NON-NLS-1$
                    objectType = "cursors";
                    break;
                }

                // TBD: Bitmaps, drawables? That's tricky, because as explained in
                // http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html
                // apparently these are used along with nulling out the callbacks,
                // and that's harder to detect here

                String parent = sdkInfo.getParentViewClass(className);
                if (parent == null) {
                    if (internalName == null) {
                        internalName = className.replace('.', '/');
                    }
                    assert internalName != null;
                    parent = driver.getSuperClass(internalName);
                }
                className = parent;
                internalName = null;
            }

            if (objectType != null) {
                Location location = context.getLocation(call);
                String message = String.format("Avoid setting %1$s as values for setTag: "
                        + "Can lead to memory leaks in versions older than Android 4.0", objectType);
                context.report(ISSUE, method, call, location, message, null);
            }
        } catch (AnalyzerException e) {
            context.log(e, null);
        }
    }
}

From source file:com.dragome.callbackevictor.serverside.bytecode.transformation.asm.ContinuationMethodAdapter.java

License:Apache License

public void visitCode() {
    mv.visitCode();/*from  w  w  w.  j a v  a 2s .com*/

    int fsize = labels.size();
    Label[] restoreLabels = new Label[fsize];
    for (int i = 0; i < restoreLabels.length; i++) {
        restoreLabels[i] = new Label();
    }

    // verify if restoring
    Label l0 = new Label();

    // PC: StackRecorder stackRecorder = StackRecorder.get();
    mv.visitMethodInsn(INVOKESTATIC, STACK_RECORDER, "get", "()L" + STACK_RECORDER + ";", false);
    mv.visitInsn(DUP);
    mv.visitVarInsn(ASTORE, stackRecorderVar);
    mv.visitLabel(startLabel);

    // PC: if (stackRecorder != null && !stackRecorder.isRestoring) {  
    mv.visitJumpInsn(IFNULL, l0);
    mv.visitVarInsn(ALOAD, stackRecorderVar);
    mv.visitFieldInsn(GETFIELD, STACK_RECORDER, "isRestoring", "Z");
    mv.visitJumpInsn(IFEQ, l0);

    mv.visitVarInsn(ALOAD, stackRecorderVar);
    // PC:    stackRecorder.popInt();
    mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Int", "()I", false);
    mv.visitTableSwitchInsn(0, fsize - 1, l0, restoreLabels);

    // switch cases
    for (int i = 0; i < fsize; i++) {
        Label frameLabel = labels.get(i);
        mv.visitLabel(restoreLabels[i]);

        MethodInsnNode mnode = nodes.get(i);
        Frame frame = analyzer.getFrames()[canalyzer.getIndex(mnode)];

        // for each local variable store the value in locals popping it from the stack!
        // locals
        int lsize = frame.getLocals();
        for (int j = lsize - 1; j >= 0; j--) {
            BasicValue value = (BasicValue) frame.getLocal(j);
            if (isNull(value)) {
                mv.visitInsn(ACONST_NULL);
                mv.visitVarInsn(ASTORE, j);
            } else if (value == BasicValue.UNINITIALIZED_VALUE) {
                // TODO ??
            } else if (value == BasicValue.RETURNADDRESS_VALUE) {
                // TODO ??
            } else {
                mv.visitVarInsn(ALOAD, stackRecorderVar);
                Type type = value.getType();
                if (value.isReference()) {
                    mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Object",
                            "()Ljava/lang/Object;", false);
                    Type t = value.getType();
                    String desc = t.getDescriptor();
                    if (desc.charAt(0) == '[') {
                        mv.visitTypeInsn(CHECKCAST, desc);
                    } else {
                        mv.visitTypeInsn(CHECKCAST, t.getInternalName());
                    }
                    mv.visitVarInsn(ASTORE, j);

                } else {
                    mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPopMethod(type),
                            "()" + type.getDescriptor(), false);
                    mv.visitVarInsn(type.getOpcode(ISTORE), j);
                }
            }
        }

        if (frame instanceof MonitoringFrame) {
            int[] monitoredLocals = ((MonitoringFrame) frame).getMonitored();
            // System.out.println(System.identityHashCode(frame)+" AMonitored locals "+monitoredLocals.length);
            for (int monitoredLocal : monitoredLocals) {
                // System.out.println(System.identityHashCode(frame)+" AMonitored local "+monitoredLocals[j]);
                mv.visitVarInsn(ALOAD, monitoredLocal);
                mv.visitInsn(MONITORENTER);
            }
        }

        // stack
        int argSize = Type.getArgumentTypes(mnode.desc).length;
        int ownerSize = mnode.getOpcode() == INVOKESTATIC ? 0 : 1; // TODO
        int initSize = mnode.name.equals("<init>") ? 2 : 0;
        int ssize = frame.getStackSize();
        for (int j = 0; j < ssize - argSize - ownerSize - initSize; j++) {
            BasicValue value = (BasicValue) frame.getStack(j);
            if (isNull(value)) {
                mv.visitInsn(ACONST_NULL);
            } else if (value == BasicValue.UNINITIALIZED_VALUE) {
                // TODO ??
            } else if (value == BasicValue.RETURNADDRESS_VALUE) {
                // TODO ??
            } else if (value.isReference()) {
                mv.visitVarInsn(ALOAD, stackRecorderVar);
                mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Object", "()Ljava/lang/Object;",
                        false);
                mv.visitTypeInsn(CHECKCAST, value.getType().getInternalName());
            } else {
                Type type = value.getType();
                mv.visitVarInsn(ALOAD, stackRecorderVar);
                mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPopMethod(type),
                        "()" + type.getDescriptor(), false);
            }
        }

        boolean hasMethodRef = false;
        if (mnode.getOpcode() != INVOKESTATIC) {
            // Load the object whose method we are calling  
            BasicValue value = ((BasicValue) frame.getStack(ssize - argSize - 1));
            if (isNull(value)) {
                // If user code causes NPE, then we keep this behavior: load null to get NPE at runtime 
                mv.visitInsn(ACONST_NULL);
            } else {
                hasMethodRef = true;

                mv.visitVarInsn(ALOAD, stackRecorderVar);
                mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Reference",
                        "()Ljava/lang/Object;", false);
                mv.visitTypeInsn(CHECKCAST, value.getType().getInternalName());

            }
        }

        // Create null types for the parameters of the method invocation
        // RS:
        if (hasMethodRef && canalyzer._continueReflection && mnode.name.contains("invoke")
                && mnode.owner.contains("java/lang/reflect/Method")) {
            ContinuationMethodAnalyzer.MyVariables vars = canalyzer._reflectMapping.get(mnode);
            mv.visitVarInsn(ALOAD, vars.objectVar());
            mv.visitVarInsn(ALOAD, vars.argsVar());
            //mv.visitVarInsn(ALOAD, 2);
            //mv.visitVarInsn(ALOAD, 4);
        }
        //RS:
        else {
            for (Type paramType : Type.getArgumentTypes(mnode.desc)) {
                pushDefault(paramType);
            }
        }

        // continue to the next method
        mv.visitJumpInsn(GOTO, frameLabel);
    }

    // PC: }
    // end of start block
    mv.visitLabel(l0);
}

From source file:com.dragome.callbackevictor.serverside.bytecode.transformation.asm.ContinuationMethodAdapter.java

License:Apache License

public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
    mv.visitMethodInsn(opcode, owner, name, desc, itf);

    if (currentFrame != null) {
        Label fl = new Label();

        mv.visitVarInsn(ALOAD, stackRecorderVar);
        mv.visitJumpInsn(IFNULL, fl);//from w ww .j a  v  a2  s  . c o  m
        mv.visitVarInsn(ALOAD, stackRecorderVar);
        mv.visitFieldInsn(GETFIELD, STACK_RECORDER, "isCapturing", "Z");
        mv.visitJumpInsn(IFEQ, fl);

        // save stack
        Type returnType = Type.getReturnType(desc);
        boolean hasReturn = returnType != Type.VOID_TYPE;
        if (hasReturn) {
            mv.visitInsn(returnType.getSize() == 1 ? POP : POP2);
        }

        Type[] params = Type.getArgumentTypes(desc);
        int argSize = params.length;
        int ownerSize = opcode == INVOKESTATIC ? 0 : 1; // TODO
        int ssize = currentFrame.getStackSize() - argSize - ownerSize;
        for (int i = ssize - 1; i >= 0; i--) {
            BasicValue value = (BasicValue) currentFrame.getStack(i);
            if (isNull(value)) {
                mv.visitInsn(POP);
            } else if (value == BasicValue.UNINITIALIZED_VALUE) {
                // TODO ??
            } else if (value.isReference()) {
                mv.visitVarInsn(ALOAD, stackRecorderVar);
                mv.visitInsn(SWAP);
                mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, PUSH_METHOD + "Object",
                        "(Ljava/lang/Object;)V", false);
            } else {
                Type type = value.getType();
                if (type.getSize() > 1) {
                    mv.visitInsn(ACONST_NULL); // dummy stack entry
                    mv.visitVarInsn(ALOAD, stackRecorderVar);
                    mv.visitInsn(DUP2_X2); // swap2 for long/double
                    mv.visitInsn(POP2);
                    mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPushMethod(type),
                            "(" + type.getDescriptor() + ")V", false);
                    mv.visitInsn(POP); // remove dummy stack entry
                } else {
                    mv.visitVarInsn(ALOAD, stackRecorderVar);
                    mv.visitInsn(SWAP);
                    mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPushMethod(type),
                            "(" + type.getDescriptor() + ")V", false);
                }
            }
        }

        if (!isStatic) {
            //RS:
            if (canalyzer._continueReflection && name.equals("invoke")
                    && owner.startsWith("java/lang/reflect/Method")) {
                mv.visitVarInsn(ALOAD, stackRecorderVar);
                ContinuationMethodAnalyzer.MyVariables vars = canalyzer._reflectMapping
                        .get(nodes.get(currentIndex));
                //               System.out.println("Class:" + canalyzer.className + "method:" + stackRecorderVar + ":" + name + ":" + owner + ":" + desc + ":" + vars.methodVar());
                mv.visitVarInsn(ALOAD, vars.methodVar());
                //mv.visitVarInsn(ALOAD, 3);
                mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, "replace" + "Reference",
                        "(Ljava/lang/Object;)V", false);
            }
            //RS:
            mv.visitVarInsn(ALOAD, stackRecorderVar);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, PUSH_METHOD + "Reference",
                    "(Ljava/lang/Object;)V", false);
        }

        // save locals
        int fsize = currentFrame.getLocals();
        for (int j = 0; j < fsize; j++) {
            BasicValue value = (BasicValue) currentFrame.getLocal(j);
            if (isNull(value)) {
                // no need to save null
            } else if (value == BasicValue.UNINITIALIZED_VALUE) {
                // no need to save uninitialized objects
            } else if (value.isReference()) {
                mv.visitVarInsn(ALOAD, stackRecorderVar);
                mv.visitVarInsn(ALOAD, j);
                mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, PUSH_METHOD + "Object",
                        "(Ljava/lang/Object;)V", false);
            } else {
                mv.visitVarInsn(ALOAD, stackRecorderVar);
                Type type = value.getType();
                mv.visitVarInsn(type.getOpcode(ILOAD), j);
                mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPushMethod(type),
                        "(" + type.getDescriptor() + ")V", false);
            }
        }

        mv.visitVarInsn(ALOAD, stackRecorderVar);
        if (currentIndex >= 128) {
            // if > 127 then it's a SIPUSH, not a BIPUSH...
            mv.visitIntInsn(SIPUSH, currentIndex);
        } else {
            // TODO optimize to iconst_0...
            mv.visitIntInsn(BIPUSH, currentIndex);
        }
        mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, "pushInt", "(I)V", false);

        if (currentFrame instanceof MonitoringFrame) {
            int[] monitoredLocals = ((MonitoringFrame) currentFrame).getMonitored();
            // System.out.println(System.identityHashCode(currentFrame)+" Monitored locals "+monitoredLocals.length);
            for (int monitoredLocal : monitoredLocals) {
                // System.out.println(System.identityHashCode(currentFrame)+" Monitored local "+monitoredLocals[j]);
                mv.visitVarInsn(ALOAD, monitoredLocal);
                mv.visitInsn(MONITOREXIT);
            }
        }

        Type methodReturnType = Type.getReturnType(methodDesc);
        pushDefault(methodReturnType);
        mv.visitInsn(methodReturnType.getOpcode(IRETURN));
        mv.visitLabel(fl);

        currentIndex++;
        currentFrame = null;
    }
}

From source file:dodola.anole.lib.ConstructorDelegationDetector.java

License:Apache License

/**
 * Deconstruct a constructor into its components and adds the necessary code to link the components
 * later. The generated bytecode does not correspond exactly to this code, but in essence, for
 * a constructor of this form:// w  w  w  . ja v  a 2  s. c om
 * <p/>
 * <code>
 * <init>(int x) {
 * super(x = 1, expr2() ? 3 : 7)
 * doSomething(x)
 * }
 * </code>
 * <p/>
 * it creates the two parts:
 * <code>
 * Object[] init$args(Object[] locals, int x) {
 * Object[] args = new Object[2];
 * args[0] = (x = 1)
 * args[1] = expr2() ? 3 : 7;
 * locals[0] = x;
 * return new Object[] {"myclass.<init>(I;I;)V", args};
 * }
 * <p>
 * void init$body(int x) {
 * doSomething(x);
 * }
 * </code>
 *
 * @param owner  the owning class.
 * @param method the constructor method.
 */
public static Constructor deconstruct(String owner, MethodNode method) {
    // Basic interpreter uses BasicValue.REFERENCE_VALUE for all object types. However
    // we need to distinguish one in particular. The value of the local variable 0, ie. the
    // uninitialized this. By doing it this way we ensure that whenever there is a ALOAD_0
    // a LocalValue instance will be on the stack.
    BasicInterpreter interpreter = new BasicInterpreter() {
        boolean done = false;

        @Override
        // newValue is called first to initialize the frame values of all the local variables
        // we intercept the first one to create our own special value.
        public BasicValue newValue(Type type) {
            if (type == null) {
                return BasicValue.UNINITIALIZED_VALUE;
            } else if (type.getSort() == Type.VOID) {
                return null;
            } else {
                // If this is the first value created (i.e. the first local variable)
                // we use a special marker.
                BasicValue ret = done ? super.newValue(type) : new LocalValue(type);
                done = true;
                return ret;
            }
        }
    };

    Analyzer analyzer = new Analyzer(interpreter);
    AbstractInsnNode[] instructions = method.instructions.toArray();
    try {
        Frame[] frames = analyzer.analyze(owner, method);
        if (frames.length != instructions.length) {
            // Should never happen.
            throw new IllegalStateException("The number of frames is not equals to the number of instructions");
        }
        VarInsnNode lastThis = null;
        int stackAtThis = -1;
        boolean poppedThis = false;
        // Records the most recent line number encountered. For javac, there should always be
        // a line number node before the call of interest to this(...) or super(...). For robustness,
        // -1 is recorded as a sentinel to indicate this assumption didn't hold. Upstream consumers
        // should check for -1 and recover in a reasonable way (for example, don't set the line
        // number in generated code).
        int recentLine = -1;
        for (int i = 0; i < instructions.length; i++) {
            AbstractInsnNode insn = instructions[i];
            Frame frame = frames[i];
            if (frame.getStackSize() < stackAtThis) {
                poppedThis = true;
            }
            if (insn instanceof MethodInsnNode) {
                // TODO: Do we need to check that the stack is empty after this super call?
                MethodInsnNode methodhInsn = (MethodInsnNode) insn;
                Type[] types = Type.getArgumentTypes(methodhInsn.desc);
                Value value = frame.getStack(frame.getStackSize() - types.length - 1);
                if (value instanceof LocalValue && methodhInsn.name.equals("<init>")) {
                    if (poppedThis) {
                        throw new IllegalStateException("Unexpected constructor structure.");
                    }
                    return split(owner, method, lastThis, methodhInsn, recentLine);
                }
            } else if (insn instanceof VarInsnNode) {
                VarInsnNode var = (VarInsnNode) insn;
                if (var.var == 0) {
                    lastThis = var;
                    stackAtThis = frame.getStackSize();
                    poppedThis = false;
                }
            } else if (insn instanceof LineNumberNode) {
                // Record the most recent line number encountered so that call to this(...)
                // or super(...) has line number information. Ultimately used to emit a line
                // number in the generated code.
                LineNumberNode lineNumberNode = (LineNumberNode) insn;
                recentLine = lineNumberNode.line;
            }
        }
        throw new IllegalStateException("Unexpected constructor structure.");
    } catch (AnalyzerException e) {
        throw new IllegalStateException(e);
    }
}

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

License:Open Source License

@Override
public BasicValue merge(final BasicValue v, final BasicValue w) {
    if (!v.equals(w)) {
        Type t = v.getType();/*from w w w  . j  a v a  2 s . c  o  m*/
        Type u = w.getType();
        if (t != null && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY)) {
            if (u != null && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY)) {
                if ("Lnull;".equals(t.getDescriptor())) {
                    return w;
                }
                if ("Lnull;".equals(u.getDescriptor())) {
                    return v;
                }
                if (isAssignableFrom(t, u)) {
                    return v;
                }
                if (isAssignableFrom(u, t)) {
                    return w;
                }

                if (t.getSort() == Type.ARRAY && u.getSort() == Type.ARRAY) {
                    BasicValue vComp = new BasicValue(
                            Reflection.makeArrayType(t.getDimensions() - 1, t.getElementType()));
                    BasicValue wComp = new BasicValue(
                            Reflection.makeArrayType(u.getDimensions() - 1, u.getElementType()));
                    BasicValue mergedComp = merge(vComp, wComp);
                    if (!mergedComp.equals(BasicValue.UNINITIALIZED_VALUE)) {
                        Type mergedCompType = mergedComp.getType();
                        return new BasicValue(Reflection.makeArrayType(1, mergedCompType));
                    }
                }

                do {
                    if (t == null || isInterface(t)) {
                        return BasicValue.REFERENCE_VALUE;
                    }
                    t = getSuperClass(t);
                    if (isAssignableFrom(t, u)) {
                        return newValue(t);
                    }
                } while (true);
            }
        }
        return BasicValue.UNINITIALIZED_VALUE;
    }
    return v;
}