List of usage examples for org.objectweb.asm.tree InsnList set
public void set(final AbstractInsnNode oldInsnNode, final AbstractInsnNode newInsnNode)
From source file:com.github.fge.grappa.transform.process.GroupClassGenerator.java
License:Apache License
protected static void convertXLoads(InstructionGroup group) { String owner = group.getGroupClassType().getInternalName(); InsnList insnList; for (InstructionGraphNode node : group.getNodes()) { if (!node.isXLoad()) continue; VarInsnNode insn = (VarInsnNode) node.getInstruction(); FieldNode field = group.getFields().get(insn.var); FieldInsnNode fieldNode = new FieldInsnNode(GETFIELD, owner, field.name, field.desc); insnList = group.getInstructions(); // insert the correct GETFIELD after the xLoad insnList.insert(insn, fieldNode); // change the load to ALOAD 0 insnList.set(insn, new VarInsnNode(ALOAD, 0)); }/*from w ww . j a va 2 s. co m*/ }
From source file:de.tuberlin.uebb.jbop.optimizer.var.LocalVarInliner.java
License:Open Source License
private AbstractInsnNode hanldeLoad(final InsnList original, final AbstractInsnNode currentNode, final Map<Integer, Object> knownValues) { final int index = NodeHelper.getVarIndex(currentNode); if (knownValues.containsKey(index) && currentNode.getNext() != null && currentNode.getPrevious() != null) { final Object value = knownValues.get(index); final AbstractInsnNode replacement = NodeHelper.getInsnNodeFor(value); original.set(currentNode, replacement); optimized = true;/*w w w .jav a 2 s.c o m*/ return replacement; } return currentNode; }
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 w w.ja va2s.com 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:org.coldswap.asm.field.PrivateStaticFieldReplacer.java
License:Open Source License
/** * Replaces any GETSTATIC/PUTSTATIC call of the field in the old class with the field * introduced in the new class./*from w w w .j a v a2s .c om*/ * * @param classNode containing the old class. * @param fieldNode containing the old field. */ @SuppressWarnings("unchecked") private void replaceReferences(ClassNode classNode, FieldNode fieldNode) { List<MethodNode> methodNodes = classNode.methods; String contClass = classNode.name.substring(classNode.name.lastIndexOf("/") + 1); final String className = classPackage + TransformerNameGenerator.getPrivateStaticFieldClassName(contClass, fieldNode.name); for (MethodNode method : methodNodes) { InsnList inst = method.instructions; Iterator iter = inst.iterator(); while (iter.hasNext()) { AbstractInsnNode absIns = (AbstractInsnNode) iter.next(); int opcode = absIns.getOpcode(); // check if instruction is GETSTATIC or PUTSTATIC if (opcode == Opcodes.GETSTATIC) { // get type if (absIns.getType() == AbstractInsnNode.FIELD_INSN) { final Boolean[] foundField = { false }; final ClassNode cNode = classNode; final FieldNode fNode = fieldNode; absIns.accept(new MethodVisitor(Opcodes.ASM5) { @Override public void visitFieldInsn(int i, String s, String s2, String s3) { if (cNode.name.equals(s) && fNode.name.equals(s2)) { foundField[0] = true; } super.visitFieldInsn(i, s, s2, s3); } }); if (foundField[0]) { inst.set(absIns, new FieldInsnNode(Opcodes.GETSTATIC, className, fieldNode.name, fieldNode.desc)); } } } else if (opcode == Opcodes.PUTSTATIC) { if (absIns.getType() == AbstractInsnNode.FIELD_INSN) { final Boolean[] foundField = { false }; final ClassNode cNode = classNode; final FieldNode fNode = fieldNode; absIns.accept(new MethodVisitor(Opcodes.ASM5) { @Override public void visitFieldInsn(int i, String s, String s2, String s3) { if (cNode.name.equals(s) && fNode.name.equals(s2)) { foundField[0] = true; } super.visitFieldInsn(i, s, s2, s3); } }); if (foundField[0]) { inst.set(absIns, new FieldInsnNode(Opcodes.PUTSTATIC, className, fieldNode.name, fieldNode.desc)); } } } } } }
From source file:org.coldswap.asm.field.ProtectedStaticFieldReferenceReplacer.java
License:Open Source License
@SuppressWarnings("uncheked") @Override//from w ww . ja v a 2 s .c o m public int findAndReplace(ClassNode classNode) { int counter = 0; if (classNode.superName.equals(supperClass)) { List<MethodNode> methodNodes = classNode.methods; for (MethodNode method : methodNodes) { InsnList inst = method.instructions; Iterator iter = inst.iterator(); while (iter.hasNext()) { AbstractInsnNode absIns = (AbstractInsnNode) iter.next(); int opcode = absIns.getOpcode(); // check if instruction is GETSTATIC or PUTSTATIC if (opcode == Opcodes.GETSTATIC) { // get type if (absIns.getType() == AbstractInsnNode.FIELD_INSN) { final Boolean[] foundField = { false }; absIns.accept(new MethodVisitor(Opcodes.ASM5) { @Override public void visitFieldInsn(int i, String s, String s2, String s3) { if (oldClass.equals(s) && fieldToReplace.name.equals(s2)) { foundField[0] = true; } super.visitFieldInsn(i, s, s2, s3); } }); if (foundField[0]) { inst.set(absIns, new FieldInsnNode(Opcodes.GETSTATIC, newClass, fieldToReplace.name, fieldToReplace.desc)); counter++; } } } else if (opcode == Opcodes.PUTSTATIC) { if (absIns.getType() == AbstractInsnNode.FIELD_INSN) { final Boolean[] foundField = { false }; absIns.accept(new MethodVisitor(Opcodes.ASM5) { @Override public void visitFieldInsn(int i, String s, String s2, String s3) { if (oldClass.equals(s) && fieldToReplace.name.equals(s2)) { foundField[0] = true; } super.visitFieldInsn(i, s, s2, s3); } }); if (foundField[0]) { inst.set(absIns, new FieldInsnNode(Opcodes.PUTSTATIC, newClass, fieldToReplace.name, fieldToReplace.desc)); counter++; } } } } } } return counter; }
From source file:org.coldswap.asm.field.ProtectedStaticFieldReplacer.java
License:Open Source License
/** * Replaces any GETSTATIC/PUTSTATIC call of the field in the old class with the field * introduced in the new class./* w ww . j ava2s. c o m*/ * * @param classNode containing the old class. * @param fieldNode containing the old field. */ private void replaceReferences(ClassNode classNode, FieldNode fieldNode) { List<MethodNode> methodNodes = classNode.methods; String contClass = classNode.name.substring(classNode.name.lastIndexOf("/") + 1); final String className = classPackage + TransformerNameGenerator.getProtectedStaticFieldClassName(contClass, fieldNode.name); for (MethodNode method : methodNodes) { InsnList inst = method.instructions; Iterator iter = inst.iterator(); while (iter.hasNext()) { AbstractInsnNode absIns = (AbstractInsnNode) iter.next(); int opcode = absIns.getOpcode(); // check if instruction is GETSTATIC or PUTSTATIC if (opcode == Opcodes.GETSTATIC) { // get type if (absIns.getType() == AbstractInsnNode.FIELD_INSN) { final Boolean[] foundField = { false }; final ClassNode cNode = classNode; final FieldNode fNode = fieldNode; absIns.accept(new MethodVisitor(Opcodes.ASM5) { @Override public void visitFieldInsn(int i, String s, String s2, String s3) { if (cNode.name.equals(s) && fNode.name.equals(s2)) { foundField[0] = true; } super.visitFieldInsn(i, s, s2, s3); } }); if (foundField[0]) { inst.set(absIns, new FieldInsnNode(Opcodes.GETSTATIC, className, fieldNode.name, fieldNode.desc)); } } } else if (opcode == Opcodes.PUTSTATIC) { if (absIns.getType() == AbstractInsnNode.FIELD_INSN) { final Boolean[] foundField = { false }; final ClassNode cNode = classNode; final FieldNode fNode = fieldNode; absIns.accept(new MethodVisitor(Opcodes.ASM5) { @Override public void visitFieldInsn(int i, String s, String s2, String s3) { if (cNode.name.equals(s) && fNode.name.equals(s2)) { foundField[0] = true; } super.visitFieldInsn(i, s, s2, s3); } }); if (foundField[0]) { inst.set(absIns, new FieldInsnNode(Opcodes.PUTSTATIC, className, fieldNode.name, fieldNode.desc)); } } } } } }
From source file:org.coldswap.asm.field.PublicStaticFieldReferenceReplacer.java
License:Open Source License
@SuppressWarnings("unchecked") @Override/*from w ww. j a v a 2 s . c o m*/ public int findAndReplace(ClassNode classNode) { int counter = 0; List<MethodNode> methodNodes = classNode.methods; for (MethodNode method : methodNodes) { InsnList inst = method.instructions; Iterator iter = inst.iterator(); while (iter.hasNext()) { AbstractInsnNode absIns = (AbstractInsnNode) iter.next(); int opcode = absIns.getOpcode(); // check if instruction is GETSTATIC or PUTSTATIC if (opcode == Opcodes.GETSTATIC) { // get type if (absIns.getType() == AbstractInsnNode.FIELD_INSN) { final Boolean[] foundField = { false }; absIns.accept(new MethodVisitor(Opcodes.ASM5) { @Override public void visitFieldInsn(int i, String s, String s2, String s3) { if (oldClass.equals(s) && fieldToReplace.name.equals(s2)) { foundField[0] = true; } super.visitFieldInsn(i, s, s2, s3); } }); if (foundField[0]) { inst.set(absIns, new FieldInsnNode(Opcodes.GETSTATIC, newClass, fieldToReplace.name, fieldToReplace.desc)); counter++; } } } else if (opcode == Opcodes.PUTSTATIC) { if (absIns.getType() == AbstractInsnNode.FIELD_INSN) { final Boolean[] foundField = { false }; absIns.accept(new MethodVisitor(Opcodes.ASM5) { @Override public void visitFieldInsn(int i, String s, String s2, String s3) { if (oldClass.equals(s) && fieldToReplace.name.equals(s2)) { foundField[0] = true; } super.visitFieldInsn(i, s, s2, s3); } }); if (foundField[0]) { inst.set(absIns, new FieldInsnNode(Opcodes.PUTSTATIC, newClass, fieldToReplace.name, fieldToReplace.desc)); counter++; } } } } } return counter; }
From source file:org.coldswap.asm.field.PublicStaticFieldReplacer.java
License:Open Source License
/** * Replaces any GETSTATIC/PUTSTATIC call of the field in the old class with the field * introduced in the new class./*from ww w . j av a2 s . co m*/ * * @param classNode containing the old class. * @param fieldNode containing the old field. */ private void replaceReferences(ClassNode classNode, FieldNode fieldNode) { List<MethodNode> methodNodes = classNode.methods; String contClass = classNode.name.substring(classNode.name.lastIndexOf("/") + 1); final String className = classPackage + TransformerNameGenerator.getPublicStaticFieldClassName(contClass, fieldNode.name); for (MethodNode method : methodNodes) { InsnList inst = method.instructions; Iterator iter = inst.iterator(); while (iter.hasNext()) { AbstractInsnNode absIns = (AbstractInsnNode) iter.next(); int opcode = absIns.getOpcode(); // check if instruction is GETSTATIC or PUTSTATIC if (opcode == Opcodes.GETSTATIC) { // get type if (absIns.getType() == AbstractInsnNode.FIELD_INSN) { final Boolean[] foundField = { false }; final ClassNode cNode = classNode; final FieldNode fNode = fieldNode; absIns.accept(new MethodVisitor(Opcodes.ASM5) { @Override public void visitFieldInsn(int i, String s, String s2, String s3) { if (cNode.name.equals(s) && fNode.name.equals(s2)) { foundField[0] = true; } super.visitFieldInsn(i, s, s2, s3); } }); if (foundField[0]) { inst.set(absIns, new FieldInsnNode(Opcodes.GETSTATIC, className, fieldNode.name, fieldNode.desc)); } } } else if (opcode == Opcodes.PUTSTATIC) { if (absIns.getType() == AbstractInsnNode.FIELD_INSN) { final Boolean[] foundField = { false }; final ClassNode cNode = classNode; final FieldNode fNode = fieldNode; absIns.accept(new MethodVisitor(Opcodes.ASM5) { @Override public void visitFieldInsn(int i, String s, String s2, String s3) { if (cNode.name.equals(s) && fNode.name.equals(s2)) { foundField[0] = true; } super.visitFieldInsn(i, s, s2, s3); } }); if (foundField[0]) { inst.set(absIns, new FieldInsnNode(Opcodes.PUTSTATIC, className, fieldNode.name, fieldNode.desc)); } } } } } }
From source file:org.coldswap.asm.VirtualMethodReplacer.java
License:Open Source License
@Override public MethodNode replaceInvoke(MethodNode methodNode) { InsnList instructions = methodNode.instructions; Iterator it = instructions.iterator(); while (it.hasNext()) { AbstractInsnNode code = (AbstractInsnNode) it.next(); if (code.getOpcode() == Opcodes.INVOKEVIRTUAL) { // check if methodToReplace is called final boolean[] callFounded = new boolean[] { false }; code.accept(new MethodVisitor(Opcodes.ASM5) { @Override// ww w.j av a 2 s .c om public void visitMethodInsn(int i, String s, String s2, String s3) { if (s.equals(classContainer) && s2.equals(methodName)) { callFounded[0] = true; } super.visitMethodInsn(i, s, s2, s3); } }); if (callFounded[0]) { // if the return type is primitive and the value is not discarded, unbox if (AutoBoxing.isPrimitive(retType.getDescriptor())) { AbstractInsnNode codeNext = code.getNext(); boolean discarded = false; // if returning primitive double or long and it is discarded with a pop2 than discard with // simple pop, because we use an Object as return value. if (codeNext.getOpcode() == Opcodes.POP2 && (retType.getDescriptor().equals("D") || retType.getDescriptor().equals("J"))) { instructions.set(codeNext, new InsnNode(Opcodes.POP)); } if (codeNext.getOpcode() == Opcodes.POP || codeNext.getOpcode() == Opcodes.POP2) { discarded = true; } if (!discarded) { instructions.insert(code, AutoBoxing.unbox(retType)); } } // replace call with a custom call String newMethodName; AbstractInsnNode newInvoke = null; if (Constants.VAROBJECT.equals(methodType)) { newMethodName = TransformerNameGenerator.getObjectMethodNameWithCounter(classContainer, methodNumber); newInvoke = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, classContainer, newMethodName, "([Ljava/lang/Object;)Ljava/lang/Object;"); } else if (Constants.INT.equals(methodType)) { newMethodName = TransformerNameGenerator.getIntMethodNameWithCounter(classContainer, methodNumber); newInvoke = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, classContainer, newMethodName, "(I)Ljava/lang/Object;"); } else if (Constants.FLOAT.equals(methodType)) { newMethodName = TransformerNameGenerator.getFloatMethodNameWithCounter(classContainer, methodNumber); newInvoke = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, classContainer, newMethodName, "(F)Ljava/lang/Object;"); } else if (Constants.STRING.equals(methodType)) { newMethodName = TransformerNameGenerator.getStringMethodNameWithCounter(classContainer, methodNumber); newInvoke = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, classContainer, newMethodName, "(Ljava/lang/String;)Ljava/lang/Object;"); } else if (Constants.LONG.equals(methodType)) { newMethodName = TransformerNameGenerator.getLongMethodNameWithCounter(classContainer, methodNumber); newInvoke = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, classContainer, newMethodName, "(J)Ljava/lang/Object;"); } if (newInvoke != null) { instructions.set(code, newInvoke); } } } } return methodNode; }
From source file:org.eclipse.objectteams.otredyn.bytecode.asm.MoveCodeToCallOrigAdapter.java
License:Open Source License
/** To avoid infinite recursion, calls super.m(a1, a2) must be translated to super.callOrig(boundMethodId, new Object[] {a1, a2}). */ private void adjustSuperCalls(InsnList instructions, String selector, Type[] args, Type returnType, int boundMethodIdSlot) { // search://from w w w . j a va 2s .c om List<MethodInsnNode> toReplace = new ArrayList<MethodInsnNode>(); ListIterator<AbstractInsnNode> orgMethodIter = instructions.iterator(); while (orgMethodIter.hasNext()) { AbstractInsnNode orgMethodNode = orgMethodIter.next(); if (orgMethodNode.getOpcode() == Opcodes.INVOKESPECIAL && ((MethodInsnNode) orgMethodNode).name.equals(selector)) toReplace.add((MethodInsnNode) orgMethodNode); } if (toReplace.isEmpty()) return; // replace: for (MethodInsnNode oldNode : toReplace) { // we need to insert into the loading sequence before the invocation, find the insertion points: AbstractInsnNode[] insertionPoints = StackBalanceAnalyzer.findInsertionPointsBefore(oldNode, args); AbstractInsnNode firstInsert = insertionPoints.length > 0 ? insertionPoints[0] : oldNode; // push first arg to _OT$callOrig(): instructions.insertBefore(firstInsert, new IntInsnNode(Opcodes.ILOAD, boundMethodIdSlot)); // prepare array as second arg to _OT$callOrig(): instructions.insertBefore(firstInsert, new IntInsnNode(Opcodes.BIPUSH, args.length)); instructions.insertBefore(firstInsert, new TypeInsnNode(Opcodes.ANEWARRAY, "java/lang/Object")); for (int i = 0; i < insertionPoints.length; i++) { // NB: each iteration has an even stack balance, where the top is the Object[]. instructions.insertBefore(insertionPoints[i], new InsnNode(Opcodes.DUP)); instructions.insertBefore(insertionPoints[i], new IntInsnNode(Opcodes.BIPUSH, i)); // leave the original loading sequence in tact and continue at the next point: AbstractInsnNode insertAt = (i + 1 < insertionPoints.length) ? insertionPoints[i + 1] : oldNode; instructions.insertBefore(insertAt, AsmTypeHelper.getBoxingInstructionForType(args[i])); instructions.insertBefore(insertAt, new InsnNode(Opcodes.AASTORE)); } if (returnType == Type.VOID_TYPE) instructions.insert(oldNode, new InsnNode(Opcodes.POP)); else instructions.insert(oldNode, AsmTypeHelper.getUnboxingInstructionForType(returnType)); instructions.set(oldNode, new MethodInsnNode(Opcodes.INVOKESPECIAL, ((MethodInsnNode) oldNode).owner, callOrig.getName(), callOrig.getSignature())); } }