Example usage for org.objectweb.asm.tree MethodNode MethodNode

List of usage examples for org.objectweb.asm.tree MethodNode MethodNode

Introduction

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

Prototype

public MethodNode(final int api, final int access, final String name, final String descriptor,
        final String signature, final String[] exceptions) 

Source Link

Document

Constructs a new MethodNode .

Usage

From source file:org.spongepowered.mod.asm.util.ASMHelper.java

License:MIT License

/**
 * Generate a forwarding method of the form
 * "T name() { return Class.forward(this); }".
 *
 * @param clazz Class to generate new method on
 * @param name Name of method to generate
 * @param forwardname Name of method to call
 * @param rettype Return type of method/*from  w w  w .  j  a  v a2 s.  co  m*/
 * @param thistype Type to treat 'this' as for overload searching purposes
 */
public static void generateForwardingToStaticMethod(ClassNode clazz, String name, String forwardname,
        Type rettype, Type fowardtype, Type thistype) {
    MethodNode method = new MethodNode(Opcodes.ASM5, Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, name,
            "()" + rettype.getDescriptor(), null, null);

    populateForwardingToStaticMethod(method, forwardname, rettype, thistype, fowardtype);

    clazz.methods.add(method);
}

From source file:org.spongepowered.mod.asm.util.ASMHelper.java

License:MIT License

/**
 * Generate a forwarding method of the form
 * "T name(S object) { return object.forward(); }".
 *
 * @param clazz Class to generate new method on
 * @param name Name of method to generate
 * @param forwardname Name of method to call
 * @param rettype Return type of method//from w ww .j  av a2  s .c o  m
 * @param argtype Type of object to call method on
 */
public static void generateForwardingMethod(ClassNode clazz, String name, String forwardname, Type rettype,
        Type argtype) {
    MethodNode method = new MethodNode(Opcodes.ASM5, Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, name,
            "()" + rettype.getDescriptor(), null, null);

    populateForwardingMethod(method, forwardname, rettype, argtype, Type.getObjectType(clazz.name));

    clazz.methods.add(method);
}

From source file:org.teavm.parsing.Parser.java

License:Apache License

public static MethodHolder parseMethod(MethodNode node, String className, String fileName) {
    MethodNode nodeWithoutJsr = new MethodNode(Opcodes.ASM5, node.access, node.name, node.desc, node.signature,
            node.exceptions.toArray(new String[0]));
    JSRInlinerAdapter adapter = new JSRInlinerAdapter(nodeWithoutJsr, node.access, node.name, node.desc,
            node.signature, node.exceptions.toArray(new String[0]));
    node.accept(adapter);//w ww  . ja va 2s.c  o m
    node = nodeWithoutJsr;
    ValueType[] signature = MethodDescriptor.parseSignature(node.desc);
    MethodHolder method = new MethodHolder(node.name, signature);
    parseModifiers(node.access, method);
    ProgramParser programParser = new ProgramParser();
    programParser.setFileName(fileName);
    Program program = programParser.parse(node, className);
    new UnreachableBasicBlockEliminator().optimize(program);
    PhiUpdater phiUpdater = new PhiUpdater();
    phiUpdater.updatePhis(program, applySignature(program, method.getParameterTypes()));
    method.setProgram(program);
    parseAnnotations(method.getAnnotations(), node.visibleAnnotations, node.invisibleAnnotations);
    while (program.variableCount() <= method.parameterCount()) {
        program.createVariable();
    }
    if (node.annotationDefault != null) {
        method.setAnnotationDefault(parseAnnotationValue(node.annotationDefault));
    }
    for (int i = 0; i < method.parameterCount(); ++i) {
        parseAnnotations(method.parameterAnnotation(i),
                node.visibleParameterAnnotations != null ? node.visibleParameterAnnotations[i] : null,
                node.invisibleParameterAnnotations != null ? node.invisibleParameterAnnotations[i] : null);
    }
    return method;
}

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 w  w .  ja v a 2  s . c o  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;
}