Compare commits

...

9 Commits

Author SHA1 Message Date
Coleen Phillimore
950c8adfd7 8340212: -Xshare:off -XX:CompressedClassSpaceBaseAddress=0x40001000000 crashes on macos-aarch64
Reviewed-by: iklam
Backport-of: a6277bb521
2024-12-11 17:16:13 +00:00
Chen Liang
03bdee0f75 8342469: Improve API documentation for java.lang.classfile.instruction
Reviewed-by: asotona
Backport-of: 0f035545e5
2024-12-11 16:06:40 +00:00
Kevin Driver
4ecb28ccdc 8344924: Default CA certificates loaded despite request to use custom keystore
Reviewed-by: mullan
Backport-of: 4c39e9faa0
2024-12-10 21:14:37 +00:00
Michael McMahon
ba02e0bd1b 8345794: Backout doc change introduced by JDK-8235786
Reviewed-by: dfuchs
Backport-of: eff20a38c7
2024-12-10 16:58:13 +00:00
Per Minborg
253030a6d4 8345465: Fix performance regression on x64 after JDK-8345120
Reviewed-by: jvernee
Backport-of: 06c44dd568
2024-12-10 14:22:42 +00:00
Chen Liang
a81325433d 8334733: Remove obsolete @enablePreview from tests after JDK-8334714
Reviewed-by: mchung
Backport-of: 4966419550
2024-12-09 18:35:16 +00:00
Magnus Ihse Bursie
203422a8ed 8345424: Move FindDebuginfoFiles out of FileUtils.gmk
Reviewed-by: erikj
Backport-of: 5f30a8d90c
2024-12-09 15:57:55 +00:00
Fernando Guallini
8e9ba788ae 8345414: Google CAInterop test failures
Reviewed-by: rhalade
2024-12-06 18:41:47 +00:00
Matias Saavedra Silva
3aa07dbf14 8343890: SEGV crash in RunTimeClassInfo::klass
Reviewed-by: ccheung
Backport-of: bf0debc023
2024-12-05 22:01:31 +00:00
418 changed files with 2737 additions and 1293 deletions

View File

@@ -29,6 +29,7 @@ include $(SPEC)
include MakeBase.gmk
include CopyFiles.gmk
include DebugInfoUtils.gmk
include Execute.gmk
include Modules.gmk
include Utils.gmk

View File

@@ -29,6 +29,7 @@ include $(SPEC)
include MakeBase.gmk
include CopyFiles.gmk
include DebugInfoUtils.gmk
include Modules.gmk
include modules/LauncherCommon.gmk

View File

@@ -0,0 +1,58 @@
#
# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
ifeq ($(_MAKEBASE_GMK), )
$(error You must include MakeBase.gmk prior to including DebugInfoUtils.gmk)
endif
################################################################################
#
# Common debuginfo utility functions
#
################################################################################
################################################################################
# Find native debuginfo files in a directory
#
# Param 1 - dir to find debuginfo files in
FindDebuginfoFiles = \
$(wildcard $(addprefix $1/*, $(DEBUGINFO_SUFFIXES)) \
$(addprefix $1/*/*, $(DEBUGINFO_SUFFIXES)) \
$(addprefix $1/*/*/*, $(DEBUGINFO_SUFFIXES)))
# Pick the correct debug info files to copy, either zipped or not.
ifeq ($(ZIP_EXTERNAL_DEBUG_SYMBOLS), true)
DEBUGINFO_SUFFIXES += .diz
else
DEBUGINFO_SUFFIXES := .debuginfo .pdb .map
# On Macosx, if debug symbols have not been zipped, find all files inside *.dSYM
# dirs.
ifeq ($(call isTargetOs, macosx), true)
$(call FillFindCache, \
$(SUPPORT_OUTPUTDIR)/modules_libs $(SUPPORT_OUTPUTDIR)/modules_cmds)
FindDebuginfoFiles = \
$(if $(wildcard $1), $(call containing, .dSYM/, $(call FindFiles, $1)))
endif
endif

View File

@@ -307,26 +307,3 @@ ifeq ($(DISABLE_CACHE_FIND), true)
else
FindFiles = $(CacheFindFiles)
endif
# Find native debuginfo files in a directory
#
# Param 1 - dir to find debuginfo files in
FindDebuginfoFiles = \
$(wildcard $(addprefix $1/*, $(DEBUGINFO_SUFFIXES)) \
$(addprefix $1/*/*, $(DEBUGINFO_SUFFIXES)) \
$(addprefix $1/*/*/*, $(DEBUGINFO_SUFFIXES)))
# Pick the correct debug info files to copy, either zipped or not.
ifeq ($(ZIP_EXTERNAL_DEBUG_SYMBOLS), true)
DEBUGINFO_SUFFIXES += .diz
else
DEBUGINFO_SUFFIXES := .debuginfo .pdb .map
# On Macosx, if debug symbols have not been zipped, find all files inside *.dSYM
# dirs.
ifeq ($(call isTargetOs, macosx), true)
$(call FillFindCache, \
$(SUPPORT_OUTPUTDIR)/modules_libs $(SUPPORT_OUTPUTDIR)/modules_cmds)
FindDebuginfoFiles = \
$(if $(wildcard $1), $(call containing, .dSYM/, $(call FindFiles, $1)))
endif
endif

View File

@@ -24,12 +24,14 @@
*/
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/macroAssembler.hpp"
#include "logging/log.hpp"
#include "oops/compressedKlass.hpp"
#include "memory/metaspace.hpp"
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/formatBuffer.hpp"
// Helper function; reserve at an address that is compatible with EOR
static char* reserve_at_eor_compatible_address(size_t size, bool aslr) {
@@ -79,6 +81,7 @@ static char* reserve_at_eor_compatible_address(size_t size, bool aslr) {
}
return result;
}
char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size_t size, bool aslr, bool optimize_for_zero_base) {
char* result = nullptr;
@@ -117,3 +120,12 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size
return result;
}
bool CompressedKlassPointers::check_klass_decode_mode(address base, int shift, const size_t range) {
return MacroAssembler::check_klass_decode_mode(base, shift, range);
}
bool CompressedKlassPointers::set_klass_decode_mode() {
const size_t range = klass_range_end() - base();
return MacroAssembler::set_klass_decode_mode(_base, _shift, range);
}

View File

@@ -5291,32 +5291,47 @@ void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) {
MacroAssembler::KlassDecodeMode MacroAssembler::_klass_decode_mode(KlassDecodeNone);
MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode() {
assert(UseCompressedClassPointers, "not using compressed class pointers");
assert(Metaspace::initialized(), "metaspace not initialized yet");
assert(_klass_decode_mode != KlassDecodeNone, "should be initialized");
return _klass_decode_mode;
}
if (_klass_decode_mode != KlassDecodeNone) {
return _klass_decode_mode;
}
MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode(address base, int shift, const size_t range) {
assert(UseCompressedClassPointers, "not using compressed class pointers");
if (CompressedKlassPointers::base() == nullptr) {
return (_klass_decode_mode = KlassDecodeZero);
// KlassDecodeMode shouldn't be set already.
assert(_klass_decode_mode == KlassDecodeNone, "set once");
if (base == nullptr) {
return KlassDecodeZero;
}
if (operand_valid_for_logical_immediate(
/*is32*/false, (uint64_t)CompressedKlassPointers::base())) {
const size_t range = CompressedKlassPointers::klass_range_end() - CompressedKlassPointers::base();
/*is32*/false, (uint64_t)base)) {
const uint64_t range_mask = right_n_bits(log2i_ceil(range));
if (((uint64_t)CompressedKlassPointers::base() & range_mask) == 0) {
return (_klass_decode_mode = KlassDecodeXor);
if (((uint64_t)base & range_mask) == 0) {
return KlassDecodeXor;
}
}
const uint64_t shifted_base =
(uint64_t)CompressedKlassPointers::base() >> CompressedKlassPointers::shift();
guarantee((shifted_base & 0xffff0000ffffffff) == 0,
"compressed class base bad alignment");
(uint64_t)base >> shift;
if ((shifted_base & 0xffff0000ffffffff) == 0) {
return KlassDecodeMovk;
}
return (_klass_decode_mode = KlassDecodeMovk);
// No valid encoding.
return KlassDecodeNone;
}
// Check if one of the above decoding modes will work for given base, shift and range.
bool MacroAssembler::check_klass_decode_mode(address base, int shift, const size_t range) {
return klass_decode_mode(base, shift, range) != KlassDecodeNone;
}
bool MacroAssembler::set_klass_decode_mode(address base, int shift, const size_t range) {
_klass_decode_mode = klass_decode_mode(base, shift, range);
return _klass_decode_mode != KlassDecodeNone;
}
void MacroAssembler::encode_klass_not_null(Register dst, Register src) {

View File

@@ -94,11 +94,22 @@ class MacroAssembler: public Assembler {
KlassDecodeMovk
};
KlassDecodeMode klass_decode_mode();
// Calculate decoding mode based on given parameters, used for checking then ultimately setting.
static KlassDecodeMode klass_decode_mode(address base, int shift, const size_t range);
private:
static KlassDecodeMode _klass_decode_mode;
// Returns above setting with asserts
static KlassDecodeMode klass_decode_mode();
public:
// Checks the decode mode and returns false if not compatible with preferred decoding mode.
static bool check_klass_decode_mode(address base, int shift, const size_t range);
// Sets the decode mode and returns false if cannot be set.
static bool set_klass_decode_mode(address base, int shift, const size_t range);
public:
MacroAssembler(CodeBuffer* code) : Assembler(code) {}

View File

@@ -145,15 +145,16 @@ size_t MetaspaceShared::core_region_alignment() {
}
static bool shared_base_valid(char* shared_base) {
// We check user input for SharedBaseAddress at dump time. We must weed out values
// we already know to be invalid later.
// We check user input for SharedBaseAddress at dump time.
// At CDS runtime, "shared_base" will be the (attempted) mapping start. It will also
// be the encoding base, since the the headers of archived base objects (and with Lilliput,
// the prototype mark words) carry pre-computed narrow Klass IDs that refer to the mapping
// start as base.
//
// Therefore, "shared_base" must be later usable as encoding base.
// On AARCH64, The "shared_base" may not be later usable as encoding base, depending on the
// total size of the reserved area and the precomputed_narrow_klass_shift. This is checked
// before reserving memory. Here we weed out values already known to be invalid later.
return AARCH64_ONLY(is_aligned(shared_base, 4 * G)) NOT_AARCH64(true);
}
@@ -1486,6 +1487,15 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
const size_t total_range_size =
archive_space_size + gap_size + class_space_size;
// Test that class space base address plus shift can be decoded by aarch64, when restored.
const int precomputed_narrow_klass_shift = ArchiveBuilder::precomputed_narrow_klass_shift();
if (!CompressedKlassPointers::check_klass_decode_mode(base_address, precomputed_narrow_klass_shift,
total_range_size)) {
log_info(cds)("CDS initialization: Cannot use SharedBaseAddress " PTR_FORMAT " with precomputed shift %d.",
p2i(base_address), precomputed_narrow_klass_shift);
use_archive_base_addr = false;
}
assert(total_range_size > ccs_begin_offset, "must be");
if (use_windows_memory_mapping() && use_archive_base_addr) {
if (base_address != nullptr) {
@@ -1525,7 +1535,7 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
}
// Paranoid checks:
assert(base_address == nullptr || (address)total_space_rs.base() == base_address,
assert(!use_archive_base_addr || (address)total_space_rs.base() == base_address,
"Sanity (" PTR_FORMAT " vs " PTR_FORMAT ")", p2i(base_address), p2i(total_space_rs.base()));
assert(is_aligned(total_space_rs.base(), base_address_alignment), "Sanity");
assert(total_space_rs.size() == total_range_size, "Sanity");

View File

@@ -76,10 +76,13 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) {
}
InstanceKlass* RunTimeClassInfo::klass() const {
if (ArchiveBuilder::is_active() && ArchiveBuilder::current()->is_in_buffer_space((address)this)) {
return ArchiveBuilder::current()->offset_to_buffered<InstanceKlass*>(_klass_offset);
} else {
if (MetaspaceShared::is_in_shared_metaspace(this)) {
// <this> is inside a mmaped CDS archive.
return ArchiveUtils::offset_to_archived_address<InstanceKlass*>(_klass_offset);
} else {
// <this> is a temporary copy of a RunTimeClassInfo that's being initialized
// by the ArchiveBuilder.
return ArchiveBuilder::current()->offset_to_buffered<InstanceKlass*>(_klass_offset);
}
}

View File

@@ -30,6 +30,7 @@
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "utilities/debug.hpp"
#include "utilities/formatBuffer.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/ostream.hpp"
@@ -176,6 +177,12 @@ void CompressedKlassPointers::initialize_for_given_encoding(address addr, size_t
calc_lowest_highest_narrow_klass_id();
// This has already been checked for SharedBaseAddress and if this fails, it's a bug in the allocation code.
if (!set_klass_decode_mode()) {
fatal("base=" PTR_FORMAT " given with shift %d, cannot be used to encode class pointers",
p2i(_base), _shift);
}
DEBUG_ONLY(sanity_check_after_initialization();)
}
@@ -267,6 +274,20 @@ void CompressedKlassPointers::initialize(address addr, size_t len) {
calc_lowest_highest_narrow_klass_id();
// Initialize klass decode mode and check compability with decode instructions
if (!set_klass_decode_mode()) {
// Give fatal error if this is a specified address
if ((address)CompressedClassSpaceBaseAddress == _base) {
vm_exit_during_initialization(
err_msg("CompressedClassSpaceBaseAddress=" PTR_FORMAT " given with shift %d, cannot be used to encode class pointers",
CompressedClassSpaceBaseAddress, _shift));
} else {
// If this fails, it's a bug in the allocation code.
fatal("CompressedClassSpaceBaseAddress=" PTR_FORMAT " given with shift %d, cannot be used to encode class pointers",
p2i(_base), _shift);
}
}
#ifdef ASSERT
sanity_check_after_initialization();
#endif

View File

@@ -258,6 +258,9 @@ public:
is_aligned(addr, klass_alignment_in_bytes());
}
// Check that with the given base, shift and range, aarch64 an encode and decode the klass pointer.
static bool check_klass_decode_mode(address base, int shift, const size_t range) NOT_AARCH64({ return true;});
static bool set_klass_decode_mode() NOT_AARCH64({ return true;}); // can be called after initialization
};
#endif // SHARE_OOPS_COMPRESSEDKLASS_HPP

View File

@@ -32,6 +32,8 @@ import java.lang.classfile.attribute.ModuleAttribute;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.classfile.instruction.BranchInstruction;
import java.lang.classfile.instruction.DiscontinuedInstruction;
import java.lang.classfile.instruction.ExceptionCatch;
import java.lang.constant.ClassDesc;
import java.lang.reflect.AccessFlag;
@@ -230,17 +232,35 @@ public sealed interface ClassFile
/**
* Option describing whether to automatically rewrite short jumps to
* long when necessary.
* Default is {@code FIX_SHORT_JUMPS} to automatically rewrite jump
* Default is {@link #FIX_SHORT_JUMPS} to automatically rewrite jump
* instructions.
* <p>
* Due to physical restrictions, some types of instructions cannot encode
* certain jump targets with bci offsets less than -32768 or greater than
* 32767, as they use a {@code s2} to encode such an offset. (The maximum
* length of the {@code code} array is 65535.) These types of instructions
* are called "short jumps".
*
* @see BranchInstruction
* @see DiscontinuedInstruction.JsrInstruction
* @since 24
*/
enum ShortJumpsOption implements Option {
/** Automatically convert short jumps to long when necessary */
/**
* Automatically convert short jumps to long when necessary.
* <p>
* For an invalid instruction model, a {@link CodeBuilder} may generate
* another or a few other instructions to accomplish the same effect.
*/
FIX_SHORT_JUMPS,
/** Fail if short jump overflows */
/**
* Fail with an {@link IllegalArgumentException} if short jump overflows.
* <p>
* This is useful to ensure the physical accuracy of a generated {@code
* class} file.
*/
FAIL_ON_SHORT_JUMPS
}

View File

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

View File

@@ -25,13 +25,20 @@
package java.lang.classfile;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.instruction.*;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models an executable instruction in a method body.
* Models an executable instruction in the {@code code} array of the {@link
* CodeAttribute Code} attribute of a method.
* <p>
* The {@link #opcode() opcode} identifies the operation of an instruction.
* Each {@linkplain Opcode#kind() kind} of opcode has its own modeling interface
* for instructions.
*
* @sealedGraph
* @since 24
*/
public sealed interface Instruction extends CodeElement
@@ -46,12 +53,14 @@ public sealed interface Instruction extends CodeElement
ThrowInstruction, TypeCheckInstruction, AbstractInstruction {
/**
* {@return the opcode of this instruction}
* {@return the operation of this instruction}
*/
Opcode opcode();
/**
* {@return the size in bytes of this instruction}
* This value is equal to {@link Opcode#sizeIfFixed()
* opcode().sizeIfFixed()} if it is not {@code -1}.
*/
int sizeInBytes();
}

View File

@@ -24,21 +24,60 @@
*/
package java.lang.classfile;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.instruction.LabelTarget;
import java.util.ListIterator;
import jdk.internal.classfile.impl.LabelImpl;
/**
* A marker for a position within the instructions of a method body. The
* association between a label's identity and the position it represents is
* managed by the entity managing the method body (a {@link CodeModel} or {@link
* CodeBuilder}), not the label itself; this allows the same label to have a
* meaning both in an existing method (as managed by a {@linkplain CodeModel})
* and in the transformation of that method (as managed by a {@linkplain
* CodeBuilder}), while corresponding to different positions in each. When
* traversing the elements of a {@linkplain CodeModel}, {@linkplain Label}
* markers will be delivered at the position to which they correspond. A label
* can be bound to the current position within a {@linkplain CodeBuilder} via
* {@link CodeBuilder#labelBinding(Label)} or {@link CodeBuilder#with(ClassFileElement)}.
* position is a cursor position in the list of instructions, similar to that
* of a {@link ListIterator}.
*
* <h2 id="reading">Reading Labels</h2>
* Labels read from {@code class} files represent positions in the {@code code}
* array of a {@link CodeAttribute Code} attribute. It is associated with a
* <dfn>{@index bci}</dfn> (bytecode index), also known as <dfn>{@index pc}</dfn>
* (program counter), the index into the {@code code} array; the actual cursor
* position is immediately before the given index, so a label at the beginning
* of the instructions has bci {@code 0}, and a label at the end of the
* instructions has bci {@link CodeAttribute#codeLength codeLength() + 1}. The
* bci can be inspected through {@link CodeAttribute#labelToBci
* CodeAttribute::labelToBci}.
* <p>
* In generic {@link CodeModel}s, a label may not have a bci value; the position
* of a label can be found by searching for the corresponding {@link LabelTarget}
* within that model.
*
* <h2 id="writing">Writing Labels</h2>
* Many models in {@link java.lang.classfile} refer to labels. To write a
* label, a label must be obtained, it must be bound to a {@link CodeBuilder}.
* <p>
* To obtain a label:
* <ul>
* <li>Use a label read from other models.
* <li>Use pre-defined labels from a {@link CodeBuilder}, such as {@link
* CodeBuilder#startLabel() CodeBuilder::startLabel}, {@link CodeBuilder#endLabel
* CodeBuilder::endLabel}, or {@link CodeBuilder.BlockCodeBuilder#breakLabel
* BlockCodeBuilder::breakLabel}. They are already bound.
* <li>Create labels with {@link CodeBuilder#newLabel CodeBuilder::newLabel} or
* {@link CodeBuilder#newBoundLabel CodeBuilder::newBoundLabel}.
* </ul>
* <p>
* A label must be bound exactly once in the {@code CodeBuilder} where it is
* used; otherwise, writing fails. To bind an unbound label:
* <ul>
* <li>Send a read {@link LabelTarget} to a {@code CodeBuilder}.
* <li>Use {@link CodeBuilder#labelBinding CodeBuilder::labelBinding}.
* </ul>
* Note that a label read from another model is not automatically bound in a
* {@code CodeBuilder}; they are separate entities and the label is bound to
* different positions in them.
*
* @see CodeAttribute#labelToBci CodeAttribute::labelToBci
* @see CodeBuilder#newLabel CodeBuilder::newLabel
* @see CodeBuilder#labelBinding CodeBuilder::labelBinding
* @since 24
*/
public sealed interface Label

File diff suppressed because it is too large Load Diff

View File

@@ -26,6 +26,9 @@
package java.lang.classfile;
import java.lang.classfile.instruction.DiscontinuedInstruction;
import java.lang.classfile.instruction.LoadInstruction;
import java.lang.classfile.instruction.NewPrimitiveArrayInstruction;
import java.lang.classfile.instruction.StoreInstruction;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
import java.lang.invoke.TypeDescriptor;
@@ -33,13 +36,17 @@ import java.lang.invoke.TypeDescriptor;
import jdk.internal.vm.annotation.Stable;
/**
* Describes the data types Java Virtual Machine operates on.
* This omits {@code returnAddress} (JVMS {@jvms 2.3.3}),
* which is only used by discontinued {@link
* DiscontinuedInstruction.JsrInstruction jsr} and {@link
* DiscontinuedInstruction.RetInstruction ret} instructions,
* and includes {@link #VOID void} (JVMS {@jvms 4.3.3}), which
* appears as a method return type.
* Describes the data types Java Virtual Machine operates on. This omits {@code
* returnAddress} (JVMS {@jvms 2.3.3}) and includes {@link #VOID void} (JVMS
* {@jvms 4.3.3}), which appears as a method return type.
* <p>
* The <code>{@index returnAddress}</code> type is only used by discontinued
* {@linkplain DiscontinuedInstruction.JsrInstruction jump subroutine} and
* {@linkplain DiscontinuedInstruction.RetInstruction return from subroutine}
* instructions. Jump subroutine instructions push {@code returnAddress} to the
* operand stack; {@link StoreInstruction astore} instructions store {@code
* returnAddress} from the operand stack to local variables; return from
* subroutine instructions load {@code returnAddress} from local variables.
*
* <h2 id="computational-type">Computational Type</h2>
* In the {@code class} file format, local variables (JVMS {@jvms 2.6.1}),
@@ -164,7 +171,10 @@ public enum TypeKind {
/**
* {@return the code used by the {@link Opcode#NEWARRAY newarray} instruction to create an array
* of this component type, or {@code -1} if this type is not supported by {@code newarray}}
* @jvms 6.5.newarray <i>newarray</i>
*
* @jvms 6.5.newarray <em>newarray</em>
* @see NewPrimitiveArrayInstruction
* @see #fromNewarrayCode(int) fromNewarrayCode(int)
*/
public int newarrayCode() {
return newarrayCode;
@@ -175,6 +185,7 @@ public enum TypeKind {
* This is also the category of this type for instructions operating on the operand stack without
* regard to type (JVMS {@jvms 2.11.1}), such as {@link Opcode#POP pop} versus {@link Opcode#POP2
* pop2}.
*
* @jvms 2.6.1 Local Variables
* @jvms 2.6.2 Operand Stacks
*/
@@ -185,6 +196,9 @@ public enum TypeKind {
/**
* {@return the {@linkplain ##computational-type computational type} for this type, or {@link #VOID void}
* for {@code void}}
*
* @see LoadInstruction
* @see StoreInstruction
*/
public TypeKind asLoadable() {
return ordinal() < 4 ? INT : this;
@@ -193,9 +207,12 @@ public enum TypeKind {
/**
* {@return the component type described by the array code used as an operand to {@link Opcode#NEWARRAY
* newarray}}
*
* @param newarrayCode the operand of the {@code newarray} instruction
* @throws IllegalArgumentException if the code is invalid
* @jvms 6.5.newarray <i>newarray</i>
* @jvms 6.5.newarray <em>newarray</em>
* @see NewPrimitiveArrayInstruction
* @see #newarrayCode() newarrayCode()
*/
public static TypeKind fromNewarrayCode(int newarrayCode) {
return switch (newarrayCode) {

View File

@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -35,18 +36,29 @@ import jdk.internal.classfile.impl.Util;
/**
* Models an array load instruction in the {@code code} array of a {@code Code}
* attribute. Corresponding opcodes will have a {@code kind} of {@link
* Opcode.Kind#ARRAY_LOAD}. Delivered as a {@link CodeElement} when
* attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind}
* of {@link Opcode.Kind#ARRAY_LOAD}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
* <p>
* An array load instruction is composite:
* {@snippet lang=text :
* // @link substring="ArrayLoadInstruction" target="CodeBuilder#arrayLoad(TypeKind)" :
* ArrayLoadInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind"
* }
* where {@code typeKind} is not {@link TypeKind#VOID void}, and {@link
* TypeKind#BOOLEAN boolean} is converted to {@link TypeKind#BYTE byte}.
*
* @see Opcode.Kind#ARRAY_LOAD
* @see CodeBuilder#arrayLoad CodeBuilder::arrayLoad
* @since 24
*/
public sealed interface ArrayLoadInstruction extends Instruction
permits AbstractInstruction.UnboundArrayLoadInstruction {
/**
* {@return the component type of the array} The {@link TypeKind#BYTE byte}
* {@return the component type of the array} The {@link TypeKind#BYTE byte}
* type load instruction {@link Opcode#BALOAD baload} also operates on
* {@link TypeKind#BOOLEAN boolean} arrays.
* {@link TypeKind#BOOLEAN boolean} arrays, so this never returns
* {@code boolean}.
*/
TypeKind typeKind();
@@ -56,7 +68,7 @@ public sealed interface ArrayLoadInstruction extends Instruction
* @param op the opcode for the specific type of array load instruction,
* which must be of kind {@link Opcode.Kind#ARRAY_LOAD}
* @throws IllegalArgumentException if the opcode kind is not
* {@link Opcode.Kind#ARRAY_LOAD}.
* {@link Opcode.Kind#ARRAY_LOAD}
*/
static ArrayLoadInstruction of(Opcode op) {
Util.checkKind(op, Opcode.Kind.ARRAY_LOAD);

View File

@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -35,18 +36,29 @@ import jdk.internal.classfile.impl.Util;
/**
* Models an array store instruction in the {@code code} array of a {@code Code}
* attribute. Corresponding opcodes will have a {@code kind} of {@link
* Opcode.Kind#ARRAY_STORE}. Delivered as a {@link CodeElement} when
* attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind}
* of {@link Opcode.Kind#ARRAY_STORE}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
* <p>
* An array store instruction is composite:
* {@snippet lang=text :
* // @link substring="ArrayStoreInstruction" target="CodeBuilder#arrayStore(TypeKind)" :
* ArrayStoreInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind"
* }
* where {@code typeKind} is not {@link TypeKind#VOID void}, and {@link
* TypeKind#BOOLEAN boolean} is converted to {@link TypeKind#BYTE byte}.
*
* @see Opcode.Kind#ARRAY_STORE
* @see CodeBuilder#arrayStore CodeBuilder::arrayStore
* @since 24
*/
public sealed interface ArrayStoreInstruction extends Instruction
permits AbstractInstruction.UnboundArrayStoreInstruction {
/**
* {@return the component type of the array} The {@link TypeKind#BYTE byte}
* {@return the component type of the array} The {@link TypeKind#BYTE byte}
* type store instruction {@link Opcode#BASTORE bastore} also operates on
* {@link TypeKind#BOOLEAN boolean} arrays.
* {@link TypeKind#BOOLEAN boolean} arrays, so this never returns
* {@code boolean}.
*/
TypeKind typeKind();
@@ -56,7 +68,7 @@ public sealed interface ArrayStoreInstruction extends Instruction
* @param op the opcode for the specific type of array store instruction,
* which must be of kind {@link Opcode.Kind#ARRAY_STORE}
* @throws IllegalArgumentException if the opcode kind is not
* {@link Opcode.Kind#ARRAY_STORE}.
* {@link Opcode.Kind#ARRAY_STORE}
*/
static ArrayStoreInstruction of(Opcode op) {
Util.checkKind(op, Opcode.Kind.ARRAY_STORE);

View File

@@ -24,28 +24,41 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Label;
import java.lang.classfile.Opcode;
import java.lang.classfile.*;
import jdk.internal.classfile.impl.AbstractInstruction;
import jdk.internal.classfile.impl.Util;
/**
* Models a branching instruction (conditional or unconditional) in the {@code
* code} array of a {@code Code} attribute. Corresponding opcodes will have a
* {@code kind} of {@link Opcode.Kind#BRANCH}. Delivered as a {@link
* CodeElement} when traversing the elements of a {@link CodeModel}.
* code} array of a {@code Code} attribute. Corresponding opcodes have a
* {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#BRANCH}. Delivered as
* a {@link CodeElement} when traversing the elements of a {@link CodeModel}.
* <p>
* A branch instruction is composite:
* {@snippet lang=text :
* // @link substring="BranchInstruction" target="#of":
* BranchInstruction(
* Opcode opcode, // @link substring="opcode" target="#opcode()"
* Label target // @link substring="target" target="#target()"
* )
* }
* <p>
* Due to physical restrictions, some types of instructions cannot encode labels
* too far away in the list of code elements. In such cases, the {@link
* ClassFile.ShortJumpsOption} controls how an invalid branch instruction model
* is written by a {@link CodeBuilder}.
*
* @see Opcode.Kind#BRANCH
* @see CodeBuilder#branch CodeBuilder::branch
* @see ClassFile.ShortJumpsOption
* @since 24
*/
public sealed interface BranchInstruction extends Instruction
permits AbstractInstruction.BoundBranchInstruction,
AbstractInstruction.UnboundBranchInstruction {
/**
* {@return the target of the branch}
* {@return the branch target of this instruction}
*/
Label target();
@@ -56,7 +69,7 @@ public sealed interface BranchInstruction extends Instruction
* which must be of kind {@link Opcode.Kind#BRANCH}
* @param target the target of the branch
* @throws IllegalArgumentException if the opcode kind is not
* {@link Opcode.Kind#BRANCH}.
* {@link Opcode.Kind#BRANCH}
*/
static BranchInstruction of(Opcode op, Label target) {
Util.checkKind(op, Opcode.Kind.BRANCH);

View File

@@ -25,6 +25,7 @@
package java.lang.classfile.instruction;
import java.lang.classfile.ClassFile;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Label;
@@ -36,11 +37,31 @@ import jdk.internal.classfile.impl.AbstractPseudoInstruction;
import jdk.internal.classfile.impl.BoundCharacterRange;
/**
* A pseudo-instruction which models a single entry in the
* {@link CharacterRangeTableAttribute}. Delivered as a {@link CodeElement}
* during traversal of the elements of a {@link CodeModel}, according to
* the setting of the {@link ClassFile.DebugElementsOption} option.
* A pseudo-instruction which models a single entry in the {@link
* CharacterRangeTableAttribute CharacterRangeTable} attribute. Delivered as a
* {@link CodeElement} during traversal of the elements of a {@link CodeModel},
* according to the setting of the {@link ClassFile.DebugElementsOption} option.
* <p>
* A character range entry is composite:
* {@snippet lang=text :
* // @link substring="CharacterRange" target="#of":
* CharacterRange(
* Label startScope, // @link substring="startScope" target="#startScope"
* Label endScope, // @link substring="endScope" target="#endScope"
* int characterRangeStart, // @link substring="characterRangeStart" target="#characterRangeStart"
* int characterRangeEnd, // @link substring="characterRangeEnd" target="#characterRangeEnd"
* int flags // @link substring="flags" target="#flags"
* )
* }
* <p>
* Another model, {@link CharacterRangeInfo}, also models a character range
* entry; it has no dependency on a {@code CodeModel} and represents of bci
* values as {@code int}s instead of {@code Label}s, and is used as components
* of a {@link CharacterRangeTableAttribute}.
*
* @see CharacterRangeInfo
* @see CodeBuilder#characterRange CodeBuilder::characterRange
* @see ClassFile.DebugElementsOption
* @since 24
*/
public sealed interface CharacterRange extends PseudoInstruction
@@ -114,7 +135,7 @@ public sealed interface CharacterRange extends PseudoInstruction
* <li>{@link #FLAG_BRANCH_FALSE}
* </ul>
*
* @see java.lang.classfile.attribute.CharacterRangeInfo#flags()
* @see CharacterRangeInfo#flags()
*
* @return the flags
*/

View File

@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -38,12 +39,22 @@ import jdk.internal.classfile.impl.Util;
/**
* Models a constant-load instruction in the {@code code} array of a {@code
* Code} attribute, including "intrinsic constant" instructions (e.g., {@code
* iconst_0}), "argument constant" instructions (e.g., {@code bipush}), and "load
* constant" instructions (e.g., {@code LDC}). Corresponding opcodes will have
* a {@code kind} of {@link Opcode.Kind#CONSTANT}. Delivered as a {@link
* CodeElement} when traversing the elements of a {@link CodeModel}.
* Code} attribute, including {@linkplain IntrinsicConstantInstruction
* "intrinsic"}, {@linkplain ArgumentConstantInstruction "argument"}, and
* {@linkplain LoadConstantInstruction "load"} constant instructions.
* Corresponding opcodes have a {@linkplain Opcode#kind() kind} of {@link
* Opcode.Kind#CONSTANT}. Delivered as a {@link CodeElement} when traversing
* the elements of a {@link CodeModel}.
* <p>
* The loaded constant value is symbolically represented as a {@link ConstantDesc}:
* {@snippet lang=text :
* // @link substring="ConstantInstruction" target="CodeBuilder#loadConstant(ConstantDesc)" :
* ConstantInstruction(ConstantDesc constantValue) // @link substring="constantValue" target="#constantValue()"
* }
*
* @see Opcode.Kind#CONSTANT
* @see CodeBuilder#loadConstant(ConstantDesc) CodeBuilder::loadConstant
* @sealedGraph
* @since 24
*/
public sealed interface ConstantInstruction extends Instruction {
@@ -54,22 +65,36 @@ public sealed interface ConstantInstruction extends Instruction {
ConstantDesc constantValue();
/**
* {@return the type of the constant}
* {@return the {@linkplain TypeKind##computational-type computational type} of the constant}
* This is derived from the {@link #constantValue() constantValue}.
*/
TypeKind typeKind();
/**
* Models an "intrinsic constant" instruction (e.g., {@code
* iconst_0}).
* Models an "intrinsic constant" instruction, which encodes
* the constant value in its opcode. Examples include {@link
* Opcode#ACONST_NULL aconst_null} and {@link
* Opcode#ICONST_0 iconst_0}.
* <p>
* An intrinsic constant instruction is composite:
* {@snippet lang=text :
* // @link substring="IntrinsicConstantInstruction" target="#ofIntrinsic" :
* IntrinsicConstantInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()"
* }
* where:
* <dl>
* <dt>{@link #opcode() opcode}</dt>
* <dd>Must be of the constant kind and have a {@linkplain
* Opcode#sizeIfFixed() fixed size} of 1.</dd>
* </dl>
*
* @see Opcode.Kind#CONSTANT
* @see ConstantInstruction#ofIntrinsic ConstantInstruction::ofIntrinsic
* @since 24
*/
sealed interface IntrinsicConstantInstruction extends ConstantInstruction
permits AbstractInstruction.UnboundIntrinsicConstantInstruction {
/**
* {@return the type of the constant}
*/
@Override
default TypeKind typeKind() {
return BytecodeHelpers.intrinsicConstantType(opcode());
@@ -77,9 +102,31 @@ public sealed interface ConstantInstruction extends Instruction {
}
/**
* Models an "argument constant" instruction (e.g., {@code
* bipush}).
* Models an "argument constant" instruction, which encodes the
* constant value in the instruction directly. Includes {@link
* Opcode#BIPUSH bipush} and {@link Opcode#SIPUSH sipush} instructions.
* <p>
* An argument constant instruction is composite:
* {@snippet lang=text :
* // @link substring="ArgumentConstantInstruction" target="#ofArgument" :
* ArgumentConstantInstruction(
* Opcode opcode, // @link substring="opcode" target="#opcode()"
* int constantValue // @link substring="constantValue" target="#constantValue()"
* )
* }
* where:
* <ul>
* <li>{@code opcode} must be one of {@code bipush} or {@code sipush}.
* <li>{@code constantValue} must be in the range of {@code byte}, {@code
* [-128, 127]}, for {@code bipush}, and in the range of {@code short},
* {@code [-32768, 32767]}, for {@code sipush}.
* </ul>
*
* @see Opcode.Kind#CONSTANT
* @see ConstantInstruction#ofArgument ConstantInstruction::ofArgument
* @see CodeBuilder#loadConstant(int) CodeBuilder::loadConstant(int)
* @see CodeBuilder#bipush CodeBuilder::bipush
* @see CodeBuilder#sipush CodeBuilder::sipush
* @since 24
*/
sealed interface ArgumentConstantInstruction extends ConstantInstruction
@@ -89,9 +136,6 @@ public sealed interface ConstantInstruction extends Instruction {
@Override
Integer constantValue();
/**
* {@return the type of the constant}
*/
@Override
default TypeKind typeKind() {
return TypeKind.INT;
@@ -99,9 +143,24 @@ public sealed interface ConstantInstruction extends Instruction {
}
/**
* Models a "load constant" instruction (e.g., {@code
* ldc}).
* Models a "load constant" instruction, which encodes the constant value
* in the constant pool. Includes {@link Opcode#LDC ldc} and {@link
* Opcode#LDC_W ldc_w}, and {@link Opcode#LDC2_W ldc2_w} instructions.
* <p>
* A load constant instruction is composite:
* {@snippet lang=text :
* // @link substring="LoadConstantInstruction" target="CodeBuilder#ldc(LoadableConstantEntry)" :
* LoadConstantInstruction(LoadableConstantEntry constantEntry) // @link substring="constantEntry" target="#constantEntry()"
* }
* <p>
* A "load constant" instruction can load any constant value supported by
* other constant-load instructions. However, other instructions are
* usually more optimized, avoiding extra constant pool entries and being
* smaller.
*
* @see Opcode.Kind#CONSTANT
* @see ConstantInstruction#ofLoad ConstantInstruction::ofLoad
* @see CodeBuilder#ldc CodeBuilder::ldc
* @since 24
*/
sealed interface LoadConstantInstruction extends ConstantInstruction
@@ -113,9 +172,6 @@ public sealed interface ConstantInstruction extends Instruction {
*/
LoadableConstantEntry constantEntry();
/**
* {@return the type of the constant}
*/
@Override
default TypeKind typeKind() {
return constantEntry().typeKind();
@@ -139,6 +195,10 @@ public sealed interface ConstantInstruction extends Instruction {
/**
* {@return an argument constant instruction}
* <p>
* {@code value} must be in the range of {@code byte}, {@code [-128, 127]},
* for {@link Opcode#BIPUSH}, and in the range of {@code short}, {@code
* [-32768, 32767]}, for {@link Opcode#SIPUSH}.
*
* @param op the opcode for the specific type of argument constant instruction,
* which must be {@link Opcode#BIPUSH} or {@link Opcode#SIPUSH}

View File

@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -36,10 +37,27 @@ import jdk.internal.classfile.impl.Util;
/**
* Models a primitive conversion instruction in the {@code code} array of a
* {@code Code} attribute, such as {@code i2l}. Corresponding opcodes will have
* a {@code kind} of {@link Opcode.Kind#CONVERT}. Delivered as a {@link
* CodeElement} when traversing the elements of a {@link CodeModel}.
* {@code Code} attribute, such as {@link Opcode#I2L i2l}. Corresponding opcodes
* have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#CONVERT}.
* Delivered as a {@link CodeElement} when traversing the elements of a {@link CodeModel}.
* <p>
* A primitive conversion instruction is composite:
* {@snippet lang=text :
* // @link substring="ConvertInstruction" target="#of(TypeKind, TypeKind)" :
* ConvertInstruction(
* TypeKind fromType, // @link substring="fromType" target="#fromType"
* TypeKind toType // @link substring="toType" target="#toType"
* )
* }
* where these conversions are valid:
* <ul>
* <li>Between {@code int}, {@code long}, {@code float}, and {@code double}, where
* {@code fromType != toType};
* <li>From {@code int} to {@code byte}, {@code char}, and {@code short}.
* </ul>
*
* @see Opcode.Kind#CONVERT
* @see CodeBuilder#conversion CodeBuilder::conversion
* @since 24
*/
public sealed interface ConvertInstruction extends Instruction
@@ -55,10 +73,16 @@ public sealed interface ConvertInstruction extends Instruction
TypeKind toType();
/**
* {@return A conversion instruction}
* {@return a conversion instruction} Valid conversions are:
* <ul>
* <li>Between {@code int}, {@code long}, {@code float}, and {@code double},
* where {@code fromType != toType};
* <li>From {@code int} to {@code byte}, {@code char}, and {@code short}.
* </ul>
*
* @param fromType the type to convert from
* @param toType the type to convert to
* @throws IllegalArgumentException if this is not a valid conversion
*/
static ConvertInstruction of(TypeKind fromType, TypeKind toType) {
return of(BytecodeHelpers.convertOpcode(fromType, toType));

View File

@@ -24,32 +24,54 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Label;
import java.lang.classfile.Opcode;
import java.lang.classfile.*;
import jdk.internal.classfile.impl.AbstractInstruction;
import jdk.internal.classfile.impl.BytecodeHelpers;
import jdk.internal.classfile.impl.Util;
/**
* Models instruction discontinued from the {@code code} array of a {@code Code}
* attribute. Delivered as a {@link CodeElement} when traversing the elements of
* a {@link CodeModel}.
* Marker interface for instruction discontinued from the {@code code} array of
* a {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
* the elements of a {@link CodeModel}.
*
* @apiNote
* While most instructions have convenience factory methods in {@link
* CodeBuilder}, discontinued instructions can only be supplied to code builders
* explicitly with {@link CodeBuilder#with CodeBuilder::with} to discourage
* their use.
*
* @jvms 4.9.1 Static Constraints
* @sealedGraph
* @since 24
*/
public sealed interface DiscontinuedInstruction extends Instruction {
/**
* Models JSR and JSR_W instructions discontinued from the {@code code}
* array of a {@code Code} attribute since class file version 51.0.
* Corresponding opcodes will have a {@code kind} of
* {@link Opcode.Kind#DISCONTINUED_JSR}. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
* Models jump subroutine instructions discontinued from the {@code code}
* array of a {@code Code} attribute since class file major version {@value
* ClassFile#JAVA_7_VERSION} (JVMS {@jvms 4.9.1}). Corresponding opcodes
* have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#DISCONTINUED_JSR}.
* Delivered as a {@link CodeElement} when traversing the elements of a
* {@link CodeModel}.
* <p>
* A jump subroutine instruction is composite:
* {@snippet lang=text :
* // @link substring="JsrInstruction" target="#of(Label)" :
* JsrInstruction(Label target) // @link substring="target" target="#target()"
* }
* <p>
* Due to physical restrictions, {@link Opcode#JSR jsr} instructions cannot
* encode labels too far away in the list of code elements. In such cases,
* the {@link ClassFile.ShortJumpsOption} controls how an invalid {@code jsr}
* instruction model is written by a {@link CodeBuilder}.
* <p>
* Jump subroutine instructions push a {@link TypeKind##returnAddress
* returnAddress} value to the operand stack, and {@link StoreInstruction
* astore} series of instructions can then store this value to a local
* variable slot.
*
* @see Opcode.Kind#DISCONTINUED_JSR
* @since 24
*/
sealed interface JsrInstruction extends DiscontinuedInstruction
@@ -57,14 +79,18 @@ public sealed interface DiscontinuedInstruction extends Instruction {
AbstractInstruction.UnboundJsrInstruction {
/**
* {@return the target of the JSR instruction}
* {@return the target of the jump subroutine instruction}
*/
Label target();
/**
* {@return a JSR instruction}
* {@return a jump subroutine instruction}
*
* @param op the opcode for the specific type of JSR instruction,
* @apiNote
* The explicit {@code op} argument allows creating {@link Opcode#JSR_W
* jsr_w} instructions to avoid short jumps.
*
* @param op the opcode for the specific type of jump subroutine instruction,
* which must be of kind {@link Opcode.Kind#DISCONTINUED_JSR}
* @param target target label of the subroutine
* @throws IllegalArgumentException if the opcode kind is not
@@ -76,7 +102,7 @@ public sealed interface DiscontinuedInstruction extends Instruction {
}
/**
* {@return a JSR instruction}
* {@return a jump subroutine instruction}
*
* @param target target label of the subroutine
*/
@@ -86,12 +112,26 @@ public sealed interface DiscontinuedInstruction extends Instruction {
}
/**
* Models RET and RET_W instructions discontinued from the {@code code}
* array of a {@code Code} attribute since class file version 51.0.
* Corresponding opcodes will have a {@code kind} of
* Models return from subroutine instructions discontinued from the {@code
* code} array of a {@code Code} attribute since class file major version
* {@value ClassFile#JAVA_7_VERSION} (JVMS {@jvms 4.9.1}).
* Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
* {@link Opcode.Kind#DISCONTINUED_RET}. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
* <p>
* A return from subroutine instruction is composite:
* {@snippet lang=text :
* // @link substring="RetInstruction" target="#of(int)" :
* RetInstruction(int slot) // @link substring="slot" target="#slot()"
* }
* where {@code slot} must be within {@code [0, 65535]}.
* <p>
* {@link StoreInstruction astore} series of instructions store a {@link
* TypeKind##returnAddress returnAddress} value to a local variable slot,
* making the slot usable by a return from subroutine instruction.
*
* @jvms 6.5.ret <em>ret</em>
* @see Opcode.Kind#DISCONTINUED_RET
* @since 24
*/
sealed interface RetInstruction extends DiscontinuedInstruction
@@ -100,13 +140,23 @@ public sealed interface DiscontinuedInstruction extends Instruction {
/**
* {@return the local variable slot with return address}
* The value is within {@code [0, 65535]}.
*/
int slot();
/**
* {@return a RET or RET_W instruction}
* {@return a return from subroutine instruction}
* <p>
* {@code slot} must be in the closed range of {@code [0, 255]} for
* {@link Opcode#RET ret}, or within {@code [0, 65535]} for {@link
* Opcode#RET_W wide ret}.
*
* @param op the opcode for the specific type of RET instruction,
* @apiNote
* The explicit {@code op} argument allows creating {@code wide ret}
* instructions with {@code slot} in the range of regular {@code ret}
* instructions.
*
* @param op the opcode for the specific type of return from subroutine instruction,
* which must be of kind {@link Opcode.Kind#DISCONTINUED_RET}
* @param slot the local variable slot to load return address from
* @throws IllegalArgumentException if the opcode kind is not
@@ -118,7 +168,9 @@ public sealed interface DiscontinuedInstruction extends Instruction {
}
/**
* {@return a RET instruction}
* {@return a return from subroutine instruction}
* <p>
* {@code slot} must be within {@code [0, 65535]}.
*
* @param slot the local variable slot to load return address from
* @throws IllegalArgumentException if {@code slot} is out of range

View File

@@ -24,23 +24,37 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Label;
import java.lang.classfile.PseudoInstruction;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.constantpool.ClassEntry;
import java.util.Optional;
import jdk.internal.classfile.impl.AbstractPseudoInstruction;
/**
* A pseudo-instruction modeling an entry in the exception table of a code
* attribute. Entries in the exception table model catch and finally blocks.
* Delivered as a {@link CodeElement} when traversing the contents
* of a {@link CodeModel}.
*
* @see PseudoInstruction
* A pseudo-instruction modeling an entry in the {@code exception_table} array
* of a {@link CodeAttribute Code} attribute. Catch (JVMS {@jvms 3.12}) and
* finally (JVMS {@jvms 3.14}) blocks in Java source code compile to exception
* table entries. Delivered as a {@link CodeElement} when traversing the
* contents of a {@link CodeModel}.
* <p>
* An exception table entry is composite:
* {@snippet lang=text :
* // @link substring="ExceptionCatch" target="#of(Label, Label, Label, Optional)" :
* ExceptionCatch(
* Label handler, // @link substring="handler" target="#handler"
* Label tryStart, // @link substring="tryStart" target="#tryStart"
* Label tryEnd, // @link substring="tryEnd" target="#tryEnd"
* Optional<ClassEntry> catchType // @link substring="catchType" target="#catchType"
* )
* }
*
* @see CodeBuilder#exceptionCatch CodeBuilder::exceptionCatch
* @jvms 4.7.3 The {@code Code} Attribute
* @since 24
*/
public sealed interface ExceptionCatch extends PseudoInstruction
@@ -61,8 +75,8 @@ public sealed interface ExceptionCatch extends PseudoInstruction
Label tryEnd();
/**
* {@return the type of the exception to catch, or empty if this handler is
* unconditional}
* {@return the type of the exception to catch, or empty if this handler
* catches everything}
*/
Optional<ClassEntry> catchType();
@@ -80,10 +94,10 @@ public sealed interface ExceptionCatch extends PseudoInstruction
}
/**
* {@return an exception table pseudo-instruction for an unconditional handler}
* {@return an exception table pseudo-instruction to catch everything}
* @param handler the handler for the exception
* @param tryStart the beginning of the instruction range for the gaurded instructions
* @param tryEnd the end of the instruction range for the gaurded instructions
* @param tryStart the beginning of the instruction range for the guarded instructions
* @param tryEnd the end of the instruction range for the guarded instructions
*/
static ExceptionCatch of(Label handler, Label tryStart, Label tryEnd) {
return new AbstractPseudoInstruction.ExceptionCatchImpl(handler, tryStart, tryEnd, (ClassEntry) null);

View File

@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -40,10 +41,21 @@ import jdk.internal.classfile.impl.Util;
/**
* Models a field access instruction in the {@code code} array of a {@code Code}
* attribute. Corresponding opcodes will have a {@code kind} of {@link
* Opcode.Kind#FIELD_ACCESS}. Delivered as a {@link CodeElement} when
* attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind}
* of {@link Opcode.Kind#FIELD_ACCESS}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
* <p>
* A field access instruction is composite:
* {@snippet lang=text :
* // @link substring="FieldInstruction" target="#of(Opcode, FieldRefEntry)" :
* FieldInstruction(
* Opcode opcode, // @link substring="opcode" target="#opcode()"
* FieldRefEntry field, // @link substring="field" target="#field()"
* )
* }
*
* @see Opcode.Kind#FIELD_ACCESS
* @see CodeBuilder#fieldAccess CodeBuilder::fieldAccess
* @since 24
*/
public sealed interface FieldInstruction extends Instruction
@@ -68,7 +80,11 @@ public sealed interface FieldInstruction extends Instruction
}
/**
* {@return the field descriptor of the field}
* {@return the field descriptor string of the field}
*
* @apiNote
* A symbolic descriptor for the type of the field is available through
* {@link #typeSymbol() typeSymbol()}.
*/
default Utf8Entry type() {
return field().nameAndType().type();
@@ -103,6 +119,8 @@ public sealed interface FieldInstruction extends Instruction
* @param owner the class holding the field
* @param name the name of the field
* @param type the field descriptor
* @throws IllegalArgumentException if the opcode kind is not
* {@link Opcode.Kind#FIELD_ACCESS}.
*/
static FieldInstruction of(Opcode op,
ClassEntry owner,
@@ -118,6 +136,8 @@ public sealed interface FieldInstruction extends Instruction
* which must be of kind {@link Opcode.Kind#FIELD_ACCESS}
* @param owner the class holding the field
* @param nameAndType the name and field descriptor of the field
* @throws IllegalArgumentException if the opcode kind is not
* {@link Opcode.Kind#FIELD_ACCESS}.
*/
static FieldInstruction of(Opcode op,
ClassEntry owner,

View File

@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -33,10 +34,27 @@ import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models a local variable increment instruction in the {@code code} array of a
* {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
* {@link Opcode.Kind#INCREMENT}. Delivered as a {@link CodeElement} when
* {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind()
* kind} of {@link Opcode.Kind#INCREMENT}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
* <p>
* A local variable increment instruction is composite:
* {@snippet lang=text :
* // @link substring="IncrementInstruction" target="#of" :
* IncrementInstruction(
* int slot, // @link substring="slot" target="#slot()"
* int constant // @link substring="constant" target="#constant()"
* )
* }
* where
* <ul>
* <li>{@code slot} must be within {@code [0, 65535]}.
* <li>{@code constant} must be within {@code [-32768, 32767]}.
* </ul>
*
* @see Opcode.Kind#INCREMENT
* @see CodeBuilder#iinc CodeBuilder::iinc
* @jvms 6.5.iinc <em>iinc</em>
* @since 24
*/
public sealed interface IncrementInstruction extends Instruction
@@ -54,6 +72,10 @@ public sealed interface IncrementInstruction extends Instruction
/**
* {@return an increment instruction}
* <ul>
* <li>{@code slot} must be within {@code [0, 65535]}.
* <li>{@code constant} must be within {@code [-32768, 32767]}.
* </ul>
*
* @param slot the local variable slot to increment
* @param constant the value to increment by

View File

@@ -24,9 +24,11 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Opcode;
import java.lang.classfile.constantpool.InvokeDynamicEntry;
import java.lang.classfile.constantpool.LoadableConstantEntry;
import java.lang.classfile.constantpool.Utf8Entry;
@@ -40,10 +42,20 @@ import jdk.internal.classfile.impl.AbstractInstruction;
import jdk.internal.classfile.impl.Util;
/**
* Models an {@code invokedynamic} instruction in the {@code code} array of a
* {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
* the elements of a {@link CodeModel}.
* Models a dynamically-computed call site invocation instruction in the
* {@code code} array of a {@code Code} attribute. The corresponding opcode is
* {@link Opcode#INVOKEDYNAMIC invokedynamic}. Delivered as a {@link
* CodeElement} when traversing the elements of a {@link CodeModel}.
* <p>
* A dynamically-computed call site invocation instruction is composite:
* {@snippet lang=text :
* // @link substring="InvokeDynamicInstruction" target="#of" :
* InvokeDynamicInstruction(InvokeDynamicEntry invokedynamic) // @link substring="invokedynamic" target="#invokedynamic()"
* }
*
* @see Opcode.Kind#INVOKE_DYNAMIC
* @see CodeBuilder#invokedynamic CodeBuilder::invokedynamic
* @jvms 6.5.invokedynamic <em>invokedynamic</em>
* @since 24
*/
public sealed interface InvokeDynamicInstruction extends Instruction
@@ -62,6 +74,10 @@ public sealed interface InvokeDynamicInstruction extends Instruction
/**
* {@return the invocation type of the call site}
*
* @apiNote
* A symbolic descriptor for the invocation typeis available through {@link
* #typeSymbol() typeSymbol()}.
*/
default Utf8Entry type() {
return invokedynamic().type();

View File

@@ -24,10 +24,12 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Opcode;
import java.lang.classfile.TypeKind;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.constantpool.InterfaceMethodRefEntry;
import java.lang.classfile.constantpool.MemberRefEntry;
@@ -42,10 +44,26 @@ import jdk.internal.classfile.impl.Util;
/**
* Models a method invocation instruction in the {@code code} array of a {@code
* Code} attribute, other than {@code invokedynamic}. Corresponding opcodes
* will have a {@code kind} of {@link Opcode.Kind#INVOKE}. Delivered as a
* {@link CodeElement} when traversing the elements of a {@link CodeModel}.
* Code} attribute, other than {@link InvokeDynamicInstruction invokedynamic}.
* Corresponding opcodes have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#INVOKE}.
* Delivered as a {@link CodeElement} when traversing the elements of a {@link CodeModel}.
* <p>
* A method invocation instruction is composite:
* {@snippet lang=text :
* // @link substring="InvokeInstruction" target="#of(Opcode, MemberRefEntry)" :
* InvokeInstruction(
* Opcode opcode, // @link substring="opcode" target="#opcode()"
* MethodRefEntry | InterfaceMethodRefEntry method) // @link substring="method" target="#method()"
* )
* }
* where {@code method} must be an {@code InterfaceMethodRefEntry} for {@link
* Opcode#INVOKEINTERFACE invokeinterface} opcode, and must be a {@code
* MethodRefEntry} for {@link Opcode#INVOKEVIRTUAL invokevirtual} opcode.
* {@link Opcode#INVOKESTATIC invokestatic} and {@link Opcode#INVOKESPECIAL
* invokespecial} can have either type of entry for {@code method}.
*
* @see Opcode.Kind#INVOKE
* @see CodeBuilder#invoke CodeBuilder::invoke
* @since 24
*/
public sealed interface InvokeInstruction extends Instruction
@@ -57,18 +75,25 @@ public sealed interface InvokeInstruction extends Instruction
MemberRefEntry method();
/**
* {@return whether the class holding the method is an interface}
* {@return whether the class or interface holding the method is an interface}
*/
boolean isInterface();
/**
* {@return the {@code count} value of an {@code invokeinterface} instruction, as defined in JVMS {@jvms 6.5}
* or {@code 0} for {@code invokespecial}, {@code invokestatic} and {@code invokevirtual} instructions}
* {@return the {@code count} value of an {@code invokeinterface} instruction,
* or {@code 0} for other instructions}
* <p>
* For an {@code invokeinterface} instruction, this value must be equivalent
* to the sum of {@linkplain TypeKind#slotSize() slot sizes} of all arguments
* plus one, which is equal to the number of operand stack depth consumed by
* this interface method invocation instruction.
*
* @jvms 6.5.invokeinterface <em>invokeinterface</em>
*/
int count();
/**
* {@return the class holding the method}
* {@return the class or interface holding the method}
*/
default ClassEntry owner() {
return method().owner();
@@ -82,7 +107,11 @@ public sealed interface InvokeInstruction extends Instruction
}
/**
* {@return the method descriptor of the method}
* {@return the method descriptor string of the method}
*
* @apiNote
* A symbolic descriptor for the type of the method is available through
* {@link #typeSymbol() typeSymbol()}.
*/
default Utf8Entry type() {
return method().nameAndType().type();
@@ -95,7 +124,6 @@ public sealed interface InvokeInstruction extends Instruction
return Util.methodTypeSymbol(method().type());
}
/**
* {@return an invocation instruction}
*
@@ -103,7 +131,7 @@ public sealed interface InvokeInstruction extends Instruction
* which must be of kind {@link Opcode.Kind#INVOKE}
* @param method a constant pool entry describing the method
* @throws IllegalArgumentException if the opcode kind is not
* {@link Opcode.Kind#INVOKE}.
* {@link Opcode.Kind#INVOKE}
*/
static InvokeInstruction of(Opcode op, MemberRefEntry method) {
Util.checkKind(op, Opcode.Kind.INVOKE);
@@ -119,6 +147,8 @@ public sealed interface InvokeInstruction extends Instruction
* @param name the name of the method
* @param type the method descriptor
* @param isInterface whether the class holding the method is an interface
* @throws IllegalArgumentException if the opcode kind is not
* {@link Opcode.Kind#INVOKE}
*/
static InvokeInstruction of(Opcode op,
ClassEntry owner,
@@ -136,6 +166,8 @@ public sealed interface InvokeInstruction extends Instruction
* @param owner the class holding the method
* @param nameAndType the name and type of the method
* @param isInterface whether the class holding the method is an interface
* @throws IllegalArgumentException if the opcode kind is not
* {@link Opcode.Kind#INVOKE}
*/
static InvokeInstruction of(Opcode op,
ClassEntry owner,

View File

@@ -24,10 +24,13 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.CodeTransform;
import java.lang.classfile.Label;
import java.lang.classfile.PseudoInstruction;
import java.lang.classfile.attribute.CodeAttribute;
import jdk.internal.classfile.impl.LabelImpl;
@@ -35,9 +38,28 @@ import jdk.internal.classfile.impl.LabelImpl;
* A pseudo-instruction which indicates that the specified label corresponds to
* the current position in the {@code Code} attribute. Delivered as a {@link
* CodeElement} during traversal of the elements of a {@link CodeModel}.
* <p>
* This can be used to inspect the target position of labels across {@linkplain
* CodeTransform transformations}, as {@linkplain CodeAttribute#labelToBci bci}
* is not stable.
* <p>
* When passed to a {@link CodeBuilder}, this pseudo-instruction sets the
* specified label to be bound at the current position in the builder.
* <p>
* By design, {@code LabelTarget} cannot be created by users and can only be
* read from a code model. Use {@link CodeBuilder#labelBinding
* CodeBuilder::labelBinding} to bind arbitrary labels to a {@code CodeBuilder}.
* <p>
* For a {@code CodeBuilder cob}, a {@code LabelTarget lt}, these two calls are
* equivalent:
* {@snippet lang=java :
* cob.with(lt); // @link substring="with" target="CodeBuilder#with"
* // @link substring="labelBinding" target="CodeBuilder#labelBinding" :
* cob.labelBinding(lt.label()); // @link substring="label" target="#label"
* }
*
* @see PseudoInstruction
*
* @see Label
* @see CodeBuilder#labelBinding CodeBuilder::labelBinding
* @since 24
*/
public sealed interface LabelTarget extends PseudoInstruction

View File

@@ -25,21 +25,42 @@
package java.lang.classfile.instruction;
import java.lang.classfile.ClassFile;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.PseudoInstruction;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.attribute.LineNumberInfo;
import java.lang.classfile.attribute.LineNumberTableAttribute;
import jdk.internal.classfile.impl.LineNumberImpl;
/**
* A pseudo-instruction which models a single entry in the
* {@link LineNumberTableAttribute}. Delivered as a {@link CodeElement}
* during traversal of the elements of a {@link CodeModel}, according to
* the setting of the {@link ClassFile.LineNumbersOption} option.
* A pseudo-instruction which indicates the code for a given line number starts
* after the current position in a {@link CodeAttribute Code} attribute. This
* models a single entry in the {@link LineNumberTableAttribute LineNumberTable}
* attribute. Delivered as a {@link CodeElement} during traversal of the
* elements of a {@link CodeModel}, according to the setting of the {@link
* ClassFile.LineNumbersOption} option.
* <p>
* A line number entry is composite:
* {@snippet lang=text :
* // @link substring="LineNumber" target="#of" :
* LineNumber(int line) // @link substring="int line" target="#line"
* }
* <p>
* Another model, {@link LineNumberInfo}, also models a line number entry; it
* has no dependency on a {@code CodeModel} and represents of bci values as
* {@code int}s instead of order of pseudo-instructions in the elements of a
* {@code CodeModel}, and is used as components of a {@link LineNumberTableAttribute}.
*
* @see PseudoInstruction
* @apiNote
* Line numbers are represented with custom pseudo-instructions to avoid using
* labels, which usually indicate branching targets for the control flow.
*
* @see LineNumberInfo
* @see CodeBuilder#lineNumber CodeBuilder::lineNumber
* @see ClassFile.LineNumbersOption
* @since 24
*/
public sealed interface LineNumber extends PseudoInstruction

View File

@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -36,10 +37,23 @@ import jdk.internal.classfile.impl.Util;
/**
* Models a local variable load instruction in the {@code code} array of a
* {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
* {@link Opcode.Kind#LOAD}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
* {@code Code} attribute. Corresponding opcodes have a {@linkplain
* Opcode#kind() kind} of {@link Opcode.Kind#LOAD}. Delivered as a {@link
* CodeElement} when traversing the elements of a {@link CodeModel}.
* <p>
* A local variable load instruction is composite:
* {@snippet lang=text :
* // @link substring="LoadInstruction" target="#of(TypeKind, int)" :
* LoadInstruction(
* TypeKind typeKind, // @link substring="typeKind" target="#typeKind"
* int slot // @link substring="slot" target="#slot"
* )
* }
* where {@code TypeKind} is {@linkplain TypeKind##computational-type
* computational}, and {@code slot} is within {@code [0, 65535]}.
*
* @see Opcode.Kind#LOAD
* @see CodeBuilder#loadLocal CodeBuilder::loadLocal
* @since 24
*/
public sealed interface LoadInstruction extends Instruction
@@ -48,16 +62,21 @@ public sealed interface LoadInstruction extends Instruction
/**
* {@return the local variable slot to load from}
* The value is within {@code [0, 65535]}.
*/
int slot();
/**
* {@return the type of the value to be loaded}
* {@return the {@linkplain TypeKind##computational-type computational type}
* of the value to be loaded}
*/
TypeKind typeKind();
/**
* {@return a local variable load instruction}
* {@code kind} is {@linkplain TypeKind#asLoadable() converted} to its
* computational type.
* {@code slot} must be within {@code [0, 65535]}.
*
* @param kind the type of the value to be loaded
* @param slot the local variable slot to load from
@@ -71,6 +90,20 @@ public sealed interface LoadInstruction extends Instruction
/**
* {@return a local variable load instruction}
* <p>
* The range of {@code slot} is restricted by the {@code op} and its
* {@linkplain Opcode#sizeIfFixed() size}:
* <ul>
* <li>If {@code op} has size 1, {@code slot} must be exactly the slot value
* implied by the opcode.
* <li>If {@code op} has size 2, {@code slot} must be within {@code [0, 255]}.
* <li>If {@code op} has size 4, {@code slot} must be within {@code [0, 65535]}.
* </ul>
*
* @apiNote
* The explicit {@code op} argument allows creating {@code wide} or
* regular load instructions when the {@code slot} can be encoded
* with more optimized load instructions.
*
* @param op the opcode for the specific type of load instruction,
* which must be of kind {@link Opcode.Kind#LOAD}

View File

@@ -25,10 +25,12 @@
package java.lang.classfile.instruction;
import java.lang.classfile.ClassFile;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Label;
import java.lang.classfile.PseudoInstruction;
import java.lang.classfile.attribute.LocalVariableInfo;
import java.lang.classfile.attribute.LocalVariableTableAttribute;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.constant.ClassDesc;
@@ -39,19 +41,45 @@ import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.Util;
/**
* A pseudo-instruction which models a single entry in the
* {@link LocalVariableTableAttribute}. Delivered as a {@link CodeElement}
* during traversal of the elements of a {@link CodeModel}, according to
* the setting of the {@link ClassFile.DebugElementsOption} option.
* A pseudo-instruction which models a single entry in the {@link
* LocalVariableTableAttribute LocalVariableTable} attribute. Delivered as a
* {@link CodeElement} during traversal of the elements of a {@link CodeModel},
* according to the setting of the {@link ClassFile.DebugElementsOption} option.
* <p>
* A local variable entry is composite:
* {@snippet lang=text :
* // @link substring="LocalVariable" target="#of(int, String, ClassDesc, Label, Label)" :
* LocalVariable(
* int slot, // @link substring="slot" target="#slot"
* String name, // @link substring="name" target="#name"
* ClassDesc type, // @link substring="type" target="#type"
* Label startScope, // @link substring="startScope" target="#startScope"
* Label endScope // @link substring="endScope" target="#endScope"
* )
* }
* Where {@code slot} is within {@code [0, 65535]}.
* <p>
* Another model, {@link LocalVariableInfo}, also models a local variable
* entry; it has no dependency on a {@code CodeModel} and represents of bci
* values as {@code int}s instead of {@code Label}s, and is used as components
* of a {@link LocalVariableTableAttribute}.
*
* @see PseudoInstruction
* @apiNote
* {@code LocalVariable} is used for all local variables in Java source code.
* If a local variable has a parameterized type, a type argument, or an array
* type of one of the previous types, a {@link LocalVariableType} should be
* created for that local variable as well.
*
* @see LocalVariableInfo
* @see CodeBuilder#localVariable CodeBuilder::localVariable
* @see ClassFile.DebugElementsOption
* @since 24
*/
public sealed interface LocalVariable extends PseudoInstruction
permits AbstractPseudoInstruction.UnboundLocalVariable, BoundLocalVariable {
/**
* {@return the local variable slot}
* The value is within {@code [0, 65535]}.
*/
int slot();
@@ -61,7 +89,11 @@ public sealed interface LocalVariable extends PseudoInstruction
Utf8Entry name();
/**
* {@return the local variable field descriptor}
* {@return the local variable field descriptor string}
*
* @apiNote
* A symbolic descriptor for the type of the local variable is available
* through {@link #typeSymbol() typeSymbol()}.
*/
Utf8Entry type();
@@ -84,6 +116,7 @@ public sealed interface LocalVariable extends PseudoInstruction
/**
* {@return a local variable pseudo-instruction}
* {@code slot} must be within {@code [0, 65535]}.
*
* @param slot the local variable slot
* @param nameEntry the local variable name
@@ -99,6 +132,7 @@ public sealed interface LocalVariable extends PseudoInstruction
/**
* {@return a local variable pseudo-instruction}
* {@code slot} must be within {@code [0, 65535]}.
*
* @param slot the local variable slot
* @param name the local variable name

View File

@@ -24,12 +24,8 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.ClassFile;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Label;
import java.lang.classfile.PseudoInstruction;
import java.lang.classfile.Signature;
import java.lang.classfile.*;
import java.lang.classfile.attribute.LocalVariableTypeInfo;
import java.lang.classfile.attribute.LocalVariableTypeTableAttribute;
import java.lang.classfile.constantpool.Utf8Entry;
@@ -39,16 +35,44 @@ import jdk.internal.classfile.impl.TemporaryConstantPool;
/**
* A pseudo-instruction which models a single entry in the {@link
* LocalVariableTypeTableAttribute}. Delivered as a {@link CodeElement} during
* traversal of the elements of a {@link CodeModel}, according to the setting of
* the {@link ClassFile.DebugElementsOption} option.
* LocalVariableTypeTableAttribute LocalVariableTypeTable} attribute. Delivered
* as a {@link CodeElement} during traversal of the elements of a {@link CodeModel},
* according to the setting of the {@link ClassFile.DebugElementsOption} option.
* <p>
* A local variable type entry is composite:
* {@snippet lang=text :
* // @link substring="LocalVariableType" target="#of(int, String, Signature, Label, Label)" :
* LocalVariableType(
* int slot, // @link substring="slot" target="#slot"
* String name, // @link substring="name" target="#name"
* Signature signature, // @link substring="signature" target="#signatureSymbol"
* Label startScope, // @link substring="startScope" target="#startScope"
* Label endScope // @link substring="endScope" target="#endScope"
* )
* }
* Where {@code slot} is within {@code [0, 65535]}.
* <p>
* Another model, {@link LocalVariableTypeInfo}, also models a local variable
* type entry; it has no dependency on a {@code CodeModel} and represents of bci
* values as {@code int}s instead of {@code Label}s, and is used as components
* of a {@link LocalVariableTypeTableAttribute}.
*
* @apiNote
* {@code LocalVariableType} is used if a local variable has a parameterized
* type, a type argument, or an array type of one of the previous types as its
* type. A {@link LocalVariable} with the erased type should still be created
* for that local variable.
*
* @see LocalVariableTypeInfo
* @see CodeBuilder#localVariableType CodeBuilder::localVariableType
* @see ClassFile.DebugElementsOption
* @since 24
*/
public sealed interface LocalVariableType extends PseudoInstruction
permits AbstractPseudoInstruction.UnboundLocalVariableType, BoundLocalVariableType {
/**
* {@return the local variable slot}
* The value is within {@code [0, 65535]}.
*/
int slot();
@@ -58,12 +82,16 @@ public sealed interface LocalVariableType extends PseudoInstruction
Utf8Entry name();
/**
* {@return the local variable signature}
* {@return the local variable generic signature string}
*
* @apiNote
* A symbolic generic signature of the local variable is available
* through {@link #signatureSymbol() signatureSymbol()}.
*/
Utf8Entry signature();
/**
* {@return the local variable signature}
* {@return the local variable generic signature}
*/
default Signature signatureSymbol() {
return Signature.parseFrom(signature().stringValue());
@@ -81,6 +109,7 @@ public sealed interface LocalVariableType extends PseudoInstruction
/**
* {@return a local variable type pseudo-instruction}
* {@code slot} must be within {@code [0, 65535]}.
*
* @param slot the local variable slot
* @param nameEntry the local variable name
@@ -96,6 +125,7 @@ public sealed interface LocalVariableType extends PseudoInstruction
/**
* {@return a local variable type pseudo-instruction}
* {@code slot} must be within {@code [0, 65535]}.
*
* @param slot the local variable slot
* @param name the local variable name

View File

@@ -24,19 +24,36 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Label;
import java.lang.classfile.Opcode;
import java.util.List;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models a {@code lookupswitch} instruction in the {@code code} array of a
* {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
* the elements of a {@link CodeModel}.
* Models a {@link Opcode#LOOKUPSWITCH lookupswitch} instruction in the {@code
* code} array of a {@code Code} attribute. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
* <p>
* A lookup switch instruction is composite:
* {@snippet lang=text :
* // @link substring="LookupSwitchInstruction" target="#of" :
* LookupSwitchInstruction(
* Label defaultTarget, // @link substring="defaultTarget" target="#defaultTarget"
* List<SwitchCase> cases // @link substring="cases" target="#cases()"
* )
* }
* If elements in {@code cases} are not sorted ascending by their {@link
* SwitchCase#caseValue caseValue}, a sorted version of the {@code cases} list
* will be written instead.
*
* @see Opcode.Kind#LOOKUP_SWITCH
* @see CodeBuilder#lookupswitch CodeBuilder::lookupswitch
* @jvms 6.5.lookupswitch <em>lookupswitch</em>
* @since 24
*/
public sealed interface LookupSwitchInstruction extends Instruction

View File

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

View File

@@ -24,19 +24,34 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Opcode;
import java.lang.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.AbstractInstruction;
import jdk.internal.classfile.impl.BytecodeHelpers;
/**
* Models a {@code multianewarray} invocation instruction in the {@code code}
* Models a {@link Opcode#MULTIANEWARRAY multianewarray} instruction in the {@code code}
* array of a {@code Code} attribute. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
* <p>
* A new multi-dimensional array instruction is composite:
* {@snippet lang=text :
* // @link substring="NewMultiArrayInstruction" target="#of" :
* NewMultiArrayInstruction(
* ClassEntry arrayType, // @link substring="arrayType" target="#arrayType"
* int dimensions // @link substring="dimensions" target="#dimensions"
* )
* }
* where the {@code arrayType} is an array class.
*
* @see Opcode.Kind#NEW_MULTI_ARRAY
* @see CodeBuilder#multianewarray CodeBuilder::multianewarray
* @jvms 6.5.multianewarray <em>multianewarray</em>
* @since 24
*/
public sealed interface NewMultiArrayInstruction extends Instruction
@@ -44,7 +59,7 @@ public sealed interface NewMultiArrayInstruction extends Instruction
AbstractInstruction.UnboundNewMultidimensionalArrayInstruction {
/**
* {@return the type of the array, as a symbolic descriptor}
* {@return the type of the array}
*/
ClassEntry arrayType();

View File

@@ -24,18 +24,30 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Opcode;
import java.lang.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models a {@code new} instruction in the {@code code} array of a {@code Code}
* Models a {@link Opcode#NEW new} instruction in the {@code code} array of a {@code Code}
* attribute. Delivered as a {@link CodeElement} when traversing the elements
* of a {@link CodeModel}.
* <p>
* A new object instruction is composite:
* {@snippet lang=text :
* // @link substring="NewObjectInstruction" target="#of" :
* NewObjectInstruction(ClassEntry className) // @link substring="className" target="#className"
* }
* where the {@code className} is a non-abstract class.
*
* @see Opcode.Kind#NEW_OBJECT
* @see CodeBuilder#new_ CodeBuilder::new_
* @jvms 6.5.new <em>new</em>
* @since 24
*/
public sealed interface NewObjectInstruction extends Instruction

View File

@@ -24,18 +24,30 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Opcode;
import java.lang.classfile.TypeKind;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models a {@code newarray} invocation instruction in the {@code code}
* Models a {@link Opcode#NEWARRAY newarray} instruction in the {@code code}
* array of a {@code Code} attribute. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
* <p>
* A new primitive array instruction is composite:
* {@snippet lang=text :
* // @link substring="NewPrimitiveArrayInstruction" target="#of" :
* NewPrimitiveArrayInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind"
* }
* where {@code typeKind} is primitive and not {@code void}.
*
* @see Opcode.Kind#NEW_PRIMITIVE_ARRAY
* @see CodeBuilder#newarray CodeBuilder::newarray
* @jvms 6.5.newarray <em>newarray</em>
* @since 24
*/
public sealed interface NewPrimitiveArrayInstruction extends Instruction
@@ -43,6 +55,10 @@ public sealed interface NewPrimitiveArrayInstruction extends Instruction
AbstractInstruction.UnboundNewPrimitiveArrayInstruction {
/**
* {@return the component type of the array}
*
* @apiNote
* The backing array code for this instruction is available through
* {@link TypeKind#newarrayCode() typeKind().newarrayCode()}.
*/
TypeKind typeKind();
@@ -50,8 +66,9 @@ public sealed interface NewPrimitiveArrayInstruction extends Instruction
* {@return a new primitive array instruction}
*
* @param typeKind the component type of the array
* @throws IllegalArgumentException when the {@code typeKind} is not a legal
* primitive array component type
* @throws IllegalArgumentException when {@code typeKind} is not primitive
* or is {@code void}
* @see TypeKind#fromNewarrayCode(int) TypeKind::fromNewarrayCode
*/
static NewPrimitiveArrayInstruction of(TypeKind typeKind) {
// Implicit null-check:

View File

@@ -24,18 +24,29 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Opcode;
import java.lang.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models a {@code anewarray} invocation instruction in the {@code code}
* Models a {@link Opcode#ANEWARRAY anewarray} instruction in the {@code code}
* array of a {@code Code} attribute. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
* <p>
* A new reference array instruction is composite:
* {@snippet lang=text :
* // @link substring="NewReferenceArrayInstruction" target="#of" :
* NewReferenceArrayInstruction(ClassEntry componentType) // @link substring="componentType" target="#componentType"
* }
*
* @see Opcode.Kind#NEW_REF_ARRAY
* @see CodeBuilder#newarray CodeBuilder::anewarray
* @jvms 6.5.anewarray <em>anewarray</em>
* @since 24
*/
public sealed interface NewReferenceArrayInstruction extends Instruction

View File

@@ -24,17 +24,23 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Opcode;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models a {@code nop} invocation instruction in the {@code code}
* Models a {@link Opcode#NOP nop} instruction in the {@code code}
* array of a {@code Code} attribute. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
* <p>
* A no-op instruction has no visible state.
*
* @see CodeBuilder#nop CodeBuilder::nop
* @jvms 6.5.nop <em>nop</em>
* @since 24
*/
public sealed interface NopInstruction extends Instruction

View File

@@ -35,23 +35,31 @@ import jdk.internal.classfile.impl.Util;
/**
* Models an arithmetic operator instruction in the {@code code} array of a
* {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
* {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
* {@link Opcode.Kind#OPERATOR}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
* <p>
* An operator instruction is composite:
* {@snippet lang=text :
* // @link substring="OperatorInstruction" target="#of" :
* OperatorInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()"
* }
*
* @see Opcode.Kind#OPERATOR
* @since 24
*/
public sealed interface OperatorInstruction extends Instruction
permits AbstractInstruction.UnboundOperatorInstruction {
/**
* {@return the operand type of the instruction}
* This is derived from the {@link #opcode opcode}.
*/
TypeKind typeKind();
/**
* {@return an operator instruction}
*
* @param op the opcode for the specific type of array load instruction,
* @param op the opcode for the specific type of operator instruction,
* which must be of kind {@link Opcode.Kind#OPERATOR}
* @throws IllegalArgumentException if the opcode kind is not
* {@link Opcode.Kind#OPERATOR}.

View File

@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -36,22 +37,35 @@ import jdk.internal.classfile.impl.Util;
/**
* Models a return-from-method instruction in the {@code code} array of a
* {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
* {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
* {@link Opcode.Kind#RETURN}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
* <p>
* A return-from-method instruction is composite:
* {@snippet lang=text :
* // @link substring="ReturnInstruction" target="#of(TypeKind)" :
* ReturnInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind()"
* }
* where {@code typeKind} is {@linkplain TypeKind##computational-type
* computational} or {@link TypeKind#VOID void}.
*
* @see Opcode.Kind#RETURN
* @see CodeBuilder#return_(TypeKind) CodeBuilder::return_
* @since 24
*/
public sealed interface ReturnInstruction extends Instruction
permits AbstractInstruction.UnboundReturnInstruction {
/**
* {@return the type of the return instruction}
* {@return the {@linkplain TypeKind##computational-type computational type}, including
* {@link TypeKind#VOID void}, of the return instruction}
*/
TypeKind typeKind();
/**
* {@return a return instruction}
* {@code typeKind} is {@linkplain TypeKind#asLoadable() converted} to its
* computational type.
*
* @param typeKind the type of the return instruction
*/

View File

@@ -34,10 +34,17 @@ import jdk.internal.classfile.impl.Util;
/**
* Models a stack manipulation instruction in the {@code code} array of a
* {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
* {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
* {@link Opcode.Kind#STACK}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
* <p>
* A stack manipulation instruction is composite:
* {@snippet lang=text :
* // @link substring="StackInstruction" target="#of" :
* StackInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()"
* }
*
* @see Opcode.Kind#STACK
* @since 24
*/
public sealed interface StackInstruction extends Instruction

View File

@@ -24,6 +24,7 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
@@ -36,10 +37,28 @@ import jdk.internal.classfile.impl.Util;
/**
* Models a local variable store instruction in the {@code code} array of a
* {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
* {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
* {@link Opcode.Kind#STORE}. Delivered as a {@link CodeElement} when
* traversing the elements of a {@link CodeModel}.
* <p>
* A local variable store instruction is composite:
* {@snippet lang=text :
* // @link substring="StoreInstruction" target="#of(TypeKind, int)" :
* StoreInstruction(
* TypeKind typeKind, // @link substring="typeKind" target="#typeKind"
* int slot // @link substring="slot" target="#slot"
* )
* }
* where {@code TypeKind} is {@linkplain TypeKind##computational-type
* computational}, and {@code slot} is within {@code [0, 65535]}.
* <p>
* {@code astore} series of instructions, or {@code reference} type store
* instructions, can also operate on the {@link TypeKind##returnAddress
* returnAddress} type from discontinued {@linkplain
* DiscontinuedInstruction.JsrInstruction jump subroutine instructions}.
*
* @see Opcode.Kind#STORE
* @see CodeBuilder#storeLocal CodeBuilder::storeLocal
* @since 24
*/
public sealed interface StoreInstruction extends Instruction
@@ -47,16 +66,23 @@ public sealed interface StoreInstruction extends Instruction
/**
* {@return the local variable slot to store to}
* The value is within {@code [0, 65535]}.
*/
int slot();
/**
* {@return the type of the value to be stored}
* {@return the {@linkplain TypeKind##computational-type computational type}
* of the value to be stored} The {@link TypeKind#REFERENCE reference}
* type store instructions also operate on the {@code returnAddress} type,
* which does not apply to {@code reference} type load instructions.
*/
TypeKind typeKind();
/**
* {@return a local variable store instruction}
* {@code kind} is {@linkplain TypeKind#asLoadable() converted} to its
* computational type.
* {@code slot} must be within {@code [0, 65535]}.
*
* @param kind the type of the value to be stored
* @param slot the local variable slot to store to
@@ -70,6 +96,20 @@ public sealed interface StoreInstruction extends Instruction
/**
* {@return a local variable store instruction}
* <p>
* The range of {@code slot} is restricted by the {@code op} and its
* {@linkplain Opcode#sizeIfFixed() size}:
* <ul>
* <li>If {@code op} has size 1, {@code slot} must be exactly the slot value
* implied by the opcode.
* <li>If {@code op} has size 2, {@code slot} must be within {@code [0, 255]}.
* <li>If {@code op} has size 4, {@code slot} must be within {@code [0, 65535]}.
* </ul>
*
* @apiNote
* The explicit {@code op} argument allows creating {@code wide} or
* regular store instructions when the {@code slot} can be encoded
* with more optimized store instructions.
*
* @param op the opcode for the specific type of store instruction,
* which must be of kind {@link Opcode.Kind#STORE}

View File

@@ -29,12 +29,20 @@ import java.lang.classfile.Label;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models a single case in a {@code lookupswitch} or {@code tableswitch}
* instruction.
* Models a single case in a {@link LookupSwitchInstruction lookupswitch} or
* {@link TableSwitchInstruction tableswitch} instruction.
* <p>
* A switch case is composite:
* {@snippet lang=text :
* // @link substring="SwitchCase" target="#of" :
* SwitchCase(
* int caseValue, // @link substring="caseValue" target="#caseValue"
* Label target // @link substring="target" target="#target"
* )
* }
*
* @see LookupSwitchInstruction
* @see TableSwitchInstruction
*
* @since 24
*/
public sealed interface SwitchCase
@@ -47,11 +55,10 @@ public sealed interface SwitchCase
Label target();
/**
* Create a {@linkplain SwitchCase}
* {@return a new switch case}
*
* @param caseValue the integer value for the case
* @param target the branch target for the case
* @return the {@linkplain SwitchCase}
*/
static SwitchCase of(int caseValue, Label target) {
return new AbstractInstruction.SwitchCaseImpl(caseValue, target);

View File

@@ -24,19 +24,45 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Label;
import java.lang.classfile.Opcode;
import java.util.List;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models a {@code tableswitch} instruction in the {@code code} array of a
* Models a {@link Opcode#TABLESWITCH tableswitch} instruction in the {@code code} array of a
* {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
* the elements of a {@link CodeModel}.
* <p>
* A table switch instruction is composite:
* {@snippet lang=text :
* // @link substring="TableSwitchInstruction" target="#of" :
* TableSwitchInstruction(
* int lowValue, // @link substring="int lowValue" target="#lowValue"
* int highValue, // @link substring="int highValue" target="#highValue"
* Label defaultTarget, // @link substring="defaultTarget" target="#defaultTarget"
* List<SwitchCase> cases // @link substring="cases" target="#cases()"
* )
* }
* <p>
* When read from {@code class} files, the {@code cases} may omit cases that
* duplicate the default target. The list is sorted ascending by the {@link
* SwitchCase#caseValue() caseValue}.
* <p>
* When writing to {@code class} file, the order in the {@code cases} list does
* not matter, as there is only one valid order in the physical representation
* of table switch entries. Treatment of elements in {@code cases} whose value
* is less than {@code lowValue} or greater than {@code highValue}, and elements
* whose value duplicates that of another, is not specified.
*
* @see Opcode.Kind#TABLE_SWITCH
* @see CodeBuilder#tableswitch CodeBuilder::tableswitch
* @jvms 6.5.tableswitch <em>tableswitch</em>
* @since 24
*/
public sealed interface TableSwitchInstruction extends Instruction
@@ -67,7 +93,8 @@ public sealed interface TableSwitchInstruction extends Instruction
* @param lowValue the low value of the switch target range, inclusive
* @param highValue the high value of the switch target range, inclusive
* @param defaultTarget the default target of the switch
* @param cases the cases of the switch
* @param cases the cases of the switch; duplicate or out of bound case
* handling is not specified
*/
static TableSwitchInstruction of(int lowValue, int highValue, Label defaultTarget, List<SwitchCase> cases) {
return new AbstractInstruction.UnboundTableSwitchInstruction(lowValue, highValue, defaultTarget, cases);

View File

@@ -24,17 +24,23 @@
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.CodeModel;
import java.lang.classfile.Instruction;
import java.lang.classfile.Opcode;
import jdk.internal.classfile.impl.AbstractInstruction;
/**
* Models an {@code athrow} instruction in the {@code code} array of a
* Models an {@link Opcode#ATHROW athrow} instruction in the {@code code} array of a
* {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
* the elements of a {@link CodeModel}.
* <p>
* A throw instruction has no visible state.
*
* @see Opcode.Kind#THROW_EXCEPTION
* @see CodeBuilder#athrow CodeBuiler::athrow
* @since 24
*/
public sealed interface ThrowInstruction extends Instruction

View File

@@ -36,9 +36,24 @@ import jdk.internal.classfile.impl.TemporaryConstantPool;
import jdk.internal.classfile.impl.Util;
/**
* Models an {@code instanceof} or {@code checkcast} instruction in the {@code
* code} array of a {@code Code} attribute. Delivered as a {@link CodeElement}
* when traversing the elements of a {@link CodeModel}.
* Models an {@link Opcode#INSTANCEOF instanceof} or a {@link Opcode#CHECKCAST checkcast}
* instruction in the {@code code} array of a {@code Code} attribute. Corresponding
* opcodes have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#TYPE_CHECK}.
* Delivered as a {@link CodeElement} when traversing the elements of a {@link CodeModel}.
* <p>
* An {@code instanceof} checks the type and pushes an integer to the operand stack.
* A {@code checkcast} checks the type and throws a {@link ClassCastException} if
* the check fails. {@code instanceof} treat the {@code null} reference as a
* failure, while {@code checkcast} treat the {@code null} reference as a success.
* <p>
* A type check instruction is composite:
* {@snippet lang=text :
* // @link substring="TypeCheckInstruction" target="#of(Opcode, ClassEntry)" :
* TypeCheckInstruction(
* Opcode opcode, // @link substring="opcode" target="#opcode"
* ClassEntry type // @link substring="type" target="#type"
* )
* }
*
* @since 24
*/
@@ -47,7 +62,7 @@ public sealed interface TypeCheckInstruction extends Instruction
AbstractInstruction.UnboundTypeCheckInstruction {
/**
* {@return the type against which the instruction checks or casts}
* {@return the type against which the instruction checks}
*/
ClassEntry type();
@@ -58,7 +73,7 @@ public sealed interface TypeCheckInstruction extends Instruction
* which must be of kind {@link Opcode.Kind#TYPE_CHECK}
* @param type the type against which to check or cast
* @throws IllegalArgumentException if the opcode kind is not
* {@link Opcode.Kind#TYPE_CHECK}.
* {@link Opcode.Kind#TYPE_CHECK}
*/
static TypeCheckInstruction of(Opcode op, ClassEntry type) {
Util.checkKind(op, Opcode.Kind.TYPE_CHECK);
@@ -71,6 +86,8 @@ public sealed interface TypeCheckInstruction extends Instruction
* @param op the opcode for the specific type of type check instruction,
* which must be of kind {@link Opcode.Kind#TYPE_CHECK}
* @param type the type against which to check or cast
* @throws IllegalArgumentException if the opcode kind is not
* {@link Opcode.Kind#TYPE_CHECK}, or if {@code type} is primitive
*/
static TypeCheckInstruction of(Opcode op, ClassDesc type) {
return of(op, TemporaryConstantPool.INSTANCE.classEntry(type));

View File

@@ -26,9 +26,45 @@
/**
* <h2>Provides interfaces describing code instructions for the {@link java.lang.classfile} library.</h2>
*
* The {@code java.lang.classfile.attribute} package contains interfaces describing code instructions.
* The {@code java.lang.classfile.instruction} package contains interfaces describing code instructions.
* Implementations of these interfaces are immutable.
* <p>
* Unless otherwise specified, passing {@code null} or an array or collection containing a {@code null} element as an
* argument to a constructor or method of any Class-File API class or interface will cause a {@link NullPointerException}
* to be thrown.
*
* <h2 id="reading">Reading of instructions</h2>
* Instructions and pseudo-instructions are usually accessed from a {@link CodeModel}, such as {@link CodeModel#forEach
* CodeModel::forEach}, and categorized by pattern-matching.
* <p>
* When read from {@code class} files, instructions are lazily inflated; the contents of these instructions, besides the
* bare structure, are not evaluated to speed up parsing. Instructions to users interest, such as those filtered by the
* pattern matching, have their contents read on demand, to avoid unnecessary reading of unrelated instructions in a code
* array.
* <p>
* Due to the lazy nature of {@code class} file parsing, {@link IllegalArgumentException} indicating malformed
* {@code class} file data can be thrown at any method invocation. For example, an instruction object for a {@link
* TypeCheckInstruction} may be obtained from a {@code CodeModel}, but the subsequent invocation of {@link
* TypeCheckInstruction#type() .type()} may fail with {@code IllegalArgumentException} because the instruction refers
* to a bad constant pool index.
*
* <h2 id="writing">Writing of instructions</h2>
* Writing of instructions happen on {@link CodeBuilder}. The most basic way to write instructions is to pass an
* instruction object to {@link CodeBuilder#with CodeBuilder::with}, which supports all valid instructions.
* Yet, {@code CodeBuilder} provides a lot of {@linkplain CodeBuilder##instruction-factories convenience factory methods}
* for easy creation of instructions, named by their mnemonic. These accessors are more concise, and often more
* efficient at run-time than passing instruction objects.
* <p>
* Due to restrictions in the {@code class} file format, some instructions may not be representable in a {@code CodeBuilder}.
* In some scenarios, such as for {@link BranchInstruction}, Class-File API options control if alternatives can be used
* in code generation instead. Otherwise, they can be configured to fail-fast to ensure the parity of {@code CodeBuilder}
* commands with the generated {@code code} array data.
*
* @jvms 6.5 Instructions
* @since 24
*/
package java.lang.classfile.instruction;
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeModel;

View File

@@ -130,8 +130,8 @@ public final class StringSupport {
final long toOffset) {
final long length = toOffset - fromOffset;
segment.checkBounds(fromOffset, length);
if (length == 0) {
// The state has to be checked explicitly for zero-length segments
if (length < Byte.BYTES) {
// There can be no null terminator present
segment.scope.checkValidState();
throw nullNotFound(segment, fromOffset, toOffset);
}
@@ -164,7 +164,8 @@ public final class StringSupport {
final long toOffset) {
final long length = toOffset - fromOffset;
segment.checkBounds(fromOffset, length);
if (length == 0) {
if (length < Short.BYTES) {
// There can be no null terminator present
segment.scope.checkValidState();
throw nullNotFound(segment, fromOffset, toOffset);
}
@@ -199,19 +200,23 @@ public final class StringSupport {
final long toOffset) {
final long length = toOffset - fromOffset;
segment.checkBounds(fromOffset, length);
if (length == 0) {
if (length < Integer.BYTES) {
// There can be no null terminator present
segment.scope.checkValidState();
throw nullNotFound(segment, fromOffset, toOffset);
}
final long longBytes = length & LONG_MASK;
final long longLimit = fromOffset + longBytes;
long offset = fromOffset;
for (; offset < longLimit; offset += Long.BYTES) {
long val = SCOPED_MEMORY_ACCESS.getLongUnaligned(segment.sessionImpl(), segment.unsafeGetBase(), segment.unsafeGetOffset() + offset, !Architecture.isLittleEndian());
if (mightContainZeroInt(val)) {
for (int j = 0; j < Long.BYTES; j += Integer.BYTES) {
if (SCOPED_MEMORY_ACCESS.getIntUnaligned(segment.sessionImpl(), segment.unsafeGetBase(), segment.unsafeGetOffset() + offset + j, !Architecture.isLittleEndian()) == 0) {
return requireWithinStringSize(offset + j - fromOffset, segment, fromOffset, toOffset);
// For quad byte strings, it does not pay off to use long scanning on x64
if (!Architecture.isX64()) {
final long longBytes = length & LONG_MASK;
final long longLimit = fromOffset + longBytes;
for (; offset < longLimit; offset += Long.BYTES) {
long val = SCOPED_MEMORY_ACCESS.getLongUnaligned(segment.sessionImpl(), segment.unsafeGetBase(), segment.unsafeGetOffset() + offset, !Architecture.isLittleEndian());
if (mightContainZeroInt(val)) {
for (int j = 0; j < Long.BYTES; j += Integer.BYTES) {
if (SCOPED_MEMORY_ACCESS.getIntUnaligned(segment.sessionImpl(), segment.unsafeGetBase(), segment.unsafeGetOffset() + offset + j, !Architecture.isLittleEndian()) == 0) {
return requireWithinStringSize(offset + j - fromOffset, segment, fromOffset, toOffset);
}
}
}
}

View File

@@ -25,7 +25,6 @@
package sun.security.ssl;
import java.lang.invoke.MethodHandles;
import java.net.Socket;
import java.security.*;
import java.security.cert.*;
@@ -52,15 +51,6 @@ import sun.security.validator.*;
final class X509TrustManagerImpl extends X509ExtendedTrustManager
implements X509TrustManager {
static {
// eagerly initialize to avoid pinning virtual thread during TLS handshake
try {
MethodHandles.lookup().ensureInitialized(AnchorCertificates.class);
} catch (IllegalAccessException e) {
throw new ExceptionInInitializerError(e);
}
}
private final String validatorType;
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -233,29 +233,22 @@ public abstract class HttpExchange implements AutoCloseable, Request {
public abstract String getProtocol();
/**
* Returns the attribute's value from this exchange's
* {@linkplain HttpContext#getAttributes() context attributes}.
*
* @apiNote {@link Filter} modules may store arbitrary objects as attributes through
* {@code HttpExchange} instances as an out-of-band communication mechanism. Other filters
* {@link Filter} modules may store arbitrary objects with {@code HttpExchange}
* instances as an out-of-band communication mechanism. Other filters
* or the exchange handler may then access these objects.
*
* <p> Each {@code Filter} class will document the attributes which they make
* available.
*
* @param name the name of the attribute to retrieve
* @return the attribute's value or {@code null} if either the attribute isn't set
* or the attribute value is {@code null}
* @return the attribute object, or {@code null} if it does not exist
* @throws NullPointerException if name is {@code null}
*/
public abstract Object getAttribute(String name);
/**
* Sets an attribute with the given {@code name} and {@code value} in this exchange's
* {@linkplain HttpContext#getAttributes() context attributes}.
*
* @apiNote {@link Filter} modules may store arbitrary objects as attributes through
* {@code HttpExchange} instances as an out-of-band communication mechanism. Other filters
* {@link Filter} modules may store arbitrary objects with {@code HttpExchange}
* instances as an out-of-band communication mechanism. Other filters
* or the exchange handler may then access these objects.
*
* <p> Each {@code Filter} class will document the attributes which they make

View File

@@ -116,10 +116,6 @@ runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le
runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64
runtime/NMT/VirtualAllocCommitMerge.java 8309698 linux-s390x
# Fails with +UseCompactObjectHeaders on aarch64
runtime/cds/appcds/SharedBaseAddress.java 8340212 linux-aarch64,macosx-aarch64
runtime/cds/SharedBaseAddress.java 8340212 linux-aarch64,macosx-aarch64
applications/jcstress/copy.java 8229852 linux-all
containers/docker/TestJcmd.java 8278102 linux-all

View File

@@ -32,7 +32,6 @@
* @clean jdk.internal.vm.test.AnnotationTestInput$Missing
* @compile ../../../../../../../../../../../jdk/jdk/internal/vm/AnnotationEncodingDecoding/alt/MemberDeleted.java
* ../../../../../../../../../../../jdk/jdk/internal/vm/AnnotationEncodingDecoding/alt/MemberTypeChanged.java
* @enablePreview
* @modules jdk.internal.vm.ci/jdk.vm.ci.meta
* jdk.internal.vm.ci/jdk.vm.ci.runtime
* jdk.internal.vm.ci/jdk.vm.ci.common

View File

@@ -71,6 +71,33 @@ public class CompressedClassPointersEncodingScheme {
output.shouldContain("Narrow klass base: " + expectedEncodingBaseString + ", Narrow klass shift: " + expectedEncodingShift);
}
private static void testFailure(String forceAddressString) throws IOException {
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(
"-Xshare:off", // to make CompressedClassSpaceBaseAddress work
"-XX:+UnlockDiagnosticVMOptions",
"-XX:CompressedClassSpaceBaseAddress=" + forceAddressString,
"-Xmx128m",
"-Xlog:metaspace*",
"-version");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.reportDiagnosticSummary();
// We ignore cases where we were not able to map at the force address
if (!output.contains("Successfully forced class space address to " + forceAddressString)) {
throw new SkippedException("Skipping because we cannot force ccs to " + forceAddressString);
}
if (Platform.isAArch64()) {
output.shouldHaveExitValue(1);
output.shouldContain("Error occurred during initialization of VM");
output.shouldContain("CompressedClassSpaceBaseAddress=" + forceAddressString +
" given with shift 0, cannot be used to encode class pointers");
} else {
output.shouldHaveExitValue(0);
}
}
final static long K = 1024;
final static long M = K * 1024;
final static long G = M * 1024;
@@ -123,5 +150,9 @@ public class CompressedClassPointersEncodingScheme {
expectedShift = 10;
test(forceAddress, true, ccsSize, forceAddress, expectedShift);
}
// Test failure for -XX:CompressedClassBaseAddress and -Xshare:off
testFailure("0x0000040001000000");
}
}

View File

@@ -34,7 +34,6 @@ import org.testng.annotations.Test;
* @test
* @bug 8221730
* @summary Test of diagnostic command VM.version (tests all DCMD executors)
* @enablePreview
* @modules java.base/jdk.internal.misc
* java.base/jdk.internal.module
* java.compiler

View File

@@ -42,8 +42,8 @@ JAVAC = $(JDK_HOME)/bin/javac
JAR = $(JDK_HOME)/bin/jar
SRC_FILES = $(shell find $(SRC_DIR) -name '*.java')
# Exclude files that need '--enable-preview' to compile.
LIB_FILES = $(filter-out %ModuleInfoWriter.java, $(shell find $(TESTLIBRARY_DIR)/jdk/test/lib/ \
# Must exclude files that need '--enable-preview' to compile, if there is any.
LIB_FILES = $(shell find $(TESTLIBRARY_DIR)/jdk/test/lib/ \
$(TESTLIBRARY_DIR)/jdk/test/lib/process \
$(TESTLIBRARY_DIR)/jdk/test/lib/util \
$(TESTLIBRARY_DIR)/jtreg \

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,19 +23,16 @@
/*
* @test
* @bug 8288109 8235786
* @bug 8288109
* @summary Tests for HttpExchange set/getAttribute
* @library /test/lib
* @run junit/othervm ExchangeAttributeTest
*/
import com.sun.net.httpserver.Filter;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import jdk.test.lib.net.URIBuilder;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -56,87 +53,44 @@ import static org.junit.jupiter.api.Assertions.*;
public class ExchangeAttributeTest {
private static final InetAddress LOOPBACK_ADDR = InetAddress.getLoopbackAddress();
private static final boolean ENABLE_LOGGING = true;
private static final Logger logger = Logger.getLogger("com.sun.net.httpserver");
private static HttpServer server;
static final InetAddress LOOPBACK_ADDR = InetAddress.getLoopbackAddress();
static final boolean ENABLE_LOGGING = true;
static final Logger logger = Logger.getLogger("com.sun.net.httpserver");
@BeforeAll
public static void setup() throws Exception {
public static void setup() {
if (ENABLE_LOGGING) {
ConsoleHandler ch = new ConsoleHandler();
logger.setLevel(Level.ALL);
ch.setLevel(Level.ALL);
logger.addHandler(ch);
}
server = HttpServer.create(new InetSocketAddress(LOOPBACK_ADDR, 0), 10);
server.createContext("/normal", new AttribHandler());
final HttpContext filteredCtx = server.createContext("/filtered", new AttribHandler());
filteredCtx.getFilters().add(new AttributeAddingFilter());
server.start();
System.out.println("Server started at " + server.getAddress());
}
@AfterAll
public static void afterAll() {
if (server != null) {
System.out.println("Stopping server " + server.getAddress());
server.stop(0);
}
}
/*
* Verifies that HttpExchange.setAttribute() allows for null value.
*/
@Test
public void testNullAttributeValue() throws Exception {
try (var client = HttpClient.newBuilder().proxy(NO_PROXY).build()) {
var request = HttpRequest.newBuilder(uri(server, "/normal", null)).build();
public void testExchangeAttributes() throws Exception {
var handler = new AttribHandler();
var server = HttpServer.create(new InetSocketAddress(LOOPBACK_ADDR,0), 10);
server.createContext("/", handler);
server.start();
try {
var client = HttpClient.newBuilder().proxy(NO_PROXY).build();
var request = HttpRequest.newBuilder(uri(server, "")).build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
assertEquals(200, response.statusCode());
}
}
/*
* Verifies that an attribute set on one exchange is accessible to another exchange that
* belongs to the same HttpContext.
*/
@Test
public void testSharedAttribute() throws Exception {
try (var client = HttpClient.newBuilder().proxy(NO_PROXY).build()) {
final var firstReq = HttpRequest.newBuilder(uri(server, "/filtered", "firstreq"))
.build();
System.out.println("issuing request " + firstReq);
final var firstResp = client.send(firstReq, HttpResponse.BodyHandlers.ofString());
assertEquals(200, firstResp.statusCode());
// issue the second request
final var secondReq = HttpRequest.newBuilder(uri(server, "/filtered", "secondreq"))
.build();
System.out.println("issuing request " + secondReq);
final var secondResp = client.send(secondReq, HttpResponse.BodyHandlers.ofString());
assertEquals(200, secondResp.statusCode());
// verify that the filter was invoked for both the requests. the filter internally
// does the setAttribute() and getAttribute() and asserts that the attribute value
// set by the first exchange was available through the second exchange.
assertTrue(AttributeAddingFilter.filteredFirstReq, "Filter wasn't invoked for "
+ firstReq.uri());
assertTrue(AttributeAddingFilter.filteredSecondReq, "Filter wasn't invoked for "
+ secondReq.uri());
} finally {
server.stop(0);
}
}
// --- infra ---
static URI uri(HttpServer server, String path, String query) throws URISyntaxException {
static URI uri(HttpServer server, String path) throws URISyntaxException {
return URIBuilder.newBuilder()
.scheme("http")
.loopback()
.port(server.getAddress().getPort())
.path(path)
.query(query)
.build();
}
@@ -158,54 +112,4 @@ public class ExchangeAttributeTest {
}
}
}
private static final class AttributeAddingFilter extends Filter {
private static final String ATTR_NAME ="foo-bar";
private static final String ATTR_VAL ="hello-world";
private static volatile boolean filteredFirstReq;
private static volatile boolean filteredSecondReq;
@Override
public void doFilter(final HttpExchange exchange, final Chain chain) throws IOException {
if (exchange.getRequestURI().getQuery().contains("firstreq")) {
filteredFirstReq = true;
// add a request attribute through the exchange, for this first request
// and at the same time verify that the attribute doesn't already exist
final Object attrVal = exchange.getAttribute(ATTR_NAME);
if (attrVal != null) {
throw new IOException("attribute " + ATTR_NAME + " with value: " + attrVal
+ " unexpectedly present in exchange: " + exchange.getRequestURI());
}
// set the value
exchange.setAttribute(ATTR_NAME, ATTR_VAL);
System.out.println(exchange.getRequestURI() + " set attribute "
+ ATTR_NAME + "=" + ATTR_VAL);
} else if (exchange.getRequestURI().getQuery().contains("secondreq")) {
filteredSecondReq = true;
// verify the attribute is already set and the value is the expected one.
final Object attrVal = exchange.getAttribute(ATTR_NAME);
if (attrVal == null) {
throw new IOException("attribute " + ATTR_NAME + " is missing in exchange: "
+ exchange.getRequestURI());
}
if (!ATTR_VAL.equals(attrVal)) {
throw new IOException("unexpected value: " + attrVal + " for attribute "
+ ATTR_NAME + " in exchange: " + exchange.getRequestURI());
}
System.out.println(exchange.getRequestURI() + " found attribute "
+ ATTR_NAME + "=" + attrVal);
} else {
// unexpected request
throw new IOException("unexpected request " + exchange.getRequestURI());
}
// let the request proceed
chain.doFilter(exchange);
}
@Override
public String description() {
return "AttributeAddingFilter";
}
}
}

View File

@@ -27,7 +27,6 @@
* @summary InvalidClassException is thrown when the canonical constructor
* cannot be found during deserialization.
* @library /test/lib
* @enablePreview
* @run testng BadCanonicalCtrTest
*/

View File

@@ -26,7 +26,6 @@
* @bug 8246774
* @summary Basic tests for prohibited magic serialization methods
* @library /test/lib
* @enablePreview
* @run testng ProhibitedMethods
*/

View File

@@ -26,7 +26,6 @@
* @bug 8246774
* @summary Basic tests for prohibited magic serialPersistentFields
* @library /test/lib
* @enablePreview
* @run testng SerialPersistentFieldsTest
*/

View File

@@ -24,7 +24,6 @@
/* @test
* @bug 8057919
* @summary Class.getSimpleName() should work for non-JLS compliant class names
* @enablePreview
*/
import java.lang.classfile.ClassBuilder;

View File

@@ -49,7 +49,6 @@ import static org.testng.Assert.*;
/**
* @test
* @enablePreview
* @modules java.base/jdk.internal.module
* @library /test/lib
* @build jdk.test.lib.util.ModuleInfoWriter

View File

@@ -25,7 +25,6 @@
* @test
* @bug 8140450
* @summary Basic test for the StackWalker::getByteCodeIndex method
* @enablePreview
* @run main TestBCI
*/

View File

@@ -26,7 +26,6 @@
* @bug 8228988 8266598
* @summary An annotation-typed property of an annotation that is represented as an
* incompatible property of another type should yield an AnnotationTypeMismatchException.
* @enablePreview
* @run main AnnotationTypeMismatchTest
*/

View File

@@ -27,7 +27,6 @@
* @summary Annotation property which is compiled as an array property but
* changed observed as a singular element should throw an
* AnnotationTypeMismatchException
* @enablePreview
* @run main ArityTypeMismatchTest
*/

View File

@@ -26,7 +26,6 @@
* @bug 8266766
* @summary An array property of a type that is no longer of a type that is a legal member of an
* annotation should throw an AnnotationTypeMismatchException.
* @enablePreview
* @run main ArrayTypeMismatchTest
*/

View File

@@ -26,7 +26,6 @@
* @bug 8228988 8266598
* @summary An enumeration-typed property of an annotation that is represented as an
* incompatible property of another type should yield an AnnotationTypeMismatchException.
* @enablePreview
* @run main EnumTypeMismatchTest
*/

View File

@@ -40,7 +40,6 @@ import java.util.stream.Stream;
* @bug 8158510
* @summary Verify valid annotation
* @modules java.base/sun.reflect.annotation
* @enablePreview
* @clean AnnotationWithVoidReturn AnnotationWithParameter
* AnnotationWithExtraInterface AnnotationWithException
* AnnotationWithHashCode AnnotationWithDefaultMember

View File

@@ -38,8 +38,6 @@ import jdk.test.lib.process.ProcessTools;
* @library /test/lib
* @build bootreporter.StringIdCallback bootreporter.StringIdCallbackReporter
* asmlib.Instrumentor NativeMethodPrefixAgent
* @enablePreview
* @comment The test uses asmlib/Instrumentor.java which relies on ClassFile API PreviewFeature.
* @run main/native NativeMethodPrefixApp roleDriver
*/
public class NativeMethodPrefixApp implements StringIdCallback {
@@ -87,7 +85,6 @@ public class NativeMethodPrefixApp implements StringIdCallback {
private static void launchApp(final Path agentJar) throws Exception {
final OutputAnalyzer oa = ProcessTools.executeTestJava(
"--enable-preview", // due to usage of ClassFile API PreviewFeature in the agent
"-javaagent:" + agentJar.toString(),
"-Djava.library.path=" + testLibraryPath,
NativeMethodPrefixApp.class.getName());

View File

@@ -37,8 +37,6 @@ import jdk.test.lib.helpers.ClassFileInstaller;
* @modules java.instrument
* @library /test/lib
* @build RetransformAgent asmlib.Instrumentor
* @enablePreview
* @comment The test uses asmlib/Instrumentor.java which relies on ClassFile API PreviewFeature.
* @run driver/timeout=240 RetransformApp roleDriver
* @comment The test uses a higher timeout to prevent test timeouts noted in JDK-6528548
*/
@@ -78,7 +76,6 @@ public class RetransformApp {
private static void launchApp(final Path agentJar) throws Exception {
final OutputAnalyzer oa = ProcessTools.executeTestJava(
"--enable-preview", // due to usage of ClassFile API PreviewFeature in the agent
"-javaagent:" + agentJar.toString(),
RetransformApp.class.getName());
oa.shouldHaveExitValue(0);

View File

@@ -25,7 +25,6 @@
* @test
* @bug 8022701
* @summary Illegal access exceptions via methodhandle invocations threw wrong error.
* @enablePreview
* @compile -XDignore.symbol.file BogoLoader.java InvokeSeveralWays.java MHIllegalAccess.java MethodSupplier.java
* @run main/othervm MHIllegalAccess
*/

View File

@@ -23,7 +23,6 @@
/* @test
* @modules java.base/java.lang:open
* @enablePreview
* @run testng/othervm test.DefineClassTest
* @summary Basic test for java.lang.invoke.MethodHandles.Lookup.defineClass
*/

View File

@@ -56,7 +56,6 @@ import static org.junit.jupiter.api.Assertions.*;
/*
* @test
* @bug 6983726 8206955 8269351
* @enablePreview
* @summary Basic sanity tests for MethodHandleProxies
* @build BasicTest Client
* @run junit BasicTest

View File

@@ -46,7 +46,6 @@ import static org.junit.jupiter.api.Assertions.*;
* @test
* @bug 6983726
* @library /test/lib
* @enablePreview
* @summary Tests on implementation hidden classes spinned by MethodHandleProxies
* @build WrapperHiddenClassTest Client jdk.test.lib.util.ForceGC
* @run junit WrapperHiddenClassTest

View File

@@ -25,7 +25,6 @@
* @test
* @bug 8230501
* @library /test/lib
* @enablePreview
* @run testng/othervm ClassDataTest
*/

View File

@@ -25,7 +25,6 @@
* @test
* @bug 8022718
* @summary Runtime accessibility checking: protected class, if extended, should be accessible from another package
* @enablePreview
* @compile -XDignore.symbol.file BogoLoader.java MethodInvoker.java Test.java anotherpkg/MethodSupplierOuter.java
* @run main/othervm Test
*/

View File

@@ -27,7 +27,6 @@
* @summary Test bootstrap methods throwing an exception
* @library /java/lang/invoke/common
* @build test.java.lang.invoke.lib.InstructionHelper
* @enablePreview
* @run testng BootstrapMethodJumboArgsTest
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 BootstrapMethodJumboArgsTest
*/

View File

@@ -27,7 +27,6 @@
* @summary Test bootstrap methods throwing an exception
* @library /java/lang/invoke/common
* @build test.java.lang.invoke.lib.InstructionHelper
* @enablePreview
* @run testng CondyBSMException
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyBSMException
*/

View File

@@ -27,7 +27,6 @@
* @summary Test basic invocation of bootstrap methods
* @library /java/lang/invoke/common
* @build test.java.lang.invoke.lib.InstructionHelper
* @enablePreview
* @run testng CondyBSMInvocation
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyBSMInvocation
*/

View File

@@ -27,7 +27,6 @@
* @summary Test invalid name in name and type
* @library /java/lang/invoke/common
* @build test.java.lang.invoke.lib.InstructionHelper
* @enablePreview
* @run testng CondyBSMValidationTest
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyBSMValidationTest
*/

View File

@@ -27,7 +27,6 @@
* @summary Test for an interface using condy with default overpass methods
* @library /java/lang/invoke/common
* @build test.java.lang.invoke.lib.InstructionHelper
* @enablePreview
* @run testng CondyInterfaceWithOverpassMethods
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyInterfaceWithOverpassMethods
*/

View File

@@ -27,7 +27,6 @@
* @summary Test invalid name in name and type
* @library /java/lang/invoke/common
* @build test.java.lang.invoke.lib.InstructionHelper
* @enablePreview
* @run testng CondyNameValidationTest
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyNameValidationTest
*/

View File

@@ -26,7 +26,6 @@
* @bug 8186046
* @summary Test nested dynamic constant declarations that are recursive
* @compile CondyNestedTest_Code.jcod
* @enablePreview
* @run testng CondyNestedTest
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyNestedTest
*/

View File

@@ -26,7 +26,6 @@
* @bug 8186211
* @summary Test basic invocation of multiple ldc's of the same dynamic constant that fail resolution
* @library /java/lang/invoke/common
* @enablePreview
* @run testng CondyRepeatFailedResolution
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyRepeatFailedResolution
*/

View File

@@ -25,7 +25,6 @@
* @test
* @bug 8186046
* @summary Test for condy BSMs returning primitive values or null
* @enablePreview
* @run testng CondyReturnPrimitiveTest
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyReturnPrimitiveTest
*/

View File

@@ -27,7 +27,6 @@
* @summary Test bootstrap arguments for condy
* @library /java/lang/invoke/common
* @build test.java.lang.invoke.lib.InstructionHelper
* @enablePreview
* @run testng CondyStaticArgumentsTest
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyStaticArgumentsTest
*/

View File

@@ -27,7 +27,6 @@
* @summary Test invalid name in name and type
* @library /java/lang/invoke/common
* @build test.java.lang.invoke.lib.InstructionHelper
* @enablePreview
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyTypeValidationTest
*/

View File

@@ -27,7 +27,6 @@
* @summary Stress test ldc to ensure HotSpot correctly manages oop maps
* @library /java/lang/invoke/common
* @build test.java.lang.invoke.lib.InstructionHelper
* @enablePreview
* @run testng CondyWithGarbageTest
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyWithGarbageTest
*/

View File

@@ -27,7 +27,6 @@
* @summary Test bootstrap methods returning the wrong type
* @library /java/lang/invoke/common
* @build test.java.lang.invoke.lib.InstructionHelper
* @enablePreview
* @run testng CondyWrongType
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 CondyWrongType
*/

View File

@@ -27,7 +27,6 @@
* @summary Test dynamic constant bootstraps
* @library /java/lang/invoke/common
* @build test.java.lang.invoke.lib.InstructionHelper
* @enablePreview
* @run testng ConstantBootstrapsTest
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:UseBootstrapCallInfo=3 ConstantBootstrapsTest
*/

View File

@@ -26,8 +26,6 @@
* @bug 8330467
* @modules jdk.compiler
* @library /test/lib
* @enablePreview
* @comment Change enablePreview with the flag in setup's compileSources
* @compile BadClassFile.jcod
* BadClassFile2.jcod
* BadClassFileVersion.jcod
@@ -79,8 +77,7 @@ public class BasicTest {
@BeforeTest
static void setup() throws IOException {
compileSources(SRC_DIR, CLASSES_DIR, "--enable-preview",
"--release", Integer.toString(Runtime.version().feature()));
compileSources(SRC_DIR, CLASSES_DIR);
hiddenClassBytes = Files.readAllBytes(CLASSES_DIR.resolve("HiddenClass.class"));
// compile with --release 10 with no NestHost and NestMembers attribute

View File

@@ -24,7 +24,6 @@
/*
* @test
* @library /test/lib
* @enablePreview
* @build HiddenNestmateTest
* @run testng/othervm HiddenNestmateTest
*/

View File

@@ -26,7 +26,6 @@
* @bug 8266925
* @summary hidden class members can't be statically invocable
* @modules java.base/jdk.internal.misc
* @enablePreview
* @build java.base/*
* @run testng StaticInvocableTest
*/

View File

@@ -26,7 +26,6 @@
* @bug 8027232
* @library /test/lib/
* @modules jdk.zipfs
* @enablePreview
* @compile LambdaAsm.java
* @run main/othervm LambdaAsm
* @summary ensures that j.l.i.InvokerByteCodeGenerator and Class-File API

View File

@@ -26,7 +26,6 @@
* @bug 8025636
* @library /test/lib/
* @modules jdk.compiler
* @enablePreview
* @compile LambdaStackTrace.java
* @run main LambdaStackTrace
* @summary Synthetic frames should be hidden in exceptions

View File

@@ -24,7 +24,6 @@
/* @test
* @bug 8032400
* @summary JSR292: invokeSpecial: InternalError attempting to lookup a method
* @enablePreview
* @compile -XDignore.symbol.file SpecialStatic.java
* @run testng test.java.lang.invoke.lookup.SpecialStatic
*/

View File

@@ -23,7 +23,6 @@
/**
* @test
* @enablePreview
* @modules java.base/jdk.internal.module
* @library /test/lib
* @build jdk.test.lib.util.ModuleInfoWriter

View File

@@ -23,7 +23,6 @@
/**
* @test
* @enablePreview
* @modules java.base/jdk.internal.access
* java.base/jdk.internal.module
* @library /test/lib

Some files were not shown because too many files have changed in this diff Show More