List of usage examples for org.objectweb.asm.tree TableSwitchInsnNode TableSwitchInsnNode
public TableSwitchInsnNode(final int min, final int max, final LabelNode dflt, final LabelNode... labels)
From source file:com.github.fge.grappa.transform.CodeBlock.java
License:Apache License
public CodeBlock visitTableSwitchInsn(int min, int max, LabelNode defaultHandler, LabelNode[] handlers) { instructionList.add(new TableSwitchInsnNode(min, max, defaultHandler, handlers)); return this; }
From source file:com.github.fge.grappa.transform.CodeBlock.java
License:Apache License
public CodeBlock tableswitch(int min, int max, LabelNode defaultLabel, LabelNode[] cases) { instructionList.add(new TableSwitchInsnNode(min, max, defaultLabel, cases)); return this; }
From source file:com.offbynull.coroutines.instrumenter.asm.InstructionUtils.java
License:Open Source License
/** * Generates instructions for a switch table. This does not automatically generate jumps at the end of each default/case statement. It's * your responsibility to either add the relevant jumps, throws, or returns at each default/case statement, otherwise the code will * just fall through (which is likely not what you want). * @param indexInsnList instructions to calculate the index -- must leave an int on top of the stack * @param defaultInsnList instructions to execute on default statement -- must leave the stack unchanged * @param caseStartIdx the number which the case statements start at * @param caseInsnLists instructions to execute on each case statement -- must leave the stack unchanged * @return instructions for a table switch * @throws NullPointerException if any argument is {@code null} or contains {@code null} * @throws IllegalArgumentException if any numeric argument is {@code < 0}, or if {@code caseInsnLists} is empty *///from ww w . ja v a 2s . c o m public static InsnList tableSwitch(InsnList indexInsnList, InsnList defaultInsnList, int caseStartIdx, InsnList... caseInsnLists) { Validate.notNull(defaultInsnList); Validate.notNull(indexInsnList); Validate.isTrue(caseStartIdx >= 0); Validate.notNull(caseInsnLists); Validate.noNullElements(caseInsnLists); Validate.isTrue(caseInsnLists.length > 0); InsnList ret = new InsnList(); LabelNode defaultLabelNode = new LabelNode(); LabelNode[] caseLabelNodes = new LabelNode[caseInsnLists.length]; for (int i = 0; i < caseInsnLists.length; i++) { caseLabelNodes[i] = new LabelNode(); } ret.add(indexInsnList); ret.add(new TableSwitchInsnNode(caseStartIdx, caseStartIdx + caseInsnLists.length - 1, defaultLabelNode, caseLabelNodes)); for (int i = 0; i < caseInsnLists.length; i++) { LabelNode caseLabelNode = caseLabelNodes[i]; InsnList caseInsnList = caseInsnLists[i]; if (caseInsnList != null) { ret.add(caseLabelNode); ret.add(caseInsnList); } } if (defaultInsnList != null) { ret.add(defaultLabelNode); ret.add(defaultInsnList); } return ret; }
From source file:kilim.analysis.BasicBlock.java
License:Open Source License
@SuppressWarnings("unchecked") static ArrayList<BasicBlock> dupCopyContents(boolean deepCopy, BasicBlock targetBB, BasicBlock returnToBB, HashMap<BasicBlock, BasicBlock> bbCopyMap, HashMap<Label, LabelNode> labelCopyMap) throws KilimException { ArrayList<BasicBlock> newBBs = new ArrayList<BasicBlock>(targetBB.getSubBlocks().size()); for (BasicBlock orig : targetBB.getSubBlocks()) { BasicBlock dup = bbCopyMap.get(orig); dup.flags = orig.flags;/* w ww .j a v a2 s . c om*/ dup.caughtExceptionType = orig.caughtExceptionType; dup.startPos = orig.startPos; dup.endPos = orig.endPos; dup.flow = orig.flow; dup.numPredecessors = orig.numPredecessors; dup.startFrame = null; dup.usage = orig.usage.copy(); dup.handlers = orig.handlers; if (orig.follower != null) { dup.follower = bbCopyMap.get(orig.follower); if (dup.follower == null) { assert dup.lastInstruction() == RET; } } dup.successors = new ArrayList<BasicBlock>(orig.successors.size()); if (orig.lastInstruction() == RET) { dup.addSuccessor(returnToBB); } else { for (BasicBlock s : orig.successors) { BasicBlock b = bbCopyMap.get(s); dup.addSuccessor(b); } } if (deepCopy) { MethodFlow flow = targetBB.flow; InsnList instructions = flow.instructions; // copy instructions dup.startLabel = labelCopyMap.get(orig.startLabel).getLabel(); dup.startPos = instructions.size(); dup.endPos = dup.startPos + (orig.endPos - orig.startPos); // Note: last instruction (@endPos) isn't copied in the loop. // If it has labels, a new instruction is generated; either // way the last instruction is appended separately. int newPos = instructions.size(); int end = orig.endPos; // create new labels and instructions for (int i = orig.startPos; i <= end; i++, newPos++) { Label l = flow.getLabelAt(i); if (l != null) { l = labelCopyMap.get(l).getLabel(); assert l != null; flow.setLabel(newPos, l); } if (i != end) { // last insn gets special treatment instructions.add(instructions.get(i)); } } AbstractInsnNode lastInsn = (AbstractInsnNode) instructions.get(orig.endPos); LabelNode dupLabel; int opcode = lastInsn.getOpcode(); if (lastInsn instanceof JumpInsnNode) { JumpInsnNode jin = (JumpInsnNode) lastInsn; if (lastInsn.getOpcode() != JSR) { dupLabel = labelCopyMap.get(jin.label); assert dupLabel != null; lastInsn = new JumpInsnNode(lastInsn.getOpcode(), dupLabel); } } else if (opcode == TABLESWITCH) { TableSwitchInsnNode tsin = (TableSwitchInsnNode) lastInsn; LabelNode[] labels = new LabelNode[tsin.labels.size()]; for (int i = 0; i < labels.length; i++) { dupLabel = labelCopyMap.get(tsin.labels.get(i)); assert dupLabel != null; labels[i] = dupLabel; } dupLabel = labelCopyMap.get(tsin.dflt); assert dupLabel != null; lastInsn = new TableSwitchInsnNode(tsin.min, tsin.max, dupLabel, labels); } else if (opcode == LOOKUPSWITCH) { LookupSwitchInsnNode lsin = (LookupSwitchInsnNode) lastInsn; LabelNode[] labels = new LabelNode[lsin.labels.size()]; for (int i = 0; i < labels.length; i++) { dupLabel = labelCopyMap.get(lsin.labels.get(i)); assert dupLabel != null; labels[i] = dupLabel; } dupLabel = labelCopyMap.get(lsin.dflt); assert dupLabel != null; int[] keys = new int[lsin.keys.size()]; for (int i = 0; i < keys.length; i++) { keys[i] = (Integer) lsin.keys.get(i); } lastInsn = new LookupSwitchInsnNode(dupLabel, keys, labels); } instructions.add(lastInsn); // new handlers dup.handlers = new ArrayList<Handler>(orig.handlers.size()); if (orig.handlers.size() > 0) { for (Handler oh : orig.handlers) { Handler h = new Handler(dup.startPos + (oh.from - orig.startPos), dup.endPos + (oh.to - orig.endPos), oh.type, oh.catchBB); dup.handlers.add(h); } } } newBBs.add(dup); } return newBBs; }
From source file:me.qmx.jitescript.CodeBlock.java
License:Apache License
public CodeBlock visitTableSwitchInsn(int arg0, int arg1, LabelNode arg2, LabelNode[] arg3) { this.instructionList.add(new TableSwitchInsnNode(arg0, arg1, arg2, arg3)); return this; }
From source file:me.qmx.jitescript.CodeBlock.java
License:Apache License
public CodeBlock tableswitch(int min, int max, LabelNode defaultLabel, LabelNode[] cases) { this.instructionList.add(new TableSwitchInsnNode(min, max, defaultLabel, cases)); return this; }
From source file:net.sandius.rembulan.compiler.gen.asm.InvokeMethod.java
License:Apache License
public MethodNode methodNode() { MethodNode node = new MethodNode(ACC_PUBLIC, "invoke", context.invokeMethodType().getDescriptor(), null, runMethod.throwsExceptions()); InsnList il = node.instructions;//from ww w. jav a2 s . c om List<LocalVariableNode> locals = node.localVariables; LabelNode begin = new LabelNode(); LabelNode end = new LabelNode(); int invokeKind = context.kind(); il.add(begin); // a (slotIdx -> paramIdx) map int[] slotParamMap = new int[context.slots.numSlots()]; Arrays.fill(slotParamMap, -1); for (int paramIdx = 0; paramIdx < context.fn.params().size(); paramIdx++) { int slotIdx = context.slots.slotOf(context.fn.params().get(paramIdx)); assert (slotParamMap[slotIdx] == -1); slotParamMap[slotIdx] = paramIdx; } if (invokeKind > 0) { il.add(new VarInsnNode(ALOAD, 0)); // this il.add(new VarInsnNode(ALOAD, 1)); // context il.add(ASMUtils.loadInt(0)); // resumption point // we have (invokeKind - 1) standalone parameters, mapping them onto numSlots for (int paramIdx : slotParamMap) { if (paramIdx < 0) { // slot unused il.add(new InsnNode(ACONST_NULL)); } else { // used by the parameter #paramIdx Var param = context.fn.params().get(paramIdx); boolean reified = context.types.isReified(param); if (reified) { il.add(new TypeInsnNode(NEW, Type.getInternalName(Variable.class))); il.add(new InsnNode(DUP)); } il.add(new VarInsnNode(ALOAD, 2 + paramIdx)); if (reified) { il.add(VariableMethods.constructor()); } } } } else { // variable number of parameters, encoded in an array at position 2 int lv_varargsSize = 3; int lv_varargs = 4; int numParams = context.numOfParameters(); if (context.isVararg()) { LabelNode l_v_begin = new LabelNode(); LabelNode l_v_nonempty = new LabelNode(); LabelNode l_v_empty = new LabelNode(); LabelNode l_v_done = new LabelNode(); il.add(new VarInsnNode(ALOAD, 2)); il.add(new InsnNode(ARRAYLENGTH)); if (numParams > 0) { il.add(ASMUtils.loadInt(context.numOfParameters())); il.add(new InsnNode(ISUB)); } il.add(new VarInsnNode(ISTORE, lv_varargsSize)); il.add(l_v_begin); il.add(new VarInsnNode(ILOAD, lv_varargsSize)); il.add(new JumpInsnNode(IFLE, l_v_empty)); // nonempty varargs // varargs = new Object[varargsSize]; il.add(new VarInsnNode(ILOAD, lv_varargsSize)); il.add(new TypeInsnNode(ANEWARRAY, Type.getInternalName(Object.class))); il.add(new VarInsnNode(ASTORE, lv_varargs)); il.add(l_v_nonempty); // call System.arraycopy(src, srcPos, dest, destPos, len) il.add(new VarInsnNode(ALOAD, 2)); // src il.add(ASMUtils.loadInt(numParams)); // srcPos il.add(new VarInsnNode(ALOAD, lv_varargs)); // dest il.add(ASMUtils.loadInt(0)); // destPos il.add(new VarInsnNode(ILOAD, lv_varargsSize)); // len il.add(new MethodInsnNode(INVOKESTATIC, Type.getInternalName(System.class), "arraycopy", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object.class), Type.INT_TYPE, Type.getType(Object.class), Type.INT_TYPE, Type.INT_TYPE), false)); il.add(new JumpInsnNode(GOTO, l_v_done)); // empty varargs il.add(l_v_empty); il.add(new FrameNode(F_APPEND, 1, new Object[] { Opcodes.INTEGER }, 0, null)); // varargs = new Object[0]; il.add(ASMUtils.loadInt(0)); il.add(new TypeInsnNode(ANEWARRAY, Type.getInternalName(Object.class))); il.add(new VarInsnNode(ASTORE, lv_varargs)); il.add(l_v_done); il.add(new FrameNode(F_APPEND, 1, new Object[] { ASMUtils.arrayTypeFor(Object.class).getInternalName() }, 0, null)); locals.add(new LocalVariableNode("sz", Type.INT_TYPE.getDescriptor(), null, l_v_begin, end, lv_varargsSize)); locals.add(new LocalVariableNode("varargs", ASMUtils.arrayTypeFor(Object.class).getDescriptor(), null, l_v_nonempty, l_v_empty, lv_varargs)); locals.add(new LocalVariableNode("varargs", ASMUtils.arrayTypeFor(Object.class).getDescriptor(), null, l_v_done, end, lv_varargs)); } // load #numOfParameters, mapping them onto #numOfRegisters int lv_param_offset = context.isVararg() ? lv_varargs + 1 : lv_varargsSize; if (numParams > 0) { // initialise parameter slot variables to null for (int i = 0; i < numParams; i++) { LabelNode l = new LabelNode(); int lv = lv_param_offset + i; il.add(new InsnNode(ACONST_NULL)); il.add(new VarInsnNode(ASTORE, lv)); il.add(l); il.add(new FrameNode(F_APPEND, 1, new Object[] { Type.getInternalName(Object.class) }, 0, null)); locals.add( new LocalVariableNode("arg_" + i, Type.getDescriptor(Object.class), null, l, end, lv)); } // insert switch for filling parameter slots LabelNode[] l_s_table = new LabelNode[numParams + 1]; for (int i = 0; i < numParams + 1; i++) { l_s_table[i] = new LabelNode(); } il.add(new VarInsnNode(ALOAD, 2)); il.add(new InsnNode(ARRAYLENGTH)); il.add(new TableSwitchInsnNode(0, numParams, l_s_table[numParams], l_s_table)); for (int i = numParams; i >= 0; i--) { // length of args is at least i; may assign into param (i - 1) int paramIdx = i - 1; il.add(l_s_table[i]); il.add(new FrameNode(F_SAME, 0, null, 0, null)); if (paramIdx >= 0) { // assign into param #paramIdx il.add(new VarInsnNode(ALOAD, 2)); il.add(ASMUtils.loadInt(paramIdx)); il.add(new InsnNode(AALOAD)); il.add(new VarInsnNode(ASTORE, lv_param_offset + paramIdx)); } } } // now assemble the run() method invocation, filling in nulls for non-parameter slots il.add(new VarInsnNode(ALOAD, 0)); // this il.add(new VarInsnNode(ALOAD, 1)); // context il.add(ASMUtils.loadInt(0)); // resumption point if (context.isVararg()) { il.add(new VarInsnNode(ALOAD, lv_varargs)); } for (int paramIdx : slotParamMap) { if (paramIdx < 0) { // slot not used by a parameter il.add(new InsnNode(ACONST_NULL)); } else { // slot is parameter #paramIdx Var param = context.fn.params().get(paramIdx); boolean reified = context.types.isReified(param); if (reified) { il.add(new TypeInsnNode(NEW, Type.getInternalName(Variable.class))); il.add(new InsnNode(DUP)); } il.add(new VarInsnNode(ALOAD, lv_param_offset + paramIdx)); if (reified) { il.add(VariableMethods.constructor()); } } } } il.add(runMethod.methodInvokeInsn()); il.add(new InsnNode(RETURN)); il.add(end); locals.add(new LocalVariableNode("this", context.thisClassType().getDescriptor(), null, begin, end, 0)); locals.add( new LocalVariableNode("context", Type.getDescriptor(ExecutionContext.class), null, begin, end, 1)); if (invokeKind > 0) { for (int i = 0; i < invokeKind; i++) { locals.add(new LocalVariableNode("arg_" + i, Type.getDescriptor(Object.class), null, begin, end, 2 + i)); } // TODO: maxLocals, maxStack } else { locals.add(new LocalVariableNode("args", ASMUtils.arrayTypeFor(Object.class).getDescriptor(), null, begin, end, 2)); // TODO: maxLocals, maxStack } return node; }
From source file:net.sandius.rembulan.compiler.gen.asm.RunMethod.java
License:Apache License
private InsnList dispatchTable(List<LabelNode> extLabels, List<LabelNode> resumptionLabels, LabelNode errorStateLabel) {/*from w w w. j a va 2 s .co m*/ InsnList il = new InsnList(); assert (!extLabels.isEmpty()); ArrayList<LabelNode> labels = new ArrayList<>(); labels.addAll(extLabels); labels.addAll(resumptionLabels); LabelNode[] labelArray = labels.toArray(new LabelNode[labels.size()]); int min = 1 - extLabels.size(); int max = resumptionLabels.size(); il.add(new VarInsnNode(ILOAD, LV_RESUME)); il.add(new TableSwitchInsnNode(min, max, errorStateLabel, labelArray)); return il; }
From source file:net.sandius.rembulan.compiler.gen.asm.RunMethod.java
License:Apache License
private MethodNode emitSegmentedRunMethod(int numOfSegments) { MethodNode node = new MethodNode(ACC_PRIVATE, methodName(), methodType().getDescriptor(), null, throwsExceptions());//ww w . j a v a 2 s . co m InsnList il = node.instructions; int lvOffset = slotOffset() + numOfRegisters(); int lv_rpp = lvOffset + 0; int lv_methodIdx = lvOffset + 1; int lv_jmpIdx = lvOffset + 2; int lv_stateIdx = lvOffset + 3; int lv_savedState = lvOffset + 4; LabelNode l_top = new LabelNode(); LabelNode l_ret = new LabelNode(); LabelNode l_end = new LabelNode(); LabelNode l_rpp = new LabelNode(); LabelNode l_methodIdx = new LabelNode(); LabelNode l_jmpIdx = new LabelNode(); LabelNode l_stateIdx = new LabelNode(); LabelNode l_savedState = new LabelNode(); il.add(l_top); il.add(new FrameNode(F_SAME, 0, null, 0, null)); // rpp = rp & ((1 << ST_SHIFT_SEGMENT) - 1) il.add(new VarInsnNode(ILOAD, LV_RESUME)); il.add(ASMUtils.loadInt((1 << ST_SHIFT_SEGMENT) - 1)); il.add(new InsnNode(IAND)); il.add(new VarInsnNode(ISTORE, lv_rpp)); il.add(l_rpp); il.add(new FrameNode(F_APPEND, 1, new Object[] { Opcodes.INTEGER }, 0, null)); // methodIdx = rp >>> ST_SHIFT_SEGMENT il.add(new VarInsnNode(ILOAD, LV_RESUME)); il.add(ASMUtils.loadInt(ST_SHIFT_SEGMENT)); il.add(new InsnNode(IUSHR)); il.add(new VarInsnNode(ISTORE, lv_methodIdx)); il.add(l_methodIdx); il.add(new FrameNode(F_APPEND, 1, new Object[] { Opcodes.INTEGER }, 0, null)); // jmpIdx = rpp >>> ST_SHIFT_LABELIDX il.add(new VarInsnNode(ILOAD, lv_rpp)); il.add(ASMUtils.loadInt(ST_SHIFT_LABELIDX)); il.add(new InsnNode(IUSHR)); il.add(new VarInsnNode(ISTORE, lv_jmpIdx)); il.add(l_jmpIdx); il.add(new FrameNode(F_APPEND, 1, new Object[] { Opcodes.INTEGER }, 0, null)); // stateIdx = (rp & ((1 << ST_SHIFT_LABELIDX) - 1)) - jmpIdx il.add(new VarInsnNode(ILOAD, LV_RESUME)); il.add(ASMUtils.loadInt((1 << ST_SHIFT_LABELIDX) - 1)); il.add(new InsnNode(IAND)); il.add(new VarInsnNode(ILOAD, lv_jmpIdx)); il.add(new InsnNode(ISUB)); il.add(new VarInsnNode(ISTORE, lv_stateIdx)); il.add(l_stateIdx); il.add(new FrameNode(F_APPEND, 1, new Object[] { Opcodes.INTEGER }, 0, null)); // savedState = null il.add(new InsnNode(ACONST_NULL)); il.add(new VarInsnNode(ASTORE, lv_savedState)); il.add(l_savedState); il.add(new FrameNode(F_APPEND, 1, new Object[] { context.savedStateClassType().getInternalName() }, 0, null)); // switch on methodIdx LabelNode l_after = new LabelNode(); LabelNode l_error = new LabelNode(); LabelNode[] l_invokes = new LabelNode[numOfSegments]; for (int i = 0; i < numOfSegments; i++) { l_invokes[i] = new LabelNode(); } il.add(new VarInsnNode(ILOAD, lv_methodIdx)); il.add(new TableSwitchInsnNode(0, numOfSegments - 1, l_error, l_invokes)); for (int i = 0; i < numOfSegments; i++) { il.add(l_invokes[i]); il.add(new FrameNode(F_SAME, 0, null, 0, null)); // push arguments to stack il.add(new VarInsnNode(ALOAD, 0)); il.add(new VarInsnNode(ALOAD, LV_CONTEXT)); il.add(new VarInsnNode(ILOAD, lv_stateIdx)); // pass stateIdx to the sub-method if (context.isVararg()) { il.add(new VarInsnNode(ALOAD, LV_VARARGS)); } for (int j = 0; j < numOfRegisters(); j++) { il.add(new VarInsnNode(ALOAD, slotOffset() + j)); } il.add(new MethodInsnNode(INVOKESPECIAL, context.thisClassType().getInternalName(), subRunMethodName(i), subMethodType().getDescriptor(), false)); il.add(new VarInsnNode(ASTORE, lv_savedState)); il.add(new JumpInsnNode(GOTO, l_after)); } // error state il.add(errorState(l_error)); il.add(l_after); il.add(new FrameNode(F_SAME, 0, null, 0, null)); il.add(new VarInsnNode(ALOAD, lv_savedState)); il.add(new JumpInsnNode(IFNULL, l_ret)); // savedState == null ? // continuing: savedState != null // FIXME: taken from ResumeMethod -- beware of code duplication! il.add(new VarInsnNode(ALOAD, lv_savedState)); // saved state il.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(DefaultSavedState.class), "resumptionPoint", Type.getMethodDescriptor(Type.INT_TYPE), false)); // resumption point il.add(new VarInsnNode(ISTORE, LV_RESUME)); // registers if (context.isVararg() || numOfRegisters() > 0) { il.add(new VarInsnNode(ALOAD, lv_savedState)); il.add(new MethodInsnNode(INVOKEVIRTUAL, Type.getInternalName(DefaultSavedState.class), "registers", Type.getMethodDescriptor(ASMUtils.arrayTypeFor(Object.class)), false)); int numRegs = numOfRegisters() + (context.isVararg() ? 1 : 0); for (int i = 0; i < numRegs; i++) { if (i + 1 < numRegs) { il.add(new InsnNode(DUP)); } il.add(ASMUtils.loadInt(i)); il.add(new InsnNode(AALOAD)); if (i == 0 && context.isVararg()) { il.add(new TypeInsnNode(CHECKCAST, ASMUtils.arrayTypeFor(Object.class).getInternalName())); } il.add(new VarInsnNode(ASTORE, LV_VARARGS + i)); } } // loop back to the beginning il.add(new JumpInsnNode(GOTO, l_top)); // got a null, that's the end il.add(l_ret); il.add(new FrameNode(F_SAME, 0, null, 0, null)); il.add(new InsnNode(RETURN)); il.add(l_end); // add local variables node.localVariables.addAll(baseLocals(l_top, l_end)); node.localVariables .add(new LocalVariableNode("rpp", Type.INT_TYPE.getDescriptor(), null, l_rpp, l_ret, lv_rpp)); node.localVariables.add(new LocalVariableNode("methodIdx", Type.INT_TYPE.getDescriptor(), null, l_methodIdx, l_ret, lv_methodIdx)); node.localVariables.add( new LocalVariableNode("jmpIdx", Type.INT_TYPE.getDescriptor(), null, l_jmpIdx, l_ret, lv_jmpIdx)); node.localVariables.add(new LocalVariableNode("stateIdx", Type.INT_TYPE.getDescriptor(), null, l_stateIdx, l_ret, lv_stateIdx)); node.localVariables.add(new LocalVariableNode("savedState", context.savedStateClassType().getDescriptor(), null, l_savedState, l_ret, lv_savedState)); return node; }
From source file:net.sourceforge.cobertura.instrument.HistoryMethodAdapter.java
License:GNU General Public License
@Override public void visitTableSwitchInsn(int arg0, int arg1, Label arg2, Label[] arg3) { super.visitTableSwitchInsn(arg0, arg1, arg2, arg3); LabelNode nodes[] = new LabelNode[arg3.length]; for (int i = 0; i < arg3.length; i++) { nodes[i] = new LabelNode(arg3[i]); }/* ww w. j a v a2 s . c o m*/ appendToBacklog(new TableSwitchInsnNode(arg0, arg1, new LabelNode(arg2), nodes)); }