@Override public void visitLineNumber(final int line, final Label start) { if (lineNumberTable == null) { lineNumberTable = new ByteVector(); } ++lineNumberTableLength; lineNumberTable.putShort(start.bytecodeOffset); lineNumberTable.putShort(line); }
/** * Puts a byte into this byte vector. The byte vector is automatically enlarged if necessary. * * @param byteValue a byte. * @return this byte vector. */ public ByteVector putByte(final int byteValue) { int currentLength = length; if (currentLength + 1 > data.length) { enlarge(1); } data[currentLength++] = (byte) byteValue; length = currentLength; return this; }
@Override public void visitIincInsn(final int var, final int increment) { lastBytecodeOffset = code.length; // Add the instruction to the bytecode of the method. if ((var > 255) || (increment > 127) || (increment < -128)) { code.putByte(Constants.WIDE).put12(Opcodes.IINC, var).putShort(increment); } else { code.putByte(Opcodes.IINC).put11(var, increment); } // If needed, update the maximum stack size and number of locals, and stack map frames. if (currentBasicBlock != null && (compute == COMPUTE_ALL_FRAMES || compute == COMPUTE_INSERTED_FRAMES)) { currentBasicBlock.frame.execute(Opcodes.IINC, var, null, null); } if (compute != COMPUTE_NOTHING) { int currentMaxLocals = var + 1; if (currentMaxLocals > maxLocals) { maxLocals = currentMaxLocals; } } }
/** * Puts this symbol table's constant_pool array in the given ByteVector, preceded by the * constant_pool_count value. * * @param output where the JVMS ClassFile's constant_pool array must be put. */ void putConstantPool(final ByteVector output) { output.putShort(constantPoolCount).putByteArray(constantPool.data, 0, constantPool.length); }
void putAttributes(ByteVector out) { if (mainClass != 0) { out.putShort(cw.newUTF8("ModuleMainClass")).putInt(2).putShort(mainClass); } if (packages != null) { out.putShort(cw.newUTF8("ModulePackages")) .putInt(2 + 2 * packageCount) .putShort(packageCount) .putByteArray(packages.data, 0, packages.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 visitIntInsn(final int opcode, final int operand) { lastBytecodeOffset = code.length; // Add the instruction to the bytecode of the method. if (opcode == Opcodes.SIPUSH) { code.put12(opcode, operand); } else { // BIPUSH or NEWARRAY code.put11(opcode, operand); } // 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, operand, null, null); } else if (opcode != Opcodes.NEWARRAY) { // The stack size delta is 1 for BIPUSH or SIPUSH, and 0 for NEWARRAY. int size = relativeStackSize + 1; if (size > maxRelativeStackSize) { maxRelativeStackSize = size; } relativeStackSize = size; } } }
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); }
TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible) { ByteVector bv = new ByteVector(); bv.putByte(typeRef >>> 24).putShort(start.length); for (int i = 0; i < start.length; ++i) { bv.putShort(start[i].position) .putShort(end[i].position - start[i].position) .putShort(index[i]); bv.putByte(0); } else { int length = typePath.b[typePath.offset] * 2 + 1; bv.putByteArray(typePath.b, typePath.offset, length); bv.putShort(cw.newUTF8(desc)).putShort(0); AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
size += panns[i] == null ? 0 : panns[i].getSize(); out.putInt(size).putByte(panns.length); for (int i = 0; i < panns.length; ++i) { AnnotationWriter aw = panns[i]; aw = aw.next; out.putShort(n); aw = last; while (aw != null) { out.putByteArray(aw.bv.data, 0, aw.bv.length); aw = aw.prev;
/** * 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; }
ByteVector out = new ByteVector(n); out.putByte(0); for (int i = 0; i < n;) { char c = typePath.charAt(i++); if (c == '[') { out.put11(ARRAY_ELEMENT, 0); } else if (c == '.') { out.put11(INNER_TYPE, 0); } else if (c == '*') { out.put11(WILDCARD_BOUND, 0); } else if (c >= '0' && c <= '9') { int typeArg = c - '0'; i += 1; out.put11(TYPE_ARGUMENT, typeArg);
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); }
/** * Adds a CONSTANT_Utf8_info to the constant pool of this symbol table. Does nothing if the * constant pool already contains a similar item. * * @param value a string. * @return a new or already existing Symbol with the given value. */ int addConstantUtf8(final String value) { int hashCode = hash(Symbol.CONSTANT_UTF8_TAG, value); Entry entry = get(hashCode); while (entry != null) { if (entry.tag == Symbol.CONSTANT_UTF8_TAG && entry.hashCode == hashCode && entry.value.equals(value)) { return entry.index; } entry = entry.next; } constantPool.putByte(Symbol.CONSTANT_UTF8_TAG).putUTF8(value); return put(new Entry(constantPoolCount++, Symbol.CONSTANT_UTF8_TAG, value, hashCode)).index; }
/** * 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); } } }
public void visitSource(final String file, final String debug) { if (file != null) { sourceFile = newUTF8(file); } if (debug != null) { sourceDebug = new ByteVector().putUTF8(debug); } }