diff --git a/src/java.base/share/classes/java/lang/classfile/ClassFile.java b/src/java.base/share/classes/java/lang/classfile/ClassFile.java index db293f41588..6593dfcf2ae 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassFile.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassFile.java @@ -32,6 +32,8 @@ import java.lang.classfile.constantpool.ClassEntry; import java.lang.classfile.constantpool.ConstantPoolBuilder; import java.lang.classfile.constantpool.Utf8Entry; +import java.lang.classfile.instruction.BranchInstruction; +import java.lang.classfile.instruction.DiscontinuedInstruction; import java.lang.classfile.instruction.ExceptionCatch; import java.lang.constant.ClassDesc; import java.lang.reflect.AccessFlag; @@ -230,17 +232,35 @@ enum LineNumbersOption implements Option { /** * Option describing whether to automatically rewrite short jumps to * long when necessary. - * Default is {@code FIX_SHORT_JUMPS} to automatically rewrite jump + * Default is {@link #FIX_SHORT_JUMPS} to automatically rewrite jump * instructions. + *
+ * Due to physical restrictions, some types of instructions cannot encode + * certain jump targets with bci offsets less than -32768 or greater than + * 32767, as they use a {@code s2} to encode such an offset. (The maximum + * length of the {@code code} array is 65535.) These types of instructions + * are called "short jumps". * + * @see BranchInstruction + * @see DiscontinuedInstruction.JsrInstruction * @since 24 */ enum ShortJumpsOption implements Option { - /** Automatically convert short jumps to long when necessary */ + /** + * Automatically convert short jumps to long when necessary. + *
+ * For an invalid instruction model, a {@link CodeBuilder} may generate + * another or a few other instructions to accomplish the same effect. + */ FIX_SHORT_JUMPS, - /** Fail if short jump overflows */ + /** + * Fail with an {@link IllegalArgumentException} if short jump overflows. + *
+ * This is useful to ensure the physical accuracy of a generated {@code + * class} file. + */ FAIL_ON_SHORT_JUMPS } diff --git a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java index 1a074c1554a..3cbcb893cb1 100644 --- a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java @@ -51,7 +51,7 @@ * #with(ClassFileElement)} or concretely by calling the various {@code withXxx} * methods. * - *
+ * The {@link #opcode() opcode} identifies the operation of an instruction. + * Each {@linkplain Opcode#kind() kind} of opcode has its own modeling interface + * for instructions. * + * @sealedGraph * @since 24 */ public sealed interface Instruction extends CodeElement @@ -46,12 +53,14 @@ public sealed interface Instruction extends CodeElement ThrowInstruction, TypeCheckInstruction, AbstractInstruction { /** - * {@return the opcode of this instruction} + * {@return the operation of this instruction} */ Opcode opcode(); /** * {@return the size in bytes of this instruction} + * This value is equal to {@link Opcode#sizeIfFixed() + * opcode().sizeIfFixed()} if it is not {@code -1}. */ int sizeInBytes(); } diff --git a/src/java.base/share/classes/java/lang/classfile/Label.java b/src/java.base/share/classes/java/lang/classfile/Label.java index e958e116084..653c410728c 100644 --- a/src/java.base/share/classes/java/lang/classfile/Label.java +++ b/src/java.base/share/classes/java/lang/classfile/Label.java @@ -24,21 +24,60 @@ */ package java.lang.classfile; +import java.lang.classfile.attribute.CodeAttribute; +import java.lang.classfile.instruction.LabelTarget; +import java.util.ListIterator; + import jdk.internal.classfile.impl.LabelImpl; /** * A marker for a position within the instructions of a method body. The - * association between a label's identity and the position it represents is - * managed by the entity managing the method body (a {@link CodeModel} or {@link - * CodeBuilder}), not the label itself; this allows the same label to have a - * meaning both in an existing method (as managed by a {@linkplain CodeModel}) - * and in the transformation of that method (as managed by a {@linkplain - * CodeBuilder}), while corresponding to different positions in each. When - * traversing the elements of a {@linkplain CodeModel}, {@linkplain Label} - * markers will be delivered at the position to which they correspond. A label - * can be bound to the current position within a {@linkplain CodeBuilder} via - * {@link CodeBuilder#labelBinding(Label)} or {@link CodeBuilder#with(ClassFileElement)}. + * position is a cursor position in the list of instructions, similar to that + * of a {@link ListIterator}. + * + *
+ * In generic {@link CodeModel}s, a label may not have a bci value; the position + * of a label can be found by searching for the corresponding {@link LabelTarget} + * within that model. + * + *
+ * To obtain a label: + *
+ * A label must be bound exactly once in the {@code CodeBuilder} where it is + * used; otherwise, writing fails. To bind an unbound label: + *
+ * An opcode describes the operation of an instruction. + * + * @apiNote + * The enum constants are named after the opcodes' mnemonics in uppercase. + * Wide pseudo-opcodes are named with the original opcodes' mnemonic plus + * a {@code _W} suffix. However, {@link #LDC_W ldc_w}, {@link #LDC2_W ldc2_w}, + * {@link #GOTO_W goto_w}, and {@link #JSR_W jsr_w} are legitimate opcodes + * instead of wide pseudo-opcodes. * * @see Instruction - * @see PseudoInstruction * * @since 24 */ public enum Opcode { - /** Do nothing */ + /** + * Do nothing. + * + * @jvms 6.5.nop nop + * @see Kind#NOP + */ NOP(RawBytecodeHelper.NOP, 1, Kind.NOP), - /** Push null */ + /** + * Push {@code null}. + * + * @jvms 6.5.aconst_null aconst_null + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ACONST_NULL(RawBytecodeHelper.ACONST_NULL, 1, Kind.CONSTANT), - /** Push int constant -1 */ + /** + * Push {@link TypeKind#INT int} constant {@code -1}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_M1(RawBytecodeHelper.ICONST_M1, 1, Kind.CONSTANT), - /** Push int constant 0 */ + /** + * Push {@link TypeKind#INT int} constant {@code 0}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_0(RawBytecodeHelper.ICONST_0, 1, Kind.CONSTANT), - /** Push int constant 1 */ + /** + * Push {@link TypeKind#INT int} constant {@code 1}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_1(RawBytecodeHelper.ICONST_1, 1, Kind.CONSTANT), - /** Push int constant 2 */ + /** + * Push {@link TypeKind#INT int} constant {@code 2}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_2(RawBytecodeHelper.ICONST_2, 1, Kind.CONSTANT), - /** Push int constant 3 */ + /** + * Push {@link TypeKind#INT int} constant {@code 3}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_3(RawBytecodeHelper.ICONST_3, 1, Kind.CONSTANT), - /** Push int constant 4 */ + /** + * Push {@link TypeKind#INT int} constant {@code 4}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_4(RawBytecodeHelper.ICONST_4, 1, Kind.CONSTANT), - /** Push int constant 5 */ + /** + * Push {@link TypeKind#INT int} constant {@code 5}. + * + * @jvms 6.5.iconst_i iconst_<i> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ ICONST_5(RawBytecodeHelper.ICONST_5, 1, Kind.CONSTANT), - /** Push long constant 0 */ + /** + * Push {@link TypeKind#LONG long} constant {@code 0L}. + * + * @jvms 6.5.lconst_l lconst_<l> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ LCONST_0(RawBytecodeHelper.LCONST_0, 1, Kind.CONSTANT), - /** Push long constant 1 */ + /** + * Push {@link TypeKind#LONG long} constant {@code 1L}. + * + * @jvms 6.5.lconst_l lconst_<l> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ LCONST_1(RawBytecodeHelper.LCONST_1, 1, Kind.CONSTANT), - /** Push float constant 0 */ + /** + * Push {@link TypeKind#FLOAT float} constant {@code 0.0F}. + * + * @jvms 6.5.fconst_f fconst_<f> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ FCONST_0(RawBytecodeHelper.FCONST_0, 1, Kind.CONSTANT), - /** Push float constant 1 */ + /** + * Push {@link TypeKind#FLOAT float} constant {@code 1.0F}. + * + * @jvms 6.5.fconst_f fconst_<f> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ FCONST_1(RawBytecodeHelper.FCONST_1, 1, Kind.CONSTANT), - /** Push float constant 2 */ + /** + * Push {@link TypeKind#FLOAT float} constant {@code 2.0F}. + * + * @jvms 6.5.fconst_f fconst_<f> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ FCONST_2(RawBytecodeHelper.FCONST_2, 1, Kind.CONSTANT), - /** Push double constant 0 */ + /** + * Push {@link TypeKind#DOUBLE double} constant {@code 0.0D}. + * + * @jvms 6.5.dconst_d dconst_<d> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ DCONST_0(RawBytecodeHelper.DCONST_0, 1, Kind.CONSTANT), - /** Push double constant 1 */ + /** + * Push {@link TypeKind#DOUBLE double} constant {@code 1.0D}. + * + * @jvms 6.5.dconst_d dconst_<d> + * @see ConstantInstruction.IntrinsicConstantInstruction + * @see Kind#CONSTANT + */ DCONST_1(RawBytecodeHelper.DCONST_1, 1, Kind.CONSTANT), - /** Push byte */ + /** + * Push {@link TypeKind#INT int} value from sign-extension of immediate + * {@link TypeKind#BYTE byte} value. + * + * @jvms 6.5.bipush bipush + * @see ConstantInstruction.ArgumentConstantInstruction + * @see Kind#CONSTANT + */ BIPUSH(RawBytecodeHelper.BIPUSH, 2, Kind.CONSTANT), - /** Push short */ + /** + * Push {@link TypeKind#INT int} value from sign-extension of immediate + * {@link TypeKind#SHORT short} value. + * + * @jvms 6.5.sipush sipush + * @see ConstantInstruction.ArgumentConstantInstruction + * @see Kind#CONSTANT + */ SIPUSH(RawBytecodeHelper.SIPUSH, 3, Kind.CONSTANT), - /** Push item from run-time constant pool */ + /** + * Push item from run-time constant pool. + * + * @jvms 6.5.ldc ldc + * @see ConstantInstruction.LoadConstantInstruction + * @see Kind#CONSTANT + */ LDC(RawBytecodeHelper.LDC, 2, Kind.CONSTANT), - /** Push item from run-time constant pool (wide index) */ + /** + * Push item from run-time constant pool (wide index). + * + * @jvms 6.5.ldc_w ldc_w + * @see ConstantInstruction.LoadConstantInstruction + * @see Kind#CONSTANT + */ LDC_W(RawBytecodeHelper.LDC_W, 3, Kind.CONSTANT), - /** Push long or double from run-time constant pool (wide index) */ + /** + * Push {@link TypeKind#LONG long} or {@link TypeKind#DOUBLE double} + * from run-time constant pool (wide index). + * + * @jvms 6.5.ldc2_w ldc2_w + * @see ConstantInstruction.LoadConstantInstruction + * @see Kind#CONSTANT + */ LDC2_W(RawBytecodeHelper.LDC2_W, 3, Kind.CONSTANT), - /** Load int from local variable */ + /** + * Load {@link TypeKind#INT int} from local variable. + * + * @jvms 6.5.iload iload + * @see Kind#LOAD + */ ILOAD(RawBytecodeHelper.ILOAD, 2, Kind.LOAD), - /** Load long from local variable */ + /** + * Load {@link TypeKind#LONG long} from local variable. + * + * @jvms 6.5.lload lload + * @see Kind#LOAD + */ LLOAD(RawBytecodeHelper.LLOAD, 2, Kind.LOAD), - /** Load float from local variable */ + /** + * Load {@link TypeKind#FLOAT float} from local variable. + * + * @jvms 6.5.fload fload + * @see Kind#LOAD + */ FLOAD(RawBytecodeHelper.FLOAD, 2, Kind.LOAD), - /** Load double from local variable */ + /** + * Load {@link TypeKind#DOUBLE double} from local variable. + * + * @jvms 6.5.dload dload + * @see Kind#LOAD + */ DLOAD(RawBytecodeHelper.DLOAD, 2, Kind.LOAD), - /** Load reference from local variable */ + /** + * Load {@link TypeKind#REFERENCE reference} from local variable. + * + * @jvms 6.5.aload aload + * @see Kind#LOAD + */ ALOAD(RawBytecodeHelper.ALOAD, 2, Kind.LOAD), - /** Load int from local variable 0 */ + /** + * Load {@link TypeKind#INT int} from local variable slot {@code 0}. + * + * @jvms 6.5.iload_n iload_<n> + * @see Kind#LOAD + */ ILOAD_0(RawBytecodeHelper.ILOAD_0, 1, Kind.LOAD), - /** Load int from local variable 1 */ + /** + * Load {@link TypeKind#INT int} from local variable slot {@code 1}. + * + * @jvms 6.5.iload_n iload_<n> + * @see Kind#LOAD + */ ILOAD_1(RawBytecodeHelper.ILOAD_1, 1, Kind.LOAD), - /** Load int from local variable 2 */ + /** + * Load {@link TypeKind#INT int} from local variable slot {@code 2}. + * + * @jvms 6.5.iload_n iload_<n> + * @see Kind#LOAD + */ ILOAD_2(RawBytecodeHelper.ILOAD_2, 1, Kind.LOAD), - /** Load int from local variable3 */ + /** + * Load {@link TypeKind#INT int} from local variable slot {@code 3}. + * + * @jvms 6.5.iload_n iload_<n> + * @see Kind#LOAD + */ ILOAD_3(RawBytecodeHelper.ILOAD_3, 1, Kind.LOAD), - /** Load long from local variable 0 */ + /** + * Load {@link TypeKind#LONG long} from local variable slot {@code 0}. + * + * @jvms 6.5.lload_n lload_<n> + * @see Kind#LOAD + */ LLOAD_0(RawBytecodeHelper.LLOAD_0, 1, Kind.LOAD), - /** Load long from local variable 1 */ + /** + * Load {@link TypeKind#LONG long} from local variable slot {@code 1}. + * + * @jvms 6.5.lload_n lload_<n> + * @see Kind#LOAD + */ LLOAD_1(RawBytecodeHelper.LLOAD_1, 1, Kind.LOAD), - /** Load long from local variable 2 */ + /** + * Load {@link TypeKind#LONG long} from local variable slot {@code 2}. + * + * @jvms 6.5.lload_n lload_<n> + * @see Kind#LOAD + */ LLOAD_2(RawBytecodeHelper.LLOAD_2, 1, Kind.LOAD), - /** Load long from local variable 3 */ + /** + * Load {@link TypeKind#LONG long} from local variable slot {@code 3}. + * + * @jvms 6.5.lload_n lload_<n> + * @see Kind#LOAD + */ LLOAD_3(RawBytecodeHelper.LLOAD_3, 1, Kind.LOAD), - /** Load float from local variable 0 */ + /** + * Load {@link TypeKind#FLOAT float} from local variable slot {@code 0}. + * + * @jvms 6.5.fload_n fload_<n> + * @see Kind#LOAD + */ FLOAD_0(RawBytecodeHelper.FLOAD_0, 1, Kind.LOAD), - /** Load float from local variable 1 */ + /** + * Load {@link TypeKind#FLOAT float} from local variable slot {@code 1}. + * + * @jvms 6.5.fload_n fload_<n> + * @see Kind#LOAD + */ FLOAD_1(RawBytecodeHelper.FLOAD_1, 1, Kind.LOAD), - /** Load float from local variable 2 */ + /** + * Load {@link TypeKind#FLOAT float} from local variable slot {@code 2}. + * + * @jvms 6.5.fload_n fload_<n> + * @see Kind#LOAD + */ FLOAD_2(RawBytecodeHelper.FLOAD_2, 1, Kind.LOAD), - /** Load float from local variable 3 */ + /** + * Load {@link TypeKind#FLOAT float} from local variable slot {@code 3}. + * + * @jvms 6.5.fload_n fload_<n> + * @see Kind#LOAD + */ FLOAD_3(RawBytecodeHelper.FLOAD_3, 1, Kind.LOAD), - /** Load double from local variable 0 */ + /** + * Load {@link TypeKind#DOUBLE double} from local variable slot {@code 0}. + * + * @jvms 6.5.dload_n dload_<n> + * @see Kind#LOAD + */ DLOAD_0(RawBytecodeHelper.DLOAD_0, 1, Kind.LOAD), - /** Load double from local variable 1 */ + /** + * Load {@link TypeKind#DOUBLE double} from local variable slot {@code 1}. + * + * @jvms 6.5.dload_n dload_<n> + * @see Kind#LOAD + */ DLOAD_1(RawBytecodeHelper.DLOAD_1, 1, Kind.LOAD), - /** Load double from local variable 2 */ + /** + * Load {@link TypeKind#DOUBLE double} from local variable slot {@code 2}. + * + * @jvms 6.5.dload_n dload_<n> + * @see Kind#LOAD + */ DLOAD_2(RawBytecodeHelper.DLOAD_2, 1, Kind.LOAD), - /** Load double from local variable 3 */ + /** + * Load {@link TypeKind#DOUBLE double} from local variable slot {@code 3}. + * + * @jvms 6.5.dload_n dload_<n> + * @see Kind#LOAD + */ DLOAD_3(RawBytecodeHelper.DLOAD_3, 1, Kind.LOAD), - /** Load reference from local variable 0 */ + /** + * Load {@link TypeKind#REFERENCE reference} from local variable slot {@code 0}. + * + * @jvms 6.5.aload_n aload_<n> + * @see Kind#LOAD + */ ALOAD_0(RawBytecodeHelper.ALOAD_0, 1, Kind.LOAD), - /** Load reference from local variable 1 */ + /** + * Load {@link TypeKind#REFERENCE reference} from local variable slot {@code 1}. + * + * @jvms 6.5.aload_n aload_<n> + * @see Kind#LOAD + */ ALOAD_1(RawBytecodeHelper.ALOAD_1, 1, Kind.LOAD), - /** Load reference from local variable 2 */ + /** + * Load {@link TypeKind#REFERENCE reference} from local variable slot {@code 2}. + * + * @jvms 6.5.aload_n aload_<n> + * @see Kind#LOAD + */ ALOAD_2(RawBytecodeHelper.ALOAD_2, 1, Kind.LOAD), - /** Load reference from local variable 3 */ + /** + * Load {@link TypeKind#REFERENCE reference} from local variable slot {@code 3}. + * + * @jvms 6.5.aload_n aload_<n> + * @see Kind#LOAD + */ ALOAD_3(RawBytecodeHelper.ALOAD_3, 1, Kind.LOAD), - /** Load int from array */ + /** + * Load {@link TypeKind#INT int} from array. + * + * @jvms 6.5.iaload iaload + * @see Kind#ARRAY_LOAD + */ IALOAD(RawBytecodeHelper.IALOAD, 1, Kind.ARRAY_LOAD), - /** Load long from array */ + /** + * Load {@link TypeKind#LONG long} from array. + * + * @jvms 6.5.laload laload + * @see Kind#ARRAY_LOAD + */ LALOAD(RawBytecodeHelper.LALOAD, 1, Kind.ARRAY_LOAD), - /** Load float from array */ + /** + * Load {@link TypeKind#FLOAT float} from array. + * + * @jvms 6.5.faload faload + * @see Kind#ARRAY_LOAD + */ FALOAD(RawBytecodeHelper.FALOAD, 1, Kind.ARRAY_LOAD), - /** Load double from array */ + /** + * Load {@link TypeKind#DOUBLE double} from array. + * + * @jvms 6.5.daload daload + * @see Kind#ARRAY_LOAD + */ DALOAD(RawBytecodeHelper.DALOAD, 1, Kind.ARRAY_LOAD), - /** Load reference from array */ + /** + * Load {@link TypeKind#REFERENCE reference} from array. + * + * @jvms 6.5.aaload aaload + * @see Kind#ARRAY_LOAD + */ AALOAD(RawBytecodeHelper.AALOAD, 1, Kind.ARRAY_LOAD), - /** Load byte from array */ + /** + * Load {@link TypeKind#BYTE byte} or {@link TypeKind#BOOLEAN boolean} from array. + * + * @jvms 6.5.baload baload + * @see Kind#ARRAY_LOAD + */ BALOAD(RawBytecodeHelper.BALOAD, 1, Kind.ARRAY_LOAD), - /** Load char from array */ + /** + * Load {@link TypeKind#CHAR char} from array. + * + * @jvms 6.5.caload caload + * @see Kind#ARRAY_LOAD + */ CALOAD(RawBytecodeHelper.CALOAD, 1, Kind.ARRAY_LOAD), - /** Load short from array */ + /** + * Load {@link TypeKind#SHORT short} from array. + * + * @jvms 6.5.saload saload + * @see Kind#ARRAY_LOAD + */ SALOAD(RawBytecodeHelper.SALOAD, 1, Kind.ARRAY_LOAD), - /** Store int into local variable */ + /** + * Store {@link TypeKind#INT int} into local variable. + * + * @jvms 6.5.istore istore + * @see Kind#STORE + */ ISTORE(RawBytecodeHelper.ISTORE, 2, Kind.STORE), - /** Store long into local variable */ + /** + * Store {@link TypeKind#LONG long} into local variable. + * + * @jvms 6.5.lstore lstore + * @see Kind#STORE + */ LSTORE(RawBytecodeHelper.LSTORE, 2, Kind.STORE), - /** Store float into local variable */ + /** + * Store {@link TypeKind#FLOAT float} into local variable. + * + * @jvms 6.5.fstore fstore + * @see Kind#STORE + */ FSTORE(RawBytecodeHelper.FSTORE, 2, Kind.STORE), - /** Store double into local variable */ + /** + * Store {@link TypeKind#DOUBLE double} into local variable. + * + * @jvms 6.5.dstore dstore + * @see Kind#STORE + */ DSTORE(RawBytecodeHelper.DSTORE, 2, Kind.STORE), - /** Store reference into local variable */ + /** + * Store {@link TypeKind#REFERENCE reference} into local variable. + * Can also store the {@link TypeKind##returnAddress returnAddress} type. + * + * @jvms 6.5.astore astore + * @see Kind#STORE + */ ASTORE(RawBytecodeHelper.ASTORE, 2, Kind.STORE), - /** Store int into local variable 0 */ + /** + * Store {@link TypeKind#INT int} into local variable slot {@code 0}. + * + * @jvms 6.5.istore_n istore_<n> + * @see Kind#STORE + */ ISTORE_0(RawBytecodeHelper.ISTORE_0, 1, Kind.STORE), - /** Store int into local variable 1 */ + /** + * Store {@link TypeKind#INT int} into local variable slot {@code 1}. + * + * @jvms 6.5.istore_n istore_<n> + * @see Kind#STORE + */ ISTORE_1(RawBytecodeHelper.ISTORE_1, 1, Kind.STORE), - /** Store int into local variable 2 */ + /** + * Store {@link TypeKind#INT int} into local variable slot {@code 2}. + * + * @jvms 6.5.istore_n istore_<n> + * @see Kind#STORE + */ ISTORE_2(RawBytecodeHelper.ISTORE_2, 1, Kind.STORE), - /** Store int into local variable 3 */ + /** + * Store {@link TypeKind#INT int} into local variable slot {@code 3}. + * + * @jvms 6.5.istore_n istore_<n> + * @see Kind#STORE + */ ISTORE_3(RawBytecodeHelper.ISTORE_3, 1, Kind.STORE), - /** Store long into local variable 0 */ + /** + * Store {@link TypeKind#LONG long} into local variable slot {@code 0}. + * + * @jvms 6.5.lstore_n lstore_<n> + * @see Kind#STORE + */ LSTORE_0(RawBytecodeHelper.LSTORE_0, 1, Kind.STORE), - /** Store long into local variable 1 */ + /** + * Store {@link TypeKind#LONG long} into local variable slot {@code 1}. + * + * @jvms 6.5.lstore_n lstore_<n> + * @see Kind#STORE + */ LSTORE_1(RawBytecodeHelper.LSTORE_1, 1, Kind.STORE), - /** Store long into local variable 2 */ + /** + * Store {@link TypeKind#LONG long} into local variable slot {@code 2}. + * + * @jvms 6.5.lstore_n lstore_<n> + * @see Kind#STORE + */ LSTORE_2(RawBytecodeHelper.LSTORE_2, 1, Kind.STORE), - /** Store long into local variable 3 */ + /** + * Store {@link TypeKind#LONG long} into local variable slot {@code 3}. + * + * @jvms 6.5.lstore_n lstore_<n> + * @see Kind#STORE + */ LSTORE_3(RawBytecodeHelper.LSTORE_3, 1, Kind.STORE), - /** Store float into local variable 0 */ + /** + * Store {@link TypeKind#FLOAT float} into local variable slot {@code 0}. + * + * @jvms 6.5.fstore_n fstore_<n> + * @see Kind#STORE + */ FSTORE_0(RawBytecodeHelper.FSTORE_0, 1, Kind.STORE), - /** Store float into local variable 1 */ + /** + * Store {@link TypeKind#FLOAT float} into local variable slot {@code 1}. + * + * @jvms 6.5.fstore_n fstore_<n> + * @see Kind#STORE + */ FSTORE_1(RawBytecodeHelper.FSTORE_1, 1, Kind.STORE), - /** Store float into local variable 2 */ + /** + * Store {@link TypeKind#FLOAT float} into local variable slot {@code 2}. + * + * @jvms 6.5.fstore_n fstore_<n> + * @see Kind#STORE + */ FSTORE_2(RawBytecodeHelper.FSTORE_2, 1, Kind.STORE), - /** Store float into local variable 3 */ + /** + * Store {@link TypeKind#FLOAT float} into local variable slot {@code 3}. + * + * @jvms 6.5.fstore_n fstore_<n> + * @see Kind#STORE + */ FSTORE_3(RawBytecodeHelper.FSTORE_3, 1, Kind.STORE), - /** Store double into local variable 0 */ + /** + * Store {@link TypeKind#DOUBLE double} into local variable slot {@code 0}. + * + * @jvms 6.5.dstore_n dstore_<n> + * @see Kind#STORE + */ DSTORE_0(RawBytecodeHelper.DSTORE_0, 1, Kind.STORE), - /** Store double into local variable 1 */ + /** + * Store {@link TypeKind#DOUBLE double} into local variable slot {@code 1}. + * + * @jvms 6.5.dstore_n dstore_<n> + * @see Kind#STORE + */ DSTORE_1(RawBytecodeHelper.DSTORE_1, 1, Kind.STORE), - /** Store double into local variable 2 */ + /** + * Store {@link TypeKind#DOUBLE double} into local variable slot {@code 2}. + * + * @jvms 6.5.dstore_n dstore_<n> + * @see Kind#STORE + */ DSTORE_2(RawBytecodeHelper.DSTORE_2, 1, Kind.STORE), - /** Store double into local variable 3 */ + /** + * Store {@link TypeKind#DOUBLE double} into local variable slot {@code 3}. + * + * @jvms 6.5.dstore_n dstore_<n> + * @see Kind#STORE + */ DSTORE_3(RawBytecodeHelper.DSTORE_3, 1, Kind.STORE), - /** Store reference into local variable 0 */ + /** + * Store {@link TypeKind#REFERENCE reference} into local variable slot {@code 0}. + * Can also store the {@link TypeKind##returnAddress returnAddress} type. + * + * @jvms 6.5.astore_n astore_<n> + * @see Kind#STORE + */ ASTORE_0(RawBytecodeHelper.ASTORE_0, 1, Kind.STORE), - /** Store reference into local variable 1 */ + /** + * Store {@link TypeKind#REFERENCE reference} into local variable slot {@code 1}. + * Can also store the {@link TypeKind##returnAddress returnAddress} type. + * + * @jvms 6.5.astore_n astore_<n> + * @see Kind#STORE + */ ASTORE_1(RawBytecodeHelper.ASTORE_1, 1, Kind.STORE), - /** Store reference into local variable 2 */ + /** + * Store {@link TypeKind#REFERENCE reference} into local variable slot {@code 2}. + * Can also store the {@link TypeKind##returnAddress returnAddress} type. + * + * @jvms 6.5.astore_n astore_<n> + * @see Kind#STORE + */ ASTORE_2(RawBytecodeHelper.ASTORE_2, 1, Kind.STORE), - /** Store reference into local variable 3 */ + /** + * Store {@link TypeKind#REFERENCE reference} into local variable slot {@code 3}. + * Can also store the {@link TypeKind##returnAddress returnAddress} type. + * + * @jvms 6.5.astore_n astore_<n> + * @see Kind#STORE + */ ASTORE_3(RawBytecodeHelper.ASTORE_3, 1, Kind.STORE), - /** Store into int array */ + /** + * Store into {@link TypeKind#INT int} array. + * + * @jvms 6.5.iastore iastore + * @see Kind#ARRAY_STORE + */ IASTORE(RawBytecodeHelper.IASTORE, 1, Kind.ARRAY_STORE), - /** Store into long array */ + /** + * Store into {@link TypeKind#LONG long} array. + * + * @jvms 6.5.lastore lastore + * @see Kind#ARRAY_STORE + */ LASTORE(RawBytecodeHelper.LASTORE, 1, Kind.ARRAY_STORE), - /** Store into float array */ + /** + * Store into {@link TypeKind#FLOAT float} array. + * + * @jvms 6.5.fastore fastore + * @see Kind#ARRAY_STORE + */ FASTORE(RawBytecodeHelper.FASTORE, 1, Kind.ARRAY_STORE), - /** Store into double array */ + /** + * Store into {@link TypeKind#DOUBLE double} array. + * + * @jvms 6.5.dastore dastore + * @see Kind#ARRAY_STORE + */ DASTORE(RawBytecodeHelper.DASTORE, 1, Kind.ARRAY_STORE), - /** Store into reference array */ + /** + * Store into {@link TypeKind#REFERENCE reference} array. + * + * @jvms 6.5.aastore aastore + * @see Kind#ARRAY_STORE + */ AASTORE(RawBytecodeHelper.AASTORE, 1, Kind.ARRAY_STORE), - /** Store into byte array */ + /** + * Store into {@link TypeKind#BYTE byte} or {@link TypeKind#BOOLEAN boolean} array. + * + * @jvms 6.5.bastore bastore + * @see Kind#ARRAY_STORE + */ BASTORE(RawBytecodeHelper.BASTORE, 1, Kind.ARRAY_STORE), - /** Store into char array */ + /** + * Store into {@link TypeKind#CHAR char} array. + * + * @jvms 6.5.castore castore + * @see Kind#ARRAY_STORE + */ CASTORE(RawBytecodeHelper.CASTORE, 1, Kind.ARRAY_STORE), - /** Store into short array */ + /** + * Store into {@link TypeKind#SHORT short} array. + * + * @jvms 6.5.sastore sastore + * @see Kind#ARRAY_STORE + */ SASTORE(RawBytecodeHelper.SASTORE, 1, Kind.ARRAY_STORE), - /** Pop the top operand stack value */ + /** + * Pop the top operand stack value. + * + * @jvms 6.5.pop pop + * @see Kind#STACK + */ POP(RawBytecodeHelper.POP, 1, Kind.STACK), - /** Pop the top one or two operand stack values */ + /** + * Pop the top one or two operand stack values. + * + * @jvms 6.5.pop2 pop2 + * @see Kind#STACK + */ POP2(RawBytecodeHelper.POP2, 1, Kind.STACK), - /** Duplicate the top operand stack value */ + /** + * Duplicate the top operand stack value. + * + * @jvms 6.5.dup dup + * @see Kind#STACK + */ DUP(RawBytecodeHelper.DUP, 1, Kind.STACK), - /** Duplicate the top operand stack value and insert two values down */ + /** + * Duplicate the top operand stack value and insert two values down. + * + * @jvms 6.5.dup_x1 dup_x1 + * @see Kind#STACK + */ DUP_X1(RawBytecodeHelper.DUP_X1, 1, Kind.STACK), - /** Duplicate the top operand stack value and insert two or three values down */ + /** + * Duplicate the top operand stack value and insert two or three values down. + * + * @jvms 6.5.dup_x2 dup_x2 + * @see Kind#STACK + */ DUP_X2(RawBytecodeHelper.DUP_X2, 1, Kind.STACK), - /** Duplicate the top one or two operand stack values */ + /** + * Duplicate the top one or two operand stack values. + * + * @jvms 6.5.dup2 dup2 + * @see Kind#STACK + */ DUP2(RawBytecodeHelper.DUP2, 1, Kind.STACK), - /** Duplicate the top one or two operand stack values and insert two or three values down */ + /** + * Duplicate the top one or two operand stack values and insert two or three + * values down. + * + * @jvms 6.5.dup2_x1 dup2_x1 + * @see Kind#STACK + */ DUP2_X1(RawBytecodeHelper.DUP2_X1, 1, Kind.STACK), - /** Duplicate the top one or two operand stack values and insert two, three, or four values down */ + /** + * Duplicate the top one or two operand stack values and insert two, three, + * or four values down. + * + * @jvms 6.5.dup2_x2 dup2_x2 + * @see Kind#STACK + */ DUP2_X2(RawBytecodeHelper.DUP2_X2, 1, Kind.STACK), - /** Swap the top two operand stack values */ + /** + * Swap the top two operand stack values. + * + * @jvms 6.5.swap swap + * @see Kind#STACK + */ SWAP(RawBytecodeHelper.SWAP, 1, Kind.STACK), - /** Add int */ + /** + * Add {@link TypeKind#INT int}. + * + * @jvms 6.5.iadd iadd + * @see Kind#OPERATOR + */ IADD(RawBytecodeHelper.IADD, 1, Kind.OPERATOR), - /** Add long */ + /** + * Add {@link TypeKind#LONG long}. + * + * @jvms 6.5.ladd ladd + * @see Kind#OPERATOR + */ LADD(RawBytecodeHelper.LADD, 1, Kind.OPERATOR), - /** Add float */ + /** + * Add {@link TypeKind#FLOAT float}. + * + * @jvms 6.5.fadd fadd + * @see Kind#OPERATOR + */ FADD(RawBytecodeHelper.FADD, 1, Kind.OPERATOR), - /** Add double */ + /** + * Add {@link TypeKind#DOUBLE double}. + * + * @jvms 6.5.dadd dadd + * @see Kind#OPERATOR + */ DADD(RawBytecodeHelper.DADD, 1, Kind.OPERATOR), - /** Subtract int */ + /** + * Subtract {@link TypeKind#INT int}. + * + * @jvms 6.5.isub isub + * @see Kind#OPERATOR + */ ISUB(RawBytecodeHelper.ISUB, 1, Kind.OPERATOR), - /** Subtract long */ + /** + * Subtract {@link TypeKind#LONG long}. + * + * @jvms 6.5.lsub lsub + * @see Kind#OPERATOR + */ LSUB(RawBytecodeHelper.LSUB, 1, Kind.OPERATOR), - /** Subtract float */ + /** + * Subtract {@link TypeKind#FLOAT float}. + * + * @jvms 6.5.fsub fsub + * @see Kind#OPERATOR + */ FSUB(RawBytecodeHelper.FSUB, 1, Kind.OPERATOR), - /** Subtract double */ + /** + * Subtract {@link TypeKind#DOUBLE double}. + * + * @jvms 6.5.dsub dsub + * @see Kind#OPERATOR + */ DSUB(RawBytecodeHelper.DSUB, 1, Kind.OPERATOR), - /** Multiply int */ + /** + * Multiply {@link TypeKind#INT int}. + * + * @jvms 6.5.imul imul + * @see Kind#OPERATOR + */ IMUL(RawBytecodeHelper.IMUL, 1, Kind.OPERATOR), - /** Multiply long */ + /** + * Multiply {@link TypeKind#LONG long}. + * + * @jvms 6.5.lmul lmul + * @see Kind#OPERATOR + */ LMUL(RawBytecodeHelper.LMUL, 1, Kind.OPERATOR), - /** Multiply float */ + /** + * Multiply {@link TypeKind#FLOAT float}. + * + * @jvms 6.5.fmul fmul + * @see Kind#OPERATOR + */ FMUL(RawBytecodeHelper.FMUL, 1, Kind.OPERATOR), - /** Multiply double */ + /** + * Multiply {@link TypeKind#DOUBLE double}. + * + * @jvms 6.5.dmul dmul + * @see Kind#OPERATOR + */ DMUL(RawBytecodeHelper.DMUL, 1, Kind.OPERATOR), - /** Divide int */ + /** + * Divide {@link TypeKind#INT int}. + * + * @jvms 6.5.idiv idiv + * @see Kind#OPERATOR + */ IDIV(RawBytecodeHelper.IDIV, 1, Kind.OPERATOR), - /** Divide long */ + /** + * Divide {@link TypeKind#LONG long}. + * + * @jvms 6.5.ldiv ldiv + * @see Kind#OPERATOR + */ LDIV(RawBytecodeHelper.LDIV, 1, Kind.OPERATOR), - /** Divide float */ + /** + * Divide {@link TypeKind#FLOAT float}. + * + * @jvms 6.5.fdiv fdiv + * @see Kind#OPERATOR + */ FDIV(RawBytecodeHelper.FDIV, 1, Kind.OPERATOR), - /** Divide double */ + /** + * Divide {@link TypeKind#DOUBLE double}. + * + * @jvms 6.5.ddiv ddiv + * @see Kind#OPERATOR + */ DDIV(RawBytecodeHelper.DDIV, 1, Kind.OPERATOR), - /** Remainder int */ + /** + * Remainder {@link TypeKind#INT int}. + * + * @jvms 6.5.irem irem + * @see Kind#OPERATOR + */ IREM(RawBytecodeHelper.IREM, 1, Kind.OPERATOR), - /** Remainder long */ + /** + * Remainder {@link TypeKind#LONG long}. + * + * @jvms 6.5.lrem lrem + * @see Kind#OPERATOR + */ LREM(RawBytecodeHelper.LREM, 1, Kind.OPERATOR), - /** Remainder float */ + /** + * Remainder {@link TypeKind#FLOAT float}. + * + * @jvms 6.5.frem frem + * @see Kind#OPERATOR + */ FREM(RawBytecodeHelper.FREM, 1, Kind.OPERATOR), - /** Remainder double */ + /** + * Remainder {@link TypeKind#DOUBLE double}. + * + * @jvms 6.5.drem drem + * @see Kind#OPERATOR + */ DREM(RawBytecodeHelper.DREM, 1, Kind.OPERATOR), - /** Negate int */ + /** + * Negate {@link TypeKind#INT int}. + * + * @jvms 6.5.ineg ineg + * @see Kind#OPERATOR + */ INEG(RawBytecodeHelper.INEG, 1, Kind.OPERATOR), - /** Negate long */ + /** + * Negate {@link TypeKind#LONG long}. + * + * @jvms 6.5.lneg lneg + * @see Kind#OPERATOR + */ LNEG(RawBytecodeHelper.LNEG, 1, Kind.OPERATOR), - /** Negate float */ + /** + * Negate {@link TypeKind#FLOAT float}. + * + * @jvms 6.5.fneg fneg + * @see Kind#OPERATOR + */ FNEG(RawBytecodeHelper.FNEG, 1, Kind.OPERATOR), - /** Negate double */ + /** + * Negate {@link TypeKind#DOUBLE double}. + * + * @jvms 6.5.dneg dneg + * @see Kind#OPERATOR + */ DNEG(RawBytecodeHelper.DNEG, 1, Kind.OPERATOR), - /** Shift left int */ + /** + * Shift left {@link TypeKind#INT int}. + * + * @jvms 6.5.ishl ishl + * @see Kind#OPERATOR + */ ISHL(RawBytecodeHelper.ISHL, 1, Kind.OPERATOR), - /** Shift left long */ + /** + * Shift left {@link TypeKind#LONG long}. + * + * @jvms 6.5.lshl lshl + * @see Kind#OPERATOR + */ LSHL(RawBytecodeHelper.LSHL, 1, Kind.OPERATOR), - /** Shift right int */ + /** + * Arithmetic shift right {@link TypeKind#INT int}. + * + * @jvms 6.5.ishr ishr + * @see Kind#OPERATOR + */ ISHR(RawBytecodeHelper.ISHR, 1, Kind.OPERATOR), - /** Shift right long */ + /** + * Arithmetic shift right {@link TypeKind#LONG long}. + * + * @jvms 6.5.lshr lshr + * @see Kind#OPERATOR + */ LSHR(RawBytecodeHelper.LSHR, 1, Kind.OPERATOR), - /** Logical shift right int */ + /** + * Logical shift right {@link TypeKind#INT int}. + * + * @jvms 6.5.iushr iushr + * @see Kind#OPERATOR + */ IUSHR(RawBytecodeHelper.IUSHR, 1, Kind.OPERATOR), - /** Logical shift right long */ + /** + * Logical shift right {@link TypeKind#LONG long}. + * + * @jvms 6.5.lushr lushr + * @see Kind#OPERATOR + */ LUSHR(RawBytecodeHelper.LUSHR, 1, Kind.OPERATOR), - /** Boolean AND int */ + /** + * Bitwise AND {@link TypeKind#INT int}. + * + * @apiNote + * This may be used to implement {@link TypeKind#BOOLEAN boolean} AND. + * + * @jvms 6.5.iand iand + * @see Kind#OPERATOR + */ IAND(RawBytecodeHelper.IAND, 1, Kind.OPERATOR), - /** Boolean AND long */ + /** + * Bitwise AND {@link TypeKind#LONG long}. + * + * @jvms 6.5.land land + * @see Kind#OPERATOR + */ LAND(RawBytecodeHelper.LAND, 1, Kind.OPERATOR), - /** Boolean OR int */ + /** + * Bitwise OR {@link TypeKind#INT int}. + * + * @apiNote + * This may be used to implement {@link TypeKind#BOOLEAN boolean} OR. + * + * @jvms 6.5.ior ior + * @see Kind#OPERATOR + */ IOR(RawBytecodeHelper.IOR, 1, Kind.OPERATOR), - /** Boolean OR long */ + /** + * Bitwise OR {@link TypeKind#LONG long}. + * + * @jvms 6.5.lor lor + * @see Kind#OPERATOR + */ LOR(RawBytecodeHelper.LOR, 1, Kind.OPERATOR), - /** Boolean XOR int */ + /** + * Bitwise XOR {@link TypeKind#INT int}. + * + * @apiNote + * This may be used to implement {@link TypeKind#BOOLEAN boolean} XOR. + * + * @jvms 6.5.ixor ixor + * @see Kind#OPERATOR + */ IXOR(RawBytecodeHelper.IXOR, 1, Kind.OPERATOR), - /** Boolean XOR long */ + /** + * Bitwise XOR {@link TypeKind#LONG long}. + * + * @jvms 6.5.lxor lxor + * @see Kind#OPERATOR + */ LXOR(RawBytecodeHelper.LXOR, 1, Kind.OPERATOR), - /** Increment local variable by constant */ + /** + * Increment local variable by constant. + * + * @jvms 6.5.iinc iinc + * @see Kind#INCREMENT + */ IINC(RawBytecodeHelper.IINC, 3, Kind.INCREMENT), - /** Convert int to long */ + /** + * Convert {@link TypeKind#INT int} to {@link TypeKind#LONG long}. + * + * @jls 5.1.2 Widening Primitive Conversion + * @jvms 6.5.i2l i2l + * @see Kind#CONVERT + */ I2L(RawBytecodeHelper.I2L, 1, Kind.CONVERT), - /** Convert int to float */ + /** + * Convert {@link TypeKind#INT int} to {@link TypeKind#FLOAT float}. + * + * @jls 5.1.2 Widening Primitive Conversion + * @jvms 6.5.i2f i2f + * @see Kind#CONVERT + */ I2F(RawBytecodeHelper.I2F, 1, Kind.CONVERT), - /** Convert int to double */ + /** + * Convert {@link TypeKind#INT int} to {@link TypeKind#DOUBLE double}. + * + * @jls 5.1.2 Widening Primitive Conversion + * @jvms 6.5.i2d i2d + * @see Kind#CONVERT + */ I2D(RawBytecodeHelper.I2D, 1, Kind.CONVERT), - /** Convert long to int */ + /** + * Convert {@link TypeKind#LONG long} to {@link TypeKind#INT int}. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.l2i l2i + * @see Kind#CONVERT + */ L2I(RawBytecodeHelper.L2I, 1, Kind.CONVERT), - /** Convert long to float */ + /** Convert {@link TypeKind#LONG long} to {@link TypeKind#FLOAT float}. + * + * @jls 5.1.2 Widening Primitive Conversion + * @jvms 6.5.l2f l2f + * @see Kind#CONVERT + */ L2F(RawBytecodeHelper.L2F, 1, Kind.CONVERT), - /** Convert long to double */ + /** Convert {@link TypeKind#LONG long} to {@link TypeKind#DOUBLE double}. + * + * @jls 5.1.2 Widening Primitive Conversion + * @jvms 6.5.l2d l2d + * @see Kind#CONVERT + */ L2D(RawBytecodeHelper.L2D, 1, Kind.CONVERT), - /** Convert float to int */ + /** + * Convert {@link TypeKind#FLOAT float} to {@link TypeKind#INT int}. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.f2i f2i + * @see Kind#CONVERT + */ F2I(RawBytecodeHelper.F2I, 1, Kind.CONVERT), - /** Convert float to long */ + /** + * Convert {@link TypeKind#FLOAT float} to {@link TypeKind#LONG long}. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.f2l f2l + * @see Kind#CONVERT + */ F2L(RawBytecodeHelper.F2L, 1, Kind.CONVERT), - /** Convert float to double */ + /** + * Convert {@link TypeKind#FLOAT float} to {@link TypeKind#DOUBLE double}. + * + * @jls 5.1.2 Widening Primitive Conversion + * @jvms 6.5.f2d f2d + * @see Kind#CONVERT + */ F2D(RawBytecodeHelper.F2D, 1, Kind.CONVERT), - /** Convert double to int */ + /** + * Convert {@link TypeKind#DOUBLE double} to {@link TypeKind#INT int}. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.d2i d2i + * @see Kind#CONVERT + */ D2I(RawBytecodeHelper.D2I, 1, Kind.CONVERT), - /** Convert double to long */ + /** + * Convert {@link TypeKind#DOUBLE double} to {@link TypeKind#LONG long}. + * + * @jvms 6.5.d2l d2l + * @see Kind#CONVERT + */ D2L(RawBytecodeHelper.D2L, 1, Kind.CONVERT), - /** Convert double to float */ + /** + * Convert {@link TypeKind#DOUBLE double} to {@link TypeKind#FLOAT float}. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.d2f d2f + * @see Kind#CONVERT + */ D2F(RawBytecodeHelper.D2F, 1, Kind.CONVERT), - /** Convert int to byte */ + /** + * Convert {@link TypeKind#INT int} to {@link TypeKind#BYTE byte}. + * This is as if storing the {@linkplain TypeKind##computational-type + * computational} {@code int} into a {@code byte} and loading it back. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.i2b i2b + * @see Kind#CONVERT + */ I2B(RawBytecodeHelper.I2B, 1, Kind.CONVERT), - /** Convert int to char */ + /** + * Convert {@link TypeKind#INT int} to {@link TypeKind#CHAR char}. + * This is as if storing the {@linkplain TypeKind##computational-type + * computational} {@code int} into a {@code char} and loading it back. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.i2c i2c + * @see Kind#CONVERT + */ I2C(RawBytecodeHelper.I2C, 1, Kind.CONVERT), - /** Convert int to short */ + /** + * Convert {@link TypeKind#INT int} to {@link TypeKind#SHORT short}. + * This is as if storing the {@linkplain TypeKind##computational-type + * computational} {@code int} into a {@code short} and loading it back. + * + * @jls 5.1.3 Narrowing Primitive Conversion + * @jvms 6.5.i2s i2s + * @see Kind#CONVERT + */ I2S(RawBytecodeHelper.I2S, 1, Kind.CONVERT), - /** Compare long */ + /** + * Compare {@link TypeKind#LONG long}. + * + * @see Long#compare(long, long) + * @jvms 6.5.lcmp lcmp + * @see Kind#OPERATOR + */ LCMP(RawBytecodeHelper.LCMP, 1, Kind.OPERATOR), - /** Compare float */ + /** + * Compare {@link TypeKind#FLOAT float}. + * Produces {@code -1} if any operand is {@link Float#isNaN(float) NaN}. + * + * @see Double##equivalenceRelation Floating-point Equality, Equivalence, and Comparison + * @jvms 6.5.fcmp_op fcmp<op> + * @see Kind#OPERATOR + */ FCMPL(RawBytecodeHelper.FCMPL, 1, Kind.OPERATOR), - /** Compare float */ + /** + * Compare {@link TypeKind#FLOAT float}. + * Produces {@code 1} if any operand is {@link Float#isNaN(float) NaN}. + * + * @see Double##equivalenceRelation Floating-point Equality, Equivalence, and Comparison + * @jvms 6.5.fcmp_op fcmp<op> + * @see Kind#OPERATOR + */ FCMPG(RawBytecodeHelper.FCMPG, 1, Kind.OPERATOR), - /** Compare double */ + /** + * Compare {@link TypeKind#DOUBLE double}. + * Produces {@code -1} if any operand is {@link Double#isNaN(double) NaN}. + * + * @see Double##equivalenceRelation Floating-point Equality, Equivalence, and Comparison + * @jvms 6.5.dcmp_op dcmp<op> + * @see Kind#OPERATOR + */ DCMPL(RawBytecodeHelper.DCMPL, 1, Kind.OPERATOR), - /** Compare double */ + /** + * Compare {@link TypeKind#DOUBLE double}. + * Produces {@code 1} if any operand is {@link Double#isNaN(double) NaN}. + * + * @see Double##equivalenceRelation Floating-point Equality, Equivalence, and Comparison + * @jvms 6.5.dcmp_op dcmp<op> + * @see Kind#OPERATOR + */ DCMPG(RawBytecodeHelper.DCMPG, 1, Kind.OPERATOR), - /** Branch if int comparison with zero succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code == 0} succeeds. + * + * @jvms 6.5.if_cond if_<cond> + * @see Kind#BRANCH + */ IFEQ(RawBytecodeHelper.IFEQ, 3, Kind.BRANCH), - /** Branch if int comparison with zero succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code != 0} succeeds. + * + * @jvms 6.5.if_cond if_<cond> + * @see Kind#BRANCH + */ IFNE(RawBytecodeHelper.IFNE, 3, Kind.BRANCH), - /** Branch if int comparison with zero succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code < 0} succeeds. + * + * @jvms 6.5.if_cond if_<cond> + * @see Kind#BRANCH + */ IFLT(RawBytecodeHelper.IFLT, 3, Kind.BRANCH), - /** Branch if int comparison with zero succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code >= 0} succeeds. + * + * @jvms 6.5.if_cond if_<cond> + * @see Kind#BRANCH + */ IFGE(RawBytecodeHelper.IFGE, 3, Kind.BRANCH), - /** Branch if int comparison with zero succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code > 0} succeeds. + * + * @jvms 6.5.if_cond if_<cond> + * @see Kind#BRANCH + */ IFGT(RawBytecodeHelper.IFGT, 3, Kind.BRANCH), - /** Branch if int comparison with zero succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code <= 0} succeeds. + * + * @jvms 6.5.if_cond if_<cond> + * @see Kind#BRANCH + */ IFLE(RawBytecodeHelper.IFLE, 3, Kind.BRANCH), - /** Branch if int comparison succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code operand1 == operand2} succeeds. + * + * @jvms 6.5.if_icmp_cond if_icmp<cond> + * @see Kind#BRANCH + */ IF_ICMPEQ(RawBytecodeHelper.IF_ICMPEQ, 3, Kind.BRANCH), - /** Branch if int comparison succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code operand1 != operand2} succeeds. + * + * @jvms 6.5.if_icmp_cond if_icmp<cond> + * @see Kind#BRANCH + */ IF_ICMPNE(RawBytecodeHelper.IF_ICMPNE, 3, Kind.BRANCH), - /** Branch if int comparison succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code operand1 < operand2} succeeds. + * + * @jvms 6.5.if_icmp_cond if_icmp<cond> + * @see Kind#BRANCH + */ IF_ICMPLT(RawBytecodeHelper.IF_ICMPLT, 3, Kind.BRANCH), - /** Branch if int comparison succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code operand1 >= operand2} succeeds. + * + * @jvms 6.5.if_icmp_cond if_icmp<cond> + * @see Kind#BRANCH + */ IF_ICMPGE(RawBytecodeHelper.IF_ICMPGE, 3, Kind.BRANCH), - /** Branch if int comparison succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code operand1 > operand2} succeeds. + * + * @jvms 6.5.if_icmp_cond if_icmp<cond> + * @see Kind#BRANCH + */ IF_ICMPGT(RawBytecodeHelper.IF_ICMPGT, 3, Kind.BRANCH), - /** Branch if int comparison succeeds */ + /** + * Branch if {@link TypeKind#INT int} comparison {@code operand1 <= operand2} succeeds. + * + * @jvms 6.5.if_icmp_cond if_icmp<cond> + * @see Kind#BRANCH + */ IF_ICMPLE(RawBytecodeHelper.IF_ICMPLE, 3, Kind.BRANCH), - /** Branch if reference comparison succeeds */ + /** + * Branch if {@link TypeKind#REFERENCE reference} comparison + * {@code operand1 == operand2} succeeds. + * + * @jvms 6.5.if_acmp_cond if_acmp<cond> + * @see Kind#BRANCH + */ IF_ACMPEQ(RawBytecodeHelper.IF_ACMPEQ, 3, Kind.BRANCH), - /** Branch if reference comparison succeeds */ + /** + * Branch if {@link TypeKind#REFERENCE reference} comparison + * {@code operand1 != operand2} succeeds. + * + * @jvms 6.5.if_acmp_cond if_acmp<cond> + * @see Kind#BRANCH + */ IF_ACMPNE(RawBytecodeHelper.IF_ACMPNE, 3, Kind.BRANCH), - /** Branch always */ + /** + * Branch always. + * + * @jvms 6.5.goto goto + * @see Kind#BRANCH + */ GOTO(RawBytecodeHelper.GOTO, 3, Kind.BRANCH), /** - * Jump subroutine is discontinued opcode - * @see java.lang.classfile.instruction.DiscontinuedInstruction + * (Discontinued) Jump subroutine; last used in major version {@value + * ClassFile#JAVA_6_VERSION}. + * + * @jvms 4.9.1 Static Constraints + * @jvms 6.5.jsr jsr + * @see Kind#DISCONTINUED_JSR */ JSR(RawBytecodeHelper.JSR, 3, Kind.DISCONTINUED_JSR), /** - * Return from subroutine is discontinued opcode - * @see java.lang.classfile.instruction.DiscontinuedInstruction + * (Discontinued) Return from subroutine; last used in major version + * {@value ClassFile#JAVA_6_VERSION}. + * + * @jvms 4.9.1 Static Constraints + * @jvms 6.5.ret ret + * @see Kind#DISCONTINUED_RET */ RET(RawBytecodeHelper.RET, 2, Kind.DISCONTINUED_RET), - /** Access jump table by index and jump */ + /** + * Access jump table by index and jump. + * + * @jvms 6.5.tableswitch tableswitch + * @see Kind#TABLE_SWITCH + */ TABLESWITCH(RawBytecodeHelper.TABLESWITCH, -1, Kind.TABLE_SWITCH), - /** Access jump table by key match and jump */ + /** + * Access jump table by key match and jump. + * + * @jvms 6.5.lookupswitch lookupswitch + * @see Kind#LOOKUP_SWITCH + */ LOOKUPSWITCH(RawBytecodeHelper.LOOKUPSWITCH, -1, Kind.LOOKUP_SWITCH), - /** Return int from method */ + /** + * Return {@link TypeKind#INT int} from method. + * + * @jvms 6.5.ireturn ireturn + * @see Kind#RETURN + */ IRETURN(RawBytecodeHelper.IRETURN, 1, Kind.RETURN), - /** Return long from method */ + /** + * Return {@link TypeKind#LONG long} from method. + * + * @jvms 6.5.lreturn lreturn + * @see Kind#RETURN + */ LRETURN(RawBytecodeHelper.LRETURN, 1, Kind.RETURN), - /** Return float from method */ + /** + * Return {@link TypeKind#FLOAT float} from method. + * + * @jvms 6.5.freturn freturn + * @see Kind#RETURN + */ FRETURN(RawBytecodeHelper.FRETURN, 1, Kind.RETURN), - /** Return double from method */ + /** + * Return {@link TypeKind#DOUBLE double} from method. + * + * @jvms 6.5.dreturn dreturn + * @see Kind#RETURN + */ DRETURN(RawBytecodeHelper.DRETURN, 1, Kind.RETURN), - /** Return reference from method */ + /** + * Return {@link TypeKind#REFERENCE reference} from method. + * + * @jvms 6.5.areturn areturn + * @see Kind#RETURN + */ ARETURN(RawBytecodeHelper.ARETURN, 1, Kind.RETURN), - /** Return void from method */ + /** + * Return {@link TypeKind#VOID void} from method. + * + * @jvms 6.5.return return + * @see Kind#RETURN + */ RETURN(RawBytecodeHelper.RETURN, 1, Kind.RETURN), - /** Get static field from class */ + /** + * Get {@code static} field from class. + * + * @jvms 6.5.getstatic getstatic + * @see Kind#FIELD_ACCESS + */ GETSTATIC(RawBytecodeHelper.GETSTATIC, 3, Kind.FIELD_ACCESS), - /** Set static field in class */ + /** + * Set {@code static} field in class. + * + * @jvms 6.5.putstatic putstatic + * @see Kind#FIELD_ACCESS + */ PUTSTATIC(RawBytecodeHelper.PUTSTATIC, 3, Kind.FIELD_ACCESS), - /** Fetch field from object */ + /** + * Fetch field from object. + * + * @jvms 6.5.getfield getfield + * @see Kind#FIELD_ACCESS + */ GETFIELD(RawBytecodeHelper.GETFIELD, 3, Kind.FIELD_ACCESS), - /** Set field in object */ + /** + * Set field in object. + * + * @jvms 6.5.putfield putfield + * @see Kind#FIELD_ACCESS + */ PUTFIELD(RawBytecodeHelper.PUTFIELD, 3, Kind.FIELD_ACCESS), - /** Invoke instance method; dispatch based on class */ + /** + * Invoke instance method; dispatch based on class. + * + * @jvms 6.5.invokevirtual invokevirtual + * @see Kind#INVOKE + */ INVOKEVIRTUAL(RawBytecodeHelper.INVOKEVIRTUAL, 3, Kind.INVOKE), /** * Invoke instance method; direct invocation of instance initialization - * methods and methods of the current class and its supertypes + * methods and methods of the current class and its supertypes. + * + * @jvms 6.5.invokevirtual invokevirtual + * @see Kind#INVOKE */ INVOKESPECIAL(RawBytecodeHelper.INVOKESPECIAL, 3, Kind.INVOKE), - /** Invoke a class (static) method */ + /** + * Invoke a class ({@code static}) method. + * + * @jvms 6.5.invokestatic invokestatic + * @see Kind#INVOKE + */ INVOKESTATIC(RawBytecodeHelper.INVOKESTATIC, 3, Kind.INVOKE), - /** Invoke interface method */ + /** + * Invoke interface method. + * + * @jvms 6.5.invokeinterface invokeinterface + * @see Kind#INVOKE + */ INVOKEINTERFACE(RawBytecodeHelper.INVOKEINTERFACE, 5, Kind.INVOKE), - /** Invoke a dynamically-computed call site */ + /** + * Invoke a dynamically-computed call site. + * + * @jvms 6.5.invokedynamic invokedynamic + * @see Kind#INVOKE_DYNAMIC + */ INVOKEDYNAMIC(RawBytecodeHelper.INVOKEDYNAMIC, 5, Kind.INVOKE_DYNAMIC), - /** Create new object */ + /** + * Create new object. + * + * @jvms 6.5.new new + * @see Kind#NEW_OBJECT + */ NEW(RawBytecodeHelper.NEW, 3, Kind.NEW_OBJECT), - /** Create new array */ + /** + * Create new array. + * + * @jvms 6.5.newarray newarray + * @see Kind#NEW_PRIMITIVE_ARRAY + */ NEWARRAY(RawBytecodeHelper.NEWARRAY, 2, Kind.NEW_PRIMITIVE_ARRAY), - /** Create new array of reference */ + /** + * Create new array of {@link TypeKind#REFERENCE reference}. + * + * @jvms 6.5.anewarray anewarray + * @see Kind#NEW_REF_ARRAY + */ ANEWARRAY(RawBytecodeHelper.ANEWARRAY, 3, Kind.NEW_REF_ARRAY), - /** Get length of array */ + /** + * Get length of array. + * + * @jvms 6.5.arraylength arraylength + * @see Kind#OPERATOR + */ ARRAYLENGTH(RawBytecodeHelper.ARRAYLENGTH, 1, Kind.OPERATOR), - /** Throw exception or error */ + /** + * Throw exception or error. + * + * @jvms 6.5.athrow athrow + * @see Kind#THROW_EXCEPTION + */ ATHROW(RawBytecodeHelper.ATHROW, 1, Kind.THROW_EXCEPTION), - /** Check whether object is of given type */ + /** + * Check whether object is of given type. + * + * @see Class#cast(Object) + * @jvms 6.5.checkcast checkcast + * @see Kind#TYPE_CHECK + */ CHECKCAST(RawBytecodeHelper.CHECKCAST, 3, Kind.TYPE_CHECK), - /** Determine if object is of given type */ + /** + * Determine if object is of given type. + * + * @see Class#isInstance(Object) + * @jvms 6.5.instanceof instanceof + * @see Kind#TYPE_CHECK + */ INSTANCEOF(RawBytecodeHelper.INSTANCEOF, 3, Kind.TYPE_CHECK), - /** Enter monitor for object */ + /** + * Enter monitor for object. + * + * @jvms 6.5.monitorenter monitorenter + * @see Kind#MONITOR + */ MONITORENTER(RawBytecodeHelper.MONITORENTER, 1, Kind.MONITOR), - /** Exit monitor for object */ + /** + * Exit monitor for object. + * + * @jvms 6.5.monitorexit monitorexit + * @see Kind#MONITOR + */ MONITOREXIT(RawBytecodeHelper.MONITOREXIT, 1, Kind.MONITOR), - /** Create new multidimensional array */ + /** + * Create new multidimensional array. + * + * @jvms 6.5.multianewarray multianewarray + * @see Kind#NEW_MULTI_ARRAY + */ MULTIANEWARRAY(RawBytecodeHelper.MULTIANEWARRAY, 4, Kind.NEW_MULTI_ARRAY), - /** Branch if reference is null */ + /** + * Branch if {@link TypeKind#REFERENCE reference} is {@code null}. + * + * @jvms 6.5.ifnull ifnull + * @see Kind#BRANCH + */ IFNULL(RawBytecodeHelper.IFNULL, 3, Kind.BRANCH), - /** Branch if reference not null */ + /** + * Branch if {@link TypeKind#REFERENCE reference} is not {@code null}. + * + * @jvms 6.5.ifnonnull ifnonnull + * @see Kind#BRANCH + */ IFNONNULL(RawBytecodeHelper.IFNONNULL, 3, Kind.BRANCH), - /** Branch always (wide index) */ + /** + * Branch always (wide index). + * + * @jvms 6.5.goto_w goto_w + * @see Kind#BRANCH + */ GOTO_W(RawBytecodeHelper.GOTO_W, 5, Kind.BRANCH), /** - * Jump subroutine (wide index) is discontinued opcode - * @see java.lang.classfile.instruction.DiscontinuedInstruction + * (Discontinued) Jump subroutine (wide index); last used in major + * version {@value ClassFile#JAVA_6_VERSION}. + * + * @jvms 4.9.1 Static Constraints + * @jvms 6.5.jsr_w jsr_w + * @see Kind#DISCONTINUED_JSR */ JSR_W(RawBytecodeHelper.JSR_W, 5, Kind.DISCONTINUED_JSR), - /** Load int from local variable (wide index) */ + /** + * Load {@link TypeKind#INT int} from local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.iload iload + * @see Kind#LOAD + */ ILOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ILOAD, 4, Kind.LOAD), - /** Load long from local variable (wide index) */ + /** + * Load {@link TypeKind#LONG long} from local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.lload lload + * @see Kind#LOAD + */ LLOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.LLOAD, 4, Kind.LOAD), - /** Load float from local variable (wide index) */ + /** + * Load {@link TypeKind#FLOAT float} from local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.fload fload + * @see Kind#LOAD + */ FLOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.FLOAD, 4, Kind.LOAD), - /** Load double from local variable (wide index) */ + /** + * Load {@link TypeKind#DOUBLE double} from local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.dload dload + * @see Kind#LOAD + */ DLOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.DLOAD, 4, Kind.LOAD), - /** Load reference from local variable (wide index) */ + /** + * Load {@link TypeKind#REFERENCE reference} from local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.aload aload + * @see Kind#LOAD + */ ALOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ALOAD, 4, Kind.LOAD), - /** Store int into local variable (wide index) */ + /** + * Store {@link TypeKind#INT int} into local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.istore istore + * @see Kind#STORE + */ ISTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ISTORE, 4, Kind.STORE), - /** Store long into local variable (wide index) */ + /** + * Store {@link TypeKind#LONG long} into local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.lstore lstore + * @see Kind#STORE + */ LSTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.LSTORE, 4, Kind.STORE), - /** Store float into local variable (wide index) */ + /** + * Store {@link TypeKind#FLOAT float} into local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.fstore fstore + * @see Kind#STORE + */ FSTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.FSTORE, 4, Kind.STORE), - /** Store double into local variable (wide index) */ + /** + * Store {@link TypeKind#DOUBLE double} into local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.dstore dstore + * @see Kind#STORE + */ DSTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.DSTORE, 4, Kind.STORE), - /** Store reference into local variable (wide index) */ + /** + * Store {@link TypeKind#REFERENCE reference} into local variable (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * Can also store the {@link TypeKind##returnAddress returnAddress} type. + * + * @jvms 6.5.wide wide + * @jvms 6.5.astore astore + * @see Kind#STORE + */ ASTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ASTORE, 4, Kind.STORE), /** - * Return from subroutine (wide index) is discontinued opcode - * @see java.lang.classfile.instruction.DiscontinuedInstruction + * (Discontinued) Return from subroutine (wide index); last used in major + * version {@value ClassFile#JAVA_6_VERSION}. + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 4.9.1 Static Constraints + * @jvms 6.5.wide wide + * @jvms 6.5.ret ret + * @see Kind#DISCONTINUED_RET */ RET_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.RET, 4, Kind.DISCONTINUED_RET), - /** Increment local variable by constant (wide index) */ + /** + * Increment local variable by constant (wide index). + * This is a {@linkplain #isWide() wide}-modified pseudo-opcode. + * + * @jvms 6.5.wide wide + * @jvms 6.5.iinc iinc + * @see Kind#INCREMENT + */ IINC_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.IINC, 6, Kind.INCREMENT); /** - * Kinds of opcodes. + * Kinds of opcodes. Each kind of opcode has its own modeling interface + * for its instructions. * * @since 24 */ - public static enum Kind { + public enum Kind { /** - * Load from local variable + * Load from local variable. * + * @see LoadInstruction * @see Opcode#ILOAD * @see Opcode#LLOAD * @see Opcode#FLOAD @@ -736,8 +1901,9 @@ public static enum Kind { LOAD, /** - * Store into local variable + * Store into local variable. * + * @see StoreInstruction * @see Opcode#ISTORE * @see Opcode#LSTORE * @see Opcode#FSTORE @@ -772,16 +1938,18 @@ public static enum Kind { STORE, /** - * Increment local variable + * Increment local variable. * + * @see IncrementInstruction * @see Opcode#IINC * @see Opcode#IINC_W */ INCREMENT, /** - * Branch + * Branch. * + * @see BranchInstruction * @see Opcode#IFEQ * @see Opcode#IFNE * @see Opcode#IFLT @@ -804,22 +1972,25 @@ public static enum Kind { BRANCH, /** - * Access jump table by key match and jump + * Access jump table by key match and jump. * + * @see LookupSwitchInstruction * @see Opcode#LOOKUPSWITCH */ LOOKUP_SWITCH, /** - * Access jump table by index and jump + * Access jump table by index and jump. * + * @see TableSwitchInstruction * @see Opcode#TABLESWITCH */ TABLE_SWITCH, /** - * Return from method + * Return from method. * + * @see ReturnInstruction * @see Opcode#IRETURN * @see Opcode#LRETURN * @see Opcode#FRETURN @@ -830,15 +2001,17 @@ public static enum Kind { RETURN, /** - * Throw exception or error + * Throw exception or error. * + * @see ThrowInstruction * @see Opcode#ATHROW */ THROW_EXCEPTION, /** - * Access field + * Access field. * + * @see FieldInstruction * @see Opcode#GETSTATIC * @see Opcode#PUTSTATIC * @see Opcode#GETFIELD @@ -847,8 +2020,9 @@ public static enum Kind { FIELD_ACCESS, /** - * Invoke method or constructor + * Invoke method or constructor. * + * @see InvokeInstruction * @see Opcode#INVOKEVIRTUAL * @see Opcode#INVOKESPECIAL * @see Opcode#INVOKESTATIC @@ -857,51 +2031,58 @@ public static enum Kind { INVOKE, /** - * Invoke a dynamically-computed call site + * Invoke a dynamically-computed call site. * + * @see InvokeDynamicInstruction * @see Opcode#INVOKEDYNAMIC */ INVOKE_DYNAMIC, /** - * Create new object + * Create new object. * + * @see NewObjectInstruction * @see Opcode#NEW */ NEW_OBJECT, /** - * Create new array + * Create new array. * + * @see NewPrimitiveArrayInstruction * @see Opcode#NEWARRAY */ NEW_PRIMITIVE_ARRAY, /** - * Create new reference array + * Create new {@link TypeKind#REFERENCE reference} array. * + * @see NewReferenceArrayInstruction * @see Opcode#ANEWARRAY */ NEW_REF_ARRAY, /** - * Create new multidimensional array + * Create new multidimensional array. * + * @see NewMultiArrayInstruction * @see Opcode#MULTIANEWARRAY */ NEW_MULTI_ARRAY, /** - * Check whether object is of given type + * Check whether object is of given type. * + * @see TypeCheckInstruction * @see Opcode#CHECKCAST * @see Opcode#INSTANCEOF */ TYPE_CHECK, /** - * Load from array + * Load from array. * + * @see ArrayLoadInstruction * @see Opcode#IALOAD * @see Opcode#LALOAD * @see Opcode#FALOAD @@ -914,8 +2095,9 @@ public static enum Kind { ARRAY_LOAD, /** - * Store into array + * Store into array. * + * @see ArrayStoreInstruction * @see Opcode#IASTORE * @see Opcode#LASTORE * @see Opcode#FASTORE @@ -928,8 +2110,9 @@ public static enum Kind { ARRAY_STORE, /** - * Stack operations + * Stack operations. * + * @see StackInstruction * @see Opcode#POP * @see Opcode#POP2 * @see Opcode#DUP @@ -943,8 +2126,9 @@ public static enum Kind { STACK, /** - * Type conversions + * Type conversions. * + * @see ConvertInstruction * @see Opcode#I2L * @see Opcode#I2F * @see Opcode#I2D @@ -964,8 +2148,9 @@ public static enum Kind { CONVERT, /** - * Operators + * Operators. * + * @see OperatorInstruction * @see Opcode#IADD * @see Opcode#LADD * @see Opcode#FADD @@ -1012,8 +2197,9 @@ public static enum Kind { OPERATOR, /** - * Constants + * Constants. * + * @see ConstantInstruction * @see Opcode#ACONST_NULL * @see Opcode#ICONST_M1 * @see Opcode#ICONST_0 @@ -1038,35 +2224,37 @@ public static enum Kind { CONSTANT, /** - * Monitor + * Monitor. * + * @see MonitorInstruction * @see Opcode#MONITORENTER * @see Opcode#MONITOREXIT */ MONITOR, /** - * Do nothing + * Do nothing. * + * @see NopInstruction * @see Opcode#NOP */ NOP, /** - * Discontinued jump subroutine + * Discontinued jump subroutine. * + * @see DiscontinuedInstruction.JsrInstruction * @see Opcode#JSR * @see Opcode#JSR_W - * @see java.lang.classfile.instruction.DiscontinuedInstruction */ DISCONTINUED_JSR, /** - * Discontinued return from subroutine + * Discontinued return from subroutine. * + * @see DiscontinuedInstruction.RetInstruction * @see Opcode#RET * @see Opcode#RET_W - * @see java.lang.classfile.instruction.DiscontinuedInstruction */ DISCONTINUED_RET; } @@ -1090,7 +2278,10 @@ public static enum Kind { /** * {@return true if this is a pseudo-opcode modified by wide opcode} + *
+ * {@code wide} extends local variable index by additional bytes. * + * @jvms 6.5.wide wide * @see #ILOAD_W * @see #LLOAD_W * @see #FLOAD_W @@ -1109,11 +2300,14 @@ public static enum Kind { /** * {@return size of the instruction in bytes if fixed, or -1 otherwise} This size includes * the opcode itself. + * + * @see Instruction#sizeInBytes() Instruction::sizeInBytes */ public int sizeIfFixed() { return sizeIfFixed; } /** - * {@return instruction kind} + * {@return operation kind} Each kind of operation has its own modeling + * interface to model instructions belonging to that kind. */ public Kind kind() { return kind; } } diff --git a/src/java.base/share/classes/java/lang/classfile/TypeKind.java b/src/java.base/share/classes/java/lang/classfile/TypeKind.java index 5a6475aa801..e3fc11858f5 100644 --- a/src/java.base/share/classes/java/lang/classfile/TypeKind.java +++ b/src/java.base/share/classes/java/lang/classfile/TypeKind.java @@ -26,6 +26,9 @@ package java.lang.classfile; import java.lang.classfile.instruction.DiscontinuedInstruction; +import java.lang.classfile.instruction.LoadInstruction; +import java.lang.classfile.instruction.NewPrimitiveArrayInstruction; +import java.lang.classfile.instruction.StoreInstruction; import java.lang.constant.ClassDesc; import java.lang.constant.ConstantDescs; import java.lang.invoke.TypeDescriptor; @@ -33,13 +36,17 @@ import jdk.internal.vm.annotation.Stable; /** - * Describes the data types Java Virtual Machine operates on. - * This omits {@code returnAddress} (JVMS {@jvms 2.3.3}), - * which is only used by discontinued {@link - * DiscontinuedInstruction.JsrInstruction jsr} and {@link - * DiscontinuedInstruction.RetInstruction ret} instructions, - * and includes {@link #VOID void} (JVMS {@jvms 4.3.3}), which - * appears as a method return type. + * Describes the data types Java Virtual Machine operates on. This omits {@code + * returnAddress} (JVMS {@jvms 2.3.3}) and includes {@link #VOID void} (JVMS + * {@jvms 4.3.3}), which appears as a method return type. + *
+ * The {@index returnAddress}
type is only used by discontinued
+ * {@linkplain DiscontinuedInstruction.JsrInstruction jump subroutine} and
+ * {@linkplain DiscontinuedInstruction.RetInstruction return from subroutine}
+ * instructions. Jump subroutine instructions push {@code returnAddress} to the
+ * operand stack; {@link StoreInstruction astore} instructions store {@code
+ * returnAddress} from the operand stack to local variables; return from
+ * subroutine instructions load {@code returnAddress} from local variables.
*
*
+ * An array load instruction is composite: + * {@snippet lang=text : + * // @link substring="ArrayLoadInstruction" target="CodeBuilder#arrayLoad(TypeKind)" : + * ArrayLoadInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind" + * } + * where {@code typeKind} is not {@link TypeKind#VOID void}, and {@link + * TypeKind#BOOLEAN boolean} is converted to {@link TypeKind#BYTE byte}. * + * @see Opcode.Kind#ARRAY_LOAD + * @see CodeBuilder#arrayLoad CodeBuilder::arrayLoad * @since 24 */ public sealed interface ArrayLoadInstruction extends Instruction permits AbstractInstruction.UnboundArrayLoadInstruction { /** - * {@return the component type of the array} The {@link TypeKind#BYTE byte} + * {@return the component type of the array} The {@link TypeKind#BYTE byte} * type load instruction {@link Opcode#BALOAD baload} also operates on - * {@link TypeKind#BOOLEAN boolean} arrays. + * {@link TypeKind#BOOLEAN boolean} arrays, so this never returns + * {@code boolean}. */ TypeKind typeKind(); @@ -56,7 +68,7 @@ public sealed interface ArrayLoadInstruction extends Instruction * @param op the opcode for the specific type of array load instruction, * which must be of kind {@link Opcode.Kind#ARRAY_LOAD} * @throws IllegalArgumentException if the opcode kind is not - * {@link Opcode.Kind#ARRAY_LOAD}. + * {@link Opcode.Kind#ARRAY_LOAD} */ static ArrayLoadInstruction of(Opcode op) { Util.checkKind(op, Opcode.Kind.ARRAY_LOAD); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java index c350b3a5928..e5883a2cd2a 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ArrayStoreInstruction.java @@ -24,6 +24,7 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; @@ -35,18 +36,29 @@ /** * Models an array store instruction in the {@code code} array of a {@code Code} - * attribute. Corresponding opcodes will have a {@code kind} of {@link - * Opcode.Kind#ARRAY_STORE}. Delivered as a {@link CodeElement} when + * attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} + * of {@link Opcode.Kind#ARRAY_STORE}. Delivered as a {@link CodeElement} when * traversing the elements of a {@link CodeModel}. + *
+ * An array store instruction is composite: + * {@snippet lang=text : + * // @link substring="ArrayStoreInstruction" target="CodeBuilder#arrayStore(TypeKind)" : + * ArrayStoreInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind" + * } + * where {@code typeKind} is not {@link TypeKind#VOID void}, and {@link + * TypeKind#BOOLEAN boolean} is converted to {@link TypeKind#BYTE byte}. * + * @see Opcode.Kind#ARRAY_STORE + * @see CodeBuilder#arrayStore CodeBuilder::arrayStore * @since 24 */ public sealed interface ArrayStoreInstruction extends Instruction permits AbstractInstruction.UnboundArrayStoreInstruction { /** - * {@return the component type of the array} The {@link TypeKind#BYTE byte} + * {@return the component type of the array} The {@link TypeKind#BYTE byte} * type store instruction {@link Opcode#BASTORE bastore} also operates on - * {@link TypeKind#BOOLEAN boolean} arrays. + * {@link TypeKind#BOOLEAN boolean} arrays, so this never returns + * {@code boolean}. */ TypeKind typeKind(); @@ -56,7 +68,7 @@ public sealed interface ArrayStoreInstruction extends Instruction * @param op the opcode for the specific type of array store instruction, * which must be of kind {@link Opcode.Kind#ARRAY_STORE} * @throws IllegalArgumentException if the opcode kind is not - * {@link Opcode.Kind#ARRAY_STORE}. + * {@link Opcode.Kind#ARRAY_STORE} */ static ArrayStoreInstruction of(Opcode op) { Util.checkKind(op, Opcode.Kind.ARRAY_STORE); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/BranchInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/BranchInstruction.java index 2fdc00fced1..a37e37980d4 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/BranchInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/BranchInstruction.java @@ -24,28 +24,41 @@ */ package java.lang.classfile.instruction; -import java.lang.classfile.CodeElement; -import java.lang.classfile.CodeModel; -import java.lang.classfile.Instruction; -import java.lang.classfile.Label; -import java.lang.classfile.Opcode; +import java.lang.classfile.*; import jdk.internal.classfile.impl.AbstractInstruction; import jdk.internal.classfile.impl.Util; /** * Models a branching instruction (conditional or unconditional) in the {@code - * code} array of a {@code Code} attribute. Corresponding opcodes will have a - * {@code kind} of {@link Opcode.Kind#BRANCH}. Delivered as a {@link - * CodeElement} when traversing the elements of a {@link CodeModel}. + * code} array of a {@code Code} attribute. Corresponding opcodes have a + * {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#BRANCH}. Delivered as + * a {@link CodeElement} when traversing the elements of a {@link CodeModel}. + *
+ * A branch instruction is composite: + * {@snippet lang=text : + * // @link substring="BranchInstruction" target="#of": + * BranchInstruction( + * Opcode opcode, // @link substring="opcode" target="#opcode()" + * Label target // @link substring="target" target="#target()" + * ) + * } + *
+ * Due to physical restrictions, some types of instructions cannot encode labels + * too far away in the list of code elements. In such cases, the {@link + * ClassFile.ShortJumpsOption} controls how an invalid branch instruction model + * is written by a {@link CodeBuilder}. * + * @see Opcode.Kind#BRANCH + * @see CodeBuilder#branch CodeBuilder::branch + * @see ClassFile.ShortJumpsOption * @since 24 */ public sealed interface BranchInstruction extends Instruction permits AbstractInstruction.BoundBranchInstruction, AbstractInstruction.UnboundBranchInstruction { /** - * {@return the target of the branch} + * {@return the branch target of this instruction} */ Label target(); @@ -56,7 +69,7 @@ public sealed interface BranchInstruction extends Instruction * which must be of kind {@link Opcode.Kind#BRANCH} * @param target the target of the branch * @throws IllegalArgumentException if the opcode kind is not - * {@link Opcode.Kind#BRANCH}. + * {@link Opcode.Kind#BRANCH} */ static BranchInstruction of(Opcode op, Label target) { Util.checkKind(op, Opcode.Kind.BRANCH); diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java b/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java index d47639d7dd7..07d4c116b3a 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java @@ -25,6 +25,7 @@ package java.lang.classfile.instruction; import java.lang.classfile.ClassFile; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Label; @@ -36,11 +37,31 @@ import jdk.internal.classfile.impl.BoundCharacterRange; /** - * A pseudo-instruction which models a single entry in the - * {@link CharacterRangeTableAttribute}. Delivered as a {@link CodeElement} - * during traversal of the elements of a {@link CodeModel}, according to - * the setting of the {@link ClassFile.DebugElementsOption} option. + * A pseudo-instruction which models a single entry in the {@link + * CharacterRangeTableAttribute CharacterRangeTable} attribute. Delivered as a + * {@link CodeElement} during traversal of the elements of a {@link CodeModel}, + * according to the setting of the {@link ClassFile.DebugElementsOption} option. + *
+ * A character range entry is composite: + * {@snippet lang=text : + * // @link substring="CharacterRange" target="#of": + * CharacterRange( + * Label startScope, // @link substring="startScope" target="#startScope" + * Label endScope, // @link substring="endScope" target="#endScope" + * int characterRangeStart, // @link substring="characterRangeStart" target="#characterRangeStart" + * int characterRangeEnd, // @link substring="characterRangeEnd" target="#characterRangeEnd" + * int flags // @link substring="flags" target="#flags" + * ) + * } + *
+ * Another model, {@link CharacterRangeInfo}, also models a character range + * entry; it has no dependency on a {@code CodeModel} and represents of bci + * values as {@code int}s instead of {@code Label}s, and is used as components + * of a {@link CharacterRangeTableAttribute}. * + * @see CharacterRangeInfo + * @see CodeBuilder#characterRange CodeBuilder::characterRange + * @see ClassFile.DebugElementsOption * @since 24 */ public sealed interface CharacterRange extends PseudoInstruction @@ -114,7 +135,7 @@ public sealed interface CharacterRange extends PseudoInstruction *
+ * The loaded constant value is symbolically represented as a {@link ConstantDesc}: + * {@snippet lang=text : + * // @link substring="ConstantInstruction" target="CodeBuilder#loadConstant(ConstantDesc)" : + * ConstantInstruction(ConstantDesc constantValue) // @link substring="constantValue" target="#constantValue()" + * } * + * @see Opcode.Kind#CONSTANT + * @see CodeBuilder#loadConstant(ConstantDesc) CodeBuilder::loadConstant + * @sealedGraph * @since 24 */ public sealed interface ConstantInstruction extends Instruction { @@ -54,22 +65,36 @@ public sealed interface ConstantInstruction extends Instruction { ConstantDesc constantValue(); /** - * {@return the type of the constant} + * {@return the {@linkplain TypeKind##computational-type computational type} of the constant} + * This is derived from the {@link #constantValue() constantValue}. */ TypeKind typeKind(); /** - * Models an "intrinsic constant" instruction (e.g., {@code - * iconst_0}). + * Models an "intrinsic constant" instruction, which encodes + * the constant value in its opcode. Examples include {@link + * Opcode#ACONST_NULL aconst_null} and {@link + * Opcode#ICONST_0 iconst_0}. + *
+ * An intrinsic constant instruction is composite: + * {@snippet lang=text : + * // @link substring="IntrinsicConstantInstruction" target="#ofIntrinsic" : + * IntrinsicConstantInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()" + * } + * where: + *
+ * An argument constant instruction is composite: + * {@snippet lang=text : + * // @link substring="ArgumentConstantInstruction" target="#ofArgument" : + * ArgumentConstantInstruction( + * Opcode opcode, // @link substring="opcode" target="#opcode()" + * int constantValue // @link substring="constantValue" target="#constantValue()" + * ) + * } + * where: + *
+ * A load constant instruction is composite: + * {@snippet lang=text : + * // @link substring="LoadConstantInstruction" target="CodeBuilder#ldc(LoadableConstantEntry)" : + * LoadConstantInstruction(LoadableConstantEntry constantEntry) // @link substring="constantEntry" target="#constantEntry()" + * } + *
+ * A "load constant" instruction can load any constant value supported by + * other constant-load instructions. However, other instructions are + * usually more optimized, avoiding extra constant pool entries and being + * smaller. * + * @see Opcode.Kind#CONSTANT + * @see ConstantInstruction#ofLoad ConstantInstruction::ofLoad + * @see CodeBuilder#ldc CodeBuilder::ldc * @since 24 */ sealed interface LoadConstantInstruction extends ConstantInstruction @@ -113,9 +172,6 @@ sealed interface LoadConstantInstruction extends ConstantInstruction */ LoadableConstantEntry constantEntry(); - /** - * {@return the type of the constant} - */ @Override default TypeKind typeKind() { return constantEntry().typeKind(); @@ -139,6 +195,10 @@ static IntrinsicConstantInstruction ofIntrinsic(Opcode op) { /** * {@return an argument constant instruction} + *
+ * {@code value} must be in the range of {@code byte}, {@code [-128, 127]}, + * for {@link Opcode#BIPUSH}, and in the range of {@code short}, {@code + * [-32768, 32767]}, for {@link Opcode#SIPUSH}. * * @param op the opcode for the specific type of argument constant instruction, * which must be {@link Opcode#BIPUSH} or {@link Opcode#SIPUSH} diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ConvertInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ConvertInstruction.java index 468685779b9..0edffda1af1 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ConvertInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ConvertInstruction.java @@ -24,6 +24,7 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Instruction; @@ -36,10 +37,27 @@ /** * Models a primitive conversion instruction in the {@code code} array of a - * {@code Code} attribute, such as {@code i2l}. Corresponding opcodes will have - * a {@code kind} of {@link Opcode.Kind#CONVERT}. Delivered as a {@link - * CodeElement} when traversing the elements of a {@link CodeModel}. + * {@code Code} attribute, such as {@link Opcode#I2L i2l}. Corresponding opcodes + * have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#CONVERT}. + * Delivered as a {@link CodeElement} when traversing the elements of a {@link CodeModel}. + *
+ * A primitive conversion instruction is composite: + * {@snippet lang=text : + * // @link substring="ConvertInstruction" target="#of(TypeKind, TypeKind)" : + * ConvertInstruction( + * TypeKind fromType, // @link substring="fromType" target="#fromType" + * TypeKind toType // @link substring="toType" target="#toType" + * ) + * } + * where these conversions are valid: + *
+ * A jump subroutine instruction is composite: + * {@snippet lang=text : + * // @link substring="JsrInstruction" target="#of(Label)" : + * JsrInstruction(Label target) // @link substring="target" target="#target()" + * } + *
+ * Due to physical restrictions, {@link Opcode#JSR jsr} instructions cannot + * encode labels too far away in the list of code elements. In such cases, + * the {@link ClassFile.ShortJumpsOption} controls how an invalid {@code jsr} + * instruction model is written by a {@link CodeBuilder}. + *
+ * Jump subroutine instructions push a {@link TypeKind##returnAddress + * returnAddress} value to the operand stack, and {@link StoreInstruction + * astore} series of instructions can then store this value to a local + * variable slot. * + * @see Opcode.Kind#DISCONTINUED_JSR * @since 24 */ sealed interface JsrInstruction extends DiscontinuedInstruction @@ -57,14 +79,18 @@ sealed interface JsrInstruction extends DiscontinuedInstruction AbstractInstruction.UnboundJsrInstruction { /** - * {@return the target of the JSR instruction} + * {@return the target of the jump subroutine instruction} */ Label target(); /** - * {@return a JSR instruction} + * {@return a jump subroutine instruction} * - * @param op the opcode for the specific type of JSR instruction, + * @apiNote + * The explicit {@code op} argument allows creating {@link Opcode#JSR_W + * jsr_w} instructions to avoid short jumps. + * + * @param op the opcode for the specific type of jump subroutine instruction, * which must be of kind {@link Opcode.Kind#DISCONTINUED_JSR} * @param target target label of the subroutine * @throws IllegalArgumentException if the opcode kind is not @@ -76,7 +102,7 @@ static JsrInstruction of(Opcode op, Label target) { } /** - * {@return a JSR instruction} + * {@return a jump subroutine instruction} * * @param target target label of the subroutine */ @@ -86,12 +112,26 @@ static JsrInstruction of(Label target) { } /** - * Models RET and RET_W instructions discontinued from the {@code code} - * array of a {@code Code} attribute since class file version 51.0. - * Corresponding opcodes will have a {@code kind} of + * Models return from subroutine instructions discontinued from the {@code + * code} array of a {@code Code} attribute since class file major version + * {@value ClassFile#JAVA_7_VERSION} (JVMS {@jvms 4.9.1}). + * Corresponding opcodes have a {@linkplain Opcode#kind() kind} of * {@link Opcode.Kind#DISCONTINUED_RET}. Delivered as a {@link CodeElement} * when traversing the elements of a {@link CodeModel}. + *
+ * A return from subroutine instruction is composite: + * {@snippet lang=text : + * // @link substring="RetInstruction" target="#of(int)" : + * RetInstruction(int slot) // @link substring="slot" target="#slot()" + * } + * where {@code slot} must be within {@code [0, 65535]}. + *
+ * {@link StoreInstruction astore} series of instructions store a {@link + * TypeKind##returnAddress returnAddress} value to a local variable slot, + * making the slot usable by a return from subroutine instruction. * + * @jvms 6.5.ret ret + * @see Opcode.Kind#DISCONTINUED_RET * @since 24 */ sealed interface RetInstruction extends DiscontinuedInstruction @@ -100,13 +140,23 @@ sealed interface RetInstruction extends DiscontinuedInstruction /** * {@return the local variable slot with return address} + * The value is within {@code [0, 65535]}. */ int slot(); /** - * {@return a RET or RET_W instruction} + * {@return a return from subroutine instruction} + *
+ * {@code slot} must be in the closed range of {@code [0, 255]} for + * {@link Opcode#RET ret}, or within {@code [0, 65535]} for {@link + * Opcode#RET_W wide ret}. + * + * @apiNote + * The explicit {@code op} argument allows creating {@code wide ret} + * instructions with {@code slot} in the range of regular {@code ret} + * instructions. * - * @param op the opcode for the specific type of RET instruction, + * @param op the opcode for the specific type of return from subroutine instruction, * which must be of kind {@link Opcode.Kind#DISCONTINUED_RET} * @param slot the local variable slot to load return address from * @throws IllegalArgumentException if the opcode kind is not @@ -118,7 +168,9 @@ static RetInstruction of(Opcode op, int slot) { } /** - * {@return a RET instruction} + * {@return a return from subroutine instruction} + *
+ * {@code slot} must be within {@code [0, 65535]}. * * @param slot the local variable slot to load return address from * @throws IllegalArgumentException if {@code slot} is out of range diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ExceptionCatch.java b/src/java.base/share/classes/java/lang/classfile/instruction/ExceptionCatch.java index 885f029d108..2a86c4bd09c 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/ExceptionCatch.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/ExceptionCatch.java @@ -24,23 +24,37 @@ */ package java.lang.classfile.instruction; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CodeElement; import java.lang.classfile.CodeModel; import java.lang.classfile.Label; import java.lang.classfile.PseudoInstruction; +import java.lang.classfile.attribute.CodeAttribute; import java.lang.classfile.constantpool.ClassEntry; import java.util.Optional; import jdk.internal.classfile.impl.AbstractPseudoInstruction; /** - * A pseudo-instruction modeling an entry in the exception table of a code - * attribute. Entries in the exception table model catch and finally blocks. - * Delivered as a {@link CodeElement} when traversing the contents - * of a {@link CodeModel}. - * - * @see PseudoInstruction + * A pseudo-instruction modeling an entry in the {@code exception_table} array + * of a {@link CodeAttribute Code} attribute. Catch (JVMS {@jvms 3.12}) and + * finally (JVMS {@jvms 3.14}) blocks in Java source code compile to exception + * table entries. Delivered as a {@link CodeElement} when traversing the + * contents of a {@link CodeModel}. + *
+ * An exception table entry is composite:
+ * {@snippet lang=text :
+ * // @link substring="ExceptionCatch" target="#of(Label, Label, Label, Optional)" :
+ * ExceptionCatch(
+ * Label handler, // @link substring="handler" target="#handler"
+ * Label tryStart, // @link substring="tryStart" target="#tryStart"
+ * Label tryEnd, // @link substring="tryEnd" target="#tryEnd"
+ * Optional
+ * A field access instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="FieldInstruction" target="#of(Opcode, FieldRefEntry)" :
+ * FieldInstruction(
+ * Opcode opcode, // @link substring="opcode" target="#opcode()"
+ * FieldRefEntry field, // @link substring="field" target="#field()"
+ * )
+ * }
*
+ * @see Opcode.Kind#FIELD_ACCESS
+ * @see CodeBuilder#fieldAccess CodeBuilder::fieldAccess
* @since 24
*/
public sealed interface FieldInstruction extends Instruction
@@ -68,7 +80,11 @@ default Utf8Entry name() {
}
/**
- * {@return the field descriptor of the field}
+ * {@return the field descriptor string of the field}
+ *
+ * @apiNote
+ * A symbolic descriptor for the type of the field is available through
+ * {@link #typeSymbol() typeSymbol()}.
*/
default Utf8Entry type() {
return field().nameAndType().type();
@@ -103,6 +119,8 @@ static FieldInstruction of(Opcode op, FieldRefEntry field) {
* @param owner the class holding the field
* @param name the name of the field
* @param type the field descriptor
+ * @throws IllegalArgumentException if the opcode kind is not
+ * {@link Opcode.Kind#FIELD_ACCESS}.
*/
static FieldInstruction of(Opcode op,
ClassEntry owner,
@@ -118,6 +136,8 @@ static FieldInstruction of(Opcode op,
* which must be of kind {@link Opcode.Kind#FIELD_ACCESS}
* @param owner the class holding the field
* @param nameAndType the name and field descriptor of the field
+ * @throws IllegalArgumentException if the opcode kind is not
+ * {@link Opcode.Kind#FIELD_ACCESS}.
*/
static FieldInstruction of(Opcode op,
ClassEntry owner,
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/IncrementInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/IncrementInstruction.java
index 7ea516c7cc5..a874ef0a954 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/IncrementInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/IncrementInstruction.java
@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -33,10 +34,27 @@
/**
* Models a local variable increment instruction in the {@code code} array of a
- * {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
- * {@link Opcode.Kind#INCREMENT}. Delivered as a {@link CodeElement} when
+ * {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind()
+ * kind} of {@link Opcode.Kind#INCREMENT}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
+ *
+ * A local variable increment instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="IncrementInstruction" target="#of" :
+ * IncrementInstruction(
+ * int slot, // @link substring="slot" target="#slot()"
+ * int constant // @link substring="constant" target="#constant()"
+ * )
+ * }
+ * where
+ *
+ * A dynamically-computed call site invocation instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="InvokeDynamicInstruction" target="#of" :
+ * InvokeDynamicInstruction(InvokeDynamicEntry invokedynamic) // @link substring="invokedynamic" target="#invokedynamic()"
+ * }
*
+ * @see Opcode.Kind#INVOKE_DYNAMIC
+ * @see CodeBuilder#invokedynamic CodeBuilder::invokedynamic
+ * @jvms 6.5.invokedynamic invokedynamic
* @since 24
*/
public sealed interface InvokeDynamicInstruction extends Instruction
@@ -62,6 +74,10 @@ default Utf8Entry name() {
/**
* {@return the invocation type of the call site}
+ *
+ * @apiNote
+ * A symbolic descriptor for the invocation typeis available through {@link
+ * #typeSymbol() typeSymbol()}.
*/
default Utf8Entry type() {
return invokedynamic().type();
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/InvokeInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/InvokeInstruction.java
index 904a17375ac..50791cbd0ff 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/InvokeInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/InvokeInstruction.java
@@ -24,10 +24,12 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Opcode;
+import java.lang.classfile.TypeKind;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.constantpool.InterfaceMethodRefEntry;
import java.lang.classfile.constantpool.MemberRefEntry;
@@ -42,10 +44,26 @@
/**
* Models a method invocation instruction in the {@code code} array of a {@code
- * Code} attribute, other than {@code invokedynamic}. Corresponding opcodes
- * will have a {@code kind} of {@link Opcode.Kind#INVOKE}. Delivered as a
- * {@link CodeElement} when traversing the elements of a {@link CodeModel}.
+ * Code} attribute, other than {@link InvokeDynamicInstruction invokedynamic}.
+ * Corresponding opcodes have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#INVOKE}.
+ * Delivered as a {@link CodeElement} when traversing the elements of a {@link CodeModel}.
+ *
+ * A method invocation instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="InvokeInstruction" target="#of(Opcode, MemberRefEntry)" :
+ * InvokeInstruction(
+ * Opcode opcode, // @link substring="opcode" target="#opcode()"
+ * MethodRefEntry | InterfaceMethodRefEntry method) // @link substring="method" target="#method()"
+ * )
+ * }
+ * where {@code method} must be an {@code InterfaceMethodRefEntry} for {@link
+ * Opcode#INVOKEINTERFACE invokeinterface} opcode, and must be a {@code
+ * MethodRefEntry} for {@link Opcode#INVOKEVIRTUAL invokevirtual} opcode.
+ * {@link Opcode#INVOKESTATIC invokestatic} and {@link Opcode#INVOKESPECIAL
+ * invokespecial} can have either type of entry for {@code method}.
*
+ * @see Opcode.Kind#INVOKE
+ * @see CodeBuilder#invoke CodeBuilder::invoke
* @since 24
*/
public sealed interface InvokeInstruction extends Instruction
@@ -57,18 +75,25 @@ public sealed interface InvokeInstruction extends Instruction
MemberRefEntry method();
/**
- * {@return whether the class holding the method is an interface}
+ * {@return whether the class or interface holding the method is an interface}
*/
boolean isInterface();
/**
- * {@return the {@code count} value of an {@code invokeinterface} instruction, as defined in JVMS {@jvms 6.5}
- * or {@code 0} for {@code invokespecial}, {@code invokestatic} and {@code invokevirtual} instructions}
+ * {@return the {@code count} value of an {@code invokeinterface} instruction,
+ * or {@code 0} for other instructions}
+ *
+ * For an {@code invokeinterface} instruction, this value must be equivalent
+ * to the sum of {@linkplain TypeKind#slotSize() slot sizes} of all arguments
+ * plus one, which is equal to the number of operand stack depth consumed by
+ * this interface method invocation instruction.
+ *
+ * @jvms 6.5.invokeinterface invokeinterface
*/
int count();
/**
- * {@return the class holding the method}
+ * {@return the class or interface holding the method}
*/
default ClassEntry owner() {
return method().owner();
@@ -82,7 +107,11 @@ default Utf8Entry name() {
}
/**
- * {@return the method descriptor of the method}
+ * {@return the method descriptor string of the method}
+ *
+ * @apiNote
+ * A symbolic descriptor for the type of the method is available through
+ * {@link #typeSymbol() typeSymbol()}.
*/
default Utf8Entry type() {
return method().nameAndType().type();
@@ -95,7 +124,6 @@ default MethodTypeDesc typeSymbol() {
return Util.methodTypeSymbol(method().type());
}
-
/**
* {@return an invocation instruction}
*
@@ -103,7 +131,7 @@ default MethodTypeDesc typeSymbol() {
* which must be of kind {@link Opcode.Kind#INVOKE}
* @param method a constant pool entry describing the method
* @throws IllegalArgumentException if the opcode kind is not
- * {@link Opcode.Kind#INVOKE}.
+ * {@link Opcode.Kind#INVOKE}
*/
static InvokeInstruction of(Opcode op, MemberRefEntry method) {
Util.checkKind(op, Opcode.Kind.INVOKE);
@@ -119,6 +147,8 @@ static InvokeInstruction of(Opcode op, MemberRefEntry method) {
* @param name the name of the method
* @param type the method descriptor
* @param isInterface whether the class holding the method is an interface
+ * @throws IllegalArgumentException if the opcode kind is not
+ * {@link Opcode.Kind#INVOKE}
*/
static InvokeInstruction of(Opcode op,
ClassEntry owner,
@@ -136,6 +166,8 @@ static InvokeInstruction of(Opcode op,
* @param owner the class holding the method
* @param nameAndType the name and type of the method
* @param isInterface whether the class holding the method is an interface
+ * @throws IllegalArgumentException if the opcode kind is not
+ * {@link Opcode.Kind#INVOKE}
*/
static InvokeInstruction of(Opcode op,
ClassEntry owner,
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LabelTarget.java b/src/java.base/share/classes/java/lang/classfile/instruction/LabelTarget.java
index bc1deffc98b..c5b49973133 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/LabelTarget.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/LabelTarget.java
@@ -24,10 +24,13 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
+import java.lang.classfile.CodeTransform;
import java.lang.classfile.Label;
import java.lang.classfile.PseudoInstruction;
+import java.lang.classfile.attribute.CodeAttribute;
import jdk.internal.classfile.impl.LabelImpl;
@@ -35,9 +38,28 @@
* A pseudo-instruction which indicates that the specified label corresponds to
* the current position in the {@code Code} attribute. Delivered as a {@link
* CodeElement} during traversal of the elements of a {@link CodeModel}.
+ *
+ * This can be used to inspect the target position of labels across {@linkplain
+ * CodeTransform transformations}, as {@linkplain CodeAttribute#labelToBci bci}
+ * is not stable.
+ *
+ * When passed to a {@link CodeBuilder}, this pseudo-instruction sets the
+ * specified label to be bound at the current position in the builder.
+ *
+ * By design, {@code LabelTarget} cannot be created by users and can only be
+ * read from a code model. Use {@link CodeBuilder#labelBinding
+ * CodeBuilder::labelBinding} to bind arbitrary labels to a {@code CodeBuilder}.
+ *
+ * For a {@code CodeBuilder cob}, a {@code LabelTarget lt}, these two calls are
+ * equivalent:
+ * {@snippet lang=java :
+ * cob.with(lt); // @link substring="with" target="CodeBuilder#with"
+ * // @link substring="labelBinding" target="CodeBuilder#labelBinding" :
+ * cob.labelBinding(lt.label()); // @link substring="label" target="#label"
+ * }
*
- * @see PseudoInstruction
- *
+ * @see Label
+ * @see CodeBuilder#labelBinding CodeBuilder::labelBinding
* @since 24
*/
public sealed interface LabelTarget extends PseudoInstruction
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LineNumber.java b/src/java.base/share/classes/java/lang/classfile/instruction/LineNumber.java
index a9a497708c0..3f10a3ada0d 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/LineNumber.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/LineNumber.java
@@ -25,21 +25,42 @@
package java.lang.classfile.instruction;
import java.lang.classfile.ClassFile;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.PseudoInstruction;
+import java.lang.classfile.attribute.CodeAttribute;
+import java.lang.classfile.attribute.LineNumberInfo;
import java.lang.classfile.attribute.LineNumberTableAttribute;
import jdk.internal.classfile.impl.LineNumberImpl;
/**
- * A pseudo-instruction which models a single entry in the
- * {@link LineNumberTableAttribute}. Delivered as a {@link CodeElement}
- * during traversal of the elements of a {@link CodeModel}, according to
- * the setting of the {@link ClassFile.LineNumbersOption} option.
+ * A pseudo-instruction which indicates the code for a given line number starts
+ * after the current position in a {@link CodeAttribute Code} attribute. This
+ * models a single entry in the {@link LineNumberTableAttribute LineNumberTable}
+ * attribute. Delivered as a {@link CodeElement} during traversal of the
+ * elements of a {@link CodeModel}, according to the setting of the {@link
+ * ClassFile.LineNumbersOption} option.
+ *
+ * A line number entry is composite:
+ * {@snippet lang=text :
+ * // @link substring="LineNumber" target="#of" :
+ * LineNumber(int line) // @link substring="int line" target="#line"
+ * }
+ *
+ * Another model, {@link LineNumberInfo}, also models a line number entry; it
+ * has no dependency on a {@code CodeModel} and represents of bci values as
+ * {@code int}s instead of order of pseudo-instructions in the elements of a
+ * {@code CodeModel}, and is used as components of a {@link LineNumberTableAttribute}.
*
- * @see PseudoInstruction
+ * @apiNote
+ * Line numbers are represented with custom pseudo-instructions to avoid using
+ * labels, which usually indicate branching targets for the control flow.
*
+ * @see LineNumberInfo
+ * @see CodeBuilder#lineNumber CodeBuilder::lineNumber
+ * @see ClassFile.LineNumbersOption
* @since 24
*/
public sealed interface LineNumber extends PseudoInstruction
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LoadInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/LoadInstruction.java
index c499dcc9944..81961320be3 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/LoadInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/LoadInstruction.java
@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -36,10 +37,23 @@
/**
* Models a local variable load instruction in the {@code code} array of a
- * {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
- * {@link Opcode.Kind#LOAD}. Delivered as a {@link CodeElement} when
- * traversing the elements of a {@link CodeModel}.
+ * {@code Code} attribute. Corresponding opcodes have a {@linkplain
+ * Opcode#kind() kind} of {@link Opcode.Kind#LOAD}. Delivered as a {@link
+ * CodeElement} when traversing the elements of a {@link CodeModel}.
+ *
+ * A local variable load instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="LoadInstruction" target="#of(TypeKind, int)" :
+ * LoadInstruction(
+ * TypeKind typeKind, // @link substring="typeKind" target="#typeKind"
+ * int slot // @link substring="slot" target="#slot"
+ * )
+ * }
+ * where {@code TypeKind} is {@linkplain TypeKind##computational-type
+ * computational}, and {@code slot} is within {@code [0, 65535]}.
*
+ * @see Opcode.Kind#LOAD
+ * @see CodeBuilder#loadLocal CodeBuilder::loadLocal
* @since 24
*/
public sealed interface LoadInstruction extends Instruction
@@ -48,16 +62,21 @@ public sealed interface LoadInstruction extends Instruction
/**
* {@return the local variable slot to load from}
+ * The value is within {@code [0, 65535]}.
*/
int slot();
/**
- * {@return the type of the value to be loaded}
+ * {@return the {@linkplain TypeKind##computational-type computational type}
+ * of the value to be loaded}
*/
TypeKind typeKind();
/**
* {@return a local variable load instruction}
+ * {@code kind} is {@linkplain TypeKind#asLoadable() converted} to its
+ * computational type.
+ * {@code slot} must be within {@code [0, 65535]}.
*
* @param kind the type of the value to be loaded
* @param slot the local variable slot to load from
@@ -71,6 +90,20 @@ static LoadInstruction of(TypeKind kind, int slot) {
/**
* {@return a local variable load instruction}
+ *
+ * The range of {@code slot} is restricted by the {@code op} and its
+ * {@linkplain Opcode#sizeIfFixed() size}:
+ *
+ * A local variable entry is composite:
+ * {@snippet lang=text :
+ * // @link substring="LocalVariable" target="#of(int, String, ClassDesc, Label, Label)" :
+ * LocalVariable(
+ * int slot, // @link substring="slot" target="#slot"
+ * String name, // @link substring="name" target="#name"
+ * ClassDesc type, // @link substring="type" target="#type"
+ * Label startScope, // @link substring="startScope" target="#startScope"
+ * Label endScope // @link substring="endScope" target="#endScope"
+ * )
+ * }
+ * Where {@code slot} is within {@code [0, 65535]}.
+ *
+ * Another model, {@link LocalVariableInfo}, also models a local variable
+ * entry; it has no dependency on a {@code CodeModel} and represents of bci
+ * values as {@code int}s instead of {@code Label}s, and is used as components
+ * of a {@link LocalVariableTableAttribute}.
*
- * @see PseudoInstruction
+ * @apiNote
+ * {@code LocalVariable} is used for all local variables in Java source code.
+ * If a local variable has a parameterized type, a type argument, or an array
+ * type of one of the previous types, a {@link LocalVariableType} should be
+ * created for that local variable as well.
*
+ * @see LocalVariableInfo
+ * @see CodeBuilder#localVariable CodeBuilder::localVariable
+ * @see ClassFile.DebugElementsOption
* @since 24
*/
public sealed interface LocalVariable extends PseudoInstruction
permits AbstractPseudoInstruction.UnboundLocalVariable, BoundLocalVariable {
/**
* {@return the local variable slot}
+ * The value is within {@code [0, 65535]}.
*/
int slot();
@@ -61,7 +89,11 @@ public sealed interface LocalVariable extends PseudoInstruction
Utf8Entry name();
/**
- * {@return the local variable field descriptor}
+ * {@return the local variable field descriptor string}
+ *
+ * @apiNote
+ * A symbolic descriptor for the type of the local variable is available
+ * through {@link #typeSymbol() typeSymbol()}.
*/
Utf8Entry type();
@@ -84,6 +116,7 @@ default ClassDesc typeSymbol() {
/**
* {@return a local variable pseudo-instruction}
+ * {@code slot} must be within {@code [0, 65535]}.
*
* @param slot the local variable slot
* @param nameEntry the local variable name
@@ -99,6 +132,7 @@ static LocalVariable of(int slot, Utf8Entry nameEntry, Utf8Entry descriptorEntry
/**
* {@return a local variable pseudo-instruction}
+ * {@code slot} must be within {@code [0, 65535]}.
*
* @param slot the local variable slot
* @param name the local variable name
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java
index c9427491733..1e28804a837 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariableType.java
@@ -24,12 +24,8 @@
*/
package java.lang.classfile.instruction;
-import java.lang.classfile.ClassFile;
-import java.lang.classfile.CodeElement;
-import java.lang.classfile.CodeModel;
-import java.lang.classfile.Label;
-import java.lang.classfile.PseudoInstruction;
-import java.lang.classfile.Signature;
+import java.lang.classfile.*;
+import java.lang.classfile.attribute.LocalVariableTypeInfo;
import java.lang.classfile.attribute.LocalVariableTypeTableAttribute;
import java.lang.classfile.constantpool.Utf8Entry;
@@ -39,16 +35,44 @@
/**
* A pseudo-instruction which models a single entry in the {@link
- * LocalVariableTypeTableAttribute}. Delivered as a {@link CodeElement} during
- * traversal of the elements of a {@link CodeModel}, according to the setting of
- * the {@link ClassFile.DebugElementsOption} option.
+ * LocalVariableTypeTableAttribute LocalVariableTypeTable} attribute. Delivered
+ * as a {@link CodeElement} during traversal of the elements of a {@link CodeModel},
+ * according to the setting of the {@link ClassFile.DebugElementsOption} option.
+ *
+ * A local variable type entry is composite:
+ * {@snippet lang=text :
+ * // @link substring="LocalVariableType" target="#of(int, String, Signature, Label, Label)" :
+ * LocalVariableType(
+ * int slot, // @link substring="slot" target="#slot"
+ * String name, // @link substring="name" target="#name"
+ * Signature signature, // @link substring="signature" target="#signatureSymbol"
+ * Label startScope, // @link substring="startScope" target="#startScope"
+ * Label endScope // @link substring="endScope" target="#endScope"
+ * )
+ * }
+ * Where {@code slot} is within {@code [0, 65535]}.
+ *
+ * Another model, {@link LocalVariableTypeInfo}, also models a local variable
+ * type entry; it has no dependency on a {@code CodeModel} and represents of bci
+ * values as {@code int}s instead of {@code Label}s, and is used as components
+ * of a {@link LocalVariableTypeTableAttribute}.
*
+ * @apiNote
+ * {@code LocalVariableType} is used if a local variable has a parameterized
+ * type, a type argument, or an array type of one of the previous types as its
+ * type. A {@link LocalVariable} with the erased type should still be created
+ * for that local variable.
+ *
+ * @see LocalVariableTypeInfo
+ * @see CodeBuilder#localVariableType CodeBuilder::localVariableType
+ * @see ClassFile.DebugElementsOption
* @since 24
*/
public sealed interface LocalVariableType extends PseudoInstruction
permits AbstractPseudoInstruction.UnboundLocalVariableType, BoundLocalVariableType {
/**
* {@return the local variable slot}
+ * The value is within {@code [0, 65535]}.
*/
int slot();
@@ -58,12 +82,16 @@ public sealed interface LocalVariableType extends PseudoInstruction
Utf8Entry name();
/**
- * {@return the local variable signature}
+ * {@return the local variable generic signature string}
+ *
+ * @apiNote
+ * A symbolic generic signature of the local variable is available
+ * through {@link #signatureSymbol() signatureSymbol()}.
*/
Utf8Entry signature();
/**
- * {@return the local variable signature}
+ * {@return the local variable generic signature}
*/
default Signature signatureSymbol() {
return Signature.parseFrom(signature().stringValue());
@@ -81,6 +109,7 @@ default Signature signatureSymbol() {
/**
* {@return a local variable type pseudo-instruction}
+ * {@code slot} must be within {@code [0, 65535]}.
*
* @param slot the local variable slot
* @param nameEntry the local variable name
@@ -96,6 +125,7 @@ static LocalVariableType of(int slot, Utf8Entry nameEntry, Utf8Entry signatureEn
/**
* {@return a local variable type pseudo-instruction}
+ * {@code slot} must be within {@code [0, 65535]}.
*
* @param slot the local variable slot
* @param name the local variable name
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LookupSwitchInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/LookupSwitchInstruction.java
index 7b286e9cfd2..33e3ec002fd 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/LookupSwitchInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/LookupSwitchInstruction.java
@@ -24,19 +24,36 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Label;
+import java.lang.classfile.Opcode;
import java.util.List;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
- * Models a {@code lookupswitch} instruction in the {@code code} array of a
- * {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
- * the elements of a {@link CodeModel}.
+ * Models a {@link Opcode#LOOKUPSWITCH lookupswitch} instruction in the {@code
+ * code} array of a {@code Code} attribute. Delivered as a {@link CodeElement}
+ * when traversing the elements of a {@link CodeModel}.
+ *
+ * A lookup switch instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="LookupSwitchInstruction" target="#of" :
+ * LookupSwitchInstruction(
+ * Label defaultTarget, // @link substring="defaultTarget" target="#defaultTarget"
+ * List
+ * A monitor instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="MonitorInstruction" target="#of(Opcode)" :
+ * MonitorInstruction(Opcode opcode) // @link substring="opcode" target="#opcode"
+ * }
*
* @since 24
*/
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewMultiArrayInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewMultiArrayInstruction.java
index 4a1f6cfd170..f7efd144422 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/NewMultiArrayInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewMultiArrayInstruction.java
@@ -24,19 +24,34 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
+import java.lang.classfile.Opcode;
import java.lang.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.AbstractInstruction;
import jdk.internal.classfile.impl.BytecodeHelpers;
/**
- * Models a {@code multianewarray} invocation instruction in the {@code code}
+ * Models a {@link Opcode#MULTIANEWARRAY multianewarray} instruction in the {@code code}
* array of a {@code Code} attribute. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
+ *
+ * A new multi-dimensional array instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="NewMultiArrayInstruction" target="#of" :
+ * NewMultiArrayInstruction(
+ * ClassEntry arrayType, // @link substring="arrayType" target="#arrayType"
+ * int dimensions // @link substring="dimensions" target="#dimensions"
+ * )
+ * }
+ * where the {@code arrayType} is an array class.
*
+ * @see Opcode.Kind#NEW_MULTI_ARRAY
+ * @see CodeBuilder#multianewarray CodeBuilder::multianewarray
+ * @jvms 6.5.multianewarray multianewarray
* @since 24
*/
public sealed interface NewMultiArrayInstruction extends Instruction
@@ -44,7 +59,7 @@ public sealed interface NewMultiArrayInstruction extends Instruction
AbstractInstruction.UnboundNewMultidimensionalArrayInstruction {
/**
- * {@return the type of the array, as a symbolic descriptor}
+ * {@return the type of the array}
*/
ClassEntry arrayType();
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewObjectInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewObjectInstruction.java
index f063733b64f..62b0233be87 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/NewObjectInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewObjectInstruction.java
@@ -24,18 +24,30 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
+import java.lang.classfile.Opcode;
import java.lang.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
- * Models a {@code new} instruction in the {@code code} array of a {@code Code}
+ * Models a {@link Opcode#NEW new} instruction in the {@code code} array of a {@code Code}
* attribute. Delivered as a {@link CodeElement} when traversing the elements
* of a {@link CodeModel}.
+ *
+ * A new object instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="NewObjectInstruction" target="#of" :
+ * NewObjectInstruction(ClassEntry className) // @link substring="className" target="#className"
+ * }
+ * where the {@code className} is a non-abstract class.
*
+ * @see Opcode.Kind#NEW_OBJECT
+ * @see CodeBuilder#new_ CodeBuilder::new_
+ * @jvms 6.5.new new
* @since 24
*/
public sealed interface NewObjectInstruction extends Instruction
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java
index 411bf7f6b55..c1e2c9d12fa 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java
@@ -24,18 +24,30 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
+import java.lang.classfile.Opcode;
import java.lang.classfile.TypeKind;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
- * Models a {@code newarray} invocation instruction in the {@code code}
+ * Models a {@link Opcode#NEWARRAY newarray} instruction in the {@code code}
* array of a {@code Code} attribute. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
+ *
+ * A new primitive array instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="NewPrimitiveArrayInstruction" target="#of" :
+ * NewPrimitiveArrayInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind"
+ * }
+ * where {@code typeKind} is primitive and not {@code void}.
*
+ * @see Opcode.Kind#NEW_PRIMITIVE_ARRAY
+ * @see CodeBuilder#newarray CodeBuilder::newarray
+ * @jvms 6.5.newarray newarray
* @since 24
*/
public sealed interface NewPrimitiveArrayInstruction extends Instruction
@@ -43,6 +55,10 @@ public sealed interface NewPrimitiveArrayInstruction extends Instruction
AbstractInstruction.UnboundNewPrimitiveArrayInstruction {
/**
* {@return the component type of the array}
+ *
+ * @apiNote
+ * The backing array code for this instruction is available through
+ * {@link TypeKind#newarrayCode() typeKind().newarrayCode()}.
*/
TypeKind typeKind();
@@ -50,8 +66,9 @@ public sealed interface NewPrimitiveArrayInstruction extends Instruction
* {@return a new primitive array instruction}
*
* @param typeKind the component type of the array
- * @throws IllegalArgumentException when the {@code typeKind} is not a legal
- * primitive array component type
+ * @throws IllegalArgumentException when {@code typeKind} is not primitive
+ * or is {@code void}
+ * @see TypeKind#fromNewarrayCode(int) TypeKind::fromNewarrayCode
*/
static NewPrimitiveArrayInstruction of(TypeKind typeKind) {
// Implicit null-check:
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewReferenceArrayInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewReferenceArrayInstruction.java
index c85ed9dd3d9..a092c068a36 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/NewReferenceArrayInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewReferenceArrayInstruction.java
@@ -24,18 +24,29 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
+import java.lang.classfile.Opcode;
import java.lang.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
- * Models a {@code anewarray} invocation instruction in the {@code code}
+ * Models a {@link Opcode#ANEWARRAY anewarray} instruction in the {@code code}
* array of a {@code Code} attribute. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
+ *
+ * A new reference array instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="NewReferenceArrayInstruction" target="#of" :
+ * NewReferenceArrayInstruction(ClassEntry componentType) // @link substring="componentType" target="#componentType"
+ * }
*
+ * @see Opcode.Kind#NEW_REF_ARRAY
+ * @see CodeBuilder#newarray CodeBuilder::anewarray
+ * @jvms 6.5.anewarray anewarray
* @since 24
*/
public sealed interface NewReferenceArrayInstruction extends Instruction
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NopInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NopInstruction.java
index 3c11803109a..cf0b9f25ac9 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/NopInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/NopInstruction.java
@@ -24,17 +24,23 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
+import java.lang.classfile.Opcode;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
- * Models a {@code nop} invocation instruction in the {@code code}
+ * Models a {@link Opcode#NOP nop} instruction in the {@code code}
* array of a {@code Code} attribute. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
+ *
+ * A no-op instruction has no visible state.
*
+ * @see CodeBuilder#nop CodeBuilder::nop
+ * @jvms 6.5.nop nop
* @since 24
*/
public sealed interface NopInstruction extends Instruction
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/OperatorInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/OperatorInstruction.java
index d1eb8aa1a3d..b4daf55e3a5 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/OperatorInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/OperatorInstruction.java
@@ -35,23 +35,31 @@
/**
* Models an arithmetic operator instruction in the {@code code} array of a
- * {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
+ * {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
* {@link Opcode.Kind#OPERATOR}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
+ *
+ * An operator instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="OperatorInstruction" target="#of" :
+ * OperatorInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()"
+ * }
*
+ * @see Opcode.Kind#OPERATOR
* @since 24
*/
public sealed interface OperatorInstruction extends Instruction
permits AbstractInstruction.UnboundOperatorInstruction {
/**
* {@return the operand type of the instruction}
+ * This is derived from the {@link #opcode opcode}.
*/
TypeKind typeKind();
/**
* {@return an operator instruction}
*
- * @param op the opcode for the specific type of array load instruction,
+ * @param op the opcode for the specific type of operator instruction,
* which must be of kind {@link Opcode.Kind#OPERATOR}
* @throws IllegalArgumentException if the opcode kind is not
* {@link Opcode.Kind#OPERATOR}.
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/ReturnInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/ReturnInstruction.java
index 3bbb96b1cbe..aca9196eabf 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/ReturnInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/ReturnInstruction.java
@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -36,22 +37,35 @@
/**
* Models a return-from-method instruction in the {@code code} array of a
- * {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
+ * {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
* {@link Opcode.Kind#RETURN}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
+ *
+ * A return-from-method instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="ReturnInstruction" target="#of(TypeKind)" :
+ * ReturnInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind()"
+ * }
+ * where {@code typeKind} is {@linkplain TypeKind##computational-type
+ * computational} or {@link TypeKind#VOID void}.
*
+ * @see Opcode.Kind#RETURN
+ * @see CodeBuilder#return_(TypeKind) CodeBuilder::return_
* @since 24
*/
public sealed interface ReturnInstruction extends Instruction
permits AbstractInstruction.UnboundReturnInstruction {
/**
- * {@return the type of the return instruction}
+ * {@return the {@linkplain TypeKind##computational-type computational type}, including
+ * {@link TypeKind#VOID void}, of the return instruction}
*/
TypeKind typeKind();
/**
* {@return a return instruction}
+ * {@code typeKind} is {@linkplain TypeKind#asLoadable() converted} to its
+ * computational type.
*
* @param typeKind the type of the return instruction
*/
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/StackInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/StackInstruction.java
index b01b206e368..8ef413937bc 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/StackInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/StackInstruction.java
@@ -34,10 +34,17 @@
/**
* Models a stack manipulation instruction in the {@code code} array of a
- * {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
+ * {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
* {@link Opcode.Kind#STACK}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
+ *
+ * A stack manipulation instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="StackInstruction" target="#of" :
+ * StackInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()"
+ * }
*
+ * @see Opcode.Kind#STACK
* @since 24
*/
public sealed interface StackInstruction extends Instruction
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/StoreInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/StoreInstruction.java
index 1d7bdce1fdf..93d33e0b7c2 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/StoreInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/StoreInstruction.java
@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -36,10 +37,28 @@
/**
* Models a local variable store instruction in the {@code code} array of a
- * {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
+ * {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
* {@link Opcode.Kind#STORE}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
+ *
+ * A local variable store instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="StoreInstruction" target="#of(TypeKind, int)" :
+ * StoreInstruction(
+ * TypeKind typeKind, // @link substring="typeKind" target="#typeKind"
+ * int slot // @link substring="slot" target="#slot"
+ * )
+ * }
+ * where {@code TypeKind} is {@linkplain TypeKind##computational-type
+ * computational}, and {@code slot} is within {@code [0, 65535]}.
+ *
+ * {@code astore} series of instructions, or {@code reference} type store
+ * instructions, can also operate on the {@link TypeKind##returnAddress
+ * returnAddress} type from discontinued {@linkplain
+ * DiscontinuedInstruction.JsrInstruction jump subroutine instructions}.
*
+ * @see Opcode.Kind#STORE
+ * @see CodeBuilder#storeLocal CodeBuilder::storeLocal
* @since 24
*/
public sealed interface StoreInstruction extends Instruction
@@ -47,16 +66,23 @@ public sealed interface StoreInstruction extends Instruction
/**
* {@return the local variable slot to store to}
+ * The value is within {@code [0, 65535]}.
*/
int slot();
/**
- * {@return the type of the value to be stored}
+ * {@return the {@linkplain TypeKind##computational-type computational type}
+ * of the value to be stored} The {@link TypeKind#REFERENCE reference}
+ * type store instructions also operate on the {@code returnAddress} type,
+ * which does not apply to {@code reference} type load instructions.
*/
TypeKind typeKind();
/**
* {@return a local variable store instruction}
+ * {@code kind} is {@linkplain TypeKind#asLoadable() converted} to its
+ * computational type.
+ * {@code slot} must be within {@code [0, 65535]}.
*
* @param kind the type of the value to be stored
* @param slot the local variable slot to store to
@@ -70,6 +96,20 @@ static StoreInstruction of(TypeKind kind, int slot) {
/**
* {@return a local variable store instruction}
+ *
+ * The range of {@code slot} is restricted by the {@code op} and its
+ * {@linkplain Opcode#sizeIfFixed() size}:
+ *
+ * A switch case is composite:
+ * {@snippet lang=text :
+ * // @link substring="SwitchCase" target="#of" :
+ * SwitchCase(
+ * int caseValue, // @link substring="caseValue" target="#caseValue"
+ * Label target // @link substring="target" target="#target"
+ * )
+ * }
*
* @see LookupSwitchInstruction
* @see TableSwitchInstruction
- *
* @since 24
*/
public sealed interface SwitchCase
@@ -47,11 +55,10 @@ public sealed interface SwitchCase
Label target();
/**
- * Create a {@linkplain SwitchCase}
+ * {@return a new switch case}
*
* @param caseValue the integer value for the case
* @param target the branch target for the case
- * @return the {@linkplain SwitchCase}
*/
static SwitchCase of(int caseValue, Label target) {
return new AbstractInstruction.SwitchCaseImpl(caseValue, target);
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/TableSwitchInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/TableSwitchInstruction.java
index bbe7a4d6c0c..3f7245fad49 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/TableSwitchInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/TableSwitchInstruction.java
@@ -24,19 +24,45 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Label;
+import java.lang.classfile.Opcode;
import java.util.List;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
- * Models a {@code tableswitch} instruction in the {@code code} array of a
+ * Models a {@link Opcode#TABLESWITCH tableswitch} instruction in the {@code code} array of a
* {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
* the elements of a {@link CodeModel}.
+ *
+ * A table switch instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="TableSwitchInstruction" target="#of" :
+ * TableSwitchInstruction(
+ * int lowValue, // @link substring="int lowValue" target="#lowValue"
+ * int highValue, // @link substring="int highValue" target="#highValue"
+ * Label defaultTarget, // @link substring="defaultTarget" target="#defaultTarget"
+ * List
+ * When read from {@code class} files, the {@code cases} may omit cases that
+ * duplicate the default target. The list is sorted ascending by the {@link
+ * SwitchCase#caseValue() caseValue}.
+ *
+ * When writing to {@code class} file, the order in the {@code cases} list does
+ * not matter, as there is only one valid order in the physical representation
+ * of table switch entries. Treatment of elements in {@code cases} whose value
+ * is less than {@code lowValue} or greater than {@code highValue}, and elements
+ * whose value duplicates that of another, is not specified.
*
+ * @see Opcode.Kind#TABLE_SWITCH
+ * @see CodeBuilder#tableswitch CodeBuilder::tableswitch
+ * @jvms 6.5.tableswitch tableswitch
* @since 24
*/
public sealed interface TableSwitchInstruction extends Instruction
@@ -67,7 +93,8 @@ public sealed interface TableSwitchInstruction extends Instruction
* @param lowValue the low value of the switch target range, inclusive
* @param highValue the high value of the switch target range, inclusive
* @param defaultTarget the default target of the switch
- * @param cases the cases of the switch
+ * @param cases the cases of the switch; duplicate or out of bound case
+ * handling is not specified
*/
static TableSwitchInstruction of(int lowValue, int highValue, Label defaultTarget, List
+ * A throw instruction has no visible state.
*
+ * @see Opcode.Kind#THROW_EXCEPTION
+ * @see CodeBuilder#athrow CodeBuiler::athrow
* @since 24
*/
public sealed interface ThrowInstruction extends Instruction
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/TypeCheckInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/TypeCheckInstruction.java
index 032e7a8462b..3091cf05e71 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/TypeCheckInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/TypeCheckInstruction.java
@@ -36,9 +36,24 @@
import jdk.internal.classfile.impl.Util;
/**
- * Models an {@code instanceof} or {@code checkcast} instruction in the {@code
- * code} array of a {@code Code} attribute. Delivered as a {@link CodeElement}
- * when traversing the elements of a {@link CodeModel}.
+ * Models an {@link Opcode#INSTANCEOF instanceof} or a {@link Opcode#CHECKCAST checkcast}
+ * instruction in the {@code code} array of a {@code Code} attribute. Corresponding
+ * opcodes have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#TYPE_CHECK}.
+ * Delivered as a {@link CodeElement} when traversing the elements of a {@link CodeModel}.
+ *
+ * An {@code instanceof} checks the type and pushes an integer to the operand stack.
+ * A {@code checkcast} checks the type and throws a {@link ClassCastException} if
+ * the check fails. {@code instanceof} treat the {@code null} reference as a
+ * failure, while {@code checkcast} treat the {@code null} reference as a success.
+ *
+ * A type check instruction is composite:
+ * {@snippet lang=text :
+ * // @link substring="TypeCheckInstruction" target="#of(Opcode, ClassEntry)" :
+ * TypeCheckInstruction(
+ * Opcode opcode, // @link substring="opcode" target="#opcode"
+ * ClassEntry type // @link substring="type" target="#type"
+ * )
+ * }
*
* @since 24
*/
@@ -47,7 +62,7 @@ public sealed interface TypeCheckInstruction extends Instruction
AbstractInstruction.UnboundTypeCheckInstruction {
/**
- * {@return the type against which the instruction checks or casts}
+ * {@return the type against which the instruction checks}
*/
ClassEntry type();
@@ -58,7 +73,7 @@ public sealed interface TypeCheckInstruction extends Instruction
* which must be of kind {@link Opcode.Kind#TYPE_CHECK}
* @param type the type against which to check or cast
* @throws IllegalArgumentException if the opcode kind is not
- * {@link Opcode.Kind#TYPE_CHECK}.
+ * {@link Opcode.Kind#TYPE_CHECK}
*/
static TypeCheckInstruction of(Opcode op, ClassEntry type) {
Util.checkKind(op, Opcode.Kind.TYPE_CHECK);
@@ -71,6 +86,8 @@ static TypeCheckInstruction of(Opcode op, ClassEntry type) {
* @param op the opcode for the specific type of type check instruction,
* which must be of kind {@link Opcode.Kind#TYPE_CHECK}
* @param type the type against which to check or cast
+ * @throws IllegalArgumentException if the opcode kind is not
+ * {@link Opcode.Kind#TYPE_CHECK}, or if {@code type} is primitive
*/
static TypeCheckInstruction of(Opcode op, ClassDesc type) {
return of(op, TemporaryConstantPool.INSTANCE.classEntry(type));
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/package-info.java b/src/java.base/share/classes/java/lang/classfile/instruction/package-info.java
index d2a36e16615..e732aadf1ec 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/package-info.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/package-info.java
@@ -26,9 +26,45 @@
/**
*
+ * Unless otherwise specified, passing {@code null} or an array or collection containing a {@code null} element as an
+ * argument to a constructor or method of any Class-File API class or interface will cause a {@link NullPointerException}
+ * to be thrown.
*
+ *
+ * When read from {@code class} files, instructions are lazily inflated; the contents of these instructions, besides the
+ * bare structure, are not evaluated to speed up parsing. Instructions to users interest, such as those filtered by the
+ * pattern matching, have their contents read on demand, to avoid unnecessary reading of unrelated instructions in a code
+ * array.
+ *
+ * Due to the lazy nature of {@code class} file parsing, {@link IllegalArgumentException} indicating malformed
+ * {@code class} file data can be thrown at any method invocation. For example, an instruction object for a {@link
+ * TypeCheckInstruction} may be obtained from a {@code CodeModel}, but the subsequent invocation of {@link
+ * TypeCheckInstruction#type() .type()} may fail with {@code IllegalArgumentException} because the instruction refers
+ * to a bad constant pool index.
+ *
+ *
+ * Due to restrictions in the {@code class} file format, some instructions may not be representable in a {@code CodeBuilder}.
+ * In some scenarios, such as for {@link BranchInstruction}, Class-File API options control if alternatives can be used
+ * in code generation instead. Otherwise, they can be configured to fail-fast to ensure the parity of {@code CodeBuilder}
+ * commands with the generated {@code code} array data.
+ *
+ * @jvms 6.5 Instructions
* @since 24
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
+import java.lang.classfile.CodeModel;
+
+ *
*
+ * @see Opcode.Kind#INCREMENT
+ * @see CodeBuilder#iinc CodeBuilder::iinc
+ * @jvms 6.5.iinc iinc
* @since 24
*/
public sealed interface IncrementInstruction extends Instruction
@@ -54,6 +72,10 @@ public sealed interface IncrementInstruction extends Instruction
/**
* {@return an increment instruction}
+ *
+ *
*
* @param slot the local variable slot to increment
* @param constant the value to increment by
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/InvokeDynamicInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/InvokeDynamicInstruction.java
index 43907b2a518..7cad91b9d8d 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/InvokeDynamicInstruction.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/InvokeDynamicInstruction.java
@@ -24,9 +24,11 @@
*/
package java.lang.classfile.instruction;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
+import java.lang.classfile.Opcode;
import java.lang.classfile.constantpool.InvokeDynamicEntry;
import java.lang.classfile.constantpool.LoadableConstantEntry;
import java.lang.classfile.constantpool.Utf8Entry;
@@ -40,10 +42,20 @@
import jdk.internal.classfile.impl.Util;
/**
- * Models an {@code invokedynamic} instruction in the {@code code} array of a
- * {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
- * the elements of a {@link CodeModel}.
+ * Models a dynamically-computed call site invocation instruction in the
+ * {@code code} array of a {@code Code} attribute. The corresponding opcode is
+ * {@link Opcode#INVOKEDYNAMIC invokedynamic}. Delivered as a {@link
+ * CodeElement} when traversing the elements of a {@link CodeModel}.
+ *
+ *
+ *
+ * @apiNote
+ * The explicit {@code op} argument allows creating {@code wide} or
+ * regular load instructions when the {@code slot} can be encoded
+ * with more optimized load instructions.
*
* @param op the opcode for the specific type of load instruction,
* which must be of kind {@link Opcode.Kind#LOAD}
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java
index 0f8cb672e51..f44a4e094f1 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/LocalVariable.java
@@ -25,10 +25,12 @@
package java.lang.classfile.instruction;
import java.lang.classfile.ClassFile;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Label;
import java.lang.classfile.PseudoInstruction;
+import java.lang.classfile.attribute.LocalVariableInfo;
import java.lang.classfile.attribute.LocalVariableTableAttribute;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.ClassDesc;
@@ -39,19 +41,45 @@
import jdk.internal.classfile.impl.Util;
/**
- * A pseudo-instruction which models a single entry in the
- * {@link LocalVariableTableAttribute}. Delivered as a {@link CodeElement}
- * during traversal of the elements of a {@link CodeModel}, according to
- * the setting of the {@link ClassFile.DebugElementsOption} option.
+ * A pseudo-instruction which models a single entry in the {@link
+ * LocalVariableTableAttribute LocalVariableTable} attribute. Delivered as a
+ * {@link CodeElement} during traversal of the elements of a {@link CodeModel},
+ * according to the setting of the {@link ClassFile.DebugElementsOption} option.
+ *
+ *
+ *
+ * @apiNote
+ * The explicit {@code op} argument allows creating {@code wide} or
+ * regular store instructions when the {@code slot} can be encoded
+ * with more optimized store instructions.
*
* @param op the opcode for the specific type of store instruction,
* which must be of kind {@link Opcode.Kind#STORE}
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/SwitchCase.java b/src/java.base/share/classes/java/lang/classfile/instruction/SwitchCase.java
index 3f5f91031b6..cce8f8ef03a 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/SwitchCase.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/SwitchCase.java
@@ -29,12 +29,20 @@
import jdk.internal.classfile.impl.AbstractInstruction;
/**
- * Models a single case in a {@code lookupswitch} or {@code tableswitch}
- * instruction.
+ * Models a single case in a {@link LookupSwitchInstruction lookupswitch} or
+ * {@link TableSwitchInstruction tableswitch} instruction.
+ * Provides interfaces describing code instructions for the {@link java.lang.classfile} library.
*
- * The {@code java.lang.classfile.attribute} package contains interfaces describing code instructions.
+ * The {@code java.lang.classfile.instruction} package contains interfaces describing code instructions.
+ * Implementations of these interfaces are immutable.
+ * Reading of instructions
+ * Instructions and pseudo-instructions are usually accessed from a {@link CodeModel}, such as {@link CodeModel#forEach
+ * CodeModel::forEach}, and categorized by pattern-matching.
+ * Writing of instructions
+ * Writing of instructions happen on {@link CodeBuilder}. The most basic way to write instructions is to pass an
+ * instruction object to {@link CodeBuilder#with CodeBuilder::with}, which supports all valid instructions.
+ * Yet, {@code CodeBuilder} provides a lot of {@linkplain CodeBuilder##instruction-factories convenience factory methods}
+ * for easy creation of instructions, named by their mnemonic. These accessors are more concise, and often more
+ * efficient at run-time than passing instruction objects.
+ *