public boolean merge(final Subroutine subroutine) throws AnalyzerException { boolean changes = false; for (int i = 0; i < access.length; ++i) { if (subroutine.access[i] && !access[i]) { access[i] = true; changes = true; } } if (subroutine.start == start) { for (int i = 0; i < subroutine.callers.size(); ++i) { JumpInsnNode caller = subroutine.callers.get(i); if (!callers.contains(caller)) { callers.add(caller); changes = true; } } } return changes; }
@Override public void visit(Branch.Condition.Nil cond) { assert (destLabel != null); il.add(new VarInsnNode(ALOAD, slot(cond.addr()))); if (!isSub() || resolver.isLocalLabel(destLabel)) { // local jump il.add(new JumpInsnNode(IFNULL, l(destLabel))); } else { // non-local jump LabelNode l_nojump = new LabelNode(); il.add(new JumpInsnNode(IFNONNULL, l_nojump)); il.add(_nonLocalGoto(destLabel)); il.add(l_nojump); il.add(new FrameNode(F_SAME, 0, null, 0, null)); } }
@Override public void visit(Branch.Condition.Bool cond) { assert (destLabel != null); il.add(new VarInsnNode(ALOAD, slot(cond.addr()))); il.add(ConversionMethods.booleanValueOf()); if (!isSub() || resolver.isLocalLabel(destLabel)) { // local jump il.add(new JumpInsnNode(cond.expected() ? IFNE : IFEQ, l(destLabel))); } else { // non-local jump LabelNode l_nojump = new LabelNode(); il.add(new JumpInsnNode(cond.expected() ? IFEQ : IFNE, l_nojump)); il.add(_nonLocalGoto(destLabel)); il.add(l_nojump); il.add(new FrameNode(F_SAME, 0, null, 0, null)); } }
@Override public void visit(Branch.Condition.NumLoopEnd cond) { assert (destLabel != null); il.add(new VarInsnNode(ALOAD, slot(cond.var()))); il.add(new TypeInsnNode(CHECKCAST, Type.getInternalName(Number.class))); il.add(new VarInsnNode(ALOAD, slot(cond.limit()))); il.add(new TypeInsnNode(CHECKCAST, Type.getInternalName(Number.class))); il.add(new VarInsnNode(ALOAD, slot(cond.step()))); il.add(new TypeInsnNode(CHECKCAST, Type.getInternalName(Number.class))); il.add(DispatchMethods.continueLoop()); if (!isSub() || resolver.isLocalLabel(destLabel)) { // local jump il.add(new JumpInsnNode(IFEQ, l(destLabel))); } else { // non-local jump LabelNode l_nojump = new LabelNode(); il.add(new JumpInsnNode(IFNE, l_nojump)); il.add(_nonLocalGoto(destLabel)); il.add(l_nojump); il.add(new FrameNode(F_SAME, 0, null, 0, null)); } }
@Override public Iterator<AbstractInsnNode> iterator() { return new Iterator<AbstractInsnNode>() { private int index = 0; @Override public boolean hasNext() { return index < insns.size(); } @Override public AbstractInsnNode next() { AbstractInsnNode insn = insns.get(index++); return insn.getOpcode() == GOTO ? insns.get( insns.indexOf(((JumpInsnNode) insn).label) ).getNext() : insn; } @Override public void remove() { insns.remove(insns.get(index)); } }; }
private byte[] transformPlayer(byte[] bytes) { ClassNode clazz = ASMHelper.createClassNode(bytes); MethodNode method = ASMHelper.findMethod(clazz, ASMNames.MD_PLAYER_UPDATE); InsnList needle = new InsnList(); needle.add(new VarInsnNode(Opcodes.ALOAD, 0)); needle.add(ASMHelper.getFieldInsnNode(Opcodes.GETFIELD, ASMNames.FD_PLAYER_WORLD_OBJ)); needle.add(ASMHelper.getMethodInsnNode(Opcodes.INVOKEVIRTUAL, ASMNames.MD_WORLD_IS_DAY, false)); LabelNode l2 = new LabelNode(); needle.add(new JumpInsnNode(Opcodes.IFEQ, l2)); AbstractInsnNode insertPoint = ASMHelper.findFirstNodeFromNeedle(method.instructions, needle); method.instructions.remove(insertPoint.getNext().getNext()); method.instructions.set(insertPoint.getNext(), ASMHelper.getMethodInsnNode(Opcodes.INVOKESTATIC, ASMNames.MD_RM_HELPER_SLEEP_PLAEYR, false)); return ASMHelper.createBytes(clazz, ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); }
private void patchMenu(ClassNode node) { Logger.Info("Patching menu (" + node.name + ".class)"); Iterator<MethodNode> methodNodeList = node.methods.iterator(); while (methodNodeList.hasNext()) { MethodNode methodNode = methodNodeList.next(); // Menu swap hook if (methodNode.name.equals("e") && methodNode.desc.equals("(II)V")) { AbstractInsnNode first = methodNode.instructions.getFirst(); LabelNode label = new LabelNode(); methodNode.instructions.insertBefore(first, new VarInsnNode(Opcodes.ALOAD, 0)); methodNode.instructions.insertBefore(first, new MethodInsnNode(Opcodes.INVOKESTATIC, "Game/Menu", "switchList", "(Ljava/lang/Object;)Z")); methodNode.instructions.insertBefore(first, new JumpInsnNode(Opcodes.IFGT, label)); methodNode.instructions.insertBefore(first, new InsnNode(Opcodes.RETURN)); methodNode.instructions.insertBefore(first, label); } } }
@Override public boolean matches(ClassMethod method) { List<String> visitedLabels = new ArrayList<>(); AbstractInsnNode[] instructions = method.instructions().toArray(); for (AbstractInsnNode insn : instructions) { if (insn instanceof JumpInsnNode) { Label label = ((JumpInsnNode) insn).label.getLabel(); String labelString = label.toString(); if (visitedLabels.contains(labelString)) { return true; } else { visitedLabels.add(labelString); } } } return false; }
/** * Gets the path that branches to a true value. * * @return The path that branches to a true value. */ public Optional<BasicBlock> trueBranch() { if (successors.size() == 1) { return Optional.of(successors.get(0)); } BasicInstruction endInsn = exit(); if (endInsn.insn instanceof JumpInsnNode) { LabelNode label = ((JumpInsnNode) endInsn.insn).label; for (BasicBlock successor : successors) { BasicInstruction startInsn = successor.entry(); if (startInsn != null && label == startInsn.insn) { return Optional.of(successor); } } } return Optional.empty(); }
@Override public InsnList build(MethodContext context) { Type returnType = context.getResultType(); InsnList insnList = new InsnList(); LabelNode continueLabel = new LabelNode(); insnList.add(new InsnNode(DUP)); insnList.add(new FieldInsnNode(GETSTATIC, Type.getInternalName(clazz), field, Type.getDescriptor(Object.class))); insnList.add(new JumpInsnNode(IF_ACMPEQ, continueLabel)); if (returnType.getSize() == 0) { insnList.add(new InsnNode(POP)); insnList.add(new InsnNode(RETURN)); } else if (isPrimitive(returnType)) { insnList.add(new UnboxPrimitives(returnType).build(context)); insnList.add(new InsnNode(returnType.getOpcode(IRETURN))); } else { insnList.add(new TypeInsnNode(CHECKCAST, returnType.getInternalName())); insnList.add(new InsnNode(ARETURN)); } insnList.add(continueLabel); insnList.add(new InsnNode(POP)); return insnList; }
private void transformDamageItem(MethodNode method) { InsnList postEvent = new InsnList(); LabelNode label = new LabelNode(new Label()); postEvent.add(new TypeInsnNode(Opcodes.NEW, DAMAGE_ITEM_EVENT.getInternalName())); postEvent.add(new InsnNode(Opcodes.DUP)); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 2)); postEvent.add(new VarInsnNode(Opcodes.ILOAD, 1)); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 0)); postEvent.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, DAMAGE_ITEM_EVENT_INIT.getOwnerInternalName(), DAMAGE_ITEM_EVENT_INIT.getEnvName(), DAMAGE_ITEM_EVENT_INIT.getDesc(), false)); postEvent.add(new VarInsnNode(Opcodes.ASTORE, 3)); postEvent.add(new FieldInsnNode(Opcodes.GETSTATIC, EVENTHANDLER_DAMAGE_ITEM.getOwnerInternalName(), EVENTHANDLER_DAMAGE_ITEM.getEnvName(), EVENTHANDLER_DAMAGE_ITEM.getDesc())); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 3)); postEvent.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, POST.getOwnerInternalName(), POST.getEnvName(), POST.getDesc(), false)); postEvent.add(new JumpInsnNode(Opcodes.IFEQ, label)); postEvent.add(new InsnNode(Opcodes.RETURN)); postEvent.add(label); postEvent.add(new FrameNode(Opcodes.F_APPEND, 1, new Object[] {DAMAGE_ITEM_EVENT.getInternalName()}, 0, null)); postEvent.add(new VarInsnNode(Opcodes.ALOAD, 3)); postEvent.add(new FieldInsnNode(Opcodes.GETFIELD, DAMAGE.getOwnerInternalName(), DAMAGE.getEnvName(), DAMAGE.getDesc())); postEvent.add(new VarInsnNode(Opcodes.ISTORE, 1)); method.instructions.insert(postEvent); }
private void transformAddPrefix(ClassNode cnode) { ObfMapping mapping = new ObfMapping("net/minecraftforge/fml/common/registry/GameData", "addPrefix", "(Ljava/lang/String;)Ljava/lang/String;"); MethodNode method = ASMHelper.findMethod(mapping, cnode); if (method == null) { throw new IllegalStateException("[NOVA] Lookup " + mapping + " failed!"); } Game.logger().info("Transforming method {}", method.name); @SuppressWarnings("unchecked") JumpInsnNode prev = (JumpInsnNode) method.instructions.get(49); InsnList list = new InsnList(); list.add(new VarInsnNode(ALOAD, 4)); list.add(new MethodInsnNode(INVOKESTATIC, "nova/core/wrapper/mc/forge/v18/asm/StaticForwarder", "isNovaPrefix", "(Ljava/lang/String;)Z", false)); list.add(new JumpInsnNode(IFNE, prev.label)); method.instructions.insert(prev, list); Game.logger().info("Injected instruction to method: {}", method.name); }
private void transformAddPrefix(ClassNode cnode) { ObfMapping mapping = new ObfMapping("cpw/mods/fml/common/registry/GameData", "addPrefix", "(Ljava/lang/String;)Ljava/lang/String;"); MethodNode method = ASMHelper.findMethod(mapping, cnode); if (method == null) { throw new IllegalStateException("[NOVA] Lookup " + mapping + " failed!"); } Game.logger().info("Transforming method {}", method.name); @SuppressWarnings("unchecked") JumpInsnNode prev = (JumpInsnNode) method.instructions.get(49); InsnList list = new InsnList(); list.add(new VarInsnNode(ALOAD, 4)); list.add(new MethodInsnNode(INVOKESTATIC, "nova/core/wrapper/mc/forge/v17/asm/StaticForwarder", "isNovaPrefix", "(Ljava/lang/String;)Z", false)); list.add(new JumpInsnNode(IFNE, prev.label)); method.instructions.insert(prev, list); Game.logger().info("Injected instruction to method: {}", method.name); }
private static Set<AbstractInsnNode> findJumpTargets(final InsnList instructions) { final Set<AbstractInsnNode> jumpTargets = new HashSet<AbstractInsnNode>(); final ListIterator<AbstractInsnNode> it = instructions.iterator(); while (it.hasNext()) { final AbstractInsnNode o = it.next(); if (o instanceof JumpInsnNode) { jumpTargets.add(((JumpInsnNode) o).label); } else if (o instanceof TableSwitchInsnNode) { final TableSwitchInsnNode twn = (TableSwitchInsnNode) o; jumpTargets.add(twn.dflt); jumpTargets.addAll(twn.labels); } else if (o instanceof LookupSwitchInsnNode) { final LookupSwitchInsnNode lsn = (LookupSwitchInsnNode) o; jumpTargets.add(lsn.dflt); jumpTargets.addAll(lsn.labels); } } return jumpTargets; }
/** * Insert a call to the isNull helper function * * @param opcode * @param position * @param list */ public void insertPushNull(int opcode, JumpInsnNode position, InsnList list) { int branchId = getBranchID(currentMethodNode, position); logger.info("Inserting instrumentation for NULL check at branch " + branchId + " in method " + currentMethodNode.name); MethodInsnNode nullCheck = new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(BooleanHelper.class), "isNull", Type.getMethodDescriptor(Type.INT_TYPE, new Type[] { Type.getType(Object.class), Type.INT_TYPE }), false); list.insertBefore(position, new InsnNode(Opcodes.DUP)); list.insertBefore(position, new LdcInsnNode(opcode)); list.insertBefore(position, nullCheck); //list.insertBefore(position, // new LdcInsnNode(getBranchID(currentMethodNode, position))); insertBranchIdPlaceholder(currentMethodNode, position, branchId); MethodInsnNode push = new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(BooleanHelper.class), "pushPredicate", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { Type.INT_TYPE, Type.INT_TYPE }), false); list.insertBefore(position, push); }
/** * Insert a call to the reference equality check helper function * * @param opcode * @param position * @param list */ public void insertPushEquals(int opcode, JumpInsnNode position, InsnList list) { MethodInsnNode equalCheck = new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(BooleanHelper.class), "isEqual", Type.getMethodDescriptor(Type.INT_TYPE, new Type[] { Type.getType(Object.class), Type.getType(Object.class), Type.INT_TYPE }), false); list.insertBefore(position, new InsnNode(Opcodes.DUP2)); list.insertBefore(position, new LdcInsnNode(opcode)); list.insertBefore(position, equalCheck); //list.insertBefore(position, // new LdcInsnNode(getBranchID(currentMethodNode, position))); insertBranchIdPlaceholder(currentMethodNode, position); MethodInsnNode push = new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(BooleanHelper.class), "pushPredicate", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { Type.INT_TYPE, Type.INT_TYPE }), false); list.insertBefore(position, push); }
/** * Insert a call to the distance function for unary comparison * * @param opcode * @param position * @param list */ public void insertPush(int opcode, JumpInsnNode position, InsnList list) { list.insertBefore(position, new InsnNode(Opcodes.DUP)); // TODO: We have to put a placeholder here instead of the actual branch ID // TODO: And then later add another transformation where we replace this with // actual branch IDs //list.insertBefore(position, // new LdcInsnNode(getBranchID(currentMethodNode, position))); insertBranchIdPlaceholder(currentMethodNode, position); MethodInsnNode push = new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(BooleanHelper.class), "pushPredicate", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { Type.INT_TYPE, Type.INT_TYPE }), false); list.insertBefore(position, push); }
/** * Insert a call to the distance function for binary comparison * * @param opcode * @param position * @param list */ public void insertPush2(int opcode, JumpInsnNode position, InsnList list) { list.insertBefore(position, new InsnNode(Opcodes.DUP2)); //list.insertBefore(position, new InsnNode(Opcodes.ISUB)); MethodInsnNode sub = new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(BooleanHelper.class), "intSub", Type.getMethodDescriptor(Type.INT_TYPE, new Type[] { Type.INT_TYPE, Type.INT_TYPE }), false); list.insertBefore(position, sub); insertBranchIdPlaceholder(currentMethodNode, position); // list.insertBefore(position, // new LdcInsnNode(getBranchID(currentMethodNode, position))); MethodInsnNode push = new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(BooleanHelper.class), "pushPredicate", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { Type.INT_TYPE, Type.INT_TYPE }), false); list.insertBefore(position, push); }
/** * <p> * addDefaultCaseInstrumentation * </p> * * @param v * a {@link org.evosuite.graphs.cfg.BytecodeInstruction} object. * @param instrumentation * a {@link org.objectweb.asm.tree.InsnList} object. * @param mySwitch * a {@link org.objectweb.asm.tree.AbstractInsnNode} object. * @param defaultLabel * a {@link org.objectweb.asm.tree.LabelNode} object. * @param caseLabel * a {@link org.objectweb.asm.tree.LabelNode} object. * @param endLabel * a {@link org.objectweb.asm.tree.LabelNode} object. */ protected void addDefaultCaseInstrumentation(BytecodeInstruction v, InsnList instrumentation, AbstractInsnNode mySwitch, LabelNode defaultLabel, LabelNode caseLabel, LabelNode endLabel) { int defaultCaseBranchId = BranchPool.getInstance(classLoader).getDefaultBranchForSwitch(v).getActualBranchId(); // add helper switch instrumentation.add(new InsnNode(Opcodes.DUP)); instrumentation.add(mySwitch); // add call for default case not covered instrumentation.add(caseLabel); addDefaultCaseNotCoveredCall(v, instrumentation, defaultCaseBranchId); // jump over default (break) instrumentation.add(new JumpInsnNode(Opcodes.GOTO, endLabel)); // add call for default case covered instrumentation.add(defaultLabel); addDefaultCaseCoveredCall(v, instrumentation, defaultCaseBranchId); instrumentation.add(endLabel); }
/** {@inheritDoc} */ @Override public List<Mutation> apply(MethodNode mn, String className, String methodName, BytecodeInstruction instruction, Frame frame) { List<Mutation> mutations = new LinkedList<Mutation>(); JumpInsnNode node = (JumpInsnNode) instruction.getASMNode(); LabelNode target = node.label; // insert mutation into bytecode with conditional JumpInsnNode mutation = new JumpInsnNode(getOpposite(node.getOpcode()), target); // insert mutation into pool Mutation mutationObject = MutationPool.addMutation(className, methodName, NAME, instruction, mutation, Mutation.getDefaultInfectionDistance()); mutations.add(mutationObject); return mutations; }
/** * Compares two integers and performs some action if the integers are equal. * @param lhs left hand side instruction list -- must leave an int on the stack * @param rhs right hand side instruction list -- must leave an int on the stack * @param action action to perform if results of {@code lhs} and {@code rhs} are equal * @return instructions instruction list to perform some action if two ints are equal * @throws NullPointerException if any argument is {@code null} */ public static InsnList ifIntegersEqual(InsnList lhs, InsnList rhs, InsnList action) { Validate.notNull(lhs); Validate.notNull(rhs); Validate.notNull(action); InsnList ret = new InsnList(); LabelNode notEqualLabelNode = new LabelNode(); ret.add(lhs); ret.add(rhs); ret.add(new JumpInsnNode(Opcodes.IF_ICMPNE, notEqualLabelNode)); ret.add(action); ret.add(notEqualLabelNode); return ret; }
/** * Compares two objects and performs some action if the objects are the same (uses == to check if same, not the equals method). * @param lhs left hand side instruction list -- must leave an object on the stack * @param rhs right hand side instruction list -- must leave an object on the stack * @param action action to perform if results of {@code lhs} and {@code rhs} are equal * @return instructions instruction list to perform some action if two objects are equal * @throws NullPointerException if any argument is {@code null} */ public static InsnList ifObjectsEqual(InsnList lhs, InsnList rhs, InsnList action) { Validate.notNull(lhs); Validate.notNull(rhs); Validate.notNull(action); InsnList ret = new InsnList(); LabelNode notEqualLabelNode = new LabelNode(); ret.add(lhs); ret.add(rhs); ret.add(new JumpInsnNode(Opcodes.IF_ACMPNE, notEqualLabelNode)); ret.add(action); ret.add(notEqualLabelNode); return ret; }
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 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); } }
/** * Builds a {@link ControlFlowStatement} from the given elements * * @param insnCursor the InsnCursor to read the execution branches * @param expressionStack the stack of expressions waiting to be used * @param capturedArguments the captured argument references, if any * @param localVariables the local variables, if any * @return an {@link ControlFlowStatement}. */ private Statement buildControlFlowStatement(final InsnCursor insnCursor, final Stack<Expression> expressionStack, final List<CapturedArgument> capturedArguments, final LocalVariables localVariables) { final JumpInsnNode jumpInsnNode = (JumpInsnNode) insnCursor.getCurrent(); final Expression comparisonExpression = getControlFlowExpression(jumpInsnNode, expressionStack); final LabelNode jumpLabel = jumpInsnNode.label; final InsnCursor thenInstructionCursor = insnCursor; final InsnCursor elseInstructionCursor = insnCursor.duplicate().next(); thenInstructionCursor.move(jumpLabel.getLabel()); // reading statements using a clean Expression stacks for both branches final List<Statement> thenStatements = readStatements(thenInstructionCursor, new Stack<Expression>(), capturedArguments, localVariables); final List<Statement> elseStatements = readStatements(elseInstructionCursor, new Stack<Expression>(), capturedArguments, localVariables); // insnCursor.move(thenInstructionCursor); return new ControlFlowStatement(comparisonExpression, thenStatements, elseStatements); }
/** * <p> * This method scans to find GoTo instruction * </p> * * @param nestingLevel * nesting level */ private void scanGoTo(int nestingLevel) { if (this.currentTarget[nestingLevel].getPrevious() instanceof JumpInsnNode && Opcodes.GOTO == this.currentTarget[nestingLevel] .getPrevious().getOpcode()) { logger.debug(InstrumentationMessageLoader .getMessage(MessageConstants.LOG_GOTO_FOUND)); this.isGoToFound[nestingLevel] = true; this.currentJIN[nestingLevel] = (JumpInsnNode) this.currentTarget[nestingLevel] .getPrevious(); this.currentTarget[nestingLevel] = this.currentJIN[nestingLevel].label; } else { logger.debug(InstrumentationMessageLoader .getMessage(MessageConstants.LOG_GOTO_NOT_FOUND)); this.isGoToFound[nestingLevel] = false; } }
/** * <p> * This method scans the instructions for 'else' and returns the node * </p> * * @param ifTargetIndex * Index of the target instruction of 'if' * @param endIndex * Index of the end instruction upto which scanner will work * @param nestingLevel * nesting level * @return Node */ private AbstractInsnNode scanForElse(int ifTargetIndex, int endIndex) { boolean lineNumberFound = false; LabelNode ln = (LabelNode) this.insnArr[ifTargetIndex]; for (int i = ifTargetIndex + 1; i <= endIndex; i++) { AbstractInsnNode ain = this.insnArr[i]; if (ain instanceof JumpInsnNode && InstrumentUtil.getJumpInsnOpcodesMap().containsKey( ain.getOpcode())) { if (!lineNumberFound) { return ain; } } else if (ain instanceof LineNumberNode) { LineNumberNode lnn = (LineNumberNode) ain; // if the line does not belong to the label if (lnn.start != ln) { lineNumberFound = true; return null; } } } return null; }
/** * <p> * This method gets the end index for the provided Jump instruction * </p> * * @param ain * The given jump node * @return int end index */ private int getEndIndexForBlock(AbstractInsnNode ain) { int retIndex = 0; if (ain instanceof JumpInsnNode) { JumpInsnNode jin = (JumpInsnNode) ain; LabelNode targetAIN = jin.label; if (targetAIN.getPrevious() instanceof JumpInsnNode && Opcodes.GOTO == targetAIN.getPrevious().getOpcode()) { retIndex = CollectionUtil.getObjectIndexInArray(this.insnArr, targetAIN .getPrevious().getPrevious()); } else { retIndex = CollectionUtil.getObjectIndexInArray(this.insnArr, targetAIN.getPrevious()); } } return retIndex; }
@Override public void visit(final WhenStatement object) { // Generated Bytecode // // <condition> // IF_FALSE @END // <statement> // @END ///////////////////////////////////////// /** * Embed the line number in the bytecode for debugging purposes. */ Utils.addLineNumber(code, object); final LabelNode END = new LabelNode(); compileCondition(object.getCondition()); code.add(new JumpInsnNode(Utils.IF_FALSE, END)); object.getBody().accept(this); code.add(END); }
@Override public void visit(final GotoStatement object) { // Generated Bytecode // // GOTO @LABEL // //////////////////////////////////// /** * Embed the line number in the bytecode for debugging purposes. */ Utils.addLineNumber(code, object); final String name = object.getLabel().getName(); final LabelNode node = function.labels.nodeOf(name); code.add(new JumpInsnNode(Opcodes.GOTO, node)); }
@Override public void visit(final BreakStatement object) { // Generated Bytecode: // // GOTO @BREAK // //////////////////////////////////////////////////// /** * Embed the line number in the bytecode for debugging purposes. */ Utils.addLineNumber(code, object); final LabelNode BREAK = break_labels.peek(); code.add(new JumpInsnNode(Opcodes.GOTO, BREAK)); }
@Override public void visit(final ContinueStatement object) { // Generated Bytecode: // // GOTO @CONTINUE // //////////////////////////////////////////////////// /** * Embed the line number in the bytecode for debugging purposes. */ Utils.addLineNumber(code, object); final LabelNode CONTINUE = continue_labels.peek(); code.add(new JumpInsnNode(Opcodes.GOTO, CONTINUE)); }