Example usage for org.objectweb.asm.tree.analysis SourceInterpreter SourceInterpreter

List of usage examples for org.objectweb.asm.tree.analysis SourceInterpreter SourceInterpreter

Introduction

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

Prototype

public SourceInterpreter() 

Source Link

Document

Constructs a new SourceInterpreter for the latest ASM API version.

Usage

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

License:Apache License

@Nullable
private String findFirstArgType(ClassContext context, ClassNode classNode, MethodNode method,
        MethodInsnNode call) {/*  w  w  w  .j  a  v  a 2 s  .co m*/
    // Find object being passed in as the first argument
    Analyzer analyzer = new Analyzer(new SourceInterpreter() {
        @Override
        public SourceValue newOperation(AbstractInsnNode insn) {
            if (insn.getOpcode() == Opcodes.NEW) {
                String desc = ((TypeInsnNode) insn).desc;
                return new TypeValue(1, desc);
            }
            return super.newOperation(insn);
        }

        @Override
        public SourceValue newValue(Type type) {
            if (type != null && type.getSort() == Type.VOID) {
                return null;
            } else if (type != null) {
                return new TypeValue(1, type.getInternalName());
            }
            return super.newValue(type);
        }

        @Override
        public SourceValue copyOperation(AbstractInsnNode insn, SourceValue value) {
            return value;
        }
    });
    try {
        Frame[] frames = analyzer.analyze(classNode.name, method);
        InsnList instructions = method.instructions;
        Frame frame = frames[instructions.indexOf(call)];
        if (frame.getStackSize() <= 1) {
            return null;
        }
        SourceValue stackValue = (SourceValue) frame.getStack(1);
        if (stackValue instanceof TypeValue) {
            return ((TypeValue) stackValue).getFqcn();
        }
    } catch (AnalyzerException e) {
        context.log(e, null);
    }

    return null;
}

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

License:Apache License

@Override
public void checkCall(@NonNull ClassContext context, @NonNull ClassNode classNode, @NonNull MethodNode method,
        @NonNull MethodInsnNode call) {// ww  w  .j  av a  2 s .c o m
    String owner = call.owner;
    String desc = call.desc;
    String name = call.name;
    if (owner.equals(DATE_FORMAT_OWNER)) {
        if (!name.equals(CONSTRUCTOR_NAME)) {
            return;
        }
        if (desc.equals("(Ljava/lang/String;Ljava/text/DateFormatSymbols;)V") //$NON-NLS-1$
                || desc.equals("()V") //$NON-NLS-1$
                || desc.equals("(Ljava/lang/String;)V")) { //$NON-NLS-1$
            Location location = context.getLocation(call);
            String message = "To get local formatting use getDateInstance(), getDateTimeInstance(), "
                    + "or getTimeInstance(), or use new SimpleDateFormat(String template, "
                    + "Locale locale) with for example Locale.US for ASCII dates.";
            context.report(DATE_FORMAT, method, call, location, message, null);
        }
        return;
    } else if (!owner.equals(STRING_OWNER)) {
        return;
    }

    if (name.equals(FORMAT_METHOD)) {
        // Only check the non-locale version of String.format
        if (!desc.equals("(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;")) { //$NON-NLS-1$
            return;
        }
        // Find the formatting string
        Analyzer analyzer = new Analyzer(new SourceInterpreter() {
            @Override
            public SourceValue newOperation(AbstractInsnNode insn) {
                if (insn.getOpcode() == Opcodes.LDC) {
                    Object cst = ((LdcInsnNode) insn).cst;
                    if (cst instanceof String) {
                        return new StringValue(1, (String) cst);
                    }
                }
                return super.newOperation(insn);
            }
        });
        try {
            Frame[] frames = analyzer.analyze(classNode.name, method);
            InsnList instructions = method.instructions;
            Frame frame = frames[instructions.indexOf(call)];
            if (frame.getStackSize() == 0) {
                return;
            }
            SourceValue stackValue = (SourceValue) frame.getStack(0);
            if (stackValue instanceof StringValue) {
                String format = ((StringValue) stackValue).getString();
                if (format != null && StringFormatDetector.isLocaleSpecific(format)) {
                    Location location = context.getLocation(call);
                    String message = "Implicitly using the default locale is a common source of bugs: "
                            + "Use String.format(Locale, ...) instead";
                    context.report(STRING_LOCALE, method, call, location, message, null);
                }
            }
        } catch (AnalyzerException e) {
            context.log(e, null);
        }
    } else {
        if (desc.equals("()Ljava/lang/String;")) { //$NON-NLS-1$
            Location location = context.getLocation(call);
            String message = String.format("Implicitly using the default locale is a common source of bugs: "
                    + "Use %1$s(Locale) instead", name);
            context.report(STRING_LOCALE, method, call, location, message, null);
        }
    }
}

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

License:Apache License

@SuppressWarnings("unchecked")
void moveNew() throws AnalyzerException {
    SourceInterpreter i = new SourceInterpreter();
    Analyzer a = new Analyzer(i);
    a.analyze(className, this);

    final HashMap<AbstractInsnNode, MethodInsnNode> movable = new HashMap<AbstractInsnNode, MethodInsnNode>();

    Frame[] frames = a.getFrames();
    for (int j = 0; j < methods.size(); j++) {
        MethodInsnNode mnode = methods.get(j);
        // require to move NEW instruction
        int n = instructions.indexOf(mnode);
        Frame f = frames[n];//  ww w .j av  a 2s.com
        Type[] args = Type.getArgumentTypes(mnode.desc);

        SourceValue v = (SourceValue) f.getStack(f.getStackSize() - args.length - 1);
        Set<AbstractInsnNode> insns = v.insns;
        for (final AbstractInsnNode ins : insns) {
            if (ins.getOpcode() == NEW) {
                movable.put(ins, mnode);
            } else {
                // other known patterns
                int n1 = instructions.indexOf(ins);
                if (ins.getOpcode() == DUP) { // <init> with params
                    AbstractInsnNode ins1 = instructions.get(n1 - 1);
                    if (ins1.getOpcode() == NEW) {
                        movable.put(ins1, mnode);
                    }
                } else if (ins.getOpcode() == SWAP) { // in exception handler
                    AbstractInsnNode ins1 = instructions.get(n1 - 1);
                    AbstractInsnNode ins2 = instructions.get(n1 - 2);
                    if (ins1.getOpcode() == DUP_X1 && ins2.getOpcode() == NEW) {
                        movable.put(ins2, mnode);
                    }
                }
            }
        }
    }

    int updateMaxStack = 0;
    for (final Map.Entry<AbstractInsnNode, MethodInsnNode> e : movable.entrySet()) {
        AbstractInsnNode node1 = e.getKey();
        int n1 = instructions.indexOf(node1);
        AbstractInsnNode node2 = instructions.get(n1 + 1);
        AbstractInsnNode node3 = instructions.get(n1 + 2);
        int producer = node2.getOpcode();

        instructions.remove(node1); // NEW
        boolean requireDup = false;
        if (producer == DUP) {
            instructions.remove(node2); // DUP
            requireDup = true;
        } else if (producer == DUP_X1) {
            instructions.remove(node2); // DUP_X1
            instructions.remove(node3); // SWAP
            requireDup = true;
        }

        MethodInsnNode mnode = (MethodInsnNode) e.getValue();
        AbstractInsnNode nm = mnode;

        int varOffset = stackRecorderVar + 1;
        Type[] args = Type.getArgumentTypes(mnode.desc);

        // optimizations for some common cases
        if (args.length == 0) {
            final InsnList doNew = new InsnList();
            doNew.add(node1); // NEW
            if (requireDup)
                doNew.add(new InsnNode(DUP));
            instructions.insertBefore(nm, doNew);
            nm = doNew.getLast();
            continue;
        }

        if (args.length == 1 && args[0].getSize() == 1) {
            final InsnList doNew = new InsnList();
            doNew.add(node1); // NEW
            if (requireDup) {
                doNew.add(new InsnNode(DUP));
                doNew.add(new InsnNode(DUP2_X1));
                doNew.add(new InsnNode(POP2));
                updateMaxStack = updateMaxStack < 2 ? 2 : updateMaxStack; // a two extra slots for temp values
            } else
                doNew.add(new InsnNode(SWAP));
            instructions.insertBefore(nm, doNew);
            nm = doNew.getLast();
            continue;
        }

        // TODO this one untested!
        if ((args.length == 1 && args[0].getSize() == 2)
                || (args.length == 2 && args[0].getSize() == 1 && args[1].getSize() == 1)) {
            final InsnList doNew = new InsnList();
            doNew.add(node1); // NEW
            if (requireDup) {
                doNew.add(new InsnNode(DUP));
                doNew.add(new InsnNode(DUP2_X2));
                doNew.add(new InsnNode(POP2));
                updateMaxStack = updateMaxStack < 2 ? 2 : updateMaxStack; // a two extra slots for temp values
            } else {
                doNew.add(new InsnNode(DUP_X2));
                doNew.add(new InsnNode(POP));
                updateMaxStack = updateMaxStack < 1 ? 1 : updateMaxStack; // an extra slot for temp value
            }
            instructions.insertBefore(nm, doNew);
            nm = doNew.getLast();
            continue;
        }

        final InsnList doNew = new InsnList();
        // generic code using temporary locals
        // save stack
        for (int j = args.length - 1; j >= 0; j--) {
            Type type = args[j];

            doNew.add(new VarInsnNode(type.getOpcode(ISTORE), varOffset));
            varOffset += type.getSize();
        }
        if (varOffset > maxLocals) {
            maxLocals = varOffset;
        }

        doNew.add(node1); // NEW

        if (requireDup)
            doNew.add(new InsnNode(DUP));

        // restore stack
        for (int j = 0; j < args.length; j++) {
            Type type = args[j];
            varOffset -= type.getSize();

            doNew.add(new VarInsnNode(type.getOpcode(ILOAD), varOffset));

            // clean up store to avoid memory leak?
            if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
                updateMaxStack = updateMaxStack < 1 ? 1 : updateMaxStack; // an extra slot for ACONST_NULL

                doNew.add(new InsnNode(ACONST_NULL));

                doNew.add(new VarInsnNode(type.getOpcode(ISTORE), varOffset));
            }
        }
        instructions.insertBefore(nm, doNew);
        nm = doNew.getLast();
    }

    maxStack += updateMaxStack;
}

From source file:org.apache.commons.javaflow.providers.asm3.ContinuableMethodNode.java

License:Apache License

void moveNew() throws AnalyzerException {
    final SourceInterpreter i = new SourceInterpreter();
    final Analyzer a = new Analyzer(i);
    a.analyze(className, this);

    final HashMap<AbstractInsnNode, MethodInsnNode> movable = new HashMap<AbstractInsnNode, MethodInsnNode>();

    final Frame[] frames = a.getFrames();
    for (int j = 0; j < methods.size(); j++) {
        final MethodInsnNode mnode = (MethodInsnNode) methods.get(j);
        // require to move NEW instruction
        int n = instructions.indexOf(mnode);
        Frame f = frames[n];//w  w  w .j a v  a  2s .  c o m
        Type[] args = Type.getArgumentTypes(mnode.desc);

        SourceValue v = (SourceValue) f.getStack(f.getStackSize() - args.length - 1);
        @SuppressWarnings("unchecked")
        Set<AbstractInsnNode> insns = v.insns;
        for (final AbstractInsnNode ins : insns) {
            if (ins.getOpcode() == NEW) {
                movable.put(ins, mnode);
            } else {
                // other known patterns
                int n1 = instructions.indexOf(ins);
                if (ins.getOpcode() == DUP) { // <init> with params
                    AbstractInsnNode ins1 = instructions.get(n1 - 1);
                    if (ins1.getOpcode() == NEW) {
                        movable.put(ins1, mnode);
                    }
                } else if (ins.getOpcode() == SWAP) { // in exception handler
                    AbstractInsnNode ins1 = instructions.get(n1 - 1);
                    AbstractInsnNode ins2 = instructions.get(n1 - 2);
                    if (ins1.getOpcode() == DUP_X1 && ins2.getOpcode() == NEW) {
                        movable.put(ins2, mnode);
                    }
                }
            }
        }
    }

    int updateMaxStack = 0;
    for (final Map.Entry<AbstractInsnNode, MethodInsnNode> e : movable.entrySet()) {
        AbstractInsnNode node1 = e.getKey();
        int n1 = instructions.indexOf(node1);
        AbstractInsnNode node2 = instructions.get(n1 + 1);
        AbstractInsnNode node3 = instructions.get(n1 + 2);
        int producer = node2.getOpcode();

        instructions.remove(node1); // NEW
        boolean requireDup = false;
        if (producer == DUP) {
            instructions.remove(node2); // DUP
            requireDup = true;
        } else if (producer == DUP_X1) {
            instructions.remove(node2); // DUP_X1
            instructions.remove(node3); // SWAP
            requireDup = true;
        }

        MethodInsnNode mnode = (MethodInsnNode) e.getValue();
        AbstractInsnNode nm = mnode;

        int varOffset = stackRecorderVar + 1;
        Type[] args = Type.getArgumentTypes(mnode.desc);

        // optimizations for some common cases
        if (args.length == 0) {
            final InsnList doNew = new InsnList();
            doNew.add(node1); // NEW
            if (requireDup)
                doNew.add(new InsnNode(DUP));
            instructions.insertBefore(nm, doNew);
            nm = doNew.getLast();
            continue;
        }

        if (args.length == 1 && args[0].getSize() == 1) {
            final InsnList doNew = new InsnList();
            doNew.add(node1); // NEW
            if (requireDup) {
                doNew.add(new InsnNode(DUP));
                doNew.add(new InsnNode(DUP2_X1));
                doNew.add(new InsnNode(POP2));
                updateMaxStack = updateMaxStack < 2 ? 2 : updateMaxStack; // a two extra slots for temp values
            } else
                doNew.add(new InsnNode(SWAP));
            instructions.insertBefore(nm, doNew);
            nm = doNew.getLast();
            continue;
        }

        // TODO this one untested!
        if ((args.length == 1 && args[0].getSize() == 2)
                || (args.length == 2 && args[0].getSize() == 1 && args[1].getSize() == 1)) {
            final InsnList doNew = new InsnList();
            doNew.add(node1); // NEW
            if (requireDup) {
                doNew.add(new InsnNode(DUP));
                doNew.add(new InsnNode(DUP2_X2));
                doNew.add(new InsnNode(POP2));
                updateMaxStack = updateMaxStack < 2 ? 2 : updateMaxStack; // a two extra slots for temp values
            } else {
                doNew.add(new InsnNode(DUP_X2));
                doNew.add(new InsnNode(POP));
                updateMaxStack = updateMaxStack < 1 ? 1 : updateMaxStack; // an extra slot for temp value
            }
            instructions.insertBefore(nm, doNew);
            nm = doNew.getLast();
            continue;
        }

        final InsnList doNew = new InsnList();
        // generic code using temporary locals
        // save stack
        for (int j = args.length - 1; j >= 0; j--) {
            Type type = args[j];

            doNew.add(new VarInsnNode(type.getOpcode(ISTORE), varOffset));
            varOffset += type.getSize();
        }
        if (varOffset > maxLocals) {
            maxLocals = varOffset;
        }

        doNew.add(node1); // NEW

        if (requireDup)
            doNew.add(new InsnNode(DUP));

        // restore stack
        for (int j = 0; j < args.length; j++) {
            Type type = args[j];
            varOffset -= type.getSize();

            doNew.add(new VarInsnNode(type.getOpcode(ILOAD), varOffset));

            // clean up store to avoid memory leak?
            if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
                updateMaxStack = updateMaxStack < 1 ? 1 : updateMaxStack; // an extra slot for ACONST_NULL

                doNew.add(new InsnNode(ACONST_NULL));

                doNew.add(new VarInsnNode(type.getOpcode(ISTORE), varOffset));
            }
        }
        instructions.insertBefore(nm, doNew);
        nm = doNew.getLast();
    }

    maxStack += updateMaxStack;
}

From source file:org.evosuite.graphs.cfg.BytecodeAnalyzer.java

License:Open Source License

/**
 * <p>
 * Constructor for BytecodeAnalyzer.
 * </p>
 */
public BytecodeAnalyzer() {
    super(new SourceInterpreter());
}

From source file:rubah.bytecode.transformers.RedirectFieldManipulation.java

License:Open Source License

@Override
public MethodVisitor visitMethod(int access, String name, final String desc, String signature,
        String[] exceptions) {/*  w  ww  . j  a v a  2 s  .co  m*/

    final MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions);

    if (this.namespace.isBootstrap(this.thisClass))
        return methodVisitor;

    if (this.thisClass.getFqn().startsWith("java.io") || this.thisClass.getFqn().startsWith("sun.reflect")
            || this.thisClass.getFqn().startsWith("sun.misc")
            || this.thisClass.getFqn().startsWith("java.security")
            || this.thisClass.getFqn().startsWith("java.util.concurrent.locks")
            || this.thisClass.getFqn().startsWith("java.util.concurrent.atomic")
            || (this.thisClass.getFqn().startsWith("java.lang")
                    && !this.thisClass.getFqn().equals(Class.class.getName())))
        return methodVisitor;

    if (this.objectsMap != null) {
        Method m = (Method) objectsMap.get(name);

        if (m == null)
            return methodVisitor;

        if (m.getName().startsWith(AddGettersAndSetters.GETTER_PREFFIX)
                || m.getName().startsWith(AddGettersAndSetters.SETTER_PREFFIX))
            return methodVisitor;
    }

    MethodVisitor ret = new MethodNode(ASM5, access, name, desc, signature, exceptions) {
        private Frame<SourceValue>[] sourcesFrames;
        private boolean isStatic = Modifier.isStatic(access);

        @Override
        public void visitEnd() {
            Analyzer<SourceValue> sourceAnalyzer = new Analyzer<SourceValue>(new SourceInterpreter());

            try {
                sourceAnalyzer.analyze(thisClass.getASMType().getInternalName(), this);
            } catch (AnalyzerException e) {
                System.out.println(namespace.isBootstrap(thisClass));
                System.out.println(e.getMessage());
                this.sourcesFrames = sourceAnalyzer.getFrames();
                this.printAnalyzerResult();
                throw new Error(e);
            }

            this.sourcesFrames = sourceAnalyzer.getFrames();

            ListIterator<AbstractInsnNode> iter = this.instructions.iterator();
            HashMap<AbstractInsnNode, InsnList> instructionsToAddBefore = new HashMap<AbstractInsnNode, InsnList>();
            HashMap<AbstractInsnNode, InsnList> instructionsToAddAfter = new HashMap<AbstractInsnNode, InsnList>();
            HashMap<AbstractInsnNode, AbstractInsnNode> instructionsToReplace = new HashMap<AbstractInsnNode, AbstractInsnNode>();

            while (iter.hasNext()) {
                AbstractInsnNode insnNode = iter.next();

                int opcode;
                switch ((opcode = insnNode.getOpcode())) {
                case INVOKESPECIAL: {
                    MethodInsnNode methodNode = (MethodInsnNode) insnNode;

                    int receiverDepth = Type.getArgumentTypes(methodNode.desc).length;

                    if (!this.needsRedirect(insnNode, receiverDepth))
                        continue;

                    for (AbstractInsnNode source : this.getSources(insnNode, receiverDepth)) {
                        if (source.getOpcode() == AALOAD)
                            // Already instrumented, skip it
                            continue;
                        instructionsToAddAfter.put(source, this.ensureNotProxy(methodNode.owner));
                    }

                    break;
                }
                case INVOKEVIRTUAL: {
                    MethodInsnNode methodNode = (MethodInsnNode) insnNode;
                    MethodInvocationInfo m = new MethodInvocationInfo(methodNode.name, methodNode.owner,
                            methodNode.desc);

                    if (ensureNotProxyMethods.contains(m)) {
                        int receiverDepth = 0;
                        for (Type arg : Type.getArgumentTypes(methodNode.desc))
                            receiverDepth += arg.getSize();

                        if (!this.needsRedirect(insnNode, receiverDepth))
                            continue;

                        for (AbstractInsnNode source : this.getSources(insnNode, receiverDepth))
                            instructionsToAddAfter.put(source, this.ensureNotProxy());
                    }

                    break;
                }
                case GETFIELD: {
                    if (!this.needsRedirect(insnNode, 0))
                        continue;
                    FieldInsnNode fieldNode = (FieldInsnNode) insnNode;
                    Type fieldOwner = findActualFieldOwner(Type.getObjectType(fieldNode.owner), fieldNode.name);
                    opcode = (opcode == GETFIELD ? INVOKEVIRTUAL : INVOKESTATIC);
                    String methodName = AddGettersAndSetters.generateGetterName(version, fieldOwner,
                            fieldNode.name);
                    String methodDesc = Type.getMethodDescriptor(Type.getType(fieldNode.desc));
                    instructionsToReplace.put(insnNode,
                            new MethodInsnNode(opcode, fieldNode.owner, methodName, methodDesc, false));
                    break;
                }
                case PUTFIELD: {
                    if (!this.needsRedirect(insnNode, 1))
                        continue;
                    FieldInsnNode fieldNode = (FieldInsnNode) insnNode;
                    Type fieldOwner = findActualFieldOwner(Type.getObjectType(fieldNode.owner), fieldNode.name);
                    opcode = (opcode == PUTFIELD ? INVOKEVIRTUAL : INVOKESTATIC);
                    String methodName = AddGettersAndSetters.generateSetterName(version, fieldOwner,
                            fieldNode.name);
                    String methodDesc = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(fieldNode.desc));
                    instructionsToReplace.put(insnNode,
                            new MethodInsnNode(opcode, fieldNode.owner, methodName, methodDesc, false));
                    break;
                }
                }
            }

            for (Entry<AbstractInsnNode, InsnList> entry : instructionsToAddBefore.entrySet())
                this.instructions.insertBefore(entry.getKey(), entry.getValue());

            for (Entry<AbstractInsnNode, InsnList> entry : instructionsToAddAfter.entrySet())
                this.instructions.insert(entry.getKey(), entry.getValue());

            // Destructive changes take place after constructive changes
            // so that the location nodes do not get destroyed too soon
            for (Entry<AbstractInsnNode, AbstractInsnNode> entry : instructionsToReplace.entrySet())
                this.instructions.set(entry.getKey(), entry.getValue());

            accept(methodVisitor);
        }

        private InsnList ensureNotProxy() {
            return this.ensureNotProxy(null);
        }

        private InsnList ensureNotProxy(String owner) {
            InsnList list = new InsnList();
            LabelNode label = new LabelNode();
            list.add(new InsnNode(DUP));
            list.add(new TypeInsnNode(INSTANCEOF, Type.getType(RubahProxy.class).getInternalName()));
            list.add(new JumpInsnNode(IFEQ, label));
            list.add(new TypeInsnNode(CHECKCAST, Type.getType(RubahProxy.class).getInternalName()));
            list.add(new MethodInsnNode(INVOKESTATIC, Type.getType(Rubah.class).getInternalName(),
                    "getConverted",
                    Type.getMethodDescriptor(Type.getType(Object.class), Type.getType(Object.class)), false));
            if (owner != null)
                list.add(new TypeInsnNode(CHECKCAST, owner));
            list.add(label);

            return list;
        }

        /**
         *
         * @param idx
         * @return True if local var, false if argument
         */
        private boolean isLocalVar(int idx) {
            int lastVar = (this.isStatic ? 0 : 1);
            for (Type arg : Type.getArgumentTypes(desc))
                lastVar += arg.getSize();

            return idx >= lastVar;

        }

        private Set<AbstractInsnNode> getSources(AbstractInsnNode insnNode, int depth) {
            return this.getSources(insnNode, depth, new HashSet<AbstractInsnNode>(),
                    new HashSet<AbstractInsnNode>());
        }

        private Set<AbstractInsnNode> getSources(AbstractInsnNode insnNode, int depth,
                HashSet<AbstractInsnNode> allSources, HashSet<AbstractInsnNode> alreadySeen) {
            int idx = this.instructions.indexOf(insnNode);
            Frame<SourceValue> sourcesFrame = this.sourcesFrames[idx];
            if (sourcesFrame == null) {
                // Bug in the analyzer or unreachable code
                return new HashSet<AbstractInsnNode>();
            }
            Set<AbstractInsnNode> sources = sourcesFrame
                    .getStack(sourcesFrame.getStackSize() - 1 - depth).insns;

            for (AbstractInsnNode source : sources) {
                if (alreadySeen.contains(source))
                    continue;

                alreadySeen.add(source);

                switch (source.getOpcode()) {
                case CHECKCAST:
                case DUP:
                    allSources.addAll(this.getSources(source, 0, allSources, alreadySeen));
                    break;
                case ALOAD:
                    // Is this an argument?
                    VarInsnNode n = (VarInsnNode) source;
                    if (isLocalVar(n.var)) {
                        // Only ASTORE can save to local variables
                        for (AbstractInsnNode astore : sourcesFrame.getLocal(n.var).insns) {
                            allSources.addAll(this.getSources(astore, 0, allSources, alreadySeen));
                        }
                        continue;
                    }
                    // Explicit fall-through
                default:
                    allSources.add(source);
                    break;
                }
            }

            return allSources;
        }

        private void printAnalyzerResult() {
            Textifier t = new Textifier();
            TraceMethodVisitor mv = new TraceMethodVisitor(t);
            PrintWriter pw = new PrintWriter(System.out);

            pw.println(this.name + this.desc);
            for (int j = 0; j < this.instructions.size(); ++j) {
                this.instructions.get(j).accept(mv);

                StringBuffer s = new StringBuffer();
                Frame<SourceValue> f = this.sourcesFrames[j];
                if (f == null) {
                    s.append('?');
                } else {
                    for (int k = 0; k < f.getLocals(); ++k) {
                        for (AbstractInsnNode insn : f.getLocal(k).insns) {
                            s.append(this.instructions.indexOf(insn)).append(' ');
                        }
                    }
                    s.append(" : ");
                    for (int k = 0; k < f.getStackSize(); ++k) {
                        for (AbstractInsnNode insn : f.getStack(k).insns) {
                            s.append(this.instructions.indexOf(insn)).append(' ');
                        }
                    }
                }
                while (s.length() < this.maxStack + this.maxLocals + 1) {
                    s.append(' ');
                }
                pw.print(Integer.toString(j + 100000).substring(1));
                pw.print(" " + s + " : " + t.text.get(t.text.size() - 1));
            }
            for (int j = 0; j < this.tryCatchBlocks.size(); ++j) {
                this.tryCatchBlocks.get(j).accept(mv);
                pw.print(" " + t.text.get(t.text.size() - 1));
            }
            pw.println();
            pw.flush();
        }

        private boolean needsRedirect(AbstractInsnNode insnNode, int stackDepth) {
            boolean ret = false;

            for (AbstractInsnNode insn : this.getSources(insnNode, stackDepth)) {
                switch (insn.getOpcode()) {
                case NEW:
                    continue;
                case ALOAD:
                    if (((VarInsnNode) insn).var != 0 || this.isStatic)
                        ret = true;
                    break;
                default:
                    ret = true;
                    break;
                }
            }

            return ret;
        }

    };

    return ret;
}