ByteVector bootstrapMethodsAttribute = bootstrapMethods; if (bootstrapMethodsAttribute == null) { bootstrapMethodsAttribute = bootstrapMethods = new ByteVector(); bootstrapMethodsAttribute.putShort( addConstantMethodHandle( bootstrapMethodHandle.getTag(), .index); int numBootstrapArguments = bootstrapMethodArguments.length; bootstrapMethodsAttribute.putShort(numBootstrapArguments); for (Object bootstrapMethodArgument : bootstrapMethodArguments) { bootstrapMethodsAttribute.putShort(addConstant(bootstrapMethodArgument).index);
ByteVector output = new ByteVector(typePathLength); output.putByte(0); int typePathIndex = 0; while (typePathIndex < typePathLength) { char c = typePath.charAt(typePathIndex++); if (c == '[') { output.put11(ARRAY_ELEMENT, 0); } else if (c == '.') { output.put11(INNER_TYPE, 0); } else if (c == '*') { output.put11(WILDCARD_BOUND, 0); } else if (c >= '0' && c <= '9') { int typeArg = c - '0'; output.put11(TYPE_ARGUMENT, typeArg); } else { throw new IllegalArgumentException();
case METHOD_TYPE_PARAMETER: case METHOD_FORMAL_PARAMETER: output.putShort(targetTypeAndInfo >>> 16); break; case FIELD: case METHOD_RETURN: case METHOD_RECEIVER: output.putByte(targetTypeAndInfo >>> 24); break; case CAST: case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT: case METHOD_REFERENCE_TYPE_ARGUMENT: output.putInt(targetTypeAndInfo); break; case CLASS_EXTENDS: case CONSTRUCTOR_REFERENCE: case METHOD_REFERENCE: output.put12(targetTypeAndInfo >>> 24, (targetTypeAndInfo & 0xFFFF00) >> 8); break; default:
/** * 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); }
/** * Puts the type_path JVMS structure corresponding to the given TypePath into the given * ByteVector. * * @param typePath a TypePath instance, or <tt>null</tt> 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); } } }
/** * Puts this symbol table's BootstrapMethods attribute in the given ByteVector. This includes the * 6 attribute header bytes and the num_bootstrap_methods value. * * @param output where the JVMS BootstrapMethods attribute must be put. */ void putBootstrapMethods(final ByteVector output) { if (bootstrapMethods != null) { output .putShort(addConstantUtf8(Constants.BOOTSTRAP_METHODS)) .putInt(bootstrapMethods.length + 2) .putShort(bootstrapMethodCount) .putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length); } }
size += panns[i] == null ? 0 : panns[i].getSize(); out.putInt(size).putByte(panns.length - off); for (int i = off; 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;
@Override 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.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); }
/** * 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 addConstantInteger(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)); }
@Override public void visitIincInsn(final int var, final int increment) { if (currentBlock != null) { if (compute == FRAMES) { currentBlock.frame.execute(Opcodes.IINC, var, null, null); } } if (compute != NOTHING) { // updates max locals int n = var + 1; if (n > maxLocals) { maxLocals = n; } } // adds the instruction to the bytecode of the method if ((var > 255) || (increment > 127) || (increment < -128)) { code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var) .putShort(increment); } else { code.putByte(Opcodes.IINC).put11(var, increment); } }
/** * Puts a byte into this byte vector. The byte vector is automatically * enlarged if necessary. * * @param b a byte. * @return this byte vector. */ public ByteVector putByte(final int b){ int length = this.length; if(length + 1 > data.length) { enlarge(1); } data[length++] = (byte) b; this.length = length; return this; }
/** * Adds a CONSTANT_Long_info or CONSTANT_Double_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_LONG_TAG} or {@link Symbol#CONSTANT_DOUBLE_TAG}. * @param value a long or double. * @return a constant pool constant with the given tag and primitive values. */ private Symbol addConstantLong(final int tag, final long 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; } int index = constantPoolCount; constantPool.putByte(tag).putLong(value); constantPoolCount += 2; return put(new Entry(index, tag, value, hashCode)); }
int delta; if (stackMap == null) { stackMap = new ByteVector(); delta = code.length; } else { case Opcodes.F_FULL: currentLocals = nLocal; stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal); for (int i = 0; i < nLocal; ++i) { writeFrameType(local[i]); stackMap.putShort(nStack); for (int i = 0; i < nStack; ++i) { writeFrameType(stack[i]); case Opcodes.F_APPEND: currentLocals += nLocal; stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta); for (int i = 0; i < nLocal; ++i) { writeFrameType(local[i]); case Opcodes.F_CHOP: currentLocals -= nLocal; stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta); break; case Opcodes.F_SAME: if (delta < 64) { stackMap.putByte(delta);
/** * 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; }
int constantPoolLength = classReader.header - constantPoolOffset; constantPoolCount = classReader.getItemCount(); constantPool = new ByteVector(constantPoolLength); constantPool.putByteArray(inputBytes, constantPoolOffset, constantPoolLength); bootstrapMethods = new ByteVector(bootstrapMethodsLength); bootstrapMethods.putByteArray(inputBytes, bootstrapMethodsOffset, bootstrapMethodsLength);