List of usage examples for org.objectweb.asm.tree InsnList get
public AbstractInsnNode get(final int index)
From source file:org.evosuite.regression.bytecode.RegressionClassDiff.java
License:Open Source License
private static Map<String, List<Integer>> getClassInstructions(InputStream classAsInputStream) { HashMap<String, List<Integer>> methodInstructionsMap = new HashMap<>(); try {/*from w ww .ja v a 2 s . c om*/ ClassReader reader = new ClassReader(classAsInputStream); ClassNode classNode = new ClassNode(); reader.accept(classNode, 0); @SuppressWarnings("unchecked") final List<MethodNode> methods = classNode.methods; Printer printer = new Textifier(); TraceMethodVisitor mp = new TraceMethodVisitor(printer); for (MethodNode m : methods) { List<Integer> instructions = new ArrayList<>(); InsnList inList = m.instructions; String mathodID = m.name + ": " + m.desc; System.out.println(mathodID); int[] methodInstructions = new int[inList.size()]; for (int i = 0; i < inList.size(); i++) { int op = inList.get(i).getOpcode(); methodInstructions[i] = op; AbstractInsnNode insn = inList.get(i); insn.accept(mp); // Uncomment the following comment block to print the bytecode // instructions // StringWriter sw = new StringWriter(); // printer.print(new PrintWriter(sw)); // printer.getText().clear(); // System.out.println(sw.toString()); // logger.warn("{} -> {}", sw.toString(), op); if (op != -1) instructions.add(op); } methodInstructionsMap.put(mathodID, instructions); } } catch (IOException e) { // Will fail if ClassReader fails e.printStackTrace(); } return methodInstructionsMap; }
From source file:org.evosuite.regression.RegressionClassDiff.java
License:Open Source License
public static Map<String, List<Integer>> getClassInstructions(InputStream classAsInputStream) { HashMap<String, List<Integer>> methodInstructionsMap = new HashMap<>(); try {/*from w w w . j a v a2s. com*/ ClassReader reader = new ClassReader(classAsInputStream); ClassNode classNode = new ClassNode(); reader.accept(classNode, 0); @SuppressWarnings("unchecked") final List<MethodNode> methods = classNode.methods; Printer printer = new Textifier(); TraceMethodVisitor mp = new TraceMethodVisitor(printer); for (MethodNode m : methods) { List<Integer> instructions = new ArrayList<>(); InsnList inList = m.instructions; String mathodID = m.name + ": " + m.desc; System.out.println(mathodID); int[] methodInstructions = new int[inList.size()]; for (int i = 0; i < inList.size(); i++) { int op = inList.get(i).getOpcode(); methodInstructions[i] = op; AbstractInsnNode insn = inList.get(i); insn.accept(mp); // Uncomment the following comment block to print the bytecode // instructions // StringWriter sw = new StringWriter(); // printer.print(new PrintWriter(sw)); // printer.getText().clear(); // System.out.println(sw.toString()); // logger.warn("{} -> {}", sw.toString(), op); if (op != -1) instructions.add(op); } methodInstructionsMap.put(mathodID, instructions); } } catch (IOException e) { // Will fail if ClassReader fails e.printStackTrace(); } return methodInstructionsMap; }
From source file:org.evosuite.testcarver.instrument.Instrumenter.java
License:Open Source License
private void instrumentGETXXXFieldAccesses(final ClassNode cn, final String internalClassName, final MethodNode methodNode) { final InsnList instructions = methodNode.instructions; AbstractInsnNode ins = null;//from w w w . ja v a2 s .co m FieldInsnNode fieldIns = null; for (int i = 0; i < instructions.size(); i++) { ins = instructions.get(i); if (ins instanceof FieldInsnNode) { fieldIns = (FieldInsnNode) ins; /* * Is field referencing outermost instance? if yes, ignore it * http://tns-www.lcs.mit.edu/manuals/java-1.1.1/guide/innerclasses/spec/innerclasses.doc10.html */ if (fieldIns.name.endsWith("$0")) { continue; } final int opcode = ins.getOpcode(); if (opcode == Opcodes.GETFIELD || opcode == Opcodes.GETSTATIC) { final InsnList il = new InsnList(); if (opcode == Opcodes.GETFIELD) { Type fieldType = Type.getType(fieldIns.desc); if (fieldType.getSize() == 1) { instructions.insertBefore(fieldIns, new InsnNode(Opcodes.DUP)); il.add(new InsnNode(Opcodes.SWAP)); } else if (fieldType.getSize() == 2) { instructions.insertBefore(fieldIns, new InsnNode(Opcodes.DUP)); // v // GETFIELD // v, w il.add(new InsnNode(Opcodes.DUP2_X1)); // w, v, w il.add(new InsnNode(Opcodes.POP2)); // w, v // -> Call // w } } else il.add(new InsnNode(Opcodes.ACONST_NULL)); il.add(new LdcInsnNode(this.captureId)); il.add(new LdcInsnNode(fieldIns.owner)); il.add(new LdcInsnNode(fieldIns.name)); il.add(new LdcInsnNode(fieldIns.desc)); il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, PackageInfo.getNameWithSlash(org.evosuite.testcarver.capture.FieldRegistry.class), "notifyReadAccess", "(Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V")); i += il.size(); instructions.insert(fieldIns, il); this.captureId++; } } } }
From source file:org.evosuite.testcarver.instrument.Instrumenter.java
License:Open Source License
private void instrumentPUTXXXFieldAccesses(final ClassNode cn, final String internalClassName, final MethodNode methodNode) { final InsnList instructions = methodNode.instructions; AbstractInsnNode ins = null;/*w w w. j a v a2 s. c om*/ FieldInsnNode fieldIns = null; // needed get right receiver var in case of PUTFIELD for (int i = 0; i < instructions.size(); i++) { ins = instructions.get(i); if (ins instanceof FieldInsnNode) { fieldIns = (FieldInsnNode) ins; /* * Is field referencing outermost instance? if yes, ignore it * http://tns-www.lcs.mit.edu/manuals/java-1.1.1/guide/innerclasses/spec/innerclasses.doc10.html */ if (fieldIns.name.endsWith("$0")) { continue; } final int opcode = ins.getOpcode(); if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) { // construction of // Capturer.capture(final Object receiver, final String methodName, final Object[] methodParams) // call final InsnList il = new InsnList(); if (opcode == Opcodes.PUTFIELD) { Type fieldType = Type.getType(fieldIns.desc); if (fieldType.getSize() == 1) { instructions.insertBefore(fieldIns, new InsnNode(Opcodes.DUP2)); il.add(new InsnNode(Opcodes.POP)); } else if (fieldType.getSize() == 2) { InsnList uglyList = new InsnList(); // v, w uglyList.add(new InsnNode(Opcodes.DUP2_X1)); // w, v, w uglyList.add(new InsnNode(Opcodes.POP2)); // w, v uglyList.add(new InsnNode(Opcodes.DUP)); // w, v, v uglyList.add(new InsnNode(Opcodes.DUP2_X2)); // v, v, w, v, v uglyList.add(new InsnNode(Opcodes.POP2)); // v, v, w instructions.insertBefore(fieldIns, uglyList); // PUTFIELD // v } } else il.add(new InsnNode(Opcodes.ACONST_NULL)); il.add(new LdcInsnNode(this.captureId)); il.add(new LdcInsnNode(fieldIns.owner)); il.add(new LdcInsnNode(fieldIns.name)); il.add(new LdcInsnNode(fieldIns.desc)); il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, PackageInfo.getNameWithSlash(FieldRegistry.class), "notifyModification", "(Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V")); // PUTFIELDRegistry.notifyModification also adds corresponding GETFIELD capture instructions this.captureId++; i += il.size(); instructions.insert(fieldIns, il); this.captureId++; } } } }
From source file:org.mutabilitydetector.checkers.settermethod.InitialValueFinder.java
License:Apache License
private AbstractInsnNode findValueSetUpInsnIn(final MethodNode constructor) { final List<ControlFlowBlock> blocks = enhancedClassNode.getControlFlowBlocksForMethod(constructor); final Finder<AssignmentInsn> f = EffectiveAssignmentInsnFinder.newInstance(variable, blocks); final AssignmentInsn effectiveAssignmentInsn = f.find(); final int indexOfAssignmentInstruction = effectiveAssignmentInsn.getIndexWithinMethod(); final InsnList instructions = constructor.instructions; final AbstractInsnNode result = instructions.get(indexOfAssignmentInstruction - 1); return result; }
From source file:org.springsource.loaded.TypeDiffComputer.java
License:Apache License
/** * Determine if there any differences between the methods supplied. A MethodDelta object is built to record any differences and * stored against the type delta./*from www . j a va2s . c o m*/ * * @param oMethod 'old' method * @param nMethod 'new' method * @param td the type delta where changes are currently being accumulated */ private static void computeAnyMethodDifferences(MethodNode oMethod, MethodNode nMethod, TypeDelta td) { MethodDelta md = new MethodDelta(oMethod.name, oMethod.desc); if (oMethod.access != nMethod.access) { md.setAccessChanged(oMethod.access, nMethod.access); } // TODO annotations InsnList oInstructions = oMethod.instructions; InsnList nInstructions = nMethod.instructions; if (oInstructions.size() != nInstructions.size()) { md.setInstructionsChanged(oInstructions.toArray(), nInstructions.toArray()); } else { // TODO Just interested in constructors right now - should add others if (oMethod.name.charAt(0) == '<') { String oInvokeSpecialDescriptor = null; String nInvokeSpecialDescriptor = null; int oUninitCount = 0; int nUninitCount = 0; boolean codeChange = false; for (int i = 0, max = oInstructions.size(); i < max; i++) { AbstractInsnNode oInstruction = oInstructions.get(i); AbstractInsnNode nInstruction = nInstructions.get(i); if (!codeChange) { if (!sameInstruction(oInstruction, nInstruction)) { codeChange = true; } } if (oInstruction.getType() == AbstractInsnNode.TYPE_INSN) { if (oInstruction.getOpcode() == Opcodes.NEW) { oUninitCount++; } } if (nInstruction.getType() == AbstractInsnNode.TYPE_INSN) { if (nInstruction.getOpcode() == Opcodes.NEW) { nUninitCount++; } } if (oInstruction.getType() == AbstractInsnNode.METHOD_INSN) { MethodInsnNode mi = (MethodInsnNode) oInstruction; if (mi.getOpcode() == INVOKESPECIAL && mi.name.equals("<init>")) { if (oUninitCount == 0) { // this is the one! oInvokeSpecialDescriptor = mi.desc; } else { oUninitCount--; } } } if (nInstruction.getType() == AbstractInsnNode.METHOD_INSN) { MethodInsnNode mi = (MethodInsnNode) nInstruction; if (mi.getOpcode() == INVOKESPECIAL && mi.name.equals("<init>")) { if (nUninitCount == 0) { // this is the one! nInvokeSpecialDescriptor = mi.desc; } else { nUninitCount--; } } } } // Has the invokespecial changed? if (oInvokeSpecialDescriptor == null) { if (nInvokeSpecialDescriptor != null) { md.setInvokespecialChanged(oInvokeSpecialDescriptor, nInvokeSpecialDescriptor); } } else { if (!oInvokeSpecialDescriptor.equals(nInvokeSpecialDescriptor)) { md.setInvokespecialChanged(oInvokeSpecialDescriptor, nInvokeSpecialDescriptor); } } if (codeChange) { md.setCodeChanged(oInstructions.toArray(), nInstructions.toArray()); } } } if (md.hasAnyChanges()) { // it needs recording td.addChangedMethod(md); } }
From source file:org.teavm.parsing.ProgramParser.java
License:Apache License
private void prepare(MethodNode method) { InsnList instructions = method.instructions; minLocal = 0;//from w w w . j a v a2 s . c o m if ((method.access & Opcodes.ACC_STATIC) != 0) { minLocal = 1; } labelIndexes = new HashMap<>(); lineNumbers = new HashMap<>(); for (int i = 0; i < instructions.size(); ++i) { AbstractInsnNode node = instructions.get(i); if (node instanceof LabelNode) { labelIndexes.put(((LabelNode) node).getLabel(), i); } if (node instanceof LineNumberNode) { LineNumberNode lineNumberNode = (LineNumberNode) node; lineNumbers.put(lineNumberNode.start.getLabel(), lineNumberNode.line); } } for (LocalVariableNode localVar : method.localVariables) { int location = labelIndexes.get(localVar.start.getLabel()); List<LocalVariableNode> vars = localVariableMap.get(location); if (vars == null) { vars = new ArrayList<>(); localVariableMap.put(location, vars); } vars.add(localVar); } targetInstructions = new ArrayList<>(instructions.size()); targetInstructions.addAll(Collections.nCopies(instructions.size(), null)); basicBlocks.addAll(Collections.nCopies(instructions.size(), null)); stackBefore = new StackFrame[instructions.size()]; stackAfter = new StackFrame[instructions.size()]; }
From source file:org.teavm.parsing.ProgramParser.java
License:Apache License
private void doAnalyze(MethodNode method) { InsnList instructions = method.instructions; Deque<Step> workStack = new ArrayDeque<>(); for (Object obj : method.tryCatchBlocks) { TryCatchBlockNode tryCatchNode = (TryCatchBlockNode) obj; if (tryCatchNode.start == tryCatchNode.handler) { continue; }/*from w ww. j a v a2 s . c o m*/ workStack.push(new Step(-2, labelIndexes.get(tryCatchNode.handler.getLabel()))); } workStack.push(new Step(-1, 0)); while (!workStack.isEmpty()) { Step step = workStack.pop(); index = step.target; if (stackBefore[index] != null) { continue; } switch (step.source) { case -1: stack = new StackFrame(minLocal + method.maxLocals - 1); break; case -2: stack = new StackFrame(minLocal + method.maxLocals - 1); pushSingle(); break; default: stack = stackAfter[step.source]; break; } stackBefore[index] = stack; nextIndexes = new int[] { index + 1 }; instructions.get(index).accept(methodVisitor); stackAfter[index] = stack; flushInstructions(); if (nextIndexes.length != 1) { emitNextBasicBlock(); } for (int next : nextIndexes) { workStack.push(new Step(index, next)); } } for (Object obj : method.tryCatchBlocks) { TryCatchBlockNode tryCatchNode = (TryCatchBlockNode) obj; if (tryCatchNode.start == tryCatchNode.handler) { continue; } int start = labelIndexes.get(tryCatchNode.start.getLabel()); int end = labelIndexes.get(tryCatchNode.end.getLabel()); getBasicBlock(start); getBasicBlock(end); for (int i = start; i < end; ++i) { BasicBlock block = basicBlocks.get(i); if (block != null) { TryCatchBlock tryCatch = new TryCatchBlock(); if (tryCatchNode.type != null) { tryCatch.setExceptionType(tryCatchNode.type.replace('/', '.')); } tryCatch.setHandler(getBasicBlock(labelIndexes.get(tryCatchNode.handler.getLabel()))); tryCatch.setExceptionVariable(getVariable(minLocal + method.maxLocals)); block.getTryCatchBlocks().add(tryCatch); } } } }
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 www .j ava 2 s. c om*/ 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:works.cirno.mocha.parameter.name.ASMParameterAnalyzer.java
License:Open Source License
@Override @SuppressWarnings("unchecked") public Parameter[] getParameters(InvokeTarget target, Parameter[] parameters) { if (!enabled) { return parameters; }/*from w w w . j ava 2 s. com*/ Class<?> controllerClass = target.getControllerClass(); Method method = target.getMethod(); String methodName = method.getName(); Class<?>[] parameterTypes = method.getParameterTypes(); int parameterCount = parameterTypes.length; // /////////Resolve parameter names by asm { if (log.isDebugEnabled()) { log.debug("Analyzing method {}.{}", controllerClass.getName(), method.getName()); } ClassNode node = classNodeCache.get(controllerClass); if (node == null) { String name = controllerClass.getName(); { int idx = name.lastIndexOf('.'); if (idx > 0) { name = name.substring(idx + 1); } } try (InputStream is = controllerClass.getResourceAsStream(name + ".class")) { if (is == null) { throw new FileNotFoundException(name + ".class"); } ClassReader cr = new ClassReader(is); node = new ClassNode(); cr.accept(node, ClassReader.SKIP_FRAMES); classNodeCache.put(controllerClass, node); } catch (IOException e) { log.warn("Can't read bytecode of class " + name); return null; } } if (parameters == null) { parameters = new Parameter[parameterCount]; } else if (parameters.length != parameterCount) { throw new IllegalArgumentException( "Input parameters' length is different than parameters of target"); } boolean methodNodeGot = false; for (MethodNode m : (List<MethodNode>) node.methods) { if (methodName.equals(m.name)) { String[] names = new String[parameterCount]; // do it { IdentityHashMap<LabelNode, Integer> labelPosMap = new IdentityHashMap<>(); int pos = 0; InsnList il = m.instructions; for (int i = 0, max = il.size(); i < max; i++) { AbstractInsnNode ain = il.get(i); if (ain.getType() == AbstractInsnNode.LABEL) { LabelNode label = (LabelNode) ain; labelPosMap.put(label, pos++); } } int[] poses = new int[parameterCount]; for (int i = 0; i < parameterCount; i++) { poses[i] = Integer.MAX_VALUE; } for (LocalVariableNode lvn : (List<LocalVariableNode>) m.localVariables) { if (lvn.index > 0 && lvn.index <= parameterCount) { int idx = lvn.index - 1; int startPos = labelPosMap.get(lvn.start); if (poses[idx] > startPos) { poses[idx] = startPos; names[idx] = lvn.name; } } } } if (log.isDebugEnabled()) { log.debug("Method {}.{} has parameter: {}", controllerClass.getName(), method.getName(), Arrays.toString(names)); } for (int i = 0; i < parameterCount; i++) { if (parameters[i] == null || parameters[i].getName() == null) { parameters[i] = new Parameter(names[i], parameterTypes[i]); } } methodNodeGot = true; break; } } if (!methodNodeGot) { throw new IllegalStateException("Can't get method " + method.getName() + " from ASM"); } return parameters; } }