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:fr.insalyon.telecom.jooflux.InvokeMethodTransformer.java

License:Mozilla Public License

private InsnList generateInvokeDynamicStatic(String name, String owner, String desc) {
    InsnList insnList = new InsnList();
    Handle methodHandle = new Handle(Opcodes.H_INVOKESTATIC, BOOTSTRAP_CLASS, "dynvokeStatic",
            BOOTSTRAP_SIGNATURE);/*from  ww  w . j  av  a 2s.c o  m*/
    insnList.add(new InvokeDynamicInsnNode(owner + "." + name, desc, methodHandle, ""));
    return insnList;
}

From source file:fr.insalyon.telecom.jooflux.InvokeMethodTransformer.java

License:Mozilla Public License

private InsnList generateInvokeDynamicVirtualInterfaceSpecial(String name, String owner, String desc,
        String bootstrapMethod) {
    InsnList insnList = new InsnList();
    Handle methodHandle = new Handle(Opcodes.H_INVOKESTATIC, BOOTSTRAP_CLASS, bootstrapMethod,
            BOOTSTRAP_SIGNATURE);//from  w  w w . ja v a 2  s  .com
    List<Type> argsList = new ArrayList<Type>(Arrays.asList(new Type[] { Type.getObjectType(owner) }));
    argsList.addAll(Arrays.asList(Type.getArgumentTypes(desc)));
    String descReceiver = Type.getMethodDescriptor(Type.getReturnType(desc),
            argsList.toArray(new Type[argsList.size()]));
    insnList.add(new InvokeDynamicInsnNode(owner + "." + name, descReceiver, methodHandle, ""));
    return insnList;
}

From source file:hellfirepvp.astralsorcery.core.patch.helper.PatchModifyAttributes.java

License:Open Source License

@Override
public void patch(ClassNode cn) {
    MethodNode mn = getMethod(cn, "getAttributeModifiers", "func_111283_C",
            "(Lnet/minecraft/inventory/EntityEquipmentSlot;)Lcom/google/common/collect/Multimap;");

    InsnList list = new InsnList();
    list.add(new VarInsnNode(Opcodes.ALOAD, 0));
    list.add(new VarInsnNode(Opcodes.ALOAD, 1));
    list.add(new VarInsnNode(Opcodes.ALOAD, 2));
    list.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
            "hellfirepvp/astralsorcery/common/util/SwordSharpenHelper", "applySharpenModifier",
            "(Lnet/minecraft/item/ItemStack;Lnet/minecraft/inventory/EntityEquipmentSlot;Lcom/google/common/collect/Multimap;)V",
            false));//from   w ww  .java 2s.  c  o  m
    mn.instructions.insert(mn.instructions.getLast().getPrevious().getPrevious(), list);
}

From source file:io.awacs.plugin.stacktrace.ClassTransformer.java

License:Apache License

/**
 * ??//from   w  w  w . j  a  va  2s .  co m
 * 1?StackFrames.push(0)???
 * 2???this???
 * 3?StackFrames.push(1)???
 * 4??
 */
private void transformPlainMethod(MethodNode mn, ClassNode cn) {
    InsnList before = new InsnList();
    before.add(new LdcInsnNode(cn.name.replaceAll("/", ".")));
    before.add(new LdcInsnNode(mn.name));
    before.add(new LdcInsnNode(0));
    before.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "io/awacs/plugin/stacktrace/StackFrames", "push",
            "(Ljava/lang/String;Ljava/lang/String;I)V", false));
    InsnList end = new InsnList();
    end.add(new LdcInsnNode(cn.name.replaceAll("/", ".")));
    end.add(new LdcInsnNode(mn.name));
    end.add(new LdcInsnNode(1));
    end.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "io/awacs/plugin/stacktrace/StackFrames", "push",
            "(Ljava/lang/String;Ljava/lang/String;I)V", false));

    List<AbstractInsnNode> insts = new LinkedList<>();
    for (int i = 0; i < mn.instructions.size(); i++) {
        int opcode = mn.instructions.get(i).getOpcode();
        if (opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) {
            insts.add(mn.instructions.get(i));
        }
    }
    if (!insts.isEmpty()) {
        mn.instructions.insert(before);
        for (AbstractInsnNode node : insts) {
            mn.instructions.insertBefore(node, end);
        }
    }
    mn.maxStack = mn.maxStack + 5;
}

From source file:jaspex.speculation.newspec.FlowFrame.java

License:Open Source License

/** Mtodo que implementa a deteco e correco do problema dos mltiplos fluxos de controlo.
  * Retorna true se alterou o mtodo, e false cc.
  **///from  w ww.  java  2 s .c  o m
private static boolean computeControlFlowGraph(String owner, String superOwner, MethodNode mn,
        LabelMap labelMap, boolean ranBefore) {
    //Log.debug("Visiting: {}.{}", owner, mn.name);

    FlowAnalyzer analyzer = new FlowAnalyzer(new FutureVerifier(owner, superOwner));

    try {
        analyzer.analyze(owner, mn);
        //if (ranBefore) printCode(mn, Arrays.asList(analyzer.getFrames()), null, null);
        FrameInjector.injectFrames(mn, analyzer.getFrames());
        return false;
    } catch (AnalyzerException e) {
        /*e.printStackTrace();*/ }

    // Se chegmos aqui, o Analyzer detectou problemas, e vamos ter que fazer correces no mtodo

    // Detectar o primeiro LabelNode onde aparece um MergedUninitializedValue
    LabelNode problemLabelNode = null;
    FlowFrame problemFrame = null;
    int problemPosition = -1;
    boolean problemInStack = false;

    List<FlowFrame> frames = listGenericCast(Arrays.asList(analyzer.getFrames()));

    outer: for (int i = 0; i < frames.size(); i++) {
        FlowFrame f = frames.get(i);
        if (f == null)
            continue;

        int localsStartPos = 0;
        int stackStartPos = 0;
        // Identificar se alguma entrada nos locals/stack da frame deve ser escolhida como
        // problemtica
        // Isto  um loop porque algumas das entradas encontradas podem ser backwards edges,
        // e no estamos interessadas nessas
        while (true) {
            for (int j = localsStartPos; j < f.getLocals(); j++) {
                if (f.getLocal(j) instanceof MergedUninitializedValue) {
                    problemPosition = j;
                    problemInStack = false;
                    localsStartPos = j + 1;
                }
            }
            for (int j = stackStartPos; j < f.getStackSize() && (problemPosition < 0); j++) {
                if (f.getStack(j) instanceof MergedUninitializedValue) {
                    problemPosition = j;
                    problemInStack = true;
                    stackStartPos = j + 1;
                }
            }

            // J processamos completamente a frame e no encontramos nada, ou s
            // encontramos backwards edges, passar  prxima
            if (problemPosition < 0)
                continue outer;

            if ((f.predecessors().size() > 0)
                    && (getPredecessorWithFuture(f, problemInStack, problemPosition) == null)) {
                // Isto pode acontecer quando instruco que encontrmos  o target de
                // um "backwards edge". Nesse caso, no  esta a instruco que queremos
                // processar, mas queremos uma que tenha como predecessor um Future,
                // no um MergedUninitializedValue
                /*Log.debug("Found result of backwards edge at " +
                   (problemInStack ? "stack" : "locals") + " position " + i +
                   ", continuing");*/
                problemPosition = -1;
                continue;
            }

            if (problemInStack && !(mn.instructions.get(i) instanceof LabelNode)
                    && (mn.instructions.get(i - 1) instanceof VarInsnNode)) {
                // Caso especial: Uma instruco de load colocou um
                // MergedUninitializedValue na stack, e como no estava l na instruco
                // anterior o getPredecessorWithFuture no detecta este caso, mas no
                // estamos interessados nesta frame, estamos interessadas na que originou
                // o MUV que estava nos locals
                problemPosition = -1;
                continue;
            }

            // Frame e posio escolhidas so consideradas problemticas
            break;
        }

        AbstractInsnNode insn = mn.instructions.get(i);
        // First node with problematic frame should be a LabelNode
        if (!(insn instanceof LabelNode))
            throw new AssertionError();
        problemLabelNode = (LabelNode) insn;
        problemFrame = f;

        printCode(mn, frames, problemFrame.predecessors(), f);
        Log.trace("First problematic frame is " + f + "\n\t\tPredecessors: " + f.predecessors());
        break;
    }

    if (problemLabelNode == null) {
        Log.warn("Errors found during analysis, bytecode possibly invalid, bailing out");
        throw new AssertionError(); // Causar revert de todas as alteraes no mtodo
        //return false;
    }

    // Duplicar cdigo problemtico, para depois o alterar com o DelayGetFutureMethodVisitor
    InsnList il = new InsnList();

    // Label que marca o inicio do cdigo a copiar
    LabelNode copiedBlockStartLabel = new LabelNode();

    // Criar mapa para passar ao AbstractInsnNode (ver javadoc ASM)
    //LabelMap labelMap = new LabelMap();
    labelMap.put(problemLabelNode, copiedBlockStartLabel);

    // Adiciona copiedBlockStartLabel  nova il
    il.add(problemLabelNode.clone(labelMap));

    // Usado para manter a ltima (inclusiv) instruco do bloco copiado
    AbstractInsnNode lastInsn = null;

    // Simular execuo das frames durante a cpia
    // O objectivo disto  resolver problemas como o NewSpecExample17, onde cdigo copiado deve
    // fazer branch para:
    // -- Cdigo copiado numa iterao anterior ("cdigo novo") se a frame continuar a conter um
    //    futuro, porque o cdigo novo  o que  suposto lidar com a existncia do futuro
    // -- Cdigo existente do mtodo ("cdigo antigo") se a frame j no contm um futuro, o que
    //    significa que a concretizao se faz durante o bloco actual
    FlowFrame currentFrame = analyzer.newFrame(problemFrame);
    if (problemInStack) {
        currentFrame.setStack(problemPosition,
                ((MergedUninitializedValue) currentFrame.getStack(problemPosition)).getFuture());
    } else {
        currentFrame.setLocal(problemPosition,
                ((MergedUninitializedValue) currentFrame.getLocal(problemPosition)).getFuture());
    }

    for (AbstractInsnNode n = problemLabelNode.getNext(); n != null; n = n.getNext()) {
        if (n instanceof LabelNode) {
            LabelNode labelNode = (LabelNode) n;
            if (getNextIgnoreLabelLineNop(labelNode) instanceof FrameNode) {
                // Se label se refere a uma frame, o bloco terminou
                // FIXME: Tem que se saltar sempre para labels novas, se existirem?
                il.add(new JumpInsnNode(GOTO, labelMap.get(labelNode)));
                break;
            } else {
                // Caso contrrio, substituimos por uma nova label, para permitir
                // que os LineNumberNodes continuem a existir no novo cdigo.
                labelMap.put(labelNode, new LabelNode());
            }
        }

        // Detectar, no caso de um salto, qual a label que se deve utilizar (ver comentrios acima)
        // FIXME: Ser que no caso do switch/case algumas das labels tm que apontar para o cdigo
        //     novo, e outras para o antigo?
        if (n instanceof JumpInsnNode || n instanceof LookupSwitchInsnNode
                || n instanceof TableSwitchInsnNode) {
            // Se ProblemPosition ainda tem um Futuro, saltar para cdigo novo
            if ((problemInStack && isFuture(currentFrame.getStack(problemPosition)))
                    || (!problemInStack && isFuture(currentFrame.getLocal(problemPosition)))) {
                il.add(n.clone(labelMap));
            } else { // Deixou de ter um Futuro, saltar para cdigo antigo
                il.add(n.clone(new LabelMap()));
            }
        } else {
            il.add(n.clone(labelMap));
        }

        lastInsn = n;

        // Se chegamos ao fim do bloco (GOTO, ATHROW ou *RETURN) tambm paramos a cpia
        if (n.getOpcode() == GOTO || n.getOpcode() == ATHROW || returnOpcodes.contains(n.getOpcode()))
            break;

        // Actualizar currentFrame -- simular execuo da instruco actual
        try {
            currentFrame = analyzer.computeNextFrame(currentFrame, n);
        } catch (AnalyzerException e) {
            // Ocorreu um erro, continuamos com a ltima frame vlida
            //Log.debug("WARNING: AnalyzerException during computeNextFrame");
        }
        //Log.debug("CurrentFrame: " + currentFrame + " (isFuture? " +
        //   (isFuture(currentFrame.getLocal(problemPosition)) ? "yes" : "no") + ")");
    }

    LabelNode copiedBlockEndLabel = new LabelNode();
    il.add(copiedBlockEndLabel);

    mn.instructions.add(il);
    il = mn.instructions;

    // Detectar qual dos seus predecessores originou o Futuro que ficou no MergedUninitializedValue

    if (problemFrame.predecessors().isEmpty()) { // ProblemFrame  o inicio de um exception handler
        // Popular predecessors da problemFrame com control flows de exceptions
        analyzer.populateExceptionPredecessors(problemFrame);

        //printCode(mn, frames, problemFrame.predecessors());

        // Adicionar um novo tryCatchBlock com:
        // - Range [Primeira instruco com Future,
        //      ltima instruco que tem future *E* faz parte da lista de predecessors]
        //   Razo: Lista de predecessors --> handler ainda est activo
        //          Tem future --> future pode ser substituido mais tarde
        //             (por exemplo { i = doA(); j = doB(); i = 0 })
        // - Target: Novo bloco copiado -- copiedBlockStartLabel

        AbstractInsnNode startBlockInsn = null;
        AbstractInsnNode endBlockInsn = null;

        for (FlowFrame f : problemFrame.predecessors()) {
            BasicValue v = problemInStack ? f.getStack(problemPosition) : f.getLocal(problemPosition);
            if (isFuture(v)) {
                AbstractInsnNode insn = insnForFrame(il, frames, f);

                if (startBlockInsn == null) {
                    startBlockInsn = insn;
                }

                if (endBlockInsn != null) {
                    // Detectar se o bloco actual terminou
                    if (getTryCatchBlock(mn, startBlockInsn, insn) == null)
                        break;
                }

                endBlockInsn = insn;
            } else if (startBlockInsn != null) {
                break;
            }
        }

        // Provavelmente o problema do NewSpecExample20, ver comentrios no ficheiro
        if (startBlockInsn == null || endBlockInsn == null) {
            throw new AssertionError("KNOWN BUG: Probably picked the wrong code to copy");
        }

        //Log.debug("PredecessorInsn [Exception]: First " + startBlockInsn + " Last " + endBlockInsn);

        LabelNode startBlockLabel = labelBefore(il, startBlockInsn);
        LabelNode endBlockLabel = labelAfter(il, endBlockInsn);

        TryCatchBlockNode originalBlock = getTryCatchBlock(mn, startBlockInsn, endBlockInsn);
        assert (originalBlock != null);

        mn.tryCatchBlocks.add(0, new SafeTryCatchBlockNode(startBlockLabel, endBlockLabel,
                copiedBlockStartLabel, originalBlock.type));

        if (originalBlock.start.equals(startBlockLabel) && originalBlock.end.equals(endBlockLabel)) {
            // Novo bloco substitui completamente o antigo
            mn.tryCatchBlocks.remove(originalBlock);
        } else {
            // Como o novo try/catch substitui o antigo, para que o verificador da JVM e do ASM
            // lidem melhor com a coisa (embora segundo os specs no seria necessrio), vamos
            // alterar o inicio e/ou o fim do bloco original para deixar de conter as instruces
            // que esto cobertas pelo novo bloco
            if (originalBlock.start.equals(startBlockLabel)) {
                originalBlock.start = endBlockLabel;
            } else if (originalBlock.end.equals(endBlockLabel)) {
                originalBlock.end = startBlockLabel;
            } else {
                Log.debug("FIXME: Original (old) try catch block should be adjusted");
            }
        }
    } else { // Existem predecessores, problemFrame  um bloco de cdigo normal
        FlowFrame predecessorWithFuture = getPredecessorWithFuture(problemFrame, problemInStack,
                problemPosition);

        if (predecessorWithFuture == null)
            throw new AssertionError();

        AbstractInsnNode predecessorInsn = insnForFrame(il, frames, predecessorWithFuture);
        //Log.debug("PredecessorInsn: " + predecessorInsn);

        // Detectar como vai ser feito o salto para a nova seco do cdigo

        // Casos possveis:
        // - Predecessor  instruco imediatamente antes da labelnode (e no  um salto)
        //   -> No alteramos, adicionamos goto
        //   -> Se for um salto, podemos ou no ter que alterar, dependendo de ser ou no
        //      um salto para a labelNode que marca o incio da seco problemtica
        // - Predecessor  jump / table|lookup switch
        //   -> Temos que alterar
        // Fazendo clone com o labelmap obtemos um n que tem o salto para a nova label trocado
        // pelo salto para a antiga.
        if (directlyPrecedes(predecessorInsn, problemLabelNode)
                && !hasLabelAsTarget(predecessorInsn, problemLabelNode)) {
            // No temos que alterar n, saltamos directamente para novo bloco
            il.insert(predecessorInsn, new JumpInsnNode(GOTO, copiedBlockStartLabel));
        } else {
            if (!((predecessorInsn instanceof LookupSwitchInsnNode)
                    || (predecessorInsn instanceof TableSwitchInsnNode)
                    || (predecessorInsn instanceof JumpInsnNode))) {
                throw new AssertionError(); // Instruco tem que ser salto
            }
            // N tem que ser alterado
            AbstractInsnNode replacementNode = predecessorInsn.clone(labelMap);
            il.set(predecessorInsn, replacementNode);
            if (lastInsn == predecessorInsn)
                lastInsn = replacementNode;
        }
    }

    // Corrigir exception handlers do mtodo

    // Como blocos de cdigo so copiados, temos tambm que copiar os exception handlers,
    // para que os try/catch continuem a funcionar correctamente
    List<AbstractInsnNode> copiedCodeRange = getRange(problemLabelNode, lastInsn);
    List<SafeTryCatchBlockNode> newTryCatchBlocks = new ArrayList<SafeTryCatchBlockNode>();
    for (TryCatchBlockNode tryCatchBlock : mn.tryCatchBlocks) {
        List<AbstractInsnNode> blockRange = getRange(tryCatchBlock.start, tryCatchBlock.end);
        blockRange.retainAll(copiedCodeRange);
        if (blockRange.isEmpty())
            continue;
        // Corner case: Supostamente um try/catch block cobre [start, end[, enquanto
        // que o getRange devolve [start, end]
        if (blockRange.size() == 1 && problemLabelNode == tryCatchBlock.end)
            continue;

        //Log.debug("Exception handler table needs fixup");

        // Determinar a nova label de inicio
        LabelNode newStart;
        if (copiedCodeRange.contains(tryCatchBlock.start)) {
            // loco excepo comea j dentro do copiedCodeRange
            newStart = labelMap.getMapping(tryCatchBlock.start);
        } else {
            // Bloco excepo comea fora do copiedCodeRange
            newStart = copiedBlockStartLabel;
        }

        // Determinar a nova label de fim
        LabelNode newEnd;
        if (copiedCodeRange.contains(tryCatchBlock.end)) {
            // Bloco excepo comea dentro do copiedCodeRange
            newEnd = labelMap.getMapping(tryCatchBlock.end);
        } else {
            // Bloco excepo acaba fora do copiedCodeRange
            newEnd = copiedBlockEndLabel;
        }

        newTryCatchBlocks
                .add(new SafeTryCatchBlockNode(newStart, newEnd, tryCatchBlock.handler, tryCatchBlock.type));
    }
    mn.tryCatchBlocks.addAll(newTryCatchBlocks);

    return true;
}

From source file:jvstm.atomic.ProcessParNestAnnotations.java

License:Open Source License

protected static void processClassFile(File classFile) {
    alreadyProcessed = new ArrayList<String>();
    callablesCreated = new HashMap<String, String>();
    InputStream is = null;/* w  w w  .  ja  v a2 s  .  c o m*/

    try {
        // get an input stream to read the bytecode of the class
        is = new FileInputStream(classFile);
        ClassNode cn = new ClassNode(ASM4);
        ClassReader cr = new ClassReader(is);
        cr.accept(cn, 0);

        List<MethodNode> parNestedMethods = new ArrayList<MethodNode>();
        MethodNode combinerMethod = null;
        MethodNode execMethod = null;

        List<MethodNode> staticMethodsToAdd = new ArrayList<MethodNode>();

        boolean parallelSpawn = extendsParallelSpawn(cn);
        boolean unsafeSpawn = extendsUnsafeSpawn(cn);
        if (parallelSpawn || unsafeSpawn) {
            Iterator<MethodNode> methodIter = cn.methods.iterator();
            while (methodIter.hasNext()) {
                MethodNode mn = methodIter.next();
                if (mn.name.equals("exec") && execMethod == null) {
                    execMethod = mn;
                    continue;
                }
                if (mn.invisibleAnnotations == null) {
                    continue;
                }
                for (AnnotationNode an : mn.invisibleAnnotations) {
                    if (an.desc.equals(PAR_NEST.getDescriptor())) {
                        // Ensure the method can be called from outside
                        mn.access = (mn.access & ~ACC_PRIVATE) | ACC_PUBLIC;
                        parNestedMethods.add(mn);
                        String uniqueMethodName = createUniqueMethodName(mn.name);
                        String callableClass;
                        if (parallelSpawn) {
                            callableClass = cn.name + "$nested$work$unit$" + uniqueMethodName;
                        } else {
                            callableClass = cn.name + "$unsafe$work$unit$" + uniqueMethodName;
                        }
                        callablesCreated.put(mn.name, callableClass);
                        boolean readOnlyCallable = (an.values == null) ? false : (Boolean) an.values.get(1);
                        generateCallable(classFile, cn.name, callableClass, mn, readOnlyCallable, unsafeSpawn);
                        staticMethodsToAdd.add(generateStaticCallableCreation(cn, cn.name, callableClass, mn));
                        break;
                    } else if (an.desc.equals(COMBINER.getDescriptor())) {
                        if (combinerMethod != null) {
                            throw new RuntimeException("Class: " + cn.name + " contains two @Combiner methods: "
                                    + combinerMethod.name + " and " + mn.name);
                        }
                        combinerMethod = mn;
                    }
                }
            }

            // TODO Verify the @Combiner method
            // The return should be of the same type of the parameterization
            // of the ParallelSpawn

            for (MethodNode methodToAdd : staticMethodsToAdd) {
                cn.methods.add(methodToAdd);
            }

            if (alreadyProcessed.size() == 0) {
                throw new RuntimeException(
                        "Class: " + cn.name + " must have at least one method annotated with @ParNested");
            }
            if (combinerMethod == null) {
                throw new RuntimeException(
                        "Class: " + cn.name + " must have one method annotated with @Combiner");
            }

            List<Integer> localVariablesIdx = new ArrayList<Integer>();
            int numberLocalVariables = 0;
            int listIndex = execMethod.maxLocals;
            execMethod.maxLocals++;

            InsnList preamble = new InsnList();
            preamble.add(new TypeInsnNode(NEW, ARRAY_LIST.getInternalName()));
            preamble.add(new InsnNode(DUP));
            preamble.add(new MethodInsnNode(INVOKESPECIAL, ARRAY_LIST.getInternalName(), "<init>", "()V"));
            preamble.add(new VarInsnNode(ASTORE, listIndex));

            Iterator<AbstractInsnNode> execInstIter = execMethod.instructions.iterator();
            while (execInstIter.hasNext()) {
                AbstractInsnNode instr = execInstIter.next();
                // Look out for calls to methods
                if (instr.getOpcode() == INVOKEVIRTUAL || instr.getOpcode() == INVOKESPECIAL) {
                    MethodInsnNode methodInstr = (MethodInsnNode) instr;
                    // Is method being called annotated with @ParNested
                    for (MethodNode parNestedMethod : parNestedMethods) {
                        if (parNestedMethod.name.equals(methodInstr.name)) {
                            numberLocalVariables++;
                        }
                    }
                }
            }

            for (int i = 0; i < numberLocalVariables; i++) {
                localVariablesIdx.add(i, execMethod.maxLocals);
                execMethod.maxLocals++;
            }

            int callablesManipulated = 0;
            execInstIter = execMethod.instructions.iterator();
            while (execInstIter.hasNext()) {
                AbstractInsnNode instr = execInstIter.next();
                // Look out for calls to methods
                if (instr.getOpcode() != INVOKEVIRTUAL && instr.getOpcode() != INVOKESPECIAL) {
                    continue;
                }

                MethodInsnNode methodInstr = (MethodInsnNode) instr;
                // Is method being called annotated with @ParNested
                boolean isParNestedMethod = false;
                for (MethodNode parNestedMethod : parNestedMethods) {
                    if (parNestedMethod.name.equals(methodInstr.name)) {
                        isParNestedMethod = true;
                        break;
                    }
                }
                if (!isParNestedMethod) {
                    continue;
                }

                // Let's change this call
                // If it was a call to: @ParNested public int add(int i1,
                // int i2)
                // add(foo, bar) -> add$static$callable$creator(this, foo,
                // bar)
                // the 'this' will be already in the right place in the
                // stack
                // because the method being called now is static whereas
                // previously
                // it was not
                methodInstr.setOpcode(INVOKESTATIC);
                methodInstr.name = methodInstr.name + "$static$callable$creator";
                for (MethodNode staticCreated : staticMethodsToAdd) {
                    if (staticCreated.name.equals(methodInstr.name)) {
                        methodInstr.desc = staticCreated.desc;
                        break;
                    }
                }

                InsnList midterm = new InsnList();

                // Store the callable instantiated in local variable
                midterm.add(new VarInsnNode(ASTORE, localVariablesIdx.get(callablesManipulated)));
                // Load the list
                midterm.add(new VarInsnNode(ALOAD, listIndex));
                // Load the callable
                midterm.add(new VarInsnNode(ALOAD, localVariablesIdx.get(callablesManipulated)));
                // Add it to the list
                midterm.add(new MethodInsnNode(INVOKEVIRTUAL, ARRAY_LIST.getInternalName(), "add",
                        "(Ljava/lang/Object;)Z"));
                // Pop the boolean that results from the add(Object)
                // May reuse a POP if the previous call had a return
                if (methodInstr.getNext().getOpcode() != POP) {
                    midterm.add(new InsnNode(POP));
                }

                // Add this set of instructions after the call to the
                // constrution of the callable
                execMethod.instructions.insert(methodInstr, midterm);
                callablesManipulated++;

            }

            // Insert the preamble in the start
            execMethod.instructions.insert(preamble);

            InsnList finish = new InsnList();
            // Push 'this' for the call to the combiner method
            finish.add(new VarInsnNode(ALOAD, 0));
            // Call the static method current() of jvstm.Transaction
            finish.add(new MethodInsnNode(INVOKESTATIC, TRANSACTION.getInternalName(), "current",
                    "()Ljvstm/Transaction;"));
            // Load the callables list
            finish.add(new VarInsnNode(ALOAD, listIndex));
            // Call the manage parnested method
            finish.add(new MethodInsnNode(INVOKEVIRTUAL, TRANSACTION.getInternalName(),
                    "manageNestedParallelTxs", "(Ljava/util/List;)Ljava/util/List;"));
            // Call the combiner method
            finish.add(new MethodInsnNode(INVOKEVIRTUAL, cn.name, combinerMethod.name, combinerMethod.desc));
            // Return what the combiner returns
            finish.add(new InsnNode(ARETURN));

            // Remove the "return null" that's supposed to be at the end of
            // the exec method
            execInstIter = execMethod.instructions.iterator();
            while (execInstIter.hasNext()) {
                AbstractInsnNode curNode = execInstIter.next();
                if (!execInstIter.hasNext()) {
                    // Insert the finish in the end
                    execMethod.instructions.insert(curNode.getPrevious().getPrevious(), finish);
                    execMethod.instructions.remove(curNode.getPrevious());
                    execMethod.instructions.remove(curNode);
                    break;
                }
            }

        }

        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        cn.accept(cw);
        writeClassFile(classFile, cw.toByteArray());
    } catch (IOException e) {
        throw new Error("Error processing class file", e);
    } finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
            }
        }
    }
}

From source file:jvstm.atomic.ProcessParNestAnnotations.java

License:Open Source License

private static MethodNode generateStaticCallableCreation(ClassNode classNode, String className,
        String callableClass, MethodNode mn) {
    MethodNode staticMethod = new MethodNode(V1_6, mn.access | ACC_STATIC, mn.name + "$static$callable$creator",
            "(L" + className + ";" + mn.desc.substring(1, mn.desc.indexOf(')') + 1) + "L" + callableClass + ";",
            mn.signature, new String[0]);
    InsnList content = new InsnList();
    content.add(new TypeInsnNode(NEW, callableClass));
    content.add(new InsnNode(DUP));

    int pos = 0;/*from w ww.j  av  a2s  .  c o  m*/
    // Push the instance of the class being modified (first argument of this
    // synthetized method)
    content.add(new VarInsnNode(ALOAD, pos++));
    // Push arguments of original method on the stack for callable creation
    for (Type t : Type.getArgumentTypes(mn.desc)) {
        content.add(new VarInsnNode(t.getOpcode(ILOAD), pos));
        pos += t.getSize();
    }

    // Instantiate the callable
    content.add(new MethodInsnNode(INVOKESPECIAL, callableClass, "<init>", getCallableCtorDesc(className, mn)));

    // Return it from the static method
    content.add(new InsnNode(ARETURN));

    staticMethod.instructions.add(content);
    return staticMethod;
}

From source file:me.themallard.bitmmo.impl.plugin.applethook.AppletHook.java

License:Open Source License

private void addGraphicsHook(MethodNode mn, boolean update) {
    String method = update ? "update" : "paint";
    String desc = mn.desc;//  w  ww . j  a  v  a  2  s  . co  m

    InsnList insns = new InsnList();

    insns.add(new VarInsnNode(ALOAD, 1));
    insns.add(new MethodInsnNode(INVOKESTATIC, "me/themallard/bitmmo/impl/plugin/applethook/AppletHookManager",
            method, desc, false));

    mn.instructions.insertBefore(mn.instructions.get(mn.instructions.size() - 1), insns);
}

From source file:me.themallard.bitmmo.impl.plugin.chathook.ChatHook.java

License:Open Source License

private void hookSendMessage(ClassNode cn) {
    Pattern p = new PatternBuilder().add(new InstructionElement(INVOKESTATIC), new AnyElement(),
            new LdcElement(new LdcInsnNode("Chat")), new InstructionElement(INVOKEVIRTUAL),
            new InstructionElement(POP)).build();

    for (MethodNode mn : cn.methods) {
        if (!p.contains(mn.instructions))
            continue;

        int offset = p.getOffset(mn.instructions) - 9;

        // steal/*from ww w  . jav a 2 s.c o m*/
        JumpInsnNode jin = (JumpInsnNode) mn.instructions.get(offset - 1);

        InsnList inject = new InsnList();
        inject.add(new VarInsnNode(ALOAD, 2));
        inject.add(new MethodInsnNode(INVOKESTATIC, "me/themallard/bitmmo/impl/plugin/chathook/ChatHookManager",
                "onChatMessage", "(Ljava/lang/String;)Z", false));
        inject.add(new JumpInsnNode(IFNE, jin.label));
        //         inject.add(new InsnNode(POP));

        mn.instructions.insertBefore(mn.instructions.get(offset), inject);
    }
}

From source file:me.themallard.bitmmo.impl.plugin.chathook.ChatHook.java

License:Open Source License

private void hookRecieveMessage(ClassNode cn) {
    Pattern p = new PatternBuilder().add(new InstructionElement(DUP), new InstructionElement(INVOKESPECIAL),
            new LdcElement(new LdcInsnNode("\n"))).build();

    for (MethodNode mn : cn.methods) {
        if (!p.contains(mn.instructions))
            continue;

        int offset = p.getOffset(mn.instructions);

        MethodInsnNode getMsgInsn = (MethodInsnNode) mn.instructions.get(offset + 5);

        InsnList inject = new InsnList();
        inject.add(new VarInsnNode(ALOAD, 1));
        inject.add(new MethodInsnNode(INVOKEVIRTUAL, getMsgInsn.owner, getMsgInsn.name, "()Ljava/lang/String;",
                false));/*from ww w .  j a  v  a  2  s  .  c  o  m*/
        inject.add(new MethodInsnNode(INVOKESTATIC, "me/themallard/bitmmo/impl/plugin/chathook/ChatHookManager",
                "onReceiveMessage", "(Ljava/lang/String;)V", false));

        mn.instructions.insertBefore(mn.instructions.get(offset), inject);
    }
}