mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 06:14:49 +02:00
8342469: Improve API documentation for java.lang.classfile.instruction
Reviewed-by: asotona, darcy
This commit is contained in:
parent
9bd70ec806
commit
0f035545e5
39 changed files with 2407 additions and 441 deletions
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}.
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue