Skip to content

Commit

Permalink
Further facelift
Browse files Browse the repository at this point in the history
  • Loading branch information
liach committed Nov 18, 2024
1 parent bc0fdda commit 4a92d72
Show file tree
Hide file tree
Showing 37 changed files with 1,010 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
* #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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@
import jdk.internal.classfile.impl.AbstractInstruction;

/**
* Models an executable instruction in the {@code code} array of the {@link CodeAttribute Code}
* attribute of a method.
* Models an executable instruction in the {@code code} array of the {@link
* CodeAttribute Code} attribute of a method.
* <p>
* Physically, instructions are discriminated unions identified by thier {@link
* #opcode() opcode()}. The exact type of the instruction can be identified
* from {@link Opcode#kind() Opcode::kind}. {@link #sizeInBytes() sizeInBytes()}
* indicates the exact size of such a discriminated union.
*
* @sealedGraph
* @since 24
Expand Down
62 changes: 52 additions & 10 deletions src/java.base/share/classes/java/lang/classfile/Label.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,63 @@
*/
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>, also known as <dfn>{@index pc}</dfn>, 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 {@code 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 {@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 LabelTarget
* @see CodeBuilder#newLabel CodeBuilder::newLabel
* @see CodeBuilder#newBoundLabel CodeBuilder::newBoundLabel
* @see CodeBuilder#startLabel CodeBuilder::startLabel
* @see CodeBuilder#endLabel CodeBuilder::endLabel
* @see CodeBuilder.BlockCodeBuilder#breakLabel BlockCodeBuilder::breakLabel
* @since 24
*/
public sealed interface Label
Expand Down
10 changes: 6 additions & 4 deletions src/java.base/share/classes/java/lang/classfile/Opcode.java
Original file line number Diff line number Diff line change
Expand Up @@ -1290,7 +1290,7 @@ public enum Opcode {
GOTO(RawBytecodeHelper.GOTO, 3, Kind.BRANCH),

/**
* Jump subroutine (discontinued); last used in major version {@value
* (Discontinued) Jump subroutine; last used in major version {@value
* ClassFile#JAVA_6_VERSION}.
*
* @see DiscontinuedInstruction.JsrInstruction
Expand All @@ -1300,7 +1300,7 @@ public enum Opcode {
JSR(RawBytecodeHelper.JSR, 3, Kind.DISCONTINUED_JSR),

/**
* Return from subroutine (discontinued); last used in major version
* (Discontinued) Return from subroutine; last used in major version
* {@value ClassFile#JAVA_6_VERSION}.
*
* @see DiscontinuedInstruction.RetInstruction
Expand Down Expand Up @@ -1522,7 +1522,7 @@ public enum Opcode {
GOTO_W(RawBytecodeHelper.GOTO_W, 5, Kind.BRANCH),

/**
* Jump subroutine (wide index) (discontinued); last used in major
* (Discontinued) Jump subroutine (wide index); last used in major
* version {@value ClassFile#JAVA_6_VERSION}.
*
* @see DiscontinuedInstruction.JsrInstruction
Expand Down Expand Up @@ -1623,8 +1623,9 @@ public enum Opcode {
ASTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ASTORE, 4, Kind.STORE),

/**
* Return from subroutine (wide index) (discontinued); last used in major
* (Discontinued) Return from subroutine (wide index) last used in major
* version {@value ClassFile#JAVA_6_VERSION}.
* This is a {@linkplain #isWide() wide}-modified pseudo-opcode.
*
* @see DiscontinuedInstruction.RetInstruction
* @jvms 4.9.1 Static Constraints
Expand All @@ -1635,6 +1636,7 @@ public enum Opcode {

/**
* Increment local variable by constant (wide index).
* This is a {@linkplain #isWide() wide}-modified pseudo-opcode.
*
* @jvms 6.5.wide <em>wide</em>
* @jvms 6.5.iinc <em>iinc</em>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -38,15 +39,34 @@
* 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>
* Conceptually, an array load instruction is a record:
* {@snippet lang=text :
* // @link substring="ArrayLoadInstruction" target="CodeBuilder#arrayLoad(TypeKind)" :
* ArrayLoadInstruction(TypeKind) // @link substring="TypeKind" target="#typeKind()"
* }
* where the {@code TypeKind} is not {@link TypeKind#BOOLEAN boolean} or
* {@link TypeKind#VOID void}. Boolean arrays use the {@link TypeKind#BYTE
* byte} kind instruction.
* <p>
* Physically, an array load instruction is a record:
* {@snippet lang=text :
* // @link substring="ArrayLoadInstruction" target="#of(Opcode)" :
* ArrayLoadInstruction(Opcode) // @link substring="Opcode" target="#opcode()"
* }
* where the {@code Opcode} is of the array load kind. The component type of
* the array is intrinsic to the opcode.
*
* @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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -38,15 +39,34 @@
* 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>
* Conceptually, an array store instruction is a record:
* {@snippet lang=text :
* // @link substring="ArrayStoreInstruction" target="CodeBuilder#arrayStore(TypeKind)" :
* ArrayStoreInstruction(TypeKind) // @link substring="TypeKind" target="#typeKind()"
* }
* where the {@code TypeKind} is not {@link TypeKind#BOOLEAN boolean} or
* {@link TypeKind#VOID void}. Boolean arrays use the {@link TypeKind#BYTE
* byte} kind instruction.
* <p>
* Physically, an array store instruction is a record:
* {@snippet lang=text :
* // @link substring="ArrayStoreInstruction" target="#of(Opcode)" :
* ArrayStoreInstruction(Opcode) // @link substring="Opcode" target="#opcode()"
* }
* where the {@code Opcode} is of the array store kind. The component type of
* the array is intrinsic to the opcode.
*
* @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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,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.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;
Expand All @@ -41,10 +35,29 @@
* {@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 may be rewritten in a {@link CodeBuilder} if the {@link
* #target() target} cannot be encoded and the {@link ClassFile.ShortJumpsOption#FIX_SHORT_JUMPS
* FIX_SHORT_JUMPS} option is set.
* Conceptually, a branch instruction is a record:
* {@snippet lang=text :
* // @link region substring="BranchInstruction" target="#of"
* // @link substring="Opcode" target="#opcode()" :
* BranchInstruction(Opcode, Label) // @link substring="Label" target="#target()"
* // @end
* }
* where the {@code Opcode} is of the branch kind.
* <p>
* Physically, a branch instruction has the same structure; however, some types
* of instructions use a {@code s2} to encode the target, which is insufficient
* to encode targets with bci offsets less than {@code -32768} or greater than
* {@code 32767}. Such instructions have a {@linkplain Opcode#sizeIfFixed()
* size} of {@code 3} bytes.
* <p>
* In such cases, if the {@link ClassFile.ShortJumpsOption#FIX_SHORT_JUMPS
* FIX_SHORT_JUMPS} option is set, a {@link CodeBuilder} will convert this
* instruction to other instructions to achieve the same effect. Otherwise,
* {@link ClassFile.ShortJumpsOption#FAIL_ON_SHORT_JUMPS FAIL_ON_SHORT_JUMPS}
* option can ensure the physical accuracy of the generated {@code class} file
* and fail if an exact representation is not possible.
*
* @see CodeBuilder#branch CodeBuilder::branch
* @since 24
*/
public sealed interface BranchInstruction extends Instruction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -40,7 +41,29 @@
* {@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.
* <p>
* Conceptually, a character range entry is a record:
* {@snippet lang=text :
* // @link region=0 substring="CharacterRange" target="#of"
* // @link region=1 substring="Label startScope" target="#startScope"
* // @link region=2 substring="Label endScope" target="#endScope"
* // @link region=3 substring="int characterRangeStart" target="#characterRangeStart"
* // @link region=4 substring="int characterRangeEnd" target="#characterRangeEnd"
* // @link substring="int flags" target="#flags()" :
* CharacterRange(Label startScope, Label endScope, int characterRangeStart, int characterRangeEnd, int flags)
* // @end region=0
* // @end region=1
* // @end region=2
* // @end region=3
* // @end region=4
* }
* <p>
* Physically, a character range has the same structure; it is modeled by a
* {@link CharacterRangeInfo}.
*
* @see CharacterRangeTableAttribute
* @see CharacterRangeInfo
* @see CodeBuilder#characterRange CodeBuilder::characterRange
* @since 24
*/
public sealed interface CharacterRange extends PseudoInstruction
Expand Down Expand Up @@ -114,7 +137,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
*/
Expand Down
Loading

0 comments on commit 4a92d72

Please sign in to comment.