List of usage examples for org.objectweb.asm.tree InsnList getLast
public AbstractInsnNode getLast()
From source file:de.tuberlin.uebb.jbop.optimizer.var.LocalVarInliner.java
License:Open Source License
/** * Optimize.//from www . ja v a 2 s.c o m * * @param original * the original * @param methodNode * the method node * @return the insn list */ @Override public InsnList optimize(final InsnList original, final MethodNode methodNode) { optimized = false; final Map<Integer, Object> knownValues = new HashMap<>(); final AbstractInsnNode first = original.getFirst(); final AbstractInsnNode last = original.getLast(); handleNodes(first, last, original, knownValues, methodNode); return original; }
From source file:io.moshisho.plugins.MyMojo.java
License:Apache License
private static void betterCompile(String classFile) throws IOException { InputStream is = new FileInputStream(classFile); ClassReader cr = new ClassReader(is); is.close();// w w w.j a v a2 s. com ClassNode cn = new ClassNode(); cr.accept(cn, 0); List methods = cn.methods; for (int i = 0; i < methods.size(); ++i) { MethodNode method = (MethodNode) methods.get(i); if (!isStaticllyBound(method)) { continue; } InsnList instructions = method.instructions; AbstractInsnNode last = instructions.getLast(); while (last != null && last.getType() == AbstractInsnNode.LABEL) { last = last.getPrevious(); } if (last == null || !isReturnInstruction(last) || last.getPrevious().getType() != AbstractInsnNode.METHOD_INSN) { continue; } MethodInsnNode methodInv = (MethodInsnNode) last.getPrevious(); if (!isRecursionCall(cn, method, methodInv)) { continue; } System.out.println("TailRec Optimizaing: " + method.name); // get arguments and types String methodDesc = method.desc; String argsDesc = methodDesc.substring(methodDesc.indexOf('(') + 1, methodDesc.indexOf(')')); System.out.println(argsDesc); // work with Type.getArgumentTypes List<AbstractInsnNode> listInstNodes = new LinkedList<AbstractInsnNode>(); for (int j = argsDesc.length() - 1; j >= 0; j--) { char c = argsDesc.charAt(j); switch (c) { case 'I': listInstNodes.add(new VarInsnNode(ISTORE, argsDesc.length() - j)); break; case 'Z': listInstNodes.add(new VarInsnNode(ISTORE, argsDesc.length() - j)); break; case 'C': listInstNodes.add(new VarInsnNode(ISTORE, argsDesc.length() - j)); break; case 'B': listInstNodes.add(new VarInsnNode(ISTORE, argsDesc.length() - j)); break; case 'S': listInstNodes.add(new VarInsnNode(ISTORE, argsDesc.length() - j)); break; case 'F': listInstNodes.add(new VarInsnNode(FSTORE, argsDesc.length() - j)); break; case 'J': listInstNodes.add(new VarInsnNode(LSTORE, argsDesc.length() - j)); break; case 'D': listInstNodes.add(new VarInsnNode(DSTORE, argsDesc.length() - j)); break; case '[': // TODO: case 'L': // TODO: default: System.out.println("NOT TREATING: " + c); } } // remove the last aload_0 of the recursion AbstractInsnNode pnt = last; while (pnt != null && pnt.getOpcode() != 42 && !(pnt.getOpcode() == 25 && ((VarInsnNode) pnt).var == 0)) { pnt = pnt.getPrevious(); } method.instructions.remove(pnt); Collections.reverse(listInstNodes); for (AbstractInsnNode abstractInsnNode : listInstNodes) { method.instructions.insertBefore(last.getPrevious(), abstractInsnNode); } // place instead of return //goto LabelNode startOfMethodLabel = new LabelNode(new Label()); method.instructions.insertBefore(method.instructions.getFirst(), startOfMethodLabel); JumpInsnNode gotoInst = new JumpInsnNode(GOTO, startOfMethodLabel); method.instructions.set(last.getPrevious(), gotoInst); method.instructions.remove(last); ClassWriter cw = new ClassWriter(0); cn.accept(cw); FileOutputStream fos = new FileOutputStream(classFile); fos.write(cw.toByteArray()); fos.close(); } }
From source file:io.moshisho.plugins.OptimizeClasses.java
License:Apache License
private void optimize(File clz) throws Exception { InputStream is = new FileInputStream(clz); ClassReader cr = new ClassReader(is); is.close();/*from w w w.j av a 2 s . co m*/ ClassNode cn = new ClassNode(); cr.accept(cn, 0); List methods = cn.methods; for (int i = 0; i < methods.size(); ++i) { MethodNode method = (MethodNode) methods.get(i); if (!isStaticllyBound(method)) { continue; } InsnList instructions = method.instructions; AbstractInsnNode last = instructions.getLast(); while (last != null && last.getType() == AbstractInsnNode.LABEL) { last = last.getPrevious(); } if (last == null || !isReturnInstruction(last) || last.getPrevious().getType() != AbstractInsnNode.METHOD_INSN) { continue; } MethodInsnNode methodInv = (MethodInsnNode) last.getPrevious(); if (!isRecursionCall(cn, method, methodInv)) { continue; } getLog().info("TailRec Optimizaing: " + method.name); // get arguments and types String methodDesc = method.desc; String argsDesc = methodDesc.substring(methodDesc.indexOf('(') + 1, methodDesc.indexOf(')')); //System.out.println(argsDesc); // work with Type.getArgumentTypes List<AbstractInsnNode> listInstNodes = new LinkedList<AbstractInsnNode>(); for (int j = argsDesc.length() - 1; j >= 0; j--) { char c = argsDesc.charAt(j); switch (c) { case 'I': listInstNodes.add(new VarInsnNode(ISTORE, argsDesc.length() - j)); break; case 'Z': listInstNodes.add(new VarInsnNode(ISTORE, argsDesc.length() - j)); break; case 'C': listInstNodes.add(new VarInsnNode(ISTORE, argsDesc.length() - j)); break; case 'B': listInstNodes.add(new VarInsnNode(ISTORE, argsDesc.length() - j)); break; case 'S': listInstNodes.add(new VarInsnNode(ISTORE, argsDesc.length() - j)); break; case 'F': listInstNodes.add(new VarInsnNode(FSTORE, argsDesc.length() - j)); break; case 'J': listInstNodes.add(new VarInsnNode(LSTORE, argsDesc.length() - j)); break; case 'D': listInstNodes.add(new VarInsnNode(DSTORE, argsDesc.length() - j)); break; case '[': // TODO: case 'L': // TODO: default: System.out.println("NOT TREATING: " + c); } } // remove the last aload_0 of the recursion AbstractInsnNode pnt = last; while (pnt != null && pnt.getOpcode() != 42 && !(pnt.getOpcode() == 25 && ((VarInsnNode) pnt).var == 0)) { pnt = pnt.getPrevious(); } method.instructions.remove(pnt); Collections.reverse(listInstNodes); for (AbstractInsnNode abstractInsnNode : listInstNodes) { method.instructions.insertBefore(last.getPrevious(), abstractInsnNode); } // place instead of return //goto LabelNode startOfMethodLabel = new LabelNode(new Label()); method.instructions.insertBefore(method.instructions.getFirst(), startOfMethodLabel); JumpInsnNode gotoInst = new JumpInsnNode(GOTO, startOfMethodLabel); method.instructions.set(last.getPrevious(), gotoInst); method.instructions.remove(last); ClassWriter cw = new ClassWriter(0); cn.accept(cw); FileOutputStream fos = new FileOutputStream(clz); fos.write(cw.toByteArray()); fos.close(); } }
From source file:net.doubledoordev.inventorylock.asm.Transformer.java
License:Open Source License
@Override public byte[] transform(String name, String transformedName, byte[] basicClass) { ClassNode classNode = new ClassNode(); ClassReader classReader = new ClassReader(basicClass); classReader.accept(classNode, READER_FLAGS); boolean isPlayer = transformedName.equals(ENTITY_PLAYER_OWNER_NAME); if (isPlayer) LOGGER.info("Found EntityPlayer"); for (MethodNode method : classNode.methods) { InsnList list = method.instructions; if (isPlayer && INSTANCE.mapMethodDesc(method.desc).equals(ENTITY_PLAYER_DESC) && INSTANCE.mapMethodName(name, method.name, method.desc).equals(ENTITY_PLAYER_TARGET)) { final LabelNode newLabel = new LabelNode(); LOGGER.info("Found canOpen"); AbstractInsnNode node = list.getFirst(); while (node.getOpcode() != IRETURN && node != list.getLast()) { if (node.getOpcode() == IFEQ) ((JumpInsnNode) node).label = newLabel; node = node.getNext();/*from www. ja v a 2s . co m*/ } if (node.getOpcode() != IRETURN) throw new RuntimeException("ASM failed. (return not found)"); final AbstractInsnNode target = node; while (node.getType() != LABEL && node != list.getLast()) node = node.getNext(); if (node.getType() != LABEL) throw new RuntimeException("ASM failed. (label not found)"); final LabelNode label = ((LabelNode) node); //Adding "else if (code instanceof BetterLockCode) return ((BetterLockCode) code).contains(this.getUniqueID());" InsnList inject = new InsnList(); inject.add(newLabel); inject.add(new VarInsnNode(ALOAD, 1)); inject.add(new TypeInsnNode(INSTANCEOF, BETTER_LOCK_TYPE)); inject.add(new JumpInsnNode(IFEQ, label)); inject.add(new VarInsnNode(ALOAD, 1)); inject.add(new TypeInsnNode(CHECKCAST, BETTER_LOCK_TYPE)); inject.add(new VarInsnNode(ALOAD, 0)); //inject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, ENTITY_PLAYER_OWNER, ENTITY_PLAYER_GET_UUID, ENTITY_PLATER_GET_UUID_DESC, false)); inject.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, BETTER_LOCK_TYPE, BETTER_LOCK_CONTAINS, BETTER_LOCK_CONTAINS_DESC, false)); inject.add(new InsnNode(IRETURN)); list.insert(target, inject); LOGGER.info("Injected elseif into EntityPlayer's canOpen"); } for (AbstractInsnNode node = list.getFirst(); node != list.getLast(); node = node.getNext()) { if (node.getOpcode() != INVOKESTATIC) continue; MethodInsnNode methodInsnNode = ((MethodInsnNode) node); // if (transformedName.equals("net.minecraft.tileentity.TileEntityLockable")) // LOGGER.info("In {} ({}) Method {}.{}{} Translated {}.{}{}", name, transformedName, // methodInsnNode.owner, methodInsnNode.name, methodInsnNode.desc, // INSTANCE.map(methodInsnNode.owner), INSTANCE.mapMethodName(methodInsnNode.owner, methodInsnNode.name, methodInsnNode.desc), INSTANCE.mapMethodDesc(methodInsnNode.desc).equals(LOCK_CODE_DESC)); if (INSTANCE.map(methodInsnNode.owner).equals(LOCK_CODE_OWNER) && INSTANCE.mapMethodDesc(methodInsnNode.desc).equals(LOCK_CODE_DESC) && INSTANCE.mapMethodName(methodInsnNode.owner, methodInsnNode.name, methodInsnNode.desc) .equals(LOCK_CODE_TARGET)) { methodInsnNode.owner = LOCK_CODE_OWNER_REPLACE; methodInsnNode.name = LOCK_CODE_NAME; LOGGER.info("Replaced call in class {} ({}), method {}{}", name, transformedName, method.name, method.desc); } } } final ClassWriter writer = new ClassWriter(WRITER_FLAGS); classNode.accept(writer); return writer.toByteArray(); }
From source file:org.apache.commons.javaflow.providers.asm3.ContinuableMethodNode.java
License:Apache License
void moveNew() throws AnalyzerException { final SourceInterpreter i = new SourceInterpreter(); final Analyzer a = new Analyzer(i); a.analyze(className, this); final HashMap<AbstractInsnNode, MethodInsnNode> movable = new HashMap<AbstractInsnNode, MethodInsnNode>(); final Frame[] frames = a.getFrames(); for (int j = 0; j < methods.size(); j++) { final MethodInsnNode mnode = (MethodInsnNode) methods.get(j); // require to move NEW instruction int n = instructions.indexOf(mnode); Frame f = frames[n];//from ww w .j a v a 2 s. c om Type[] args = Type.getArgumentTypes(mnode.desc); SourceValue v = (SourceValue) f.getStack(f.getStackSize() - args.length - 1); @SuppressWarnings("unchecked") Set<AbstractInsnNode> insns = v.insns; for (final AbstractInsnNode ins : insns) { if (ins.getOpcode() == NEW) { movable.put(ins, mnode); } else { // other known patterns int n1 = instructions.indexOf(ins); if (ins.getOpcode() == DUP) { // <init> with params AbstractInsnNode ins1 = instructions.get(n1 - 1); if (ins1.getOpcode() == NEW) { movable.put(ins1, mnode); } } else if (ins.getOpcode() == SWAP) { // in exception handler AbstractInsnNode ins1 = instructions.get(n1 - 1); AbstractInsnNode ins2 = instructions.get(n1 - 2); if (ins1.getOpcode() == DUP_X1 && ins2.getOpcode() == NEW) { movable.put(ins2, mnode); } } } } } int updateMaxStack = 0; for (final Map.Entry<AbstractInsnNode, MethodInsnNode> e : movable.entrySet()) { AbstractInsnNode node1 = e.getKey(); int n1 = instructions.indexOf(node1); AbstractInsnNode node2 = instructions.get(n1 + 1); AbstractInsnNode node3 = instructions.get(n1 + 2); int producer = node2.getOpcode(); instructions.remove(node1); // NEW boolean requireDup = false; if (producer == DUP) { instructions.remove(node2); // DUP requireDup = true; } else if (producer == DUP_X1) { instructions.remove(node2); // DUP_X1 instructions.remove(node3); // SWAP requireDup = true; } MethodInsnNode mnode = (MethodInsnNode) e.getValue(); AbstractInsnNode nm = mnode; int varOffset = stackRecorderVar + 1; Type[] args = Type.getArgumentTypes(mnode.desc); // optimizations for some common cases if (args.length == 0) { final InsnList doNew = new InsnList(); doNew.add(node1); // NEW if (requireDup) doNew.add(new InsnNode(DUP)); instructions.insertBefore(nm, doNew); nm = doNew.getLast(); continue; } if (args.length == 1 && args[0].getSize() == 1) { final InsnList doNew = new InsnList(); doNew.add(node1); // NEW if (requireDup) { doNew.add(new InsnNode(DUP)); doNew.add(new InsnNode(DUP2_X1)); doNew.add(new InsnNode(POP2)); updateMaxStack = updateMaxStack < 2 ? 2 : updateMaxStack; // a two extra slots for temp values } else doNew.add(new InsnNode(SWAP)); instructions.insertBefore(nm, doNew); nm = doNew.getLast(); continue; } // TODO this one untested! if ((args.length == 1 && args[0].getSize() == 2) || (args.length == 2 && args[0].getSize() == 1 && args[1].getSize() == 1)) { final InsnList doNew = new InsnList(); doNew.add(node1); // NEW if (requireDup) { doNew.add(new InsnNode(DUP)); doNew.add(new InsnNode(DUP2_X2)); doNew.add(new InsnNode(POP2)); updateMaxStack = updateMaxStack < 2 ? 2 : updateMaxStack; // a two extra slots for temp values } else { doNew.add(new InsnNode(DUP_X2)); doNew.add(new InsnNode(POP)); updateMaxStack = updateMaxStack < 1 ? 1 : updateMaxStack; // an extra slot for temp value } instructions.insertBefore(nm, doNew); nm = doNew.getLast(); continue; } final InsnList doNew = new InsnList(); // generic code using temporary locals // save stack for (int j = args.length - 1; j >= 0; j--) { Type type = args[j]; doNew.add(new VarInsnNode(type.getOpcode(ISTORE), varOffset)); varOffset += type.getSize(); } if (varOffset > maxLocals) { maxLocals = varOffset; } doNew.add(node1); // NEW if (requireDup) doNew.add(new InsnNode(DUP)); // restore stack for (int j = 0; j < args.length; j++) { Type type = args[j]; varOffset -= type.getSize(); doNew.add(new VarInsnNode(type.getOpcode(ILOAD), varOffset)); // clean up store to avoid memory leak? if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { updateMaxStack = updateMaxStack < 1 ? 1 : updateMaxStack; // an extra slot for ACONST_NULL doNew.add(new InsnNode(ACONST_NULL)); doNew.add(new VarInsnNode(type.getOpcode(ISTORE), varOffset)); } } instructions.insertBefore(nm, doNew); nm = doNew.getLast(); } maxStack += updateMaxStack; }
From source file:org.evosuite.instrumentation.NodeRegularExpression.java
License:Open Source License
/** * <p>matches</p>//from w w w . jav a 2s.co m * * @param instructions a {@link org.objectweb.asm.tree.InsnList} object. * @return a boolean. */ public boolean matches(InsnList instructions) { int match = 0; AbstractInsnNode node = instructions.getFirst(); while (node != instructions.getLast()) { if (node.getType() == AbstractInsnNode.FRAME || node.getType() == AbstractInsnNode.LABEL || node.getType() == AbstractInsnNode.LINE) { node = node.getNext(); continue; } else { boolean found = false; for (int opcode : pattern[match]) { if (node.getOpcode() == opcode) { match++; found = true; break; } } if (!found) match = 0; } if (match == pattern.length) return true; node = node.getNext(); } return false; }
From source file:org.evosuite.instrumentation.NodeRegularExpression.java
License:Open Source License
/** * <p>getNextMatch</p>//w w w. j a v a 2s . c o m * * @param start a {@link org.objectweb.asm.tree.AbstractInsnNode} object. * @param instructions a {@link org.objectweb.asm.tree.InsnList} object. * @return a {@link org.objectweb.asm.tree.AbstractInsnNode} object. */ public AbstractInsnNode getNextMatch(AbstractInsnNode start, InsnList instructions) { int match = 0; AbstractInsnNode node = start; AbstractInsnNode startNode = start; while (node != instructions.getLast()) { if (node.getType() == AbstractInsnNode.FRAME || node.getType() == AbstractInsnNode.LABEL || node.getType() == AbstractInsnNode.LINE) { node = node.getNext(); continue; } else { boolean found = false; for (int opcode : pattern[match]) { if (node.getOpcode() == opcode) { if (match == 0) startNode = node; match++; found = true; break; } } if (!found) match = 0; } if (match == pattern.length) { return startNode; } node = node.getNext(); } return null; }
From source file:org.parboiled.transform.process.LabellingGenerator.java
License:Apache License
@Override public void process(@Nonnull final ParserClassNode classNode, @Nonnull final RuleMethod method) throws Exception { Objects.requireNonNull(classNode, "classNode"); Objects.requireNonNull(method, "method"); // super methods have flag moved to the overriding method Preconditions.checkState(!method.isSuperMethod()); final InsnList instructions = method.instructions; AbstractInsnNode retInsn = instructions.getLast(); while (retInsn.getOpcode() != ARETURN) retInsn = retInsn.getPrevious(); final LabelNode label = new LabelNode(); final CodeBlock block = CodeBlock.newCodeBlock().dup().ifnull(label).ldc(getLabelText(method)) .invokeinterface(CodegenUtils.p(Rule.class), "label", CodegenUtils.sig(Rule.class, String.class)) .label(label);/*from w ww .j a v a 2 s.c o m*/ instructions.insertBefore(retInsn, block.getInstructionList()); }
From source file:org.parboiled.transform.process.VarFramingGenerator.java
License:Apache License
@Override public void process(@Nonnull final ParserClassNode classNode, @Nonnull final RuleMethod method) throws Exception { Objects.requireNonNull(classNode, "classNode"); Objects.requireNonNull(method, "method"); final InsnList instructions = method.instructions; AbstractInsnNode ret = instructions.getLast(); while (ret.getOpcode() != ARETURN) ret = ret.getPrevious();/* w w w . ja v a 2 s . c o m*/ final CodeBlock block = CodeBlock.newCodeBlock(); block.newobj(CodegenUtils.p(VarFramingMatcher.class)).dup_x1().swap(); createVarFieldArray(block, method); block.invokespecial(CodegenUtils.p(VarFramingMatcher.class), "<init>", CodegenUtils.sig(void.class, Rule.class, Var[].class)); instructions.insertBefore(ret, block.getInstructionList()); method.setBodyRewritten(); }
From source file:org.spongepowered.asm.mixin.transformer.MixinTransformer.java
License:MIT License
/** * Get insns corresponding to the instance initialiser (hopefully) from the * supplied constructor.//from w ww . jav a 2 s . c o m * * TODO Potentially rewrite this to be less horrible. * * @param mixin * @param ctor * @return initialiser bytecode extracted from the supplied constructor, or * null if the constructor range could not be parsed */ private InsnList getInitialiser(MixinTargetContext mixin, MethodNode ctor) { // Find the range of line numbers which corresponds to the constructor body Range init = this.getConstructorRange(ctor); if (!init.isValid()) { return null; } // Now we know where the constructor is, look for insns which lie OUTSIDE the method body int line = 0; InsnList initialiser = new InsnList(); boolean gatherNodes = false; int trimAtOpcode = -1; LabelNode optionalInsn = null; for (Iterator<AbstractInsnNode> iter = ctor.instructions.iterator(init.marker); iter.hasNext();) { AbstractInsnNode insn = iter.next(); if (insn instanceof LineNumberNode) { line = ((LineNumberNode) insn).line; AbstractInsnNode next = ctor.instructions.get(ctor.instructions.indexOf(insn) + 1); if (line == init.end && next.getOpcode() != Opcodes.RETURN) { gatherNodes = true; trimAtOpcode = Opcodes.RETURN; } else { gatherNodes = init.excludes(line); trimAtOpcode = -1; } } else if (gatherNodes) { if (optionalInsn != null) { initialiser.add(optionalInsn); optionalInsn = null; } if (insn instanceof LabelNode) { optionalInsn = (LabelNode) insn; } else { int opcode = insn.getOpcode(); if (opcode == trimAtOpcode) { trimAtOpcode = -1; continue; } for (int ivalidOp : MixinTransformer.INITIALISER_OPCODE_BLACKLIST) { if (opcode == ivalidOp) { // At the moment I don't handle any transient locals because I haven't seen any in the wild, but let's avoid writing // code which will likely break things and fix it if a real test case ever appears throw new InvalidMixinException(mixin, "Cannot handle " + ASMHelper.getOpcodeName(opcode) + " opcode (0x" + Integer.toHexString(opcode).toUpperCase() + ") in class initialiser"); } } initialiser.add(insn); } } } // Check that the last insn is a PUTFIELD, if it's not then AbstractInsnNode last = initialiser.getLast(); if (last != null) { if (last.getOpcode() != Opcodes.PUTFIELD) { throw new InvalidMixinException(mixin, "Could not parse initialiser, expected 0xB5, found 0x" + Integer.toHexString(last.getOpcode())); } } return initialiser; }