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

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

Introduction

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

Prototype

InsnList

Source Link

Usage

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

License:Apache License

@SuppressWarnings("unchecked")
MethodNode transform(String coroutineName, boolean generateDebugCode) {
    MethodNode transformedMethod = new MethodNode();
    transformedMethod.access = ACC_PUBLIC | ACC_FINAL | (method.access & ACC_STATIC);
    transformedMethod.name = coroutineName;
    transformedMethod.desc = COROUTINE_METHOD_DESCRIPTOR;
    transformedMethod.exceptions = method.exceptions;
    final InsnList newCode = transformedMethod.instructions;
    Analyzer analyzer = new Analyzer(new BasicInterpreter() {

        @Override/*from   w ww. ja  v a 2  s  .co m*/
        public Value binaryOperation(AbstractInsnNode insn, Value value1, Value value2)
                throws AnalyzerException {
            if (insn.getOpcode() == AALOAD) {
                return new BasicValue(((BasicValue) value1).getType().getElementType());
            }
            return super.binaryOperation(insn, value1, value2);
        };

        @Override
        public Value merge(Value v, Value w) {
            if (v == NULL_VALUE) {
                BasicValue w1 = (BasicValue) w;
                if (w1.isReference()) {
                    return w1;
                }
            }
            if (w == NULL_VALUE) {
                BasicValue v1 = (BasicValue) v;
                if (v1.isReference())
                    return v1;
            }
            if (!v.equals(w)) {
                BasicValue v1 = (BasicValue) v;
                BasicValue w1 = (BasicValue) w;
                if (v1.isReference() & w1.isReference()) {
                    Class<?> c1;
                    Class<?> c2;
                    try {
                        c1 = MethodTransformer.getClass(v1);
                        c2 = MethodTransformer.getClass(w1);
                    } catch (ClassNotFoundException e) {
                        throw new CoroutineGenerationException(
                                "It was needed to load a class during transformation process but loading unexpectedly failed",
                                e);
                    }
                    if (c1.isAssignableFrom(c2)) {
                        return v;
                    }
                    if (c2.isAssignableFrom(c1)) {
                        return w;
                    }
                }
            } else {
                return v;
            }
            return BasicValue.UNINITIALIZED_VALUE;
        }

        @Override
        public Value newValue(Type type) {
            if (type != null) {
                int typeSort = type.getSort();
                switch (typeSort) {
                case Type.VOID:
                    return NULL_VALUE;
                case Type.BOOLEAN:
                case Type.CHAR:
                case Type.BYTE:
                case Type.SHORT:
                case Type.INT:
                    return BasicValue.INT_VALUE;
                case Type.FLOAT:
                    return BasicValue.FLOAT_VALUE;
                case Type.LONG:
                    return BasicValue.LONG_VALUE;
                case Type.DOUBLE:
                    return BasicValue.DOUBLE_VALUE;
                case Type.ARRAY:
                case Type.OBJECT:
                    if (type.getInternalName().equals("null")) {
                        return NULL_VALUE;
                    }
                    return new BasicValue(type);
                default:
                    throw new Error("Internal error");
                }
            }
            return BasicValue.UNINITIALIZED_VALUE;
        }
    });
    Frame[] frames;
    try {
        frames = analyzer.analyze(methodOwner, method);
    } catch (AnalyzerException e) {
        throw new CoroutineGenerationException(e);
    }
    InsnList code = method.instructions;
    final List<Integer> yields = new ArrayList<Integer>(8);
    /*
     * Copy instructions patching variable indexes and frames, remember
     * yield indexes
     */
    int ic = 0;
    Iterator<AbstractInsnNode> i = code.iterator();
    while (i.hasNext()) {
        AbstractInsnNode insn = i.next();
        switch (insn.getType()) {
        case AbstractInsnNode.FRAME:
            FrameNode frame = (FrameNode) insn.clone(labelsMap);
            // update values
            if (frame.type == F_FULL) {
                if (isStatic) {
                    frame.local.addAll(0, argsStackMapList);
                } else {
                    frame.local.addAll(1, argsStackMapList);
                }
            }
            newCode.add(frame);
            break;
        case AbstractInsnNode.IINC_INSN:
            IincInsnNode iinc = (IincInsnNode) insn.clone(labelsMap);
            iinc.var += variableIndexOffset;
            newCode.add(iinc);
            break;
        case AbstractInsnNode.INSN:
            switch (insn.getOpcode()) {
            case DRETURN:
            case FRETURN:
            case IRETURN:
            case LRETURN:
            case ARETURN:
            case RETURN:
                newCode.add(new InsnNode(POP));
                newCode.add(throwex("java/util/NoSuchElementException"));
                break;
            default:
                newCode.add(insn.clone(labelsMap));
            }
            break;
        case AbstractInsnNode.JUMP_INSN:
            if (insn.getOpcode() == JSR) {
                throw new CoroutineGenerationException("<jsr> not allowed");
            }
            JumpInsnNode jump = (JumpInsnNode) insn;
            LabelNode target = jump.label;
            if (!labelsMap.containsKey(target)) {
                labelsMap.put(target, new LabelNode());
            }
            newCode.add(jump.clone(labelsMap));
            break;
        case AbstractInsnNode.LABEL:
            if (!labelsMap.containsKey(insn)) {
                labelsMap.put((LabelNode) insn, new LabelNode());
            }
            newCode.add(insn.clone(labelsMap));
            break;
        case AbstractInsnNode.METHOD_INSN:
            if (insn.getOpcode() == INVOKESTATIC) {
                MethodInsnNode method = (MethodInsnNode) insn;
                if (method.owner.equals(COROUTINES_NAME)) {
                    String methodName = method.name;
                    if (methodName.equals("_")) {
                        /*
                         * a call to artificial CoIterator, since it is
                         * not needed after instrumentation we replace
                         * it with null. This null will be popped by
                         * corresponding ARETURN. Stack is not changed
                         */
                        newCode.add(new InsnNode(ACONST_NULL));
                        break;
                    }
                    if (methodName.equals("yield")) {
                        /*
                         * a call to yield - core of coroutine
                         * processing
                         */
                        yields.add(ic);
                    }
                }
            }
            newCode.add(insn.clone(labelsMap));
            break;
        case AbstractInsnNode.VAR_INSN:
            if (insn.getOpcode() == RET) {
                throw new CoroutineGenerationException("<ret> not allowed");
            }
            VarInsnNode var = (VarInsnNode) insn.clone(labelsMap);
            if (var.var != 0 || isStatic) {
                var.var += variableIndexOffset;
            }
            newCode.add(var);
            break;
        default:
            newCode.add(insn.clone(labelsMap));
            break;
        }
        ic += 1;
    }
    /*
     * patch yields in transformed code
     */
    final List<LabelNode> gotos = new ArrayList<LabelNode>(9);
    final Set<TryCatchBlockNode> patchedTryCatchBlocks = new HashSet<TryCatchBlockNode>();
    int yieldIndex = 0;
    i = newCode.iterator();
    while (i.hasNext()) {
        AbstractInsnNode insn = i.next();
        /*
         * track locals
         */
        int insnType = insn.getType();
        if (insnType == AbstractInsnNode.VAR_INSN) {
            int opcode = insn.getOpcode();
            if (opcode == ASTORE || opcode == DSTORE || opcode == LSTORE || opcode == ISTORE
                    || opcode == FSTORE) {
                int varIndex = ((VarInsnNode) insn).var - variableIndexOffset;
                finals[varIndex] = false;
            }
            continue;
        }
        /*
         * track line numbers
         */
        if (insnType == AbstractInsnNode.LINE) {
            lineNumber = ((LineNumberNode) insn).line;
            continue;
        }
        if (insnType != AbstractInsnNode.METHOD_INSN) {
            continue;
        }
        MethodInsnNode method = (MethodInsnNode) insn;
        if (!method.owner.equals(COROUTINES_NAME) || !method.name.equals("yield")) {
            continue;
        }
        InsnList yieldCode = new InsnList();
        int index = yields.get(yieldIndex);
        Frame f = frames[index];
        /*
         * a) operand on the top of stack is passed to the caller, we will
         * save it in 'in' parameter OR there is nothing to be passed to the
         * caller in case of yield() overload
         */
        boolean yieldWithArgument = Type.getArgumentTypes(method.desc).length != 0;
        boolean nonemptyStack;
        Type[] stackContents = null;
        int stackTop = 0;
        if (yieldWithArgument) {
            yieldCode.add(input(getStackTop(f)));
            nonemptyStack = f.getStackSize() > 1;
            stackTop = 1;
        } else {
            nonemptyStack = f.getStackSize() > 0;
        }
        /*
         * b) save remaining stack
         */
        if (nonemptyStack) {
            stackContents = getStackContents(f);
            // sanitize stack
            for (Type t : stackContents) {
                if (t == null) {
                    throw new CoroutineGenerationException(
                            "It is not possible to yield with uninitialized memory on the stack. Probably you use construct such as: new A(..,yield,..). Please move this yield call out of constructor");
                }
            }
            yieldCode.add(savestack(frame, stackContents, stackTop));
        }
        /*
         * c) save locals and state
         */
        Type[] locals = getLocals(f);
        yieldCode.add(saveLocals(locals));
        yieldCode.add(new VarInsnNode(ALOAD, frame));
        yieldCode.add(makeInt(++yieldIndex));
        yieldCode.add(new MethodInsnNode(INVOKEVIRTUAL, FRAME_NAME, "setState", "(I)V"));
        /*
         * d) jump to exit - in debug mode save line number
         */
        if (generateDebugCode) {
            yieldCode.add(new VarInsnNode(ALOAD, frame));
            yieldCode.add(makeInt(lineNumber));
            yieldCode.add(new MethodInsnNode(INVOKEVIRTUAL, FRAME_NAME, "setLineOfCode", "(I)V"));
        }
        yieldCode.add(new JumpInsnNode(GOTO, yieldLabel));
        /*
         * e) fix jump from switch statement
         */
        LabelNode jump = new LabelNode();
        gotos.add(jump);
        yieldCode.add(jump);
        yieldCode.add(emitCleanFrame());
        /*
         * f) check if exit condition occurs, load locals, restore stack and
         * stack map
         */
        yieldCode.add(new VarInsnNode(ALOAD, frame));
        yieldCode.add(new MethodInsnNode(INVOKEVIRTUAL, FRAME_NAME, "isCoroutineClosed", "()Z"));
        LabelNode continueHere = new LabelNode();
        yieldCode.add(new JumpInsnNode(IFEQ, continueHere));
        yieldCode.add(throwex(COROUTINE_EXIT_EXCEPTION));
        yieldCode.add(continueHere);
        yieldCode.add(new FrameNode(F_SAME, 0, EMPTY_LOCALS, 0, EMPTY_STACK));
        /*
         * find previous frame node, load locals then emit new frame node
         * and load rest
         */
        FrameNode prevFrame = findPreviousFrame(code.get(index));
        Type[] prevLocals;
        if (prevFrame != null) {
            Frame oldFrame = frames[code.indexOf(prevFrame)];
            prevLocals = getLocals(oldFrame);
        } else {
            prevLocals = getLocals(frames[0]);
        }
        yieldCode.add(restoreLocals(prevLocals));
        FrameNode frameNode = mergeFrames(getFrameTypes(prevLocals), null);
        if (frameNode.type != F_SAME) {
            // bug fix - when no locals are restored and the stack is empty
            // two frames are collapsed
            yieldCode.add(frameNode);
        }
        if (nonemptyStack) {
            yieldCode.add(loadstack(frame, stackContents, stackTop));
        }
        // restore temp locals in scope
        yieldCode.add(restoreLocals(diff(locals, prevLocals)));
        /*
         * push "sent" value
         */
        yieldCode.add(new VarInsnNode(ALOAD, out));
        newCode.insertBefore(method, yieldCode);
        /*
         * patch try catch blocks
         */
        List<TryCatchBlockNode> tryCatchBlocks = analyzer.getHandlers(index);
        if (tryCatchBlocks != null) {
            for (TryCatchBlockNode tryCatchBlock : tryCatchBlocks) {
                if (!patchedTryCatchBlocks.contains(tryCatchBlock)) {
                    LabelNode handler = tryCatchBlock.handler;
                    InsnList handlerPatch = new InsnList();
                    String exceptionType = tryCatchBlock.type == null ? "java/lang/Throwable"
                            : tryCatchBlock.type;
                    FrameNode catchFrame = emitCatchFrame(exceptionType);
                    handlerPatch.add(catchFrame);
                    Type[] ls = getLocals(frames[code.indexOf(handler)]);
                    handlerPatch.add(restoreLocals(ls));
                    handlerPatch.add(
                            mergeFrames(getFrameTypes(ls), new Type[] { Type.getObjectType(exceptionType) }));
                    patchedTryCatchBlocks.add(tryCatchBlock);
                    AbstractInsnNode newHandler = labelsMap.get(handler);
                    // remove "real" frame since it is not needed now
                    newCode.remove(findNextFrame(newHandler));
                    newCode.insert(newHandler, handlerPatch);
                }
            }
        }
        newCode.remove(method);
    }
    /*
     * copy local variables (wath out for indices change) and try catch
     * blocks to new method (clone)
     */
    List<TryCatchBlockNode> tryCatchBlocks = method.tryCatchBlocks;
    if (!tryCatchBlocks.isEmpty()) {
        transformedMethod.tryCatchBlocks = new ArrayList<TryCatchBlockNode>(tryCatchBlocks.size());
        for (TryCatchBlockNode tryCatchBlock : tryCatchBlocks) {
            transformedMethod.tryCatchBlocks.add(
                    new TryCatchBlockNode(labelsMap.get(tryCatchBlock.start), labelsMap.get(tryCatchBlock.end),
                            labelsMap.get(tryCatchBlock.handler), tryCatchBlock.type));
        }
    }
    if (method.localVariables != null) {
        List<LocalVariableNode> localVariables = method.localVariables;
        List<LocalVariableNode> newLocalVariables = new ArrayList<LocalVariableNode>(localVariables.size());
        for (LocalVariableNode localVariable : localVariables) {
            int newIndex = localVariable.index;
            if (newIndex != 0 || isStatic) {
                newIndex += variableIndexOffset;
            }
            newLocalVariables
                    .add(new LocalVariableNode(localVariable.name, localVariable.desc, localVariable.signature,
                            labelsMap.get(localVariable.start), labelsMap.get(localVariable.end), newIndex));
        }
        transformedMethod.localVariables = newLocalVariables;
    }
    newCode.insert(codeBefore(gotos));
    newCode.add(codeAfter());
    return transformedMethod;
}

From source file:portablejim.veinminer.asm.ItemInWorldManagerTransformer.java

License:Open Source License

private InsnList buildBlockIdFunctionCall(String obfuscatedClassName, String worldType, int blockVarIndex) {
    InsnList blockIdFunctionCall = new InsnList();
    blockIdFunctionCall.add(new TypeInsnNode(Opcodes.NEW, blockIdClassName));
    blockIdFunctionCall.add(new InsnNode(Opcodes.DUP));
    blockIdFunctionCall.add(new VarInsnNode(Opcodes.ALOAD, 0));
    blockIdFunctionCall.add(new FieldInsnNode(Opcodes.GETFIELD, obfuscatedClassName.replace(".", "/"),
            getCorrectName("theWorld"), typemap.get(getCorrectName("theWorld"))));
    blockIdFunctionCall.add(new VarInsnNode(Opcodes.ILOAD, 1));
    blockIdFunctionCall.add(new VarInsnNode(Opcodes.ILOAD, 2));
    blockIdFunctionCall.add(new VarInsnNode(Opcodes.ILOAD, 3));
    blockIdFunctionCall.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, blockIdClassName, "<init>",
            String.format("(%sIII)V", worldType)));

    blockIdFunctionCall.add(new VarInsnNode(Opcodes.ASTORE, blockVarIndex));

    return blockIdFunctionCall;
}

From source file:portablejim.veinminer.asm.ItemInWorldManagerTransformer.java

License:Open Source License

private int insertCallAfterTryHarvestBlockFunction(MethodNode curMethod, String obfuscatedClassName,
        int startIndex) throws IndexOutOfBoundsException {
    LocalVariablesSorter varSorter = new LocalVariablesSorter(curMethod.access, curMethod.desc, curMethod);

    String worldType = typemap.get(getCorrectName("theWorld"));
    String playerType = typemap.get(getCorrectName("thisPlayerMP"));

    while (!isMethodWithName(curMethod.instructions.get(startIndex), "tryHarvestBlock")) {
        ++startIndex;// ww  w .  j av  a2 s.com
    }

    do {
        --startIndex;
    } while (curMethod.instructions.get(startIndex).getType() == AbstractInsnNode.VAR_INSN);

    int blockVarIndex = varSorter.newLocal(Type.getType(BlockID.class));
    curMethod.instructions.insert(curMethod.instructions.get(startIndex),
            buildBlockIdFunctionCall(obfuscatedClassName, worldType, blockVarIndex));
    ++startIndex;

    while (!isMethodWithName(curMethod.instructions.get(startIndex), "tryHarvestBlock")) {
        ++startIndex;
    }

    // Add variable to store result
    int newVarIndex = varSorter.newLocal(Type.BOOLEAN_TYPE);
    VarInsnNode newVar = new VarInsnNode(Opcodes.ISTORE, newVarIndex);
    curMethod.instructions.insert(curMethod.instructions.get(startIndex), newVar);
    ++startIndex;

    // Add in function call to call function
    InsnList veinMinerFunctionCall = new InsnList();
    veinMinerFunctionCall
            .add(new FieldInsnNode(Opcodes.GETSTATIC, targetClassName, "instance", targetClassType));
    veinMinerFunctionCall.add(new VarInsnNode(Opcodes.ALOAD, 0));
    veinMinerFunctionCall.add(new FieldInsnNode(Opcodes.GETFIELD, obfuscatedClassName.replace(".", "/"),
            getCorrectName("theWorld"), typemap.get(getCorrectName("theWorld"))));
    veinMinerFunctionCall.add(new VarInsnNode(Opcodes.ALOAD, 0));
    veinMinerFunctionCall.add(new FieldInsnNode(Opcodes.GETFIELD, obfuscatedClassName.replace(".", "/"),
            getCorrectName("thisPlayerMP"), typemap.get(getCorrectName("thisPlayerMP"))));
    veinMinerFunctionCall.add(new VarInsnNode(Opcodes.ILOAD, 1));
    veinMinerFunctionCall.add(new VarInsnNode(Opcodes.ILOAD, 2));
    veinMinerFunctionCall.add(new VarInsnNode(Opcodes.ILOAD, 3));
    veinMinerFunctionCall.add(new VarInsnNode(Opcodes.ILOAD, newVarIndex));
    veinMinerFunctionCall.add(new VarInsnNode(Opcodes.ALOAD, blockVarIndex));

    String blockIdClassType = String.format("L%s;", blockIdClassName);
    veinMinerFunctionCall.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, targetClassName, targetMethodName,
            String.format(targetMethodType, worldType, playerType, blockIdClassType)));
    curMethod.instructions.insert(curMethod.instructions.get(startIndex), veinMinerFunctionCall);
    ++startIndex;

    // Get rid of un-needed POP.
    while (curMethod.instructions.get(startIndex).getOpcode() != Opcodes.POP) {
        ++startIndex;
    }
    curMethod.instructions.remove(curMethod.instructions.get(startIndex));

    return startIndex;
}

From source file:pxb.android.dex2jar.optimize.D.java

License:Apache License

/**
 * @param method// ww  w.  j a  v a 2 s.  co  m
 */
@SuppressWarnings("rawtypes")
private void rebuild(MethodNode method) {
    InsnList insnList = new InsnList();
    method.instructions = insnList;
    List<LabelNode> visited = new ArrayList<LabelNode>();
    Stack<Block> toWriteBlock = new Stack<Block>();
    toWriteBlock.push(first);
    doRebuild(insnList, toWriteBlock, visited);
    method.tryCatchBlocks = new ArrayList();
    for (Iterator<?> it = method.tryCatchBlocks.iterator(); it.hasNext();) {
        TryCatchBlockNode tcn = (TryCatchBlockNode) it.next();
        toWriteBlock.push(map.get(tcn.handler));
        doRebuild(insnList, toWriteBlock, visited);
    }
}

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) {/*from   ww  w.  ja  v  a2s.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;
}

From source file:uk.co.mysterymayhem.tessellatorfix.Transformer.java

private static byte[] patchTessellatorClass(byte[] bytes) {
    String targetMethodName;//from   w  ww .ja va 2 s. c om

    if (Plugin.runtimeDeobfEnabled) {
        targetMethodName = "func_147564_a";
    } else {
        targetMethodName = "getVertexState";
    }

    ClassNode classNode = new ClassNode();
    ClassReader classReader = new ClassReader(bytes);
    classReader.accept(classNode, 0);

    Iterator<MethodNode> methods = classNode.methods.iterator();
    while (methods.hasNext()) {
        MethodNode m = methods.next();
        if ((m.name.equals(targetMethodName)
                && m.desc.equals("(FFF)Lnet/minecraft/client/shader/TesselatorVertexState;"))) {
            FMLLog.info("Inside target Tessellator method");

            InsnList toInject = new InsnList();

            // Insertion of "if (this.rawBufferIndex < 1) return"
            LabelNode labelNode = new LabelNode();

            toInject.add(new VarInsnNode(Opcodes.ALOAD, 0));
            String fieldName;
            if (Plugin.runtimeDeobfEnabled) {
                fieldName = "field_147569_p";
            } else {
                fieldName = "rawBufferIndex";
            }
            toInject.add(new FieldInsnNode(Opcodes.GETFIELD, "net/minecraft/client/renderer/Tessellator",
                    fieldName, "I"));
            toInject.add(new InsnNode(Opcodes.ICONST_1));
            toInject.add(new JumpInsnNode(Opcodes.IF_ICMPGE, labelNode));
            toInject.add(new InsnNode(Opcodes.ACONST_NULL));
            toInject.add(new InsnNode(Opcodes.ARETURN));
            toInject.add(labelNode);

            // Insert after
            m.instructions.insert(toInject);

            ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
            classNode.accept(writer);
            FMLLog.info("Exiting target Tessellator method");
            return writer.toByteArray();
        }
    }

    FMLLog.warning("Could not find Tessellator method out of:");
    StringBuilder builder = new StringBuilder();
    for (MethodNode methodNode : classNode.methods) {
        builder.append(methodNode.name).append(":").append(methodNode.desc).append("\n");
    }
    FMLLog.info(builder.toString());

    return bytes;
}

From source file:vazkii.quark.base.asm.ClassTransformer.java

License:Creative Commons License

private static byte[] transformModelBiped(byte[] basicClass) {
    log("Transforming ModelBiped");
    MethodSignature sig = new MethodSignature("setRotationAngles", "func_78087_a", "a",
            "(FFFFFFLnet/minecraft/entity/Entity;)V");

    return transform(basicClass, Pair.of(sig, combine((AbstractInsnNode node) -> { // Filter
        return node.getOpcode() == Opcodes.RETURN;
    }, (MethodNode method, AbstractInsnNode node) -> { // Action
        InsnList newInstructions = new InsnList();

        newInstructions.add(new VarInsnNode(Opcodes.ALOAD, 7));
        newInstructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, ASM_HOOKS, "updateEmotes",
                "(Lnet/minecraft/entity/Entity;)V"));

        method.instructions.insertBefore(node, newInstructions);
        return true;
    })));//www .  j ava 2  s . c  o  m
}

From source file:vazkii.quark.base.asm.ClassTransformer.java

License:Creative Commons License

private static byte[] transformRenderItem(byte[] basicClass) {
    log("Transforming RenderItem");
    MethodSignature sig1 = new MethodSignature("renderItem", "func_180454_a", "a",
            "(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/renderer/block/model/IBakedModel;)V");
    MethodSignature sig2 = new MethodSignature("renderEffect", "func_191966_a", "a",
            "(Lnet/minecraft/client/renderer/block/model/IBakedModel;)V");

    byte[] transClass = basicClass;

    transClass = transform(transClass, Pair.of(sig1, combine((AbstractInsnNode node) -> { // Filter
        return true;
    }, (MethodNode method, AbstractInsnNode node) -> { // Action
        InsnList newInstructions = new InsnList();

        newInstructions.add(new VarInsnNode(Opcodes.ALOAD, 1));
        newInstructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, ASM_HOOKS, "setColorRuneTargetStack",
                "(Lnet/minecraft/item/ItemStack;)V"));

        method.instructions.insertBefore(node, newInstructions);
        return true;
    })));//from  w  ww.j a  va 2s  .  c om

    transClass = transform(transClass, Pair.of(sig2, combine((AbstractInsnNode node) -> { // Filter
        return node.getOpcode() == Opcodes.LDC && ((LdcInsnNode) node).cst.equals(-8372020);
    }, (MethodNode method, AbstractInsnNode node) -> { // Action
        InsnList newInstructions = new InsnList();

        newInstructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, ASM_HOOKS, "getRuneColor", "(I)I"));

        method.instructions.insert(node, newInstructions);
        return false;
    })));

    return transClass;
}

From source file:vazkii.quark.base.asm.ClassTransformer.java

License:Creative Commons License

private static byte[] transformLayerArmorBase(byte[] basicClass) {
    log("Transforming LayerArmorBase");
    MethodSignature sig1 = new MethodSignature("renderArmorLayer", "func_188361_a", "a",
            "(Lnet/minecraft/entity/EntityLivingBase;FFFFFFFLnet/minecraft/inventory/EntityEquipmentSlot;)V");
    MethodSignature sig2 = new MethodSignature("renderEnchantedGlint", "func_188364_a", "a",
            "(Lnet/minecraft/client/renderer/entity/RenderLivingBase;Lnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/client/model/ModelBase;FFFFFFF)V");

    byte[] transClass = basicClass;

    transClass = transform(transClass, Pair.of(sig1, combine((AbstractInsnNode node) -> { // Filter
        return node.getOpcode() == Opcodes.ASTORE;
    }, (MethodNode method, AbstractInsnNode node) -> { // Action
        InsnList newInstructions = new InsnList();

        newInstructions.add(new VarInsnNode(Opcodes.ALOAD, 10));
        newInstructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, ASM_HOOKS, "setColorRuneTargetStack",
                "(Lnet/minecraft/item/ItemStack;)V"));

        method.instructions.insert(node, newInstructions);
        return true;
    })));//  w ww  .j a  va 2s  . c o  m

    if (!hasOptifine(sig2.toString())) {
        invokestaticCount = 0;
        transClass = transform(transClass, Pair.of(sig2, combine((AbstractInsnNode node) -> { // Filter
            return node.getOpcode() == Opcodes.INVOKESTATIC && ((MethodInsnNode) node).desc.equals("(FFFF)V");
        }, (MethodNode method, AbstractInsnNode node) -> { // Action
            invokestaticCount++;

            InsnList newInstructions = new InsnList();

            newInstructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, ASM_HOOKS, "applyRuneColor", "()V"));

            method.instructions.insert(node, newInstructions);
            return invokestaticCount == 2;
        })));
    }

    return transClass;
}

From source file:vazkii.quark.base.asm.ClassTransformer.java

License:Creative Commons License

private static byte[] transformEntityBoat(byte[] basicClass) {
    log("Transforming EntityBoat");
    MethodSignature sig1 = new MethodSignature("attackEntityFrom", "func_70097_a", "a",
            "(Lnet/minecraft/util/DamageSource;F)Z");
    MethodSignature sig2 = new MethodSignature("onUpdate", "func_70071_h_", "B_", "()V");

    byte[] transClass = transform(basicClass, Pair.of(sig1, combine((AbstractInsnNode node) -> { // Filter
        return node.getOpcode() == Opcodes.POP;
    }, (MethodNode method, AbstractInsnNode node) -> { // Action
        InsnList newInstructions = new InsnList();

        newInstructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
        newInstructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, ASM_HOOKS, "dropBoatBanner",
                "(Lnet/minecraft/entity/item/EntityBoat;)V"));

        method.instructions.insertBefore(node, newInstructions);
        return true;
    })));//  www .j  av  a2s  . c  om

    transClass = transform(transClass, Pair.of(sig2, combine((AbstractInsnNode node) -> { // Filter
        return true;
    }, (MethodNode method, AbstractInsnNode node) -> { // Action
        InsnList newInstructions = new InsnList();

        newInstructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
        newInstructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, ASM_HOOKS, "onBoatUpdate",
                "(Lnet/minecraft/entity/item/EntityBoat;)V"));

        method.instructions.insertBefore(node, newInstructions);
        return true;
    })));

    return transClass;
}