/** * This method returns the BytecodeInstruction that loaded the reference * which is located on top of the stack minus positionFromTop when this * instruction is executed. * * This is done using the CFGFrame created by the SourceInterpreter() of the * BytecodeAnalyzer via the CFGGenerator * * Note that this method may return null. This can happen when aliasing is * involved. For example for method invocations on objects this can happen * when you first store the object in a local variable and then call a * method on that variable * * see PairTestClass.sourceCallerTest() for an even worse example. * * TODO: this could be done better by following the SourceValues even * further. */ public BytecodeInstruction getSourceOfStackInstruction(int positionFromTop) { if (frame == null) throw new IllegalStateException( "expect each BytecodeInstruction to have its CFGFrame set"); int stackPos = frame.getStackSize() - (1 + positionFromTop); if (stackPos < 0){ StackTraceElement[] se = new Throwable().getStackTrace(); int t=0; System.out.println("Stack trace: "); while(t<se.length){ System.out.println(se[t]); t++; } return null; } SourceValue source = (SourceValue) frame.getStack(stackPos); if (source.insns.size() != 1) { // we don't know for sure, let's be conservative return null; } Object sourceIns = source.insns.iterator().next(); AbstractInsnNode sourceInstruction = (AbstractInsnNode) sourceIns; BytecodeInstruction src = BytecodeInstructionPool.getInstance(classLoader).getInstruction(className, methodName, sourceInstruction); return src; }
private InsnList procAtCallSite(final ProcInstance processor) throws InvalidContextUsageException { final Frame <SourceValue> frame = info.getSourceFrame (weavingLoc); final InsnList result = new InsnList(); for (final ProcMethodInstance pmi : processor.getMethods ()) { final Code code = pmi.getCode ().clone (); final int index = pmi.getArgPos (); final int total = pmi.getArgsCount (); final Type type = pmi.getArgType ().getASMType (); final InsnList insns = code.getInstructions (); rewriteArgumentContextCalls (index, total, type, insns); // Duplicate call site arguments and store them into local vars. final SourceValue source = FrameHelper.getStackByIndex (frame, total - 1 - index); for (final AbstractInsnNode argLoadInsn : source.insns) { // TRICK: the value has to be set properly because // method code will be not adjusted by fixLocalIndex method.instructions.insert (argLoadInsn, AsmHelper.storeVar (type, method.maxLocals + maxLocals)); method.instructions.insert (argLoadInsn, new InsnNode (type.getSize () == 2 ? Opcodes.DUP2 : Opcodes.DUP)); } __shiftLocalSlots (maxLocals, insns); maxLocals = __calcMaxLocals (maxLocals + type.getSize(), insns); result.add (insns); method.tryCatchBlocks.addAll (code.getTryCatchBlocks ()); } return result; }
private void tryRemoveAllocation(InsnList ilist, AbstractInsnNode next, Map<AbstractInsnNode, Frame<SourceValue>> frames) { if (next.getOpcode() != Opcodes.DUP) { return; } // TODO LB: iterate over a copy unless we are sure an iterator is OK for (AbstractInsnNode instr : ilist.toArray()) { if (instr.getOpcode() == Opcodes.INVOKESPECIAL) { Type[] args = Type .getArgumentTypes(((MethodInsnNode) instr).desc); Frame<SourceValue> frame = frames.get(instr); Set<AbstractInsnNode> sources = FrameHelper.getStackByIndex( frame, args.length).insns; if (sources.contains(next)) { for (Type arg : args) { ilist.insert(instr, new InsnNode(arg.getSize() == 2 ? Opcodes.POP2 : Opcodes.POP)); } ilist.remove(instr); } } } ilist.remove(next); }
public Frame<SourceValue> getSourceFrame(AbstractInsnNode instr) { return sourceFrameMap.get(instr); }
private boolean removePop() { Map<AbstractInsnNode, Frame<SourceValue>> frames = FrameHelper.createSourceMapping(PartialEvaluator.class.getName(), method); boolean isOptimized = false; // TODO LB: iterate over a copy unless we are sure an iterator is OK for (AbstractInsnNode instr : ilist.toArray()) { int opcode = instr.getOpcode(); if (opcode != Opcodes.POP && opcode != Opcodes.POP2) { continue; } Frame<SourceValue> frame = frames.get(instr); if (frame == null) { continue; } Set<AbstractInsnNode> sources = FrameHelper.getStackByIndex(frame, 0).insns; if (unremovablePop(sources)) { continue; } for (AbstractInsnNode source : sources) { switch (source.getOpcode()) { case Opcodes.INVOKESPECIAL: case Opcodes.INVOKEVIRTUAL: case Opcodes.INVOKESTATIC: tryRemoveInvocation(ilist, (MethodInsnNode) source); break; case Opcodes.NEW: tryRemoveAllocation(ilist, source.getNext(), frames); break; default: break; } ilist.remove(source); } ilist.remove(instr); isOptimized = true; } return isOptimized; }
public static Analyzer<SourceValue> getSourceAnalyzer() { return new Analyzer<SourceValue>(new SourceInterpreter()); }
public static int dupStack ( Frame <SourceValue> frame, MethodNode method, int operand, Type type, int slot ) { SourceValue source = getStackByIndex (frame, operand); for (final AbstractInsnNode insn : source.insns) { // if the instruction duplicates two-size operand(s), weaver should // be careful that the operand might be either 2 one-size operands, // or 1 two-size operand. switch (insn.getOpcode()) { case Opcodes.DUP2: if (source.size != 1) { break; } dupStack (frame, method, operand + 2, type, slot); continue; case Opcodes.DUP2_X1: if (source.size != 1) { break; } dupStack (frame, method, operand + 3, type, slot); continue; case Opcodes.DUP2_X2: if (source.size != 1) { break; } SourceValue x2 = getStackByIndex (frame, operand + 2); dupStack (frame, method, operand + (4 - x2.size), type, slot); continue; case Opcodes.SWAP: if (operand > 0 && getStackByIndex (frame, operand - 1).insns.contains (insn) ) { // insert 'dup' instruction and then store to a local slot method.instructions.insertBefore ( insn, new InsnNode (Opcodes.DUP) ); method.instructions.insertBefore ( insn, AsmHelper.storeVar (type, slot) ); continue; } default: break; } // insert 'dup' instruction and then store to a local slot method.instructions.insert (insn, AsmHelper.storeVar (type, slot)); method.instructions.insert ( insn, new InsnNode (source.size == 2 ? Opcodes.DUP2 : Opcodes.DUP) ); } return source.size; }
public static Frame<SourceValue>[] getSourceFrames(String clazz, MethodNode method) { return getFrames(getSourceAnalyzer(), clazz, method); }
public static Map<AbstractInsnNode, Frame<SourceValue>> createSourceMapping( String clazz, MethodNode method) { return createMapping(getSourceAnalyzer(), clazz, method); }