/** * Puts the type_path JVMS structure corresponding to the given TypePath into the given * ByteVector. * * @param typePath a TypePath instance, or {@literal null} for empty paths. * @param output where the type path must be put. */ static void put(final TypePath typePath, final ByteVector output) { if (typePath == null) { output.putByte(0); } else { int length = typePath.typePathContainer[typePath.typePathOffset] * 2 + 1; output.putByteArray(typePath.typePathContainer, typePath.typePathOffset, length); } } }
@Override public void visitTableSwitchInsn( final int min, final int max, final Label dflt, final Label... labels) { lastBytecodeOffset = code.length; // Add the instruction to the bytecode of the method. code.putByte(Opcodes.TABLESWITCH).putByteArray(null, 0, (4 - code.length % 4) % 4); dflt.put(code, lastBytecodeOffset, true); code.putInt(min).putInt(max); for (Label label : labels) { label.put(code, lastBytecodeOffset, true); } // If needed, update the maximum stack size and number of locals, and stack map frames. visitSwitchInsn(dflt, labels); }
@Override public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { lastBytecodeOffset = code.length; // Add the instruction to the bytecode of the method. code.putByte(Opcodes.LOOKUPSWITCH).putByteArray(null, 0, (4 - code.length % 4) % 4); dflt.put(code, lastBytecodeOffset, true); code.putInt(labels.length); for (int i = 0; i < labels.length; ++i) { code.putInt(keys[i]); labels[i].put(code, lastBytecodeOffset, true); } // If needed, update the maximum stack size and number of locals, and stack map frames. visitSwitchInsn(dflt, labels); }
@Override public void visitInsn(final int opcode) { lastBytecodeOffset = code.length; // Add the instruction to the bytecode of the method. code.putByte(opcode); // If needed, update the maximum stack size and number of locals, and stack map frames. if (currentBasicBlock != null) { if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) { currentBasicBlock.frame.execute(opcode, 0, null, null); } else { int size = relativeStackSize + STACK_SIZE_DELTA[opcode]; if (size > maxRelativeStackSize) { maxRelativeStackSize = size; } relativeStackSize = size; } if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) || opcode == Opcodes.ATHROW) { endCurrentBasicBlockWithNoSuccessor(); } } }
@Override public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels) { lastCodeOffset = code.length; // adds the instruction to the bytecode of the method int source = code.length; code.putByte(Opcodes.TABLESWITCH); code.putByteArray(null, 0, (4 - code.length % 4) % 4); dflt.put(this, code, source, true); code.putInt(min).putInt(max); for (int i = 0; i < labels.length; ++i) { labels[i].put(this, code, source, true); } // updates currentBlock visitSwitchInsn(dflt, labels); }
public void visitMultiANewArrayInsn(final String desc, final int dims) { Item i = cw.newClassItem(desc); // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i); } else { // updates current stack size (max stack size unchanged because // stack size variation always negative or null) stackSize += 1 - dims; } } // adds the instruction to the bytecode of the method code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims); }
@Override public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { lastCodeOffset = code.length; // adds the instruction to the bytecode of the method int source = code.length; code.putByte(Opcodes.LOOKUPSWITCH); code.putByteArray(null, 0, (4 - code.length % 4) % 4); dflt.put(this, code, source, true); code.putInt(labels.length); for (int i = 0; i < labels.length; ++i) { code.putInt(keys[i]); labels[i].put(this, code, source, true); } // updates currentBlock visitSwitchInsn(dflt, labels); }
@Override public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) { lastBytecodeOffset = code.length; // Add the instruction to the bytecode of the method. Symbol descSymbol = symbolTable.addConstantClass(descriptor); code.put12(Opcodes.MULTIANEWARRAY, descSymbol.index).putByte(numDimensions); // If needed, update the maximum stack size and number of locals, and stack map frames. if (currentBasicBlock != null) { if (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES) { currentBasicBlock.frame.execute( Opcodes.MULTIANEWARRAY, numDimensions, descSymbol, symbolTable); } else { // No need to update maxRelativeStackSize (the stack size delta is always negative). relativeStackSize += 1 - numDimensions; } } }
@Override public void visitMultiANewArrayInsn(final String desc, final int dims) { lastCodeOffset = code.length; Item i = cw.newStringishItem(ClassWriter.CLASS, desc); // Label currentBlock = this.currentBlock; if (currentBlock != null) { if (compute == FRAMES || compute == INSERTED_FRAMES) { currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i); } else { // updates current stack size (max stack size unchanged because // stack size variation always negative or null) stackSize += 1 - dims; } } // adds the instruction to the bytecode of the method code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims); }
/** * Adds a float to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * * @param value the float value. * @return a new or already existing float item. */ Item newFloat(final float value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(FLOAT).putInt(key.intVal); result = new Item(index++, key); put(result); } return result; }
/** * Adds an integer to the constant pool of the class being build. Does * nothing if the constant pool already contains a similar item. * * @param value the int value. * @return a new or already existing int item. */ Item newInteger(final int value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(INT).putInt(value); result = new Item(index++, key); put(result); } return result; }
/** * Adds an integer to the constant pool of the class being build. Does * nothing if the constant pool already contains a similar item. * * @param value * the int value. * @return a new or already existing int item. */ Item newInteger(final int value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(INT).putInt(value); result = new Item(index++, key); put(result); } return result; }
/** * Adds a long to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * * @param value * the long value. * @return a new or already existing long item. */ Item newLong(final long value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(LONG).putLong(value); result = new Item(index, key); index += 2; put(result); } return result; }
/** * Adds a double to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * * @param value * the double value. * @return a new or already existing double item. */ Item newDouble(final double value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(DOUBLE).putLong(key.longVal); result = new Item(index, key); index += 2; put(result); } return result; }
public void visitTableSwitchInsn( final int min, final int max, final Label dflt, final Label labels[]) { // adds the instruction to the bytecode of the method int source = code.length; code.putByte(Opcodes.TABLESWITCH); code.length += (4 - code.length % 4) % 4; dflt.put(this, code, source, true); code.putInt(min).putInt(max); for (int i = 0; i < labels.length; ++i) { labels[i].put(this, code, source, true); } // updates currentBlock visitSwitchInsn(dflt, labels); }
public void visitLookupSwitchInsn( final Label dflt, final int keys[], final Label labels[]) { // adds the instruction to the bytecode of the method int source = code.length; code.putByte(Opcodes.LOOKUPSWITCH); code.length += (4 - code.length % 4) % 4; dflt.put(this, code, source, true); code.putInt(labels.length); for (int i = 0; i < labels.length; ++i) { code.putInt(keys[i]); labels[i].put(this, code, source, true); } // updates currentBlock visitSwitchInsn(dflt, labels); }
/** * Adds a long to the constant pool of the class being build. Does nothing * if the constant pool already contains a similar item. * * @param value the long value. * @return a new or already existing long item. */ Item newLong(final long value) { key.set(value); Item result = get(key); if (result == null) { pool.putByte(LONG).putLong(value); result = new Item(index, key); put(result); index += 2; } return result; }
/** * Adds a CONSTANT_Integer_info or CONSTANT_Float_info to the constant pool of this symbol table. * Does nothing if the constant pool already contains a similar item. * * @param tag one of {@link Symbol#CONSTANT_INTEGER_TAG} or {@link Symbol#CONSTANT_FLOAT_TAG}. * @param value an int or float. * @return a constant pool constant with the given tag and primitive values. */ private Symbol addConstantIntegerOrFloat(final int tag, final int value) { int hashCode = hash(tag, value); Entry entry = get(hashCode); while (entry != null) { if (entry.tag == tag && entry.hashCode == hashCode && entry.data == value) { return entry; } entry = entry.next; } constantPool.putByte(tag).putInt(value); return put(new Entry(constantPoolCount++, tag, value, hashCode)); }