8342469: Improve API documentation for java.lang.classfile.instruction

Reviewed-by: asotona, darcy
This commit is contained in:
Chen Liang 2024-12-10 20:34:12 +00:00
parent 9bd70ec806
commit 0f035545e5
39 changed files with 2407 additions and 441 deletions

View file

@ -32,6 +32,8 @@ import java.lang.classfile.attribute.ModuleAttribute;
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 @@ public sealed interface ClassFile
/**
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* This is useful to ensure the physical accuracy of a generated {@code
* class} file.
*/
FAIL_ON_SHORT_JUMPS
}

View file

@ -51,7 +51,7 @@ import static jdk.internal.classfile.impl.BytecodeHelpers.handleDescToHandleInfo
* #with(ClassFileElement)} or concretely by calling the various {@code withXxx}
* methods.
*
* <h2>Instruction Factories</h2>
* <h2 id="instruction-factories">Instruction Factories</h2>
* {@code CodeBuilder} provides convenience methods to create instructions (See
* JVMS {@jvms 6.5} Instructions) by their mnemonic, taking necessary operands.
* <ul>

View file

@ -25,13 +25,20 @@
package java.lang.classfile;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.instruction.*;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models an executable instruction in a method body.
* Models an executable instruction in the {@code code} array of the {@link
* CodeAttribute Code} attribute of a method.
* <p>
* 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();
}

View file

@ -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}.
*
* <h2 id="reading">Reading Labels</h2>
* Labels read from {@code class} files represent positions in the {@code code}
* array of a {@link CodeAttribute Code} attribute. It is associated with a
* <dfn>{@index bci}</dfn> (bytecode index), also known as <dfn>{@index pc}</dfn>
* (program counter), the index into the {@code code} array; the actual cursor
* position is immediately before the given index, so a label at the beginning
* of the instructions has bci {@code 0}, and a label at the end of the
* instructions has bci {@link CodeAttribute#codeLength codeLength() + 1}. The
* bci can be inspected through {@link CodeAttribute#labelToBci
* CodeAttribute::labelToBci}.
* <p>
* 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.
*
* <h2 id="writing">Writing Labels</h2>
* Many models in {@link java.lang.classfile} refer to labels. To write a
* label, a label must be obtained, it must be bound to a {@link CodeBuilder}.
* <p>
* To obtain a label:
* <ul>
* <li>Use a label read from other models.
* <li>Use pre-defined labels from a {@link CodeBuilder}, such as {@link
* CodeBuilder#startLabel() CodeBuilder::startLabel}, {@link CodeBuilder#endLabel
* CodeBuilder::endLabel}, or {@link CodeBuilder.BlockCodeBuilder#breakLabel
* BlockCodeBuilder::breakLabel}. They are already bound.
* <li>Create labels with {@link CodeBuilder#newLabel CodeBuilder::newLabel} or
* {@link CodeBuilder#newBoundLabel CodeBuilder::newBoundLabel}.
* </ul>
* <p>
* A label must be bound exactly once in the {@code CodeBuilder} where it is
* used; otherwise, writing fails. To bind an unbound label:
* <ul>
* <li>Send a read {@link LabelTarget} to a {@code CodeBuilder}.
* <li>Use {@link CodeBuilder#labelBinding CodeBuilder::labelBinding}.
* </ul>
* Note that a label read from another model is not automatically bound in a
* {@code CodeBuilder}; they are separate entities and the label is bound to
* different positions in them.
*
* @see CodeAttribute#labelToBci CodeAttribute::labelToBci
* @see CodeBuilder#newLabel CodeBuilder::newLabel
* @see CodeBuilder#labelBinding CodeBuilder::labelBinding
* @since 24
*/
public sealed interface Label

File diff suppressed because it is too large Load diff

View file

@ -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 java.lang.invoke.TypeDescriptor;
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.
* <p>
* The <code>{@index returnAddress}</code> 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.
*
* <h2 id="computational-type">Computational Type</h2>
* In the {@code class} file format, local variables (JVMS {@jvms 2.6.1}),
@ -164,7 +171,10 @@ public enum TypeKind {
/**
* {@return the code used by the {@link Opcode#NEWARRAY newarray} instruction to create an array
* of this component type, or {@code -1} if this type is not supported by {@code newarray}}
* @jvms 6.5.newarray <i>newarray</i>
*
* @jvms 6.5.newarray <em>newarray</em>
* @see NewPrimitiveArrayInstruction
* @see #fromNewarrayCode(int) fromNewarrayCode(int)
*/
public int newarrayCode() {
return newarrayCode;
@ -175,6 +185,7 @@ public enum TypeKind {
* This is also the category of this type for instructions operating on the operand stack without
* regard to type (JVMS {@jvms 2.11.1}), such as {@link Opcode#POP pop} versus {@link Opcode#POP2
* pop2}.
*
* @jvms 2.6.1 Local Variables
* @jvms 2.6.2 Operand Stacks
*/
@ -185,6 +196,9 @@ public enum TypeKind {
/**
* {@return the {@linkplain ##computational-type computational type} for this type, or {@link #VOID void}
* for {@code void}}
*
* @see LoadInstruction
* @see StoreInstruction
*/
public TypeKind asLoadable() {
return ordinal() < 4 ? INT : this;
@ -193,9 +207,12 @@ public enum TypeKind {
/**
* {@return the component type described by the array code used as an operand to {@link Opcode#NEWARRAY
* newarray}}
*
* @param newarrayCode the operand of the {@code newarray} instruction
* @throws IllegalArgumentException if the code is invalid
* @jvms 6.5.newarray <i>newarray</i>
* @jvms 6.5.newarray <em>newarray</em>
* @see NewPrimitiveArrayInstruction
* @see #newarrayCode() newarrayCode()
*/
public static TypeKind fromNewarrayCode(int newarrayCode) {
return switch (newarrayCode) {

View file

@ -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 @@ import jdk.internal.classfile.impl.Util;
/**
* Models an array load instruction in the {@code code} array of a {@code Code}
* attribute. Corresponding opcodes will have a {@code kind} of {@link
* Opcode.Kind#ARRAY_LOAD}. Delivered as a {@link CodeElement} when
* attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind}
* of {@link Opcode.Kind#ARRAY_LOAD}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
* <p>
* 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);

View file

@ -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 @@ import jdk.internal.classfile.impl.Util;
/**
* 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}.
* <p>
* 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);

View file

@ -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}.
* <p>
* 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()"
* )
* }
* <p>
* 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);

View file

@ -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.AbstractPseudoInstruction;
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.
* <p>
* 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"
* )
* }
* <p>
* 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
* <li>{@link #FLAG_BRANCH_FALSE}
* </ul>
*
* @see java.lang.classfile.attribute.CharacterRangeInfo#flags()
* @see CharacterRangeInfo#flags()
*
* @return the flags
*/

View file

@ -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;
@ -38,12 +39,22 @@ import jdk.internal.classfile.impl.Util;
/**
* Models a constant-load instruction in the {@code code} array of a {@code
* Code} attribute, including "intrinsic constant" instructions (e.g., {@code
* iconst_0}), "argument constant" instructions (e.g., {@code bipush}), and "load
* constant" instructions (e.g., {@code LDC}). Corresponding opcodes will have
* a {@code kind} of {@link Opcode.Kind#CONSTANT}. Delivered as a {@link
* CodeElement} when traversing the elements of a {@link CodeModel}.
* Code} attribute, including {@linkplain IntrinsicConstantInstruction
* "intrinsic"}, {@linkplain ArgumentConstantInstruction "argument"}, and
* {@linkplain LoadConstantInstruction "load"} constant instructions.
* Corresponding opcodes have a {@linkplain Opcode#kind() kind} of {@link
* Opcode.Kind#CONSTANT}. Delivered as a {@link CodeElement} when traversing
* the elements of a {@link CodeModel}.
* <p>
* 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}.
* <p>
* An intrinsic constant instruction is composite:
* {@snippet lang=text :
* // @link substring="IntrinsicConstantInstruction" target="#ofIntrinsic" :
* IntrinsicConstantInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()"
* }
* where:
* <dl>
* <dt>{@link #opcode() opcode}</dt>
* <dd>Must be of the constant kind and have a {@linkplain
* Opcode#sizeIfFixed() fixed size} of 1.</dd>
* </dl>
*
* @see Opcode.Kind#CONSTANT
* @see ConstantInstruction#ofIntrinsic ConstantInstruction::ofIntrinsic
* @since 24
*/
sealed interface IntrinsicConstantInstruction extends ConstantInstruction
permits AbstractInstruction.UnboundIntrinsicConstantInstruction {
/**
* {@return the type of the constant}
*/
@Override
default TypeKind typeKind() {
return BytecodeHelpers.intrinsicConstantType(opcode());
@ -77,9 +102,31 @@ public sealed interface ConstantInstruction extends Instruction {
}
/**
* Models an "argument constant" instruction (e.g., {@code
* bipush}).
* Models an "argument constant" instruction, which encodes the
* constant value in the instruction directly. Includes {@link
* Opcode#BIPUSH bipush} and {@link Opcode#SIPUSH sipush} instructions.
* <p>
* 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:
* <ul>
* <li>{@code opcode} must be one of {@code bipush} or {@code sipush}.
* <li>{@code constantValue} must be in the range of {@code byte}, {@code
* [-128, 127]}, for {@code bipush}, and in the range of {@code short},
* {@code [-32768, 32767]}, for {@code sipush}.
* </ul>
*
* @see Opcode.Kind#CONSTANT
* @see ConstantInstruction#ofArgument ConstantInstruction::ofArgument
* @see CodeBuilder#loadConstant(int) CodeBuilder::loadConstant(int)
* @see CodeBuilder#bipush CodeBuilder::bipush
* @see CodeBuilder#sipush CodeBuilder::sipush
* @since 24
*/
sealed interface ArgumentConstantInstruction extends ConstantInstruction
@ -89,9 +136,6 @@ public sealed interface ConstantInstruction extends Instruction {
@Override
Integer constantValue();
/**
* {@return the type of the constant}
*/
@Override
default TypeKind typeKind() {
return TypeKind.INT;
@ -99,9 +143,24 @@ public sealed interface ConstantInstruction extends Instruction {
}
/**
* Models a "load constant" instruction (e.g., {@code
* ldc}).
* Models a "load constant" instruction, which encodes the constant value
* in the constant pool. Includes {@link Opcode#LDC ldc} and {@link
* Opcode#LDC_W ldc_w}, and {@link Opcode#LDC2_W ldc2_w} instructions.
* <p>
* A load constant instruction is composite:
* {@snippet lang=text :
* // @link substring="LoadConstantInstruction" target="CodeBuilder#ldc(LoadableConstantEntry)" :
* LoadConstantInstruction(LoadableConstantEntry constantEntry) // @link substring="constantEntry" target="#constantEntry()"
* }
* <p>
* 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 @@ public sealed interface ConstantInstruction extends Instruction {
*/
LoadableConstantEntry constantEntry();
/**
* {@return the type of the constant}
*/
@Override
default TypeKind typeKind() {
return constantEntry().typeKind();
@ -139,6 +195,10 @@ public sealed interface ConstantInstruction extends Instruction {
/**
* {@return an argument constant instruction}
* <p>
* {@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}

View file

@ -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 @@ import jdk.internal.classfile.impl.Util;
/**
* 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}.
* <p>
* 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:
* <ul>
* <li>Between {@code int}, {@code long}, {@code float}, and {@code double}, where
* {@code fromType != toType};
* <li>From {@code int} to {@code byte}, {@code char}, and {@code short}.
* </ul>
*
* @see Opcode.Kind#CONVERT
* @see CodeBuilder#conversion CodeBuilder::conversion
* @since 24
*/
public sealed interface ConvertInstruction extends Instruction
@ -55,10 +73,16 @@ public sealed interface ConvertInstruction extends Instruction
TypeKind toType();
/**
* {@return A conversion instruction}
* {@return a conversion instruction} Valid conversions are:
* <ul>
* <li>Between {@code int}, {@code long}, {@code float}, and {@code double},
* where {@code fromType != toType};
* <li>From {@code int} to {@code byte}, {@code char}, and {@code short}.
* </ul>
*
* @param fromType the type to convert from
* @param toType the type to convert to
* @throws IllegalArgumentException if this is not a valid conversion
*/
static ConvertInstruction of(TypeKind fromType, TypeKind toType) {
return of(BytecodeHelpers.convertOpcode(fromType, toType));

View file

@ -24,32 +24,54 @@
*/
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.BytecodeHelpers;
import jdk.internal.classfile.impl.Util;
/**
* Models instruction discontinued from the {@code code} array of a {@code Code}
* attribute. Delivered as a {@link CodeElement} when traversing the elements of
* a {@link CodeModel}.
* Marker interface for instruction discontinued from the {@code code} array of
* a {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
* the elements of a {@link CodeModel}.
*
* @apiNote
* While most instructions have convenience factory methods in {@link
* CodeBuilder}, discontinued instructions can only be supplied to code builders
* explicitly with {@link CodeBuilder#with CodeBuilder::with} to discourage
* their use.
*
* @jvms 4.9.1 Static Constraints
* @sealedGraph
* @since 24
*/
public sealed interface DiscontinuedInstruction extends Instruction {
/**
* Models JSR and JSR_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
* {@link Opcode.Kind#DISCONTINUED_JSR}. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
* Models jump 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_JSR}.
* Delivered as a {@link CodeElement} when traversing the elements of a
* {@link CodeModel}.
* <p>
* A jump subroutine instruction is composite:
* {@snippet lang=text :
* // @link substring="JsrInstruction" target="#of(Label)" :
* JsrInstruction(Label target) // @link substring="target" target="#target()"
* }
* <p>
* 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}.
* <p>
* 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 @@ public sealed interface DiscontinuedInstruction extends Instruction {
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 @@ public sealed interface DiscontinuedInstruction extends Instruction {
}
/**
* {@return a JSR instruction}
* {@return a jump subroutine instruction}
*
* @param target target label of the subroutine
*/
@ -86,12 +112,26 @@ public sealed interface DiscontinuedInstruction extends Instruction {
}
/**
* 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}.
* <p>
* 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]}.
* <p>
* {@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 <em>ret</em>
* @see Opcode.Kind#DISCONTINUED_RET
* @since 24
*/
sealed interface RetInstruction extends DiscontinuedInstruction
@ -100,13 +140,23 @@ public sealed interface DiscontinuedInstruction extends Instruction {
/**
* {@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}
* <p>
* {@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}.
*
* @param op the opcode for the specific type of RET instruction,
* @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 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 @@ public sealed interface DiscontinuedInstruction extends Instruction {
}
/**
* {@return a RET instruction}
* {@return a return from subroutine instruction}
* <p>
* {@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

View file

@ -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}.
* <p>
* 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<ClassEntry> catchType // @link substring="catchType" target="#catchType"
* )
* }
*
* @see CodeBuilder#exceptionCatch CodeBuilder::exceptionCatch
* @jvms 4.7.3 The {@code Code} Attribute
* @since 24
*/
public sealed interface ExceptionCatch extends PseudoInstruction
@ -61,8 +75,8 @@ public sealed interface ExceptionCatch extends PseudoInstruction
Label tryEnd();
/**
* {@return the type of the exception to catch, or empty if this handler is
* unconditional}
* {@return the type of the exception to catch, or empty if this handler
* catches everything}
*/
Optional<ClassEntry> catchType();
@ -80,10 +94,10 @@ public sealed interface ExceptionCatch extends PseudoInstruction
}
/**
* {@return an exception table pseudo-instruction for an unconditional handler}
* {@return an exception table pseudo-instruction to catch everything}
* @param handler the handler for the exception
* @param tryStart the beginning of the instruction range for the gaurded instructions
* @param tryEnd the end of the instruction range for the gaurded instructions
* @param tryStart the beginning of the instruction range for the guarded instructions
* @param tryEnd the end of the instruction range for the guarded instructions
*/
static ExceptionCatch of(Label handler, Label tryStart, Label tryEnd) {
return new AbstractPseudoInstruction.ExceptionCatchImpl(handler, tryStart, tryEnd, (ClassEntry) null);

View file

@ -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;
@ -40,10 +41,21 @@ import jdk.internal.classfile.impl.Util;
/**
* Models a field access instruction in the {@code code} array of a {@code Code}
* attribute. Corresponding opcodes will have a {@code kind} of {@link
* Opcode.Kind#FIELD_ACCESS}. Delivered as a {@link CodeElement} when
* attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind}
* of {@link Opcode.Kind#FIELD_ACCESS}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
* <p>
* 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 @@ public sealed interface FieldInstruction extends Instruction
}
/**
* {@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 @@ public sealed interface FieldInstruction extends Instruction
* @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 @@ public sealed interface FieldInstruction extends Instruction
* 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,

View file

@ -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 @@ import jdk.internal.classfile.impl.AbstractInstruction;
/**
* 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}.
* <p>
* 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
* <ul>
* <li>{@code slot} must be within {@code [0, 65535]}.
* <li>{@code constant} must be within {@code [-32768, 32767]}.
* </ul>
*
* @see Opcode.Kind#INCREMENT
* @see CodeBuilder#iinc CodeBuilder::iinc
* @jvms 6.5.iinc <em>iinc</em>
* @since 24
*/
public sealed interface IncrementInstruction extends Instruction
@ -54,6 +72,10 @@ public sealed interface IncrementInstruction extends Instruction
/**
* {@return an increment instruction}
* <ul>
* <li>{@code slot} must be within {@code [0, 65535]}.
* <li>{@code constant} must be within {@code [-32768, 32767]}.
* </ul>
*
* @param slot the local variable slot to increment
* @param constant the value to increment by

View file

@ -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.AbstractInstruction;
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}.
* <p>
* 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 <em>invokedynamic</em>
* @since 24
*/
public sealed interface InvokeDynamicInstruction extends Instruction
@ -62,6 +74,10 @@ public sealed interface InvokeDynamicInstruction extends Instruction
/**
* {@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();

View file

@ -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 @@ import jdk.internal.classfile.impl.Util;
/**
* 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}.
* <p>
* 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}
* <p>
* 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 <em>invokeinterface</em>
*/
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 @@ public sealed interface InvokeInstruction extends Instruction
}
/**
* {@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 @@ public sealed interface InvokeInstruction extends Instruction
return Util.methodTypeSymbol(method().type());
}
/**
* {@return an invocation instruction}
*
@ -103,7 +131,7 @@ public sealed interface InvokeInstruction extends Instruction
* 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 @@ public sealed interface InvokeInstruction extends Instruction
* @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 @@ public sealed interface InvokeInstruction extends Instruction
* @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,

View file

@ -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 @@ import jdk.internal.classfile.impl.LabelImpl;
* 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}.
* <p>
* This can be used to inspect the target position of labels across {@linkplain
* CodeTransform transformations}, as {@linkplain CodeAttribute#labelToBci bci}
* is not stable.
* <p>
* When passed to a {@link CodeBuilder}, this pseudo-instruction sets the
* specified label to be bound at the current position in the builder.
* <p>
* 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}.
* <p>
* 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

View file

@ -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.
* <p>
* A line number entry is composite:
* {@snippet lang=text :
* // @link substring="LineNumber" target="#of" :
* LineNumber(int line) // @link substring="int line" target="#line"
* }
* <p>
* 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

View file

@ -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 @@ import jdk.internal.classfile.impl.Util;
/**
* 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}.
* <p>
* 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 @@ public sealed interface LoadInstruction extends Instruction
/**
* {@return a local variable load instruction}
* <p>
* The range of {@code slot} is restricted by the {@code op} and its
* {@linkplain Opcode#sizeIfFixed() size}:
* <ul>
* <li>If {@code op} has size 1, {@code slot} must be exactly the slot value
* implied by the opcode.
* <li>If {@code op} has size 2, {@code slot} must be within {@code [0, 255]}.
* <li>If {@code op} has size 4, {@code slot} must be within {@code [0, 65535]}.
* </ul>
*
* @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}

View file

@ -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.TemporaryConstantPool;
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.
* <p>
* 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]}.
* <p>
* 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 @@ public sealed interface LocalVariable extends PseudoInstruction
/**
* {@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 @@ public sealed interface LocalVariable extends PseudoInstruction
/**
* {@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

View file

@ -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 @@ import jdk.internal.classfile.impl.TemporaryConstantPool;
/**
* 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.
* <p>
* 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]}.
* <p>
* 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 @@ public sealed interface LocalVariableType extends PseudoInstruction
/**
* {@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 @@ public sealed interface LocalVariableType extends PseudoInstruction
/**
* {@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

View file

@ -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}.
* <p>
* A lookup switch instruction is composite:
* {@snippet lang=text :
* // @link substring="LookupSwitchInstruction" target="#of" :
* LookupSwitchInstruction(
* Label defaultTarget, // @link substring="defaultTarget" target="#defaultTarget"
* List<SwitchCase> cases // @link substring="cases" target="#cases()"
* )
* }
* If elements in {@code cases} are not sorted ascending by their {@link
* SwitchCase#caseValue caseValue}, a sorted version of the {@code cases} list
* will be written instead.
*
* @see Opcode.Kind#LOOKUP_SWITCH
* @see CodeBuilder#lookupswitch CodeBuilder::lookupswitch
* @jvms 6.5.lookupswitch <em>lookupswitch</em>
* @since 24
*/
public sealed interface LookupSwitchInstruction extends Instruction

View file

@ -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,9 +34,17 @@ import jdk.internal.classfile.impl.AbstractInstruction;
import jdk.internal.classfile.impl.Util;
/**
* Models a {@code monitorenter} or {@code monitorexit} 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#MONITORENTER monitorenter} or {@link Opcode#MONITOREXIT
* monitorexit} instruction in the {@code code} array of a {@code Code} attribute.
* Corresponding opcodes have a {@linkplain Opcode#kind() kind} of {@link
* Opcode.Kind#MONITOR}. Delivered as a {@link CodeElement} when traversing the
* elements of a {@link CodeModel}.
* <p>
* A monitor instruction is composite:
* {@snippet lang=text :
* // @link substring="MonitorInstruction" target="#of(Opcode)" :
* MonitorInstruction(Opcode opcode) // @link substring="opcode" target="#opcode"
* }
*
* @since 24
*/

View file

@ -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}.
* <p>
* 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 <em>multianewarray</em>
* @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();

View file

@ -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}.
* <p>
* 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 <em>new</em>
* @since 24
*/
public sealed interface NewObjectInstruction extends Instruction

View file

@ -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}.
* <p>
* 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 <em>newarray</em>
* @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:

View file

@ -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}.
* <p>
* 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 <em>anewarray</em>
* @since 24
*/
public sealed interface NewReferenceArrayInstruction extends Instruction

View file

@ -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}.
* <p>
* A no-op instruction has no visible state.
*
* @see CodeBuilder#nop CodeBuilder::nop
* @jvms 6.5.nop <em>nop</em>
* @since 24
*/
public sealed interface NopInstruction extends Instruction

View file

@ -35,23 +35,31 @@ import jdk.internal.classfile.impl.Util;
/**
* 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}.
* <p>
* 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}.

View file

@ -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 @@ import jdk.internal.classfile.impl.Util;
/**
* 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}.
* <p>
* 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
*/

View file

@ -34,10 +34,17 @@ import jdk.internal.classfile.impl.Util;
/**
* 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}.
* <p>
* 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

View file

@ -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 @@ import jdk.internal.classfile.impl.Util;
/**
* 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}.
* <p>
* 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]}.
* <p>
* {@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 @@ public sealed interface StoreInstruction extends Instruction
/**
* {@return a local variable store instruction}
* <p>
* The range of {@code slot} is restricted by the {@code op} and its
* {@linkplain Opcode#sizeIfFixed() size}:
* <ul>
* <li>If {@code op} has size 1, {@code slot} must be exactly the slot value
* implied by the opcode.
* <li>If {@code op} has size 2, {@code slot} must be within {@code [0, 255]}.
* <li>If {@code op} has size 4, {@code slot} must be within {@code [0, 65535]}.
* </ul>
*
* @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}

View file

@ -29,12 +29,20 @@ import java.lang.classfile.Label;
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.
* <p>
* 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);

View file

@ -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}.
* <p>
* 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<SwitchCase> cases // @link substring="cases" target="#cases()"
* )
* }
* <p>
* 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}.
* <p>
* 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 <em>tableswitch</em>
* @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<SwitchCase> cases) {
return new AbstractInstruction.UnboundTableSwitchInstruction(lowValue, highValue, defaultTarget, cases);

View file

@ -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 an {@code athrow} instruction in the {@code code} array of a
* Models an {@link Opcode#ATHROW athrow} instruction in the {@code code} array of a
* {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
* the elements of a {@link CodeModel}.
* <p>
* 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

View file

@ -36,9 +36,24 @@ import jdk.internal.classfile.impl.TemporaryConstantPool;
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}.
* <p>
* 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.
* <p>
* 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 @@ public sealed interface TypeCheckInstruction extends Instruction
* @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));

View file

@ -26,9 +26,45 @@
/**
* <h2>Provides interfaces describing code instructions for the {@link java.lang.classfile} library.</h2>
*
* 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.
* <p>
* 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.
*
* <h2 id="reading">Reading of instructions</h2>
* Instructions and pseudo-instructions are usually accessed from a {@link CodeModel}, such as {@link CodeModel#forEach
* CodeModel::forEach}, and categorized by pattern-matching.
* <p>
* 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.
* <p>
* 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.
*
* <h2 id="writing">Writing of instructions</h2>
* 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.
* <p>
* 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;