/** * 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); } } }
/** * Puts the given public API frame element type in {@link #stackMapTableEntries} , using the JVMS * verification_type_info format used in StackMapTable attributes. * * @param type a frame element type described using the same format as in {@link * MethodVisitor#visitFrame}, i.e. either {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link * Opcodes#FLOAT}, {@link Opcodes#LONG}, {@link Opcodes#DOUBLE}, {@link Opcodes#NULL}, or * {@link Opcodes#UNINITIALIZED_THIS}, or the internal name of a class, or a Label designating * a NEW instruction (for uninitialized types). */ private void putFrameType(final Object type) { if (type instanceof Integer) { stackMapTableEntries.putByte(((Integer) type).intValue()); } else if (type instanceof String) { stackMapTableEntries .putByte(Frame.ITEM_OBJECT) .putShort(symbolTable.addConstantClass((String) type).index); } else { stackMapTableEntries .putByte(Frame.ITEM_UNINITIALIZED) .putShort(((Label) type).bytecodeOffset); } }
@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 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; } } }
@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 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(); } } }
output.putByte(annotableParameterCount); for (int i = 0; i < annotableParameterCount; ++i) { AnnotationWriter annotationWriter = annotationWriters[i];
switch (abstractType & KIND_MASK) { case CONSTANT_KIND: output.putByte(typeValue); break; case REFERENCE_KIND: output .putByte(ITEM_OBJECT) .putShort(symbolTable.addConstantClass(symbolTable.getType(typeValue).value).index); break; case UNINITIALIZED_KIND: output.putByte(ITEM_UNINITIALIZED).putShort((int) symbolTable.getType(typeValue).data); break; default: .putByte(ITEM_OBJECT) .putShort(symbolTable.addConstantClass(typeDescriptor.toString()).index);
.putShort(symbolTable.addConstantUtf8(Constants.METHOD_PARAMETERS)) .putInt(1 + parameters.length) .putByte(parametersCount) .putByteArray(parameters.data, 0, parameters.length);
@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; } } }
output.putByte(0); int typePathIndex = 0; while (typePathIndex < typePathLength) {
case METHOD_RETURN: case METHOD_RECEIVER: output.putByte(targetTypeAndInfo >>> 24); break; case CAST:
/** * 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; }
code.putByte(Constants.GOTO_W); } else if (baseOpcode == Opcodes.JSR) { code.putByte(Constants.JSR_W); } else { code.putByte(baseOpcode >= Opcodes.IFNULL ? baseOpcode ^ 1 : ((baseOpcode + 1) ^ 1) - 1); code.putShort(8); code.putByte(Constants.ASM_GOTO_W); hasAsmInstructions = true; code.putByte(opcode); label.put(code, code.length - 1, true); } else { code.putByte(baseOpcode); label.put(code, code.length - 1, false);
stackMapTableEntries.putByte(offsetDelta); break; case Frame.SAME_LOCALS_1_STACK_ITEM_FRAME: stackMapTableEntries.putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME + offsetDelta); putAbstractTypes(3 + numLocal, 4 + numLocal); break; case Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED: stackMapTableEntries .putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) .putShort(offsetDelta); putAbstractTypes(3 + numLocal, 4 + numLocal); break; case Frame.SAME_FRAME_EXTENDED: stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED).putShort(offsetDelta); break; case Frame.CHOP_FRAME: stackMapTableEntries .putByte(Frame.SAME_FRAME_EXTENDED + numLocalDelta) .putShort(offsetDelta); break; case Frame.APPEND_FRAME: stackMapTableEntries .putByte(Frame.SAME_FRAME_EXTENDED + numLocalDelta) .putShort(offsetDelta); putAbstractTypes(3 + previousNumlocal, 3 + numLocal); case Frame.FULL_FRAME: default: stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(numLocal);
/** * 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)); }
/** * 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 addConstantLongOrDouble(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)); }
case Opcodes.F_FULL: currentLocals = numLocal; stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(numLocal); for (int i = 0; i < numLocal; ++i) { putFrameType(local[i]); case Opcodes.F_APPEND: currentLocals += numLocal; stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED + numLocal).putShort(offsetDelta); for (int i = 0; i < numLocal; ++i) { putFrameType(local[i]); case Opcodes.F_CHOP: currentLocals -= numLocal; stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED - numLocal).putShort(offsetDelta); break; case Opcodes.F_SAME: if (offsetDelta < 64) { stackMapTableEntries.putByte(offsetDelta); } else { stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED).putShort(offsetDelta); stackMapTableEntries.putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME + offsetDelta); } else { stackMapTableEntries .putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) .putShort(offsetDelta);
typeAnnotation.putByte(typeRef >>> 24).putShort(start.length); for (int i = 0; i < start.length; ++i) { typeAnnotation