mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-29 20:00:53 +01:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
950c8adfd7 | ||
|
|
03bdee0f75 | ||
|
|
4ecb28ccdc | ||
|
|
ba02e0bd1b | ||
|
|
253030a6d4 | ||
|
|
a81325433d | ||
|
|
203422a8ed | ||
|
|
8e9ba788ae | ||
|
|
3aa07dbf14 |
@@ -29,6 +29,7 @@ include $(SPEC)
|
||||
include MakeBase.gmk
|
||||
|
||||
include CopyFiles.gmk
|
||||
include DebugInfoUtils.gmk
|
||||
include Execute.gmk
|
||||
include Modules.gmk
|
||||
include Utils.gmk
|
||||
|
||||
@@ -29,6 +29,7 @@ include $(SPEC)
|
||||
include MakeBase.gmk
|
||||
|
||||
include CopyFiles.gmk
|
||||
include DebugInfoUtils.gmk
|
||||
include Modules.gmk
|
||||
include modules/LauncherCommon.gmk
|
||||
|
||||
|
||||
58
make/common/DebugInfoUtils.gmk
Normal file
58
make/common/DebugInfoUtils.gmk
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -32,6 +32,8 @@ import java.lang.classfile.attribute.ModuleAttribute;
|
||||
import java.lang.classfile.constantpool.ClassEntry;
|
||||
import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
||||
import java.lang.classfile.constantpool.Utf8Entry;
|
||||
import java.lang.classfile.instruction.BranchInstruction;
|
||||
import java.lang.classfile.instruction.DiscontinuedInstruction;
|
||||
import java.lang.classfile.instruction.ExceptionCatch;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.reflect.AccessFlag;
|
||||
@@ -230,17 +232,35 @@ public sealed interface ClassFile
|
||||
/**
|
||||
* Option describing whether to automatically rewrite short jumps to
|
||||
* long when necessary.
|
||||
* Default is {@code FIX_SHORT_JUMPS} to automatically rewrite jump
|
||||
* Default is {@link #FIX_SHORT_JUMPS} to automatically rewrite jump
|
||||
* instructions.
|
||||
* <p>
|
||||
* Due to physical restrictions, some types of instructions cannot encode
|
||||
* certain jump targets with bci offsets less than -32768 or greater than
|
||||
* 32767, as they use a {@code s2} to encode such an offset. (The maximum
|
||||
* length of the {@code code} array is 65535.) These types of instructions
|
||||
* are called "short jumps".
|
||||
*
|
||||
* @see BranchInstruction
|
||||
* @see DiscontinuedInstruction.JsrInstruction
|
||||
* @since 24
|
||||
*/
|
||||
enum ShortJumpsOption implements Option {
|
||||
|
||||
/** Automatically convert short jumps to long when necessary */
|
||||
/**
|
||||
* Automatically convert short jumps to long when necessary.
|
||||
* <p>
|
||||
* For an invalid instruction model, a {@link CodeBuilder} may generate
|
||||
* another or a few other instructions to accomplish the same effect.
|
||||
*/
|
||||
FIX_SHORT_JUMPS,
|
||||
|
||||
/** Fail if short jump overflows */
|
||||
/**
|
||||
* Fail with an {@link IllegalArgumentException} if short jump overflows.
|
||||
* <p>
|
||||
* This is useful to ensure the physical accuracy of a generated {@code
|
||||
* class} file.
|
||||
*/
|
||||
FAIL_ON_SHORT_JUMPS
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ import static jdk.internal.classfile.impl.BytecodeHelpers.handleDescToHandleInfo
|
||||
* #with(ClassFileElement)} or concretely by calling the various {@code withXxx}
|
||||
* methods.
|
||||
*
|
||||
* <h2>Instruction Factories</h2>
|
||||
* <h2 id="instruction-factories">Instruction Factories</h2>
|
||||
* {@code CodeBuilder} provides convenience methods to create instructions (See
|
||||
* JVMS {@jvms 6.5} Instructions) by their mnemonic, taking necessary operands.
|
||||
* <ul>
|
||||
|
||||
@@ -25,13 +25,20 @@
|
||||
|
||||
package java.lang.classfile;
|
||||
|
||||
import java.lang.classfile.attribute.CodeAttribute;
|
||||
import java.lang.classfile.instruction.*;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
|
||||
/**
|
||||
* Models an executable instruction in a method body.
|
||||
* Models an executable instruction in the {@code code} array of the {@link
|
||||
* CodeAttribute Code} attribute of a method.
|
||||
* <p>
|
||||
* The {@link #opcode() opcode} identifies the operation of an instruction.
|
||||
* Each {@linkplain Opcode#kind() kind} of opcode has its own modeling interface
|
||||
* for instructions.
|
||||
*
|
||||
* @sealedGraph
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface Instruction extends CodeElement
|
||||
@@ -46,12 +53,14 @@ public sealed interface Instruction extends CodeElement
|
||||
ThrowInstruction, TypeCheckInstruction, AbstractInstruction {
|
||||
|
||||
/**
|
||||
* {@return the opcode of this instruction}
|
||||
* {@return the operation of this instruction}
|
||||
*/
|
||||
Opcode opcode();
|
||||
|
||||
/**
|
||||
* {@return the size in bytes of this instruction}
|
||||
* This value is equal to {@link Opcode#sizeIfFixed()
|
||||
* opcode().sizeIfFixed()} if it is not {@code -1}.
|
||||
*/
|
||||
int sizeInBytes();
|
||||
}
|
||||
|
||||
@@ -24,21 +24,60 @@
|
||||
*/
|
||||
package java.lang.classfile;
|
||||
|
||||
import java.lang.classfile.attribute.CodeAttribute;
|
||||
import java.lang.classfile.instruction.LabelTarget;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import jdk.internal.classfile.impl.LabelImpl;
|
||||
|
||||
/**
|
||||
* A marker for a position within the instructions of a method body. The
|
||||
* association between a label's identity and the position it represents is
|
||||
* managed by the entity managing the method body (a {@link CodeModel} or {@link
|
||||
* CodeBuilder}), not the label itself; this allows the same label to have a
|
||||
* meaning both in an existing method (as managed by a {@linkplain CodeModel})
|
||||
* and in the transformation of that method (as managed by a {@linkplain
|
||||
* CodeBuilder}), while corresponding to different positions in each. When
|
||||
* traversing the elements of a {@linkplain CodeModel}, {@linkplain Label}
|
||||
* markers will be delivered at the position to which they correspond. A label
|
||||
* can be bound to the current position within a {@linkplain CodeBuilder} via
|
||||
* {@link CodeBuilder#labelBinding(Label)} or {@link CodeBuilder#with(ClassFileElement)}.
|
||||
* position is a cursor position in the list of instructions, similar to that
|
||||
* of a {@link ListIterator}.
|
||||
*
|
||||
* <h2 id="reading">Reading Labels</h2>
|
||||
* Labels read from {@code class} files represent positions in the {@code code}
|
||||
* array of a {@link CodeAttribute Code} attribute. It is associated with a
|
||||
* <dfn>{@index bci}</dfn> (bytecode index), also known as <dfn>{@index pc}</dfn>
|
||||
* (program counter), the index into the {@code code} array; the actual cursor
|
||||
* position is immediately before the given index, so a label at the beginning
|
||||
* of the instructions has bci {@code 0}, and a label at the end of the
|
||||
* instructions has bci {@link CodeAttribute#codeLength codeLength() + 1}. The
|
||||
* bci can be inspected through {@link CodeAttribute#labelToBci
|
||||
* CodeAttribute::labelToBci}.
|
||||
* <p>
|
||||
* In generic {@link CodeModel}s, a label may not have a bci value; the position
|
||||
* of a label can be found by searching for the corresponding {@link LabelTarget}
|
||||
* within that model.
|
||||
*
|
||||
* <h2 id="writing">Writing Labels</h2>
|
||||
* Many models in {@link java.lang.classfile} refer to labels. To write a
|
||||
* label, a label must be obtained, it must be bound to a {@link CodeBuilder}.
|
||||
* <p>
|
||||
* To obtain a label:
|
||||
* <ul>
|
||||
* <li>Use a label read from other models.
|
||||
* <li>Use pre-defined labels from a {@link CodeBuilder}, such as {@link
|
||||
* CodeBuilder#startLabel() CodeBuilder::startLabel}, {@link CodeBuilder#endLabel
|
||||
* CodeBuilder::endLabel}, or {@link CodeBuilder.BlockCodeBuilder#breakLabel
|
||||
* BlockCodeBuilder::breakLabel}. They are already bound.
|
||||
* <li>Create labels with {@link CodeBuilder#newLabel CodeBuilder::newLabel} or
|
||||
* {@link CodeBuilder#newBoundLabel CodeBuilder::newBoundLabel}.
|
||||
* </ul>
|
||||
* <p>
|
||||
* A label must be bound exactly once in the {@code CodeBuilder} where it is
|
||||
* used; otherwise, writing fails. To bind an unbound label:
|
||||
* <ul>
|
||||
* <li>Send a read {@link LabelTarget} to a {@code CodeBuilder}.
|
||||
* <li>Use {@link CodeBuilder#labelBinding CodeBuilder::labelBinding}.
|
||||
* </ul>
|
||||
* Note that a label read from another model is not automatically bound in a
|
||||
* {@code CodeBuilder}; they are separate entities and the label is bound to
|
||||
* different positions in them.
|
||||
*
|
||||
* @see CodeAttribute#labelToBci CodeAttribute::labelToBci
|
||||
* @see CodeBuilder#newLabel CodeBuilder::newLabel
|
||||
* @see CodeBuilder#labelBinding CodeBuilder::labelBinding
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface Label
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,9 @@
|
||||
package java.lang.classfile;
|
||||
|
||||
import java.lang.classfile.instruction.DiscontinuedInstruction;
|
||||
import java.lang.classfile.instruction.LoadInstruction;
|
||||
import java.lang.classfile.instruction.NewPrimitiveArrayInstruction;
|
||||
import java.lang.classfile.instruction.StoreInstruction;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.constant.ConstantDescs;
|
||||
import java.lang.invoke.TypeDescriptor;
|
||||
@@ -33,13 +36,17 @@ import java.lang.invoke.TypeDescriptor;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
/**
|
||||
* Describes the data types Java Virtual Machine operates on.
|
||||
* This omits {@code returnAddress} (JVMS {@jvms 2.3.3}),
|
||||
* which is only used by discontinued {@link
|
||||
* DiscontinuedInstruction.JsrInstruction jsr} and {@link
|
||||
* DiscontinuedInstruction.RetInstruction ret} instructions,
|
||||
* and includes {@link #VOID void} (JVMS {@jvms 4.3.3}), which
|
||||
* appears as a method return type.
|
||||
* Describes the data types Java Virtual Machine operates on. This omits {@code
|
||||
* returnAddress} (JVMS {@jvms 2.3.3}) and includes {@link #VOID void} (JVMS
|
||||
* {@jvms 4.3.3}), which appears as a method return type.
|
||||
* <p>
|
||||
* The <code>{@index returnAddress}</code> type is only used by discontinued
|
||||
* {@linkplain DiscontinuedInstruction.JsrInstruction jump subroutine} and
|
||||
* {@linkplain DiscontinuedInstruction.RetInstruction return from subroutine}
|
||||
* instructions. Jump subroutine instructions push {@code returnAddress} to the
|
||||
* operand stack; {@link StoreInstruction astore} instructions store {@code
|
||||
* returnAddress} from the operand stack to local variables; return from
|
||||
* subroutine instructions load {@code returnAddress} from local variables.
|
||||
*
|
||||
* <h2 id="computational-type">Computational Type</h2>
|
||||
* In the {@code class} file format, local variables (JVMS {@jvms 2.6.1}),
|
||||
@@ -164,7 +171,10 @@ public enum TypeKind {
|
||||
/**
|
||||
* {@return the code used by the {@link Opcode#NEWARRAY newarray} instruction to create an array
|
||||
* of this component type, or {@code -1} if this type is not supported by {@code newarray}}
|
||||
* @jvms 6.5.newarray <i>newarray</i>
|
||||
*
|
||||
* @jvms 6.5.newarray <em>newarray</em>
|
||||
* @see NewPrimitiveArrayInstruction
|
||||
* @see #fromNewarrayCode(int) fromNewarrayCode(int)
|
||||
*/
|
||||
public int newarrayCode() {
|
||||
return newarrayCode;
|
||||
@@ -175,6 +185,7 @@ public enum TypeKind {
|
||||
* This is also the category of this type for instructions operating on the operand stack without
|
||||
* regard to type (JVMS {@jvms 2.11.1}), such as {@link Opcode#POP pop} versus {@link Opcode#POP2
|
||||
* pop2}.
|
||||
*
|
||||
* @jvms 2.6.1 Local Variables
|
||||
* @jvms 2.6.2 Operand Stacks
|
||||
*/
|
||||
@@ -185,6 +196,9 @@ public enum TypeKind {
|
||||
/**
|
||||
* {@return the {@linkplain ##computational-type computational type} for this type, or {@link #VOID void}
|
||||
* for {@code void}}
|
||||
*
|
||||
* @see LoadInstruction
|
||||
* @see StoreInstruction
|
||||
*/
|
||||
public TypeKind asLoadable() {
|
||||
return ordinal() < 4 ? INT : this;
|
||||
@@ -193,9 +207,12 @@ public enum TypeKind {
|
||||
/**
|
||||
* {@return the component type described by the array code used as an operand to {@link Opcode#NEWARRAY
|
||||
* newarray}}
|
||||
*
|
||||
* @param newarrayCode the operand of the {@code newarray} instruction
|
||||
* @throws IllegalArgumentException if the code is invalid
|
||||
* @jvms 6.5.newarray <i>newarray</i>
|
||||
* @jvms 6.5.newarray <em>newarray</em>
|
||||
* @see NewPrimitiveArrayInstruction
|
||||
* @see #newarrayCode() newarrayCode()
|
||||
*/
|
||||
public static TypeKind fromNewarrayCode(int newarrayCode) {
|
||||
return switch (newarrayCode) {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
@@ -35,18 +36,29 @@ import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models an array load instruction in the {@code code} array of a {@code Code}
|
||||
* attribute. Corresponding opcodes will have a {@code kind} of {@link
|
||||
* Opcode.Kind#ARRAY_LOAD}. Delivered as a {@link CodeElement} when
|
||||
* attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind}
|
||||
* of {@link Opcode.Kind#ARRAY_LOAD}. Delivered as a {@link CodeElement} when
|
||||
* traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* An array load instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="ArrayLoadInstruction" target="CodeBuilder#arrayLoad(TypeKind)" :
|
||||
* ArrayLoadInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind"
|
||||
* }
|
||||
* where {@code typeKind} is not {@link TypeKind#VOID void}, and {@link
|
||||
* TypeKind#BOOLEAN boolean} is converted to {@link TypeKind#BYTE byte}.
|
||||
*
|
||||
* @see Opcode.Kind#ARRAY_LOAD
|
||||
* @see CodeBuilder#arrayLoad CodeBuilder::arrayLoad
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface ArrayLoadInstruction extends Instruction
|
||||
permits AbstractInstruction.UnboundArrayLoadInstruction {
|
||||
/**
|
||||
* {@return the component type of the array} The {@link TypeKind#BYTE byte}
|
||||
* {@return the component type of the array} The {@link TypeKind#BYTE byte}
|
||||
* type load instruction {@link Opcode#BALOAD baload} also operates on
|
||||
* {@link TypeKind#BOOLEAN boolean} arrays.
|
||||
* {@link TypeKind#BOOLEAN boolean} arrays, so this never returns
|
||||
* {@code boolean}.
|
||||
*/
|
||||
TypeKind typeKind();
|
||||
|
||||
@@ -56,7 +68,7 @@ public sealed interface ArrayLoadInstruction extends Instruction
|
||||
* @param op the opcode for the specific type of array load instruction,
|
||||
* which must be of kind {@link Opcode.Kind#ARRAY_LOAD}
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
* {@link Opcode.Kind#ARRAY_LOAD}.
|
||||
* {@link Opcode.Kind#ARRAY_LOAD}
|
||||
*/
|
||||
static ArrayLoadInstruction of(Opcode op) {
|
||||
Util.checkKind(op, Opcode.Kind.ARRAY_LOAD);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
@@ -35,18 +36,29 @@ import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models an array store instruction in the {@code code} array of a {@code Code}
|
||||
* attribute. Corresponding opcodes will have a {@code kind} of {@link
|
||||
* Opcode.Kind#ARRAY_STORE}. Delivered as a {@link CodeElement} when
|
||||
* attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind}
|
||||
* of {@link Opcode.Kind#ARRAY_STORE}. Delivered as a {@link CodeElement} when
|
||||
* traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* An array store instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="ArrayStoreInstruction" target="CodeBuilder#arrayStore(TypeKind)" :
|
||||
* ArrayStoreInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind"
|
||||
* }
|
||||
* where {@code typeKind} is not {@link TypeKind#VOID void}, and {@link
|
||||
* TypeKind#BOOLEAN boolean} is converted to {@link TypeKind#BYTE byte}.
|
||||
*
|
||||
* @see Opcode.Kind#ARRAY_STORE
|
||||
* @see CodeBuilder#arrayStore CodeBuilder::arrayStore
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface ArrayStoreInstruction extends Instruction
|
||||
permits AbstractInstruction.UnboundArrayStoreInstruction {
|
||||
/**
|
||||
* {@return the component type of the array} The {@link TypeKind#BYTE byte}
|
||||
* {@return the component type of the array} The {@link TypeKind#BYTE byte}
|
||||
* type store instruction {@link Opcode#BASTORE bastore} also operates on
|
||||
* {@link TypeKind#BOOLEAN boolean} arrays.
|
||||
* {@link TypeKind#BOOLEAN boolean} arrays, so this never returns
|
||||
* {@code boolean}.
|
||||
*/
|
||||
TypeKind typeKind();
|
||||
|
||||
@@ -56,7 +68,7 @@ public sealed interface ArrayStoreInstruction extends Instruction
|
||||
* @param op the opcode for the specific type of array store instruction,
|
||||
* which must be of kind {@link Opcode.Kind#ARRAY_STORE}
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
* {@link Opcode.Kind#ARRAY_STORE}.
|
||||
* {@link Opcode.Kind#ARRAY_STORE}
|
||||
*/
|
||||
static ArrayStoreInstruction of(Opcode op) {
|
||||
Util.checkKind(op, Opcode.Kind.ARRAY_STORE);
|
||||
|
||||
@@ -24,28 +24,41 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.lang.classfile.*;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a branching instruction (conditional or unconditional) in the {@code
|
||||
* code} array of a {@code Code} attribute. Corresponding opcodes will have a
|
||||
* {@code kind} of {@link Opcode.Kind#BRANCH}. Delivered as a {@link
|
||||
* CodeElement} when traversing the elements of a {@link CodeModel}.
|
||||
* code} array of a {@code Code} attribute. Corresponding opcodes have a
|
||||
* {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#BRANCH}. Delivered as
|
||||
* a {@link CodeElement} when traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A branch instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="BranchInstruction" target="#of":
|
||||
* BranchInstruction(
|
||||
* Opcode opcode, // @link substring="opcode" target="#opcode()"
|
||||
* Label target // @link substring="target" target="#target()"
|
||||
* )
|
||||
* }
|
||||
* <p>
|
||||
* Due to physical restrictions, some types of instructions cannot encode labels
|
||||
* too far away in the list of code elements. In such cases, the {@link
|
||||
* ClassFile.ShortJumpsOption} controls how an invalid branch instruction model
|
||||
* is written by a {@link CodeBuilder}.
|
||||
*
|
||||
* @see Opcode.Kind#BRANCH
|
||||
* @see CodeBuilder#branch CodeBuilder::branch
|
||||
* @see ClassFile.ShortJumpsOption
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface BranchInstruction extends Instruction
|
||||
permits AbstractInstruction.BoundBranchInstruction,
|
||||
AbstractInstruction.UnboundBranchInstruction {
|
||||
/**
|
||||
* {@return the target of the branch}
|
||||
* {@return the branch target of this instruction}
|
||||
*/
|
||||
Label target();
|
||||
|
||||
@@ -56,7 +69,7 @@ public sealed interface BranchInstruction extends Instruction
|
||||
* which must be of kind {@link Opcode.Kind#BRANCH}
|
||||
* @param target the target of the branch
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
* {@link Opcode.Kind#BRANCH}.
|
||||
* {@link Opcode.Kind#BRANCH}
|
||||
*/
|
||||
static BranchInstruction of(Opcode op, Label target) {
|
||||
Util.checkKind(op, Opcode.Kind.BRANCH);
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Label;
|
||||
@@ -36,11 +37,31 @@ import jdk.internal.classfile.impl.AbstractPseudoInstruction;
|
||||
import jdk.internal.classfile.impl.BoundCharacterRange;
|
||||
|
||||
/**
|
||||
* A pseudo-instruction which models a single entry in the
|
||||
* {@link CharacterRangeTableAttribute}. Delivered as a {@link CodeElement}
|
||||
* during traversal of the elements of a {@link CodeModel}, according to
|
||||
* the setting of the {@link ClassFile.DebugElementsOption} option.
|
||||
* A pseudo-instruction which models a single entry in the {@link
|
||||
* CharacterRangeTableAttribute CharacterRangeTable} attribute. Delivered as a
|
||||
* {@link CodeElement} during traversal of the elements of a {@link CodeModel},
|
||||
* according to the setting of the {@link ClassFile.DebugElementsOption} option.
|
||||
* <p>
|
||||
* A character range entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="CharacterRange" target="#of":
|
||||
* CharacterRange(
|
||||
* Label startScope, // @link substring="startScope" target="#startScope"
|
||||
* Label endScope, // @link substring="endScope" target="#endScope"
|
||||
* int characterRangeStart, // @link substring="characterRangeStart" target="#characterRangeStart"
|
||||
* int characterRangeEnd, // @link substring="characterRangeEnd" target="#characterRangeEnd"
|
||||
* int flags // @link substring="flags" target="#flags"
|
||||
* )
|
||||
* }
|
||||
* <p>
|
||||
* Another model, {@link CharacterRangeInfo}, also models a character range
|
||||
* entry; it has no dependency on a {@code CodeModel} and represents of bci
|
||||
* values as {@code int}s instead of {@code Label}s, and is used as components
|
||||
* of a {@link CharacterRangeTableAttribute}.
|
||||
*
|
||||
* @see CharacterRangeInfo
|
||||
* @see CodeBuilder#characterRange CodeBuilder::characterRange
|
||||
* @see ClassFile.DebugElementsOption
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface CharacterRange extends PseudoInstruction
|
||||
@@ -114,7 +135,7 @@ public sealed interface CharacterRange extends PseudoInstruction
|
||||
* <li>{@link #FLAG_BRANCH_FALSE}
|
||||
* </ul>
|
||||
*
|
||||
* @see java.lang.classfile.attribute.CharacterRangeInfo#flags()
|
||||
* @see CharacterRangeInfo#flags()
|
||||
*
|
||||
* @return the flags
|
||||
*/
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
@@ -38,12 +39,22 @@ import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a constant-load instruction in the {@code code} array of a {@code
|
||||
* Code} attribute, including "intrinsic constant" instructions (e.g., {@code
|
||||
* iconst_0}), "argument constant" instructions (e.g., {@code bipush}), and "load
|
||||
* constant" instructions (e.g., {@code LDC}). Corresponding opcodes will have
|
||||
* a {@code kind} of {@link Opcode.Kind#CONSTANT}. Delivered as a {@link
|
||||
* CodeElement} when traversing the elements of a {@link CodeModel}.
|
||||
* Code} attribute, including {@linkplain IntrinsicConstantInstruction
|
||||
* "intrinsic"}, {@linkplain ArgumentConstantInstruction "argument"}, and
|
||||
* {@linkplain LoadConstantInstruction "load"} constant instructions.
|
||||
* Corresponding opcodes have a {@linkplain Opcode#kind() kind} of {@link
|
||||
* Opcode.Kind#CONSTANT}. Delivered as a {@link CodeElement} when traversing
|
||||
* the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* The loaded constant value is symbolically represented as a {@link ConstantDesc}:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="ConstantInstruction" target="CodeBuilder#loadConstant(ConstantDesc)" :
|
||||
* ConstantInstruction(ConstantDesc constantValue) // @link substring="constantValue" target="#constantValue()"
|
||||
* }
|
||||
*
|
||||
* @see Opcode.Kind#CONSTANT
|
||||
* @see CodeBuilder#loadConstant(ConstantDesc) CodeBuilder::loadConstant
|
||||
* @sealedGraph
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface ConstantInstruction extends Instruction {
|
||||
@@ -54,22 +65,36 @@ public sealed interface ConstantInstruction extends Instruction {
|
||||
ConstantDesc constantValue();
|
||||
|
||||
/**
|
||||
* {@return the type of the constant}
|
||||
* {@return the {@linkplain TypeKind##computational-type computational type} of the constant}
|
||||
* This is derived from the {@link #constantValue() constantValue}.
|
||||
*/
|
||||
TypeKind typeKind();
|
||||
|
||||
/**
|
||||
* Models an "intrinsic constant" instruction (e.g., {@code
|
||||
* iconst_0}).
|
||||
* Models an "intrinsic constant" instruction, which encodes
|
||||
* the constant value in its opcode. Examples include {@link
|
||||
* Opcode#ACONST_NULL aconst_null} and {@link
|
||||
* Opcode#ICONST_0 iconst_0}.
|
||||
* <p>
|
||||
* An intrinsic constant instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="IntrinsicConstantInstruction" target="#ofIntrinsic" :
|
||||
* IntrinsicConstantInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()"
|
||||
* }
|
||||
* where:
|
||||
* <dl>
|
||||
* <dt>{@link #opcode() opcode}</dt>
|
||||
* <dd>Must be of the constant kind and have a {@linkplain
|
||||
* Opcode#sizeIfFixed() fixed size} of 1.</dd>
|
||||
* </dl>
|
||||
*
|
||||
* @see Opcode.Kind#CONSTANT
|
||||
* @see ConstantInstruction#ofIntrinsic ConstantInstruction::ofIntrinsic
|
||||
* @since 24
|
||||
*/
|
||||
sealed interface IntrinsicConstantInstruction extends ConstantInstruction
|
||||
permits AbstractInstruction.UnboundIntrinsicConstantInstruction {
|
||||
|
||||
/**
|
||||
* {@return the type of the constant}
|
||||
*/
|
||||
@Override
|
||||
default TypeKind typeKind() {
|
||||
return BytecodeHelpers.intrinsicConstantType(opcode());
|
||||
@@ -77,9 +102,31 @@ public sealed interface ConstantInstruction extends Instruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Models an "argument constant" instruction (e.g., {@code
|
||||
* bipush}).
|
||||
* Models an "argument constant" instruction, which encodes the
|
||||
* constant value in the instruction directly. Includes {@link
|
||||
* Opcode#BIPUSH bipush} and {@link Opcode#SIPUSH sipush} instructions.
|
||||
* <p>
|
||||
* An argument constant instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="ArgumentConstantInstruction" target="#ofArgument" :
|
||||
* ArgumentConstantInstruction(
|
||||
* Opcode opcode, // @link substring="opcode" target="#opcode()"
|
||||
* int constantValue // @link substring="constantValue" target="#constantValue()"
|
||||
* )
|
||||
* }
|
||||
* where:
|
||||
* <ul>
|
||||
* <li>{@code opcode} must be one of {@code bipush} or {@code sipush}.
|
||||
* <li>{@code constantValue} must be in the range of {@code byte}, {@code
|
||||
* [-128, 127]}, for {@code bipush}, and in the range of {@code short},
|
||||
* {@code [-32768, 32767]}, for {@code sipush}.
|
||||
* </ul>
|
||||
*
|
||||
* @see Opcode.Kind#CONSTANT
|
||||
* @see ConstantInstruction#ofArgument ConstantInstruction::ofArgument
|
||||
* @see CodeBuilder#loadConstant(int) CodeBuilder::loadConstant(int)
|
||||
* @see CodeBuilder#bipush CodeBuilder::bipush
|
||||
* @see CodeBuilder#sipush CodeBuilder::sipush
|
||||
* @since 24
|
||||
*/
|
||||
sealed interface ArgumentConstantInstruction extends ConstantInstruction
|
||||
@@ -89,9 +136,6 @@ public sealed interface ConstantInstruction extends Instruction {
|
||||
@Override
|
||||
Integer constantValue();
|
||||
|
||||
/**
|
||||
* {@return the type of the constant}
|
||||
*/
|
||||
@Override
|
||||
default TypeKind typeKind() {
|
||||
return TypeKind.INT;
|
||||
@@ -99,9 +143,24 @@ public sealed interface ConstantInstruction extends Instruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Models a "load constant" instruction (e.g., {@code
|
||||
* ldc}).
|
||||
* Models a "load constant" instruction, which encodes the constant value
|
||||
* in the constant pool. Includes {@link Opcode#LDC ldc} and {@link
|
||||
* Opcode#LDC_W ldc_w}, and {@link Opcode#LDC2_W ldc2_w} instructions.
|
||||
* <p>
|
||||
* A load constant instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="LoadConstantInstruction" target="CodeBuilder#ldc(LoadableConstantEntry)" :
|
||||
* LoadConstantInstruction(LoadableConstantEntry constantEntry) // @link substring="constantEntry" target="#constantEntry()"
|
||||
* }
|
||||
* <p>
|
||||
* A "load constant" instruction can load any constant value supported by
|
||||
* other constant-load instructions. However, other instructions are
|
||||
* usually more optimized, avoiding extra constant pool entries and being
|
||||
* smaller.
|
||||
*
|
||||
* @see Opcode.Kind#CONSTANT
|
||||
* @see ConstantInstruction#ofLoad ConstantInstruction::ofLoad
|
||||
* @see CodeBuilder#ldc CodeBuilder::ldc
|
||||
* @since 24
|
||||
*/
|
||||
sealed interface LoadConstantInstruction extends ConstantInstruction
|
||||
@@ -113,9 +172,6 @@ public sealed interface ConstantInstruction extends Instruction {
|
||||
*/
|
||||
LoadableConstantEntry constantEntry();
|
||||
|
||||
/**
|
||||
* {@return the type of the constant}
|
||||
*/
|
||||
@Override
|
||||
default TypeKind typeKind() {
|
||||
return constantEntry().typeKind();
|
||||
@@ -139,6 +195,10 @@ public sealed interface ConstantInstruction extends Instruction {
|
||||
|
||||
/**
|
||||
* {@return an argument constant instruction}
|
||||
* <p>
|
||||
* {@code value} must be in the range of {@code byte}, {@code [-128, 127]},
|
||||
* for {@link Opcode#BIPUSH}, and in the range of {@code short}, {@code
|
||||
* [-32768, 32767]}, for {@link Opcode#SIPUSH}.
|
||||
*
|
||||
* @param op the opcode for the specific type of argument constant instruction,
|
||||
* which must be {@link Opcode#BIPUSH} or {@link Opcode#SIPUSH}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
@@ -36,10 +37,27 @@ import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a primitive conversion instruction in the {@code code} array of a
|
||||
* {@code Code} attribute, such as {@code i2l}. Corresponding opcodes will have
|
||||
* a {@code kind} of {@link Opcode.Kind#CONVERT}. Delivered as a {@link
|
||||
* CodeElement} when traversing the elements of a {@link CodeModel}.
|
||||
* {@code Code} attribute, such as {@link Opcode#I2L i2l}. Corresponding opcodes
|
||||
* have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#CONVERT}.
|
||||
* Delivered as a {@link CodeElement} when traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A primitive conversion instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="ConvertInstruction" target="#of(TypeKind, TypeKind)" :
|
||||
* ConvertInstruction(
|
||||
* TypeKind fromType, // @link substring="fromType" target="#fromType"
|
||||
* TypeKind toType // @link substring="toType" target="#toType"
|
||||
* )
|
||||
* }
|
||||
* where these conversions are valid:
|
||||
* <ul>
|
||||
* <li>Between {@code int}, {@code long}, {@code float}, and {@code double}, where
|
||||
* {@code fromType != toType};
|
||||
* <li>From {@code int} to {@code byte}, {@code char}, and {@code short}.
|
||||
* </ul>
|
||||
*
|
||||
* @see Opcode.Kind#CONVERT
|
||||
* @see CodeBuilder#conversion CodeBuilder::conversion
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface ConvertInstruction extends Instruction
|
||||
@@ -55,10 +73,16 @@ public sealed interface ConvertInstruction extends Instruction
|
||||
TypeKind toType();
|
||||
|
||||
/**
|
||||
* {@return A conversion instruction}
|
||||
* {@return a conversion instruction} Valid conversions are:
|
||||
* <ul>
|
||||
* <li>Between {@code int}, {@code long}, {@code float}, and {@code double},
|
||||
* where {@code fromType != toType};
|
||||
* <li>From {@code int} to {@code byte}, {@code char}, and {@code short}.
|
||||
* </ul>
|
||||
*
|
||||
* @param fromType the type to convert from
|
||||
* @param toType the type to convert to
|
||||
* @throws IllegalArgumentException if this is not a valid conversion
|
||||
*/
|
||||
static ConvertInstruction of(TypeKind fromType, TypeKind toType) {
|
||||
return of(BytecodeHelpers.convertOpcode(fromType, toType));
|
||||
|
||||
@@ -24,32 +24,54 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.lang.classfile.*;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
import jdk.internal.classfile.impl.BytecodeHelpers;
|
||||
import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models instruction discontinued from the {@code code} array of a {@code Code}
|
||||
* attribute. Delivered as a {@link CodeElement} when traversing the elements of
|
||||
* a {@link CodeModel}.
|
||||
* Marker interface for instruction discontinued from the {@code code} array of
|
||||
* a {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
|
||||
* the elements of a {@link CodeModel}.
|
||||
*
|
||||
* @apiNote
|
||||
* While most instructions have convenience factory methods in {@link
|
||||
* CodeBuilder}, discontinued instructions can only be supplied to code builders
|
||||
* explicitly with {@link CodeBuilder#with CodeBuilder::with} to discourage
|
||||
* their use.
|
||||
*
|
||||
* @jvms 4.9.1 Static Constraints
|
||||
* @sealedGraph
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface DiscontinuedInstruction extends Instruction {
|
||||
|
||||
/**
|
||||
* Models JSR and JSR_W instructions discontinued from the {@code code}
|
||||
* array of a {@code Code} attribute since class file version 51.0.
|
||||
* Corresponding opcodes will have a {@code kind} of
|
||||
* {@link Opcode.Kind#DISCONTINUED_JSR}. Delivered as a {@link CodeElement}
|
||||
* when traversing the elements of a {@link CodeModel}.
|
||||
* Models jump subroutine instructions discontinued from the {@code code}
|
||||
* array of a {@code Code} attribute since class file major version {@value
|
||||
* ClassFile#JAVA_7_VERSION} (JVMS {@jvms 4.9.1}). Corresponding opcodes
|
||||
* have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#DISCONTINUED_JSR}.
|
||||
* Delivered as a {@link CodeElement} when traversing the elements of a
|
||||
* {@link CodeModel}.
|
||||
* <p>
|
||||
* A jump subroutine instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="JsrInstruction" target="#of(Label)" :
|
||||
* JsrInstruction(Label target) // @link substring="target" target="#target()"
|
||||
* }
|
||||
* <p>
|
||||
* Due to physical restrictions, {@link Opcode#JSR jsr} instructions cannot
|
||||
* encode labels too far away in the list of code elements. In such cases,
|
||||
* the {@link ClassFile.ShortJumpsOption} controls how an invalid {@code jsr}
|
||||
* instruction model is written by a {@link CodeBuilder}.
|
||||
* <p>
|
||||
* Jump subroutine instructions push a {@link TypeKind##returnAddress
|
||||
* returnAddress} value to the operand stack, and {@link StoreInstruction
|
||||
* astore} series of instructions can then store this value to a local
|
||||
* variable slot.
|
||||
*
|
||||
* @see Opcode.Kind#DISCONTINUED_JSR
|
||||
* @since 24
|
||||
*/
|
||||
sealed interface JsrInstruction extends DiscontinuedInstruction
|
||||
@@ -57,14 +79,18 @@ public sealed interface DiscontinuedInstruction extends Instruction {
|
||||
AbstractInstruction.UnboundJsrInstruction {
|
||||
|
||||
/**
|
||||
* {@return the target of the JSR instruction}
|
||||
* {@return the target of the jump subroutine instruction}
|
||||
*/
|
||||
Label target();
|
||||
|
||||
/**
|
||||
* {@return a JSR instruction}
|
||||
* {@return a jump subroutine instruction}
|
||||
*
|
||||
* @param op the opcode for the specific type of JSR instruction,
|
||||
* @apiNote
|
||||
* The explicit {@code op} argument allows creating {@link Opcode#JSR_W
|
||||
* jsr_w} instructions to avoid short jumps.
|
||||
*
|
||||
* @param op the opcode for the specific type of jump subroutine instruction,
|
||||
* which must be of kind {@link Opcode.Kind#DISCONTINUED_JSR}
|
||||
* @param target target label of the subroutine
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
@@ -76,7 +102,7 @@ public sealed interface DiscontinuedInstruction extends Instruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return a JSR instruction}
|
||||
* {@return a jump subroutine instruction}
|
||||
*
|
||||
* @param target target label of the subroutine
|
||||
*/
|
||||
@@ -86,12 +112,26 @@ public sealed interface DiscontinuedInstruction extends Instruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Models RET and RET_W instructions discontinued from the {@code code}
|
||||
* array of a {@code Code} attribute since class file version 51.0.
|
||||
* Corresponding opcodes will have a {@code kind} of
|
||||
* Models return from subroutine instructions discontinued from the {@code
|
||||
* code} array of a {@code Code} attribute since class file major version
|
||||
* {@value ClassFile#JAVA_7_VERSION} (JVMS {@jvms 4.9.1}).
|
||||
* Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
|
||||
* {@link Opcode.Kind#DISCONTINUED_RET}. Delivered as a {@link CodeElement}
|
||||
* when traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A return from subroutine instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="RetInstruction" target="#of(int)" :
|
||||
* RetInstruction(int slot) // @link substring="slot" target="#slot()"
|
||||
* }
|
||||
* where {@code slot} must be within {@code [0, 65535]}.
|
||||
* <p>
|
||||
* {@link StoreInstruction astore} series of instructions store a {@link
|
||||
* TypeKind##returnAddress returnAddress} value to a local variable slot,
|
||||
* making the slot usable by a return from subroutine instruction.
|
||||
*
|
||||
* @jvms 6.5.ret <em>ret</em>
|
||||
* @see Opcode.Kind#DISCONTINUED_RET
|
||||
* @since 24
|
||||
*/
|
||||
sealed interface RetInstruction extends DiscontinuedInstruction
|
||||
@@ -100,13 +140,23 @@ public sealed interface DiscontinuedInstruction extends Instruction {
|
||||
|
||||
/**
|
||||
* {@return the local variable slot with return address}
|
||||
* The value is within {@code [0, 65535]}.
|
||||
*/
|
||||
int slot();
|
||||
|
||||
/**
|
||||
* {@return a RET or RET_W instruction}
|
||||
* {@return a return from subroutine instruction}
|
||||
* <p>
|
||||
* {@code slot} must be in the closed range of {@code [0, 255]} for
|
||||
* {@link Opcode#RET ret}, or within {@code [0, 65535]} for {@link
|
||||
* Opcode#RET_W wide ret}.
|
||||
*
|
||||
* @param op the opcode for the specific type of RET instruction,
|
||||
* @apiNote
|
||||
* The explicit {@code op} argument allows creating {@code wide ret}
|
||||
* instructions with {@code slot} in the range of regular {@code ret}
|
||||
* instructions.
|
||||
*
|
||||
* @param op the opcode for the specific type of return from subroutine instruction,
|
||||
* which must be of kind {@link Opcode.Kind#DISCONTINUED_RET}
|
||||
* @param slot the local variable slot to load return address from
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
@@ -118,7 +168,9 @@ public sealed interface DiscontinuedInstruction extends Instruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return a RET instruction}
|
||||
* {@return a return from subroutine instruction}
|
||||
* <p>
|
||||
* {@code slot} must be within {@code [0, 65535]}.
|
||||
*
|
||||
* @param slot the local variable slot to load return address from
|
||||
* @throws IllegalArgumentException if {@code slot} is out of range
|
||||
|
||||
@@ -24,23 +24,37 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.PseudoInstruction;
|
||||
import java.lang.classfile.attribute.CodeAttribute;
|
||||
import java.lang.classfile.constantpool.ClassEntry;
|
||||
import java.util.Optional;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractPseudoInstruction;
|
||||
|
||||
/**
|
||||
* A pseudo-instruction modeling an entry in the exception table of a code
|
||||
* attribute. Entries in the exception table model catch and finally blocks.
|
||||
* Delivered as a {@link CodeElement} when traversing the contents
|
||||
* of a {@link CodeModel}.
|
||||
*
|
||||
* @see PseudoInstruction
|
||||
* A pseudo-instruction modeling an entry in the {@code exception_table} array
|
||||
* of a {@link CodeAttribute Code} attribute. Catch (JVMS {@jvms 3.12}) and
|
||||
* finally (JVMS {@jvms 3.14}) blocks in Java source code compile to exception
|
||||
* table entries. Delivered as a {@link CodeElement} when traversing the
|
||||
* contents of a {@link CodeModel}.
|
||||
* <p>
|
||||
* An exception table entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="ExceptionCatch" target="#of(Label, Label, Label, Optional)" :
|
||||
* ExceptionCatch(
|
||||
* Label handler, // @link substring="handler" target="#handler"
|
||||
* Label tryStart, // @link substring="tryStart" target="#tryStart"
|
||||
* Label tryEnd, // @link substring="tryEnd" target="#tryEnd"
|
||||
* Optional<ClassEntry> catchType // @link substring="catchType" target="#catchType"
|
||||
* )
|
||||
* }
|
||||
*
|
||||
* @see CodeBuilder#exceptionCatch CodeBuilder::exceptionCatch
|
||||
* @jvms 4.7.3 The {@code Code} Attribute
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface ExceptionCatch extends PseudoInstruction
|
||||
@@ -61,8 +75,8 @@ public sealed interface ExceptionCatch extends PseudoInstruction
|
||||
Label tryEnd();
|
||||
|
||||
/**
|
||||
* {@return the type of the exception to catch, or empty if this handler is
|
||||
* unconditional}
|
||||
* {@return the type of the exception to catch, or empty if this handler
|
||||
* catches everything}
|
||||
*/
|
||||
Optional<ClassEntry> catchType();
|
||||
|
||||
@@ -80,10 +94,10 @@ public sealed interface ExceptionCatch extends PseudoInstruction
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return an exception table pseudo-instruction for an unconditional handler}
|
||||
* {@return an exception table pseudo-instruction to catch everything}
|
||||
* @param handler the handler for the exception
|
||||
* @param tryStart the beginning of the instruction range for the gaurded instructions
|
||||
* @param tryEnd the end of the instruction range for the gaurded instructions
|
||||
* @param tryStart the beginning of the instruction range for the guarded instructions
|
||||
* @param tryEnd the end of the instruction range for the guarded instructions
|
||||
*/
|
||||
static ExceptionCatch of(Label handler, Label tryStart, Label tryEnd) {
|
||||
return new AbstractPseudoInstruction.ExceptionCatchImpl(handler, tryStart, tryEnd, (ClassEntry) null);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
@@ -40,10 +41,21 @@ import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a field access instruction in the {@code code} array of a {@code Code}
|
||||
* attribute. Corresponding opcodes will have a {@code kind} of {@link
|
||||
* Opcode.Kind#FIELD_ACCESS}. Delivered as a {@link CodeElement} when
|
||||
* attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind}
|
||||
* of {@link Opcode.Kind#FIELD_ACCESS}. Delivered as a {@link CodeElement} when
|
||||
* traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A field access instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="FieldInstruction" target="#of(Opcode, FieldRefEntry)" :
|
||||
* FieldInstruction(
|
||||
* Opcode opcode, // @link substring="opcode" target="#opcode()"
|
||||
* FieldRefEntry field, // @link substring="field" target="#field()"
|
||||
* )
|
||||
* }
|
||||
*
|
||||
* @see Opcode.Kind#FIELD_ACCESS
|
||||
* @see CodeBuilder#fieldAccess CodeBuilder::fieldAccess
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface FieldInstruction extends Instruction
|
||||
@@ -68,7 +80,11 @@ public sealed interface FieldInstruction extends Instruction
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the field descriptor of the field}
|
||||
* {@return the field descriptor string of the field}
|
||||
*
|
||||
* @apiNote
|
||||
* A symbolic descriptor for the type of the field is available through
|
||||
* {@link #typeSymbol() typeSymbol()}.
|
||||
*/
|
||||
default Utf8Entry type() {
|
||||
return field().nameAndType().type();
|
||||
@@ -103,6 +119,8 @@ public sealed interface FieldInstruction extends Instruction
|
||||
* @param owner the class holding the field
|
||||
* @param name the name of the field
|
||||
* @param type the field descriptor
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
* {@link Opcode.Kind#FIELD_ACCESS}.
|
||||
*/
|
||||
static FieldInstruction of(Opcode op,
|
||||
ClassEntry owner,
|
||||
@@ -118,6 +136,8 @@ public sealed interface FieldInstruction extends Instruction
|
||||
* which must be of kind {@link Opcode.Kind#FIELD_ACCESS}
|
||||
* @param owner the class holding the field
|
||||
* @param nameAndType the name and field descriptor of the field
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
* {@link Opcode.Kind#FIELD_ACCESS}.
|
||||
*/
|
||||
static FieldInstruction of(Opcode op,
|
||||
ClassEntry owner,
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
@@ -33,10 +34,27 @@ import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
|
||||
/**
|
||||
* Models a local variable increment instruction in the {@code code} array of a
|
||||
* {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
|
||||
* {@link Opcode.Kind#INCREMENT}. Delivered as a {@link CodeElement} when
|
||||
* {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind()
|
||||
* kind} of {@link Opcode.Kind#INCREMENT}. Delivered as a {@link CodeElement} when
|
||||
* traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A local variable increment instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="IncrementInstruction" target="#of" :
|
||||
* IncrementInstruction(
|
||||
* int slot, // @link substring="slot" target="#slot()"
|
||||
* int constant // @link substring="constant" target="#constant()"
|
||||
* )
|
||||
* }
|
||||
* where
|
||||
* <ul>
|
||||
* <li>{@code slot} must be within {@code [0, 65535]}.
|
||||
* <li>{@code constant} must be within {@code [-32768, 32767]}.
|
||||
* </ul>
|
||||
*
|
||||
* @see Opcode.Kind#INCREMENT
|
||||
* @see CodeBuilder#iinc CodeBuilder::iinc
|
||||
* @jvms 6.5.iinc <em>iinc</em>
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface IncrementInstruction extends Instruction
|
||||
@@ -54,6 +72,10 @@ public sealed interface IncrementInstruction extends Instruction
|
||||
|
||||
/**
|
||||
* {@return an increment instruction}
|
||||
* <ul>
|
||||
* <li>{@code slot} must be within {@code [0, 65535]}.
|
||||
* <li>{@code constant} must be within {@code [-32768, 32767]}.
|
||||
* </ul>
|
||||
*
|
||||
* @param slot the local variable slot to increment
|
||||
* @param constant the value to increment by
|
||||
|
||||
@@ -24,9 +24,11 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.lang.classfile.constantpool.InvokeDynamicEntry;
|
||||
import java.lang.classfile.constantpool.LoadableConstantEntry;
|
||||
import java.lang.classfile.constantpool.Utf8Entry;
|
||||
@@ -40,10 +42,20 @@ import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models an {@code invokedynamic} instruction in the {@code code} array of a
|
||||
* {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
|
||||
* the elements of a {@link CodeModel}.
|
||||
* Models a dynamically-computed call site invocation instruction in the
|
||||
* {@code code} array of a {@code Code} attribute. The corresponding opcode is
|
||||
* {@link Opcode#INVOKEDYNAMIC invokedynamic}. Delivered as a {@link
|
||||
* CodeElement} when traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A dynamically-computed call site invocation instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="InvokeDynamicInstruction" target="#of" :
|
||||
* InvokeDynamicInstruction(InvokeDynamicEntry invokedynamic) // @link substring="invokedynamic" target="#invokedynamic()"
|
||||
* }
|
||||
*
|
||||
* @see Opcode.Kind#INVOKE_DYNAMIC
|
||||
* @see CodeBuilder#invokedynamic CodeBuilder::invokedynamic
|
||||
* @jvms 6.5.invokedynamic <em>invokedynamic</em>
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface InvokeDynamicInstruction extends Instruction
|
||||
@@ -62,6 +74,10 @@ public sealed interface InvokeDynamicInstruction extends Instruction
|
||||
|
||||
/**
|
||||
* {@return the invocation type of the call site}
|
||||
*
|
||||
* @apiNote
|
||||
* A symbolic descriptor for the invocation typeis available through {@link
|
||||
* #typeSymbol() typeSymbol()}.
|
||||
*/
|
||||
default Utf8Entry type() {
|
||||
return invokedynamic().type();
|
||||
|
||||
@@ -24,10 +24,12 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.lang.classfile.TypeKind;
|
||||
import java.lang.classfile.constantpool.ClassEntry;
|
||||
import java.lang.classfile.constantpool.InterfaceMethodRefEntry;
|
||||
import java.lang.classfile.constantpool.MemberRefEntry;
|
||||
@@ -42,10 +44,26 @@ import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a method invocation instruction in the {@code code} array of a {@code
|
||||
* Code} attribute, other than {@code invokedynamic}. Corresponding opcodes
|
||||
* will have a {@code kind} of {@link Opcode.Kind#INVOKE}. Delivered as a
|
||||
* {@link CodeElement} when traversing the elements of a {@link CodeModel}.
|
||||
* Code} attribute, other than {@link InvokeDynamicInstruction invokedynamic}.
|
||||
* Corresponding opcodes have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#INVOKE}.
|
||||
* Delivered as a {@link CodeElement} when traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A method invocation instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="InvokeInstruction" target="#of(Opcode, MemberRefEntry)" :
|
||||
* InvokeInstruction(
|
||||
* Opcode opcode, // @link substring="opcode" target="#opcode()"
|
||||
* MethodRefEntry | InterfaceMethodRefEntry method) // @link substring="method" target="#method()"
|
||||
* )
|
||||
* }
|
||||
* where {@code method} must be an {@code InterfaceMethodRefEntry} for {@link
|
||||
* Opcode#INVOKEINTERFACE invokeinterface} opcode, and must be a {@code
|
||||
* MethodRefEntry} for {@link Opcode#INVOKEVIRTUAL invokevirtual} opcode.
|
||||
* {@link Opcode#INVOKESTATIC invokestatic} and {@link Opcode#INVOKESPECIAL
|
||||
* invokespecial} can have either type of entry for {@code method}.
|
||||
*
|
||||
* @see Opcode.Kind#INVOKE
|
||||
* @see CodeBuilder#invoke CodeBuilder::invoke
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface InvokeInstruction extends Instruction
|
||||
@@ -57,18 +75,25 @@ public sealed interface InvokeInstruction extends Instruction
|
||||
MemberRefEntry method();
|
||||
|
||||
/**
|
||||
* {@return whether the class holding the method is an interface}
|
||||
* {@return whether the class or interface holding the method is an interface}
|
||||
*/
|
||||
boolean isInterface();
|
||||
|
||||
/**
|
||||
* {@return the {@code count} value of an {@code invokeinterface} instruction, as defined in JVMS {@jvms 6.5}
|
||||
* or {@code 0} for {@code invokespecial}, {@code invokestatic} and {@code invokevirtual} instructions}
|
||||
* {@return the {@code count} value of an {@code invokeinterface} instruction,
|
||||
* or {@code 0} for other instructions}
|
||||
* <p>
|
||||
* For an {@code invokeinterface} instruction, this value must be equivalent
|
||||
* to the sum of {@linkplain TypeKind#slotSize() slot sizes} of all arguments
|
||||
* plus one, which is equal to the number of operand stack depth consumed by
|
||||
* this interface method invocation instruction.
|
||||
*
|
||||
* @jvms 6.5.invokeinterface <em>invokeinterface</em>
|
||||
*/
|
||||
int count();
|
||||
|
||||
/**
|
||||
* {@return the class holding the method}
|
||||
* {@return the class or interface holding the method}
|
||||
*/
|
||||
default ClassEntry owner() {
|
||||
return method().owner();
|
||||
@@ -82,7 +107,11 @@ public sealed interface InvokeInstruction extends Instruction
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the method descriptor of the method}
|
||||
* {@return the method descriptor string of the method}
|
||||
*
|
||||
* @apiNote
|
||||
* A symbolic descriptor for the type of the method is available through
|
||||
* {@link #typeSymbol() typeSymbol()}.
|
||||
*/
|
||||
default Utf8Entry type() {
|
||||
return method().nameAndType().type();
|
||||
@@ -95,7 +124,6 @@ public sealed interface InvokeInstruction extends Instruction
|
||||
return Util.methodTypeSymbol(method().type());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@return an invocation instruction}
|
||||
*
|
||||
@@ -103,7 +131,7 @@ public sealed interface InvokeInstruction extends Instruction
|
||||
* which must be of kind {@link Opcode.Kind#INVOKE}
|
||||
* @param method a constant pool entry describing the method
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
* {@link Opcode.Kind#INVOKE}.
|
||||
* {@link Opcode.Kind#INVOKE}
|
||||
*/
|
||||
static InvokeInstruction of(Opcode op, MemberRefEntry method) {
|
||||
Util.checkKind(op, Opcode.Kind.INVOKE);
|
||||
@@ -119,6 +147,8 @@ public sealed interface InvokeInstruction extends Instruction
|
||||
* @param name the name of the method
|
||||
* @param type the method descriptor
|
||||
* @param isInterface whether the class holding the method is an interface
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
* {@link Opcode.Kind#INVOKE}
|
||||
*/
|
||||
static InvokeInstruction of(Opcode op,
|
||||
ClassEntry owner,
|
||||
@@ -136,6 +166,8 @@ public sealed interface InvokeInstruction extends Instruction
|
||||
* @param owner the class holding the method
|
||||
* @param nameAndType the name and type of the method
|
||||
* @param isInterface whether the class holding the method is an interface
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
* {@link Opcode.Kind#INVOKE}
|
||||
*/
|
||||
static InvokeInstruction of(Opcode op,
|
||||
ClassEntry owner,
|
||||
|
||||
@@ -24,10 +24,13 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.CodeTransform;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.PseudoInstruction;
|
||||
import java.lang.classfile.attribute.CodeAttribute;
|
||||
|
||||
import jdk.internal.classfile.impl.LabelImpl;
|
||||
|
||||
@@ -35,9 +38,28 @@ import jdk.internal.classfile.impl.LabelImpl;
|
||||
* A pseudo-instruction which indicates that the specified label corresponds to
|
||||
* the current position in the {@code Code} attribute. Delivered as a {@link
|
||||
* CodeElement} during traversal of the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* This can be used to inspect the target position of labels across {@linkplain
|
||||
* CodeTransform transformations}, as {@linkplain CodeAttribute#labelToBci bci}
|
||||
* is not stable.
|
||||
* <p>
|
||||
* When passed to a {@link CodeBuilder}, this pseudo-instruction sets the
|
||||
* specified label to be bound at the current position in the builder.
|
||||
* <p>
|
||||
* By design, {@code LabelTarget} cannot be created by users and can only be
|
||||
* read from a code model. Use {@link CodeBuilder#labelBinding
|
||||
* CodeBuilder::labelBinding} to bind arbitrary labels to a {@code CodeBuilder}.
|
||||
* <p>
|
||||
* For a {@code CodeBuilder cob}, a {@code LabelTarget lt}, these two calls are
|
||||
* equivalent:
|
||||
* {@snippet lang=java :
|
||||
* cob.with(lt); // @link substring="with" target="CodeBuilder#with"
|
||||
* // @link substring="labelBinding" target="CodeBuilder#labelBinding" :
|
||||
* cob.labelBinding(lt.label()); // @link substring="label" target="#label"
|
||||
* }
|
||||
*
|
||||
* @see PseudoInstruction
|
||||
*
|
||||
* @see Label
|
||||
* @see CodeBuilder#labelBinding CodeBuilder::labelBinding
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface LabelTarget extends PseudoInstruction
|
||||
|
||||
@@ -25,21 +25,42 @@
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.PseudoInstruction;
|
||||
import java.lang.classfile.attribute.CodeAttribute;
|
||||
import java.lang.classfile.attribute.LineNumberInfo;
|
||||
import java.lang.classfile.attribute.LineNumberTableAttribute;
|
||||
|
||||
import jdk.internal.classfile.impl.LineNumberImpl;
|
||||
|
||||
/**
|
||||
* A pseudo-instruction which models a single entry in the
|
||||
* {@link LineNumberTableAttribute}. Delivered as a {@link CodeElement}
|
||||
* during traversal of the elements of a {@link CodeModel}, according to
|
||||
* the setting of the {@link ClassFile.LineNumbersOption} option.
|
||||
* A pseudo-instruction which indicates the code for a given line number starts
|
||||
* after the current position in a {@link CodeAttribute Code} attribute. This
|
||||
* models a single entry in the {@link LineNumberTableAttribute LineNumberTable}
|
||||
* attribute. Delivered as a {@link CodeElement} during traversal of the
|
||||
* elements of a {@link CodeModel}, according to the setting of the {@link
|
||||
* ClassFile.LineNumbersOption} option.
|
||||
* <p>
|
||||
* A line number entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="LineNumber" target="#of" :
|
||||
* LineNumber(int line) // @link substring="int line" target="#line"
|
||||
* }
|
||||
* <p>
|
||||
* Another model, {@link LineNumberInfo}, also models a line number entry; it
|
||||
* has no dependency on a {@code CodeModel} and represents of bci values as
|
||||
* {@code int}s instead of order of pseudo-instructions in the elements of a
|
||||
* {@code CodeModel}, and is used as components of a {@link LineNumberTableAttribute}.
|
||||
*
|
||||
* @see PseudoInstruction
|
||||
* @apiNote
|
||||
* Line numbers are represented with custom pseudo-instructions to avoid using
|
||||
* labels, which usually indicate branching targets for the control flow.
|
||||
*
|
||||
* @see LineNumberInfo
|
||||
* @see CodeBuilder#lineNumber CodeBuilder::lineNumber
|
||||
* @see ClassFile.LineNumbersOption
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface LineNumber extends PseudoInstruction
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
@@ -36,10 +37,23 @@ import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a local variable load instruction in the {@code code} array of a
|
||||
* {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
|
||||
* {@link Opcode.Kind#LOAD}. Delivered as a {@link CodeElement} when
|
||||
* traversing the elements of a {@link CodeModel}.
|
||||
* {@code Code} attribute. Corresponding opcodes have a {@linkplain
|
||||
* Opcode#kind() kind} of {@link Opcode.Kind#LOAD}. Delivered as a {@link
|
||||
* CodeElement} when traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A local variable load instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="LoadInstruction" target="#of(TypeKind, int)" :
|
||||
* LoadInstruction(
|
||||
* TypeKind typeKind, // @link substring="typeKind" target="#typeKind"
|
||||
* int slot // @link substring="slot" target="#slot"
|
||||
* )
|
||||
* }
|
||||
* where {@code TypeKind} is {@linkplain TypeKind##computational-type
|
||||
* computational}, and {@code slot} is within {@code [0, 65535]}.
|
||||
*
|
||||
* @see Opcode.Kind#LOAD
|
||||
* @see CodeBuilder#loadLocal CodeBuilder::loadLocal
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface LoadInstruction extends Instruction
|
||||
@@ -48,16 +62,21 @@ public sealed interface LoadInstruction extends Instruction
|
||||
|
||||
/**
|
||||
* {@return the local variable slot to load from}
|
||||
* The value is within {@code [0, 65535]}.
|
||||
*/
|
||||
int slot();
|
||||
|
||||
/**
|
||||
* {@return the type of the value to be loaded}
|
||||
* {@return the {@linkplain TypeKind##computational-type computational type}
|
||||
* of the value to be loaded}
|
||||
*/
|
||||
TypeKind typeKind();
|
||||
|
||||
/**
|
||||
* {@return a local variable load instruction}
|
||||
* {@code kind} is {@linkplain TypeKind#asLoadable() converted} to its
|
||||
* computational type.
|
||||
* {@code slot} must be within {@code [0, 65535]}.
|
||||
*
|
||||
* @param kind the type of the value to be loaded
|
||||
* @param slot the local variable slot to load from
|
||||
@@ -71,6 +90,20 @@ public sealed interface LoadInstruction extends Instruction
|
||||
|
||||
/**
|
||||
* {@return a local variable load instruction}
|
||||
* <p>
|
||||
* The range of {@code slot} is restricted by the {@code op} and its
|
||||
* {@linkplain Opcode#sizeIfFixed() size}:
|
||||
* <ul>
|
||||
* <li>If {@code op} has size 1, {@code slot} must be exactly the slot value
|
||||
* implied by the opcode.
|
||||
* <li>If {@code op} has size 2, {@code slot} must be within {@code [0, 255]}.
|
||||
* <li>If {@code op} has size 4, {@code slot} must be within {@code [0, 65535]}.
|
||||
* </ul>
|
||||
*
|
||||
* @apiNote
|
||||
* The explicit {@code op} argument allows creating {@code wide} or
|
||||
* regular load instructions when the {@code slot} can be encoded
|
||||
* with more optimized load instructions.
|
||||
*
|
||||
* @param op the opcode for the specific type of load instruction,
|
||||
* which must be of kind {@link Opcode.Kind#LOAD}
|
||||
|
||||
@@ -25,10 +25,12 @@
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.PseudoInstruction;
|
||||
import java.lang.classfile.attribute.LocalVariableInfo;
|
||||
import java.lang.classfile.attribute.LocalVariableTableAttribute;
|
||||
import java.lang.classfile.constantpool.Utf8Entry;
|
||||
import java.lang.constant.ClassDesc;
|
||||
@@ -39,19 +41,45 @@ import jdk.internal.classfile.impl.TemporaryConstantPool;
|
||||
import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* A pseudo-instruction which models a single entry in the
|
||||
* {@link LocalVariableTableAttribute}. Delivered as a {@link CodeElement}
|
||||
* during traversal of the elements of a {@link CodeModel}, according to
|
||||
* the setting of the {@link ClassFile.DebugElementsOption} option.
|
||||
* A pseudo-instruction which models a single entry in the {@link
|
||||
* LocalVariableTableAttribute LocalVariableTable} attribute. Delivered as a
|
||||
* {@link CodeElement} during traversal of the elements of a {@link CodeModel},
|
||||
* according to the setting of the {@link ClassFile.DebugElementsOption} option.
|
||||
* <p>
|
||||
* A local variable entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="LocalVariable" target="#of(int, String, ClassDesc, Label, Label)" :
|
||||
* LocalVariable(
|
||||
* int slot, // @link substring="slot" target="#slot"
|
||||
* String name, // @link substring="name" target="#name"
|
||||
* ClassDesc type, // @link substring="type" target="#type"
|
||||
* Label startScope, // @link substring="startScope" target="#startScope"
|
||||
* Label endScope // @link substring="endScope" target="#endScope"
|
||||
* )
|
||||
* }
|
||||
* Where {@code slot} is within {@code [0, 65535]}.
|
||||
* <p>
|
||||
* Another model, {@link LocalVariableInfo}, also models a local variable
|
||||
* entry; it has no dependency on a {@code CodeModel} and represents of bci
|
||||
* values as {@code int}s instead of {@code Label}s, and is used as components
|
||||
* of a {@link LocalVariableTableAttribute}.
|
||||
*
|
||||
* @see PseudoInstruction
|
||||
* @apiNote
|
||||
* {@code LocalVariable} is used for all local variables in Java source code.
|
||||
* If a local variable has a parameterized type, a type argument, or an array
|
||||
* type of one of the previous types, a {@link LocalVariableType} should be
|
||||
* created for that local variable as well.
|
||||
*
|
||||
* @see LocalVariableInfo
|
||||
* @see CodeBuilder#localVariable CodeBuilder::localVariable
|
||||
* @see ClassFile.DebugElementsOption
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface LocalVariable extends PseudoInstruction
|
||||
permits AbstractPseudoInstruction.UnboundLocalVariable, BoundLocalVariable {
|
||||
/**
|
||||
* {@return the local variable slot}
|
||||
* The value is within {@code [0, 65535]}.
|
||||
*/
|
||||
int slot();
|
||||
|
||||
@@ -61,7 +89,11 @@ public sealed interface LocalVariable extends PseudoInstruction
|
||||
Utf8Entry name();
|
||||
|
||||
/**
|
||||
* {@return the local variable field descriptor}
|
||||
* {@return the local variable field descriptor string}
|
||||
*
|
||||
* @apiNote
|
||||
* A symbolic descriptor for the type of the local variable is available
|
||||
* through {@link #typeSymbol() typeSymbol()}.
|
||||
*/
|
||||
Utf8Entry type();
|
||||
|
||||
@@ -84,6 +116,7 @@ public sealed interface LocalVariable extends PseudoInstruction
|
||||
|
||||
/**
|
||||
* {@return a local variable pseudo-instruction}
|
||||
* {@code slot} must be within {@code [0, 65535]}.
|
||||
*
|
||||
* @param slot the local variable slot
|
||||
* @param nameEntry the local variable name
|
||||
@@ -99,6 +132,7 @@ public sealed interface LocalVariable extends PseudoInstruction
|
||||
|
||||
/**
|
||||
* {@return a local variable pseudo-instruction}
|
||||
* {@code slot} must be within {@code [0, 65535]}.
|
||||
*
|
||||
* @param slot the local variable slot
|
||||
* @param name the local variable name
|
||||
|
||||
@@ -24,12 +24,8 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.PseudoInstruction;
|
||||
import java.lang.classfile.Signature;
|
||||
import java.lang.classfile.*;
|
||||
import java.lang.classfile.attribute.LocalVariableTypeInfo;
|
||||
import java.lang.classfile.attribute.LocalVariableTypeTableAttribute;
|
||||
import java.lang.classfile.constantpool.Utf8Entry;
|
||||
|
||||
@@ -39,16 +35,44 @@ import jdk.internal.classfile.impl.TemporaryConstantPool;
|
||||
|
||||
/**
|
||||
* A pseudo-instruction which models a single entry in the {@link
|
||||
* LocalVariableTypeTableAttribute}. Delivered as a {@link CodeElement} during
|
||||
* traversal of the elements of a {@link CodeModel}, according to the setting of
|
||||
* the {@link ClassFile.DebugElementsOption} option.
|
||||
* LocalVariableTypeTableAttribute LocalVariableTypeTable} attribute. Delivered
|
||||
* as a {@link CodeElement} during traversal of the elements of a {@link CodeModel},
|
||||
* according to the setting of the {@link ClassFile.DebugElementsOption} option.
|
||||
* <p>
|
||||
* A local variable type entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="LocalVariableType" target="#of(int, String, Signature, Label, Label)" :
|
||||
* LocalVariableType(
|
||||
* int slot, // @link substring="slot" target="#slot"
|
||||
* String name, // @link substring="name" target="#name"
|
||||
* Signature signature, // @link substring="signature" target="#signatureSymbol"
|
||||
* Label startScope, // @link substring="startScope" target="#startScope"
|
||||
* Label endScope // @link substring="endScope" target="#endScope"
|
||||
* )
|
||||
* }
|
||||
* Where {@code slot} is within {@code [0, 65535]}.
|
||||
* <p>
|
||||
* Another model, {@link LocalVariableTypeInfo}, also models a local variable
|
||||
* type entry; it has no dependency on a {@code CodeModel} and represents of bci
|
||||
* values as {@code int}s instead of {@code Label}s, and is used as components
|
||||
* of a {@link LocalVariableTypeTableAttribute}.
|
||||
*
|
||||
* @apiNote
|
||||
* {@code LocalVariableType} is used if a local variable has a parameterized
|
||||
* type, a type argument, or an array type of one of the previous types as its
|
||||
* type. A {@link LocalVariable} with the erased type should still be created
|
||||
* for that local variable.
|
||||
*
|
||||
* @see LocalVariableTypeInfo
|
||||
* @see CodeBuilder#localVariableType CodeBuilder::localVariableType
|
||||
* @see ClassFile.DebugElementsOption
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface LocalVariableType extends PseudoInstruction
|
||||
permits AbstractPseudoInstruction.UnboundLocalVariableType, BoundLocalVariableType {
|
||||
/**
|
||||
* {@return the local variable slot}
|
||||
* The value is within {@code [0, 65535]}.
|
||||
*/
|
||||
int slot();
|
||||
|
||||
@@ -58,12 +82,16 @@ public sealed interface LocalVariableType extends PseudoInstruction
|
||||
Utf8Entry name();
|
||||
|
||||
/**
|
||||
* {@return the local variable signature}
|
||||
* {@return the local variable generic signature string}
|
||||
*
|
||||
* @apiNote
|
||||
* A symbolic generic signature of the local variable is available
|
||||
* through {@link #signatureSymbol() signatureSymbol()}.
|
||||
*/
|
||||
Utf8Entry signature();
|
||||
|
||||
/**
|
||||
* {@return the local variable signature}
|
||||
* {@return the local variable generic signature}
|
||||
*/
|
||||
default Signature signatureSymbol() {
|
||||
return Signature.parseFrom(signature().stringValue());
|
||||
@@ -81,6 +109,7 @@ public sealed interface LocalVariableType extends PseudoInstruction
|
||||
|
||||
/**
|
||||
* {@return a local variable type pseudo-instruction}
|
||||
* {@code slot} must be within {@code [0, 65535]}.
|
||||
*
|
||||
* @param slot the local variable slot
|
||||
* @param nameEntry the local variable name
|
||||
@@ -96,6 +125,7 @@ public sealed interface LocalVariableType extends PseudoInstruction
|
||||
|
||||
/**
|
||||
* {@return a local variable type pseudo-instruction}
|
||||
* {@code slot} must be within {@code [0, 65535]}.
|
||||
*
|
||||
* @param slot the local variable slot
|
||||
* @param name the local variable name
|
||||
|
||||
@@ -24,19 +24,36 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
|
||||
/**
|
||||
* Models a {@code lookupswitch} instruction in the {@code code} array of a
|
||||
* {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
|
||||
* the elements of a {@link CodeModel}.
|
||||
* Models a {@link Opcode#LOOKUPSWITCH lookupswitch} instruction in the {@code
|
||||
* code} array of a {@code Code} attribute. Delivered as a {@link CodeElement}
|
||||
* when traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A lookup switch instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="LookupSwitchInstruction" target="#of" :
|
||||
* LookupSwitchInstruction(
|
||||
* Label defaultTarget, // @link substring="defaultTarget" target="#defaultTarget"
|
||||
* List<SwitchCase> cases // @link substring="cases" target="#cases()"
|
||||
* )
|
||||
* }
|
||||
* If elements in {@code cases} are not sorted ascending by their {@link
|
||||
* SwitchCase#caseValue caseValue}, a sorted version of the {@code cases} list
|
||||
* will be written instead.
|
||||
*
|
||||
* @see Opcode.Kind#LOOKUP_SWITCH
|
||||
* @see CodeBuilder#lookupswitch CodeBuilder::lookupswitch
|
||||
* @jvms 6.5.lookupswitch <em>lookupswitch</em>
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface LookupSwitchInstruction extends Instruction
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
@@ -33,9 +34,17 @@ import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a {@code monitorenter} or {@code monitorexit} instruction in the
|
||||
* {@code code} array of a {@code Code} attribute. Delivered as a {@link
|
||||
* CodeElement} when traversing the elements of a {@link CodeModel}.
|
||||
* Models a {@link Opcode#MONITORENTER monitorenter} or {@link Opcode#MONITOREXIT
|
||||
* monitorexit} instruction in the {@code code} array of a {@code Code} attribute.
|
||||
* Corresponding opcodes have a {@linkplain Opcode#kind() kind} of {@link
|
||||
* Opcode.Kind#MONITOR}. Delivered as a {@link CodeElement} when traversing the
|
||||
* elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A monitor instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="MonitorInstruction" target="#of(Opcode)" :
|
||||
* MonitorInstruction(Opcode opcode) // @link substring="opcode" target="#opcode"
|
||||
* }
|
||||
*
|
||||
* @since 24
|
||||
*/
|
||||
|
||||
@@ -24,19 +24,34 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.lang.classfile.constantpool.ClassEntry;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
import jdk.internal.classfile.impl.BytecodeHelpers;
|
||||
|
||||
/**
|
||||
* Models a {@code multianewarray} invocation instruction in the {@code code}
|
||||
* Models a {@link Opcode#MULTIANEWARRAY multianewarray} instruction in the {@code code}
|
||||
* array of a {@code Code} attribute. Delivered as a {@link CodeElement}
|
||||
* when traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A new multi-dimensional array instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="NewMultiArrayInstruction" target="#of" :
|
||||
* NewMultiArrayInstruction(
|
||||
* ClassEntry arrayType, // @link substring="arrayType" target="#arrayType"
|
||||
* int dimensions // @link substring="dimensions" target="#dimensions"
|
||||
* )
|
||||
* }
|
||||
* where the {@code arrayType} is an array class.
|
||||
*
|
||||
* @see Opcode.Kind#NEW_MULTI_ARRAY
|
||||
* @see CodeBuilder#multianewarray CodeBuilder::multianewarray
|
||||
* @jvms 6.5.multianewarray <em>multianewarray</em>
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface NewMultiArrayInstruction extends Instruction
|
||||
@@ -44,7 +59,7 @@ public sealed interface NewMultiArrayInstruction extends Instruction
|
||||
AbstractInstruction.UnboundNewMultidimensionalArrayInstruction {
|
||||
|
||||
/**
|
||||
* {@return the type of the array, as a symbolic descriptor}
|
||||
* {@return the type of the array}
|
||||
*/
|
||||
ClassEntry arrayType();
|
||||
|
||||
|
||||
@@ -24,18 +24,30 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.lang.classfile.constantpool.ClassEntry;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
|
||||
/**
|
||||
* Models a {@code new} instruction in the {@code code} array of a {@code Code}
|
||||
* Models a {@link Opcode#NEW new} instruction in the {@code code} array of a {@code Code}
|
||||
* attribute. Delivered as a {@link CodeElement} when traversing the elements
|
||||
* of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A new object instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="NewObjectInstruction" target="#of" :
|
||||
* NewObjectInstruction(ClassEntry className) // @link substring="className" target="#className"
|
||||
* }
|
||||
* where the {@code className} is a non-abstract class.
|
||||
*
|
||||
* @see Opcode.Kind#NEW_OBJECT
|
||||
* @see CodeBuilder#new_ CodeBuilder::new_
|
||||
* @jvms 6.5.new <em>new</em>
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface NewObjectInstruction extends Instruction
|
||||
|
||||
@@ -24,18 +24,30 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.lang.classfile.TypeKind;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
|
||||
/**
|
||||
* Models a {@code newarray} invocation instruction in the {@code code}
|
||||
* Models a {@link Opcode#NEWARRAY newarray} instruction in the {@code code}
|
||||
* array of a {@code Code} attribute. Delivered as a {@link CodeElement}
|
||||
* when traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A new primitive array instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="NewPrimitiveArrayInstruction" target="#of" :
|
||||
* NewPrimitiveArrayInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind"
|
||||
* }
|
||||
* where {@code typeKind} is primitive and not {@code void}.
|
||||
*
|
||||
* @see Opcode.Kind#NEW_PRIMITIVE_ARRAY
|
||||
* @see CodeBuilder#newarray CodeBuilder::newarray
|
||||
* @jvms 6.5.newarray <em>newarray</em>
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface NewPrimitiveArrayInstruction extends Instruction
|
||||
@@ -43,6 +55,10 @@ public sealed interface NewPrimitiveArrayInstruction extends Instruction
|
||||
AbstractInstruction.UnboundNewPrimitiveArrayInstruction {
|
||||
/**
|
||||
* {@return the component type of the array}
|
||||
*
|
||||
* @apiNote
|
||||
* The backing array code for this instruction is available through
|
||||
* {@link TypeKind#newarrayCode() typeKind().newarrayCode()}.
|
||||
*/
|
||||
TypeKind typeKind();
|
||||
|
||||
@@ -50,8 +66,9 @@ public sealed interface NewPrimitiveArrayInstruction extends Instruction
|
||||
* {@return a new primitive array instruction}
|
||||
*
|
||||
* @param typeKind the component type of the array
|
||||
* @throws IllegalArgumentException when the {@code typeKind} is not a legal
|
||||
* primitive array component type
|
||||
* @throws IllegalArgumentException when {@code typeKind} is not primitive
|
||||
* or is {@code void}
|
||||
* @see TypeKind#fromNewarrayCode(int) TypeKind::fromNewarrayCode
|
||||
*/
|
||||
static NewPrimitiveArrayInstruction of(TypeKind typeKind) {
|
||||
// Implicit null-check:
|
||||
|
||||
@@ -24,18 +24,29 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.lang.classfile.constantpool.ClassEntry;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
|
||||
/**
|
||||
* Models a {@code anewarray} invocation instruction in the {@code code}
|
||||
* Models a {@link Opcode#ANEWARRAY anewarray} instruction in the {@code code}
|
||||
* array of a {@code Code} attribute. Delivered as a {@link CodeElement}
|
||||
* when traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A new reference array instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="NewReferenceArrayInstruction" target="#of" :
|
||||
* NewReferenceArrayInstruction(ClassEntry componentType) // @link substring="componentType" target="#componentType"
|
||||
* }
|
||||
*
|
||||
* @see Opcode.Kind#NEW_REF_ARRAY
|
||||
* @see CodeBuilder#newarray CodeBuilder::anewarray
|
||||
* @jvms 6.5.anewarray <em>anewarray</em>
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface NewReferenceArrayInstruction extends Instruction
|
||||
|
||||
@@ -24,17 +24,23 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
import java.lang.classfile.Opcode;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
|
||||
/**
|
||||
* Models a {@code nop} invocation instruction in the {@code code}
|
||||
* Models a {@link Opcode#NOP nop} instruction in the {@code code}
|
||||
* array of a {@code Code} attribute. Delivered as a {@link CodeElement}
|
||||
* when traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A no-op instruction has no visible state.
|
||||
*
|
||||
* @see CodeBuilder#nop CodeBuilder::nop
|
||||
* @jvms 6.5.nop <em>nop</em>
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface NopInstruction extends Instruction
|
||||
|
||||
@@ -35,23 +35,31 @@ import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models an arithmetic operator instruction in the {@code code} array of a
|
||||
* {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
|
||||
* {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
|
||||
* {@link Opcode.Kind#OPERATOR}. Delivered as a {@link CodeElement} when
|
||||
* traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* An operator instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="OperatorInstruction" target="#of" :
|
||||
* OperatorInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()"
|
||||
* }
|
||||
*
|
||||
* @see Opcode.Kind#OPERATOR
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface OperatorInstruction extends Instruction
|
||||
permits AbstractInstruction.UnboundOperatorInstruction {
|
||||
/**
|
||||
* {@return the operand type of the instruction}
|
||||
* This is derived from the {@link #opcode opcode}.
|
||||
*/
|
||||
TypeKind typeKind();
|
||||
|
||||
/**
|
||||
* {@return an operator instruction}
|
||||
*
|
||||
* @param op the opcode for the specific type of array load instruction,
|
||||
* @param op the opcode for the specific type of operator instruction,
|
||||
* which must be of kind {@link Opcode.Kind#OPERATOR}
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
* {@link Opcode.Kind#OPERATOR}.
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
@@ -36,22 +37,35 @@ import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a return-from-method instruction in the {@code code} array of a
|
||||
* {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
|
||||
* {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
|
||||
* {@link Opcode.Kind#RETURN}. Delivered as a {@link CodeElement} when
|
||||
* traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A return-from-method instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="ReturnInstruction" target="#of(TypeKind)" :
|
||||
* ReturnInstruction(TypeKind typeKind) // @link substring="typeKind" target="#typeKind()"
|
||||
* }
|
||||
* where {@code typeKind} is {@linkplain TypeKind##computational-type
|
||||
* computational} or {@link TypeKind#VOID void}.
|
||||
*
|
||||
* @see Opcode.Kind#RETURN
|
||||
* @see CodeBuilder#return_(TypeKind) CodeBuilder::return_
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface ReturnInstruction extends Instruction
|
||||
permits AbstractInstruction.UnboundReturnInstruction {
|
||||
|
||||
/**
|
||||
* {@return the type of the return instruction}
|
||||
* {@return the {@linkplain TypeKind##computational-type computational type}, including
|
||||
* {@link TypeKind#VOID void}, of the return instruction}
|
||||
*/
|
||||
TypeKind typeKind();
|
||||
|
||||
/**
|
||||
* {@return a return instruction}
|
||||
* {@code typeKind} is {@linkplain TypeKind#asLoadable() converted} to its
|
||||
* computational type.
|
||||
*
|
||||
* @param typeKind the type of the return instruction
|
||||
*/
|
||||
|
||||
@@ -34,10 +34,17 @@ import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a stack manipulation instruction in the {@code code} array of a
|
||||
* {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
|
||||
* {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
|
||||
* {@link Opcode.Kind#STACK}. Delivered as a {@link CodeElement} when
|
||||
* traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A stack manipulation instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="StackInstruction" target="#of" :
|
||||
* StackInstruction(Opcode opcode) // @link substring="opcode" target="#opcode()"
|
||||
* }
|
||||
*
|
||||
* @see Opcode.Kind#STACK
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface StackInstruction extends Instruction
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
@@ -36,10 +37,28 @@ import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a local variable store instruction in the {@code code} array of a
|
||||
* {@code Code} attribute. Corresponding opcodes will have a {@code kind} of
|
||||
* {@code Code} attribute. Corresponding opcodes have a {@linkplain Opcode#kind() kind} of
|
||||
* {@link Opcode.Kind#STORE}. Delivered as a {@link CodeElement} when
|
||||
* traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A local variable store instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="StoreInstruction" target="#of(TypeKind, int)" :
|
||||
* StoreInstruction(
|
||||
* TypeKind typeKind, // @link substring="typeKind" target="#typeKind"
|
||||
* int slot // @link substring="slot" target="#slot"
|
||||
* )
|
||||
* }
|
||||
* where {@code TypeKind} is {@linkplain TypeKind##computational-type
|
||||
* computational}, and {@code slot} is within {@code [0, 65535]}.
|
||||
* <p>
|
||||
* {@code astore} series of instructions, or {@code reference} type store
|
||||
* instructions, can also operate on the {@link TypeKind##returnAddress
|
||||
* returnAddress} type from discontinued {@linkplain
|
||||
* DiscontinuedInstruction.JsrInstruction jump subroutine instructions}.
|
||||
*
|
||||
* @see Opcode.Kind#STORE
|
||||
* @see CodeBuilder#storeLocal CodeBuilder::storeLocal
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface StoreInstruction extends Instruction
|
||||
@@ -47,16 +66,23 @@ public sealed interface StoreInstruction extends Instruction
|
||||
|
||||
/**
|
||||
* {@return the local variable slot to store to}
|
||||
* The value is within {@code [0, 65535]}.
|
||||
*/
|
||||
int slot();
|
||||
|
||||
/**
|
||||
* {@return the type of the value to be stored}
|
||||
* {@return the {@linkplain TypeKind##computational-type computational type}
|
||||
* of the value to be stored} The {@link TypeKind#REFERENCE reference}
|
||||
* type store instructions also operate on the {@code returnAddress} type,
|
||||
* which does not apply to {@code reference} type load instructions.
|
||||
*/
|
||||
TypeKind typeKind();
|
||||
|
||||
/**
|
||||
* {@return a local variable store instruction}
|
||||
* {@code kind} is {@linkplain TypeKind#asLoadable() converted} to its
|
||||
* computational type.
|
||||
* {@code slot} must be within {@code [0, 65535]}.
|
||||
*
|
||||
* @param kind the type of the value to be stored
|
||||
* @param slot the local variable slot to store to
|
||||
@@ -70,6 +96,20 @@ public sealed interface StoreInstruction extends Instruction
|
||||
|
||||
/**
|
||||
* {@return a local variable store instruction}
|
||||
* <p>
|
||||
* The range of {@code slot} is restricted by the {@code op} and its
|
||||
* {@linkplain Opcode#sizeIfFixed() size}:
|
||||
* <ul>
|
||||
* <li>If {@code op} has size 1, {@code slot} must be exactly the slot value
|
||||
* implied by the opcode.
|
||||
* <li>If {@code op} has size 2, {@code slot} must be within {@code [0, 255]}.
|
||||
* <li>If {@code op} has size 4, {@code slot} must be within {@code [0, 65535]}.
|
||||
* </ul>
|
||||
*
|
||||
* @apiNote
|
||||
* The explicit {@code op} argument allows creating {@code wide} or
|
||||
* regular store instructions when the {@code slot} can be encoded
|
||||
* with more optimized store instructions.
|
||||
*
|
||||
* @param op the opcode for the specific type of store instruction,
|
||||
* which must be of kind {@link Opcode.Kind#STORE}
|
||||
|
||||
@@ -29,12 +29,20 @@ import java.lang.classfile.Label;
|
||||
import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
|
||||
/**
|
||||
* Models a single case in a {@code lookupswitch} or {@code tableswitch}
|
||||
* instruction.
|
||||
* Models a single case in a {@link LookupSwitchInstruction lookupswitch} or
|
||||
* {@link TableSwitchInstruction tableswitch} instruction.
|
||||
* <p>
|
||||
* A switch case is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="SwitchCase" target="#of" :
|
||||
* SwitchCase(
|
||||
* int caseValue, // @link substring="caseValue" target="#caseValue"
|
||||
* Label target // @link substring="target" target="#target"
|
||||
* )
|
||||
* }
|
||||
*
|
||||
* @see LookupSwitchInstruction
|
||||
* @see TableSwitchInstruction
|
||||
*
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface SwitchCase
|
||||
@@ -47,11 +55,10 @@ public sealed interface SwitchCase
|
||||
Label target();
|
||||
|
||||
/**
|
||||
* Create a {@linkplain SwitchCase}
|
||||
* {@return a new switch case}
|
||||
*
|
||||
* @param caseValue the integer value for the case
|
||||
* @param target the branch target for the case
|
||||
* @return the {@linkplain SwitchCase}
|
||||
*/
|
||||
static SwitchCase of(int caseValue, Label target) {
|
||||
return new AbstractInstruction.SwitchCaseImpl(caseValue, target);
|
||||
|
||||
@@ -24,19 +24,45 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
import java.lang.classfile.Label;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
|
||||
/**
|
||||
* Models a {@code tableswitch} instruction in the {@code code} array of a
|
||||
* Models a {@link Opcode#TABLESWITCH tableswitch} instruction in the {@code code} array of a
|
||||
* {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
|
||||
* the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A table switch instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="TableSwitchInstruction" target="#of" :
|
||||
* TableSwitchInstruction(
|
||||
* int lowValue, // @link substring="int lowValue" target="#lowValue"
|
||||
* int highValue, // @link substring="int highValue" target="#highValue"
|
||||
* Label defaultTarget, // @link substring="defaultTarget" target="#defaultTarget"
|
||||
* List<SwitchCase> cases // @link substring="cases" target="#cases()"
|
||||
* )
|
||||
* }
|
||||
* <p>
|
||||
* When read from {@code class} files, the {@code cases} may omit cases that
|
||||
* duplicate the default target. The list is sorted ascending by the {@link
|
||||
* SwitchCase#caseValue() caseValue}.
|
||||
* <p>
|
||||
* When writing to {@code class} file, the order in the {@code cases} list does
|
||||
* not matter, as there is only one valid order in the physical representation
|
||||
* of table switch entries. Treatment of elements in {@code cases} whose value
|
||||
* is less than {@code lowValue} or greater than {@code highValue}, and elements
|
||||
* whose value duplicates that of another, is not specified.
|
||||
*
|
||||
* @see Opcode.Kind#TABLE_SWITCH
|
||||
* @see CodeBuilder#tableswitch CodeBuilder::tableswitch
|
||||
* @jvms 6.5.tableswitch <em>tableswitch</em>
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface TableSwitchInstruction extends Instruction
|
||||
@@ -67,7 +93,8 @@ public sealed interface TableSwitchInstruction extends Instruction
|
||||
* @param lowValue the low value of the switch target range, inclusive
|
||||
* @param highValue the high value of the switch target range, inclusive
|
||||
* @param defaultTarget the default target of the switch
|
||||
* @param cases the cases of the switch
|
||||
* @param cases the cases of the switch; duplicate or out of bound case
|
||||
* handling is not specified
|
||||
*/
|
||||
static TableSwitchInstruction of(int lowValue, int highValue, Label defaultTarget, List<SwitchCase> cases) {
|
||||
return new AbstractInstruction.UnboundTableSwitchInstruction(lowValue, highValue, defaultTarget, cases);
|
||||
|
||||
@@ -24,17 +24,23 @@
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeElement;
|
||||
import java.lang.classfile.CodeModel;
|
||||
import java.lang.classfile.Instruction;
|
||||
import java.lang.classfile.Opcode;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractInstruction;
|
||||
|
||||
/**
|
||||
* Models an {@code athrow} instruction in the {@code code} array of a
|
||||
* Models an {@link Opcode#ATHROW athrow} instruction in the {@code code} array of a
|
||||
* {@code Code} attribute. Delivered as a {@link CodeElement} when traversing
|
||||
* the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* A throw instruction has no visible state.
|
||||
*
|
||||
* @see Opcode.Kind#THROW_EXCEPTION
|
||||
* @see CodeBuilder#athrow CodeBuiler::athrow
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface ThrowInstruction extends Instruction
|
||||
|
||||
@@ -36,9 +36,24 @@ import jdk.internal.classfile.impl.TemporaryConstantPool;
|
||||
import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models an {@code instanceof} or {@code checkcast} instruction in the {@code
|
||||
* code} array of a {@code Code} attribute. Delivered as a {@link CodeElement}
|
||||
* when traversing the elements of a {@link CodeModel}.
|
||||
* Models an {@link Opcode#INSTANCEOF instanceof} or a {@link Opcode#CHECKCAST checkcast}
|
||||
* instruction in the {@code code} array of a {@code Code} attribute. Corresponding
|
||||
* opcodes have a {@linkplain Opcode#kind() kind} of {@link Opcode.Kind#TYPE_CHECK}.
|
||||
* Delivered as a {@link CodeElement} when traversing the elements of a {@link CodeModel}.
|
||||
* <p>
|
||||
* An {@code instanceof} checks the type and pushes an integer to the operand stack.
|
||||
* A {@code checkcast} checks the type and throws a {@link ClassCastException} if
|
||||
* the check fails. {@code instanceof} treat the {@code null} reference as a
|
||||
* failure, while {@code checkcast} treat the {@code null} reference as a success.
|
||||
* <p>
|
||||
* A type check instruction is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="TypeCheckInstruction" target="#of(Opcode, ClassEntry)" :
|
||||
* TypeCheckInstruction(
|
||||
* Opcode opcode, // @link substring="opcode" target="#opcode"
|
||||
* ClassEntry type // @link substring="type" target="#type"
|
||||
* )
|
||||
* }
|
||||
*
|
||||
* @since 24
|
||||
*/
|
||||
@@ -47,7 +62,7 @@ public sealed interface TypeCheckInstruction extends Instruction
|
||||
AbstractInstruction.UnboundTypeCheckInstruction {
|
||||
|
||||
/**
|
||||
* {@return the type against which the instruction checks or casts}
|
||||
* {@return the type against which the instruction checks}
|
||||
*/
|
||||
ClassEntry type();
|
||||
|
||||
@@ -58,7 +73,7 @@ public sealed interface TypeCheckInstruction extends Instruction
|
||||
* which must be of kind {@link Opcode.Kind#TYPE_CHECK}
|
||||
* @param type the type against which to check or cast
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
* {@link Opcode.Kind#TYPE_CHECK}.
|
||||
* {@link Opcode.Kind#TYPE_CHECK}
|
||||
*/
|
||||
static TypeCheckInstruction of(Opcode op, ClassEntry type) {
|
||||
Util.checkKind(op, Opcode.Kind.TYPE_CHECK);
|
||||
@@ -71,6 +86,8 @@ public sealed interface TypeCheckInstruction extends Instruction
|
||||
* @param op the opcode for the specific type of type check instruction,
|
||||
* which must be of kind {@link Opcode.Kind#TYPE_CHECK}
|
||||
* @param type the type against which to check or cast
|
||||
* @throws IllegalArgumentException if the opcode kind is not
|
||||
* {@link Opcode.Kind#TYPE_CHECK}, or if {@code type} is primitive
|
||||
*/
|
||||
static TypeCheckInstruction of(Opcode op, ClassDesc type) {
|
||||
return of(op, TemporaryConstantPool.INSTANCE.classEntry(type));
|
||||
|
||||
@@ -26,9 +26,45 @@
|
||||
/**
|
||||
* <h2>Provides interfaces describing code instructions for the {@link java.lang.classfile} library.</h2>
|
||||
*
|
||||
* The {@code java.lang.classfile.attribute} package contains interfaces describing code instructions.
|
||||
* The {@code java.lang.classfile.instruction} package contains interfaces describing code instructions.
|
||||
* Implementations of these interfaces are immutable.
|
||||
* <p>
|
||||
* Unless otherwise specified, passing {@code null} or an array or collection containing a {@code null} element as an
|
||||
* argument to a constructor or method of any Class-File API class or interface will cause a {@link NullPointerException}
|
||||
* to be thrown.
|
||||
*
|
||||
* <h2 id="reading">Reading of instructions</h2>
|
||||
* Instructions and pseudo-instructions are usually accessed from a {@link CodeModel}, such as {@link CodeModel#forEach
|
||||
* CodeModel::forEach}, and categorized by pattern-matching.
|
||||
* <p>
|
||||
* When read from {@code class} files, instructions are lazily inflated; the contents of these instructions, besides the
|
||||
* bare structure, are not evaluated to speed up parsing. Instructions to users interest, such as those filtered by the
|
||||
* pattern matching, have their contents read on demand, to avoid unnecessary reading of unrelated instructions in a code
|
||||
* array.
|
||||
* <p>
|
||||
* Due to the lazy nature of {@code class} file parsing, {@link IllegalArgumentException} indicating malformed
|
||||
* {@code class} file data can be thrown at any method invocation. For example, an instruction object for a {@link
|
||||
* TypeCheckInstruction} may be obtained from a {@code CodeModel}, but the subsequent invocation of {@link
|
||||
* TypeCheckInstruction#type() .type()} may fail with {@code IllegalArgumentException} because the instruction refers
|
||||
* to a bad constant pool index.
|
||||
*
|
||||
* <h2 id="writing">Writing of instructions</h2>
|
||||
* Writing of instructions happen on {@link CodeBuilder}. The most basic way to write instructions is to pass an
|
||||
* instruction object to {@link CodeBuilder#with CodeBuilder::with}, which supports all valid instructions.
|
||||
* Yet, {@code CodeBuilder} provides a lot of {@linkplain CodeBuilder##instruction-factories convenience factory methods}
|
||||
* for easy creation of instructions, named by their mnemonic. These accessors are more concise, and often more
|
||||
* efficient at run-time than passing instruction objects.
|
||||
* <p>
|
||||
* Due to restrictions in the {@code class} file format, some instructions may not be representable in a {@code CodeBuilder}.
|
||||
* In some scenarios, such as for {@link BranchInstruction}, Class-File API options control if alternatives can be used
|
||||
* in code generation instead. Otherwise, they can be configured to fail-fast to ensure the parity of {@code CodeBuilder}
|
||||
* commands with the generated {@code code} array data.
|
||||
*
|
||||
* @jvms 6.5 Instructions
|
||||
* @since 24
|
||||
*/
|
||||
package java.lang.classfile.instruction;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.CodeModel;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
* @summary InvalidClassException is thrown when the canonical constructor
|
||||
* cannot be found during deserialization.
|
||||
* @library /test/lib
|
||||
* @enablePreview
|
||||
* @run testng BadCanonicalCtrTest
|
||||
*/
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
* @bug 8246774
|
||||
* @summary Basic tests for prohibited magic serialization methods
|
||||
* @library /test/lib
|
||||
* @enablePreview
|
||||
* @run testng ProhibitedMethods
|
||||
*/
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
* @bug 8246774
|
||||
* @summary Basic tests for prohibited magic serialPersistentFields
|
||||
* @library /test/lib
|
||||
* @enablePreview
|
||||
* @run testng SerialPersistentFieldsTest
|
||||
*/
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
/* @test
|
||||
* @bug 8057919
|
||||
* @summary Class.getSimpleName() should work for non-JLS compliant class names
|
||||
* @enablePreview
|
||||
*/
|
||||
|
||||
import java.lang.classfile.ClassBuilder;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
* @test
|
||||
* @bug 8140450
|
||||
* @summary Basic test for the StackWalker::getByteCodeIndex method
|
||||
* @enablePreview
|
||||
* @run main TestBCI
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
* @test
|
||||
* @bug 8230501
|
||||
* @library /test/lib
|
||||
* @enablePreview
|
||||
* @run testng/othervm ClassDataTest
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
/*
|
||||
* @test
|
||||
* @library /test/lib
|
||||
* @enablePreview
|
||||
* @build HiddenNestmateTest
|
||||
* @run testng/othervm HiddenNestmateTest
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @enablePreview
|
||||
* @modules java.base/jdk.internal.module
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.util.ModuleInfoWriter
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user