mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-19 23:11:42 +01:00
Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1495f7addb | ||
|
|
c141aa1e08 | ||
|
|
467f407037 | ||
|
|
f7858e2422 | ||
|
|
6965840e0d | ||
|
|
1399f253b0 | ||
|
|
f45a23cabd | ||
|
|
f42e2c10c6 | ||
|
|
57c46ac2fe | ||
|
|
24053d9b6a | ||
|
|
e76cc44502 | ||
|
|
4a623a2b6d | ||
|
|
ecdc322029 | ||
|
|
da74fbd920 | ||
|
|
f0a89c5d8e | ||
|
|
c61fbfd6ea | ||
|
|
92a4e23467 | ||
|
|
ba36d309c3 | ||
|
|
41630c5c32 | ||
|
|
864d0fde23 | ||
|
|
ff9b8e4607 | ||
|
|
7d4fa7818b | ||
|
|
c033806b8c | ||
|
|
bf45128055 | ||
|
|
29c6bf23fb | ||
|
|
c3b52089f6 | ||
|
|
860b30ddf9 | ||
|
|
256856a5a1 | ||
|
|
cc7c293bce | ||
|
|
33971ecb6e | ||
|
|
4254e99ce2 | ||
|
|
05c3769986 | ||
|
|
ab78b04cf6 | ||
|
|
bed040191b | ||
|
|
5d138cbba0 | ||
|
|
63aa68a7c6 | ||
|
|
f0ada9f34e | ||
|
|
303736b038 | ||
|
|
2c336299aa | ||
|
|
4aec2d4ef9 | ||
|
|
b8249c5d90 | ||
|
|
0225372e0b | ||
|
|
2cc14faa21 | ||
|
|
f703b6e7b1 | ||
|
|
297b21fb60 | ||
|
|
67b8251679 | ||
|
|
6e8aad1ad4 | ||
|
|
4d6eccd9fc | ||
|
|
6bc14d6b77 | ||
|
|
897a8abecc | ||
|
|
3b53ed7fb0 | ||
|
|
6fdfa72996 | ||
|
|
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) {}
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
|
||||
} else {
|
||||
fn = CAST_FROM_FN_PTR(address, StubRoutines::dsin());
|
||||
}
|
||||
__ call(fn);
|
||||
__ rt_call(fn);
|
||||
__ mv(ra, x9);
|
||||
break;
|
||||
case Interpreter::java_lang_math_cos :
|
||||
@@ -202,7 +202,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
|
||||
} else {
|
||||
fn = CAST_FROM_FN_PTR(address, StubRoutines::dcos());
|
||||
}
|
||||
__ call(fn);
|
||||
__ rt_call(fn);
|
||||
__ mv(ra, x9);
|
||||
break;
|
||||
case Interpreter::java_lang_math_tan :
|
||||
@@ -215,7 +215,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
|
||||
} else {
|
||||
fn = CAST_FROM_FN_PTR(address, StubRoutines::dtan());
|
||||
}
|
||||
__ call(fn);
|
||||
__ rt_call(fn);
|
||||
__ mv(ra, x9);
|
||||
break;
|
||||
case Interpreter::java_lang_math_log :
|
||||
@@ -228,7 +228,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
|
||||
} else {
|
||||
fn = CAST_FROM_FN_PTR(address, StubRoutines::dlog());
|
||||
}
|
||||
__ call(fn);
|
||||
__ rt_call(fn);
|
||||
__ mv(ra, x9);
|
||||
break;
|
||||
case Interpreter::java_lang_math_log10 :
|
||||
@@ -241,7 +241,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
|
||||
} else {
|
||||
fn = CAST_FROM_FN_PTR(address, StubRoutines::dlog10());
|
||||
}
|
||||
__ call(fn);
|
||||
__ rt_call(fn);
|
||||
__ mv(ra, x9);
|
||||
break;
|
||||
case Interpreter::java_lang_math_exp :
|
||||
@@ -254,7 +254,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
|
||||
} else {
|
||||
fn = CAST_FROM_FN_PTR(address, StubRoutines::dexp());
|
||||
}
|
||||
__ call(fn);
|
||||
__ rt_call(fn);
|
||||
__ mv(ra, x9);
|
||||
break;
|
||||
case Interpreter::java_lang_math_pow :
|
||||
@@ -268,7 +268,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
|
||||
} else {
|
||||
fn = CAST_FROM_FN_PTR(address, StubRoutines::dpow());
|
||||
}
|
||||
__ call(fn);
|
||||
__ rt_call(fn);
|
||||
__ mv(ra, x9);
|
||||
break;
|
||||
case Interpreter::java_lang_math_fmaD :
|
||||
|
||||
@@ -154,10 +154,6 @@ void VM_Version::common_initialize() {
|
||||
unaligned_access.value() != MISALIGNED_FAST);
|
||||
}
|
||||
|
||||
if (FLAG_IS_DEFAULT(AlignVector)) {
|
||||
FLAG_SET_DEFAULT(AlignVector, AvoidUnalignedAccesses);
|
||||
}
|
||||
|
||||
// See JDK-8026049
|
||||
// This machine has fast unaligned memory accesses
|
||||
if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) {
|
||||
@@ -440,6 +436,10 @@ void VM_Version::c2_initialize() {
|
||||
warning("AES/CTR intrinsics are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false);
|
||||
}
|
||||
|
||||
if (FLAG_IS_DEFAULT(AlignVector)) {
|
||||
FLAG_SET_DEFAULT(AlignVector, AvoidUnalignedAccesses);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // COMPILER2
|
||||
|
||||
@@ -308,6 +308,12 @@ void VM_Version::initialize() {
|
||||
if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
|
||||
FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true);
|
||||
}
|
||||
|
||||
// The OptoScheduling information is not maintained in s390.ad.
|
||||
if (OptoScheduling) {
|
||||
warning("OptoScheduling is not supported on this CPU.");
|
||||
FLAG_SET_DEFAULT(OptoScheduling, false);
|
||||
}
|
||||
#endif
|
||||
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
|
||||
FLAG_SET_DEFAULT(UsePopCountInstruction, true);
|
||||
@@ -323,12 +329,6 @@ void VM_Version::initialize() {
|
||||
if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) {
|
||||
FLAG_SET_DEFAULT(UseUnalignedAccesses, true);
|
||||
}
|
||||
|
||||
// The OptoScheduling information is not maintained in s390.ad.
|
||||
if (OptoScheduling) {
|
||||
warning("OptoScheduling is not supported on this CPU.");
|
||||
FLAG_SET_DEFAULT(OptoScheduling, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ enum platform_dependent_constants {
|
||||
// AVX512 intrinsics add more code in 64-bit VM,
|
||||
// Windows have more code to save/restore registers
|
||||
_compiler_stubs_code_size = 20000 LP64_ONLY(+47000) WINDOWS_ONLY(+2000),
|
||||
_final_stubs_code_size = 10000 LP64_ONLY(+20000) WINDOWS_ONLY(+2000) ZGC_ONLY(+20000)
|
||||
_final_stubs_code_size = 10000 LP64_ONLY(+20000) WINDOWS_ONLY(+22000) ZGC_ONLY(+20000)
|
||||
};
|
||||
|
||||
class x86 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -985,8 +986,10 @@ bool MetaspaceShared::try_link_class(JavaThread* current, InstanceKlass* ik) {
|
||||
ik->external_name());
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
SystemDictionaryShared::set_class_has_failed_verification(ik);
|
||||
} else {
|
||||
assert(!SystemDictionaryShared::has_class_failed_verification(ik), "sanity");
|
||||
ik->compute_has_loops_flag_for_methods();
|
||||
}
|
||||
ik->compute_has_loops_flag_for_methods();
|
||||
BytecodeVerificationLocal = saved;
|
||||
return true;
|
||||
} else {
|
||||
@@ -1486,6 +1489,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 +1537,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, 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
|
||||
@@ -205,7 +205,7 @@ void CodeCache::initialize_heaps() {
|
||||
const bool cache_size_set = FLAG_IS_CMDLINE(ReservedCodeCacheSize);
|
||||
const size_t ps = page_size(false, 8);
|
||||
const size_t min_size = MAX2(os::vm_allocation_granularity(), ps);
|
||||
const size_t min_cache_size = CompilerConfig::min_code_cache_size(); // Make sure we have enough space for VM internal code
|
||||
const size_t min_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3); // Make sure we have enough space for VM internal code
|
||||
size_t cache_size = align_up(ReservedCodeCacheSize, min_size);
|
||||
|
||||
// Prerequisites
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2010, 2025, 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
|
||||
@@ -455,7 +455,7 @@ void CompilationPolicy::initialize() {
|
||||
c2_size = C2Compiler::initial_code_buffer_size();
|
||||
#endif
|
||||
size_t buffer_size = c1_only ? c1_size : (c1_size/3 + 2*c2_size/3);
|
||||
int max_count = (ReservedCodeCacheSize - (int)CompilerConfig::min_code_cache_size()) / (int)buffer_size;
|
||||
int max_count = (ReservedCodeCacheSize - (CodeCacheMinimumUseSpace DEBUG_ONLY(* 3))) / (int)buffer_size;
|
||||
if (count > max_count) {
|
||||
// Lower the compiler count such that all buffers fit into the code cache
|
||||
count = MAX2(max_count, c1_only ? 1 : 2);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2025, 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
|
||||
@@ -475,7 +475,8 @@ void CompilerConfig::set_jvmci_specific_flags() {
|
||||
|
||||
bool CompilerConfig::check_args_consistency(bool status) {
|
||||
// Check lower bounds of the code cache
|
||||
size_t min_code_cache_size = CompilerConfig::min_code_cache_size();
|
||||
// Template Interpreter code is approximately 3X larger in debug builds.
|
||||
uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3);
|
||||
if (ReservedCodeCacheSize < InitialCodeCacheSize) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"Invalid ReservedCodeCacheSize: %dK. Must be at least InitialCodeCacheSize=%dK.\n",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2025, 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
|
||||
@@ -148,8 +148,6 @@ public:
|
||||
inline static bool is_c2_or_jvmci_compiler_only();
|
||||
inline static bool is_c2_or_jvmci_compiler_enabled();
|
||||
|
||||
inline static size_t min_code_cache_size();
|
||||
|
||||
private:
|
||||
static bool is_compilation_mode_selected();
|
||||
static void set_compilation_policy_flags();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2025, 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
|
||||
@@ -25,12 +25,6 @@
|
||||
#ifndef SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP
|
||||
#define SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP
|
||||
|
||||
#ifdef COMPILER1
|
||||
#include "c1/c1_Compiler.hpp"
|
||||
#endif
|
||||
#ifdef COMPILER2
|
||||
#include "opto/c2compiler.hpp"
|
||||
#endif
|
||||
#include "compiler/compilerDefinitions.hpp"
|
||||
|
||||
#include "compiler/compiler_globals.hpp"
|
||||
@@ -138,13 +132,4 @@ inline bool CompilerConfig::is_c2_or_jvmci_compiler_enabled() {
|
||||
return is_c2_enabled() || is_jvmci_compiler_enabled();
|
||||
}
|
||||
|
||||
inline size_t CompilerConfig::min_code_cache_size() {
|
||||
size_t min_code_cache_size = CodeCacheMinimumUseSpace;
|
||||
// Template Interpreter code is approximately 3X larger in debug builds.
|
||||
DEBUG_ONLY(min_code_cache_size *= 3);
|
||||
COMPILER1_PRESENT(min_code_cache_size += Compiler::code_buffer_size());
|
||||
COMPILER2_PRESENT(min_code_cache_size += C2Compiler::initial_code_buffer_size());
|
||||
return min_code_cache_size;
|
||||
}
|
||||
|
||||
#endif // SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP
|
||||
|
||||
@@ -37,7 +37,11 @@ size_t MinNewSize = 0;
|
||||
size_t MinOldSize = 0;
|
||||
size_t MaxOldSize = 0;
|
||||
|
||||
size_t OldSize = 0;
|
||||
// If InitialHeapSize or MinHeapSize is not set on cmdline, this variable,
|
||||
// together with NewSize, is used to derive them.
|
||||
// Using the same value when it was a configurable flag to avoid breakage.
|
||||
// See more in JDK-8346005
|
||||
size_t OldSize = ScaleForWordSize(4*M);
|
||||
|
||||
size_t GenAlignment = 0;
|
||||
|
||||
|
||||
@@ -180,8 +180,8 @@ void ShenandoahGenerationalHeap::gc_threads_do(ThreadClosure* tcl) const {
|
||||
}
|
||||
|
||||
void ShenandoahGenerationalHeap::stop() {
|
||||
regulator_thread()->stop();
|
||||
ShenandoahHeap::stop();
|
||||
regulator_thread()->stop();
|
||||
}
|
||||
|
||||
void ShenandoahGenerationalHeap::evacuate_collection_set(bool concurrent) {
|
||||
|
||||
@@ -538,7 +538,6 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) :
|
||||
_pacer(nullptr),
|
||||
_verifier(nullptr),
|
||||
_phase_timings(nullptr),
|
||||
_mmu_tracker(),
|
||||
_monitoring_support(nullptr),
|
||||
_memory_pool(nullptr),
|
||||
_stw_memory_manager("Shenandoah Pauses"),
|
||||
@@ -632,6 +631,8 @@ public:
|
||||
|
||||
void ShenandoahHeap::post_initialize() {
|
||||
CollectedHeap::post_initialize();
|
||||
|
||||
// Schedule periodic task to report on gc thread CPU utilization
|
||||
_mmu_tracker.initialize();
|
||||
|
||||
MutexLocker ml(Threads_lock);
|
||||
@@ -2084,6 +2085,9 @@ void ShenandoahHeap::stop() {
|
||||
// Step 0. Notify policy to disable event recording and prevent visiting gc threads during shutdown
|
||||
_shenandoah_policy->record_shutdown();
|
||||
|
||||
// Step 0a. Stop reporting on gc thread cpu utilization
|
||||
mmu_tracker()->stop();
|
||||
|
||||
// Step 1. Notify control thread that we are in shutdown.
|
||||
// Note that we cannot do that with stop(), because stop() is blocking and waits for the actual shutdown.
|
||||
// Doing stop() here would wait for the normal GC cycle to complete, never falling through to cancel below.
|
||||
|
||||
@@ -93,11 +93,6 @@ size_t ShenandoahGenerationalMemoryPool::used_in_bytes() {
|
||||
return _generation->used();
|
||||
}
|
||||
|
||||
size_t ShenandoahGenerationalMemoryPool::max_size() const {
|
||||
return _generation->max_capacity();
|
||||
}
|
||||
|
||||
|
||||
ShenandoahYoungGenMemoryPool::ShenandoahYoungGenMemoryPool(ShenandoahHeap* heap) :
|
||||
ShenandoahGenerationalMemoryPool(heap,
|
||||
"Shenandoah Young Gen",
|
||||
|
||||
@@ -55,7 +55,6 @@ public:
|
||||
explicit ShenandoahGenerationalMemoryPool(ShenandoahHeap* heap, const char* name, ShenandoahGeneration* generation);
|
||||
MemoryUsage get_memory_usage() override;
|
||||
size_t used_in_bytes() override;
|
||||
size_t max_size() const override;
|
||||
};
|
||||
|
||||
class ShenandoahYoungGenMemoryPool : public ShenandoahGenerationalMemoryPool {
|
||||
|
||||
@@ -48,6 +48,7 @@ class ThreadTimeAccumulator : public ThreadClosure {
|
||||
size_t total_time;
|
||||
ThreadTimeAccumulator() : total_time(0) {}
|
||||
void do_thread(Thread* thread) override {
|
||||
assert(!thread->has_terminated(), "Cannot get cpu time for terminated thread: " UINTX_FORMAT, thread->osthread()->thread_id_for_printing());
|
||||
total_time += os::thread_cpu_time(thread);
|
||||
}
|
||||
};
|
||||
@@ -65,7 +66,6 @@ ShenandoahMmuTracker::ShenandoahMmuTracker() :
|
||||
}
|
||||
|
||||
ShenandoahMmuTracker::~ShenandoahMmuTracker() {
|
||||
_mmu_periodic_task->disenroll();
|
||||
delete _mmu_periodic_task;
|
||||
}
|
||||
|
||||
@@ -175,6 +175,10 @@ void ShenandoahMmuTracker::report() {
|
||||
log_debug(gc)("Periodic Sample: GCU = %.3f%%, MU = %.3f%% during most recent %.1fs", gcu * 100, mu * 100, time_delta);
|
||||
}
|
||||
|
||||
void ShenandoahMmuTracker::stop() const {
|
||||
_mmu_periodic_task->disenroll();
|
||||
}
|
||||
|
||||
void ShenandoahMmuTracker::initialize() {
|
||||
// initialize static data
|
||||
_active_processors = os::initial_active_processor_count();
|
||||
|
||||
@@ -101,6 +101,10 @@ public:
|
||||
// GCPauseIntervalMillis and defaults to 5 seconds. This method computes
|
||||
// the MMU over the elapsed interval and records it in a running average.
|
||||
void report();
|
||||
|
||||
// Unenrolls the periodic task that collects CPU utilization for GC threads. This must happen _before_ the
|
||||
// gc threads are stopped and terminated.
|
||||
void stop() const;
|
||||
};
|
||||
|
||||
#endif //SHARE_GC_SHENANDOAH_SHENANDOAHMMUTRACKER_HPP
|
||||
|
||||
@@ -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,15 @@ public:
|
||||
is_aligned(addr, klass_alignment_in_bytes());
|
||||
}
|
||||
|
||||
#if defined(AARCH64) && !defined(ZERO)
|
||||
// Check that with the given base, shift and range, aarch64 code can encode and decode the klass pointer.
|
||||
static bool check_klass_decode_mode(address base, int shift, const size_t range);
|
||||
// Called after initialization.
|
||||
static bool set_klass_decode_mode();
|
||||
#else
|
||||
static bool check_klass_decode_mode(address base, int shift, const size_t range) { return true; }
|
||||
static bool set_klass_decode_mode() { return true; }
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // SHARE_OOPS_COMPRESSEDKLASS_HPP
|
||||
|
||||
@@ -395,159 +395,9 @@ Node* AddNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a + a + ... + a into a*n
|
||||
Node* serial_additions = convert_serial_additions(phase, bt);
|
||||
if (serial_additions != nullptr) {
|
||||
return serial_additions;
|
||||
}
|
||||
|
||||
return AddNode::Ideal(phase, can_reshape);
|
||||
}
|
||||
|
||||
// Try to convert a serial of additions into a single multiplication. Also convert `(a * CON) + a` to `(CON + 1) * a` as
|
||||
// a side effect. On success, a new MulNode is returned.
|
||||
Node* AddNode::convert_serial_additions(PhaseGVN* phase, BasicType bt) {
|
||||
// We need to make sure that the current AddNode is not part of a MulNode that has already been optimized to a
|
||||
// power-of-2 addition (e.g., 3 * a => (a << 2) + a). Without this check, GVN would keep trying to optimize the same
|
||||
// node and can't progress. For example, 3 * a => (a << 2) + a => 3 * a => (a << 2) + a => ...
|
||||
if (find_power_of_two_addition_pattern(this, bt, nullptr) != nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Node* in1 = in(1);
|
||||
Node* in2 = in(2);
|
||||
jlong multiplier;
|
||||
|
||||
// While multiplications can be potentially optimized to power-of-2 subtractions (e.g., a * 7 => (a << 3) - a),
|
||||
// (x - y) + y => x is already handled by the Identity() methods. So, we don't need to check for that pattern here.
|
||||
if (find_simple_addition_pattern(in1, bt, &multiplier) == in2
|
||||
|| find_simple_lshift_pattern(in1, bt, &multiplier) == in2
|
||||
|| find_simple_multiplication_pattern(in1, bt, &multiplier) == in2
|
||||
|| find_power_of_two_addition_pattern(in1, bt, &multiplier) == in2) {
|
||||
multiplier++; // +1 for the in2 term
|
||||
|
||||
Node* con = (bt == T_INT)
|
||||
? (Node*) phase->intcon((jint) multiplier) // intentional type narrowing to allow overflow at max_jint
|
||||
: (Node*) phase->longcon(multiplier);
|
||||
return MulNode::make(con, in2, bt);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to match `a + a`. On success, return `a` and set `2` as `multiplier`.
|
||||
// The method matches `n` for pattern: AddNode(a, a).
|
||||
Node* AddNode::find_simple_addition_pattern(Node* n, BasicType bt, jlong* multiplier) {
|
||||
if (n->Opcode() == Op_Add(bt) && n->in(1) == n->in(2)) {
|
||||
*multiplier = 2;
|
||||
return n->in(1);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to match `a << CON`. On success, return `a` and set `1 << CON` as `multiplier`.
|
||||
// Match `n` for pattern: LShiftNode(a, CON).
|
||||
// Note that the power-of-2 multiplication optimization could potentially convert a MulNode to this pattern.
|
||||
Node* AddNode::find_simple_lshift_pattern(Node* n, BasicType bt, jlong* multiplier) {
|
||||
// Note that power-of-2 multiplication optimization could potentially convert a MulNode to this pattern
|
||||
if (n->Opcode() == Op_LShift(bt) && n->in(2)->is_Con()) {
|
||||
Node* con = n->in(2);
|
||||
if (con->is_top()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*multiplier = ((jlong) 1 << con->get_int());
|
||||
return n->in(1);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to match `CON * a`. On success, return `a` and set `CON` as `multiplier`.
|
||||
// Match `n` for patterns:
|
||||
// - MulNode(CON, a)
|
||||
// - MulNode(a, CON)
|
||||
Node* AddNode::find_simple_multiplication_pattern(Node* n, BasicType bt, jlong* multiplier) {
|
||||
// This optimization technically only produces MulNode(CON, a), but we might as match MulNode(a, CON), too.
|
||||
if (n->Opcode() == Op_Mul(bt) && (n->in(1)->is_Con() || n->in(2)->is_Con())) {
|
||||
Node* con = n->in(1);
|
||||
Node* base = n->in(2);
|
||||
|
||||
// swap ConNode to lhs for easier matching
|
||||
if (!con->is_Con()) {
|
||||
swap(con, base);
|
||||
}
|
||||
|
||||
if (con->is_top()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*multiplier = con->get_integer_as_long(bt);
|
||||
return base;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to match `(a << CON1) + (a << CON2)`. On success, return `a` and set `(1 << CON1) + (1 << CON2)` as `multiplier`.
|
||||
// Match `n` for patterns:
|
||||
// - AddNode(LShiftNode(a, CON), LShiftNode(a, CON)/a)
|
||||
// - AddNode(LShiftNode(a, CON)/a, LShiftNode(a, CON))
|
||||
// given that lhs is different from rhs.
|
||||
// Note that one of the term of the addition could simply be `a` (i.e., a << 0). Calling this function with `multiplier`
|
||||
// being null is safe.
|
||||
Node* AddNode::find_power_of_two_addition_pattern(Node* n, BasicType bt, jlong* multiplier) {
|
||||
if (n->Opcode() == Op_Add(bt) && n->in(1) != n->in(2)) {
|
||||
Node* lhs = n->in(1);
|
||||
Node* rhs = n->in(2);
|
||||
|
||||
// swap LShiftNode to lhs for easier matching
|
||||
if (lhs->Opcode() != Op_LShift(bt)) {
|
||||
swap(lhs, rhs);
|
||||
}
|
||||
|
||||
// AddNode(LShiftNode(a, CON), *)?
|
||||
if (lhs->Opcode() != Op_LShift(bt) || !lhs->in(2)->is_Con()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
jlong lhs_multiplier = 0;
|
||||
if (multiplier != nullptr) {
|
||||
Node* con = lhs->in(2);
|
||||
if (con->is_top()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
lhs_multiplier = (jlong) 1 << con->get_int();
|
||||
}
|
||||
|
||||
// AddNode(LShiftNode(a, CON), a)?
|
||||
if (lhs->in(1) == rhs) {
|
||||
if (multiplier != nullptr) {
|
||||
*multiplier = lhs_multiplier + 1;
|
||||
}
|
||||
|
||||
return rhs;
|
||||
}
|
||||
|
||||
// AddNode(LShiftNode(a, CON), LShiftNode(a, CON2))?
|
||||
if (rhs->Opcode() == Op_LShift(bt) && lhs->in(1) == rhs->in(1) && rhs->in(2)->is_Con()) {
|
||||
if (multiplier != nullptr) {
|
||||
Node* con = rhs->in(2);
|
||||
if (con->is_top()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
*multiplier = lhs_multiplier + ((jlong) 1 << con->get_int());
|
||||
}
|
||||
|
||||
return lhs->in(1);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Node* AddINode::Ideal(PhaseGVN* phase, bool can_reshape) {
|
||||
Node* in1 = in(1);
|
||||
|
||||
@@ -42,13 +42,6 @@ typedef const Pair<Node*, jint> ConstAddOperands;
|
||||
// by virtual functions.
|
||||
class AddNode : public Node {
|
||||
virtual uint hash() const;
|
||||
|
||||
Node* convert_serial_additions(PhaseGVN* phase, BasicType bt);
|
||||
static Node* find_simple_addition_pattern(Node* n, BasicType bt, jlong* multiplier);
|
||||
static Node* find_simple_lshift_pattern(Node* n, BasicType bt, jlong* multiplier);
|
||||
static Node* find_simple_multiplication_pattern(Node* n, BasicType bt, jlong* multiplier);
|
||||
static Node* find_power_of_two_addition_pattern(Node* n, BasicType bt, jlong* multiplier);
|
||||
|
||||
public:
|
||||
AddNode( Node *in1, Node *in2 ) : Node(nullptr,in1,in2) {
|
||||
init_class_id(Class_Add);
|
||||
|
||||
@@ -4262,7 +4262,7 @@ bool LibraryCallKit::inline_native_subtype_check() {
|
||||
|
||||
//---------------------generate_array_guard_common------------------------
|
||||
Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region,
|
||||
bool obj_array, bool not_array) {
|
||||
bool obj_array, bool not_array, Node** obj) {
|
||||
|
||||
if (stopped()) {
|
||||
return nullptr;
|
||||
@@ -4304,7 +4304,14 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region,
|
||||
// invert the test if we are looking for a non-array
|
||||
if (not_array) btest = BoolTest(btest).negate();
|
||||
Node* bol = _gvn.transform(new BoolNode(cmp, btest));
|
||||
return generate_fair_guard(bol, region);
|
||||
Node* ctrl = generate_fair_guard(bol, region);
|
||||
Node* is_array_ctrl = not_array ? control() : ctrl;
|
||||
if (obj != nullptr && is_array_ctrl != nullptr && is_array_ctrl != top()) {
|
||||
// Keep track of the fact that 'obj' is an array to prevent
|
||||
// array specific accesses from floating above the guard.
|
||||
*obj = _gvn.transform(new CastPPNode(is_array_ctrl, *obj, TypeAryPtr::BOTTOM));
|
||||
}
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
|
||||
@@ -4399,7 +4406,7 @@ bool LibraryCallKit::inline_native_getLength() {
|
||||
if (stopped()) return true;
|
||||
|
||||
// Deoptimize if it is a non-array.
|
||||
Node* non_array = generate_non_array_guard(load_object_klass(array), nullptr);
|
||||
Node* non_array = generate_non_array_guard(load_object_klass(array), nullptr, &array);
|
||||
|
||||
if (non_array != nullptr) {
|
||||
PreserveJVMState pjvms(this);
|
||||
@@ -5259,12 +5266,13 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
|
||||
record_for_igvn(result_reg);
|
||||
|
||||
Node* obj_klass = load_object_klass(obj);
|
||||
Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)nullptr);
|
||||
Node* array_obj = obj;
|
||||
Node* array_ctl = generate_array_guard(obj_klass, (RegionNode*)nullptr, &array_obj);
|
||||
if (array_ctl != nullptr) {
|
||||
// It's an array.
|
||||
PreserveJVMState pjvms(this);
|
||||
set_control(array_ctl);
|
||||
Node* obj_length = load_array_length(obj);
|
||||
Node* obj_length = load_array_length(array_obj);
|
||||
Node* array_size = nullptr; // Size of the array without object alignment padding.
|
||||
Node* alloc_obj = new_array(obj_klass, obj_length, 0, &array_size, /*deoptimize_on_exception=*/true);
|
||||
|
||||
@@ -5278,7 +5286,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
|
||||
set_control(is_obja);
|
||||
// Generate a direct call to the right arraycopy function(s).
|
||||
// Clones are always tightly coupled.
|
||||
ArrayCopyNode* ac = ArrayCopyNode::make(this, true, obj, intcon(0), alloc_obj, intcon(0), obj_length, true, false);
|
||||
ArrayCopyNode* ac = ArrayCopyNode::make(this, true, array_obj, intcon(0), alloc_obj, intcon(0), obj_length, true, false);
|
||||
ac->set_clone_oop_array();
|
||||
Node* n = _gvn.transform(ac);
|
||||
assert(n == ac, "cannot disappear");
|
||||
@@ -5299,7 +5307,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
|
||||
// the object.)
|
||||
|
||||
if (!stopped()) {
|
||||
copy_to_clone(obj, alloc_obj, array_size, true);
|
||||
copy_to_clone(array_obj, alloc_obj, array_size, true);
|
||||
|
||||
// Present the results of the copy.
|
||||
result_reg->init_req(_array_path, control());
|
||||
@@ -5920,8 +5928,8 @@ bool LibraryCallKit::inline_arraycopy() {
|
||||
record_for_igvn(slow_region);
|
||||
|
||||
// (1) src and dest are arrays.
|
||||
generate_non_array_guard(load_object_klass(src), slow_region);
|
||||
generate_non_array_guard(load_object_klass(dest), slow_region);
|
||||
generate_non_array_guard(load_object_klass(src), slow_region, &src);
|
||||
generate_non_array_guard(load_object_klass(dest), slow_region, &dest);
|
||||
|
||||
// (2) src and dest arrays must have elements of the same BasicType
|
||||
// done at macro expansion or at Ideal transformation time
|
||||
@@ -8537,7 +8545,7 @@ bool LibraryCallKit::inline_getObjectSize() {
|
||||
PhiNode* result_val = new PhiNode(result_reg, TypeLong::LONG);
|
||||
record_for_igvn(result_reg);
|
||||
|
||||
Node* array_ctl = generate_array_guard(klass_node, nullptr);
|
||||
Node* array_ctl = generate_array_guard(klass_node, nullptr, &obj);
|
||||
if (array_ctl != nullptr) {
|
||||
// Array case: size is round(header + element_size*arraylength).
|
||||
// Since arraylength is different for every array instance, we have to
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2025, 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
|
||||
@@ -163,20 +163,20 @@ class LibraryCallKit : public GraphKit {
|
||||
RegionNode* region);
|
||||
Node* generate_interface_guard(Node* kls, RegionNode* region);
|
||||
Node* generate_hidden_class_guard(Node* kls, RegionNode* region);
|
||||
Node* generate_array_guard(Node* kls, RegionNode* region) {
|
||||
return generate_array_guard_common(kls, region, false, false);
|
||||
Node* generate_array_guard(Node* kls, RegionNode* region, Node** obj = nullptr) {
|
||||
return generate_array_guard_common(kls, region, false, false, obj);
|
||||
}
|
||||
Node* generate_non_array_guard(Node* kls, RegionNode* region) {
|
||||
return generate_array_guard_common(kls, region, false, true);
|
||||
Node* generate_non_array_guard(Node* kls, RegionNode* region, Node** obj = nullptr) {
|
||||
return generate_array_guard_common(kls, region, false, true, obj);
|
||||
}
|
||||
Node* generate_objArray_guard(Node* kls, RegionNode* region) {
|
||||
return generate_array_guard_common(kls, region, true, false);
|
||||
Node* generate_objArray_guard(Node* kls, RegionNode* region, Node** obj = nullptr) {
|
||||
return generate_array_guard_common(kls, region, true, false, obj);
|
||||
}
|
||||
Node* generate_non_objArray_guard(Node* kls, RegionNode* region) {
|
||||
return generate_array_guard_common(kls, region, true, true);
|
||||
Node* generate_non_objArray_guard(Node* kls, RegionNode* region, Node** obj = nullptr) {
|
||||
return generate_array_guard_common(kls, region, true, true, obj);
|
||||
}
|
||||
Node* generate_array_guard_common(Node* kls, RegionNode* region,
|
||||
bool obj_array, bool not_array);
|
||||
bool obj_array, bool not_array, Node** obj = nullptr);
|
||||
Node* generate_virtual_guard(Node* obj_klass, RegionNode* slow_region);
|
||||
CallJavaNode* generate_method_call(vmIntrinsicID method_id, bool is_virtual, bool is_static, bool res_not_null);
|
||||
CallJavaNode* generate_method_call_static(vmIntrinsicID method_id, bool res_not_null) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, 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
|
||||
@@ -582,6 +582,7 @@ void Type::Initialize_shared(Compile* current) {
|
||||
TypeAryPtr::_array_interfaces = TypeInterfaces::make(&array_interfaces);
|
||||
TypeAryKlassPtr::_array_interfaces = TypeAryPtr::_array_interfaces;
|
||||
|
||||
TypeAryPtr::BOTTOM = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::BOTTOM, TypeInt::POS), nullptr, false, Type::OffsetBot);
|
||||
TypeAryPtr::RANGE = TypeAryPtr::make( TypePtr::BotPTR, TypeAry::make(Type::BOTTOM,TypeInt::POS), nullptr /* current->env()->Object_klass() */, false, arrayOopDesc::length_offset_in_bytes());
|
||||
|
||||
TypeAryPtr::NARROWOOPS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeNarrowOop::BOTTOM, TypeInt::POS), nullptr /*ciArrayKlass::make(o)*/, false, Type::OffsetBot);
|
||||
@@ -4682,16 +4683,17 @@ bool TypeAryKlassPtr::is_meet_subtype_of_helper(const TypeKlassPtr *other, bool
|
||||
|
||||
//=============================================================================
|
||||
// Convenience common pre-built types.
|
||||
const TypeAryPtr *TypeAryPtr::RANGE;
|
||||
const TypeAryPtr *TypeAryPtr::OOPS;
|
||||
const TypeAryPtr *TypeAryPtr::NARROWOOPS;
|
||||
const TypeAryPtr *TypeAryPtr::BYTES;
|
||||
const TypeAryPtr *TypeAryPtr::SHORTS;
|
||||
const TypeAryPtr *TypeAryPtr::CHARS;
|
||||
const TypeAryPtr *TypeAryPtr::INTS;
|
||||
const TypeAryPtr *TypeAryPtr::LONGS;
|
||||
const TypeAryPtr *TypeAryPtr::FLOATS;
|
||||
const TypeAryPtr *TypeAryPtr::DOUBLES;
|
||||
const TypeAryPtr* TypeAryPtr::BOTTOM;
|
||||
const TypeAryPtr* TypeAryPtr::RANGE;
|
||||
const TypeAryPtr* TypeAryPtr::OOPS;
|
||||
const TypeAryPtr* TypeAryPtr::NARROWOOPS;
|
||||
const TypeAryPtr* TypeAryPtr::BYTES;
|
||||
const TypeAryPtr* TypeAryPtr::SHORTS;
|
||||
const TypeAryPtr* TypeAryPtr::CHARS;
|
||||
const TypeAryPtr* TypeAryPtr::INTS;
|
||||
const TypeAryPtr* TypeAryPtr::LONGS;
|
||||
const TypeAryPtr* TypeAryPtr::FLOATS;
|
||||
const TypeAryPtr* TypeAryPtr::DOUBLES;
|
||||
|
||||
//------------------------------make-------------------------------------------
|
||||
const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, 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
|
||||
@@ -1470,16 +1470,17 @@ public:
|
||||
virtual const TypeKlassPtr* as_klass_type(bool try_for_exact = false) const;
|
||||
|
||||
// Convenience common pre-built types.
|
||||
static const TypeAryPtr *RANGE;
|
||||
static const TypeAryPtr *OOPS;
|
||||
static const TypeAryPtr *NARROWOOPS;
|
||||
static const TypeAryPtr *BYTES;
|
||||
static const TypeAryPtr *SHORTS;
|
||||
static const TypeAryPtr *CHARS;
|
||||
static const TypeAryPtr *INTS;
|
||||
static const TypeAryPtr *LONGS;
|
||||
static const TypeAryPtr *FLOATS;
|
||||
static const TypeAryPtr *DOUBLES;
|
||||
static const TypeAryPtr* BOTTOM;
|
||||
static const TypeAryPtr* RANGE;
|
||||
static const TypeAryPtr* OOPS;
|
||||
static const TypeAryPtr* NARROWOOPS;
|
||||
static const TypeAryPtr* BYTES;
|
||||
static const TypeAryPtr* SHORTS;
|
||||
static const TypeAryPtr* CHARS;
|
||||
static const TypeAryPtr* INTS;
|
||||
static const TypeAryPtr* LONGS;
|
||||
static const TypeAryPtr* FLOATS;
|
||||
static const TypeAryPtr* DOUBLES;
|
||||
// selects one of the above:
|
||||
static const TypeAryPtr *get_array_body_type(BasicType elem) {
|
||||
assert((uint)elem <= T_CONFLICT && _array_body_type[elem] != nullptr, "bad elem type");
|
||||
|
||||
@@ -1637,8 +1637,9 @@ bool LibraryCallKit::inline_vector_reduction() {
|
||||
int opc = VectorSupport::vop2ideal(opr->get_con(), elem_bt);
|
||||
int sopc = ReductionNode::opcode(opc, elem_bt);
|
||||
|
||||
// Ensure reduction operation for lanewise operation
|
||||
// When using mask, mask use type needs to be VecMaskUseLoad.
|
||||
if (!arch_supports_vector(sopc, num_elem, elem_bt, is_masked_op ? VecMaskUseLoad : VecMaskNotUsed)) {
|
||||
if (sopc == opc || !arch_supports_vector(sopc, num_elem, elem_bt, is_masked_op ? VecMaskUseLoad : VecMaskNotUsed)) {
|
||||
log_if_needed(" ** not supported: arity=1 op=%d/reduce vlen=%d etype=%s is_masked_op=%d",
|
||||
sopc, num_elem, type2name(elem_bt), is_masked_op ? 1 : 0);
|
||||
return false;
|
||||
|
||||
@@ -1466,6 +1466,9 @@ bool VectorCastNode::implemented(int opc, uint vlen, BasicType src_type, BasicTy
|
||||
if (is_java_primitive(dst_type) &&
|
||||
is_java_primitive(src_type) &&
|
||||
(vlen > 1) && is_power_of_2(vlen) &&
|
||||
// In rare case, the input to the VectorCast could be a Replicate node. We need to make sure creating is supported:
|
||||
// check the src_type:
|
||||
VectorNode::vector_size_supported_auto_vectorization(src_type, vlen) &&
|
||||
VectorNode::vector_size_supported_auto_vectorization(dst_type, vlen)) {
|
||||
int vopc = VectorCastNode::opcode(opc, src_type);
|
||||
return vopc > 0 && Matcher::match_rule_supported_auto_vectorization(vopc, vlen, dst_type);
|
||||
|
||||
@@ -598,7 +598,7 @@ JvmtiEventControllerPrivate::recompute_thread_enabled(JvmtiThreadState *state) {
|
||||
}
|
||||
// compute interp_only mode
|
||||
bool should_be_interp = (any_env_enabled & INTERP_EVENT_BITS) != 0 || has_frame_pops;
|
||||
bool is_now_interp = state->is_interp_only_mode();
|
||||
bool is_now_interp = state->is_interp_only_mode() || state->is_pending_interp_only_mode();
|
||||
|
||||
if (should_be_interp != is_now_interp) {
|
||||
if (should_be_interp) {
|
||||
|
||||
@@ -60,14 +60,14 @@ JVM_END
|
||||
#if INCLUDE_JVMTI
|
||||
class JvmtiUnmountBeginMark : public StackObj {
|
||||
Handle _vthread;
|
||||
JavaThread* _target;
|
||||
JavaThread* _current;
|
||||
freeze_result _result;
|
||||
bool _failed;
|
||||
|
||||
public:
|
||||
JvmtiUnmountBeginMark(JavaThread* t) :
|
||||
_vthread(t, t->vthread()), _target(t), _result(freeze_pinned_native), _failed(false) {
|
||||
assert(!_target->is_in_VTMS_transition(), "must be");
|
||||
_vthread(t, t->vthread()), _current(t), _result(freeze_pinned_native), _failed(false) {
|
||||
assert(!_current->is_in_VTMS_transition(), "must be");
|
||||
|
||||
if (JvmtiVTMSTransitionDisabler::VTMS_notify_jvmti_events()) {
|
||||
JvmtiVTMSTransitionDisabler::VTMS_vthread_unmount((jthread)_vthread.raw_value(), true);
|
||||
@@ -75,26 +75,26 @@ class JvmtiUnmountBeginMark : public StackObj {
|
||||
// Don't preempt if there is a pending popframe or earlyret operation. This can
|
||||
// be installed in start_VTMS_transition() so we need to check it here.
|
||||
if (JvmtiExport::can_pop_frame() || JvmtiExport::can_force_early_return()) {
|
||||
JvmtiThreadState* state = _target->jvmti_thread_state();
|
||||
if (_target->has_pending_popframe() || (state != nullptr && state->is_earlyret_pending())) {
|
||||
JvmtiThreadState* state = _current->jvmti_thread_state();
|
||||
if (_current->has_pending_popframe() || (state != nullptr && state->is_earlyret_pending())) {
|
||||
_failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't preempt in case there is an async exception installed since
|
||||
// we would incorrectly throw it during the unmount logic in the carrier.
|
||||
if (_target->has_async_exception_condition()) {
|
||||
if (_current->has_async_exception_condition()) {
|
||||
_failed = true;
|
||||
}
|
||||
} else {
|
||||
_target->set_is_in_VTMS_transition(true);
|
||||
_current->set_is_in_VTMS_transition(true);
|
||||
java_lang_Thread::set_is_in_VTMS_transition(_vthread(), true);
|
||||
}
|
||||
}
|
||||
~JvmtiUnmountBeginMark() {
|
||||
assert(!_target->is_suspended(), "must be");
|
||||
assert(!_current->is_suspended(), "must be");
|
||||
|
||||
assert(_target->is_in_VTMS_transition(), "must be");
|
||||
assert(_current->is_in_VTMS_transition(), "must be");
|
||||
assert(java_lang_Thread::is_in_VTMS_transition(_vthread()), "must be");
|
||||
|
||||
// Read it again since for late binding agents the flag could have
|
||||
@@ -106,7 +106,7 @@ class JvmtiUnmountBeginMark : public StackObj {
|
||||
if (jvmti_present) {
|
||||
JvmtiVTMSTransitionDisabler::VTMS_vthread_mount((jthread)_vthread.raw_value(), false);
|
||||
} else {
|
||||
_target->set_is_in_VTMS_transition(false);
|
||||
_current->set_is_in_VTMS_transition(false);
|
||||
java_lang_Thread::set_is_in_VTMS_transition(_vthread(), false);
|
||||
}
|
||||
}
|
||||
@@ -115,51 +115,59 @@ class JvmtiUnmountBeginMark : public StackObj {
|
||||
bool failed() { return _failed; }
|
||||
};
|
||||
|
||||
static bool is_vthread_safe_to_preempt_for_jvmti(JavaThread* target) {
|
||||
if (target->is_in_VTMS_transition()) {
|
||||
// We caught target at the end of a mount transition.
|
||||
static bool is_vthread_safe_to_preempt_for_jvmti(JavaThread* current) {
|
||||
if (current->is_in_VTMS_transition()) {
|
||||
// We are at the end of a mount transition.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
static bool is_vthread_safe_to_preempt(JavaThread* target, oop vthread) {
|
||||
static bool is_vthread_safe_to_preempt(JavaThread* current, oop vthread) {
|
||||
assert(java_lang_VirtualThread::is_instance(vthread), "");
|
||||
if (java_lang_VirtualThread::state(vthread) != java_lang_VirtualThread::RUNNING) { // inside transition
|
||||
return false;
|
||||
}
|
||||
return JVMTI_ONLY(is_vthread_safe_to_preempt_for_jvmti(target)) NOT_JVMTI(true);
|
||||
return JVMTI_ONLY(is_vthread_safe_to_preempt_for_jvmti(current)) NOT_JVMTI(true);
|
||||
}
|
||||
|
||||
typedef freeze_result (*FreezeContFnT)(JavaThread*, intptr_t*);
|
||||
|
||||
static void verify_preempt_preconditions(JavaThread* target, oop continuation) {
|
||||
assert(target == JavaThread::current(), "no support for external preemption");
|
||||
assert(target->has_last_Java_frame(), "");
|
||||
assert(!target->preempting(), "");
|
||||
assert(target->last_continuation() != nullptr, "");
|
||||
assert(target->last_continuation()->cont_oop(target) == continuation, "");
|
||||
static void verify_preempt_preconditions(JavaThread* current, oop continuation) {
|
||||
assert(current == JavaThread::current(), "no support for external preemption");
|
||||
assert(current->has_last_Java_frame(), "");
|
||||
assert(!current->preempting(), "");
|
||||
assert(current->last_continuation() != nullptr, "");
|
||||
assert(current->last_continuation()->cont_oop(current) == continuation, "");
|
||||
assert(Continuation::continuation_scope(continuation) == java_lang_VirtualThread::vthread_scope(), "");
|
||||
assert(!target->has_pending_exception(), "");
|
||||
assert(!current->has_pending_exception(), "");
|
||||
}
|
||||
|
||||
freeze_result Continuation::try_preempt(JavaThread* target, oop continuation) {
|
||||
verify_preempt_preconditions(target, continuation);
|
||||
freeze_result Continuation::try_preempt(JavaThread* current, oop continuation) {
|
||||
verify_preempt_preconditions(current, continuation);
|
||||
|
||||
if (LockingMode == LM_LEGACY) {
|
||||
return freeze_unsupported;
|
||||
}
|
||||
|
||||
if (!is_vthread_safe_to_preempt(target, target->vthread())) {
|
||||
if (!is_vthread_safe_to_preempt(current, current->vthread())) {
|
||||
return freeze_pinned_native;
|
||||
}
|
||||
|
||||
JVMTI_ONLY(JvmtiUnmountBeginMark jubm(target);)
|
||||
JVMTI_ONLY(JvmtiUnmountBeginMark jubm(current);)
|
||||
JVMTI_ONLY(if (jubm.failed()) return freeze_pinned_native;)
|
||||
freeze_result res = CAST_TO_FN_PTR(FreezeContFnT, freeze_preempt_entry())(target, target->last_Java_sp());
|
||||
freeze_result res = CAST_TO_FN_PTR(FreezeContFnT, freeze_preempt_entry())(current, current->last_Java_sp());
|
||||
log_trace(continuations, preempt)("try_preempt: %d", res);
|
||||
JVMTI_ONLY(jubm.set_result(res);)
|
||||
|
||||
if (current->has_pending_exception()) {
|
||||
assert(res == freeze_exception, "expecting an exception result from freeze");
|
||||
// We don't want to throw exceptions, especially when returning
|
||||
// from monitorenter since the compiler does not expect one. We
|
||||
// just ignore the exception and pin the vthread to the carrier.
|
||||
current->clear_pending_exception();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -2603,6 +2603,7 @@ void ThawBase::recurse_thaw_compiled_frame(const frame& hf, frame& caller, int n
|
||||
|| (stub_caller && f.cb()->as_nmethod()->is_marked_for_deoptimization())) {
|
||||
// The caller of the safepoint stub when the continuation is preempted is not at a call instruction, and so
|
||||
// cannot rely on nmethod patching for deopt.
|
||||
assert(_thread->is_interp_only_mode() || stub_caller, "expected a stub-caller");
|
||||
|
||||
log_develop_trace(continuations)("Deoptimizing thawed frame");
|
||||
DEBUG_ONLY(ContinuationHelper::Frame::patch_pc(f, nullptr));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2025, 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
|
||||
@@ -1264,36 +1264,49 @@ static bool monitors_used_above_threshold(MonitorList* list) {
|
||||
if (MonitorUsedDeflationThreshold == 0) { // disabled case is easy
|
||||
return false;
|
||||
}
|
||||
// Start with ceiling based on a per-thread estimate:
|
||||
size_t ceiling = ObjectSynchronizer::in_use_list_ceiling();
|
||||
size_t old_ceiling = ceiling;
|
||||
if (ceiling < list->max()) {
|
||||
// The max used by the system has exceeded the ceiling so use that:
|
||||
ceiling = list->max();
|
||||
}
|
||||
size_t monitors_used = list->count();
|
||||
if (monitors_used == 0) { // empty list is easy
|
||||
return false;
|
||||
}
|
||||
if (NoAsyncDeflationProgressMax != 0 &&
|
||||
_no_progress_cnt >= NoAsyncDeflationProgressMax) {
|
||||
double remainder = (100.0 - MonitorUsedDeflationThreshold) / 100.0;
|
||||
size_t new_ceiling = ceiling + (size_t)((double)ceiling * remainder) + 1;
|
||||
ObjectSynchronizer::set_in_use_list_ceiling(new_ceiling);
|
||||
log_info(monitorinflation)("Too many deflations without progress; "
|
||||
"bumping in_use_list_ceiling from " SIZE_FORMAT
|
||||
" to " SIZE_FORMAT, old_ceiling, new_ceiling);
|
||||
_no_progress_cnt = 0;
|
||||
ceiling = new_ceiling;
|
||||
}
|
||||
size_t old_ceiling = ObjectSynchronizer::in_use_list_ceiling();
|
||||
// Make sure that we use a ceiling value that is not lower than
|
||||
// previous, not lower than the recorded max used by the system, and
|
||||
// not lower than the current number of monitors in use (which can
|
||||
// race ahead of max). The result is guaranteed > 0.
|
||||
size_t ceiling = MAX3(old_ceiling, list->max(), monitors_used);
|
||||
|
||||
// Check if our monitor usage is above the threshold:
|
||||
size_t monitor_usage = (monitors_used * 100LL) / ceiling;
|
||||
if (int(monitor_usage) > MonitorUsedDeflationThreshold) {
|
||||
// Deflate monitors if over the threshold percentage, unless no
|
||||
// progress on previous deflations.
|
||||
bool is_above_threshold = true;
|
||||
|
||||
// Check if it's time to adjust the in_use_list_ceiling up, due
|
||||
// to too many async deflation attempts without any progress.
|
||||
if (NoAsyncDeflationProgressMax != 0 &&
|
||||
_no_progress_cnt >= NoAsyncDeflationProgressMax) {
|
||||
double remainder = (100.0 - MonitorUsedDeflationThreshold) / 100.0;
|
||||
size_t delta = (size_t)(ceiling * remainder) + 1;
|
||||
size_t new_ceiling = (ceiling > SIZE_MAX - delta)
|
||||
? SIZE_MAX // Overflow, let's clamp new_ceiling.
|
||||
: ceiling + delta;
|
||||
|
||||
ObjectSynchronizer::set_in_use_list_ceiling(new_ceiling);
|
||||
log_info(monitorinflation)("Too many deflations without progress; "
|
||||
"bumping in_use_list_ceiling from " SIZE_FORMAT
|
||||
" to " SIZE_FORMAT, old_ceiling, new_ceiling);
|
||||
_no_progress_cnt = 0;
|
||||
ceiling = new_ceiling;
|
||||
|
||||
// Check if our monitor usage is still above the threshold:
|
||||
monitor_usage = (monitors_used * 100LL) / ceiling;
|
||||
is_above_threshold = int(monitor_usage) > MonitorUsedDeflationThreshold;
|
||||
}
|
||||
log_info(monitorinflation)("monitors_used=" SIZE_FORMAT ", ceiling=" SIZE_FORMAT
|
||||
", monitor_usage=" SIZE_FORMAT ", threshold=%d",
|
||||
monitors_used, ceiling, monitor_usage, MonitorUsedDeflationThreshold);
|
||||
return true;
|
||||
return is_above_threshold;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, 2025, 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
|
||||
@@ -180,8 +180,8 @@ abstract class HKDFKeyDerivation extends KDFSpi {
|
||||
} else if (derivationSpec instanceof HKDFParameterSpec.Expand anExpand) {
|
||||
// set this value in the "if"
|
||||
if ((pseudoRandomKey = anExpand.prk().getEncoded()) == null) {
|
||||
throw new AssertionError(
|
||||
"PRK is required for HKDFParameterSpec.Expand");
|
||||
throw new InvalidAlgorithmParameterException(
|
||||
"Cannot retrieve PRK for HKDFParameterSpec.Expand");
|
||||
}
|
||||
// set this value in the "if"
|
||||
if ((info = anExpand.info()) == null) {
|
||||
@@ -411,4 +411,4 @@ abstract class HKDFKeyDerivation extends KDFSpi {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2025, 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
|
||||
@@ -349,8 +349,8 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
* @jls 15.21.1 Numerical Equality Operators == and !=
|
||||
* @jls 15.20.1 Numerical Comparison Operators {@code <}, {@code <=}, {@code >}, and {@code >=}
|
||||
*
|
||||
* @see <a href="https://standards.ieee.org/ieee/754/6210/">
|
||||
* <cite>IEEE Standard for Floating-Point Arithmetic</cite></a>
|
||||
* @spec https://standards.ieee.org/ieee/754/6210/
|
||||
* IEEE Standard for Floating-Point Arithmetic
|
||||
*
|
||||
* @author Lee Boynton
|
||||
* @author Arthur van Hoff
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2025, 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
|
||||
@@ -67,8 +67,8 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
* decimal conversion issues} in {@code java.lang.Double} is also
|
||||
* applicable to {@code float} values.
|
||||
*
|
||||
* @see <a href="https://standards.ieee.org/ieee/754/6210/">
|
||||
* <cite>IEEE Standard for Floating-Point Arithmetic</cite></a>
|
||||
* @spec https://standards.ieee.org/ieee/754/6210/
|
||||
* IEEE Standard for Floating-Point Arithmetic
|
||||
*
|
||||
* @author Lee Boynton
|
||||
* @author Arthur van Hoff
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2025, 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
|
||||
@@ -120,8 +120,8 @@ import static java.lang.Double.*;
|
||||
* implementation condition than required for most of the methods in
|
||||
* question that are also included in this class.
|
||||
*
|
||||
* @see <a href="https://standards.ieee.org/ieee/754/6210/">
|
||||
* <cite>IEEE Standard for Floating-Point Arithmetic</cite></a>
|
||||
* @spec https://standards.ieee.org/ieee/754/6210/
|
||||
* IEEE Standard for Floating-Point Arithmetic
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2025, 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
|
||||
@@ -98,8 +98,8 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
* href="Math.html#Ieee754RecommendedOps">relate to the IEEE 754
|
||||
* recommended operations</a>.
|
||||
*
|
||||
* @see <a href="https://standards.ieee.org/ieee/754/6210/">
|
||||
* <cite>IEEE Standard for Floating-Point Arithmetic</cite></a>
|
||||
* @spec https://standards.ieee.org/ieee/754/6210/
|
||||
* IEEE Standard for Floating-Point Arithmetic
|
||||
*
|
||||
* @author Joseph D. Darcy
|
||||
* @since 1.3
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -25,7 +25,9 @@
|
||||
|
||||
package java.lang.classfile;
|
||||
|
||||
import java.lang.classfile.attribute.BootstrapMethodsAttribute;
|
||||
import java.lang.classfile.constantpool.ConstantPool;
|
||||
import java.lang.classfile.constantpool.ConstantPoolBuilder;
|
||||
import java.lang.classfile.constantpool.LoadableConstantEntry;
|
||||
import java.lang.classfile.constantpool.MethodHandleEntry;
|
||||
import java.util.List;
|
||||
@@ -34,10 +36,20 @@ import jdk.internal.classfile.impl.BootstrapMethodEntryImpl;
|
||||
|
||||
/**
|
||||
* Models an entry in the bootstrap method table. The bootstrap method table
|
||||
* is stored in the {@code BootstrapMethods} attribute, but is modeled by
|
||||
* the {@link ConstantPool}, since the bootstrap method table is logically
|
||||
* part of the constant pool.
|
||||
* is stored in the {@link BootstrapMethodsAttribute BootstrapMethods}
|
||||
* attribute, but is modeled by the {@link ConstantPool}, since the bootstrap
|
||||
* method table is logically part of the constant pool.
|
||||
* <p>
|
||||
* A bootstrap method entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="BootstrapMethodEntry" target="ConstantPoolBuilder#bsmEntry(MethodHandleEntry, List)" :
|
||||
* BootstrapMethodEntry(
|
||||
* MethodHandleEntry bootstrapMethod, // @link substring="bootstrapMethod" target="#bootstrapMethod"
|
||||
* List<LoadableConstantEntry> arguments // @link substring="arguments" target="#arguments()"
|
||||
* )
|
||||
* }
|
||||
*
|
||||
* @see ConstantPoolBuilder#bsmEntry ConstantPoolBuilder::bsmEntry
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface BootstrapMethodEntry
|
||||
@@ -45,11 +57,19 @@ public sealed interface BootstrapMethodEntry
|
||||
|
||||
/**
|
||||
* {@return the constant pool associated with this entry}
|
||||
*
|
||||
* @apiNote
|
||||
* Given a {@link ConstantPoolBuilder} {@code builder} and a {@code
|
||||
* BootstrapMethodEntry} {@code entry}, use {@link
|
||||
* ConstantPoolBuilder#canWriteDirect
|
||||
* builder.canWriteDirect(entry.constantPool())} instead of object equality
|
||||
* of the constant pool to determine if an entry is compatible.
|
||||
*/
|
||||
ConstantPool constantPool();
|
||||
|
||||
/**
|
||||
* {@return the index into the bootstrap method table corresponding to this entry}
|
||||
* {@return the index into the bootstrap method table corresponding to this
|
||||
* entry}
|
||||
*/
|
||||
int bsmIndex();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -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;
|
||||
@@ -138,21 +140,56 @@ public sealed interface ClassFile
|
||||
|
||||
/**
|
||||
* Option describing whether to preserve the original constant pool when
|
||||
* transforming a classfile. Reusing the constant pool enables significant
|
||||
* optimizations in processing time and minimizes differences between the
|
||||
* original and transformed classfile, but may result in a bigger classfile
|
||||
* when a classfile is significantly transformed.
|
||||
* Default is {@code SHARED_POOL} to preserve the original constant
|
||||
* pool.
|
||||
* transforming a {@code class} file. Reusing the constant pool enables
|
||||
* significant optimizations in processing time and minimizes differences
|
||||
* between the original and transformed {@code class} files, but may result
|
||||
* in a bigger transformed {@code class} file when many elements of the
|
||||
* original {@code class} file are dropped and many original constant
|
||||
* pool entries become unused. Default is {@link #SHARED_POOL} to preserve
|
||||
* the original constant pool.
|
||||
*
|
||||
* @see ConstantPoolBuilder
|
||||
* @see #build(ClassEntry, ConstantPoolBuilder, Consumer)
|
||||
* @see #transformClass(ClassModel, ClassTransform)
|
||||
* @since 24
|
||||
*/
|
||||
enum ConstantPoolSharingOption implements Option {
|
||||
|
||||
/** Preserves the original constant pool when transforming classfile */
|
||||
/**
|
||||
* Preserves the original constant pool when transforming the {@code
|
||||
* class} file.
|
||||
* <p>
|
||||
* These two transformations below are equivalent:
|
||||
* {@snippet lang=java :
|
||||
* ClassModel originalClass = null; // @replace substring=null; replacement=...
|
||||
* ClassDesc resultClassName = null; // @replace substring=null; replacement=...
|
||||
* ClassTransform classTransform = null; // @replace substring=null; replacement=...
|
||||
* var resultOne = ClassFile.of(ConstantPoolSharingOption.SHARED_POOL)
|
||||
* .transformClass(originalClass, resultClassName, classTransform);
|
||||
* var resultTwo = ClassFile.of().build(resultClassName, ConstantPoolBuilder.of(originalClass),
|
||||
* clb -> clb.transform(originalClass, classTransform));
|
||||
* }
|
||||
*
|
||||
* @see ConstantPoolBuilder#of(ClassModel) ConstantPoolBuilder::of(ClassModel)
|
||||
*/
|
||||
SHARED_POOL,
|
||||
|
||||
/** Creates a new constant pool when transforming classfile */
|
||||
/**
|
||||
* Creates a new constant pool when transforming the {@code class} file.
|
||||
* <p>
|
||||
* These two transformations below are equivalent:
|
||||
* {@snippet lang=java :
|
||||
* ClassModel originalClass = null; // @replace substring=null; replacement=...
|
||||
* ClassDesc resultClassName = null; // @replace substring=null; replacement=...
|
||||
* ClassTransform classTransform = null; // @replace substring=null; replacement=...
|
||||
* var resultOne = ClassFile.of(ConstantPoolSharingOption.NEW_POOL)
|
||||
* .transformClass(originalClass, resultClassName, classTransform);
|
||||
* var resultTwo = ClassFile.of().build(resultClassName, ConstantPoolBuilder.of(),
|
||||
* clb -> clb.transform(originalClass, classTransform));
|
||||
* }
|
||||
*
|
||||
* @see ConstantPoolBuilder#of() ConstantPoolBuilder::of()
|
||||
*/
|
||||
NEW_POOL
|
||||
}
|
||||
|
||||
@@ -230,17 +267,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>
|
||||
|
||||
@@ -34,6 +34,8 @@ import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import jdk.internal.classfile.components.ClassPrinter;
|
||||
|
||||
/**
|
||||
* A {@link ClassFileElement} that has complex structure defined in terms of
|
||||
* other classfile elements, such as a method, field, method body, or entire
|
||||
@@ -92,4 +94,14 @@ public sealed interface CompoundElement<E extends ClassFileElement>
|
||||
return Collections.unmodifiableList(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return a text representation of the compound element and its contents for debugging purposes}
|
||||
*
|
||||
* The format, structure and exact contents of the returned string are not specified and may change at any time in the future.
|
||||
*/
|
||||
default String toDebugString() {
|
||||
StringBuilder text = new StringBuilder();
|
||||
ClassPrinter.toYaml(this, ClassPrinter.Verbosity.TRACE_ALL, text::append);
|
||||
return text.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -28,10 +28,9 @@ import java.lang.classfile.AnnotationValue;
|
||||
import java.lang.constant.ConstantDesc;
|
||||
|
||||
/**
|
||||
* A constant pool entry that may be used by annotation constant values,
|
||||
* which includes the four kinds of primitive constants and UTF8 constants.
|
||||
* These entries are also the only entries that do not refer to other
|
||||
* constant pool entries.
|
||||
* Marker interface for constant pool entries that can represent constant values
|
||||
* associated with elements of annotations. They are also the only entries that
|
||||
* do not refer to other constant pool entries.
|
||||
*
|
||||
* @apiNote
|
||||
* An annotation constant value entry alone is not sufficient to determine
|
||||
@@ -40,6 +39,7 @@ import java.lang.constant.ConstantDesc;
|
||||
* in {@link AnnotationValue.OfInt}.
|
||||
*
|
||||
* @see AnnotationValue.OfConstant
|
||||
* @jvms 4.7.16.1 The {@code element_value} structure
|
||||
* @sealedGraph
|
||||
* @since 24
|
||||
*/
|
||||
@@ -47,9 +47,9 @@ public sealed interface AnnotationConstantValueEntry extends PoolEntry
|
||||
permits DoubleEntry, FloatEntry, IntegerEntry, LongEntry, Utf8Entry {
|
||||
|
||||
/**
|
||||
* {@return the constant value} The constant value will be an {@link Integer},
|
||||
* {@link Long}, {@link Float}, {@link Double} for the primitive constants,
|
||||
* or {@link String} for UTF8 constants.
|
||||
* {@return the constant value} The constant value will be an {@link
|
||||
* Integer}, {@link Long}, {@link Float}, {@link Double} for the primitive
|
||||
* constants, or {@link String} for UTF8 constants.
|
||||
*/
|
||||
ConstantDesc constantValue();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -30,33 +30,82 @@ import java.lang.constant.ConstantDesc;
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_Class_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.1 The CONSTANT_Class_info Structure
|
||||
* Models a {@code CONSTANT_Class_info} structure, representing a reference
|
||||
* type, in the constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* The use of a {@code ClassEntry} is modeled by a {@link ClassDesc} that is not
|
||||
* primitive. Conversions are through {@link ConstantPoolBuilder#classEntry(
|
||||
* ClassDesc)} and {@link #asSymbol()}.
|
||||
* <p>
|
||||
* A {@code ClassEntry} is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="ClassEntry" target="ConstantPoolBuilder#classEntry(Utf8Entry)" :
|
||||
* ClassEntry(Utf8Entry name) // @link substring="name" target="#name"
|
||||
* }
|
||||
* where {@code name} represents:
|
||||
* <ul>
|
||||
* <li>The internal form of a binary name (JVMS {@jvms 4.2.1}), if and only if
|
||||
* this {@code ClassEntry} represents a class or interface, such as {@code
|
||||
* java/lang/String} for the {@link String} class.
|
||||
* <li>A field descriptor string (JVMS {@jvms 4.3.2}) representing an array type,
|
||||
* if and only if this {@code ClassEntry} represents an array type, such as
|
||||
* {@code [I} for the {@code int[]} type, or {@code [Ljava/lang/String;} for the
|
||||
* {@code String[]} type.
|
||||
* </ul>
|
||||
* A field descriptor string for an array type can be distinguished by its
|
||||
* leading {@code '['} character.
|
||||
*
|
||||
* @apiNote
|
||||
* The internal form of a binary name, where all occurrences of {@code .} in the
|
||||
* name are replaced by {@code /}, is informally known as an <dfn>{@index
|
||||
* "internal name"}</dfn>. This concept also applies to package names in
|
||||
* addition to class and interface names.
|
||||
*
|
||||
* @see ConstantPoolBuilder#classEntry ConstantPoolBuilder::classEntry
|
||||
* @see ClassDesc
|
||||
* @jvms 4.4.1 The {@code CONSTANT_Class_info} Structure
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface ClassEntry
|
||||
extends LoadableConstantEntry
|
||||
permits AbstractPoolEntry.ClassEntryImpl {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* This is equivalent to {@link #asSymbol() asSymbol()}.
|
||||
*/
|
||||
@Override
|
||||
default ConstantDesc constantValue() {
|
||||
return asSymbol();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the UTF8 constant pool entry for the class name}
|
||||
* {@return the {@code Utf8Entry} referred by this structure} If the
|
||||
* value of the UTF8 starts with a {@code [}, this represents an array type
|
||||
* and the value is a descriptor string; otherwise, this represents a class
|
||||
* or interface and the value is the {@linkplain ##internalname internal
|
||||
* form} of a binary name.
|
||||
*
|
||||
* @see ConstantPoolBuilder#classEntry(Utf8Entry)
|
||||
* ConstantPoolBuilder::classEntry(Utf8Entry)
|
||||
*/
|
||||
Utf8Entry name();
|
||||
|
||||
/**
|
||||
* {@return the class name, as an internal binary name}
|
||||
* {@return the represented reference type, as the {@linkplain
|
||||
* ##internalname internal form} of a binary name or an array descriptor
|
||||
* string} This is a shortcut for {@link #name() name().stringValue()}.
|
||||
*/
|
||||
String asInternalName();
|
||||
|
||||
/**
|
||||
* {@return the class name, as a symbolic descriptor}
|
||||
* {@return the represented reference type, as a symbolic descriptor} The
|
||||
* returned descriptor is never {@linkplain ClassDesc#isPrimitive()
|
||||
* primitive}.
|
||||
*
|
||||
* @see ConstantPoolBuilder#classEntry(ClassDesc)
|
||||
* ConstantPoolBuilder::classEntry(ClassDesc)
|
||||
*/
|
||||
ClassDesc asSymbol();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -33,10 +33,36 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_Dynamic_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
|
||||
* Models a {@code CONSTANT_Dynamic_info} structure, representing a <dfn>{@index
|
||||
* "dynamically-computed constant"}</dfn>, in the constant pool of a {@code
|
||||
* class} file.
|
||||
* <p>
|
||||
* The use of a {@code ConstantDynamicEntry} is modeled by a {@link
|
||||
* DynamicConstantDesc}. Conversions are through {@link #asSymbol()} and {@link
|
||||
* ConstantPoolBuilder#constantDynamicEntry(DynamicConstantDesc)}.
|
||||
* <p>
|
||||
* A dynamic constant entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="ConstantDynamicEntry" target="ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)" :
|
||||
* ConstantDynamicEntry(
|
||||
* BootstrapMethodEntry bootstrap, // @link substring="bootstrap" target="#bootstrap()"
|
||||
* NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()"
|
||||
* )
|
||||
* }
|
||||
* where {@link #type() nameAndType.type()} is a {@linkplain #typeSymbol()
|
||||
* field descriptor} string.
|
||||
*
|
||||
* @apiNote
|
||||
* A dynamically-computed constant is frequently called a <dfn>{@index "dynamic
|
||||
* constant"}</dfn>, or a <dfn>{@index "condy"}</dfn>, from the abbreviation of
|
||||
* "constant dynamic".
|
||||
*
|
||||
* @see ConstantPoolBuilder#constantDynamicEntry
|
||||
* ConstantPoolBuilder::constantDynamicEntry
|
||||
* @see DynamicConstantDesc
|
||||
* @see java.lang.invoke##condycon Dynamically-computed constants
|
||||
* @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code
|
||||
* CONSTANT_InvokeDynamic_info} Structures
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface ConstantDynamicEntry
|
||||
@@ -44,19 +70,28 @@ public sealed interface ConstantDynamicEntry
|
||||
permits AbstractPoolEntry.ConstantDynamicEntryImpl {
|
||||
|
||||
/**
|
||||
* {@return a symbolic descriptor for the dynamic constant's type}
|
||||
* {@return a symbolic descriptor for the {@linkplain #type() field type} of
|
||||
* this dynamically-computed constant}
|
||||
*/
|
||||
default ClassDesc typeSymbol() {
|
||||
return Util.fieldTypeSymbol(type());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* This is equivalent to {@link #asSymbol() asSymbol()}.
|
||||
*/
|
||||
@Override
|
||||
default ConstantDesc constantValue() {
|
||||
return asSymbol();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the symbolic descriptor for the {@code invokedynamic} constant}
|
||||
* {@return a symbolic descriptor for this dynamically-computed constant}
|
||||
*
|
||||
* @see ConstantPoolBuilder#constantDynamicEntry(DynamicConstantDesc)
|
||||
* ConstantPoolBuilder::constantDynamicEntry(DynamicConstantDesc)
|
||||
*/
|
||||
default DynamicConstantDesc<?> asSymbol() {
|
||||
return DynamicConstantDesc.ofNamed(bootstrap().bootstrapMethod().asSymbol(),
|
||||
@@ -68,10 +103,15 @@ public sealed interface ConstantDynamicEntry
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the type of the constant}
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @apiNote
|
||||
* The data type of a dynamically-computed constant depends on its
|
||||
* {@linkplain #type() descriptor}, while the data type of all other
|
||||
* constants can be determined by their {@linkplain #tag() constant type}.
|
||||
*/
|
||||
@Override
|
||||
default TypeKind typeKind() {
|
||||
return TypeKind.fromDescriptor(type().stringValue());
|
||||
return TypeKind.fromDescriptor(type());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -27,14 +27,22 @@ package java.lang.classfile.constantpool;
|
||||
|
||||
import java.lang.classfile.BootstrapMethodEntry;
|
||||
import java.lang.classfile.ClassReader;
|
||||
import java.lang.classfile.attribute.BootstrapMethodsAttribute;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* Provides read access to the constant pool and bootstrap method table of a
|
||||
* classfile.
|
||||
* @jvms 4.4 The Constant Pool
|
||||
* Provides read access to the constant pool and the bootstrap method table of a
|
||||
* {@code class} file.
|
||||
*
|
||||
* <h2 id="index">Index in the Constant Pool</h2>
|
||||
* The constant pool entries are accessed by index. A valid index is in the
|
||||
* range of {@link #size() [1, size())}. It is {@linkplain PoolEntry#width()
|
||||
* unusable} if a {@link LongEntry} or {@link DoubleEntry} is at its previous
|
||||
* index.
|
||||
*
|
||||
* @see BootstrapMethodsAttribute
|
||||
* @jvms 4.4 The Constant Pool
|
||||
* @sealedGraph
|
||||
* @since 24
|
||||
*/
|
||||
@@ -46,7 +54,7 @@ public sealed interface ConstantPool extends Iterable<PoolEntry>
|
||||
*
|
||||
* @apiNote
|
||||
* If only a particular type of entry is expected, use {@link #entryByIndex(
|
||||
* int, Class) entryByIndex(int, Class)}.
|
||||
* int, Class)}.
|
||||
*
|
||||
* @param index the index within the pool of the desired entry
|
||||
* @throws ConstantPoolException if the index is out of range of the
|
||||
@@ -55,7 +63,11 @@ public sealed interface ConstantPool extends Iterable<PoolEntry>
|
||||
PoolEntry entryByIndex(int index);
|
||||
|
||||
/**
|
||||
* {@return the size of the constant pool}
|
||||
* {@return the exclusive upper bound of the valid indices of this constant
|
||||
* pool} The actual number of entries is lower because {@code 0}, {@code
|
||||
* size()} are not valid, and a valid index may be unusable.
|
||||
*
|
||||
* @see ##index Index in the Constant Pool
|
||||
*/
|
||||
int size();
|
||||
|
||||
@@ -66,12 +78,17 @@ public sealed interface ConstantPool extends Iterable<PoolEntry>
|
||||
* @param index the index within the pool of the desired entry
|
||||
* @param cls the entry type
|
||||
* @throws ConstantPoolException if the index is out of range of the
|
||||
* constant pool, or the entry is not of the given type
|
||||
* constant pool or considered unusable, or the entry is not
|
||||
* of the given type
|
||||
*/
|
||||
<T extends PoolEntry> T entryByIndex(int index, Class<T> cls);
|
||||
|
||||
/**
|
||||
* {@return an iterator over pool entries}
|
||||
*
|
||||
* @apiNote
|
||||
* This skips any unusable index and is less error-prone than iterating by
|
||||
* raw index. See <em>{@linkplain ##index Index in the Constant Pool}</em>.
|
||||
*/
|
||||
@Override
|
||||
default Iterator<PoolEntry> iterator() {
|
||||
@@ -93,7 +110,6 @@ public sealed interface ConstantPool extends Iterable<PoolEntry>
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@return the {@link BootstrapMethodEntry} at the specified index within
|
||||
* the bootstrap method table}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -25,10 +25,16 @@
|
||||
package java.lang.classfile.constantpool;
|
||||
|
||||
import java.lang.classfile.BootstrapMethodEntry;
|
||||
import java.lang.classfile.ClassBuilder;
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.ClassFileBuilder;
|
||||
import java.lang.classfile.ClassModel;
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.attribute.ConstantValueAttribute;
|
||||
import java.lang.classfile.instruction.ConstantInstruction;
|
||||
import java.lang.constant.*;
|
||||
import java.lang.invoke.MethodHandleInfo;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry.ClassEntryImpl;
|
||||
import jdk.internal.classfile.impl.ClassReaderImpl;
|
||||
@@ -39,14 +45,45 @@ import jdk.internal.classfile.impl.Util;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Builder for the constant pool of a classfile. Provides read and write access
|
||||
* to the constant pool that is being built. Writing is append-only and idempotent
|
||||
* (entry-bearing methods will return an existing entry if there is one).
|
||||
* Builder for the constant pool of a {@code class} file. Provides read and
|
||||
* write access to the constant pool that is {@linkplain ClassFileBuilder#constantPool()
|
||||
* being built}. Writing is append-only (the index of new entries monotonically
|
||||
* increase) and idempotent (entry-bearing methods will return an existing entry
|
||||
* if there is a suitable one).
|
||||
* <p>
|
||||
* For {@code class} file building, an overload of {@link ClassFile#build(
|
||||
* ClassEntry, ConstantPoolBuilder, Consumer) ClassFile::build} takes a
|
||||
* {@code ConstantPoolBuilder}. For {@code class} file transformations via
|
||||
* {@link ClassFile#transformClass ClassFile::transformClass}, the {@link
|
||||
* ClassFile.ConstantPoolSharingOption} controls how the constant pool builder
|
||||
* of the resulting {@code class} is created.
|
||||
*
|
||||
* A {@linkplain ConstantPoolBuilder} is associated with a {@link ClassBuilder}.
|
||||
* The {@linkplain ConstantPoolBuilder} also provides access to some of the
|
||||
* state of the {@linkplain ClassBuilder}, such as classfile processing options.
|
||||
* <h2 id="alien">Alien Constant Pool Entries</h2>
|
||||
* In {@code class} file building and constant pool building, some constant pool
|
||||
* entries supplied may be {@linkplain #canWriteDirect(ConstantPool) alien}
|
||||
* to this constant pool builder of the active class file builder. For example,
|
||||
* {@link #classEntry(Utf8Entry) classEntry(Utf8Entry)} may be called with an
|
||||
* alien UTF8 entry. Alien entries will be converted to a pool entry in
|
||||
* this constant pool builder, reusing equivalent entries or adding new entries
|
||||
* if there is none. As a result, all pool entries returned by entry-bearing
|
||||
* methods in this constant pool builder belong to this constant pool.
|
||||
* <p>
|
||||
* Some {@link ClassFileBuilder} methods may have their outputs adjusted if they
|
||||
* receive pool entries alien to {@linkplain ClassFileBuilder#constantPool
|
||||
* their constant pools}. For example, if an {@link ConstantInstruction#ofLoad
|
||||
* ldc_w} instruction with an alien entry is written to a {@link CodeBuilder},
|
||||
* the {@code CodeBuilder} may emit a functionally equivalent {@code ldc}
|
||||
* instruction instead, if the converted entry can be encoded in such an
|
||||
* instruction.
|
||||
* <p>
|
||||
* To avoid the conversion of alien constant pool entries, such as for the
|
||||
* accuracy of the generated {@code class} file, users can always supply
|
||||
* constant pool entries obtained by calling the constant pool builder
|
||||
* entry-bearing methods of the constant pools associated with the {@code
|
||||
* ClassFileBuilder}. Otherwise, the conversions have no impact on the
|
||||
* behaviors of the generated {@code class} files.
|
||||
*
|
||||
* @see ClassFileBuilder#constantPool()
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface ConstantPoolBuilder
|
||||
@@ -55,10 +92,14 @@ public sealed interface ConstantPoolBuilder
|
||||
|
||||
/**
|
||||
* {@return a new constant pool builder} The new constant pool builder will
|
||||
* be pre-populated with the contents of the constant pool associated with
|
||||
* the class reader.
|
||||
* be pre-populated with the contents of the constant pool {@linkplain
|
||||
* ClassModel#constantPool() associated with} the given class model. The
|
||||
* index of new entries will start from the {@link ConstantPool#size()
|
||||
* size()} of the source pool.
|
||||
*
|
||||
* @param classModel the class to copy from
|
||||
* @see ClassFile#build(ClassEntry, ConstantPoolBuilder, Consumer)
|
||||
* @see ClassFile.ConstantPoolSharingOption#SHARED_POOL
|
||||
*/
|
||||
static ConstantPoolBuilder of(ClassModel classModel) {
|
||||
return new SplitConstantPool((ClassReaderImpl) classModel.constantPool());
|
||||
@@ -66,35 +107,47 @@ public sealed interface ConstantPoolBuilder
|
||||
|
||||
/**
|
||||
* {@return a new constant pool builder} The new constant pool builder
|
||||
* will be empty.
|
||||
* will be empty. The index of new entries will start from {@code 1}.
|
||||
*
|
||||
* @see ClassFile.ConstantPoolSharingOption#NEW_POOL
|
||||
*/
|
||||
static ConstantPoolBuilder of() {
|
||||
return new SplitConstantPool();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return whether the provided constant pool is index-compatible with this
|
||||
* one} This may be because they are the same constant pool, or because this
|
||||
* constant pool was copied from the other.
|
||||
* {@return {@code true} if the index of any entry in the given constant
|
||||
* pool refers to the same entry in this builder} This may be because they
|
||||
* are the same builder, or because this builder was {@linkplain
|
||||
* #of(ClassModel) pre-populated} from the given constant pool.
|
||||
* <p>
|
||||
* If the constant pool of an entry is not directly writable to this pool,
|
||||
* it is alien to this pool, and a {@link ClassFileBuilder} associated
|
||||
* with this constant pool will convert that alien constant pool entry.
|
||||
*
|
||||
* @param constantPool the other constant pool
|
||||
* @param constantPool the given constant pool
|
||||
* @see ClassFileBuilder#constantPool() ClassFileBuilder::constantPool
|
||||
* @see ##alien Alien Constant Pool Entries
|
||||
*/
|
||||
boolean canWriteDirect(ConstantPool constantPool);
|
||||
|
||||
/**
|
||||
* {@return A {@link Utf8Entry} describing the provided {@linkplain String}}
|
||||
* If a UTF8 entry in the pool already describes this string, it is returned;
|
||||
* otherwise, a new entry is added and the new entry is returned.
|
||||
* {@return a {@link Utf8Entry} describing the provided {@link String}}
|
||||
*
|
||||
* @param s the string
|
||||
* @see Utf8Entry#stringValue() Utf8Entry::stringValue
|
||||
*/
|
||||
Utf8Entry utf8Entry(String s);
|
||||
|
||||
/**
|
||||
* {@return A {@link Utf8Entry} describing the field descriptor of the provided
|
||||
* {@linkplain ClassDesc}}
|
||||
* If a UTF8 entry in the pool already describes this field descriptor, it is returned;
|
||||
* otherwise, a new entry is added and the new entry is returned.
|
||||
* {@return a {@link Utf8Entry} describing the {@linkplain
|
||||
* ClassDesc#descriptorString() field descriptor string} of the provided
|
||||
* {@link ClassDesc}}
|
||||
*
|
||||
* @apiNote
|
||||
* The resulting {@code Utf8Entry} is usually not {@linkplain
|
||||
* #classEntry(Utf8Entry) referable by} a {@link ClassEntry}, which uses
|
||||
* internal form of binary names.
|
||||
*
|
||||
* @param desc the symbolic descriptor for the class
|
||||
*/
|
||||
@@ -103,10 +156,9 @@ public sealed interface ConstantPoolBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link Utf8Entry} describing the method descriptor of the provided
|
||||
* {@linkplain MethodTypeDesc}}
|
||||
* If a UTF8 entry in the pool already describes this field descriptor, it is returned;
|
||||
* otherwise, a new entry is added and the new entry is returned.
|
||||
* {@return a {@link Utf8Entry} describing the {@linkplain
|
||||
* MethodTypeDesc#descriptorString() method descriptor string} of the
|
||||
* provided {@link MethodTypeDesc}}
|
||||
*
|
||||
* @param desc the symbolic descriptor for the method type
|
||||
*/
|
||||
@@ -115,25 +167,24 @@ public sealed interface ConstantPoolBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link ClassEntry} describing the class whose internal name
|
||||
* is encoded in the provided {@linkplain Utf8Entry}}
|
||||
* If a Class entry in the pool already describes this class,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link ClassEntry} referring to the provided {@link
|
||||
* Utf8Entry}} The {@code Utf8Entry} describes the internal form
|
||||
* of the binary name of a class or interface or the field descriptor
|
||||
* string of an array type.
|
||||
*
|
||||
* @param ne the constant pool entry describing the internal name of the class
|
||||
* @param ne the {@code Utf8Entry}
|
||||
* @see ClassEntry#name() ClassEntry::name
|
||||
*/
|
||||
ClassEntry classEntry(Utf8Entry ne);
|
||||
|
||||
/**
|
||||
* {@return A {@link ClassEntry} describing the class described by
|
||||
* provided {@linkplain ClassDesc}}
|
||||
* If a Class entry in the pool already describes this class,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link ClassEntry} describing the same reference type
|
||||
* as the provided {@link ClassDesc}}
|
||||
*
|
||||
* @param classDesc the symbolic descriptor for the class
|
||||
* @throws IllegalArgumentException if {@code classDesc} represents a primitive type
|
||||
* @param classDesc the symbolic descriptor for the reference type
|
||||
* @throws IllegalArgumentException if {@code classDesc} represents a
|
||||
* primitive type
|
||||
* @see ClassEntry#asSymbol() ClassEntry::asSymbol
|
||||
*/
|
||||
default ClassEntry classEntry(ClassDesc classDesc) {
|
||||
if (requireNonNull(classDesc).isPrimitive()) {
|
||||
@@ -145,196 +196,191 @@ public sealed interface ConstantPoolBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link PackageEntry} describing the class whose internal name
|
||||
* is encoded in the provided {@linkplain Utf8Entry}}
|
||||
* If a Package entry in the pool already describes this class,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link PackageEntry} referring to the provided {@link
|
||||
* Utf8Entry}} The {@code Utf8Entry} describes the internal form
|
||||
* of the name of a package.
|
||||
*
|
||||
* @param nameEntry the constant pool entry describing the internal name of
|
||||
* the package
|
||||
* @param nameEntry the {@code Utf8Entry}
|
||||
* @see PackageEntry#name() PackageEntry::name
|
||||
*/
|
||||
PackageEntry packageEntry(Utf8Entry nameEntry);
|
||||
|
||||
/**
|
||||
* {@return A {@link PackageEntry} describing the class described by
|
||||
* provided {@linkplain PackageDesc}}
|
||||
* If a Package entry in the pool already describes this class,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link PackageEntry} describing the same package as the
|
||||
* provided {@link PackageDesc}}
|
||||
*
|
||||
* @param packageDesc the symbolic descriptor for the class
|
||||
* @param packageDesc the symbolic descriptor for the package
|
||||
* @see PackageEntry#asSymbol() PackageEntry::asSymbol
|
||||
*/
|
||||
default PackageEntry packageEntry(PackageDesc packageDesc) {
|
||||
return packageEntry(utf8Entry(packageDesc.internalName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link ModuleEntry} describing the module whose name
|
||||
* is encoded in the provided {@linkplain Utf8Entry}}
|
||||
* If a module entry in the pool already describes this class,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link ModuleEntry} referring to the provided {@link
|
||||
* Utf8Entry}} The {@code Utf8Entry} describes the module name.
|
||||
*
|
||||
* @param moduleName the constant pool entry describing the module name
|
||||
* @see ModuleEntry#name() ModuleEntry::name
|
||||
*/
|
||||
ModuleEntry moduleEntry(Utf8Entry moduleName);
|
||||
|
||||
/**
|
||||
* {@return A {@link ModuleEntry} describing the module described by
|
||||
* provided {@linkplain ModuleDesc}}
|
||||
* If a module entry in the pool already describes this class,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link ModuleEntry} describing the same module as the provided
|
||||
* {@link ModuleDesc}}
|
||||
*
|
||||
* @param moduleDesc the symbolic descriptor for the class
|
||||
* @param moduleDesc the symbolic descriptor for the module
|
||||
* @see ModuleEntry#asSymbol() ModuleEntry::asSymbol
|
||||
*/
|
||||
default ModuleEntry moduleEntry(ModuleDesc moduleDesc) {
|
||||
return moduleEntry(utf8Entry(moduleDesc.name()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link NameAndTypeEntry} describing the provided name and type}
|
||||
* If a NameAndType entry in the pool already describes this name and type,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link NameAndTypeEntry} referring to the provided name and
|
||||
* type {@link Utf8Entry}} The name {@code Utf8Entry} describes an
|
||||
* unqualified name or the special name {@value ConstantDescs#INIT_NAME},
|
||||
* and the type {@code Utf8Entry} describes a field or method descriptor
|
||||
* string.
|
||||
*
|
||||
* @param nameEntry the member name
|
||||
* @param typeEntry the member field or method descriptor
|
||||
* @param nameEntry the name {@code Utf8Entry}
|
||||
* @param typeEntry the type {@code Utf8Entry}
|
||||
* @see NameAndTypeEntry#name() NameAndTypeEntry::name
|
||||
* @see NameAndTypeEntry#type() NameAndTypeEntry::type
|
||||
*/
|
||||
NameAndTypeEntry nameAndTypeEntry(Utf8Entry nameEntry, Utf8Entry typeEntry);
|
||||
|
||||
/**
|
||||
* {@return A {@link NameAndTypeEntry} describing the provided name and type}
|
||||
* If a NameAndType entry in the pool already describes this name and type,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link NameAndTypeEntry} describing the provided unqualified
|
||||
* name and field descriptor}
|
||||
*
|
||||
* @param name the member name
|
||||
* @param type the symbolic descriptor for a field type
|
||||
* @param name the unqualified name
|
||||
* @param type the field descriptor
|
||||
*/
|
||||
default NameAndTypeEntry nameAndTypeEntry(String name, ClassDesc type) {
|
||||
return nameAndTypeEntry(utf8Entry(name), utf8Entry(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link NameAndTypeEntry} describing the provided name and type}
|
||||
* If a NameAndType entry in the pool already describes this name and type,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link NameAndTypeEntry} describing the provided name and
|
||||
* method descriptor} The name can be an unqualified name or the
|
||||
* special name {@value ConstantDescs#INIT_NAME}.
|
||||
*
|
||||
* @param name the member name
|
||||
* @param type the symbolic descriptor for a method type
|
||||
* @param name the unqualified name, or {@value ConstantDescs#INIT_NAME}
|
||||
* @param type the method descriptor
|
||||
*/
|
||||
default NameAndTypeEntry nameAndTypeEntry(String name, MethodTypeDesc type) {
|
||||
return nameAndTypeEntry(utf8Entry(name), utf8Entry(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link FieldRefEntry} describing a field of a class}
|
||||
* If a FieldRef entry in the pool already describes this field,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link FieldRefEntry} referring to a {@link ClassEntry} and a
|
||||
* {@link NameAndTypeEntry}} The {@code ClassEntry} describes a class or
|
||||
* interface that has this field as a member, and the {@code
|
||||
* NameAndTypeEntry} describes the unqualified name and the field descriptor
|
||||
* for this field.
|
||||
*
|
||||
* @param owner the class the field is a member of
|
||||
* @param nameAndType the name and type of the field
|
||||
* @param owner the {@code ClassEntry}
|
||||
* @param nameAndType the {@code NameAndTypeEntry}
|
||||
* @see FieldRefEntry#owner() FieldRefEntry::owner
|
||||
* @see FieldRefEntry#nameAndType() FieldRefEntry::nameAndType
|
||||
*/
|
||||
FieldRefEntry fieldRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType);
|
||||
|
||||
/**
|
||||
* {@return A {@link FieldRefEntry} describing a field of a class}
|
||||
* If a FieldRef entry in the pool already describes this field,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link FieldRefEntry} describing a field of a class}
|
||||
*
|
||||
* @param owner the class the field is a member of
|
||||
* @param name the name of the field
|
||||
* @param type the type of the field
|
||||
* @param owner the class or interface the field is a member of
|
||||
* @param name the unqualified name of the field
|
||||
* @param type the field descriptor
|
||||
* @throws IllegalArgumentException if {@code owner} represents a primitive type
|
||||
* @see FieldRefEntry#typeSymbol() FieldRefEntry::typeSymbol
|
||||
*/
|
||||
default FieldRefEntry fieldRefEntry(ClassDesc owner, String name, ClassDesc type) {
|
||||
return fieldRefEntry(classEntry(owner), nameAndTypeEntry(name, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link MethodRefEntry} describing a method of a class}
|
||||
* If a MethodRefEntry entry in the pool already describes this method,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link MethodRefEntry} referring to a {@link ClassEntry} and a
|
||||
* {@link NameAndTypeEntry}} The {@code ClassEntry} describes a class that
|
||||
* has this method as a member, and the {@code NameAndTypeEntry} describes
|
||||
* the unqualified name or the special name {@value ConstantDescs#INIT_NAME}
|
||||
* and the method descriptor for this method.
|
||||
*
|
||||
* @param owner the class the method is a member of
|
||||
* @param nameAndType the name and type of the method
|
||||
* @param owner the {@code ClassEntry}
|
||||
* @param nameAndType the {@code NameAndTypeEntry}
|
||||
* @see MethodRefEntry#owner() MethodRefEntry::owner
|
||||
* @see MethodRefEntry#nameAndType() MethodRefEntry::nameAndType
|
||||
*/
|
||||
MethodRefEntry methodRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType);
|
||||
|
||||
/**
|
||||
* {@return A {@link MethodRefEntry} describing a method of a class}
|
||||
* If a MethodRefEntry entry in the pool already describes this method,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link MethodRefEntry} describing a method of a class}
|
||||
*
|
||||
* @param owner the class the method is a member of
|
||||
* @param name the name of the method
|
||||
* @param type the type of the method
|
||||
* @param name the unqualified name, or special name {@value
|
||||
* ConstantDescs#INIT_NAME}, of the method
|
||||
* @param type the method descriptor
|
||||
* @throws IllegalArgumentException if {@code owner} represents a primitive type
|
||||
* @see MethodRefEntry#typeSymbol() MethodRefEntry::typeSymbol
|
||||
*/
|
||||
default MethodRefEntry methodRefEntry(ClassDesc owner, String name, MethodTypeDesc type) {
|
||||
return methodRefEntry(classEntry(owner), nameAndTypeEntry(name, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link InterfaceMethodRefEntry} describing a method of a class}
|
||||
* If a InterfaceMethodRefEntry entry in the pool already describes this method,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return an {@link InterfaceMethodRefEntry} referring to a {@link
|
||||
* ClassEntry} and a {@link NameAndTypeEntry}} The {@code ClassEntry}
|
||||
* describes an interface that has this method as a member, and the {@code
|
||||
* NameAndTypeEntry} describes the unqualified name and the method
|
||||
* descriptor for this method.
|
||||
*
|
||||
* @param owner the class the method is a member of
|
||||
* @param nameAndType the name and type of the method
|
||||
* @param owner the {@code ClassEntry}
|
||||
* @param nameAndType the {@code NameAndTypeEntry}
|
||||
* @see InterfaceMethodRefEntry#owner() InterfaceMethodRefEntry::owner
|
||||
* @see InterfaceMethodRefEntry#nameAndType()
|
||||
* InterfaceMethodRefEntry::nameAndType
|
||||
*/
|
||||
InterfaceMethodRefEntry interfaceMethodRefEntry(ClassEntry owner, NameAndTypeEntry nameAndType);
|
||||
|
||||
/**
|
||||
* {@return A {@link InterfaceMethodRefEntry} describing a method of a class}
|
||||
* If a InterfaceMethodRefEntry entry in the pool already describes this method,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return an {@link InterfaceMethodRefEntry} describing a method of an
|
||||
* interface}
|
||||
*
|
||||
* @param owner the class the method is a member of
|
||||
* @param name the name of the method
|
||||
* @param type the type of the method
|
||||
* @param owner the interface the method is a member of
|
||||
* @param name the unqualified name of the method
|
||||
* @param type the method descriptor
|
||||
* @throws IllegalArgumentException if {@code owner} represents a primitive type
|
||||
* @see InterfaceMethodRefEntry#typeSymbol() InterfaceMethodRefEntry::typeSymbol
|
||||
*/
|
||||
default InterfaceMethodRefEntry interfaceMethodRefEntry(ClassDesc owner, String name, MethodTypeDesc type) {
|
||||
return interfaceMethodRefEntry(classEntry(owner), nameAndTypeEntry(name, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link MethodTypeEntry} describing a method type}
|
||||
* If a MethodType entry in the pool already describes this method type,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link MethodTypeEntry} describing the same method type as
|
||||
* the provided {@link MethodTypeDesc}}
|
||||
*
|
||||
* @param descriptor the symbolic descriptor of the method type
|
||||
* @see MethodTypeEntry#asSymbol() MethodTypeEntry::asSymbol
|
||||
*/
|
||||
MethodTypeEntry methodTypeEntry(MethodTypeDesc descriptor);
|
||||
|
||||
/**
|
||||
* {@return A {@link MethodTypeEntry} describing a method type}
|
||||
* If a MethodType entry in the pool already describes this method type,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link MethodTypeEntry} referring to a {@link Utf8Entry}}
|
||||
* The {@code Utf8Entry} represents a method descriptor string.
|
||||
*
|
||||
* @param descriptor the constant pool entry for the method type descriptor
|
||||
* @param descriptor the {@code Utf8Entry}
|
||||
* @see MethodTypeEntry#descriptor() MethodTypeEntry::descriptor
|
||||
*/
|
||||
MethodTypeEntry methodTypeEntry(Utf8Entry descriptor);
|
||||
|
||||
/**
|
||||
* {@return A {@link MethodHandleEntry} describing a direct method handle}
|
||||
* If a MethodHandle entry in the pool already describes this method handle,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link MethodHandleEntry} describing the same method handle as
|
||||
* the given {@link DirectMethodHandleDesc}}
|
||||
*
|
||||
* @param descriptor the symbolic descriptor of the method handle
|
||||
* @see MethodHandleEntry#asSymbol() MethodHandleEntry::asSymbol
|
||||
*/
|
||||
default MethodHandleEntry methodHandleEntry(DirectMethodHandleDesc descriptor) {
|
||||
var owner = classEntry(descriptor.owner());
|
||||
@@ -347,125 +393,133 @@ public sealed interface ConstantPoolBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link MethodHandleEntry} describing a field accessor or method}
|
||||
* If a MethodHandle entry in the pool already describes this method handle,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link MethodHandleEntry} encoding a reference kind and
|
||||
* referring to a {@link MemberRefEntry}} The reference kind must be
|
||||
* in {@code [1, 9]}, and the {@code MemberRefEntry} is subject to
|
||||
* various restrictions based on the reference kind (JVMS {@jvms 4.4.8}).
|
||||
*
|
||||
* @param refKind the reference kind of the method handle (JVMS {@jvms 4.4.8})
|
||||
* @param reference the constant pool entry describing the field or method
|
||||
* @param refKind the reference kind of the method handle
|
||||
* @param reference the {@code MemberRefEntry}
|
||||
* @see MethodHandleInfo##refkinds Reference kinds
|
||||
* @see MethodHandleEntry#kind() MethodHandleEntry::kind
|
||||
* @see MethodHandleEntry#reference() MethodHandleEntry::reference
|
||||
*/
|
||||
MethodHandleEntry methodHandleEntry(int refKind, MemberRefEntry reference);
|
||||
|
||||
/**
|
||||
* {@return An {@link InvokeDynamicEntry} describing a dynamic call site}
|
||||
* If an InvokeDynamic entry in the pool already describes this site,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return an {@link InvokeDynamicEntry} describing the same dynamic call
|
||||
* site as the provided {@link DynamicCallSiteDesc}}
|
||||
*
|
||||
* @param dcsd the symbolic descriptor of the method handle
|
||||
* @param dcsd the symbolic descriptor of the dynamic call site
|
||||
* @see InvokeDynamicEntry#asSymbol() InvokeDynamicEntry::asSymbol
|
||||
*/
|
||||
default InvokeDynamicEntry invokeDynamicEntry(DynamicCallSiteDesc dcsd) {
|
||||
return invokeDynamicEntry(bsmEntry((DirectMethodHandleDesc)dcsd.bootstrapMethod(), List.of(dcsd.bootstrapArgs())), nameAndTypeEntry(dcsd.invocationName(), dcsd.invocationType()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return An {@link InvokeDynamicEntry} describing a dynamic call site}
|
||||
* If an InvokeDynamic entry in the pool already describes this site,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return an {@link InvokeDynamicEntry} referring to a {@link
|
||||
* BootstrapMethodEntry} and a {@link NameAndTypeEntry}}
|
||||
* The {@code BootstrapMethodEntry} describes the bootstrap method
|
||||
* and its invocation arguments in addition to the name and type,
|
||||
* and the {@code NameAndTypeEntry} a name and a method descriptor.
|
||||
*
|
||||
* @param bootstrapMethodEntry the entry in the bootstrap method table
|
||||
* @param nameAndType the invocation name and type
|
||||
* @param bootstrapMethodEntry the {@code BootstrapMethodEntry}
|
||||
* @param nameAndType the {@code NameAndTypeEntry}
|
||||
* @see InvokeDynamicEntry#bootstrap() InvokeDynamicEntry::bootstrap
|
||||
* @see InvokeDynamicEntry#nameAndType() InvokeDynamicEntry::nameAndType
|
||||
*/
|
||||
InvokeDynamicEntry invokeDynamicEntry(BootstrapMethodEntry bootstrapMethodEntry,
|
||||
NameAndTypeEntry nameAndType);
|
||||
|
||||
/**
|
||||
* {@return A {@link ConstantDynamicEntry} describing a dynamic constant}
|
||||
* If a ConstantDynamic entry in the pool already describes this site,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link ConstantDynamicEntry} describing the dynamic constant
|
||||
* as the provided {@link DynamicConstantDesc}}
|
||||
*
|
||||
* @param dcd the symbolic descriptor of the constant
|
||||
* @see ConstantDynamicEntry#asSymbol() ConstantDynamicEntry::asSymbol
|
||||
*/
|
||||
default ConstantDynamicEntry constantDynamicEntry(DynamicConstantDesc<?> dcd) {
|
||||
return constantDynamicEntry(bsmEntry(dcd.bootstrapMethod(), List.of(dcd.bootstrapArgs())), nameAndTypeEntry(dcd.constantName(), dcd.constantType()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link ConstantDynamicEntry} describing a dynamic constant}
|
||||
* If a ConstantDynamic entry in the pool already describes this site,
|
||||
* it is returned; otherwise, a new entry is added and the new entry is
|
||||
* returned.
|
||||
* {@return a {@link ConstantDynamicEntry} referring to a {@link
|
||||
* BootstrapMethodEntry} and a {@link NameAndTypeEntry}}
|
||||
* The {@code BootstrapMethodEntry} describes the bootstrap method
|
||||
* and its invocation arguments in addition to the name and type,
|
||||
* and the {@code NameAndTypeEntry} a name and a field descriptor.
|
||||
*
|
||||
* @param bootstrapMethodEntry the entry in the bootstrap method table
|
||||
* @param nameAndType the invocation name and type
|
||||
* @param bootstrapMethodEntry the {@code BootstrapMethodEntry}
|
||||
* @param nameAndType the {@code NameAndTypeEntry}
|
||||
* @see ConstantDynamicEntry#bootstrap() ConstantDynamicEntry::bootstrap
|
||||
* @see ConstantDynamicEntry#nameAndType() ConstantDynamicEntry::nameAndType
|
||||
*/
|
||||
ConstantDynamicEntry constantDynamicEntry(BootstrapMethodEntry bootstrapMethodEntry, NameAndTypeEntry nameAndType);
|
||||
|
||||
/**
|
||||
* {@return An {@link IntegerEntry} describing the provided value}
|
||||
* If an integer entry in the pool already describes this value, it is returned;
|
||||
* otherwise, a new entry is added and the new entry is returned.
|
||||
* {@return an {@link IntegerEntry} describing the provided value}
|
||||
*
|
||||
* @param value the value
|
||||
* @see IntegerEntry#intValue() IntegerEntry::intValue
|
||||
*/
|
||||
IntegerEntry intEntry(int value);
|
||||
|
||||
/**
|
||||
* {@return A {@link FloatEntry} describing the provided value}
|
||||
* If a float entry in the pool already describes this value, it is returned;
|
||||
* otherwise, a new entry is added and the new entry is returned.
|
||||
* {@return a {@link FloatEntry} describing the provided value}
|
||||
*
|
||||
* @param value the value
|
||||
* @see FloatEntry#floatValue() FloatEntry::floatValue
|
||||
*/
|
||||
FloatEntry floatEntry(float value);
|
||||
|
||||
/**
|
||||
* {@return A {@link LongEntry} describing the provided value}
|
||||
* If a long entry in the pool already describes this value, it is returned;
|
||||
* otherwise, a new entry is added and the new entry is returned.
|
||||
* {@return a {@link LongEntry} describing the provided value}
|
||||
*
|
||||
* @param value the value
|
||||
* @see LongEntry#longValue() LongEntry::longValue
|
||||
*/
|
||||
LongEntry longEntry(long value);
|
||||
|
||||
/**
|
||||
* {@return A {@link DoubleEntry} describing the provided value}
|
||||
* If a double entry in the pool already describes this value, it is returned;
|
||||
* otherwise, a new entry is added and the new entry is returned.
|
||||
* {@return a {@link DoubleEntry} describing the provided value}
|
||||
*
|
||||
* @param value the value
|
||||
* @see DoubleEntry#doubleValue() DoubleEntry::doubleValue
|
||||
*/
|
||||
DoubleEntry doubleEntry(double value);
|
||||
|
||||
/**
|
||||
* {@return A {@link StringEntry} referencing the provided UTF8 entry}
|
||||
* If a String entry in the pool already describes this value, it is returned;
|
||||
* otherwise, a new entry is added and the new entry is returned.
|
||||
* {@return a {@link StringEntry} referring to a {@link Utf8Entry}}
|
||||
* The {@code Utf8Entry} describes the string value.
|
||||
*
|
||||
* @param utf8 the UTF8 entry describing the string
|
||||
* @param utf8 the {@code Utf8Entry}
|
||||
* @see StringEntry#utf8() StringEntry::utf8
|
||||
*/
|
||||
StringEntry stringEntry(Utf8Entry utf8);
|
||||
|
||||
/**
|
||||
* {@return A {@link StringEntry} describing the provided value}
|
||||
* If a string entry in the pool already describes this value, it is returned;
|
||||
* otherwise, a new entry is added and the new entry is returned.
|
||||
* {@return a {@link StringEntry} describing the provided value}
|
||||
*
|
||||
* @param value the value
|
||||
* @see StringEntry#stringValue() StringEntry::stringValue
|
||||
*/
|
||||
default StringEntry stringEntry(String value) {
|
||||
return stringEntry(utf8Entry(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link ConstantValueEntry} describing the provided
|
||||
* Integer, Long, Float, Double, or String constant}
|
||||
* {@return a {@link ConstantValueEntry} describing the provided constant
|
||||
* {@link Integer}, {@link Long}, {@link Float}, {@link Double}, or {@link
|
||||
* String} value}
|
||||
*
|
||||
* @param c the constant
|
||||
* @see ConstantValueEntry#constantValue()
|
||||
* @param c the provided constant value
|
||||
* @throws IllegalArgumentException if the value is not one of {@code
|
||||
* Integer}, {@code Long}, {@code Float}, {@code Double}, or {@code
|
||||
* String}
|
||||
* @see ConstantValueEntry#constantValue() ConstantValueEntry::constantValue
|
||||
* @see ConstantValueAttribute#of(ConstantDesc)
|
||||
* ConstantValueAttribute::of(ConstantDesc)
|
||||
*/
|
||||
default ConstantValueEntry constantValueEntry(ConstantDesc c) {
|
||||
if (c instanceof Integer i) return intEntry(i);
|
||||
@@ -477,13 +531,10 @@ public sealed interface ConstantPoolBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return A {@link LoadableConstantEntry} describing the provided
|
||||
* constant} The constant should be an Integer, String, Long, Float,
|
||||
* Double, ClassDesc (for a Class constant), MethodTypeDesc (for a MethodType
|
||||
* constant), DirectMethodHandleDesc (for a MethodHandle constant), or
|
||||
* a DynamicConstantDesc (for a dynamic constant.)
|
||||
* {@return a {@link LoadableConstantEntry} describing the provided constant
|
||||
* value}
|
||||
*
|
||||
* @param c the constant
|
||||
* @param c the nominal descriptor for the constant
|
||||
*/
|
||||
default LoadableConstantEntry loadableConstantEntry(ConstantDesc c) {
|
||||
if (c instanceof Integer i) return intEntry(i);
|
||||
@@ -500,10 +551,10 @@ public sealed interface ConstantPoolBuilder
|
||||
|
||||
/**
|
||||
* {@return a {@link BootstrapMethodEntry} describing the provided
|
||||
* bootstrap method and static arguments}
|
||||
* bootstrap method and arguments}
|
||||
*
|
||||
* @param methodReference the bootstrap method
|
||||
* @param arguments the bootstrap arguments
|
||||
* @param arguments the arguments
|
||||
*/
|
||||
default BootstrapMethodEntry bsmEntry(DirectMethodHandleDesc methodReference,
|
||||
List<ConstantDesc> arguments) {
|
||||
@@ -512,11 +563,16 @@ public sealed interface ConstantPoolBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return a {@link BootstrapMethodEntry} describing the provided
|
||||
* bootstrap method and static arguments}
|
||||
* {@return a {@link BootstrapMethodEntry} referring to a {@link
|
||||
* MethodHandleEntry} and a list of {@link LoadableConstantEntry}}
|
||||
* The {@code MethodHandleEntry} is the bootstrap method, and the
|
||||
* list of {@code LoadableConstantEntry} is the arguments.
|
||||
*
|
||||
* @param methodReference the bootstrap method
|
||||
* @param arguments the bootstrap arguments
|
||||
* @param methodReference the {@code MethodHandleEntry}
|
||||
* @param arguments the list of {@code LoadableConstantEntry}
|
||||
* @see BootstrapMethodEntry#bootstrapMethod()
|
||||
* BootstrapMethodEntry::bootstrapMethod
|
||||
* @see BootstrapMethodEntry#arguments() BootstrapMethodEntry::arguments
|
||||
*/
|
||||
BootstrapMethodEntry bsmEntry(MethodHandleEntry methodReference,
|
||||
List<LoadableConstantEntry> arguments);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 2025, 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
|
||||
@@ -27,7 +27,9 @@ package java.lang.classfile.constantpool;
|
||||
|
||||
/**
|
||||
* Thrown to indicate that requested entry cannot be obtained from the constant
|
||||
* pool.
|
||||
* pool or the bootstrap method table. This is also thrown when the lazy
|
||||
* evaluation of constant pool or bootstrap method table entries encounter
|
||||
* format errors.
|
||||
*
|
||||
* @since 24
|
||||
*/
|
||||
@@ -47,7 +49,8 @@ public class ConstantPoolException extends IllegalArgumentException {
|
||||
* Constructs a {@code ConstantPoolException} with the specified detail
|
||||
* message.
|
||||
*
|
||||
* @param message the detail message.
|
||||
* @param message the detail message, may be {@code null} for no detail
|
||||
* message
|
||||
*/
|
||||
public ConstantPoolException(String message) {
|
||||
super(message);
|
||||
@@ -55,11 +58,10 @@ public class ConstantPoolException extends IllegalArgumentException {
|
||||
|
||||
/**
|
||||
* Constructs a {@code ConstantPoolException} with the specified cause and
|
||||
* a detail message of {@code (cause==null ? null : cause.toString())}.
|
||||
* @param cause the cause (which is saved for later retrieval by the
|
||||
* {@link Throwable#getCause()} method). (A {@code null} value is
|
||||
* permitted, and indicates that the cause is nonexistent or
|
||||
* unknown.)
|
||||
* a detail message of {@code cause == null ? null : cause.toString()}.
|
||||
*
|
||||
* @param cause the cause, may be {@code null} for nonexistent or unknown
|
||||
* cause
|
||||
*/
|
||||
public ConstantPoolException(Throwable cause) {
|
||||
super(cause);
|
||||
@@ -69,12 +71,10 @@ public class ConstantPoolException extends IllegalArgumentException {
|
||||
* Constructs a {@code ConstantPoolException} with the specified detail
|
||||
* message and cause.
|
||||
*
|
||||
* @param message the detail message (which is saved for later retrieval
|
||||
* by the {@link Throwable#getMessage()} method).
|
||||
* @param cause the cause (which is saved for later retrieval by the
|
||||
* {@link Throwable#getCause()} method). (A {@code null} value
|
||||
* is permitted, and indicates that the cause is nonexistent or
|
||||
* unknown.)
|
||||
* @param message the detail message, may be {@code null} for no detail
|
||||
* message
|
||||
* @param cause the cause, may be {@code null} for nonexistent or unknown
|
||||
* cause
|
||||
*/
|
||||
public ConstantPoolException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -28,10 +28,11 @@ import java.lang.classfile.Attributes;
|
||||
import java.lang.constant.ConstantDesc;
|
||||
|
||||
/**
|
||||
* Models a constant pool entry that can be used as the constant in a
|
||||
* {@link Attributes#constantValue() ConstantValue} attribute; this includes the four
|
||||
* primitive constant types and {@linkplain String} constants.
|
||||
* Marker interface for constant pool entries that can represent constant values
|
||||
* in the {@link Attributes#constantValue() ConstantValue} attribute.
|
||||
*
|
||||
* @see ConstantPoolBuilder#constantValueEntry
|
||||
* ConstantPoolBuilder::constantValueEntry
|
||||
* @sealedGraph
|
||||
* @since 24
|
||||
*/
|
||||
@@ -39,8 +40,8 @@ public sealed interface ConstantValueEntry extends LoadableConstantEntry
|
||||
permits DoubleEntry, FloatEntry, IntegerEntry, LongEntry, StringEntry {
|
||||
|
||||
/**
|
||||
* {@return the constant value} The constant value will be an {@link Integer},
|
||||
* {@link Long}, {@link Float}, {@link Double}, or {@link String}.
|
||||
* {@return the constant value} The constant value will be an {@link
|
||||
* Integer}, {@link Long}, {@link Float}, {@link Double}, or {@link String}.
|
||||
*
|
||||
* @see ConstantPoolBuilder#constantValueEntry(ConstantDesc)
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -29,10 +29,20 @@ import java.lang.classfile.TypeKind;
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_Double_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures
|
||||
* Models a {@code CONSTANT_Double_info} structure, representing a {@code
|
||||
* double} constant, in the constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* The use of a {@code DoubleEntry} is modeled by a {@code double}. Conversions
|
||||
* are through {@link ConstantPoolBuilder#doubleEntry} and {@link #doubleValue()}.
|
||||
* In the conversions, all NaN values of the {@code double} may be collapsed
|
||||
* into a single {@linkplain Double#NaN "canonical" NaN value}.
|
||||
* <p>
|
||||
* A double entry has a {@linkplain #width() width} of {@code 2}, making its
|
||||
* subsequent constant pool index valid and unusable.
|
||||
*
|
||||
* @see ConstantPoolBuilder#doubleEntry ConstantPoolBuilder::doubleEntry
|
||||
* @jvms 4.4.5 The {@code CONSTANT_Long_info} and {@code CONSTANT_Double_info}
|
||||
* Structures
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface DoubleEntry
|
||||
@@ -40,13 +50,13 @@ public sealed interface DoubleEntry
|
||||
permits AbstractPoolEntry.DoubleEntryImpl {
|
||||
|
||||
/**
|
||||
* {@return the double value}
|
||||
* {@return the {@code double} value}
|
||||
*
|
||||
* @see ConstantPoolBuilder#doubleEntry(double)
|
||||
* ConstantPoolBuilder::doubleEntry(double)
|
||||
*/
|
||||
double doubleValue();
|
||||
|
||||
/**
|
||||
* {@return the type of the constant}
|
||||
*/
|
||||
@Override
|
||||
default TypeKind typeKind() {
|
||||
return TypeKind.DOUBLE;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -27,10 +27,27 @@ package java.lang.classfile.constantpool;
|
||||
import java.lang.classfile.BootstrapMethodEntry;
|
||||
|
||||
/**
|
||||
* Models a dynamic constant pool entry, which is either {@link ConstantDynamicEntry}
|
||||
* or {@link InvokeDynamicEntry}.
|
||||
* @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
|
||||
* Superinterface modeling dynamically-computed constant pool entries, which
|
||||
* include {@link ConstantDynamicEntry} and {@link InvokeDynamicEntry}, in the
|
||||
* constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* Different types of dynamically-computed constant pool entries bear structural
|
||||
* similarities, but they appear in distinct locations. As a result, their uses
|
||||
* are represented by different symbolic descriptors, specific to each subtype.
|
||||
* <p>
|
||||
* A dynamic constant entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* DynamicConstantPoolEntry(
|
||||
* BootstrapMethodEntry bootstrap, // @link substring="bootstrap" target="#bootstrap()"
|
||||
* NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()"
|
||||
* )
|
||||
* }
|
||||
*
|
||||
* @see java.lang.invoke##jvm_mods Dynamic resolution of call sites and
|
||||
* constants
|
||||
* @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code
|
||||
* CONSTANT_InvokeDynamic_info} Structures
|
||||
* @jvms 5.4.3.6 Dynamically-Computed Constant and Call Site Resolution
|
||||
* @sealedGraph
|
||||
* @since 24
|
||||
*/
|
||||
@@ -39,28 +56,50 @@ public sealed interface DynamicConstantPoolEntry extends PoolEntry
|
||||
|
||||
/**
|
||||
* {@return the entry in the bootstrap method table for this constant}
|
||||
*
|
||||
* @see java.lang.invoke##bsm Execution of bootstrap methods
|
||||
* @see ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)
|
||||
* ConstantPoolBuilder::constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)
|
||||
* @see ConstantPoolBuilder#invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)
|
||||
* ConstantPoolBuilder::invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)
|
||||
*/
|
||||
BootstrapMethodEntry bootstrap();
|
||||
|
||||
/**
|
||||
* {@return index of the entry in the bootstrap method table for this constant}
|
||||
* {@return index of the entry in the bootstrap method table for this
|
||||
* constant} The return value is equivalent to {@code
|
||||
* bootstrap().bsmIndex()}.
|
||||
*/
|
||||
int bootstrapMethodIndex();
|
||||
|
||||
/**
|
||||
* {@return the invocation name and type}
|
||||
* {@return the name and the descriptor string indicated by this symbolic
|
||||
* reference}
|
||||
*
|
||||
* @see java.lang.invoke##bsm Execution of bootstrap methods
|
||||
* @see ConstantPoolBuilder#constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)
|
||||
* ConstantPoolBuilder::constantDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)
|
||||
* @see ConstantPoolBuilder#invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)
|
||||
* ConstantPoolBuilder::invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)
|
||||
*/
|
||||
NameAndTypeEntry nameAndType();
|
||||
|
||||
/**
|
||||
* {@return the invocation name}
|
||||
* {@return the name indicated by this symbolic reference}
|
||||
*/
|
||||
default Utf8Entry name() {
|
||||
return nameAndType().name();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the invocation type}
|
||||
* {@return the descriptor string indicated by this symbolic reference}
|
||||
* This is a field descriptor string if this entry is a {@link
|
||||
* ConstantDynamicEntry}, or a method descriptor string if this entry is a
|
||||
* {@link InvokeDynamicEntry}.
|
||||
*
|
||||
* @apiNote
|
||||
* Each subinterface has its specific accessor named {@code typeSymbol} for
|
||||
* the symbolic descriptor derived from this descriptor string.
|
||||
*/
|
||||
default Utf8Entry type() {
|
||||
return nameAndType().type();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -30,17 +30,31 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_Fieldref_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures
|
||||
* Models a {@code CONSTANT_Fieldref_info} structure, or a symbolic reference
|
||||
* to a field, in the constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* A field reference constant pool entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="FieldRefEntry" target="ConstantPoolBuilder#fieldRefEntry(ClassEntry, NameAndTypeEntry)" :
|
||||
* FieldRefEntry(
|
||||
* ClassEntry owner, // @link substring="owner" target="#owner()"
|
||||
* NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()"
|
||||
* )
|
||||
* }
|
||||
* where the {@link #type() nameAndType.type()} represents a {@linkplain
|
||||
* #typeSymbol() field descriptor} string.
|
||||
*
|
||||
* @see ConstantPoolBuilder#fieldRefEntry ConstantPoolBuilder::fieldRefEntry
|
||||
* @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code
|
||||
* CONSTANT_Methodref_info}, and {@code
|
||||
* CONSTANT_InterfaceMethodref_info} Structures
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface FieldRefEntry extends MemberRefEntry
|
||||
permits AbstractPoolEntry.FieldRefEntryImpl {
|
||||
|
||||
/**
|
||||
* {@return a symbolic descriptor for the field's type}
|
||||
* {@return a symbolic descriptor for the {@linkplain #type() field type}}
|
||||
*/
|
||||
default ClassDesc typeSymbol() {
|
||||
return Util.fieldTypeSymbol(type());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -29,10 +29,17 @@ import java.lang.classfile.TypeKind;
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_Float_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures
|
||||
* Models a {@code CONSTANT_Float_info} structure, or a {@code float} constant,
|
||||
* in the constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* The use of a {@code FloatEntry} is modeled by a {@code float}. Conversions
|
||||
* are through {@link ConstantPoolBuilder#floatEntry} and {@link #floatValue()}.
|
||||
* In the conversions, all NaN values of the {@code float} may be collapsed into
|
||||
* a single {@linkplain Float#NaN "canonical" NaN value}.
|
||||
*
|
||||
* @see ConstantPoolBuilder#floatEntry ConstantPoolBuilder::floatEntry
|
||||
* @jvms 4.4.4 The {@code CONSTANT_Integer_info} and {@code CONSTANT_Float_info}
|
||||
* Structures
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface FloatEntry
|
||||
@@ -40,14 +47,12 @@ public sealed interface FloatEntry
|
||||
permits AbstractPoolEntry.FloatEntryImpl {
|
||||
|
||||
/**
|
||||
* {@return the float value}
|
||||
* {@return the {@code float} value}
|
||||
*
|
||||
* @see ConstantPoolBuilder#floatEntry(float)
|
||||
*/
|
||||
|
||||
float floatValue();
|
||||
|
||||
/**
|
||||
* {@return the type of the constant}
|
||||
*/
|
||||
@Override
|
||||
default TypeKind typeKind() {
|
||||
return TypeKind.FLOAT;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -29,10 +29,15 @@ import java.lang.classfile.TypeKind;
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_Integer_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.4 The CONSTANT_Integer_info and CONSTANT_Float_info Structures
|
||||
* Models a {@code CONSTANT_Integer_info} structure, or an {@code int} constant,
|
||||
* in the constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* The use of a {@code IntegerEntry} is modeled by an {@code int}. Conversions
|
||||
* are through {@link ConstantPoolBuilder#intEntry(int)} and {@link #intValue()}.
|
||||
*
|
||||
* @see ConstantPoolBuilder#intEntry ConstantPoolBuilder::intEntry
|
||||
* @jvms 4.4.4 The {@code CONSTANT_Integer_info} and {@code CONSTANT_Float_info}
|
||||
* Structures
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface IntegerEntry
|
||||
@@ -40,13 +45,12 @@ public sealed interface IntegerEntry
|
||||
permits AbstractPoolEntry.IntegerEntryImpl {
|
||||
|
||||
/**
|
||||
* {@return the integer value}
|
||||
* {@return the {@code int} value}
|
||||
*
|
||||
* @see ConstantPoolBuilder#intEntry(int)
|
||||
*/
|
||||
int intValue();
|
||||
|
||||
/**
|
||||
* {@return the type of the constant}
|
||||
*/
|
||||
@Override
|
||||
default TypeKind typeKind() {
|
||||
return TypeKind.INT;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -30,10 +30,26 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_InterfaceMethodRef_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures
|
||||
* Models a {@code CONSTANT_InterfaceMethodRef_info} structure, or a symbolic
|
||||
* reference to an interface method, in the constant pool of a {@code class}
|
||||
* file.
|
||||
* <p>
|
||||
* An interface method reference entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="InterfaceMethodRefEntry" target="ConstantPoolBuilder#interfaceMethodRefEntry(ClassEntry, NameAndTypeEntry)" :
|
||||
* InterfaceMethodRefEntry(
|
||||
* ClassEntry owner, // @link substring="owner" target="#owner()"
|
||||
* NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()"
|
||||
* )
|
||||
* }
|
||||
* where the {@link #type() type} in the {@code nameAndType} is a {@linkplain
|
||||
* #typeSymbol() method descriptor} string.
|
||||
*
|
||||
* @see ConstantPoolBuilder#interfaceMethodRefEntry
|
||||
* ConstantPoolBuilder::interfaceMethodRefEntry
|
||||
* @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code
|
||||
* CONSTANT_Methodref_info}, and {@code
|
||||
* CONSTANT_InterfaceMethodref_info} Structures
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface InterfaceMethodRefEntry
|
||||
@@ -41,7 +57,7 @@ public sealed interface InterfaceMethodRefEntry
|
||||
permits AbstractPoolEntry.InterfaceMethodRefEntryImpl {
|
||||
|
||||
/**
|
||||
* {@return a symbolic descriptor for the interface method's type}
|
||||
* {@return a symbolic descriptor for the {@linkplain #type() method type}}
|
||||
*/
|
||||
default MethodTypeDesc typeSymbol() {
|
||||
return Util.methodTypeSymbol(type());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -32,9 +32,38 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a constant pool entry for a dynamic call site.
|
||||
* @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
|
||||
* Models a {@code CONSTANT_InvokeDynamic_info} structure, or the symbolic
|
||||
* reference to a <dfn>{@index "dynamically-computed call site"}</dfn>, in the
|
||||
* constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* The use of a {@code InvokeDynamicEntry} is modeled by a {@link
|
||||
* DynamicCallSiteDesc} symbolic descriptor. It can be obtained from {@link
|
||||
* #asSymbol() InvokeDynamicEntry::asSymbol} and converted back to a constant
|
||||
* pool entry through {@link ConstantPoolBuilder#invokeDynamicEntry(DynamicCallSiteDesc)
|
||||
* ConstantPoolBuilder::invokeDynamicEntry}.
|
||||
* <p>
|
||||
* An invoke dynamic entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="InvokeDynamicEntry" target="ConstantPoolBuilder#invokeDynamicEntry(BootstrapMethodEntry, NameAndTypeEntry)" :
|
||||
* InvokeDynamicEntry(
|
||||
* BootstrapMethodEntry bootstrap, // @link substring="bootstrap" target="#bootstrap()"
|
||||
* NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()"
|
||||
* )
|
||||
* }
|
||||
* where the {@link #type() type} in the {@code nameAndType} is a {@linkplain
|
||||
* #typeSymbol() method descriptor} string.
|
||||
*
|
||||
* @apiNote
|
||||
* A dynamically-computed call site is frequently called a <dfn>{@index "dynamic
|
||||
* call site"}</dfn>, or an <dfn>{@index "indy"}</dfn>, from the abbreviation of
|
||||
* "invoke dynamic".
|
||||
*
|
||||
* @see ConstantPoolBuilder#invokeDynamicEntry
|
||||
* ConstantPoolBuilder::invokeDynamicEntry
|
||||
* @see DynamicCallSiteDesc
|
||||
* @see java.lang.invoke##indyinsn Dynamically-computed call sites
|
||||
* @jvms 4.4.10 The {@code CONSTANT_Dynamic_info} and {@code
|
||||
* CONSTANT_InvokeDynamic_info} Structures
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface InvokeDynamicEntry
|
||||
@@ -42,14 +71,18 @@ public sealed interface InvokeDynamicEntry
|
||||
permits AbstractPoolEntry.InvokeDynamicEntryImpl {
|
||||
|
||||
/**
|
||||
* {@return a symbolic descriptor for the call site's invocation type}
|
||||
* {@return a symbolic descriptor for the {@linkplain #type() invocation
|
||||
* type} of this dynamic call site}
|
||||
*/
|
||||
default MethodTypeDesc typeSymbol() {
|
||||
return Util.methodTypeSymbol(type());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return a symbolic descriptor for the dynamic call site}
|
||||
* {@return a symbolic descriptor for this dynamic call site}
|
||||
*
|
||||
* @see ConstantPoolBuilder#invokeDynamicEntry(DynamicCallSiteDesc)
|
||||
* ConstantPoolBuilder::invokeDynamicEntry(DynamicCallSiteDesc)
|
||||
*/
|
||||
default DynamicCallSiteDesc asSymbol() {
|
||||
return DynamicCallSiteDesc.of(bootstrap().bootstrapMethod().asSymbol(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -24,13 +24,22 @@
|
||||
*/
|
||||
package java.lang.classfile.constantpool;
|
||||
|
||||
import java.lang.classfile.CodeBuilder;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.lang.classfile.TypeKind;
|
||||
import java.lang.classfile.instruction.ConstantInstruction;
|
||||
import java.lang.constant.ConstantDesc;
|
||||
|
||||
/**
|
||||
* Marker interface for constant pool entries suitable for loading via the
|
||||
* {@code LDC} instructions.
|
||||
* {@link ConstantInstruction.LoadConstantInstruction ldc} instructions.
|
||||
* <p>
|
||||
* The use of a {@code LoadableConstantEntry} is modeled by a {@link ConstantDesc}.
|
||||
* Conversions are through {@link ConstantPoolBuilder#loadableConstantEntry(ConstantDesc)}
|
||||
* and {@link #constantValue()}.
|
||||
*
|
||||
* @see CodeBuilder#ldc(LoadableConstantEntry)
|
||||
* @jvms 4.4 The Constant Pool
|
||||
* @sealedGraph
|
||||
* @since 24
|
||||
*/
|
||||
@@ -38,12 +47,19 @@ public sealed interface LoadableConstantEntry extends PoolEntry
|
||||
permits ClassEntry, ConstantDynamicEntry, ConstantValueEntry, MethodHandleEntry, MethodTypeEntry {
|
||||
|
||||
/**
|
||||
* {@return the constant described by this entry}
|
||||
* {@return a symbolic descriptor of this constant}
|
||||
*
|
||||
* @see ConstantPoolBuilder#loadableConstantEntry(ConstantDesc)
|
||||
*/
|
||||
ConstantDesc constantValue();
|
||||
|
||||
/**
|
||||
* {@return the type of the constant}
|
||||
* {@return the data type of this constant}
|
||||
* <p>
|
||||
* If the data type is of {@linkplain TypeKind#slotSize() category} 2, this
|
||||
* constant must be loaded with {@link Opcode#LDC2_W ldc2_w}; otherwise, the
|
||||
* data type is of category 1, and this constant must be loaded with {@link
|
||||
* Opcode#LDC ldc} or {@link Opcode#LDC_W ldc_w}.
|
||||
*/
|
||||
default TypeKind typeKind() {
|
||||
return TypeKind.REFERENCE;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -29,10 +29,18 @@ import java.lang.classfile.TypeKind;
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_Long_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.5 The CONSTANT_Long_info and CONSTANT_Double_info Structures
|
||||
* Models a {@code CONSTANT_Long_info} structure, or a {@code long} constant, in
|
||||
* the constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* The use of a {@code LongEntry} is modeled by a {@code long}. Conversions are
|
||||
* through {@link ConstantPoolBuilder#longEntry(long)} and {@link #longValue()}.
|
||||
* <p>
|
||||
* A long entry has a {@linkplain #width() width} of {@code 2}, making its
|
||||
* subsequent constant pool index valid and unusable.
|
||||
*
|
||||
* @see ConstantPoolBuilder#longEntry ConstantPoolBuilder::longEntry
|
||||
* @jvms 4.4.5 The {@code CONSTANT_Long_info} and {@code CONSTANT_Double_info}
|
||||
* Structures
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface LongEntry
|
||||
@@ -40,7 +48,10 @@ public sealed interface LongEntry
|
||||
permits AbstractPoolEntry.LongEntryImpl {
|
||||
|
||||
/**
|
||||
* {@return the long value}
|
||||
* {@return the {@code long} value}
|
||||
*
|
||||
* @see ConstantPoolBuilder#longEntry(long)
|
||||
* ConstantPoolBuilder::longEntry(long)
|
||||
*/
|
||||
long longValue();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -24,24 +24,45 @@
|
||||
*/
|
||||
package java.lang.classfile.constantpool;
|
||||
|
||||
import java.lang.classfile.Opcode;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a member reference constant in the constant pool of a classfile,
|
||||
* which includes references to fields, methods, and interface methods.
|
||||
* Superinterface modeling symbolic references to a member of a class or interface
|
||||
* in the constant pool of a {@code class} file, which include references to
|
||||
* {@linkplain FieldRefEntry fields}, {@linkplain MethodRefEntry class methods},
|
||||
* and {@linkplain InterfaceMethodRefEntry interface methods}.
|
||||
* <p>
|
||||
* Different types of symbolic references to a member of a class or interface
|
||||
* bear structural similarities and share parts of the resolution processes, and
|
||||
* they can sometimes appear in the same locations. For example, both {@link
|
||||
* MethodRefEntry} and {@link InterfaceMethodRefEntry} can appear in an {@link
|
||||
* Opcode#INVOKESTATIC invokestatic} instruction.
|
||||
* <p>
|
||||
* A member reference entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* MemberRefEntry(
|
||||
* ClassEntry owner, // @link substring="owner" target="#owner()"
|
||||
* NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()"
|
||||
* )
|
||||
* }
|
||||
*
|
||||
* @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code
|
||||
* CONSTANT_Methodref_info}, and {@code
|
||||
* CONSTANT_InterfaceMethodref_info} Structures
|
||||
* @sealedGraph
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface MemberRefEntry extends PoolEntry
|
||||
permits FieldRefEntry, InterfaceMethodRefEntry, MethodRefEntry, AbstractPoolEntry.AbstractMemberRefEntry {
|
||||
/**
|
||||
* {@return the class in which this member ref lives}
|
||||
* {@return the class or interface which this member belongs to}
|
||||
*/
|
||||
ClassEntry owner();
|
||||
|
||||
/**
|
||||
* {@return the name and type of the member}
|
||||
* {@return the name and descriptor string of the member}
|
||||
*/
|
||||
NameAndTypeEntry nameAndType();
|
||||
|
||||
@@ -53,7 +74,14 @@ public sealed interface MemberRefEntry extends PoolEntry
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the type of the member}
|
||||
* {@return the descriptor string of the member} This is a field descriptor
|
||||
* string if this entry is a {@link FieldRefEntry}, or a method descriptor
|
||||
* string if this entry is a {@link MethodRefEntry} or {@link
|
||||
* InterfaceMethodRefEntry}.
|
||||
*
|
||||
* @apiNote
|
||||
* Each subinterface defines a {@code typeSymbol()} accessor for the
|
||||
* symbolic descriptor for the member type.
|
||||
*/
|
||||
default Utf8Entry type() {
|
||||
return nameAndType().type();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -26,13 +26,35 @@ package java.lang.classfile.constantpool;
|
||||
|
||||
import java.lang.constant.ConstantDesc;
|
||||
import java.lang.constant.DirectMethodHandleDesc;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandleInfo;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_MethodHandle_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.8 The CONSTANT_MethodHandle_info Structure
|
||||
* Models a {@code CONSTANT_MethodHandle_info} structure, or a symbolic
|
||||
* reference to a {@linkplain MethodHandle method handle}, in the constant pool
|
||||
* of a {@code class} file. The method handle directly accesses an accessible
|
||||
* method, field, or constructor.
|
||||
* <p>
|
||||
* The use of a {@code MethodHandleEntry} is modeled by a {@link
|
||||
* DirectMethodHandleDesc}. Conversions are through {@link
|
||||
* ConstantPoolBuilder#methodHandleEntry(DirectMethodHandleDesc)} and {@link
|
||||
* #asSymbol()}.
|
||||
* <p>
|
||||
* A method handle entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="MethodHandleEntry" target="ConstantPoolBuilder#methodHandleEntry(int, MemberRefEntry)" :
|
||||
* MethodHandleEntry(
|
||||
* int refKind, // @link substring="refKind" target="#kind()"
|
||||
* MemberRefEntry reference // @link substring="reference" target="#reference()"
|
||||
* )
|
||||
* }
|
||||
* where {@code refKind} is in the range {@code [1, 9]}.
|
||||
*
|
||||
* @see ConstantPoolBuilder#methodHandleEntry
|
||||
* ConstantPoolBuilder::methodHandleEntry
|
||||
* @jvms 4.4.8 The {@code CONSTANT_MethodHandle_info} Structure
|
||||
*
|
||||
* @since 24
|
||||
*/
|
||||
@@ -40,6 +62,11 @@ public sealed interface MethodHandleEntry
|
||||
extends LoadableConstantEntry
|
||||
permits AbstractPoolEntry.MethodHandleEntryImpl {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* This is equivalent to {@link #asSymbol() asSymbol()}.
|
||||
*/
|
||||
@Override
|
||||
default ConstantDesc constantValue() {
|
||||
return asSymbol();
|
||||
@@ -47,17 +74,22 @@ public sealed interface MethodHandleEntry
|
||||
|
||||
/**
|
||||
* {@return the reference kind of this method handle (JVMS {@jvms 4.4.8})}
|
||||
* @see java.lang.invoke.MethodHandleInfo
|
||||
*
|
||||
* @see MethodHandleInfo##refkinds Reference kinds
|
||||
*/
|
||||
int kind();
|
||||
|
||||
/**
|
||||
* {@return the constant pool entry describing the method}
|
||||
* {@return the constant pool entry describing the field or method,
|
||||
* according to the {@linkplain #kind() reference kind}}
|
||||
*/
|
||||
MemberRefEntry reference();
|
||||
|
||||
/**
|
||||
* {@return a symbolic descriptor for this method handle}
|
||||
*
|
||||
* @see ConstantPoolBuilder#methodHandleEntry(DirectMethodHandleDesc)
|
||||
* ConstantPoolBuilder::methodHandleEntry(DirectMethodHandleDesc)
|
||||
*/
|
||||
DirectMethodHandleDesc asSymbol();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -30,17 +30,31 @@ import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
import jdk.internal.classfile.impl.Util;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_MethodRef_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.2 The CONSTANT_Fieldref_info, CONSTANT_Methodref_info, and CONSTANT_InterfaceMethodref_info Structures
|
||||
* Models a {@code CONSTANT_MethodRef_info} structure, or a symbolic reference
|
||||
* to a class method, in the constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* A class method reference entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="MethodRefEntry" target="ConstantPoolBuilder#methodRefEntry(ClassEntry, NameAndTypeEntry)" :
|
||||
* MethodRefEntry(
|
||||
* ClassEntry owner, // @link substring="owner" target="#owner()"
|
||||
* NameAndTypeEntry nameAndType // @link substring="nameAndType" target="#nameAndType()"
|
||||
* )
|
||||
* }
|
||||
* where the type in the {@code NameAndTypeEntry} is a {@linkplain #typeSymbol()
|
||||
* method descriptor} string.
|
||||
*
|
||||
* @see ConstantPoolBuilder#methodRefEntry ConstantPoolBuilder::methodRefEntry
|
||||
* @jvms 4.4.2 The {@code CONSTANT_Fieldref_info}, {@code
|
||||
* CONSTANT_Methodref_info}, and {@code
|
||||
* CONSTANT_InterfaceMethodref_info} Structures
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface MethodRefEntry extends MemberRefEntry
|
||||
permits AbstractPoolEntry.MethodRefEntryImpl {
|
||||
|
||||
/**
|
||||
* {@return a symbolic descriptor for the method's type}
|
||||
* {@return a symbolic descriptor for the {@linkplain #type() method type}}
|
||||
*/
|
||||
default MethodTypeDesc typeSymbol() {
|
||||
return Util.methodTypeSymbol(type());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -30,28 +30,46 @@ import java.lang.constant.MethodTypeDesc;
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_MethodType_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.9 The CONSTANT_MethodType_info Structure
|
||||
* Models a {@code CONSTANT_MethodType_info} structure, or a symbolic reference
|
||||
* to a method type, in the constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* The use of a {@code MethodTypeEntry} is modeled by a {@link MethodTypeDesc}.
|
||||
* Conversions are through {@link ConstantPoolBuilder#methodTypeEntry(MethodTypeDesc)}
|
||||
* and {@link #asSymbol()}.
|
||||
* <p>
|
||||
* A method type entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="MethodTypeEntry" target="ConstantPoolBuilder#methodTypeEntry(Utf8Entry)" :
|
||||
* MethodTypeEntry(Utf8Entry descriptor) // @link substring="descriptor" target="#descriptor()"
|
||||
* }
|
||||
* where {@code descriptor} is a {@linkplain #asSymbol() method descriptor}
|
||||
* string.
|
||||
*
|
||||
* @jvms 4.4.9 The {@code CONSTANT_MethodType_info} Structure
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface MethodTypeEntry
|
||||
extends LoadableConstantEntry
|
||||
permits AbstractPoolEntry.MethodTypeEntryImpl {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* This is equivalent to {@link #asSymbol() asSymbol()}.
|
||||
*/
|
||||
@Override
|
||||
default ConstantDesc constantValue() {
|
||||
return asSymbol();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the constant pool entry describing the method type}
|
||||
* {@return the {@linkplain #asSymbol() method descriptor} string}
|
||||
*/
|
||||
Utf8Entry descriptor();
|
||||
|
||||
/**
|
||||
* {@return a symbolic descriptor for the method type}
|
||||
* {@return a symbolic descriptor for the {@linkplain #descriptor() method
|
||||
* type}}
|
||||
*/
|
||||
MethodTypeDesc asSymbol();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -29,21 +29,32 @@ import java.lang.constant.ModuleDesc;
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_Module_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.11 The CONSTANT_Module_info Structure
|
||||
* Models a {@code CONSTANT_Module_info} structure, denoting a module, in the
|
||||
* constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* The use of a {@code ModuleEntry} is modeled by a {@link ModuleDesc}.
|
||||
* Conversions are through {@link ConstantPoolBuilder#moduleEntry(ModuleDesc)}
|
||||
* and {@link #asSymbol()}.
|
||||
* <p>
|
||||
* A module entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="ModuleEntry" target="ConstantPoolBuilder#moduleEntry(Utf8Entry)" :
|
||||
* ModuleEntry(Utf8Entry name) // @link substring="name" target="#name()"
|
||||
* }
|
||||
* where {@code name} is a {@linkplain #asSymbol() module name}.
|
||||
*
|
||||
* @jvms 4.4.11 The {@code CONSTANT_Module_info} Structure
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface ModuleEntry extends PoolEntry
|
||||
permits AbstractPoolEntry.ModuleEntryImpl {
|
||||
/**
|
||||
* {@return the name of the module}
|
||||
* {@return the name of the {@linkplain #asSymbol() module}}
|
||||
*/
|
||||
Utf8Entry name();
|
||||
|
||||
/**
|
||||
* {@return a symbolic descriptor for the module}
|
||||
* {@return a symbolic descriptor for the {@linkplain #name() module name}}
|
||||
*/
|
||||
ModuleDesc asSymbol();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -24,13 +24,36 @@
|
||||
*/
|
||||
package java.lang.classfile.constantpool;
|
||||
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.constant.MethodTypeDesc;
|
||||
import java.lang.invoke.TypeDescriptor;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_NameAndType_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.6 The CONSTANT_NameAndType_info Structure
|
||||
* Models a {@code CONSTANT_NameAndType_info} structure, representing a field or
|
||||
* method, in the constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* The use of a {@code NameAndTypeEntry} is symbolically represented as a
|
||||
* {@code String name}, and a {@link ConstantPoolBuilder#nameAndTypeEntry(String,
|
||||
* ClassDesc) ClassDesc} or a {@link ConstantPoolBuilder#nameAndTypeEntry(String,
|
||||
* MethodTypeDesc) MethodTypeDesc} {@code type}, depending on where this {@code
|
||||
* NameAndTypeEntry} appears. The accessors to the symbolic descriptors for the
|
||||
* {@code type} is defined on a per-use-site basis, such as {@link
|
||||
* FieldRefEntry#typeSymbol()} returning a {@code ClassDesc}, and {@link
|
||||
* MethodRefEntry#typeSymbol()} returning a {@code MethodTypeDesc}.
|
||||
* <p>
|
||||
* A name and type entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* NameAndTypeEntry( // @link substring="NameAndTypeEntry" target="ConstantPoolBuilder#nameAndTypeEntry(Utf8Entry, Utf8Entry)"
|
||||
* Utf8Entry name, // @link substring="name" target="#name()"
|
||||
* Utf8Entry type // @link substring="type" target="#type()"
|
||||
* )
|
||||
* }
|
||||
* where {@code name} is an unqualified name, and {@code type} is a field or
|
||||
* method descriptor string.
|
||||
*
|
||||
* @jvms 4.4.6 The {@code CONSTANT_NameAndType_info} Structure
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface NameAndTypeEntry extends PoolEntry
|
||||
@@ -42,7 +65,10 @@ public sealed interface NameAndTypeEntry extends PoolEntry
|
||||
Utf8Entry name();
|
||||
|
||||
/**
|
||||
* {@return the field or method descriptor}
|
||||
* {@return the field or method {@linkplain TypeDescriptor descriptor}
|
||||
* string} It is a method descriptor strings if it starts with {@code (}.
|
||||
* Otherwise, it is a field descriptor string, and must start with one of
|
||||
* the {@code BCDFIJSZL[} characters.
|
||||
*/
|
||||
Utf8Entry type();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -29,21 +29,35 @@ import java.lang.constant.PackageDesc;
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_Package_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.12 The CONSTANT_Package_info Structure
|
||||
* Models a {@code CONSTANT_Package_info}, representing a package, in the
|
||||
* constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* The use of a {@code PackageEntry} is represented by a {@link PackageDesc}
|
||||
* that does not represent the unnamed package. Conversions are through
|
||||
* {@link ConstantPoolBuilder#packageEntry(PackageDesc)} and
|
||||
* {@link #asSymbol()}.
|
||||
* <p>
|
||||
* A package entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="PackageEntry" target="ConstantPoolBuilder#packageEntry(Utf8Entry)" :
|
||||
* PackageEntry(Utf8Entry name) // @link substring="name" target="#name()"
|
||||
* }
|
||||
* where {@code name} is the {@linkplain ClassEntry##internalname internal form}
|
||||
* of a binary package name and is not empty.
|
||||
*
|
||||
* @jvms 4.4.12 The {@code CONSTANT_Package_info} Structure
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface PackageEntry extends PoolEntry
|
||||
permits AbstractPoolEntry.PackageEntryImpl {
|
||||
/**
|
||||
* {@return the package name}
|
||||
* {@return the {@linkplain ClassEntry##internalname internal form} of the
|
||||
* {@linkplain #asSymbol() package} name}
|
||||
*/
|
||||
Utf8Entry name();
|
||||
|
||||
/**
|
||||
* {@return a symbolic descriptor for the package name}
|
||||
* {@return a symbolic descriptor for the {@linkplain #name() package name}}
|
||||
*/
|
||||
PackageDesc asSymbol();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -24,9 +24,28 @@
|
||||
*/
|
||||
package java.lang.classfile.constantpool;
|
||||
|
||||
import java.lang.classfile.Attribute;
|
||||
import java.lang.classfile.ClassFileBuilder;
|
||||
import java.lang.classfile.Opcode;
|
||||
import java.lang.classfile.TypeKind;
|
||||
|
||||
/**
|
||||
* Models an entry in the constant pool of a classfile.
|
||||
* Models an entry in the constant pool of a {@code class} file. Entries are
|
||||
* read from {@code class} files, and can be created with a {@link
|
||||
* ConstantPoolBuilder} to write to {@code class} files.
|
||||
*
|
||||
* @implNote
|
||||
* <h2 id="unbound">Unbound Constant Pool Entries</h2>
|
||||
* Implementations may create unbound constant pool entries not belonging to
|
||||
* an actual constant pool. They conveniently represent constant pool entries
|
||||
* referred by unbound {@linkplain Attribute attributes} not read from a {@code
|
||||
* class} file. Their {@link #index() index()} return a non-positive invalid
|
||||
* value, and behaviors of their {@link #constantPool() constantPool()} are
|
||||
* unspecified. They are considered alien to any {@linkplain
|
||||
* ClassFileBuilder#constantPool() contextual constant pool} and will be
|
||||
* converted when they are written to {@code class} files.
|
||||
*
|
||||
* @see ConstantPoolBuilder##alien Alien Constant Pool Entries
|
||||
* @sealedGraph
|
||||
* @since 24
|
||||
*/
|
||||
@@ -88,6 +107,14 @@ public sealed interface PoolEntry
|
||||
|
||||
/**
|
||||
* {@return the constant pool this entry is from}
|
||||
*
|
||||
* @apiNote
|
||||
* Given a {@link ConstantPoolBuilder} {@code builder} and a {@code
|
||||
* PoolEntry entry}, use {@link ConstantPoolBuilder#canWriteDirect
|
||||
* builder.canWriteDirect(entry.constantPool())} instead of object equality
|
||||
* of the constant pool to determine if an entry belongs to the builder.
|
||||
*
|
||||
* @see ##unbound Unbound Constant Pool Entries
|
||||
*/
|
||||
ConstantPool constantPool();
|
||||
|
||||
@@ -102,11 +129,32 @@ public sealed interface PoolEntry
|
||||
|
||||
/**
|
||||
* {@return the index within the constant pool corresponding to this entry}
|
||||
* A valid index is always positive; if the index is non-positive, this
|
||||
* entry is {@linkplain ##unbound unbound}.
|
||||
*
|
||||
* @see ##unbound Unbound Constant Pool Entries
|
||||
*/
|
||||
int index();
|
||||
|
||||
/**
|
||||
* {@return the number of constant pool slots this entry consumes}
|
||||
* <p>
|
||||
* All pool entries except {@link LongEntry CONSTANT_Long} and {@link
|
||||
* DoubleEntry CONSTANT_Double} have width {@code 1}. These two exceptions
|
||||
* have width {@code 2}, and their subsequent indices at {@link #index()
|
||||
* index() + 1} are considered unusable.
|
||||
*
|
||||
* @apiNote
|
||||
* If this entry is {@linkplain LoadableConstantEntry loadable}, the width
|
||||
* of this entry does not decide if this entry should be loaded with {@link
|
||||
* Opcode#LDC ldc} or {@link Opcode#LDC2_W ldc2_w}. For example, {@link
|
||||
* ConstantDynamicEntry} always has width {@code 1}, but it must be loaded
|
||||
* with {@code ldc2_w} if its {@linkplain ConstantDynamicEntry#typeKind()
|
||||
* type} is {@link TypeKind#LONG long} or {@link TypeKind#DOUBLE double}.
|
||||
* Use {@link LoadableConstantEntry#typeKind() typeKind().slotSize()} to
|
||||
* determine the loading instruction instead.
|
||||
*
|
||||
* @see ConstantPool##index Index in the Constant Pool
|
||||
*/
|
||||
int width();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -27,10 +27,20 @@ package java.lang.classfile.constantpool;
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_String_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.3 The CONSTANT_String_info Structure
|
||||
* Models a {@code CONSTANT_String_info} structure, or a string constant, in the
|
||||
* constant pool of a {@code class} file.
|
||||
* <p>
|
||||
* The use of a {@code StringEntry} is represented by a {@link String}.
|
||||
* Conversions are through {@link ConstantPoolBuilder#stringEntry(String)} and
|
||||
* {@link #stringValue()}.
|
||||
* <p>
|
||||
* A string entry is composite:
|
||||
* {@snippet lang=text :
|
||||
* // @link substring="StringEntry" target="ConstantPoolBuilder#stringEntry(Utf8Entry)" :
|
||||
* StringEntry(Utf8Entry utf8) // @link substring="utf8" target="#utf8()"
|
||||
* }
|
||||
*
|
||||
* @jvms 4.4.3 The {@code CONSTANT_String_info} Structure
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface StringEntry
|
||||
@@ -38,11 +48,15 @@ public sealed interface StringEntry
|
||||
permits AbstractPoolEntry.StringEntryImpl {
|
||||
/**
|
||||
* {@return the UTF constant pool entry describing the string contents}
|
||||
*
|
||||
* @see ConstantPoolBuilder#stringEntry(Utf8Entry)
|
||||
*/
|
||||
Utf8Entry utf8();
|
||||
|
||||
/**
|
||||
* {@return the string value for this entry}
|
||||
*
|
||||
* @see ConstantPoolBuilder#stringEntry(String)
|
||||
*/
|
||||
String stringValue();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2025, 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
|
||||
@@ -24,13 +24,40 @@
|
||||
*/
|
||||
package java.lang.classfile.constantpool;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.lang.classfile.AnnotationValue;
|
||||
import java.lang.classfile.MethodModel;
|
||||
import java.lang.constant.ClassDesc;
|
||||
import java.lang.constant.MethodTypeDesc;
|
||||
import java.lang.invoke.TypeDescriptor;
|
||||
|
||||
import jdk.internal.classfile.impl.AbstractPoolEntry;
|
||||
|
||||
/**
|
||||
* Models a {@code CONSTANT_UTF8_info} constant in the constant pool of a
|
||||
* classfile.
|
||||
* @jvms 4.4.7 The CONSTANT_Utf8_info Structure
|
||||
* Models a {@code CONSTANT_UTF8_info} constant, representing strings, in the
|
||||
* constant pool of a {@code class} file. This describes strings in the
|
||||
* {@linkplain DataInput##modified-utf-8 Modified UTF-8} format.
|
||||
* <p>
|
||||
* The use of a {@code Utf8Entry} is represented by a {@link String}.
|
||||
* Conversions are through {@link ConstantPoolBuilder#utf8Entry(String)} and
|
||||
* {@link #stringValue()}.
|
||||
* <p>
|
||||
* Some uses of {@code Utf8Entry} represent field or method {@linkplain
|
||||
* TypeDescriptor#descriptorString() descriptor strings}, symbolically
|
||||
* represented as {@link ClassDesc} or {@link MethodTypeDesc}, depending on
|
||||
* where a {@code Utf8Entry} appear. Entries representing such uses are created
|
||||
* with {@link ConstantPoolBuilder#utf8Entry(ClassDesc)} and {@link
|
||||
* ConstantPoolBuilder#utf8Entry(MethodTypeDesc)}, and they can be converted to
|
||||
* symbolic descriptors on a per-use-site basis, such as in {@link
|
||||
* AnnotationValue.OfClass#classSymbol()} and {@link MethodModel#methodTypeSymbol()}.
|
||||
* <p>
|
||||
* Unlike most constant pool entries, a UTF-8 entry is of flexible length: it is
|
||||
* represented as an array structure, with an {@code u2} for the data length in
|
||||
* bytes, followed by that number of bytes of Modified UTF-8 data. It can
|
||||
* represent at most 65535 bytes of data due to the physical restrictions.
|
||||
*
|
||||
* @jvms 4.4.7 The {@code CONSTANT_Utf8_info} Structure
|
||||
* @see DataInput##modified-utf-8 Modified UTF-8
|
||||
* @since 24
|
||||
*/
|
||||
public sealed interface Utf8Entry
|
||||
@@ -39,6 +66,15 @@ public sealed interface Utf8Entry
|
||||
|
||||
/**
|
||||
* {@return the string value for this entry}
|
||||
*
|
||||
* @apiNote
|
||||
* A {@code Utf8Entry} can be used directly as a {@link CharSequence} if
|
||||
* {@code String} functionalities are not strictly desired. If only string
|
||||
* equivalence is desired, {@link #equalsString(String) equalsString} should
|
||||
* be used. Reduction of string processing can significantly improve {@code
|
||||
* class} file reading performance.
|
||||
*
|
||||
* @see ConstantPoolBuilder#utf8Entry(String)
|
||||
*/
|
||||
String stringValue();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 2025, 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
|
||||
@@ -24,11 +24,59 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* <h2>Provides interfaces describing classfile constant pool entries for the {@link java.lang.classfile} library.</h2>
|
||||
* <h2>Provides interfaces describing constant pool entries for the {@link java.lang.classfile} library.</h2>
|
||||
*
|
||||
* The {@code java.lang.classfile.constantpool} package contains interfaces describing classfile constant pool entries.
|
||||
* The {@code java.lang.classfile.constantpool} package contains interfaces describing constant pool entries in the
|
||||
* {@code class} file format. Constant pool entries are low-level models to faithfully represent the exact structure
|
||||
* of a {@code class} file.
|
||||
* <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 the constant pool entries</h2>
|
||||
* When read from {@code class} files, the pool entries are lazily inflated; the contents of these entries, besides the
|
||||
* bare structure, are not evaluated to speed up parsing. Entries to users interest, usually accessed from other models
|
||||
* and elements, have their contents read on demand. For example, to search for methods, a user should filter first by
|
||||
* access flags and then by method name, and use {@link Utf8Entry#equalsString(String)} instead of checking equality
|
||||
* against {@link Utf8Entry#stringValue()}. This avoids inflation of UTF-8 entries as much as possible:
|
||||
* {@snippet lang="java" class="PackageSnippets" region="isStaticWorkMethod"}
|
||||
* <p>
|
||||
* The entries also define accessors to validated symbolic information with nominal descriptor abstractions from the
|
||||
* {@link java.lang.constant} package. These symbolic information accessors perform validation against the read
|
||||
* {@code class} files, and throw {@link IllegalArgumentException} when the accessed constant pool entry contains
|
||||
* invalid data. The nominal descriptors represent validated data, which saves users from extra validations in future
|
||||
* processing.
|
||||
* <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 exception may come from a {@link
|
||||
* ClassEntry} when it is first read from the constant pool (referring to an invalid index or wrong type of entry), when
|
||||
* its referred UTF-8 entry is expanded (malformed UTF-8 data), or when its symbolic information is accessed (the string
|
||||
* is not valid for a class entry).
|
||||
*
|
||||
* <h2 id="writing">Writing the constant pool entries</h2>
|
||||
* In general, users do not need to worry about working with the constant pool and its entries when writing {@code
|
||||
* class} files. Most Class-File API models and elements have two sets of factory methods: one that accepts symbolic
|
||||
* information representing the uses, and another that accepts constant pool entries. The constant pool builder
|
||||
* associated with {@code class} file builders, {@link ClassFileBuilder#constantPool}, automatically creates or reuses
|
||||
* pool entries from the symbolic information. Validated data in symbolic information helps {@code class} file
|
||||
* generation by avoiding extraneous parsing of raw constant pool entry data.
|
||||
* <p>
|
||||
* As always, users can use factories that accept constant pool entries if they already have them by hand, or if they
|
||||
* desire fine-grained control over {@code class} file generation.
|
||||
* <p>
|
||||
* If many models and elements are reused from another {@link ClassModel} in class building, the class building process
|
||||
* can use a constant pool builder that extends from the given {@code ClassModel}, available through {@link
|
||||
* ConstantPoolBuilder#of(ClassModel) ConstantPoolBuilder::of(ClassModel)}, so that byte data with constant pool
|
||||
* references can be copied in batch, speeding up class building. This is especially applicable to class transformations,
|
||||
* and {@link ClassFile.ConstantPoolSharingOption ConstantPoolSharingOption} exists to control this behavior.
|
||||
*
|
||||
* @jvms 4.4 The Constant Pool
|
||||
* @since 24
|
||||
*/
|
||||
package java.lang.classfile.constantpool;
|
||||
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.ClassFileBuilder;
|
||||
import java.lang.classfile.ClassModel;
|
||||
import java.lang.classfile.MethodModel;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2025, 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.
|
||||
*/
|
||||
package java.lang.classfile.constantpool.snippet;
|
||||
|
||||
import java.lang.classfile.ClassFile;
|
||||
import java.lang.classfile.MethodModel;
|
||||
import java.lang.classfile.constantpool.Utf8Entry;
|
||||
|
||||
class PackageSnippets {
|
||||
|
||||
// @start region=isStaticWorkMethod
|
||||
boolean isStaticWorkMethod(MethodModel method) {
|
||||
// check static flag first to avoid unnecessary evaluation of UTF-8 entry
|
||||
return (method.flags().flagsMask() & ClassFile.ACC_STATIC) != 0
|
||||
// use equalsString to avoid full conversion to String for comparison
|
||||
// the Utf8Entry can also act as a basic CharSequence without full conversion
|
||||
// @link substring="methodName" target="MethodModel#methodName" :
|
||||
&& method.methodName().equalsString("work"); // @link substring="equalsString" target="Utf8Entry#equalsString"
|
||||
}
|
||||
// @end
|
||||
}
|
||||
@@ -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 regex="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();
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user