diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index e4c05acb684b7..d5958853701ca 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -384,6 +384,7 @@ jobs:
- build-windows-aarch64
- test-linux-x64
- test-macos-x64
+ - test-macos-aarch64
- test-windows-x64
steps:
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000000000..f4c5e7e67cb46
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,3 @@
+# JDK Vulnerabilities
+
+Please follow the process outlined in the [OpenJDK Vulnerability Policy](https://openjdk.org/groups/vulnerability/report) to disclose vulnerabilities in the JDK.
diff --git a/doc/building.html b/doc/building.html
index 707531553124b..c91d876246cde 100644
--- a/doc/building.html
+++ b/doc/building.html
@@ -614,10 +614,9 @@
clang
--with-toolchain-type=clang.
Apple Xcode
The oldest supported version of Xcode is 13.0.
-
You will need the Xcode command line developer tools to be able to
-build the JDK. (Actually, only the command line tools are
-needed, not the IDE.) The simplest way to install these is to run:
-
xcode-select --install
+
You will need to download Xcode either from the App Store or specific
+versions can be easily located via the Xcode Releases website.
When updating Xcode, it is advisable to keep an older version for
building the JDK. To use a specific version of Xcode you have multiple
options:
diff --git a/doc/building.md b/doc/building.md
index 51ac0cad7d98b..47ad9e7c72b4c 100644
--- a/doc/building.md
+++ b/doc/building.md
@@ -422,13 +422,9 @@ To use clang instead of gcc on Linux, use `--with-toolchain-type=clang`.
The oldest supported version of Xcode is 13.0.
-You will need the Xcode command line developer tools to be able to build the
-JDK. (Actually, *only* the command line tools are needed, not the IDE.) The
-simplest way to install these is to run:
-
-```
-xcode-select --install
-```
+You will need to download Xcode either from the App Store or specific versions
+can be easily located via the [Xcode Releases](https://xcodereleases.com)
+website.
When updating Xcode, it is advisable to keep an older version for building the
JDK. To use a specific version of Xcode you have multiple options:
diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad
index fced9cfc35e57..39eae43a287e7 100644
--- a/src/hotspot/cpu/aarch64/aarch64.ad
+++ b/src/hotspot/cpu/aarch64/aarch64.ad
@@ -1244,7 +1244,7 @@ source %{
// r27 is not allocatable when compressed oops is on and heapbase is not
// zero, compressed klass pointers doesn't use r27 after JDK-8234794
- if (UseCompressedOops && (CompressedOops::ptrs_base() != nullptr)) {
+ if (UseCompressedOops && (CompressedOops::base() != nullptr)) {
_NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg()));
_NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg()));
_NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg()));
diff --git a/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp
index cd834969e1a4f..fcec3ae64fde8 100644
--- a/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp
@@ -93,7 +93,7 @@ static size_t probe_valid_max_address_bit() {
}
size_t ZPlatformAddressOffsetBits() {
- const static size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1;
+ static const size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1;
const size_t max_address_offset_bits = valid_max_address_offset_bits - 3;
const size_t min_address_offset_bits = max_address_offset_bits - 2;
const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio);
diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
index 08b69b34a9462..c5c02619d446e 100644
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
@@ -2967,7 +2967,7 @@ void MacroAssembler::verify_heapbase(const char* msg) {
if (CheckCompressedOops) {
Label ok;
push(1 << rscratch1->encoding(), sp); // cmpptr trashes rscratch1
- cmpptr(rheapbase, ExternalAddress(CompressedOops::ptrs_base_addr()));
+ cmpptr(rheapbase, ExternalAddress(CompressedOops::base_addr()));
br(Assembler::EQ, ok);
stop(msg);
bind(ok);
@@ -3133,9 +3133,9 @@ void MacroAssembler::reinit_heapbase()
{
if (UseCompressedOops) {
if (Universe::is_fully_initialized()) {
- mov(rheapbase, CompressedOops::ptrs_base());
+ mov(rheapbase, CompressedOops::base());
} else {
- lea(rheapbase, ExternalAddress(CompressedOops::ptrs_base_addr()));
+ lea(rheapbase, ExternalAddress(CompressedOops::base_addr()));
ldr(rheapbase, Address(rheapbase));
}
}
diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
index 3117c75149854..1b02108b00f94 100644
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
@@ -49,6 +49,7 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/signature.hpp"
#include "runtime/stubRoutines.hpp"
+#include "runtime/timerTrace.hpp"
#include "runtime/vframeArray.hpp"
#include "utilities/align.hpp"
#include "utilities/formatBuffer.hpp"
diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
index 38d48b86f23b0..3210789bbbdfa 100644
--- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
@@ -69,12 +69,6 @@ int TemplateInterpreter::InterpreterCodeSize = 200 * 1024;
#define __ _masm->
-//-----------------------------------------------------------------------------
-
-extern "C" void entry(CodeBuffer*);
-
-//-----------------------------------------------------------------------------
-
address TemplateInterpreterGenerator::generate_slow_signature_handler() {
address entry = __ pc();
diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
index 7648e5c5d9260..7c1f3aafe7d52 100644
--- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
+++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
@@ -38,6 +38,7 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/safepointMechanism.hpp"
#include "runtime/stubRoutines.hpp"
+#include "runtime/timerTrace.hpp"
#include "runtime/vframeArray.hpp"
#include "utilities/align.hpp"
#include "utilities/powerOfTwo.hpp"
diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp
index c05e97a4e9aa3..83fad376d292a 100644
--- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp
@@ -92,7 +92,7 @@ void C1_MacroAssembler::lock_object(Register Rmark, Register Roop, Register Rbox
}
if (LockingMode == LM_LIGHTWEIGHT) {
- lightweight_lock(Roop, Rmark, Rscratch, slow_int);
+ lightweight_lock(Rbox, Roop, Rmark, Rscratch, slow_int);
} else if (LockingMode == LM_LEGACY) {
// ... and mark it unlocked.
ori(Rmark, Rmark, markWord::unlocked_value);
diff --git a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp
index cc69c0abe361f..1147c3b42b25f 100644
--- a/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp
@@ -39,12 +39,12 @@
void C2_MacroAssembler::fast_lock_lightweight(ConditionRegister flag, Register obj, Register box,
Register tmp1, Register tmp2, Register tmp3) {
- compiler_fast_lock_lightweight_object(flag, obj, tmp1, tmp2, tmp3);
+ compiler_fast_lock_lightweight_object(flag, obj, box, tmp1, tmp2, tmp3);
}
void C2_MacroAssembler::fast_unlock_lightweight(ConditionRegister flag, Register obj, Register box,
Register tmp1, Register tmp2, Register tmp3) {
- compiler_fast_unlock_lightweight_object(flag, obj, tmp1, tmp2, tmp3);
+ compiler_fast_unlock_lightweight_object(flag, obj, box, tmp1, tmp2, tmp3);
}
// Intrinsics for CompactStrings
diff --git a/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp b/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp
index 136fd7a8ad1cd..ddeb9adf0a9ae 100644
--- a/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp
+++ b/src/hotspot/cpu/ppc/gc/z/zAddress_ppc.cpp
@@ -90,7 +90,7 @@ static size_t probe_valid_max_address_bit() {
}
size_t ZPlatformAddressOffsetBits() {
- const static size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1;
+ static const size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1;
const size_t max_address_offset_bits = valid_max_address_offset_bits - 3;
const size_t min_address_offset_bits = max_address_offset_bits - 2;
const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio);
diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
index a29e0810d52ca..aa77f0169ea1a 100644
--- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
+++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
@@ -968,7 +968,7 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) {
}
if (LockingMode == LM_LIGHTWEIGHT) {
- lightweight_lock(object, header, tmp, slow_case);
+ lightweight_lock(monitor, object, header, tmp, slow_case);
b(count_locking);
} else if (LockingMode == LM_LEGACY) {
// Load markWord from object into header.
diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
index 8449d74d8a861..a8635af9582d1 100644
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
@@ -2730,9 +2730,9 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe
bind(failure);
}
-void MacroAssembler::compiler_fast_lock_lightweight_object(ConditionRegister flag, Register obj, Register tmp1,
- Register tmp2, Register tmp3) {
- assert_different_registers(obj, tmp1, tmp2, tmp3);
+void MacroAssembler::compiler_fast_lock_lightweight_object(ConditionRegister flag, Register obj, Register box,
+ Register tmp1, Register tmp2, Register tmp3) {
+ assert_different_registers(obj, box, tmp1, tmp2, tmp3);
assert(flag == CCR0, "bad condition register");
// Handle inflated monitor.
@@ -2742,11 +2742,17 @@ void MacroAssembler::compiler_fast_lock_lightweight_object(ConditionRegister fla
// Finish fast lock unsuccessfully. MUST branch to with flag == EQ
Label slow_path;
+ if (UseObjectMonitorTable) {
+ // Clear cache in case fast locking succeeds.
+ li(tmp1, 0);
+ std(tmp1, in_bytes(BasicObjectLock::lock_offset()) + BasicLock::object_monitor_cache_offset_in_bytes(), box);
+ }
+
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(tmp1, obj);
lbz(tmp1, in_bytes(Klass::misc_flags_offset()), tmp1);
- testbitdi(flag, R0, tmp1, exact_log2(KlassFlags::_misc_is_value_based_class));
- bne(flag, slow_path);
+ testbitdi(CCR0, R0, tmp1, exact_log2(KlassFlags::_misc_is_value_based_class));
+ bne(CCR0, slow_path);
}
const Register mark = tmp1;
@@ -2761,8 +2767,8 @@ void MacroAssembler::compiler_fast_lock_lightweight_object(ConditionRegister fla
// Check if lock-stack is full.
lwz(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
- cmplwi(flag, top, LockStack::end_offset() - 1);
- bgt(flag, slow_path);
+ cmplwi(CCR0, top, LockStack::end_offset() - 1);
+ bgt(CCR0, slow_path);
// The underflow check is elided. The recursive check will always fail
// when the lock stack is empty because of the _bad_oop_sentinel field.
@@ -2770,19 +2776,19 @@ void MacroAssembler::compiler_fast_lock_lightweight_object(ConditionRegister fla
// Check if recursive.
subi(t, top, oopSize);
ldx(t, R16_thread, t);
- cmpd(flag, obj, t);
- beq(flag, push);
+ cmpd(CCR0, obj, t);
+ beq(CCR0, push);
// Check for monitor (0b10) or locked (0b00).
ld(mark, oopDesc::mark_offset_in_bytes(), obj);
andi_(t, mark, markWord::lock_mask_in_place);
- cmpldi(flag, t, markWord::unlocked_value);
- bgt(flag, inflated);
- bne(flag, slow_path);
+ cmpldi(CCR0, t, markWord::unlocked_value);
+ bgt(CCR0, inflated);
+ bne(CCR0, slow_path);
// Not inflated.
- // Try to lock. Transition lock bits 0b00 => 0b01
+ // Try to lock. Transition lock bits 0b01 => 0b00
assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid a lea");
atomically_flip_locked_state(/* is_unlock */ false, obj, mark, slow_path, MacroAssembler::MemBarAcq);
@@ -2797,38 +2803,84 @@ void MacroAssembler::compiler_fast_lock_lightweight_object(ConditionRegister fla
{ // Handle inflated monitor.
bind(inflated);
+ // mark contains the tagged ObjectMonitor*.
+ const uintptr_t monitor_tag = markWord::monitor_value;
+ const Register monitor = mark;
+ const Register owner_addr = tmp2;
+ Label monitor_locked;
+
if (!UseObjectMonitorTable) {
- // mark contains the tagged ObjectMonitor*.
- const Register tagged_monitor = mark;
- const uintptr_t monitor_tag = markWord::monitor_value;
- const Register owner_addr = tmp2;
+ // Compute owner address.
+ addi(owner_addr, mark, in_bytes(ObjectMonitor::owner_offset()) - monitor_tag);
+ } else {
+ Label monitor_found;
+ Register cache_addr = tmp2;
+
+ // Load cache address
+ addi(cache_addr, R16_thread, in_bytes(JavaThread::om_cache_oops_offset()));
+
+ const int num_unrolled = 2;
+ for (int i = 0; i < num_unrolled; i++) {
+ ld(tmp3, 0, cache_addr);
+ cmpd(CCR0, tmp3, obj);
+ beq(CCR0, monitor_found);
+ addi(cache_addr, cache_addr, in_bytes(OMCache::oop_to_oop_difference()));
+ }
+
+ Label loop;
+
+ // Search for obj in cache.
+ bind(loop);
+
+ // Check for match.
+ ld(tmp3, 0, cache_addr);
+ cmpd(CCR0, tmp3, obj);
+ beq(CCR0, monitor_found);
+
+ // Search until null encountered, guaranteed _null_sentinel at end.
+ addi(cache_addr, cache_addr, in_bytes(OMCache::oop_to_oop_difference()));
+ cmpdi(CCR1, tmp3, 0);
+ bne(CCR1, loop);
+ // Cache Miss, CCR0.NE set from cmp above
+ b(slow_path);
+
+ bind(monitor_found);
+ ld(monitor, in_bytes(OMCache::oop_to_monitor_difference()), cache_addr);
// Compute owner address.
- addi(owner_addr, tagged_monitor, in_bytes(ObjectMonitor::owner_offset()) - monitor_tag);
-
- // CAS owner (null => current thread).
- cmpxchgd(/*flag=*/flag,
- /*current_value=*/t,
- /*compare_value=*/(intptr_t)0,
- /*exchange_value=*/R16_thread,
- /*where=*/owner_addr,
- MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq,
- MacroAssembler::cmpxchgx_hint_acquire_lock());
- beq(flag, locked);
-
- // Check if recursive.
- cmpd(flag, t, R16_thread);
- bne(flag, slow_path);
-
- // Recursive.
+ addi(owner_addr, monitor, in_bytes(ObjectMonitor::owner_offset()));
+ }
+
+ // CAS owner (null => current thread).
+ cmpxchgd(/*flag=*/CCR0,
+ /*current_value=*/t,
+ /*compare_value=*/(intptr_t)0,
+ /*exchange_value=*/R16_thread,
+ /*where=*/owner_addr,
+ MacroAssembler::MemBarRel | MacroAssembler::MemBarAcq,
+ MacroAssembler::cmpxchgx_hint_acquire_lock());
+ beq(CCR0, monitor_locked);
+
+ // Check if recursive.
+ cmpd(CCR0, t, R16_thread);
+ bne(CCR0, slow_path);
+
+ // Recursive.
+ if (!UseObjectMonitorTable) {
+ assert_different_registers(tmp1, owner_addr);
ld(tmp1, in_bytes(ObjectMonitor::recursions_offset() - ObjectMonitor::owner_offset()), owner_addr);
addi(tmp1, tmp1, 1);
std(tmp1, in_bytes(ObjectMonitor::recursions_offset() - ObjectMonitor::owner_offset()), owner_addr);
} else {
- // OMCache lookup not supported yet. Take the slowpath.
- // Set flag to NE
- crxor(flag, Assembler::equal, flag, Assembler::equal);
- b(slow_path);
+ assert_different_registers(tmp2, monitor);
+ ld(tmp2, in_bytes(ObjectMonitor::recursions_offset()), monitor);
+ addi(tmp2, tmp2, 1);
+ std(tmp2, in_bytes(ObjectMonitor::recursions_offset()), monitor);
+ }
+
+ bind(monitor_locked);
+ if (UseObjectMonitorTable) {
+ std(monitor, BasicLock::object_monitor_cache_offset_in_bytes(), box);
}
}
@@ -2838,21 +2890,21 @@ void MacroAssembler::compiler_fast_lock_lightweight_object(ConditionRegister fla
#ifdef ASSERT
// Check that locked label is reached with flag == EQ.
Label flag_correct;
- beq(flag, flag_correct);
+ beq(CCR0, flag_correct);
stop("Fast Lock Flag != EQ");
#endif
bind(slow_path);
#ifdef ASSERT
// Check that slow_path label is reached with flag == NE.
- bne(flag, flag_correct);
+ bne(CCR0, flag_correct);
stop("Fast Lock Flag != NE");
bind(flag_correct);
#endif
// C2 uses the value of flag (NE vs EQ) to determine the continuation.
}
-void MacroAssembler::compiler_fast_unlock_lightweight_object(ConditionRegister flag, Register obj, Register tmp1,
- Register tmp2, Register tmp3) {
+void MacroAssembler::compiler_fast_unlock_lightweight_object(ConditionRegister flag, Register obj, Register box,
+ Register tmp1, Register tmp2, Register tmp3) {
assert_different_registers(obj, tmp1, tmp2, tmp3);
assert(flag == CCR0, "bad condition register");
@@ -2874,9 +2926,9 @@ void MacroAssembler::compiler_fast_unlock_lightweight_object(ConditionRegister f
lwz(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
subi(top, top, oopSize);
ldx(t, R16_thread, top);
- cmpd(flag, obj, t);
+ cmpd(CCR0, obj, t);
// Top of lock stack was not obj. Must be monitor.
- bne(flag, inflated_load_monitor);
+ bne(CCR0, inflated_load_monitor);
// Pop lock-stack.
DEBUG_ONLY(li(t, 0);)
@@ -2889,8 +2941,8 @@ void MacroAssembler::compiler_fast_unlock_lightweight_object(ConditionRegister f
// Check if recursive.
subi(t, top, oopSize);
ldx(t, R16_thread, t);
- cmpd(flag, obj, t);
- beq(flag, unlocked);
+ cmpd(CCR0, obj, t);
+ beq(CCR0, unlocked);
// Not recursive.
@@ -2941,62 +2993,62 @@ void MacroAssembler::compiler_fast_unlock_lightweight_object(ConditionRegister f
cmplwi(CCR0, top, in_bytes(JavaThread::lock_stack_base_offset()));
blt(CCR0, check_done);
ldx(t, R16_thread, top);
- cmpd(flag, obj, t);
- bne(flag, inflated);
+ cmpd(CCR0, obj, t);
+ bne(CCR0, inflated);
stop("Fast Unlock lock on stack");
bind(check_done);
#endif
- if (!UseObjectMonitorTable) {
- // mark contains the tagged ObjectMonitor*.
- const Register monitor = mark;
- const uintptr_t monitor_tag = markWord::monitor_value;
+ // mark contains the tagged ObjectMonitor*.
+ const Register monitor = mark;
+ const uintptr_t monitor_tag = markWord::monitor_value;
+ if (!UseObjectMonitorTable) {
// Untag the monitor.
subi(monitor, mark, monitor_tag);
+ } else {
+ ld(monitor, BasicLock::object_monitor_cache_offset_in_bytes(), box);
+ // null check with Flags == NE, no valid pointer below alignof(ObjectMonitor*)
+ cmpldi(CCR0, monitor, checked_cast(alignof(ObjectMonitor*)));
+ blt(CCR0, slow_path);
+ }
- const Register recursions = tmp2;
- Label not_recursive;
+ const Register recursions = tmp2;
+ Label not_recursive;
- // Check if recursive.
- ld(recursions, in_bytes(ObjectMonitor::recursions_offset()), monitor);
- addic_(recursions, recursions, -1);
- blt(CCR0, not_recursive);
+ // Check if recursive.
+ ld(recursions, in_bytes(ObjectMonitor::recursions_offset()), monitor);
+ addic_(recursions, recursions, -1);
+ blt(CCR0, not_recursive);
- // Recursive unlock.
- std(recursions, in_bytes(ObjectMonitor::recursions_offset()), monitor);
- crorc(CCR0, Assembler::equal, CCR0, Assembler::equal);
- b(unlocked);
+ // Recursive unlock.
+ std(recursions, in_bytes(ObjectMonitor::recursions_offset()), monitor);
+ crorc(CCR0, Assembler::equal, CCR0, Assembler::equal);
+ b(unlocked);
- bind(not_recursive);
+ bind(not_recursive);
- Label release_;
- const Register t2 = tmp2;
+ Label release_;
+ const Register t2 = tmp2;
- // Check if the entry lists are empty.
- ld(t, in_bytes(ObjectMonitor::EntryList_offset()), monitor);
- ld(t2, in_bytes(ObjectMonitor::cxq_offset()), monitor);
- orr(t, t, t2);
- cmpdi(flag, t, 0);
- beq(flag, release_);
+ // Check if the entry lists are empty.
+ ld(t, in_bytes(ObjectMonitor::EntryList_offset()), monitor);
+ ld(t2, in_bytes(ObjectMonitor::cxq_offset()), monitor);
+ orr(t, t, t2);
+ cmpdi(CCR0, t, 0);
+ beq(CCR0, release_);
- // The owner may be anonymous and we removed the last obj entry in
- // the lock-stack. This loses the information about the owner.
- // Write the thread to the owner field so the runtime knows the owner.
- std(R16_thread, in_bytes(ObjectMonitor::owner_offset()), monitor);
- b(slow_path);
+ // The owner may be anonymous and we removed the last obj entry in
+ // the lock-stack. This loses the information about the owner.
+ // Write the thread to the owner field so the runtime knows the owner.
+ std(R16_thread, in_bytes(ObjectMonitor::owner_offset()), monitor);
+ b(slow_path);
- bind(release_);
- // Set owner to null.
- release();
- // t contains 0
- std(t, in_bytes(ObjectMonitor::owner_offset()), monitor);
- } else {
- // OMCache lookup not supported yet. Take the slowpath.
- // Set flag to NE
- crxor(flag, Assembler::equal, flag, Assembler::equal);
- b(slow_path);
- }
+ bind(release_);
+ // Set owner to null.
+ release();
+ // t contains 0
+ std(t, in_bytes(ObjectMonitor::owner_offset()), monitor);
}
bind(unlocked);
@@ -3005,13 +3057,13 @@ void MacroAssembler::compiler_fast_unlock_lightweight_object(ConditionRegister f
#ifdef ASSERT
// Check that unlocked label is reached with flag == EQ.
Label flag_correct;
- beq(flag, flag_correct);
+ beq(CCR0, flag_correct);
stop("Fast Lock Flag != EQ");
#endif
bind(slow_path);
#ifdef ASSERT
// Check that slow_path label is reached with flag == NE.
- bne(flag, flag_correct);
+ bne(CCR0, flag_correct);
stop("Fast Lock Flag != NE");
bind(flag_correct);
#endif
@@ -4640,15 +4692,21 @@ void MacroAssembler::atomically_flip_locked_state(bool is_unlock, Register obj,
//
// - obj: the object to be locked
// - t1, t2: temporary register
-void MacroAssembler::lightweight_lock(Register obj, Register t1, Register t2, Label& slow) {
+void MacroAssembler::lightweight_lock(Register box, Register obj, Register t1, Register t2, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
- assert_different_registers(obj, t1, t2);
+ assert_different_registers(box, obj, t1, t2);
Label push;
const Register top = t1;
const Register mark = t2;
const Register t = R0;
+ if (UseObjectMonitorTable) {
+ // Clear cache in case fast locking succeeds.
+ li(t, 0);
+ std(t, in_bytes(BasicObjectLock::lock_offset()) + BasicLock::object_monitor_cache_offset_in_bytes(), box);
+ }
+
// Check if the lock-stack is full.
lwz(top, in_bytes(JavaThread::lock_stack_top_offset()), R16_thread);
cmplwi(CCR0, top, LockStack::end_offset());
@@ -4669,7 +4727,7 @@ void MacroAssembler::lightweight_lock(Register obj, Register t1, Register t2, La
andi_(t, t, markWord::lock_mask_in_place);
bne(CCR0, slow);
- // Try to lock. Transition lock bits 0b00 => 0b01
+ // Try to lock. Transition lock bits 0b01 => 0b00
atomically_flip_locked_state(/* is_unlock */ false, obj, mark, slow, MacroAssembler::MemBarAcq);
bind(push);
diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
index 03ad37a4fb04a..224e7bff99541 100644
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
@@ -654,7 +654,7 @@ class MacroAssembler: public Assembler {
void inc_held_monitor_count(Register tmp);
void dec_held_monitor_count(Register tmp);
void atomically_flip_locked_state(bool is_unlock, Register obj, Register tmp, Label& failed, int semantics);
- void lightweight_lock(Register obj, Register t1, Register t2, Label& slow);
+ void lightweight_lock(Register box, Register obj, Register t1, Register t2, Label& slow);
void lightweight_unlock(Register obj, Register t1, Label& slow);
// allocation (for C1)
@@ -675,11 +675,11 @@ class MacroAssembler: public Assembler {
void compiler_fast_unlock_object(ConditionRegister flag, Register oop, Register box,
Register tmp1, Register tmp2, Register tmp3);
- void compiler_fast_lock_lightweight_object(ConditionRegister flag, Register oop, Register tmp1,
- Register tmp2, Register tmp3);
+ void compiler_fast_lock_lightweight_object(ConditionRegister flag, Register oop, Register box,
+ Register tmp1, Register tmp2, Register tmp3);
- void compiler_fast_unlock_lightweight_object(ConditionRegister flag, Register oop, Register tmp1,
- Register tmp2, Register tmp3);
+ void compiler_fast_unlock_lightweight_object(ConditionRegister flag, Register oop, Register box,
+ Register tmp1, Register tmp2, Register tmp3);
// Check if safepoint requested and if so branch
void safepoint_poll(Label& slow_path, Register temp, bool at_return, bool in_nmethod);
diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad
index e7e066ebcc6d3..612b7bf898c08 100644
--- a/src/hotspot/cpu/ppc/ppc.ad
+++ b/src/hotspot/cpu/ppc/ppc.ad
@@ -12106,10 +12106,10 @@ instruct cmpFastUnlock(flagsRegCR0 crx, iRegPdst oop, iRegPdst box, iRegPdst tmp
ins_pipe(pipe_class_compare);
%}
-instruct cmpFastLockLightweight(flagsRegCR0 crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1, iRegPdst tmp2) %{
+instruct cmpFastLockLightweight(flagsRegCR0 crx, iRegPdst oop, iRegPdst box, iRegPdst tmp1, iRegPdst tmp2, flagsRegCR1 cr1) %{
predicate(LockingMode == LM_LIGHTWEIGHT);
match(Set crx (FastLock oop box));
- effect(TEMP tmp1, TEMP tmp2);
+ effect(TEMP tmp1, TEMP tmp2, KILL cr1);
format %{ "FASTLOCK $oop, $box, $tmp1, $tmp2" %}
ins_encode %{
diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
index 5cf5f7cf73e03..aa8ae6070b6a6 100644
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
+++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
@@ -2399,7 +2399,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// Try fastpath for locking.
if (LockingMode == LM_LIGHTWEIGHT) {
// fast_lock kills r_temp_1, r_temp_2, r_temp_3.
- __ compiler_fast_lock_lightweight_object(CCR0, r_oop, r_temp_1, r_temp_2, r_temp_3);
+ __ compiler_fast_lock_lightweight_object(CCR0, r_oop, r_box, r_temp_1, r_temp_2, r_temp_3);
} else {
// fast_lock kills r_temp_1, r_temp_2, r_temp_3.
__ compiler_fast_lock_object(CCR0, r_oop, r_box, r_temp_1, r_temp_2, r_temp_3);
@@ -2605,7 +2605,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// Try fastpath for unlocking.
if (LockingMode == LM_LIGHTWEIGHT) {
- __ compiler_fast_unlock_lightweight_object(CCR0, r_oop, r_temp_1, r_temp_2, r_temp_3);
+ __ compiler_fast_unlock_lightweight_object(CCR0, r_oop, r_box, r_temp_1, r_temp_2, r_temp_3);
} else {
__ compiler_fast_unlock_object(CCR0, r_oop, r_box, r_temp_1, r_temp_2, r_temp_3);
}
diff --git a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp
index 03dca2aeb9b7b..cf3dd4cbd34c0 100644
--- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp
+++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp
@@ -1078,6 +1078,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
case Interpreter::java_lang_math_sin : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsin); break;
case Interpreter::java_lang_math_cos : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dcos); break;
case Interpreter::java_lang_math_tan : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dtan); break;
+ case Interpreter::java_lang_math_tanh : /* run interpreted */ break;
case Interpreter::java_lang_math_abs : /* run interpreted */ break;
case Interpreter::java_lang_math_sqrt : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsqrt); break;
case Interpreter::java_lang_math_log : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog); break;
diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp
index 98ab86bf72eb6..d1021d9e283d2 100644
--- a/src/hotspot/cpu/riscv/assembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp
@@ -705,6 +705,16 @@ class Assembler : public AbstractAssembler {
emit(insn);
}
+ void fencei() {
+ unsigned insn = 0;
+ patch((address)&insn, 6, 0, 0b0001111); // opcode
+ patch((address)&insn, 11, 7, 0b00000); // rd
+ patch((address)&insn, 14, 12, 0b001); // func
+ patch((address)&insn, 19, 15, 0b00000); // rs1
+ patch((address)&insn, 31, 20, 0b000000000000); // fm
+ emit(insn);
+ }
+
#define INSN(NAME, op, funct3, funct7) \
void NAME() { \
unsigned insn = 0; \
diff --git a/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp
index ef13676b02ed8..df111723d56b6 100644
--- a/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp
+++ b/src/hotspot/cpu/riscv/gc/z/zAddress_riscv.cpp
@@ -92,7 +92,7 @@ static size_t probe_valid_max_address_bit() {
}
size_t ZPlatformAddressOffsetBits() {
- const static size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1;
+ static const size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1;
const size_t max_address_offset_bits = valid_max_address_offset_bits - 3;
const size_t min_address_offset_bits = max_address_offset_bits - 2;
const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio);
diff --git a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp
index 8fbeaa45371d1..cbb918ade00fe 100644
--- a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp
@@ -636,8 +636,20 @@ void ZBarrierSetAssembler::patch_barrier_relocation(address addr, int format) {
ShouldNotReachHere();
}
- // A full fence is generated before icache_flush by default in invalidate_word
- ICache::invalidate_range(addr, bytes);
+ // If we are using UseCtxFencei no ICache invalidation is needed here.
+ // Instead every hart will preform an fence.i either by a Java thread
+ // (due to patching epoch will take it to slow path),
+ // or by the kernel when a Java thread is moved to a hart.
+ // The instruction streams changes must only happen before the disarm of
+ // the nmethod barrier. Where the disarm have a leading full two way fence.
+ // If this is performed during a safepoint, all Java threads will emit a fence.i
+ // before transitioning to 'Java', e.g. leaving native or the safepoint wait barrier.
+ if (!UseCtxFencei) {
+ // ICache invalidation is a serialization point.
+ // The above patching of instructions happens before the invalidation.
+ // Hence it have a leading full two way fence (wr, wr).
+ ICache::invalidate_range(addr, bytes);
+ }
}
#ifdef COMPILER2
diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp
index c2585f2d1618d..dd31de14704ab 100644
--- a/src/hotspot/cpu/riscv/globals_riscv.hpp
+++ b/src/hotspot/cpu/riscv/globals_riscv.hpp
@@ -122,6 +122,8 @@ define_pd_global(intx, InlineSmallCode, 1000);
product(bool, UseRVVForBigIntegerShiftIntrinsics, true, \
"Use RVV instructions for left/right shift of BigInteger") \
product(bool, UseTrampolines, false, EXPERIMENTAL, \
- "Far calls uses jal to trampoline.")
+ "Far calls uses jal to trampoline.") \
+ product(bool, UseCtxFencei, false, EXPERIMENTAL, \
+ "Use PR_RISCV_CTX_SW_FENCEI_ON to avoid explicit icache flush")
#endif // CPU_RISCV_GLOBALS_RISCV_HPP
diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
index de0df45bbf507..32a446959a246 100644
--- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
@@ -1455,6 +1455,7 @@ void MacroAssembler::update_word_crc32(Register crc, Register v, Register tmp1,
}
+#ifdef COMPILER2
// This improvement (vectorization) is based on java.base/share/native/libzip/zlib/zcrc32.c.
// To make it, following steps are taken:
// 1. in zcrc32.c, modify N to 16 and related code,
@@ -1550,6 +1551,7 @@ void MacroAssembler::vector_update_crc32(Register crc, Register buf, Register le
addi(buf, buf, N*4);
}
}
+#endif // COMPILER2
/**
* @param crc register containing existing CRC (32-bit)
@@ -1576,11 +1578,13 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len,
add(table2, table0, 2*single_table_size*sizeof(juint), tmp1);
add(table3, table2, 1*single_table_size*sizeof(juint), tmp1);
+#ifdef COMPILER2
if (UseRVV) {
const int64_t tmp_limit = MaxVectorSize >= 32 ? unroll_words*3 : unroll_words*5;
mv(tmp1, tmp_limit);
bge(len, tmp1, L_vector_entry);
}
+#endif // COMPILER2
subw(len, len, unroll_words);
bge(len, zr, L_unroll_loop_entry);
@@ -1643,6 +1647,7 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len,
andi(tmp2, tmp2, right_8_bits);
update_byte_crc32(crc, tmp2, table0);
+#ifdef COMPILER2
// put vector code here, otherwise "offset is too large" error occurs.
if (UseRVV) {
j(L_exit); // only need to jump exit when UseRVV == true, it's a jump from end of block `L_by1_loop`.
@@ -1655,6 +1660,7 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len,
addiw(len, len, 4);
bgt(len, zr, L_by1_loop);
}
+#endif // COMPILER2
bind(L_exit);
andn(crc, tmp5, crc);
@@ -1970,9 +1976,9 @@ int MacroAssembler::patch_oop(address insn_addr, address o) {
void MacroAssembler::reinit_heapbase() {
if (UseCompressedOops) {
if (Universe::is_fully_initialized()) {
- mv(xheapbase, CompressedOops::ptrs_base());
+ mv(xheapbase, CompressedOops::base());
} else {
- ExternalAddress target(CompressedOops::ptrs_base_addr());
+ ExternalAddress target(CompressedOops::base_addr());
relocate(target.rspec(), [&] {
int32_t offset;
la(xheapbase, target.target(), offset);
@@ -2085,23 +2091,11 @@ void MacroAssembler::addw(Register Rd, Register Rn, int32_t increment, Register
}
void MacroAssembler::sub(Register Rd, Register Rn, int64_t decrement, Register temp) {
- if (is_simm12(-decrement)) {
- addi(Rd, Rn, -decrement);
- } else {
- assert_different_registers(Rn, temp);
- li(temp, decrement);
- sub(Rd, Rn, temp);
- }
+ add(Rd, Rn, -decrement, temp);
}
void MacroAssembler::subw(Register Rd, Register Rn, int32_t decrement, Register temp) {
- if (is_simm12(-decrement)) {
- addiw(Rd, Rn, -decrement);
- } else {
- assert_different_registers(Rn, temp);
- li(temp, decrement);
- subw(Rd, Rn, temp);
- }
+ addw(Rd, Rn, -decrement, temp);
}
void MacroAssembler::andrw(Register Rd, Register Rs1, Register Rs2) {
@@ -3171,6 +3165,13 @@ void MacroAssembler::membar(uint32_t order_constraint) {
}
}
+void MacroAssembler::cmodx_fence() {
+ BLOCK_COMMENT("cmodx fence");
+ if (VM_Version::supports_fencei_barrier()) {
+ Assembler::fencei();
+ }
+}
+
// Form an address from base + offset in Rd. Rd my or may not
// actually be used: you must use the Address that is returned. It
// is up to you to ensure that the shift provided matches the size
diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
index 43d9dc387ca20..fd174f241eb0b 100644
--- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
@@ -431,6 +431,8 @@ class MacroAssembler: public Assembler {
}
}
+ void cmodx_fence();
+
void pause() {
Assembler::fence(w, 0);
}
@@ -1319,11 +1321,12 @@ class MacroAssembler: public Assembler {
Register table0, Register table1, Register table2, Register table3,
bool upper);
void update_byte_crc32(Register crc, Register val, Register table);
+
+#ifdef COMPILER2
void vector_update_crc32(Register crc, Register buf, Register len,
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5,
Register table0, Register table3);
-#ifdef COMPILER2
void mul_add(Register out, Register in, Register offset,
Register len, Register k, Register tmp);
void wide_mul(Register prod_lo, Register prod_hi, Register n, Register m);
@@ -1353,7 +1356,7 @@ class MacroAssembler: public Assembler {
Register tmp1, Register tmp2, Register tmp3, Register tmp4,
Register tmp5, Register tmp6, Register product_hi);
-#endif
+#endif // COMPILER2
void inflate_lo32(Register Rd, Register Rs, Register tmp1 = t0, Register tmp2 = t1);
void inflate_hi32(Register Rd, Register Rs, Register tmp1 = t0, Register tmp2 = t1);
diff --git a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp
index d0903c96e2271..18b4302c7e68e 100644
--- a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp
+++ b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp
@@ -55,7 +55,21 @@ void Relocation::pd_set_data_value(address x, bool verify_only) {
bytes = MacroAssembler::pd_patch_instruction_size(addr(), x);
break;
}
- ICache::invalidate_range(addr(), bytes);
+
+ // If we are using UseCtxFencei no ICache invalidation is needed here.
+ // Instead every hart will preform an fence.i either by a Java thread
+ // (due to patching epoch will take it to slow path),
+ // or by the kernel when a Java thread is moved to a hart.
+ // The instruction streams changes must only happen before the disarm of
+ // the nmethod barrier. Where the disarm have a leading full two way fence.
+ // If this is performed during a safepoint, all Java threads will emit a fence.i
+ // before transitioning to 'Java', e.g. leaving native or the safepoint wait barrier.
+ if (!UseCtxFencei) {
+ // ICache invalidation is a serialization point.
+ // The above patching of instructions happens before the invalidation.
+ // Hence it have a leading full two way fence (wr, wr).
+ ICache::invalidate_range(addr(), bytes);
+ }
}
address Relocation::pd_call_destination(address orig_addr) {
diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad
index 54947f6bf9a19..510c0ff5d4646 100644
--- a/src/hotspot/cpu/riscv/riscv_v.ad
+++ b/src/hotspot/cpu/riscv/riscv_v.ad
@@ -4895,11 +4895,10 @@ instruct gather_loadS(vReg dst, indirect mem, vReg idx) %{
effect(TEMP_DEF dst);
format %{ "gather_loadS $dst, $mem, $idx" %}
ins_encode %{
- __ vmv1r_v(as_VectorRegister($dst$$reg), as_VectorRegister($idx$$reg));
BasicType bt = Matcher::vector_element_basic_type(this);
Assembler::SEW sew = Assembler::elemtype_to_sew(bt);
__ vsetvli_helper(bt, Matcher::vector_length(this));
- __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($dst$$reg), (int)sew);
+ __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($idx$$reg), (int)sew);
__ vluxei32_v(as_VectorRegister($dst$$reg), as_Register($mem$$base),
as_VectorRegister($dst$$reg));
%}
@@ -4929,11 +4928,10 @@ instruct gather_loadS_masked(vReg dst, indirect mem, vReg idx, vRegMask_V0 v0, v
effect(TEMP_DEF dst, TEMP tmp);
format %{ "gather_loadS_masked $dst, $mem, $idx, $v0\t# KILL $tmp" %}
ins_encode %{
- __ vmv1r_v(as_VectorRegister($tmp$$reg), as_VectorRegister($idx$$reg));
BasicType bt = Matcher::vector_element_basic_type(this);
Assembler::SEW sew = Assembler::elemtype_to_sew(bt);
__ vsetvli_helper(bt, Matcher::vector_length(this));
- __ vsll_vi(as_VectorRegister($tmp$$reg), as_VectorRegister($tmp$$reg), (int)sew);
+ __ vsll_vi(as_VectorRegister($tmp$$reg), as_VectorRegister($idx$$reg), (int)sew);
__ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($dst$$reg),
as_VectorRegister($dst$$reg));
__ vluxei32_v(as_VectorRegister($dst$$reg), as_Register($mem$$base),
@@ -4969,11 +4967,10 @@ instruct scatter_storeS(indirect mem, vReg src, vReg idx, vReg tmp) %{
effect(TEMP tmp);
format %{ "scatter_storeS $mem, $idx, $src\t# KILL $tmp" %}
ins_encode %{
- __ vmv1r_v(as_VectorRegister($tmp$$reg), as_VectorRegister($idx$$reg));
BasicType bt = Matcher::vector_element_basic_type(this, $src);
Assembler::SEW sew = Assembler::elemtype_to_sew(bt);
__ vsetvli_helper(bt, Matcher::vector_length(this, $src));
- __ vsll_vi(as_VectorRegister($tmp$$reg), as_VectorRegister($tmp$$reg), (int)sew);
+ __ vsll_vi(as_VectorRegister($tmp$$reg), as_VectorRegister($idx$$reg), (int)sew);
__ vsuxei32_v(as_VectorRegister($src$$reg), as_Register($mem$$base),
as_VectorRegister($tmp$$reg));
%}
@@ -5003,11 +5000,10 @@ instruct scatter_storeS_masked(indirect mem, vReg src, vReg idx, vRegMask_V0 v0,
effect(TEMP tmp);
format %{ "scatter_storeS_masked $mem, $idx, $src, $v0\t# KILL $tmp" %}
ins_encode %{
- __ vmv1r_v(as_VectorRegister($tmp$$reg), as_VectorRegister($idx$$reg));
BasicType bt = Matcher::vector_element_basic_type(this, $src);
Assembler::SEW sew = Assembler::elemtype_to_sew(bt);
__ vsetvli_helper(bt, Matcher::vector_length(this, $src));
- __ vsll_vi(as_VectorRegister($tmp$$reg), as_VectorRegister($tmp$$reg), (int)sew);
+ __ vsll_vi(as_VectorRegister($tmp$$reg), as_VectorRegister($idx$$reg), (int)sew);
__ vsuxei32_v(as_VectorRegister($src$$reg), as_Register($mem$$base),
as_VectorRegister($tmp$$reg), Assembler::v0_t);
%}
diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
index 9162c1d520027..d4ec76da94315 100644
--- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
+++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
@@ -2428,6 +2428,14 @@ class StubGenerator: public StubCodeGenerator {
__ la(t1, ExternalAddress(bs_asm->patching_epoch_addr()));
__ lwu(t1, t1);
__ sw(t1, thread_epoch_addr);
+ // There are two ways this can work:
+ // - The writer did system icache shootdown after the instruction stream update.
+ // Hence do nothing.
+ // - The writer trust us to make sure our icache is in sync before entering.
+ // Hence use cmodx fence (fence.i, may change).
+ if (UseCtxFencei) {
+ __ cmodx_fence();
+ }
__ membar(__ LoadLoad);
}
@@ -5491,9 +5499,7 @@ class StubGenerator: public StubCodeGenerator {
Register stepSrcM2 = doff;
Register stepDst = isURL;
Register size = x29; // t4
- Register minusOne = x30; // t5
- __ mv(minusOne, -1);
__ mv(size, MaxVectorSize * 2);
__ mv(stepSrcM1, MaxVectorSize * 4);
__ slli(stepSrcM2, stepSrcM1, 1);
@@ -5513,7 +5519,8 @@ class StubGenerator: public StubCodeGenerator {
__ sub(length, length, stepSrcM2);
// error check
- __ bne(failedIdx, minusOne, Exit);
+ // valid value of failedIdx can only be -1 when < 0
+ __ bgez(failedIdx, Exit);
__ bge(length, stepSrcM2, ProcessM2);
@@ -5533,7 +5540,8 @@ class StubGenerator: public StubCodeGenerator {
__ sub(length, length, stepSrcM1);
// error check
- __ bne(failedIdx, minusOne, Exit);
+ // valid value of failedIdx can only be -1 when < 0
+ __ bgez(failedIdx, Exit);
__ BIND(ProcessScalar);
__ beqz(length, Exit);
diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp
index bd4bfe86d9bf7..8fdde0094f40d 100644
--- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp
+++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp
@@ -285,6 +285,7 @@ class VM_Version : public Abstract_VM_Version {
// RISCV64 supports fast class initialization checks
static bool supports_fast_class_init_checks() { return true; }
+ static bool supports_fencei_barrier() { return ext_Zifencei.enabled(); }
};
#endif // CPU_RISCV_VM_VERSION_RISCV_HPP
diff --git a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp
index f3fa19ddb31e0..f6dd20db3d67f 100644
--- a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp
+++ b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp
@@ -79,7 +79,7 @@ void C1_MacroAssembler::lock_object(Register Rmark, Register Roop, Register Rbox
assert(LockingMode != LM_MONITOR, "LM_MONITOR is already handled, by emit_lock()");
if (LockingMode == LM_LIGHTWEIGHT) {
- lightweight_lock(Roop, Rmark, tmp, slow_case);
+ lightweight_lock(Rbox, Roop, Rmark, tmp, slow_case);
} else if (LockingMode == LM_LEGACY) {
NearLabel done;
diff --git a/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp b/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp
index 3641d82dabea9..025ef4c8915cd 100644
--- a/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp
+++ b/src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp
@@ -34,12 +34,12 @@
#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Register temp1, Register temp2) {
- compiler_fast_lock_lightweight_object(obj, temp1, temp2);
+ compiler_fast_lock_lightweight_object(obj, box, temp1, temp2);
}
void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register box, Register temp1, Register temp2) {
- compiler_fast_unlock_lightweight_object(obj, temp1, temp2);
+ compiler_fast_unlock_lightweight_object(obj, box, temp1, temp2);
}
//------------------------------------------------------
diff --git a/src/hotspot/cpu/s390/downcallLinker_s390.cpp b/src/hotspot/cpu/s390/downcallLinker_s390.cpp
index 383a32448745c..85ddc5bf18548 100644
--- a/src/hotspot/cpu/s390/downcallLinker_s390.cpp
+++ b/src/hotspot/cpu/s390/downcallLinker_s390.cpp
@@ -36,8 +36,8 @@
#define __ _masm->
-static const int native_invoker_code_base_size = 512;
-static const int native_invoker_size_per_args = 8;
+static const int native_invoker_code_base_size = 384;
+static const int native_invoker_size_per_args = 12;
RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature,
int num_args,
diff --git a/src/hotspot/cpu/s390/interp_masm_s390.cpp b/src/hotspot/cpu/s390/interp_masm_s390.cpp
index e56beaa9f569c..d00b6c3e2cc2e 100644
--- a/src/hotspot/cpu/s390/interp_masm_s390.cpp
+++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp
@@ -1012,7 +1012,7 @@ void InterpreterMacroAssembler::lock_object(Register monitor, Register object) {
}
if (LockingMode == LM_LIGHTWEIGHT) {
- lightweight_lock(object, header, tmp, slow_case);
+ lightweight_lock(monitor, object, header, tmp, slow_case);
} else if (LockingMode == LM_LEGACY) {
// Load markWord from object into header.
diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp
index 65a7d3abe90af..6c26e17d5ce3b 100644
--- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp
@@ -6007,10 +6007,10 @@ SkipIfEqual::~SkipIfEqual() {
// - obj: the object to be locked, contents preserved.
// - temp1, temp2: temporary registers, contents destroyed.
// Note: make sure Z_R1 is not manipulated here when C2 compiler is in play
-void MacroAssembler::lightweight_lock(Register obj, Register temp1, Register temp2, Label& slow) {
+void MacroAssembler::lightweight_lock(Register basic_lock, Register obj, Register temp1, Register temp2, Label& slow) {
assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking");
- assert_different_registers(obj, temp1, temp2);
+ assert_different_registers(basic_lock, obj, temp1, temp2);
Label push;
const Register top = temp1;
@@ -6022,6 +6022,11 @@ void MacroAssembler::lightweight_lock(Register obj, Register temp1, Register tem
// instruction emitted as it is part of C1's null check semantics.
z_lg(mark, Address(obj, mark_offset));
+ if (UseObjectMonitorTable) {
+ // Clear cache in case fast locking succeeds.
+ const Address om_cache_addr = Address(basic_lock, BasicObjectLock::lock_offset() + in_ByteSize((BasicLock::object_monitor_cache_offset_in_bytes())));
+ z_mvghi(om_cache_addr, 0);
+ }
// First we need to check if the lock-stack has room for pushing the object reference.
z_lgf(top, Address(Z_thread, ls_top_offset));
@@ -6145,8 +6150,8 @@ void MacroAssembler::lightweight_unlock(Register obj, Register temp1, Register t
bind(unlocked);
}
-void MacroAssembler::compiler_fast_lock_lightweight_object(Register obj, Register tmp1, Register tmp2) {
- assert_different_registers(obj, tmp1, tmp2);
+void MacroAssembler::compiler_fast_lock_lightweight_object(Register obj, Register box, Register tmp1, Register tmp2) {
+ assert_different_registers(obj, box, tmp1, tmp2);
// Handle inflated monitor.
NearLabel inflated;
@@ -6155,6 +6160,11 @@ void MacroAssembler::compiler_fast_lock_lightweight_object(Register obj, Registe
// Finish fast lock unsuccessfully. MUST branch to with flag == EQ
NearLabel slow_path;
+ if (UseObjectMonitorTable) {
+ // Clear cache in case fast locking succeeds.
+ z_mvghi(Address(box, BasicLock::object_monitor_cache_offset_in_bytes()), 0);
+ }
+
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(tmp1, obj);
z_tm(Address(tmp1, Klass::misc_flags_offset()), KlassFlags::_misc_is_value_based_class);
@@ -6219,33 +6229,77 @@ void MacroAssembler::compiler_fast_lock_lightweight_object(Register obj, Registe
{ // Handle inflated monitor.
bind(inflated);
+ const Register tmp1_monitor = tmp1;
if (!UseObjectMonitorTable) {
- // mark contains the tagged ObjectMonitor*.
- const Register tagged_monitor = mark;
- const Register zero = tmp2;
-
- // Try to CAS m->owner from null to current thread.
- // If m->owner is null, then csg succeeds and sets m->owner=THREAD and CR=EQ.
- // Otherwise, register zero is filled with the current owner.
- z_lghi(zero, 0);
- z_csg(zero, Z_thread, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), tagged_monitor);
- z_bre(locked);
-
- // Check if recursive.
- z_cgr(Z_thread, zero); // zero contains the owner from z_csg instruction
- z_brne(slow_path);
-
- // Recursive
- z_agsi(Address(tagged_monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), 1ll);
- z_cgr(zero, zero);
- // z_bru(locked);
- // Uncomment above line in the future, for now jump address is right next to us.
+ assert(tmp1_monitor == mark, "should be the same here");
} else {
- // OMCache lookup not supported yet. Take the slowpath.
- // Set flag to NE
- z_ltgr(obj, obj);
+ NearLabel monitor_found;
+
+ // load cache address
+ z_la(tmp1, Address(Z_thread, JavaThread::om_cache_oops_offset()));
+
+ const int num_unrolled = 2;
+ for (int i = 0; i < num_unrolled; i++) {
+ z_cg(obj, Address(tmp1));
+ z_bre(monitor_found);
+ add2reg(tmp1, in_bytes(OMCache::oop_to_oop_difference()));
+ }
+
+ NearLabel loop;
+ // Search for obj in cache
+
+ bind(loop);
+
+ // check for match.
+ z_cg(obj, Address(tmp1));
+ z_bre(monitor_found);
+
+ // search until null encountered, guaranteed _null_sentinel at end.
+ add2reg(tmp1, in_bytes(OMCache::oop_to_oop_difference()));
+ z_cghsi(0, tmp1, 0);
+ z_brne(loop); // if not EQ to 0, go for another loop
+
+ // we reached to the end, cache miss
+ z_ltgr(obj, obj); // set CC to NE
z_bru(slow_path);
+
+ // cache hit
+ bind(monitor_found);
+ z_lg(tmp1_monitor, Address(tmp1, OMCache::oop_to_monitor_difference()));
}
+ NearLabel monitor_locked;
+ // lock the monitor
+
+ // mark contains the tagged ObjectMonitor*.
+ const Register tagged_monitor = mark;
+ const Register zero = tmp2;
+
+ const ByteSize monitor_tag = in_ByteSize(UseObjectMonitorTable ? 0 : checked_cast(markWord::monitor_value));
+ const Address owner_address(tmp1_monitor, ObjectMonitor::owner_offset() - monitor_tag);
+ const Address recursions_address(tmp1_monitor, ObjectMonitor::recursions_offset() - monitor_tag);
+
+
+ // Try to CAS m->owner from null to current thread.
+ // If m->owner is null, then csg succeeds and sets m->owner=THREAD and CR=EQ.
+ // Otherwise, register zero is filled with the current owner.
+ z_lghi(zero, 0);
+ z_csg(zero, Z_thread, owner_address);
+ z_bre(monitor_locked);
+
+ // Check if recursive.
+ z_cgr(Z_thread, zero); // zero contains the owner from z_csg instruction
+ z_brne(slow_path);
+
+ // Recursive
+ z_agsi(recursions_address, 1ll);
+
+ bind(monitor_locked);
+ if (UseObjectMonitorTable) {
+ // Cache the monitor for unlock
+ z_stg(tmp1_monitor, Address(box, BasicLock::object_monitor_cache_offset_in_bytes()));
+ }
+ // set the CC now
+ z_cgr(obj, obj);
}
BLOCK_COMMENT("} handle_inflated_monitor_lightweight_locking");
@@ -6270,11 +6324,11 @@ void MacroAssembler::compiler_fast_lock_lightweight_object(Register obj, Registe
// C2 uses the value of flag (NE vs EQ) to determine the continuation.
}
-void MacroAssembler::compiler_fast_unlock_lightweight_object(Register obj, Register tmp1, Register tmp2) {
- assert_different_registers(obj, tmp1, tmp2);
+void MacroAssembler::compiler_fast_unlock_lightweight_object(Register obj, Register box, Register tmp1, Register tmp2) {
+ assert_different_registers(obj, box, tmp1, tmp2);
// Handle inflated monitor.
- NearLabel inflated, inflated_load_monitor;
+ NearLabel inflated, inflated_load_mark;
// Finish fast unlock successfully. MUST reach to with flag == EQ.
NearLabel unlocked;
// Finish fast unlock unsuccessfully. MUST branch to with flag == NE.
@@ -6294,7 +6348,7 @@ void MacroAssembler::compiler_fast_unlock_lightweight_object(Register obj, Regis
z_aghi(top, -oopSize);
z_cg(obj, Address(Z_thread, top));
- branch_optimized(bcondNotEqual, inflated_load_monitor);
+ branch_optimized(bcondNotEqual, inflated_load_mark);
// Pop lock-stack.
#ifdef ASSERT
@@ -6315,6 +6369,9 @@ void MacroAssembler::compiler_fast_unlock_lightweight_object(Register obj, Regis
// Not recursive
// Check for monitor (0b10).
+ // Because we got here by popping (meaning we pushed in locked)
+ // there will be no monitor in the box. So we need to push back the obj
+ // so that the runtime can fix any potential anonymous owner.
z_lg(mark, Address(obj, mark_offset));
z_tmll(mark, markWord::monitor_value);
if (!UseObjectMonitorTable) {
@@ -6353,7 +6410,7 @@ void MacroAssembler::compiler_fast_unlock_lightweight_object(Register obj, Regis
{ // Handle inflated monitor.
- bind(inflated_load_monitor);
+ bind(inflated_load_mark);
z_lg(mark, Address(obj, mark_offset));
@@ -6378,49 +6435,61 @@ void MacroAssembler::compiler_fast_unlock_lightweight_object(Register obj, Regis
bind(check_done);
#endif // ASSERT
+ const Register tmp1_monitor = tmp1;
+
if (!UseObjectMonitorTable) {
- // mark contains the tagged ObjectMonitor*.
- const Register monitor = mark;
+ assert(tmp1_monitor == mark, "should be the same here");
+ } else {
+ // Uses ObjectMonitorTable. Look for the monitor in our BasicLock on the stack.
+ z_lg(tmp1_monitor, Address(box, BasicLock::object_monitor_cache_offset_in_bytes()));
+ // null check with ZF == 0, no valid pointer below alignof(ObjectMonitor*)
+ z_cghi(tmp1_monitor, alignof(ObjectMonitor*));
- NearLabel not_recursive;
- const Register recursions = tmp2;
+ z_brl(slow_path);
+ }
- // Check if recursive.
- load_and_test_long(recursions, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
- z_bre(not_recursive); // if 0 then jump, it's not recursive locking
+ // mark contains the tagged ObjectMonitor*.
+ const Register monitor = mark;
- // Recursive unlock
- z_agsi(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), -1ll);
- z_cgr(monitor, monitor); // set the CC to EQUAL
- z_bru(unlocked);
+ const ByteSize monitor_tag = in_ByteSize(UseObjectMonitorTable ? 0 : checked_cast(markWord::monitor_value));
+ const Address recursions_address{monitor, ObjectMonitor::recursions_offset() - monitor_tag};
+ const Address cxq_address{monitor, ObjectMonitor::cxq_offset() - monitor_tag};
+ const Address EntryList_address{monitor, ObjectMonitor::EntryList_offset() - monitor_tag};
+ const Address owner_address{monitor, ObjectMonitor::owner_offset() - monitor_tag};
- bind(not_recursive);
+ NearLabel not_recursive;
+ const Register recursions = tmp2;
- NearLabel not_ok;
- // Check if the entry lists are empty.
- load_and_test_long(tmp2, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)));
- z_brne(not_ok);
- load_and_test_long(tmp2, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)));
- z_brne(not_ok);
+ // Check if recursive.
+ load_and_test_long(recursions, recursions_address);
+ z_bre(not_recursive); // if 0 then jump, it's not recursive locking
- z_release();
- z_stg(tmp2 /*=0*/, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), monitor);
+ // Recursive unlock
+ z_agsi(recursions_address, -1ll);
+ z_cgr(monitor, monitor); // set the CC to EQUAL
+ z_bru(unlocked);
- z_bru(unlocked); // CC = EQ here
+ bind(not_recursive);
- bind(not_ok);
+ NearLabel not_ok;
+ // Check if the entry lists are empty.
+ load_and_test_long(tmp2, EntryList_address);
+ z_brne(not_ok);
+ load_and_test_long(tmp2, cxq_address);
+ z_brne(not_ok);
- // The owner may be anonymous, and we removed the last obj entry in
- // the lock-stack. This loses the information about the owner.
- // Write the thread to the owner field so the runtime knows the owner.
- z_stg(Z_thread, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), monitor);
- z_bru(slow_path); // CC = NE here
- } else {
- // OMCache lookup not supported yet. Take the slowpath.
- // Set flag to NE
- z_ltgr(obj, obj);
- z_bru(slow_path);
- }
+ z_release();
+ z_stg(tmp2 /*=0*/, owner_address);
+
+ z_bru(unlocked); // CC = EQ here
+
+ bind(not_ok);
+
+ // The owner may be anonymous, and we removed the last obj entry in
+ // the lock-stack. This loses the information about the owner.
+ // Write the thread to the owner field so the runtime knows the owner.
+ z_stg(Z_thread, owner_address);
+ z_bru(slow_path); // CC = NE here
}
bind(unlocked);
diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.hpp b/src/hotspot/cpu/s390/macroAssembler_s390.hpp
index c380f4dec1029..5d3a4c2994091 100644
--- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp
@@ -752,10 +752,10 @@ class MacroAssembler: public Assembler {
void compiler_fast_lock_object(Register oop, Register box, Register temp1, Register temp2);
void compiler_fast_unlock_object(Register oop, Register box, Register temp1, Register temp2);
- void lightweight_lock(Register obj, Register tmp1, Register tmp2, Label& slow);
+ void lightweight_lock(Register basic_lock, Register obj, Register tmp1, Register tmp2, Label& slow);
void lightweight_unlock(Register obj, Register tmp1, Register tmp2, Label& slow);
- void compiler_fast_lock_lightweight_object(Register obj, Register tmp1, Register tmp2);
- void compiler_fast_unlock_lightweight_object(Register obj, Register tmp1, Register tmp2);
+ void compiler_fast_lock_lightweight_object(Register obj, Register box, Register tmp1, Register tmp2);
+ void compiler_fast_unlock_lightweight_object(Register obj, Register box, Register tmp1, Register tmp2);
void resolve_jobject(Register value, Register tmp1, Register tmp2);
void resolve_global_jobject(Register value, Register tmp1, Register tmp2);
diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
index 9954c78ce1efa..468610b588e91 100644
--- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
+++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
@@ -43,6 +43,7 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/signature.hpp"
#include "runtime/stubRoutines.hpp"
+#include "runtime/timerTrace.hpp"
#include "runtime/vframeArray.hpp"
#include "utilities/align.hpp"
#include "utilities/macros.hpp"
@@ -1713,7 +1714,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// Try fastpath for locking.
if (LockingMode == LM_LIGHTWEIGHT) {
// Fast_lock kills r_temp_1, r_temp_2.
- __ compiler_fast_lock_lightweight_object(r_oop, r_tmp1, r_tmp2);
+ __ compiler_fast_lock_lightweight_object(r_oop, r_box, r_tmp1, r_tmp2);
} else {
// Fast_lock kills r_temp_1, r_temp_2.
__ compiler_fast_lock_object(r_oop, r_box, r_tmp1, r_tmp2);
@@ -1917,7 +1918,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// Try fastpath for unlocking.
if (LockingMode == LM_LIGHTWEIGHT) {
// Fast_unlock kills r_tmp1, r_tmp2.
- __ compiler_fast_unlock_lightweight_object(r_oop, r_tmp1, r_tmp2);
+ __ compiler_fast_unlock_lightweight_object(r_oop, r_box, r_tmp1, r_tmp2);
} else {
// Fast_unlock kills r_tmp1, r_tmp2.
__ compiler_fast_unlock_object(r_oop, r_box, r_tmp1, r_tmp2);
diff --git a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp
index c16e444904563..2c2e8ed9e3b3a 100644
--- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp
+++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp
@@ -1224,6 +1224,7 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
case Interpreter::java_lang_math_sin : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsin); break;
case Interpreter::java_lang_math_cos : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dcos); break;
case Interpreter::java_lang_math_tan : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dtan); break;
+ case Interpreter::java_lang_math_tanh : /* run interpreted */ break;
case Interpreter::java_lang_math_abs : /* run interpreted */ break;
case Interpreter::java_lang_math_sqrt : /* runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsqrt); not available */ break;
case Interpreter::java_lang_math_log : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog); break;
diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp
index 352cfc0018848..07476ab342f6d 100644
--- a/src/hotspot/cpu/x86/assembler_x86.cpp
+++ b/src/hotspot/cpu/x86/assembler_x86.cpp
@@ -8048,6 +8048,14 @@ void Assembler::andpd(XMMRegister dst, XMMRegister src) {
emit_int16(0x54, (0xC0 | encode));
}
+void Assembler::andnpd(XMMRegister dst, XMMRegister src) {
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ !_legacy_mode_dq, /* legacy_mode */ _legacy_mode_dq, /* no_mask_reg */ true, /* uses_vl */ true);
+ attributes.set_rex_vex_w_reverted();
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
+ emit_int16(0x55, (0xC0 | encode));
+}
+
void Assembler::andps(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse(), ""));
InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ _legacy_mode_dq, /* no_mask_reg */ true, /* uses_vl */ true);
diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp
index 7f4790e05665e..62700d1fa1bd5 100644
--- a/src/hotspot/cpu/x86/assembler_x86.hpp
+++ b/src/hotspot/cpu/x86/assembler_x86.hpp
@@ -2631,6 +2631,7 @@ class Assembler : public AbstractAssembler {
// Bitwise Logical AND of Packed Floating-Point Values
void andpd(XMMRegister dst, XMMRegister src);
+ void andnpd(XMMRegister dst, XMMRegister src);
void andps(XMMRegister dst, XMMRegister src);
void vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
diff --git a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp
index ff237d16d2216..36e2021138f2e 100644
--- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp
+++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp
@@ -807,7 +807,11 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
if (x->id() == vmIntrinsics::_dexp || x->id() == vmIntrinsics::_dlog ||
x->id() == vmIntrinsics::_dpow || x->id() == vmIntrinsics::_dcos ||
x->id() == vmIntrinsics::_dsin || x->id() == vmIntrinsics::_dtan ||
- x->id() == vmIntrinsics::_dlog10) {
+ x->id() == vmIntrinsics::_dlog10
+#ifdef _LP64
+ || x->id() == vmIntrinsics::_dtanh
+#endif
+ ) {
do_LibmIntrinsic(x);
return;
}
@@ -989,11 +993,17 @@ void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) {
break;
case vmIntrinsics::_dtan:
if (StubRoutines::dtan() != nullptr) {
- __ call_runtime_leaf(StubRoutines::dtan(), getThreadTemp(), result_reg, cc->args());
+ __ call_runtime_leaf(StubRoutines::dtan(), getThreadTemp(), result_reg, cc->args());
} else {
__ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtan), getThreadTemp(), result_reg, cc->args());
}
break;
+ case vmIntrinsics::_dtanh:
+ assert(StubRoutines::dtanh() != nullptr, "tanh intrinsic not found");
+ if (StubRoutines::dtanh() != nullptr) {
+ __ call_runtime_leaf(StubRoutines::dtanh(), getThreadTemp(), result_reg, cc->args());
+ }
+ break;
default: ShouldNotReachHere();
}
#endif // _LP64
diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp
index f5f0d6c884198..65d7c1e3303ba 100644
--- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp
@@ -636,7 +636,7 @@ void ZBarrierSetAssembler::copy_load_at(MacroAssembler* masm,
// Remove metadata bits so that the store side (vectorized or non-vectorized) can
// inject the store-good color with an or instruction.
- __ andq(dst, _zpointer_address_mask);
+ __ andq(dst, ZPointerAddressMask);
if ((decorators & ARRAYCOPY_CHECKCAST) != 0) {
// The checkcast arraycopy needs to be able to dereference the oops in order to perform a typechecks.
diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp
index 7c3716ba0da9f..5fbc7ea1be16e 100644
--- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp
+++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.hpp
@@ -64,7 +64,7 @@ class ZBarrierSetAssembler : public ZBarrierSetAssemblerBase {
GrowableArrayCHeap _store_good_relocations;
public:
- static const int32_t _zpointer_address_mask = 0xFFFF0000;
+ static const int32_t ZPointerAddressMask = 0xFFFF0000;
ZBarrierSetAssembler();
diff --git a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad
index 30220c0629e5e..455d622acdf17 100644
--- a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad
+++ b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad
@@ -141,7 +141,7 @@ instruct zLoadPNullCheck(rFlagsReg cr, memory op, immP0 zero)
ins_encode %{
// A null pointer will have all address bits 0. This mask sign extends
// all address bits, so we can test if the address is 0.
- __ testq($op$$Address, ZBarrierSetAssembler::_zpointer_address_mask);
+ __ testq($op$$Address, ZBarrierSetAssembler::ZPointerAddressMask);
%}
ins_pipe(ialu_cr_reg_imm);
%}
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
index d634c1e575799..893ae4e844ba4 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
@@ -5756,7 +5756,7 @@ void MacroAssembler::verify_heapbase(const char* msg) {
assert (Universe::heap() != nullptr, "java heap should be initialized");
if (CheckCompressedOops) {
Label ok;
- ExternalAddress src2(CompressedOops::ptrs_base_addr());
+ ExternalAddress src2(CompressedOops::base_addr());
const bool is_src2_reachable = reachable(src2);
if (!is_src2_reachable) {
push(rscratch1); // cmpptr trashes rscratch1
@@ -6047,10 +6047,10 @@ void MacroAssembler::reinit_heapbase() {
if (CompressedOops::base() == nullptr) {
MacroAssembler::xorptr(r12_heapbase, r12_heapbase);
} else {
- mov64(r12_heapbase, (int64_t)CompressedOops::ptrs_base());
+ mov64(r12_heapbase, (int64_t)CompressedOops::base());
}
} else {
- movptr(r12_heapbase, ExternalAddress(CompressedOops::ptrs_base_addr()));
+ movptr(r12_heapbase, ExternalAddress(CompressedOops::base_addr()));
}
}
}
diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
index 2bc4a0a9cba94..4f37dc31d0305 100644
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
@@ -3573,6 +3573,9 @@ void StubGenerator::generate_libm_stubs() {
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dtan)) {
StubRoutines::_dtan = generate_libmTan(); // from stubGenerator_x86_64_tan.cpp
}
+ if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dtanh)) {
+ StubRoutines::_dtanh = generate_libmTanh(); // from stubGenerator_x86_64_tanh.cpp
+ }
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dexp)) {
StubRoutines::_dexp = generate_libmExp(); // from stubGenerator_x86_64_exp.cpp
}
diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp
index d65c681585d6d..0a81da4f7c957 100644
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp
@@ -546,6 +546,7 @@ class StubGenerator: public StubCodeGenerator {
address generate_libmSin();
address generate_libmCos();
address generate_libmTan();
+ address generate_libmTanh();
address generate_libmExp();
address generate_libmPow();
address generate_libmLog();
diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_tanh.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_tanh.cpp
new file mode 100644
index 0000000000000..92ac78e15cba9
--- /dev/null
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_tanh.cpp
@@ -0,0 +1,502 @@
+/*
+* Copyright (c) 2024, Intel Corporation. All rights reserved.
+* Intel Math Library (LIBM) Source Code
+*
+* 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.
+*
+* 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.
+*
+*/
+
+#include "precompiled.hpp"
+#include "macroAssembler_x86.hpp"
+#include "stubGenerator_x86_64.hpp"
+
+/******************************************************************************/
+// ALGORITHM DESCRIPTION
+// ---------------------
+//
+// tanh(x)=(exp(x)-exp(-x))/(exp(x)+exp(-x))=(1-exp(-2*x))/(1+exp(-2*x))
+//
+// Let |x|=xH+xL (upper 26 bits, lower 27 bits)
+// log2(e) rounded to 26 bits (high part) plus a double precision low part is
+// L2EH+L2EL (upper 26, lower 53 bits)
+//
+// Let xH*L2EH=k+f+r`, where (k+f)*2^8*2=int(xH*L2EH*2^9),
+// f=0.b1 b2 ... b8, k integer
+// 2^{-f} is approximated as Tn[f]+Dn[f]
+// Tn stores the high 53 bits, Dn stores (2^{-f}-Tn[f]) rounded to double precision
+//
+// r=r`+xL*L2EH+|x|*L2EL, |r|<2^{-9}+2^{-14},
+// for |x| in [23/64,3*2^7)
+// e^{-2*|x|}=2^{-k-f}*2^{-r} ~ 2^{-k}*(Tn+Dn)*(1+p)=(T0+D0)*(1+p)
+//
+// For |x| in [2^{-4},2^5):
+// 2^{-r}-1 ~ p=c1*r+c2*r^2+..+c5*r^5
+// Let R=1/(1+T0+p*T0), truncated to 35 significant bits
+// R=1/(1+T0+D0+p*(T0+D0))*(1+eps), |eps|<2^{-33}
+// 1+T0+D0+p*(T0+D0)=KH+KL, where
+// KH=(1+T0+c1*r*T0)_high (leading 17 bits)
+// KL=T0_low+D0+(c1*r*T0)_low+c1*r*D0+(c2*r^2+..c5*r^5)*T0
+// eps ~ (R*KH-1)+R*KL
+// 1/(1+T0+D0+p*(T0+D0)) ~ R-R*eps
+// The result is approximated as (1-T0-D0-(T0+D0)*p)*(R-R*eps)
+// 1-T0-D0-(T0+D0)*p=-((KH-2)+KL)
+// The result is formed as
+// (KH-2)*R+(-(KH-2)*R*eps+(KL*R-KL*R*eps)), with the correct sign
+// set at the end
+//
+// For |x| in [2^{-64},2^{-4}):
+// A Taylor series expansion is used (x+p3*x^3+..+p13*x^{13})
+//
+// For |x|<2^{-64}: x is returned
+//
+// For |x|>=2^32: return +/-1
+//
+// Special cases:
+// tanh(NaN) = quiet NaN, and raise invalid exception
+// tanh(INF) = that INF
+// tanh(+/-0) = +/-0
+//
+/******************************************************************************/
+
+ATTRIBUTE_ALIGNED(4) static const juint _HALFMASK[] =
+{
+ 4160749568, 2147483647
+};
+
+ATTRIBUTE_ALIGNED(4) static const juint _ONEMASK[] =
+{
+ 0, 1072693248
+};
+
+ATTRIBUTE_ALIGNED(4) static const juint _TWOMASK[] =
+{
+ 0, 1073741824
+};
+
+ATTRIBUTE_ALIGNED(16) static const juint _MASK3[] =
+{
+ 0, 4294967280, 0, 4294967280
+};
+
+ATTRIBUTE_ALIGNED(16) static const juint _RMASK[] =
+{
+ 4294705152, 4294967295, 4294705152, 4294967295
+};
+
+ATTRIBUTE_ALIGNED(16) static const juint _L2E[] =
+{
+ 1610612736, 1082594631, 4166901572, 1055174155
+};
+
+ATTRIBUTE_ALIGNED(16) static const juint _Shifter[] =
+{
+ 0, 1127743488, 0, 3275227136
+};
+
+ATTRIBUTE_ALIGNED(16) static const juint _cv[] =
+{
+ 3884607281, 3168131199, 3607404735, 3190582024, 1874480759,
+ 1032041131, 4286760334, 1053736893, 4277811695, 3211144770,
+ 0, 0
+};
+
+ATTRIBUTE_ALIGNED(4) static const juint _pv[] =
+{
+ 236289503, 1064135997, 463583772, 3215696314, 1441186365,
+ 3212977891, 286331153, 1069617425, 2284589306, 1066820852,
+ 1431655765, 3218429269
+};
+
+ATTRIBUTE_ALIGNED(16) static const juint _T2_neg_f[] =
+{
+ 0, 1072693248, 0, 0, 1797923801, 1072687577,
+ 1950547427, 1013229059, 730821105, 1072681922, 2523232743, 1012067188,
+ 915592468, 1072676282, 352947894, 3161024371, 2174652632, 1072670657,
+ 4087714590, 1014450259, 35929225, 1072665048, 2809788041, 3159436968,
+ 2912730644, 1072659453, 3490067722, 3163405074, 2038973688, 1072653874,
+ 892941374, 1016046459, 1533953344, 1072648310, 769171851, 1015665633,
+ 1222472308, 1072642761, 1054357470, 3161021018, 929806999, 1072637227,
+ 3205336643, 1015259557, 481706282, 1072631708, 1696079173, 3162710528,
+ 3999357479, 1072626203, 2258941616, 1015924724, 2719515920, 1072620714,
+ 2760332941, 1015137933, 764307441, 1072615240, 3021057420, 3163329523,
+ 2256325230, 1072609780, 580117746, 1015317295, 2728693978, 1072604335,
+ 396109971, 3163462691, 2009970496, 1072598905, 2159039665, 3162572948,
+ 4224142467, 1072593489, 3389820386, 1015207202, 610758006, 1072588089,
+ 1965209397, 3161866232, 3884662774, 1072582702, 2158611599, 1014210185,
+ 991358482, 1072577331, 838715019, 3163157668, 351641897, 1072571974,
+ 2172261526, 3163010599, 1796832535, 1072566631, 3176955716, 3160585513,
+ 863738719, 1072561303, 1326992220, 3162613197, 1679558232, 1072555989,
+ 2390342287, 3163333970, 4076975200, 1072550689, 2029000899, 1015208535,
+ 3594158869, 1072545404, 2456521700, 3163256561, 64696965, 1072540134,
+ 1768797490, 1015816960, 1912561781, 1072534877, 3147495102, 1015678253,
+ 382305176, 1072529635, 2347622376, 3162578625, 3898795731, 1072524406,
+ 1249994144, 1011869818, 3707479175, 1072519192, 3613079303, 1014164738,
+ 3939148246, 1072513992, 3210352148, 1015274323, 135105010, 1072508807,
+ 1906148728, 3163375739, 721996136, 1072503635, 563754734, 1015371318,
+ 1242007932, 1072498477, 1132034716, 3163339831, 1532734324, 1072493333,
+ 3094216535, 3163162857, 1432208378, 1072488203, 1401068914, 3162363963,
+ 778901109, 1072483087, 2248183955, 3161268751, 3706687593, 1072477984,
+ 3521726940, 1013253067, 1464976603, 1072472896, 3507292405, 3161977534,
+ 2483480501, 1072467821, 1216371780, 1013034172, 2307442995, 1072462760,
+ 3190117721, 3162404539, 777507147, 1072457713, 4282924205, 1015187533,
+ 2029714210, 1072452679, 613660079, 1015099143, 1610600570, 1072447659,
+ 3766732298, 1015760183, 3657065772, 1072442652, 399025623, 3162957078,
+ 3716502172, 1072437659, 2303740125, 1014042725, 1631695677, 1072432680,
+ 2717633076, 3162344026, 1540824585, 1072427714, 1064017011, 3163487690,
+ 3287523847, 1072422761, 1625971539, 3157009955, 2420883922, 1072417822,
+ 2049810052, 1014119888, 3080351519, 1072412896, 3379126788, 3157218001,
+ 815859274, 1072407984, 240396590, 3163487443, 4062661092, 1072403084,
+ 1422616006, 3163255318, 4076559943, 1072398198, 2119478331, 3160758351,
+ 703710506, 1072393326, 1384660846, 1015195891, 2380618042, 1072388466,
+ 3149557219, 3163320799, 364333489, 1072383620, 3923737744, 3161421373,
+ 3092190715, 1072378786, 814012168, 3159523422, 1822067026, 1072373966,
+ 1241994956, 1015340290, 697153126, 1072369159, 1283515429, 3163283189,
+ 3861050111, 1072364364, 254893773, 3162813180, 2572866477, 1072359583,
+ 878562433, 1015521741, 977020788, 1072354815, 3065100517, 1015541563,
+ 3218338682, 1072350059, 3404164304, 3162477108, 557149882, 1072345317,
+ 3672720709, 1014537265, 1434058175, 1072340587, 251133233, 1015085769,
+ 1405169241, 1072335870, 2998539689, 3162830951, 321958744, 1072331166,
+ 3401933767, 1015794558, 2331271250, 1072326474, 812057446, 1012207446,
+ 2990417245, 1072321795, 3683467745, 3163369326, 2152073944, 1072317129,
+ 1486860576, 3163203456, 3964284211, 1072312475, 2111583915, 1015427164,
+ 3985553595, 1072307834, 4002146062, 1015834136, 2069751141, 1072303206,
+ 1562170675, 3162724681, 2366108318, 1072298590, 2867985102, 3161762254,
+ 434316067, 1072293987, 2028358766, 1013458122, 424392917, 1072289396,
+ 2749202995, 3162838718, 2191782032, 1072284817, 2960257726, 1013742662,
+ 1297350157, 1072280251, 1308022040, 3163412558, 1892288442, 1072275697,
+ 2446255666, 3162600381, 3833209506, 1072271155, 2722920684, 1013754842,
+ 2682146384, 1072266626, 2082178513, 3163363419, 2591453363, 1072262109,
+ 2132396182, 3159074198, 3418903055, 1072257604, 2527457337, 3160820604,
+ 727685349, 1072253112, 2038246809, 3162358742, 2966275557, 1072248631,
+ 2176155324, 3159842759, 1403662306, 1072244163, 2788809599, 3161671007,
+ 194117574, 1072239707, 777528612, 3163412089, 3492293770, 1072235262,
+ 2248032210, 1015386826, 2568320822, 1072230830, 2732824428, 1014352915,
+ 1577608921, 1072226410, 1875489510, 3162968394, 380978316, 1072222002,
+ 854188970, 3160462686, 3134592888, 1072217605, 4232266862, 1015991134,
+ 1110089947, 1072213221, 1451641639, 1015474673, 2759350287, 1072208848,
+ 1148526634, 1015894933, 3649726105, 1072204487, 4085036346, 1015649474,
+ 3643909174, 1072200138, 3537586109, 1014354647, 2604962541, 1072195801,
+ 2614425274, 3163539192, 396319521, 1072191476, 4172420816, 3159074632,
+ 1176749997, 1072187162, 2738998779, 3162035844, 515457527, 1072182860,
+ 836709333, 1015651226, 2571947539, 1072178569, 3558159064, 3163376669,
+ 2916157145, 1072174290, 219487565, 1015309367, 1413356050, 1072170023,
+ 1651349291, 3162668166, 2224145553, 1072165767, 3482522030, 3161489169,
+ 919555682, 1072161523, 3121969534, 1012948226, 1660913392, 1072157290,
+ 4218599604, 1015135707, 19972402, 1072153069, 3507899862, 1016009292,
+ 158781403, 1072148859, 2221464712, 3163286453, 1944781191, 1072144660,
+ 3993278767, 3161724279, 950803702, 1072140473, 1655364926, 1015237032,
+ 1339972927, 1072136297, 167908909, 1015572152, 2980802057, 1072132132,
+ 378619896, 1015773303, 1447192521, 1072127979, 1462857171, 3162514521,
+ 903334909, 1072123837, 1636462108, 1015039997, 1218806132, 1072119706,
+ 1818613052, 3162548441, 2263535754, 1072115586, 752233586, 3162639008,
+ 3907805044, 1072111477, 2257091225, 3161550407, 1727278727, 1072107380,
+ 3562710623, 1011471940, 4182873220, 1072103293, 629542646, 3161996303,
+ 2555984613, 1072099218, 2652555442, 3162552692, 1013258799, 1072095154,
+ 1748797611, 3160129082, 3721688645, 1072091100, 3069276937, 1015839401,
+ 1963711167, 1072087058, 1744767757, 3160574294, 4201977662, 1072083026,
+ 748330254, 1013594357, 1719614413, 1072079006, 330458198, 3163282740,
+ 2979960120, 1072074996, 2599109725, 1014498493, 3561793907, 1072070997,
+ 1157054053, 1011890350, 3339203574, 1072067009, 1483497780, 3162408754,
+ 2186617381, 1072063032, 2270764084, 3163272713, 4273770423, 1072059065,
+ 3383180809, 3163218901, 885834528, 1072055110, 1973258547, 3162261564,
+ 488188413, 1072051165, 3199821029, 1015564048, 2956612997, 1072047230,
+ 2118169751, 3162735553, 3872257780, 1072043306, 1253592103, 1015958334,
+ 3111574537, 1072039393, 2606161479, 3162759746, 551349105, 1072035491,
+ 3821916050, 3162106589, 363667784, 1072031599, 813753950, 1015785209,
+ 2425981843, 1072027717, 2830390851, 3163346599, 2321106615, 1072023846,
+ 2171176610, 1009535771, 4222122499, 1072019985, 1277378074, 3163256737,
+ 3712504873, 1072016135, 88491949, 1015427660, 671025100, 1072012296,
+ 3832014351, 3163022030, 3566716925, 1072008466, 1536826856, 1014142433,
+ 3689071823, 1072004647, 2321004996, 3162552716, 917841882, 1072000839,
+ 18715565, 1015659308, 3723038930, 1071997040, 378465264, 3162569582,
+ 3395129871, 1071993252, 4025345435, 3162335388, 4109806887, 1071989474,
+ 422403966, 1014469229, 1453150082, 1071985707, 498154669, 3161488062,
+ 3896463087, 1071981949, 1139797873, 3161233805, 2731501122, 1071978202,
+ 1774031855, 3162470021, 2135241198, 1071974465, 1236747871, 1013589147,
+ 1990012071, 1071970738, 3529070563, 3162813193, 2178460671, 1071967021,
+ 777878098, 3162842493, 2583551245, 1071963314, 3161094195, 1015606491,
+ 3088564500, 1071959617, 1762311517, 1015045673, 3577096743, 1071955930,
+ 2951496418, 1013793687, 3933059031, 1071952253, 2133366768, 3161531832,
+ 4040676318, 1071948586, 4090609238, 1015663458, 3784486610, 1071944929,
+ 1581883040, 3161698953, 3049340112, 1071941282, 3062915824, 1013170595,
+ 1720398391, 1071937645, 3980678963, 3163300080, 3978100823, 1071934017,
+ 3513027190, 1015845963, 1118294578, 1071930400, 2197495694, 3159909401,
+ 1617004845, 1071926792, 82804944, 1010342778, 1065662932, 1071923194,
+ 2533670915, 1014530238, 3645941911, 1071919605, 3814685081, 3161573341,
+ 654919306, 1071916027, 3232961757, 3163047469, 569847338, 1071912458,
+ 472945272, 3159290729, 3278348324, 1071908898, 3069497416, 1014750712,
+ 78413852, 1071905349, 4183226867, 3163017251, 3743175029, 1071901808,
+ 2072812490, 3162175075, 1276261410, 1071898278, 300981948, 1014684169,
+ 1156440435, 1071894757, 2351451249, 1013967056, 3272845541, 1071891245,
+ 928852419, 3163488248, 3219942644, 1071887743, 3798990616, 1015368806,
+ 887463927, 1071884251, 3596744163, 3160794166, 460407023, 1071880768,
+ 4237175092, 3163138469, 1829099622, 1071877294, 1016661181, 3163461005,
+ 589198666, 1071873830, 2664346172, 3163157962, 926591435, 1071870375,
+ 3208833762, 3162913514, 2732492859, 1071866929, 2691479646, 3162255684,
+ 1603444721, 1071863493, 1548633640, 3162201326, 1726216749, 1071860066,
+ 2466808228, 3161676405, 2992903935, 1071856648, 2218154406, 1015228193,
+ 1000925746, 1071853240, 1018491672, 3163309544, 4232894513, 1071849840,
+ 2383938684, 1014668519, 3991843581, 1071846450, 4092853457, 1014585763,
+ 171030293, 1071843070, 3526460132, 1014428778, 1253935211, 1071839698,
+ 1395382931, 3159702613, 2839424854, 1071836335, 1171596163, 1013041679,
+ 526652809, 1071832982, 4223459736, 1015879375, 2799960843, 1071829637,
+ 1423655381, 1015022151, 964107055, 1071826302, 2800439588, 3162833221,
+ 3504003472, 1071822975, 3594001060, 3157330652, 1724976915, 1071819658,
+ 420909223, 3163117379, 4112506593, 1071816349, 2947355221, 1014371048,
+ 1972484976, 1071813050, 675290301, 3161640050, 3790955393, 1071809759,
+ 2352942462, 3163180090, 874372905, 1071806478, 100263788, 1015940732,
+ 1709341917, 1071803205, 2571168217, 1014152499, 1897844341, 1071799941,
+ 1254300460, 1015275938, 1337108031, 1071796686, 3203724452, 1014677845,
+ 4219606026, 1071793439, 2434574742, 1014681548, 1853186616, 1071790202,
+ 3066496371, 1015656574, 2725843665, 1071786973, 1433917087, 1014838523,
+ 2440944790, 1071783753, 2492769774, 1014147454, 897099801, 1071780542,
+ 754756297, 1015241005, 2288159958, 1071777339, 2169144469, 1014876021,
+ 2218315341, 1071774145, 2694295388, 3163288868, 586995997, 1071770960,
+ 41662348, 3162627992, 1588871207, 1071767783, 143439582, 3162963416,
+ 828946858, 1071764615, 10642492, 1015939438, 2502433899, 1071761455,
+ 2148595913, 1015023991, 2214878420, 1071758304, 892270087, 3163116422,
+ 4162030108, 1071755161, 2763428480, 1015529349, 3949972341, 1071752027,
+ 2068408548, 1014913868, 1480023343, 1071748902, 2247196168, 1015327453,
+ 948735466, 1071745785, 3516338028, 3162574883, 2257959872, 1071742676,
+ 3802946148, 1012964927, 1014845819, 1071739576, 3117910646, 3161559105,
+ 1416741826, 1071736484, 2196380210, 1011413563, 3366293073, 1071733400,
+ 3119426314, 1014120554, 2471440686, 1071730325, 968836267, 3162214888,
+ 2930322912, 1071727258, 2599499422, 3162714047, 351405227, 1071724200,
+ 3125337328, 3159822479, 3228316108, 1071721149, 3010241991, 3158422804,
+ 2875075254, 1071718107, 4144233330, 3163333716, 3490863953, 1071715073,
+ 960797498, 3162948880, 685187902, 1071712048, 378731989, 1014843115,
+ 2952712987, 1071709030, 3293494651, 3160120301, 1608493509, 1071706021,
+ 3159622171, 3162807737, 852742562, 1071703020, 667253586, 1009793559,
+ 590962156, 1071700027, 3829346666, 3163275597, 728909815, 1071697042,
+ 383930225, 1015029468, 1172597893, 1071694065, 114433263, 1015347593,
+ 1828292879, 1071691096, 1255956747, 1015588398, 2602514713, 1071688135,
+ 2268929336, 1014354284, 3402036099, 1071685182, 405889334, 1015105656,
+ 4133881824, 1071682237, 2148155345, 3162931299, 410360776, 1071679301,
+ 1269990655, 1011975870, 728934454, 1071676372, 1413842688, 1014178612,
+ 702412510, 1071673451, 3803266087, 3162280415, 238821257, 1071670538,
+ 1469694871, 3162884987, 3541402996, 1071667632, 2759177317, 1014854626,
+ 1928746161, 1071664735, 983617676, 1014285177, 3899555717, 1071661845,
+ 427280750, 3162546972, 772914124, 1071658964, 4004372762, 1012230161,
+ 1048019041, 1071656090, 1398474845, 3160510595, 339411585, 1071653224,
+ 264588982, 3161636657, 2851812149, 1071650365, 2595802551, 1015767337,
+ 4200250559, 1071647514, 2808127345, 3161781938
+};
+
+#define __ _masm->
+
+address StubGenerator::generate_libmTanh() {
+ StubCodeMark mark(this, "StubRoutines", "libmTanh");
+ address start = __ pc();
+
+ Label L_2TAG_PACKET_0_0_1, L_2TAG_PACKET_1_0_1, L_2TAG_PACKET_2_0_1, L_2TAG_PACKET_3_0_1;
+ Label L_2TAG_PACKET_4_0_1, L_2TAG_PACKET_5_0_1;
+ Label B1_2, B1_4;
+
+ address HALFMASK = (address)_HALFMASK;
+ address ONEMASK = (address)_ONEMASK;
+ address TWOMASK = (address)_TWOMASK;
+ address MASK3 = (address)_MASK3;
+ address RMASK = (address)_RMASK;
+ address L2E = (address)_L2E;
+ address Shifter = (address)_Shifter;
+ address cv = (address)_cv;
+ address pv = (address)_pv;
+ address T2_neg_f = (address) _T2_neg_f;
+
+ __ enter(); // required for proper stackwalking of RuntimeStub frame
+
+ __ bind(B1_2);
+ __ movsd(xmm3, ExternalAddress(HALFMASK), r11 /*rscratch*/);
+ __ xorpd(xmm4, xmm4);
+ __ movsd(xmm1, ExternalAddress(L2E), r11 /*rscratch*/);
+ __ movsd(xmm2, ExternalAddress(L2E + 8), r11 /*rscratch*/);
+ __ movl(rax, 32768);
+ __ pinsrw(xmm4, rax, 3);
+ __ movsd(xmm6, ExternalAddress(Shifter), r11 /*rscratch*/);
+ __ pextrw(rcx, xmm0, 3);
+ __ andpd(xmm3, xmm0);
+ __ andnpd(xmm4, xmm0);
+ __ pshufd(xmm5, xmm4, 68);
+ __ movl(rdx, 32768);
+ __ andl(rdx, rcx);
+ __ andl(rcx, 32767);
+ __ subl(rcx, 16304);
+ __ cmpl(rcx, 144);
+ __ jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_1);
+ __ subsd(xmm4, xmm3);
+ __ mulsd(xmm3, xmm1);
+ __ mulsd(xmm2, xmm5);
+ __ cvtsd2siq(rax, xmm3);
+ __ movq(xmm7, xmm3);
+ __ addsd(xmm3, xmm6);
+ __ mulsd(xmm1, xmm4);
+ __ movsd(xmm4, ExternalAddress(ONEMASK), r11 /*rscratch*/);
+ __ subsd(xmm3, xmm6);
+ __ xorpd(xmm0, xmm0);
+ __ addsd(xmm2, xmm1);
+ __ subsd(xmm7, xmm3);
+ __ movdqu(xmm6, ExternalAddress(cv), r11 /*rscratch*/);
+ __ addsd(xmm2, xmm7);
+ __ movl(rcx, 255);
+ __ andl(rcx, rax);
+ __ addl(rcx, rcx);
+ __ lea(r8, ExternalAddress(T2_neg_f));
+ __ movdqu(xmm5, Address(r8, rcx, Address::times(8)));
+ __ shrl(rax, 4);
+ __ andl(rax, 65520);
+ __ subl(rax, 16368);
+ __ negl(rax);
+ __ pinsrw(xmm0, rax, 3);
+ __ movdqu(xmm1, ExternalAddress(cv + 16), r11 /*rscratch*/);
+ __ pshufd(xmm0, xmm0, 68);
+ __ mulpd(xmm0, xmm5);
+ __ movsd(xmm7, ExternalAddress(cv + 32), r11 /*rscratch*/);
+ __ pshufd(xmm2, xmm2, 68);
+ __ movq(xmm5, xmm4);
+ __ addsd(xmm4, xmm0);
+ __ mulpd(xmm6, xmm2);
+ __ mulsd(xmm7, xmm2);
+ __ mulpd(xmm2, xmm2);
+ __ addpd(xmm1, xmm6);
+ __ mulsd(xmm2, xmm2);
+ __ movsd(xmm3, ExternalAddress(ONEMASK), r11 /*rscratch*/);
+ __ mulpd(xmm1, xmm2);
+ __ pshufd(xmm6, xmm1, 78);
+ __ addsd(xmm1, xmm6);
+ __ movq(xmm6, xmm1);
+ __ addsd(xmm1, xmm7);
+ __ mulsd(xmm1, xmm0);
+ __ addsd(xmm1, xmm4);
+ __ andpd(xmm4, ExternalAddress(MASK3), r11 /*rscratch*/);
+ __ divsd(xmm5, xmm1);
+ __ subsd(xmm3, xmm4);
+ __ pshufd(xmm1, xmm0, 238);
+ __ addsd(xmm3, xmm0);
+ __ movq(xmm2, xmm4);
+ __ addsd(xmm3, xmm1);
+ __ mulsd(xmm1, xmm7);
+ __ mulsd(xmm7, xmm0);
+ __ addsd(xmm3, xmm1);
+ __ addsd(xmm4, xmm7);
+ __ movsd(xmm1, ExternalAddress(RMASK), r11 /*rscratch*/);
+ __ mulsd(xmm6, xmm0);
+ __ andpd(xmm4, ExternalAddress(MASK3), r11 /*rscratch*/);
+ __ addsd(xmm3, xmm6);
+ __ movq(xmm6, xmm4);
+ __ subsd(xmm2, xmm4);
+ __ addsd(xmm2, xmm7);
+ __ movsd(xmm7, ExternalAddress(ONEMASK), r11 /*rscratch*/);
+ __ andpd(xmm5, xmm1);
+ __ addsd(xmm3, xmm2);
+ __ mulsd(xmm4, xmm5);
+ __ xorpd(xmm2, xmm2);
+ __ mulsd(xmm3, xmm5);
+ __ subsd(xmm6, ExternalAddress(TWOMASK), r11 /*rscratch*/);
+ __ subsd(xmm4, xmm7);
+ __ xorl(rdx, 32768);
+ __ pinsrw(xmm2, rdx, 3);
+ __ addsd(xmm4, xmm3);
+ __ mulsd(xmm6, xmm5);
+ __ movq(xmm1, xmm3);
+ __ mulsd(xmm3, xmm4);
+ __ movq(xmm0, xmm6);
+ __ mulsd(xmm6, xmm4);
+ __ subsd(xmm1, xmm3);
+ __ subsd(xmm1, xmm6);
+ __ addsd(xmm0, xmm1);
+ __ xorpd(xmm0, xmm2);
+ __ jmp(B1_4);
+
+ __ bind(L_2TAG_PACKET_0_0_1);
+ __ addl(rcx, 960);
+ __ cmpl(rcx, 1104);
+ __ jcc(Assembler::aboveEqual, L_2TAG_PACKET_1_0_1);
+ __ movdqu(xmm2, ExternalAddress(pv), r11 /*rscratch*/);
+ __ pshufd(xmm1, xmm0, 68);
+ __ movdqu(xmm3, ExternalAddress(pv + 16), r11 /*rscratch*/);
+ __ mulpd(xmm1, xmm1);
+ __ movdqu(xmm4, ExternalAddress(pv + 32), r11 /*rscratch*/);
+ __ mulpd(xmm2, xmm1);
+ __ pshufd(xmm5, xmm1, 68);
+ __ addpd(xmm2, xmm3);
+ __ mulsd(xmm5, xmm5);
+ __ mulpd(xmm2, xmm1);
+ __ mulsd(xmm5, xmm5);
+ __ addpd(xmm2, xmm4);
+ __ mulpd(xmm2, xmm5);
+ __ pshufd(xmm5, xmm2, 238);
+ __ addsd(xmm2, xmm5);
+ __ mulsd(xmm2, xmm0);
+ __ addsd(xmm0, xmm2);
+ __ jmp(B1_4);
+
+ __ bind(L_2TAG_PACKET_1_0_1);
+ __ addl(rcx, 15344);
+ __ cmpl(rcx, 16448);
+ __ jcc(Assembler::aboveEqual, L_2TAG_PACKET_2_0_1);
+ __ cmpl(rcx, 16);
+ __ jcc(Assembler::below, L_2TAG_PACKET_3_0_1);
+ __ xorpd(xmm2, xmm2);
+ __ movl(rax, 17392);
+ __ pinsrw(xmm2, rax, 3);
+ __ mulsd(xmm2, xmm0);
+ __ addsd(xmm2, xmm0);
+ __ jmp(B1_4);
+
+ __ bind(L_2TAG_PACKET_3_0_1);
+ __ movq(xmm2, xmm0);
+ __ mulsd(xmm2, xmm2);
+ __ jmp(B1_4);
+
+ __ bind(L_2TAG_PACKET_2_0_1);
+ __ cmpl(rcx, 32752);
+ __ jcc(Assembler::aboveEqual, L_2TAG_PACKET_4_0_1);
+ __ xorpd(xmm2, xmm2);
+ __ movl(rcx, 15344);
+ __ pinsrw(xmm2, rcx, 3);
+ __ movq(xmm3, xmm2);
+ __ mulsd(xmm2, xmm2);
+ __ addsd(xmm2, xmm3);
+
+ __ bind(L_2TAG_PACKET_5_0_1);
+ __ xorpd(xmm0, xmm0);
+ __ orl(rdx, 16368);
+ __ pinsrw(xmm0, rdx, 3);
+ __ jmp(B1_4);
+
+ __ bind(L_2TAG_PACKET_4_0_1);
+ __ movq(xmm2, xmm0);
+ __ movdl(rax, xmm0);
+ __ psrlq(xmm2, 20);
+ __ movdl(rcx, xmm2);
+ __ orl(rcx, rax);
+ __ cmpl(rcx, 0);
+ __ jcc(Assembler::equal, L_2TAG_PACKET_5_0_1);
+ __ addsd(xmm0, xmm0);
+
+ __ bind(B1_4);
+ __ leave(); // required for proper stackwalking of RuntimeStub frame
+ __ ret(0);
+
+ return start;
+}
+
+#undef __
diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_32.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_32.cpp
index ba9eb32e8c13e..75611524e3b0a 100644
--- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_32.cpp
+++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_32.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -373,6 +373,10 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
// [ lo(arg) ]
// [ hi(arg) ]
//
+ if (kind == Interpreter::java_lang_math_tanh) {
+ return nullptr;
+ }
+
if (kind == Interpreter::java_lang_math_fmaD) {
if (!UseFMA) {
return nullptr; // Generate a vanilla entry
diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp
index 26eea4c1d6a5f..5ea2d8eba259b 100644
--- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp
+++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -465,6 +465,10 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
} else {
__ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dtan));
}
+ } else if (kind == Interpreter::java_lang_math_tanh) {
+ assert(StubRoutines::dtanh() != nullptr, "not initialized");
+ __ movdbl(xmm0, Address(rsp, wordSize));
+ __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dtanh())));
} else if (kind == Interpreter::java_lang_math_abs) {
assert(StubRoutines::x86::double_sign_mask() != nullptr, "not initialized");
__ movdbl(xmm0, Address(rsp, wordSize));
diff --git a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp
index b80124cc34e43..f967fee930579 100644
--- a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp
+++ b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp
@@ -103,14 +103,14 @@
#define ZFILENAME_HEAP "java_heap"
// Preferred tmpfs mount points, ordered by priority
-static const char* z_preferred_tmpfs_mountpoints[] = {
+static const char* ZPreferredTmpfsMountpoints[] = {
"/dev/shm",
"/run/shm",
nullptr
};
// Preferred hugetlbfs mount points, ordered by priority
-static const char* z_preferred_hugetlbfs_mountpoints[] = {
+static const char* ZPreferredHugetlbfsMountpoints[] = {
"/dev/hugepages",
"/hugepages",
nullptr
@@ -226,8 +226,8 @@ int ZPhysicalMemoryBacking::create_file_fd(const char* name) const {
? ZFILESYSTEM_HUGETLBFS
: ZFILESYSTEM_TMPFS;
const char** const preferred_mountpoints = ZLargePages::is_explicit()
- ? z_preferred_hugetlbfs_mountpoints
- : z_preferred_tmpfs_mountpoints;
+ ? ZPreferredHugetlbfsMountpoints
+ : ZPreferredTmpfsMountpoints;
// Find mountpoint
ZMountPoint mountpoint(filesystem, preferred_mountpoints);
diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp
index 1acce2540a855..817757f1ac6a2 100644
--- a/src/hotspot/os/windows/os_windows.cpp
+++ b/src/hotspot/os/windows/os_windows.cpp
@@ -1947,7 +1947,10 @@ void os::win32::print_windows_version(outputStream* st) {
// - 2016 GA 10/2016 build: 14393
// - 2019 GA 11/2018 build: 17763
// - 2022 GA 08/2021 build: 20348
- if (build_number > 20347) {
+ // - 2025 Preview build : 26040
+ if (build_number > 26039) {
+ st->print("Server 2025");
+ } else if (build_number > 20347) {
st->print("Server 2022");
} else if (build_number > 17762) {
st->print("Server 2019");
@@ -4090,6 +4093,39 @@ int os::win32::_build_minor = 0;
bool os::win32::_processor_group_warning_displayed = false;
bool os::win32::_job_object_processor_group_warning_displayed = false;
+void getWindowsInstallationType(char* buffer, int bufferSize) {
+ HKEY hKey;
+ const char* subKey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
+ const char* valueName = "InstallationType";
+
+ DWORD valueLength = bufferSize;
+
+ // Initialize buffer with empty string
+ buffer[0] = '\0';
+
+ // Open the registry key
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS) {
+ // Return empty buffer if key cannot be opened
+ return;
+ }
+
+ // Query the value
+ if (RegQueryValueExA(hKey, valueName, NULL, NULL, (LPBYTE)buffer, &valueLength) != ERROR_SUCCESS) {
+ RegCloseKey(hKey);
+ buffer[0] = '\0';
+ return;
+ }
+
+ RegCloseKey(hKey);
+}
+
+bool isNanoServer() {
+ const int BUFFER_SIZE = 256;
+ char installationType[BUFFER_SIZE];
+ getWindowsInstallationType(installationType, BUFFER_SIZE);
+ return (strcmp(installationType, "Nano Server") == 0);
+}
+
void os::win32::initialize_windows_version() {
assert(_major_version == 0, "windows version already initialized.");
@@ -4107,7 +4143,13 @@ void os::win32::initialize_windows_version() {
warning("Attempt to determine system directory failed: %s", buf_len != 0 ? error_msg_buffer : "");
return;
}
- strncat(kernel32_path, "\\kernel32.dll", MAX_PATH - ret);
+
+ if (isNanoServer()) {
+ // On Windows Nanoserver the kernel32.dll is located in the forwarders subdirectory
+ strncat(kernel32_path, "\\forwarders\\kernel32.dll", MAX_PATH - ret);
+ } else {
+ strncat(kernel32_path, "\\kernel32.dll", MAX_PATH - ret);
+ }
DWORD version_size = GetFileVersionInfoSize(kernel32_path, nullptr);
if (version_size == 0) {
diff --git a/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp
index a7dc84770f84c..368d6c971fae0 100644
--- a/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp
+++ b/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp
@@ -54,6 +54,24 @@ inline void OrderAccess::fence() {
}
inline void OrderAccess::cross_modify_fence_impl() {
+ // From 3 “Zifencei” Instruction-Fetch Fence, Version 2.0
+ // "RISC-V does not guarantee that stores to instruction memory will be made
+ // visible to instruction fetches on a RISC-V hart until that hart executes a
+ // FENCE.I instruction. A FENCE.I instruction ensures that a subsequent
+ // instruction fetch on a RISC-V hart will see any previous data stores
+ // already visible to the same RISC-V hart. FENCE.I does not ensure that other
+ // RISC-V harts’ instruction fetches will observe the local hart’s stores in a
+ // multiprocessor system."
+ //
+ // Hence to be able to use fence.i directly we need a kernel that supports
+ // PR_RISCV_CTX_SW_FENCEI_ON. Thus if context switch to another hart we are
+ // ensured that instruction fetch will see any previous data stores
+ //
+ // The alternative is using full system IPI (system wide icache sync) then
+ // this barrier is not strictly needed. As this is emitted in runtime slow-path
+ // we will just always emit it, typically after a safepoint.
+ guarantee(VM_Version::supports_fencei_barrier(), "Linux kernel require fence.i");
+ __asm__ volatile("fence.i" : : : "memory");
}
#endif // OS_CPU_LINUX_RISCV_ORDERACCESS_LINUX_RISCV_HPP
diff --git a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp
index 3f9f26b525ba5..a3a226502f6fc 100644
--- a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp
+++ b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#ifndef HWCAP_ISA_I
#define HWCAP_ISA_I nth_bit('I' - 'A')
@@ -82,6 +83,23 @@
__v; \
})
+// prctl PR_RISCV_SET_ICACHE_FLUSH_CTX is from Linux 6.9
+#ifndef PR_RISCV_SET_ICACHE_FLUSH_CTX
+#define PR_RISCV_SET_ICACHE_FLUSH_CTX 71
+#endif
+#ifndef PR_RISCV_CTX_SW_FENCEI_ON
+#define PR_RISCV_CTX_SW_FENCEI_ON 0
+#endif
+#ifndef PR_RISCV_CTX_SW_FENCEI_OFF
+#define PR_RISCV_CTX_SW_FENCEI_OFF 1
+#endif
+#ifndef PR_RISCV_SCOPE_PER_PROCESS
+#define PR_RISCV_SCOPE_PER_PROCESS 0
+#endif
+#ifndef PR_RISCV_SCOPE_PER_THREAD
+#define PR_RISCV_SCOPE_PER_THREAD 1
+#endif
+
uint32_t VM_Version::cpu_vector_length() {
assert(ext_V.enabled(), "should not call this");
return (uint32_t)read_csr(CSR_VLENB);
@@ -102,6 +120,7 @@ void VM_Version::setup_cpu_available_features() {
if (!RiscvHwprobe::probe_features()) {
os_aux_features();
}
+
char* uarch = os_uarch_additional_features();
vendor_features();
@@ -155,6 +174,24 @@ void VM_Version::setup_cpu_available_features() {
i++;
}
+ // Linux kernel require Zifencei
+ if (!ext_Zifencei.enabled()) {
+ log_info(os, cpu)("Zifencei not found, required by Linux, enabling.");
+ ext_Zifencei.enable_feature();
+ }
+
+ if (UseCtxFencei) {
+ // Note that we can set this up only for effected threads
+ // via PR_RISCV_SCOPE_PER_THREAD, i.e. on VM attach/deattach.
+ int ret = prctl(PR_RISCV_SET_ICACHE_FLUSH_CTX, PR_RISCV_CTX_SW_FENCEI_ON, PR_RISCV_SCOPE_PER_PROCESS);
+ if (ret == 0) {
+ log_debug(os, cpu)("UseCtxFencei (PR_RISCV_CTX_SW_FENCEI_ON) enabled.");
+ } else {
+ FLAG_SET_ERGO(UseCtxFencei, false);
+ log_info(os, cpu)("UseCtxFencei (PR_RISCV_CTX_SW_FENCEI_ON) disabled, unsupported by kernel.");
+ }
+ }
+
_features_string = os::strdup(buf);
}
diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp
index 04f54170d7208..aa1be5ec66c15 100644
--- a/src/hotspot/share/c1/c1_Compiler.cpp
+++ b/src/hotspot/share/c1/c1_Compiler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -173,6 +173,9 @@ bool Compiler::is_intrinsic_supported(vmIntrinsics::ID id) {
case vmIntrinsics::_dsin:
case vmIntrinsics::_dcos:
case vmIntrinsics::_dtan:
+ #if defined(AMD64)
+ case vmIntrinsics::_dtanh:
+ #endif
case vmIntrinsics::_dlog:
case vmIntrinsics::_dlog10:
case vmIntrinsics::_dexp:
diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp
index a2e903edc342f..02be6f8d49e4a 100644
--- a/src/hotspot/share/c1/c1_GraphBuilder.cpp
+++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp
@@ -3339,6 +3339,7 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
case vmIntrinsics::_dsin : // fall through
case vmIntrinsics::_dcos : // fall through
case vmIntrinsics::_dtan : // fall through
+ case vmIntrinsics::_dtanh : // fall through
case vmIntrinsics::_dlog : // fall through
case vmIntrinsics::_dlog10 : // fall through
case vmIntrinsics::_dexp : // fall through
diff --git a/src/hotspot/share/c1/c1_LIR.hpp b/src/hotspot/share/c1/c1_LIR.hpp
index c875470c3a813..97f2ab7d06b0b 100644
--- a/src/hotspot/share/c1/c1_LIR.hpp
+++ b/src/hotspot/share/c1/c1_LIR.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -2042,8 +2042,9 @@ class LIR_OpProfileCall : public LIR_Op {
virtual void print_instr(outputStream* out) const PRODUCT_RETURN;
bool should_profile_receiver_type() const {
bool callee_is_static = _profiled_callee->is_loaded() && _profiled_callee->is_static();
+ bool callee_is_private = _profiled_callee->is_loaded() && _profiled_callee->is_private();
Bytecodes::Code bc = _profiled_method->java_code_at_bci(_profiled_bci);
- bool call_is_virtual = (bc == Bytecodes::_invokevirtual && !_profiled_callee->can_be_statically_bound()) || bc == Bytecodes::_invokeinterface;
+ bool call_is_virtual = (bc == Bytecodes::_invokevirtual && !callee_is_private) || bc == Bytecodes::_invokeinterface;
return C1ProfileVirtualCalls && call_is_virtual && !callee_is_static;
}
};
diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp
index 4e63736503fe0..74fdf7a5b76a3 100644
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp
@@ -2971,6 +2971,7 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) {
case vmIntrinsics::_dsqrt: // fall through
case vmIntrinsics::_dsqrt_strict: // fall through
case vmIntrinsics::_dtan: // fall through
+ case vmIntrinsics::_dtanh: // fall through
case vmIntrinsics::_dsin : // fall through
case vmIntrinsics::_dcos : // fall through
case vmIntrinsics::_dexp : // fall through
diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp
index 5b44d5c0f1983..915f00f77c523 100644
--- a/src/hotspot/share/c1/c1_Runtime1.cpp
+++ b/src/hotspot/share/c1/c1_Runtime1.cpp
@@ -347,6 +347,7 @@ const char* Runtime1::name_for_address(address entry) {
FUNCTION_CASE(entry, StubRoutines::dsin());
FUNCTION_CASE(entry, StubRoutines::dcos());
FUNCTION_CASE(entry, StubRoutines::dtan());
+ FUNCTION_CASE(entry, StubRoutines::dtanh());
#undef FUNCTION_CASE
diff --git a/src/hotspot/share/cds/archiveHeapWriter.cpp b/src/hotspot/share/cds/archiveHeapWriter.cpp
index d8ee7155452ff..853d459c691dd 100644
--- a/src/hotspot/share/cds/archiveHeapWriter.cpp
+++ b/src/hotspot/share/cds/archiveHeapWriter.cpp
@@ -88,7 +88,6 @@ void ArchiveHeapWriter::init() {
_native_pointers = new GrowableArrayCHeap(2048);
_source_objs = new GrowableArrayCHeap(10000);
- guarantee(UseG1GC, "implementation limitation");
guarantee(MIN_GC_REGION_ALIGNMENT <= G1HeapRegion::min_region_size_in_words() * HeapWordSize, "must be");
}
}
@@ -249,11 +248,16 @@ void ArchiveHeapWriter::copy_roots_to_buffer(GrowableArrayCHeap_rank;
int rank_b = b->_rank;
@@ -452,26 +451,30 @@ size_t ArchiveHeapWriter::copy_one_source_obj_to_buffer(oop src_obj) {
void ArchiveHeapWriter::set_requested_address(ArchiveHeapInfo* info) {
assert(!info->is_used(), "only set once");
- assert(UseG1GC, "must be");
- address heap_end = (address)G1CollectedHeap::heap()->reserved().end();
- log_info(cds, heap)("Heap end = %p", heap_end);
size_t heap_region_byte_size = _buffer_used;
assert(heap_region_byte_size > 0, "must archived at least one object!");
-
if (UseCompressedOops) {
- _requested_bottom = align_down(heap_end - heap_region_byte_size, G1HeapRegion::GrainBytes);
+ if (UseG1GC) {
+ address heap_end = (address)G1CollectedHeap::heap()->reserved().end();
+ log_info(cds, heap)("Heap end = %p", heap_end);
+ _requested_bottom = align_down(heap_end - heap_region_byte_size, G1HeapRegion::GrainBytes);
+ _requested_bottom = align_down(_requested_bottom, MIN_GC_REGION_ALIGNMENT);
+ assert(is_aligned(_requested_bottom, G1HeapRegion::GrainBytes), "sanity");
+ } else {
+ _requested_bottom = align_up(CompressedOops::begin(), MIN_GC_REGION_ALIGNMENT);
+ }
} else {
// We always write the objects as if the heap started at this address. This
// makes the contents of the archive heap deterministic.
//
// Note that at runtime, the heap address is selected by the OS, so the archive
// heap will not be mapped at 0x10000000, and the contents need to be patched.
- _requested_bottom = (address)NOCOOPS_REQUESTED_BASE;
+ _requested_bottom = align_up((address)NOCOOPS_REQUESTED_BASE, MIN_GC_REGION_ALIGNMENT);
}
- assert(is_aligned(_requested_bottom, G1HeapRegion::GrainBytes), "sanity");
+ assert(is_aligned(_requested_bottom, MIN_GC_REGION_ALIGNMENT), "sanity");
_requested_top = _requested_bottom + _buffer_used;
diff --git a/src/hotspot/share/cds/archiveHeapWriter.hpp b/src/hotspot/share/cds/archiveHeapWriter.hpp
index 961d2b52133f8..29ea50ba5fe86 100644
--- a/src/hotspot/share/cds/archiveHeapWriter.hpp
+++ b/src/hotspot/share/cds/archiveHeapWriter.hpp
@@ -111,11 +111,10 @@ class ArchiveHeapWriter : AllStatic {
public:
static const intptr_t NOCOOPS_REQUESTED_BASE = 0x10000000;
- // The minimum region size of all collectors that are supported by CDS in
- // ArchiveHeapLoader::can_map() mode. Currently only G1 is supported. G1's region size
- // depends on -Xmx, but can never be smaller than 1 * M.
- // (TODO: Perhaps change to 256K to be compatible with Shenandoah)
- static constexpr int MIN_GC_REGION_ALIGNMENT = 1 * M;
+ // The minimum region size of all collectors that are supported by CDS.
+ // G1 heap region size can never be smaller than 1M.
+ // Shenandoah heap region size can never be smaller than 256K.
+ static constexpr int MIN_GC_REGION_ALIGNMENT = 256 * K;
private:
class EmbeddedOopRelocator;
diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp
index 7bbb9688015e7..c935541d7cf0a 100644
--- a/src/hotspot/share/cds/filemap.cpp
+++ b/src/hotspot/share/cds/filemap.cpp
@@ -1581,39 +1581,38 @@ static size_t write_bitmap(const CHeapBitMap* map, char* output, size_t offset)
return offset + size_in_bytes;
}
-// The start of the archived heap has many primitive arrays (String
-// bodies) that are not marked by the oop/ptr maps. So we must have
-// lots of leading zeros.
-size_t FileMapInfo::remove_bitmap_leading_zeros(CHeapBitMap* map) {
- size_t old_zeros = map->find_first_set_bit(0);
+// The sorting code groups the objects with non-null oop/ptrs together.
+// Relevant bitmaps then have lots of leading and trailing zeros, which
+// we do not have to store.
+size_t FileMapInfo::remove_bitmap_zeros(CHeapBitMap* map) {
+ BitMap::idx_t first_set = map->find_first_set_bit(0);
+ BitMap::idx_t last_set = map->find_last_set_bit(0);
size_t old_size = map->size();
// Slice and resize bitmap
- map->truncate(old_zeros, map->size());
+ map->truncate(first_set, last_set + 1);
- DEBUG_ONLY(
- size_t new_zeros = map->find_first_set_bit(0);
- assert(new_zeros == 0, "Should have removed leading zeros");
- )
+ assert(map->at(0), "First bit should be set");
+ assert(map->at(map->size() - 1), "Last bit should be set");
assert(map->size() <= old_size, "sanity");
- return old_zeros;
+
+ return first_set;
}
char* FileMapInfo::write_bitmap_region(CHeapBitMap* rw_ptrmap, CHeapBitMap* ro_ptrmap, ArchiveHeapInfo* heap_info,
size_t &size_in_bytes) {
- size_t removed_rw_zeros = remove_bitmap_leading_zeros(rw_ptrmap);
- size_t removed_ro_zeros = remove_bitmap_leading_zeros(ro_ptrmap);
- header()->set_rw_ptrmap_start_pos(removed_rw_zeros);
- header()->set_ro_ptrmap_start_pos(removed_ro_zeros);
+ size_t removed_rw_leading_zeros = remove_bitmap_zeros(rw_ptrmap);
+ size_t removed_ro_leading_zeros = remove_bitmap_zeros(ro_ptrmap);
+ header()->set_rw_ptrmap_start_pos(removed_rw_leading_zeros);
+ header()->set_ro_ptrmap_start_pos(removed_ro_leading_zeros);
size_in_bytes = rw_ptrmap->size_in_bytes() + ro_ptrmap->size_in_bytes();
if (heap_info->is_used()) {
- // Remove leading zeros
- size_t removed_oop_zeros = remove_bitmap_leading_zeros(heap_info->oopmap());
- size_t removed_ptr_zeros = remove_bitmap_leading_zeros(heap_info->ptrmap());
-
- header()->set_heap_oopmap_start_pos(removed_oop_zeros);
- header()->set_heap_ptrmap_start_pos(removed_ptr_zeros);
+ // Remove leading and trailing zeros
+ size_t removed_oop_leading_zeros = remove_bitmap_zeros(heap_info->oopmap());
+ size_t removed_ptr_leading_zeros = remove_bitmap_zeros(heap_info->ptrmap());
+ header()->set_heap_oopmap_start_pos(removed_oop_leading_zeros);
+ header()->set_heap_ptrmap_start_pos(removed_ptr_leading_zeros);
size_in_bytes += heap_info->oopmap()->size_in_bytes();
size_in_bytes += heap_info->ptrmap()->size_in_bytes();
diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp
index aa728b9d4949f..1bf2510a3351c 100644
--- a/src/hotspot/share/cds/filemap.hpp
+++ b/src/hotspot/share/cds/filemap.hpp
@@ -445,7 +445,7 @@ class FileMapInfo : public CHeapObj {
void write_header();
void write_region(int region, char* base, size_t size,
bool read_only, bool allow_exec);
- size_t remove_bitmap_leading_zeros(CHeapBitMap* map);
+ size_t remove_bitmap_zeros(CHeapBitMap* map);
char* write_bitmap_region(CHeapBitMap* rw_ptrmap, CHeapBitMap* ro_ptrmap, ArchiveHeapInfo* heap_info,
size_t &size_in_bytes);
size_t write_heap_region(ArchiveHeapInfo* heap_info);
diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp
index 2bf75a5ba6512..1fddcb0d81f8a 100644
--- a/src/hotspot/share/cds/heapShared.cpp
+++ b/src/hotspot/share/cds/heapShared.cpp
@@ -471,11 +471,13 @@ void HeapShared::archive_objects(ArchiveHeapInfo *heap_info) {
// Cache for recording where the archived objects are copied to
create_archived_object_cache();
- log_info(cds)("Heap range = [" PTR_FORMAT " - " PTR_FORMAT "]",
- UseCompressedOops ? p2i(CompressedOops::begin()) :
- p2i((address)G1CollectedHeap::heap()->reserved().start()),
- UseCompressedOops ? p2i(CompressedOops::end()) :
- p2i((address)G1CollectedHeap::heap()->reserved().end()));
+ if (UseCompressedOops || UseG1GC) {
+ log_info(cds)("Heap range = [" PTR_FORMAT " - " PTR_FORMAT "]",
+ UseCompressedOops ? p2i(CompressedOops::begin()) :
+ p2i((address)G1CollectedHeap::heap()->reserved().start()),
+ UseCompressedOops ? p2i(CompressedOops::end()) :
+ p2i((address)G1CollectedHeap::heap()->reserved().end()));
+ }
copy_objects();
CDSHeapVerifier::verify();
diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp
index 9bb85db0fe9d2..01610ebe64e15 100644
--- a/src/hotspot/share/cds/heapShared.hpp
+++ b/src/hotspot/share/cds/heapShared.hpp
@@ -143,13 +143,13 @@ class HeapShared: AllStatic {
friend class VerifySharedOopClosure;
public:
- // Can this VM write a heap region into the CDS archive? Currently only G1+compressed{oops,cp}
+ // Can this VM write a heap region into the CDS archive? Currently only {G1|Parallel|Serial}+compressed_cp
static bool can_write() {
CDS_JAVA_HEAP_ONLY(
if (_disable_writing) {
return false;
}
- return (UseG1GC && UseCompressedClassPointers);
+ return (UseG1GC || UseParallelGC || UseSerialGC) && UseCompressedClassPointers;
)
NOT_CDS_JAVA_HEAP(return false;)
}
diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp
index 60fed287df594..c8e95149b7c1a 100644
--- a/src/hotspot/share/classfile/classFileParser.cpp
+++ b/src/hotspot/share/classfile/classFileParser.cpp
@@ -1150,30 +1150,40 @@ static void parse_annotations(const ConstantPool* const cp,
if (AnnotationCollector::_unknown == id) continue;
coll->set_annotation(id);
if (AnnotationCollector::_java_lang_Deprecated == id) {
- assert(count <= 2, "change this if more element-value pairs are added to the @Deprecated annotation");
- // @Deprecated can specify forRemoval=true
+ // @Deprecated can specify forRemoval=true, which we need
+ // to record for JFR to use. If the annotation is not well-formed
+ // then we may not be able to determine that.
const u1* offset = abase + member_off;
- for (int i = 0; i < count; ++i) {
+ // There are only 2 members in @Deprecated.
+ int n_members = MIN2(count, 2);
+ for (int i = 0; i < n_members; ++i) {
int member_index = Bytes::get_Java_u2((address)offset);
offset += 2;
member = check_symbol_at(cp, member_index);
- if (member == vmSymbols::since()) {
- assert(*((address)offset) == s_tag_val, "invariant");
+ if (member == vmSymbols::since() &&
+ (*((address)offset) == s_tag_val)) {
+ // Found `since` first so skip over it
offset += 3;
- continue;
}
- if (member == vmSymbols::for_removal()) {
- assert(*((address)offset) == b_tag_val, "invariant");
+ else if (member == vmSymbols::for_removal() &&
+ (*((address)offset) == b_tag_val)) {
const u2 boolean_value_index = Bytes::get_Java_u2((address)offset + 1);
- if (cp->int_at(boolean_value_index) == 1) {
+ // No guarantee the entry is valid so check it refers to an int in the CP.
+ if (cp->is_within_bounds(boolean_value_index) &&
+ cp->tag_at(boolean_value_index).is_int() &&
+ cp->int_at(boolean_value_index) == 1) {
// forRemoval == true
coll->set_annotation(AnnotationCollector::_java_lang_Deprecated_for_removal);
}
+ break; // no need to check further
+ }
+ else {
+ // This @Deprecated annotation is malformed so we don't try to
+ // determine whether forRemoval is set.
break;
}
-
}
- continue;
+ continue; // proceed to next annotation
}
if (AnnotationCollector::_jdk_internal_vm_annotation_Contended == id) {
@@ -1194,11 +1204,21 @@ static void parse_annotations(const ConstantPool* const cp,
&& s_tag_val == *(abase + tag_off)
&& member == vmSymbols::value_name()) {
group_index = Bytes::get_Java_u2((address)abase + s_con_off);
- if (cp->symbol_at(group_index)->utf8_length() == 0) {
- group_index = 0; // default contended group
+ // No guarantee the group_index is valid so check it refers to a
+ // symbol in the CP.
+ if (cp->is_within_bounds(group_index) &&
+ cp->tag_at(group_index).is_utf8()) {
+ // Seems valid, so check for empty string and reset
+ if (cp->symbol_at(group_index)->utf8_length() == 0) {
+ group_index = 0; // default contended group
+ }
+ } else {
+ // Not valid so use the default
+ group_index = 0;
}
}
coll->set_contended_group(group_index);
+ continue; // proceed to next annotation
}
}
}
diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp
index b9a559cf9779f..bcddddc0c7c78 100644
--- a/src/hotspot/share/classfile/systemDictionary.cpp
+++ b/src/hotspot/share/classfile/systemDictionary.cpp
@@ -1149,10 +1149,12 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik,
Symbol* class_name = ik->name();
if (!is_shared_class_visible(class_name, ik, pkg_entry, class_loader)) {
+ ik->set_shared_loading_failed();
return nullptr;
}
if (!check_shared_class_super_types(ik, class_loader, protection_domain, THREAD)) {
+ ik->set_shared_loading_failed();
return nullptr;
}
diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp
index ee50aa38dd0cf..04980291716c7 100644
--- a/src/hotspot/share/classfile/systemDictionary.hpp
+++ b/src/hotspot/share/classfile/systemDictionary.hpp
@@ -293,13 +293,6 @@ class SystemDictionary : AllStatic {
const char* message);
static const char* find_nest_host_error(const constantPoolHandle& pool, int which);
-protected:
- static InstanceKlass* _well_known_klasses[];
-
-private:
- // table of box klasses (int_klass, etc.)
- static InstanceKlass* _box_klasses[T_VOID+1];
-
static OopHandle _java_system_loader;
static OopHandle _java_platform_loader;
diff --git a/src/hotspot/share/classfile/vmClasses.cpp b/src/hotspot/share/classfile/vmClasses.cpp
index 0b9b437c67b78..b62d699dfe20e 100644
--- a/src/hotspot/share/classfile/vmClasses.cpp
+++ b/src/hotspot/share/classfile/vmClasses.cpp
@@ -45,14 +45,6 @@ InstanceKlass* vmClasses::_klasses[static_cast(vmClassID::LIMIT)]
= { nullptr /*, nullptr...*/ };
InstanceKlass* vmClasses::_box_klasses[T_VOID+1] = { nullptr /*, nullptr...*/ };
-
-// CDS: scan and relocate all classes referenced by _klasses[].
-void vmClasses::metaspace_pointers_do(MetaspaceClosure* it) {
- for (auto id : EnumRange{}) {
- it->push(klass_addr_at(id));
- }
-}
-
bool vmClasses::is_loaded(InstanceKlass* klass) {
return klass != nullptr && klass->is_loaded();
}
@@ -205,8 +197,6 @@ void vmClasses::resolve_all(TRAPS) {
_box_klasses[T_SHORT] = vmClasses::Short_klass();
_box_klasses[T_INT] = vmClasses::Integer_klass();
_box_klasses[T_LONG] = vmClasses::Long_klass();
- //_box_klasses[T_OBJECT] = vmClasses::object_klass();
- //_box_klasses[T_ARRAY] = vmClasses::object_klass();
#ifdef ASSERT
if (CDSConfig::is_using_archive()) {
diff --git a/src/hotspot/share/classfile/vmClasses.hpp b/src/hotspot/share/classfile/vmClasses.hpp
index f2b8c5666eeb1..4fa078c50cd80 100644
--- a/src/hotspot/share/classfile/vmClasses.hpp
+++ b/src/hotspot/share/classfile/vmClasses.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -32,7 +32,6 @@
class ClassLoaderData;
class InstanceKlass;
-class MetaspaceClosure;
class vmClasses : AllStatic {
friend class VMStructs;
@@ -95,7 +94,6 @@ class vmClasses : AllStatic {
return &_klasses[as_int(id)];
}
- static void metaspace_pointers_do(MetaspaceClosure* it);
static void resolve_all(TRAPS);
static BasicType box_klass_type(Klass* k); // inverse of box_klass
diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp
index b470eb9b8380d..5e352e42efbc1 100644
--- a/src/hotspot/share/classfile/vmIntrinsics.cpp
+++ b/src/hotspot/share/classfile/vmIntrinsics.cpp
@@ -90,6 +90,7 @@ bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) {
case vmIntrinsics::_dsin:
case vmIntrinsics::_dcos:
case vmIntrinsics::_dtan:
+ case vmIntrinsics::_dtanh:
case vmIntrinsics::_dlog:
case vmIntrinsics::_dlog10:
case vmIntrinsics::_dexp:
@@ -141,6 +142,7 @@ bool vmIntrinsics::can_trap(vmIntrinsics::ID id) {
case vmIntrinsics::_dsin:
case vmIntrinsics::_dcos:
case vmIntrinsics::_dtan:
+ case vmIntrinsics::_dtanh:
case vmIntrinsics::_dlog:
case vmIntrinsics::_dlog10:
case vmIntrinsics::_dexp:
@@ -288,6 +290,7 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) {
case vmIntrinsics::_dsin:
case vmIntrinsics::_dcos:
case vmIntrinsics::_dtan:
+ case vmIntrinsics::_dtanh:
case vmIntrinsics::_dlog:
case vmIntrinsics::_dexp:
case vmIntrinsics::_dpow:
diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp
index 4b772c171d5a6..af1c2b31a9809 100644
--- a/src/hotspot/share/classfile/vmIntrinsics.hpp
+++ b/src/hotspot/share/classfile/vmIntrinsics.hpp
@@ -135,7 +135,7 @@ class methodHandle;
do_name(log_name,"log") do_name(log10_name,"log10") do_name(pow_name,"pow") \
do_name(exp_name,"exp") do_name(min_name,"min") do_name(max_name,"max") \
do_name(floor_name, "floor") do_name(ceil_name, "ceil") do_name(rint_name, "rint") \
- do_name(round_name, "round") \
+ do_name(round_name, "round") do_name(tanh_name,"tanh") \
\
do_name(addExact_name,"addExact") \
do_name(decrementExact_name,"decrementExact") \
@@ -161,6 +161,7 @@ class methodHandle;
do_intrinsic(_dcos, java_lang_Math, cos_name, double_double_signature, F_S) \
do_intrinsic(_dtan, java_lang_Math, tan_name, double_double_signature, F_S) \
do_intrinsic(_datan2, java_lang_Math, atan2_name, double2_double_signature, F_S) \
+ do_intrinsic(_dtanh, java_lang_Math, tanh_name, double_double_signature, F_S) \
do_intrinsic(_dsqrt, java_lang_Math, sqrt_name, double_double_signature, F_S) \
do_intrinsic(_dlog, java_lang_Math, log_name, double_double_signature, F_S) \
do_intrinsic(_dlog10, java_lang_Math, log10_name, double_double_signature, F_S) \
diff --git a/src/hotspot/share/code/compiledIC.cpp b/src/hotspot/share/code/compiledIC.cpp
index 079c8199b1870..f142e306a6b02 100644
--- a/src/hotspot/share/code/compiledIC.cpp
+++ b/src/hotspot/share/code/compiledIC.cpp
@@ -83,6 +83,7 @@ void CompiledICData::initialize(CallInfo* call_info, Klass* receiver_klass) {
_speculated_klass = (uintptr_t)receiver_klass;
}
if (call_info->call_kind() == CallInfo::itable_call) {
+ assert(call_info->resolved_method() != nullptr, "virtual or interface method must be found");
_itable_defc_klass = call_info->resolved_method()->method_holder();
_itable_refc_klass = call_info->resolved_klass();
}
@@ -238,6 +239,7 @@ void CompiledIC::set_to_megamorphic(CallInfo* call_info) {
return;
}
#ifdef ASSERT
+ assert(call_info->resolved_method() != nullptr, "virtual or interface method must be found");
int index = call_info->resolved_method()->itable_index();
assert(index == itable_index, "CallInfo pre-computes this");
InstanceKlass* k = call_info->resolved_method()->method_holder();
@@ -254,6 +256,7 @@ void CompiledIC::set_to_megamorphic(CallInfo* call_info) {
}
}
+ assert(call_info->selected_method() != nullptr, "virtual or interface method must be found");
log_trace(inlinecache)("IC@" INTPTR_FORMAT ": to megamorphic %s entry: " INTPTR_FORMAT,
p2i(_call->instruction_address()), call_info->selected_method()->print_value_string(), p2i(entry));
diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp
index 1cfd6fca08a6f..3f7fefd8a07a6 100644
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp
@@ -87,8 +87,6 @@ class G1ParScanThreadState : public CHeapObj {
// Indicates whether in the last generation (old) there is no more space
// available for allocation.
bool _old_gen_is_full;
- // Size (in elements) of a partial objArray task chunk.
- size_t _partial_objarray_chunk_size;
PartialArrayStateAllocator* _partial_array_state_allocator;
PartialArrayTaskStepper _partial_array_stepper;
StringDedup::Requests _string_dedup_requests;
diff --git a/src/hotspot/share/gc/shared/oopStorage.cpp b/src/hotspot/share/gc/shared/oopStorage.cpp
index 6c5e57c947952..568888ac7d97e 100644
--- a/src/hotspot/share/gc/shared/oopStorage.cpp
+++ b/src/hotspot/share/gc/shared/oopStorage.cpp
@@ -1135,6 +1135,26 @@ void OopStorage::BasicParState::report_num_dead() const {
const char* OopStorage::name() const { return _name; }
+bool OopStorage::print_containing(const oop* addr, outputStream* st) {
+ if (addr != nullptr) {
+ Block* block = find_block_or_null(addr);
+ if (block != nullptr && block->print_containing(addr, st)) {
+ st->print(" in oop storage \"%s\"", name());
+ return true;
+ }
+ }
+ return false;
+}
+
+bool OopStorage::Block::print_containing(const oop* addr, outputStream* st) {
+ if (contains(addr)) {
+ st->print(PTR_FORMAT " is a pointer %u/%zu into block %zu",
+ p2i(addr), get_index(addr), ARRAY_SIZE(_data), _active_index);
+ return true;
+ }
+ return false;
+}
+
#ifndef PRODUCT
void OopStorage::print_on(outputStream* st) const {
diff --git a/src/hotspot/share/gc/shared/oopStorage.hpp b/src/hotspot/share/gc/shared/oopStorage.hpp
index f78746fc14a27..96cc5a23d6a91 100644
--- a/src/hotspot/share/gc/shared/oopStorage.hpp
+++ b/src/hotspot/share/gc/shared/oopStorage.hpp
@@ -213,6 +213,7 @@ class OopStorage : public CHeapObjBase {
// Debugging and logging support.
const char* name() const;
void print_on(outputStream* st) const PRODUCT_RETURN;
+ bool print_containing(const oop* addr, outputStream* st);
// Provides access to storage internals, for unit testing.
// Declare, but not define, the public class OopStorage::TestAccess.
diff --git a/src/hotspot/share/gc/shared/oopStorage.inline.hpp b/src/hotspot/share/gc/shared/oopStorage.inline.hpp
index ce78e507efc12..545da0be0a76e 100644
--- a/src/hotspot/share/gc/shared/oopStorage.inline.hpp
+++ b/src/hotspot/share/gc/shared/oopStorage.inline.hpp
@@ -196,6 +196,8 @@ class OopStorage::Block /* No base class, to avoid messing up alignment. */ {
template bool iterate(F f);
template bool iterate(F f) const;
+
+ bool print_containing(const oop* addr, outputStream* st);
}; // class Block
inline OopStorage::Block* OopStorage::AllocationList::head() {
diff --git a/src/hotspot/share/gc/shared/oopStorageSet.cpp b/src/hotspot/share/gc/shared/oopStorageSet.cpp
index d061fc7763868..c6947590d96fb 100644
--- a/src/hotspot/share/gc/shared/oopStorageSet.cpp
+++ b/src/hotspot/share/gc/shared/oopStorageSet.cpp
@@ -82,6 +82,23 @@ template OopStorage* OopStorageSet::get_storage(StrongId);
template OopStorage* OopStorageSet::get_storage(WeakId);
template OopStorage* OopStorageSet::get_storage(Id);
+bool OopStorageSet::print_containing(const void* addr, outputStream* st) {
+ if (addr != nullptr) {
+ const void* aligned_addr = align_down(addr, alignof(oop));
+ for (OopStorage* storage : Range()) {
+ if (storage->print_containing((oop*) aligned_addr, st)) {
+ if (aligned_addr != addr) {
+ st->print_cr(" (unaligned)");
+ } else {
+ st->cr();
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
#ifdef ASSERT
void OopStorageSet::verify_initialized(uint index) {
diff --git a/src/hotspot/share/gc/shared/oopStorageSet.hpp b/src/hotspot/share/gc/shared/oopStorageSet.hpp
index 273a769dd59d4..867172c41ad74 100644
--- a/src/hotspot/share/gc/shared/oopStorageSet.hpp
+++ b/src/hotspot/share/gc/shared/oopStorageSet.hpp
@@ -26,6 +26,7 @@
#define SHARE_GC_SHARED_OOPSTORAGESET_HPP
#include "nmt/memTag.hpp"
+#include "oops/oop.hpp"
#include "utilities/debug.hpp"
#include "utilities/enumIterator.hpp"
#include "utilities/globalDefinitions.hpp"
@@ -89,6 +90,8 @@ class OopStorageSet : public AllStatic {
template
static void strong_oops_do(Closure* cl);
+ // Debugging: print location info, if in storage.
+ static bool print_containing(const void* addr, outputStream* st);
};
ENUMERATOR_VALUE_RANGE(OopStorageSet::StrongId,
diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp
index 368d76696058c..71174d11a6214 100644
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp
@@ -271,6 +271,11 @@ bool ShenandoahBarrierSetC2::is_shenandoah_wb_pre_call(Node* call) {
call->as_CallLeaf()->entry_point() == CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry);
}
+bool ShenandoahBarrierSetC2::is_shenandoah_clone_call(Node* call) {
+ return call->is_CallLeaf() &&
+ call->as_CallLeaf()->entry_point() == CAST_FROM_FN_PTR(address, ShenandoahRuntime::shenandoah_clone_barrier);
+}
+
bool ShenandoahBarrierSetC2::is_shenandoah_lrb_call(Node* call) {
if (!call->is_CallLeaf()) {
return false;
@@ -675,20 +680,10 @@ bool ShenandoahBarrierSetC2::is_gc_pre_barrier_node(Node* node) const {
return is_shenandoah_wb_pre_call(node);
}
-// Support for GC barriers emitted during parsing
bool ShenandoahBarrierSetC2::is_gc_barrier_node(Node* node) const {
- if (node->Opcode() == Op_ShenandoahLoadReferenceBarrier) return true;
- if (node->Opcode() != Op_CallLeaf && node->Opcode() != Op_CallLeafNoFP) {
- return false;
- }
- CallLeafNode *call = node->as_CallLeaf();
- if (call->_name == nullptr) {
- return false;
- }
-
- return strcmp(call->_name, "shenandoah_clone_barrier") == 0 ||
- strcmp(call->_name, "shenandoah_cas_obj") == 0 ||
- strcmp(call->_name, "shenandoah_wb_pre") == 0;
+ return is_shenandoah_lrb_call(node) ||
+ is_shenandoah_wb_pre_call(node) ||
+ is_shenandoah_clone_call(node);
}
Node* ShenandoahBarrierSetC2::step_over_gc_barrier(Node* c) const {
diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp
index 4619b217e96c6..cbfacea31ab7a 100644
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp
@@ -85,6 +85,7 @@ class ShenandoahBarrierSetC2 : public BarrierSetC2 {
static ShenandoahBarrierSetC2* bsc2();
static bool is_shenandoah_wb_pre_call(Node* call);
+ static bool is_shenandoah_clone_call(Node* call);
static bool is_shenandoah_lrb_call(Node* call);
static bool is_shenandoah_marking_if(PhaseValues* phase, Node* n);
static bool is_shenandoah_state_load(Node* n);
diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp
index 0a51f74299545..7526f895f2f7f 100644
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp
@@ -414,7 +414,7 @@ void ShenandoahBarrierC2Support::verify(RootNode* root) {
"cipherBlockChaining_decryptAESCrypt",
{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad },
{ TypeFunc::Parms+3, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone} },
- "shenandoah_clone_barrier",
+ "shenandoah_clone",
{ { TypeFunc::Parms, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone},
{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },
"ghash_processBlocks",
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp
index 6ed75a9d96106..75cdb99e177d1 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp
@@ -225,8 +225,7 @@ void ShenandoahConcurrentMark::finish_mark() {
assert(Thread::current()->is_VM_thread(), "Must by VM Thread");
finish_mark_work();
assert(task_queues()->is_empty(), "Should be empty");
- TASKQUEUE_STATS_ONLY(task_queues()->print_taskqueue_stats());
- TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
+ TASKQUEUE_STATS_ONLY(task_queues()->print_and_reset_taskqueue_stats(""));
ShenandoahHeap* const heap = ShenandoahHeap::heap();
heap->set_concurrent_mark_in_progress(false);
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
index 95a70de5790e9..8a4ef63b8e38b 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
@@ -371,6 +371,16 @@ void ShenandoahControlThread::request_gc(GCCause::Cause cause) {
}
void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
+ // For normal requested GCs (System.gc) we want to block the caller. However,
+ // for whitebox requested GC, we want to initiate the GC and return immediately.
+ // The whitebox caller thread will arrange for itself to wait until the GC notifies
+ // it that has reached the requested breakpoint (phase in the GC).
+ if (cause == GCCause::_wb_breakpoint) {
+ _requested_gc_cause = cause;
+ _gc_requested.set();
+ return;
+ }
+
// Make sure we have at least one complete GC cycle before unblocking
// from the explicit GC request.
//
@@ -390,9 +400,7 @@ void ShenandoahControlThread::handle_requested_gc(GCCause::Cause cause) {
_requested_gc_cause = cause;
_gc_requested.set();
- if (cause != GCCause::_wb_breakpoint) {
- ml.wait();
- }
+ ml.wait();
current_gc_id = get_gc_id();
}
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp
index 05cd8ef66b9d1..9a30b1fed8724 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp
@@ -133,8 +133,7 @@ void ShenandoahSTWMark::mark() {
ShenandoahCodeRoots::disarm_nmethods();
assert(task_queues()->is_empty(), "Should be empty");
- TASKQUEUE_STATS_ONLY(task_queues()->print_taskqueue_stats());
- TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
+ TASKQUEUE_STATS_ONLY(task_queues()->print_and_reset_taskqueue_stats(""));
}
void ShenandoahSTWMark::mark_roots(uint worker_id) {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.cpp b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.cpp
index 3cddc0c6c0a83..eb185c197bd5d 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.cpp
@@ -51,45 +51,6 @@ bool ShenandoahObjToScanQueueSet::is_empty() {
return true;
}
-#if TASKQUEUE_STATS
-void ShenandoahObjToScanQueueSet::print_taskqueue_stats_hdr(outputStream* const st) {
- st->print_raw_cr("GC Task Stats");
- st->print_raw("thr "); TaskQueueStats::print_header(1, st); st->cr();
- st->print_raw("--- "); TaskQueueStats::print_header(2, st); st->cr();
-}
-
-void ShenandoahObjToScanQueueSet::print_taskqueue_stats() const {
- if (!log_develop_is_enabled(Trace, gc, task, stats)) {
- return;
- }
- Log(gc, task, stats) log;
- ResourceMark rm;
- LogStream ls(log.trace());
- outputStream* st = &ls;
- print_taskqueue_stats_hdr(st);
-
- ShenandoahObjToScanQueueSet* queues = const_cast(this);
- TaskQueueStats totals;
- const uint n = size();
- for (uint i = 0; i < n; ++i) {
- st->print(UINT32_FORMAT_W(3), i);
- queues->queue(i)->stats.print(st);
- st->cr();
- totals += queues->queue(i)->stats;
- }
- st->print("tot "); totals.print(st); st->cr();
- DEBUG_ONLY(totals.verify());
-
-}
-
-void ShenandoahObjToScanQueueSet::reset_taskqueue_stats() {
- const uint n = size();
- for (uint i = 0; i < n; ++i) {
- queue(i)->stats.reset();
- }
-}
-#endif // TASKQUEUE_STATS
-
bool ShenandoahTerminatorTerminator::should_exit_termination() {
return _heap->cancelled_gc();
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp
index 2b160a2938794..10887ad8c19d6 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp
@@ -355,12 +355,6 @@ class ShenandoahObjToScanQueueSet: public ParallelClaimableQueueSet
+template
class ZArenaHashtable : public ResourceObj {
class ZArenaHashtableEntry : public ResourceObj {
public:
@@ -55,10 +55,10 @@ class ZArenaHashtable : public ResourceObj {
V _value;
};
- static const size_t _table_mask = _table_size - 1;
+ static const size_t TableMask = TableSize - 1;
Arena* _arena;
- ZArenaHashtableEntry* _table[_table_size];
+ ZArenaHashtableEntry* _table[TableSize];
public:
class Iterator {
@@ -84,7 +84,7 @@ class ZArenaHashtable : public ResourceObj {
if (_current_entry != nullptr) {
_current_entry = _current_entry->_next;
}
- while (_current_entry == nullptr && ++_current_index < _table_size) {
+ while (_current_entry == nullptr && ++_current_index < TableSize) {
_current_entry = _table->_table[_current_index];
}
}
@@ -100,12 +100,12 @@ class ZArenaHashtable : public ResourceObj {
ZArenaHashtableEntry* entry = new (_arena) ZArenaHashtableEntry();
entry->_key = key;
entry->_value = value;
- entry->_next = _table[key & _table_mask];
- _table[key & _table_mask] = entry;
+ entry->_next = _table[key & TableMask];
+ _table[key & TableMask] = entry;
}
V* get(K key) const {
- for (ZArenaHashtableEntry* e = _table[key & _table_mask]; e != nullptr; e = e->_next) {
+ for (ZArenaHashtableEntry* e = _table[key & TableMask]; e != nullptr; e = e->_next) {
if (e->_key == key) {
return &(e->_value);
}
diff --git a/src/hotspot/share/gc/z/zBarrierSet.hpp b/src/hotspot/share/gc/z/zBarrierSet.hpp
index bf233df683afb..9c20211e2285d 100644
--- a/src/hotspot/share/gc/z/zBarrierSet.hpp
+++ b/src/hotspot/share/gc/z/zBarrierSet.hpp
@@ -155,7 +155,7 @@ class ZBarrierSet : public BarrierSet {
};
template<> struct BarrierSet::GetName {
- static const BarrierSet::Name value = BarrierSet::ZBarrierSet;
+ static const BarrierSet::Name Value = BarrierSet::ZBarrierSet;
};
template<> struct BarrierSet::GetType {
diff --git a/src/hotspot/share/gc/z/zDirector.cpp b/src/hotspot/share/gc/z/zDirector.cpp
index 8901a9fbc6500..481525c425af0 100644
--- a/src/hotspot/share/gc/z/zDirector.cpp
+++ b/src/hotspot/share/gc/z/zDirector.cpp
@@ -839,7 +839,7 @@ void ZDirector::evaluate_rules() {
}
bool ZDirector::wait_for_tick() {
- const uint64_t interval_ms = MILLIUNITS / decision_hz;
+ const uint64_t interval_ms = MILLIUNITS / DecisionHz;
ZLocker locker(&_monitor);
diff --git a/src/hotspot/share/gc/z/zDirector.hpp b/src/hotspot/share/gc/z/zDirector.hpp
index 73c556a2fbd46..929ec6c2c566b 100644
--- a/src/hotspot/share/gc/z/zDirector.hpp
+++ b/src/hotspot/share/gc/z/zDirector.hpp
@@ -29,7 +29,7 @@
class ZDirector : public ZThread {
private:
- static const uint64_t decision_hz = 100;
+ static const uint64_t DecisionHz = 100;
static ZDirector* _director;
ZConditionLock _monitor;
diff --git a/src/hotspot/share/gc/z/zHeap.cpp b/src/hotspot/share/gc/z/zHeap.cpp
index 21ff703796219..dc5f1e3d21d57 100644
--- a/src/hotspot/share/gc/z/zHeap.cpp
+++ b/src/hotspot/share/gc/z/zHeap.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -248,8 +248,7 @@ void ZHeap::free_page(ZPage* page) {
_page_table.remove(page);
if (page->is_old()) {
- page->verify_remset_cleared_current();
- page->verify_remset_cleared_previous();
+ page->remset_delete();
}
// Free page
@@ -261,12 +260,10 @@ size_t ZHeap::free_empty_pages(const ZArray* pages) {
// Remove page table entries
ZArrayIterator iter(pages);
for (ZPage* page; iter.next(&page);) {
+ _page_table.remove(page);
if (page->is_old()) {
- // The remset of pages should be clean when installed into the page
- // cache.
- page->remset_clear();
+ page->remset_delete();
}
- _page_table.remove(page);
freed += page->size();
}
diff --git a/src/hotspot/share/gc/z/zLiveMap.cpp b/src/hotspot/share/gc/z/zLiveMap.cpp
index 4123620f8b7e0..715ebc6291724 100644
--- a/src/hotspot/share/gc/z/zLiveMap.cpp
+++ b/src/hotspot/share/gc/z/zLiveMap.cpp
@@ -35,9 +35,9 @@
static const ZStatCounter ZCounterMarkSeqNumResetContention("Contention", "Mark SeqNum Reset Contention", ZStatUnitOpsPerSecond);
static const ZStatCounter ZCounterMarkSegmentResetContention("Contention", "Mark Segment Reset Contention", ZStatUnitOpsPerSecond);
-static size_t bitmap_size(uint32_t size, size_t nsegments) {
+static size_t bitmap_size(uint32_t size, size_t NumSegments) {
// We need at least one bit per segment
- return MAX2(size, nsegments) * 2;
+ return MAX2(size, NumSegments) * 2;
}
ZLiveMap::ZLiveMap(uint32_t size)
@@ -46,7 +46,7 @@ ZLiveMap::ZLiveMap(uint32_t size)
_live_bytes(0),
_segment_live_bits(0),
_segment_claim_bits(0),
- _bitmap(bitmap_size(size, nsegments)),
+ _bitmap(bitmap_size(size, NumSegments)),
_segment_shift(log2i_exact(segment_size())) {}
void ZLiveMap::reset(ZGenerationId id) {
@@ -127,7 +127,7 @@ void ZLiveMap::reset_segment(BitMap::idx_t segment) {
}
void ZLiveMap::resize(uint32_t size) {
- const size_t new_bitmap_size = bitmap_size(size, nsegments);
+ const size_t new_bitmap_size = bitmap_size(size, NumSegments);
if (_bitmap.size() != new_bitmap_size) {
_bitmap.reinitialize(new_bitmap_size, false /* clear */);
_segment_shift = log2i_exact(segment_size());
diff --git a/src/hotspot/share/gc/z/zLiveMap.hpp b/src/hotspot/share/gc/z/zLiveMap.hpp
index f8b16d06dc52c..7c18e1db06096 100644
--- a/src/hotspot/share/gc/z/zLiveMap.hpp
+++ b/src/hotspot/share/gc/z/zLiveMap.hpp
@@ -35,7 +35,7 @@ class ZLiveMap {
friend class ZLiveMapTest;
private:
- static const size_t nsegments = 64;
+ static const size_t NumSegments = 64;
volatile uint32_t _seqnum;
volatile uint32_t _live_objects;
diff --git a/src/hotspot/share/gc/z/zLiveMap.inline.hpp b/src/hotspot/share/gc/z/zLiveMap.inline.hpp
index 28390b72a89ca..a9382522480c0 100644
--- a/src/hotspot/share/gc/z/zLiveMap.inline.hpp
+++ b/src/hotspot/share/gc/z/zLiveMap.inline.hpp
@@ -52,19 +52,19 @@ inline size_t ZLiveMap::live_bytes() const {
}
inline const BitMapView ZLiveMap::segment_live_bits() const {
- return BitMapView(const_cast(&_segment_live_bits), nsegments);
+ return BitMapView(const_cast(&_segment_live_bits), NumSegments);
}
inline const BitMapView ZLiveMap::segment_claim_bits() const {
- return BitMapView(const_cast(&_segment_claim_bits), nsegments);
+ return BitMapView(const_cast(&_segment_claim_bits), NumSegments);
}
inline BitMapView ZLiveMap::segment_live_bits() {
- return BitMapView(&_segment_live_bits, nsegments);
+ return BitMapView(&_segment_live_bits, NumSegments);
}
inline BitMapView ZLiveMap::segment_claim_bits() {
- return BitMapView(&_segment_claim_bits, nsegments);
+ return BitMapView(&_segment_claim_bits, NumSegments);
}
inline bool ZLiveMap::is_segment_live(BitMap::idx_t segment) const {
@@ -80,15 +80,15 @@ inline bool ZLiveMap::claim_segment(BitMap::idx_t segment) {
}
inline BitMap::idx_t ZLiveMap::first_live_segment() const {
- return segment_live_bits().find_first_set_bit(0, nsegments);
+ return segment_live_bits().find_first_set_bit(0, NumSegments);
}
inline BitMap::idx_t ZLiveMap::next_live_segment(BitMap::idx_t segment) const {
- return segment_live_bits().find_first_set_bit(segment + 1, nsegments);
+ return segment_live_bits().find_first_set_bit(segment + 1, NumSegments);
}
inline BitMap::idx_t ZLiveMap::segment_size() const {
- return _bitmap.size() / nsegments;
+ return _bitmap.size() / NumSegments;
}
inline BitMap::idx_t ZLiveMap::index_to_segment(BitMap::idx_t index) const {
@@ -167,7 +167,7 @@ inline void ZLiveMap::iterate(ZGenerationId id, Function function) {
return true;
};
- for (BitMap::idx_t segment = first_live_segment(); segment < nsegments; segment = next_live_segment(segment)) {
+ for (BitMap::idx_t segment = first_live_segment(); segment < NumSegments; segment = next_live_segment(segment)) {
// For each live segment
iterate_segment(segment, live_only);
}
diff --git a/src/hotspot/share/gc/z/zPage.cpp b/src/hotspot/share/gc/z/zPage.cpp
index dc40c5367c121..ff56768e9ad99 100644
--- a/src/hotspot/share/gc/z/zPage.cpp
+++ b/src/hotspot/share/gc/z/zPage.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -78,27 +78,16 @@ void ZPage::reset_seqnum() {
Atomic::store(&_seqnum_other, ZGeneration::generation(_generation_id == ZGenerationId::young ? ZGenerationId::old : ZGenerationId::young)->seqnum());
}
-void ZPage::remset_initialize() {
- // Remsets should only be initialized once and only for old pages.
+void ZPage::remset_alloc() {
+ // Remsets should only be allocated/initialized once and only for old pages.
assert(!_remembered_set.is_initialized(), "Should not be initialized");
assert(is_old(), "Only old pages need a remset");
_remembered_set.initialize(size());
}
-void ZPage::remset_initialize_or_verify_cleared() {
- assert(is_old(), "Only old pages need a remset");
-
- if (_remembered_set.is_initialized()) {
- verify_remset_cleared_current();
- verify_remset_cleared_previous();
- } else {
- remset_initialize();
- }
-}
-
-void ZPage::remset_clear() {
- _remembered_set.clear_all();
+void ZPage::remset_delete() {
+ _remembered_set.delete_all();
}
void ZPage::reset(ZPageAge age) {
@@ -123,7 +112,6 @@ void ZPage::reset_top_for_allocation() {
void ZPage::reset_type_and_size(ZPageType type) {
_type = type;
_livemap.resize(object_max_count());
- _remembered_set.resize(size());
}
ZPage* ZPage::retype(ZPageType type) {
@@ -216,10 +204,6 @@ void ZPage::verify_remset_cleared_previous() const {
}
}
-void ZPage::clear_remset_current() {
- _remembered_set.clear_current();
-}
-
void ZPage::clear_remset_previous() {
_remembered_set.clear_previous();
}
diff --git a/src/hotspot/share/gc/z/zPage.hpp b/src/hotspot/share/gc/z/zPage.hpp
index 42e14f904bc77..9b6c155f77d9f 100644
--- a/src/hotspot/share/gc/z/zPage.hpp
+++ b/src/hotspot/share/gc/z/zPage.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -155,9 +155,8 @@ class ZPage : public CHeapObj {
void clear_remset_range_non_par_current(uintptr_t l_offset, size_t size);
void swap_remset_bitmaps();
- void remset_initialize();
- void remset_initialize_or_verify_cleared();
- void remset_clear();
+ void remset_alloc();
+ void remset_delete();
ZBitMap::ReverseIterator remset_reverse_iterator_previous();
BitMap::Iterator remset_iterator_limited_current(uintptr_t l_offset, size_t size);
@@ -182,7 +181,6 @@ class ZPage : public CHeapObj {
void verify_remset_cleared_current() const;
void verify_remset_cleared_previous() const;
- void clear_remset_current();
void clear_remset_previous();
void* remset_current();
diff --git a/src/hotspot/share/gc/z/zPageAllocator.cpp b/src/hotspot/share/gc/z/zPageAllocator.cpp
index f5d8ae6e3d160..01200f76b519e 100644
--- a/src/hotspot/share/gc/z/zPageAllocator.cpp
+++ b/src/hotspot/share/gc/z/zPageAllocator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -733,7 +733,7 @@ ZPage* ZPageAllocator::alloc_page(ZPageType type, size_t size, ZAllocationFlags
page->reset_top_for_allocation();
page->reset_livemap();
if (age == ZPageAge::old) {
- page->remset_initialize_or_verify_cleared();
+ page->remset_alloc();
}
// Update allocation statistics. Exclude gc relocations to avoid
diff --git a/src/hotspot/share/gc/z/zReferenceProcessor.hpp b/src/hotspot/share/gc/z/zReferenceProcessor.hpp
index f8e924ed99fc1..31c789ee859e5 100644
--- a/src/hotspot/share/gc/z/zReferenceProcessor.hpp
+++ b/src/hotspot/share/gc/z/zReferenceProcessor.hpp
@@ -36,8 +36,8 @@ class ZReferenceProcessor : public ReferenceDiscoverer {
friend class ZReferenceProcessorTask;
private:
- static const size_t reference_type_count = REF_PHANTOM + 1;
- typedef size_t Counters[reference_type_count];
+ static const size_t ReferenceTypeCount = REF_PHANTOM + 1;
+ typedef size_t Counters[ReferenceTypeCount];
ZWorkers* const _workers;
ReferencePolicy* _soft_reference_policy;
diff --git a/src/hotspot/share/gc/z/zRelocate.cpp b/src/hotspot/share/gc/z/zRelocate.cpp
index 90209e4c62253..33304bcefd37f 100644
--- a/src/hotspot/share/gc/z/zRelocate.cpp
+++ b/src/hotspot/share/gc/z/zRelocate.cpp
@@ -848,7 +848,7 @@ class ZRelocateWork : public StackObj {
to_page->reset(to_age);
to_page->reset_top_for_allocation();
if (promotion) {
- to_page->remset_initialize();
+ to_page->remset_alloc();
}
// Verify that the inactive remset is clear when resetting the page for
@@ -943,35 +943,15 @@ class ZRelocateWork : public StackObj {
return ZGeneration::old()->active_remset_is_current();
}
- void clear_remset_before_reuse(ZPage* page, bool in_place) {
+ void clear_remset_before_in_place_reuse(ZPage* page) {
if (_forwarding->from_age() != ZPageAge::old) {
// No remset bits
return;
}
- if (in_place) {
- // Clear 'previous' remset bits. For in-place relocated pages, the previous
- // remset bits are always used, even when active_remset_is_current().
- page->clear_remset_previous();
-
- return;
- }
-
- // Normal relocate
-
- // Clear active remset bits
- if (active_remset_is_current()) {
- page->clear_remset_current();
- } else {
- page->clear_remset_previous();
- }
-
- // Verify that inactive remset bits are all cleared
- if (active_remset_is_current()) {
- page->verify_remset_cleared_previous();
- } else {
- page->verify_remset_cleared_current();
- }
+ // Clear 'previous' remset bits. For in-place relocated pages, the previous
+ // remset bits are always used, even when active_remset_is_current().
+ page->clear_remset_previous();
}
void finish_in_place_relocation() {
@@ -1017,7 +997,7 @@ class ZRelocateWork : public StackObj {
ZPage* const page = _forwarding->detach_page();
// Ensure that previous remset bits are cleared
- clear_remset_before_reuse(page, true /* in_place */);
+ clear_remset_before_in_place_reuse(page);
page->log_msg(" (relocate page done in-place)");
@@ -1029,11 +1009,6 @@ class ZRelocateWork : public StackObj {
// Wait for all other threads to call release_page
ZPage* const page = _forwarding->detach_page();
- // Ensure that all remset bits are cleared
- // Note: cleared after detach_page, when we know that
- // the young generation isn't scanning the remset.
- clear_remset_before_reuse(page, false /* in_place */);
-
page->log_msg(" (relocate page done normal)");
// Free page
@@ -1292,7 +1267,7 @@ class ZFlipAgePagesTask : public ZTask {
new_page->reset(to_age);
new_page->reset_livemap();
if (promotion) {
- new_page->remset_initialize();
+ new_page->remset_alloc();
}
if (promotion) {
diff --git a/src/hotspot/share/gc/z/zRememberedSet.cpp b/src/hotspot/share/gc/z/zRememberedSet.cpp
index ed1dcfaf14d55..f605401648dfb 100644
--- a/src/hotspot/share/gc/z/zRememberedSet.cpp
+++ b/src/hotspot/share/gc/z/zRememberedSet.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -55,18 +55,10 @@ void ZRememberedSet::initialize(size_t page_size) {
_bitmap[1].initialize(size_in_bits, true /* clear */);
}
-void ZRememberedSet::resize(size_t page_size) {
- // The bitmaps only need to be resized if remset has been
- // initialized, and hence the bitmaps have been initialized.
- if (is_initialized()) {
- const BitMap::idx_t size_in_bits = to_bit_size(page_size);
-
- // The bitmaps need to be cleared when free, but since this function is
- // only used for shrinking the clear argument is correct but not crucial.
- assert(size_in_bits <= _bitmap[0].size(), "Only used for shrinking");
- _bitmap[0].resize(size_in_bits, true /* clear */);
- _bitmap[1].resize(size_in_bits, true /* clear */);
- }
+void ZRememberedSet::delete_all() {
+ assert(is_initialized(), "precondition");
+ _bitmap[0].resize(0);
+ _bitmap[1].resize(0);
}
bool ZRememberedSet::is_cleared_current() const {
@@ -77,15 +69,6 @@ bool ZRememberedSet::is_cleared_previous() const {
return previous()->is_empty();
}
-void ZRememberedSet::clear_all() {
- _bitmap[0].clear_large();
- _bitmap[1].clear_large();
-}
-
-void ZRememberedSet::clear_current() {
- current()->clear_large();
-}
-
void ZRememberedSet::clear_previous() {
previous()->clear_large();
}
diff --git a/src/hotspot/share/gc/z/zRememberedSet.hpp b/src/hotspot/share/gc/z/zRememberedSet.hpp
index d18c357f0ddbe..c3c6e8bc31317 100644
--- a/src/hotspot/share/gc/z/zRememberedSet.hpp
+++ b/src/hotspot/share/gc/z/zRememberedSet.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -114,8 +114,7 @@ class ZRememberedSet {
bool is_initialized() const;
void initialize(size_t page_size);
-
- void resize(size_t page_size);
+ void delete_all();
bool at_current(uintptr_t offset) const;
bool at_previous(uintptr_t offset) const;
@@ -133,8 +132,6 @@ class ZRememberedSet {
bool is_cleared_current() const;
bool is_cleared_previous() const;
- void clear_all();
- void clear_current();
void clear_previous();
void swap_remset_bitmaps();
diff --git a/src/hotspot/share/gc/z/zStackWatermark.cpp b/src/hotspot/share/gc/z/zStackWatermark.cpp
index ead5300e9c318..0c7ec553e5c0c 100644
--- a/src/hotspot/share/gc/z/zStackWatermark.cpp
+++ b/src/hotspot/share/gc/z/zStackWatermark.cpp
@@ -130,7 +130,7 @@ void ZStackWatermark::save_old_watermark() {
} else {
// Found none too replace - push it to the top
_old_watermarks_newest++;
- assert(_old_watermarks_newest < _old_watermarks_max, "Unexpected amount of old watermarks");
+ assert(_old_watermarks_newest < OldWatermarksMax, "Unexpected amount of old watermarks");
}
// Install old watermark
diff --git a/src/hotspot/share/gc/z/zStackWatermark.hpp b/src/hotspot/share/gc/z/zStackWatermark.hpp
index fd4efeef76131..f2cf59d3b4a80 100644
--- a/src/hotspot/share/gc/z/zStackWatermark.hpp
+++ b/src/hotspot/share/gc/z/zStackWatermark.hpp
@@ -59,8 +59,8 @@ class ZStackWatermark : public StackWatermark {
private:
// Stores old watermarks, which describes the
// colors of the non-processed part of the stack.
- const static int _old_watermarks_max = 3;
- ZColorWatermark _old_watermarks[_old_watermarks_max];
+ static const int OldWatermarksMax = 3;
+ ZColorWatermark _old_watermarks[OldWatermarksMax];
int _old_watermarks_newest;
ThreadLocalAllocStats _stats;
diff --git a/src/hotspot/share/gc/z/zStat.cpp b/src/hotspot/share/gc/z/zStat.cpp
index c2a7a23c04f53..56b3590960f7c 100644
--- a/src/hotspot/share/gc/z/zStat.cpp
+++ b/src/hotspot/share/gc/z/zStat.cpp
@@ -1019,7 +1019,7 @@ ZStatMutatorAllocRateStats ZStatMutatorAllocRate::stats() {
// Stat thread
//
ZStat::ZStat()
- : _metronome(sample_hz) {
+ : _metronome(SampleHz) {
set_name("ZStat");
create_and_start();
ZStatMutatorAllocRate::initialize();
@@ -1098,11 +1098,11 @@ void ZStat::terminate() {
//
class ZStatTablePrinter {
private:
- static const size_t _buffer_size = 256;
+ static const size_t BufferSize = 256;
const size_t _column0_width;
const size_t _columnN_width;
- char _buffer[_buffer_size];
+ char _buffer[BufferSize];
public:
class ZColumn {
@@ -1119,7 +1119,7 @@ class ZStatTablePrinter {
}
size_t print(size_t position, const char* fmt, va_list va) {
- const int res = jio_vsnprintf(_buffer + position, _buffer_size - position, fmt, va);
+ const int res = jio_vsnprintf(_buffer + position, BufferSize - position, fmt, va);
if (res < 0) {
return 0;
}
diff --git a/src/hotspot/share/gc/z/zStat.hpp b/src/hotspot/share/gc/z/zStat.hpp
index d7482dbe6aaaf..d7fff6d7b8e13 100644
--- a/src/hotspot/share/gc/z/zStat.hpp
+++ b/src/hotspot/share/gc/z/zStat.hpp
@@ -384,7 +384,7 @@ class ZStatMutatorAllocRate : public AllStatic {
//
class ZStat : public ZThread {
private:
- static const uint64_t sample_hz = 1;
+ static const uint64_t SampleHz = 1;
ZMetronome _metronome;
diff --git a/src/hotspot/share/gc/z/zStoreBarrierBuffer.cpp b/src/hotspot/share/gc/z/zStoreBarrierBuffer.cpp
index c94551dc62d20..78106aad729b7 100644
--- a/src/hotspot/share/gc/z/zStoreBarrierBuffer.cpp
+++ b/src/hotspot/share/gc/z/zStoreBarrierBuffer.cpp
@@ -55,7 +55,7 @@ ZStoreBarrierBuffer::ZStoreBarrierBuffer()
_last_installed_color(),
_base_pointer_lock(),
_base_pointers(),
- _current(ZBufferStoreBarriers ? _buffer_size_bytes : 0) {}
+ _current(ZBufferStoreBarriers ? BufferSizeBytes : 0) {}
void ZStoreBarrierBuffer::initialize() {
_last_processed_color = ZPointerStoreGoodMask;
@@ -63,11 +63,11 @@ void ZStoreBarrierBuffer::initialize() {
}
void ZStoreBarrierBuffer::clear() {
- _current = _buffer_size_bytes;
+ _current = BufferSizeBytes;
}
bool ZStoreBarrierBuffer::is_empty() const {
- return _current == _buffer_size_bytes;
+ return _current == BufferSizeBytes;
}
void ZStoreBarrierBuffer::install_base_pointers_inner() {
@@ -79,7 +79,7 @@ void ZStoreBarrierBuffer::install_base_pointers_inner() {
(ZPointer::remap_bits(_last_processed_color) & ZPointerRemappedOldMask) == 0,
"Should not have double bit errors");
- for (size_t i = current(); i < _buffer_length; ++i) {
+ for (size_t i = current(); i < BufferLength; ++i) {
const ZStoreBarrierEntry& entry = _buffer[i];
volatile zpointer* const p = entry._p;
const zaddress_unsafe p_unsafe = to_zaddress_unsafe((uintptr_t)p);
@@ -229,7 +229,7 @@ void ZStoreBarrierBuffer::on_new_phase() {
// Install all base pointers for relocation
install_base_pointers();
- for (size_t i = current(); i < _buffer_length; ++i) {
+ for (size_t i = current(); i < BufferLength; ++i) {
on_new_phase_relocate(i);
on_new_phase_remember(i);
on_new_phase_mark(i);
@@ -259,7 +259,7 @@ void ZStoreBarrierBuffer::on_error(outputStream* st) {
st->print_cr(" _last_processed_color: " PTR_FORMAT, _last_processed_color);
st->print_cr(" _last_installed_color: " PTR_FORMAT, _last_installed_color);
- for (size_t i = current(); i < _buffer_length; ++i) {
+ for (size_t i = current(); i < BufferLength; ++i) {
st->print_cr(" [%2zu]: base: " PTR_FORMAT " p: " PTR_FORMAT " prev: " PTR_FORMAT,
i,
untype(_base_pointers[i]),
@@ -276,7 +276,7 @@ void ZStoreBarrierBuffer::flush() {
OnError on_error(this);
VMErrorCallbackMark mark(&on_error);
- for (size_t i = current(); i < _buffer_length; ++i) {
+ for (size_t i = current(); i < BufferLength; ++i) {
const ZStoreBarrierEntry& entry = _buffer[i];
const zaddress addr = ZBarrier::make_load_good(entry._prev);
ZBarrier::mark_and_remember(entry._p, addr);
@@ -296,7 +296,7 @@ bool ZStoreBarrierBuffer::is_in(volatile zpointer* p) {
const uintptr_t last_remap_bits = ZPointer::remap_bits(buffer->_last_processed_color) & ZPointerRemappedMask;
const bool needs_remap = last_remap_bits != ZPointerRemapped;
- for (size_t i = buffer->current(); i < _buffer_length; ++i) {
+ for (size_t i = buffer->current(); i < BufferLength; ++i) {
const ZStoreBarrierEntry& entry = buffer->_buffer[i];
volatile zpointer* entry_p = entry._p;
diff --git a/src/hotspot/share/gc/z/zStoreBarrierBuffer.hpp b/src/hotspot/share/gc/z/zStoreBarrierBuffer.hpp
index f828ffb8ab25d..f2e4a343d9c01 100644
--- a/src/hotspot/share/gc/z/zStoreBarrierBuffer.hpp
+++ b/src/hotspot/share/gc/z/zStoreBarrierBuffer.hpp
@@ -50,10 +50,10 @@ class ZStoreBarrierBuffer : public CHeapObj {
private:
// Tune ZStoreBarrierBuffer length to decrease the opportunity goto
// copy_store_at slow-path.
- static const size_t _buffer_length = 32 LOONGARCH64_ONLY(+32);
- static const size_t _buffer_size_bytes = _buffer_length * sizeof(ZStoreBarrierEntry);
+ static const size_t BufferLength = 32 LOONGARCH64_ONLY(+32);
+ static const size_t BufferSizeBytes = BufferLength * sizeof(ZStoreBarrierEntry);
- ZStoreBarrierEntry _buffer[_buffer_length];
+ ZStoreBarrierEntry _buffer[BufferLength];
// Color from previous phase this buffer was processed
uintptr_t _last_processed_color;
@@ -62,7 +62,7 @@ class ZStoreBarrierBuffer : public CHeapObj {
uintptr_t _last_installed_color;
ZLock _base_pointer_lock;
- zaddress_unsafe _base_pointers[_buffer_length];
+ zaddress_unsafe _base_pointers[BufferLength];
// sizeof(ZStoreBarrierEntry) scaled index growing downwards
size_t _current;
diff --git a/src/hotspot/share/gc/z/zValue.hpp b/src/hotspot/share/gc/z/zValue.hpp
index 29f1b707e7c6b..4953978297f52 100644
--- a/src/hotspot/share/gc/z/zValue.hpp
+++ b/src/hotspot/share/gc/z/zValue.hpp
@@ -39,7 +39,7 @@ class ZValueStorage : public AllStatic {
static uintptr_t _end;
public:
- static const size_t offset = 4 * K;
+ static const size_t Offset = 4 * K;
static uintptr_t alloc(size_t size);
};
diff --git a/src/hotspot/share/gc/z/zValue.inline.hpp b/src/hotspot/share/gc/z/zValue.inline.hpp
index 2367bac0f0aab..c2aa8bbbb4004 100644
--- a/src/hotspot/share/gc/z/zValue.inline.hpp
+++ b/src/hotspot/share/gc/z/zValue.inline.hpp
@@ -44,7 +44,7 @@ template uintptr_t ZValueStorage::_top = 0;
template
uintptr_t ZValueStorage::alloc(size_t size) {
- assert(size <= offset, "Allocation too large");
+ assert(size <= Offset, "Allocation too large");
// Allocate entry in existing memory block
const uintptr_t addr = align_up(_top, S::alignment());
@@ -56,10 +56,10 @@ uintptr_t ZValueStorage::alloc(size_t size) {
}
// Allocate new block of memory
- const size_t block_alignment = offset;
- const size_t block_size = offset * S::count();
+ const size_t block_alignment = Offset;
+ const size_t block_size = Offset * S::count();
_top = ZUtils::alloc_aligned_unfreeable(block_alignment, block_size);
- _end = _top + offset;
+ _end = _top + Offset;
// Retry allocation
return alloc(size);
@@ -119,7 +119,7 @@ inline uint32_t ZPerWorkerStorage::id() {
template
inline uintptr_t ZValue::value_addr(uint32_t value_id) const {
- return _addr + (value_id * S::offset);
+ return _addr + (value_id * S::Offset);
}
template
diff --git a/src/hotspot/share/gc/z/zVerify.cpp b/src/hotspot/share/gc/z/zVerify.cpp
index b735965e9d49b..03b50e110e4c4 100644
--- a/src/hotspot/share/gc/z/zVerify.cpp
+++ b/src/hotspot/share/gc/z/zVerify.cpp
@@ -589,7 +589,7 @@ void ZVerify::on_color_flip() {
for (JavaThreadIteratorWithHandle jtiwh; JavaThread* const jt = jtiwh.next(); ) {
const ZStoreBarrierBuffer* const buffer = ZThreadLocalData::store_barrier_buffer(jt);
- for (size_t i = buffer->current(); i < ZStoreBarrierBuffer::_buffer_length; ++i) {
+ for (size_t i = buffer->current(); i < ZStoreBarrierBuffer::BufferLength; ++i) {
volatile zpointer* const p = buffer->_buffer[i]._p;
bool created = false;
z_verify_store_barrier_buffer_table->put_if_absent(p, true, &created);
diff --git a/src/hotspot/share/interpreter/abstractInterpreter.cpp b/src/hotspot/share/interpreter/abstractInterpreter.cpp
index 2fad5ba39ef5c..9d72f9ba0edec 100644
--- a/src/hotspot/share/interpreter/abstractInterpreter.cpp
+++ b/src/hotspot/share/interpreter/abstractInterpreter.cpp
@@ -138,6 +138,7 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHan
case vmIntrinsics::_dsin: return java_lang_math_sin;
case vmIntrinsics::_dcos: return java_lang_math_cos;
case vmIntrinsics::_dtan: return java_lang_math_tan;
+ case vmIntrinsics::_dtanh: return java_lang_math_tanh;
case vmIntrinsics::_dabs: return java_lang_math_abs;
case vmIntrinsics::_dlog: return java_lang_math_log;
case vmIntrinsics::_dlog10: return java_lang_math_log10;
@@ -198,6 +199,7 @@ vmIntrinsics::ID AbstractInterpreter::method_intrinsic(MethodKind kind) {
case java_lang_math_sin : return vmIntrinsics::_dsin;
case java_lang_math_cos : return vmIntrinsics::_dcos;
case java_lang_math_tan : return vmIntrinsics::_dtan;
+ case java_lang_math_tanh : return vmIntrinsics::_dtanh;
case java_lang_math_abs : return vmIntrinsics::_dabs;
case java_lang_math_log : return vmIntrinsics::_dlog;
case java_lang_math_log10 : return vmIntrinsics::_dlog10;
@@ -309,6 +311,7 @@ void AbstractInterpreter::print_method_kind(MethodKind kind) {
case java_lang_math_sin : tty->print("java_lang_math_sin" ); break;
case java_lang_math_cos : tty->print("java_lang_math_cos" ); break;
case java_lang_math_tan : tty->print("java_lang_math_tan" ); break;
+ case java_lang_math_tanh : tty->print("java_lang_math_tanh" ); break;
case java_lang_math_abs : tty->print("java_lang_math_abs" ); break;
case java_lang_math_log : tty->print("java_lang_math_log" ); break;
case java_lang_math_log10 : tty->print("java_lang_math_log10" ); break;
diff --git a/src/hotspot/share/interpreter/abstractInterpreter.hpp b/src/hotspot/share/interpreter/abstractInterpreter.hpp
index e487b152b76ea..790706c2de3cd 100644
--- a/src/hotspot/share/interpreter/abstractInterpreter.hpp
+++ b/src/hotspot/share/interpreter/abstractInterpreter.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -72,6 +72,7 @@ class AbstractInterpreter: AllStatic {
java_lang_math_sin, // implementation of java.lang.Math.sin (x)
java_lang_math_cos, // implementation of java.lang.Math.cos (x)
java_lang_math_tan, // implementation of java.lang.Math.tan (x)
+ java_lang_math_tanh, // implementation of java.lang.Math.tanh (x)
java_lang_math_abs, // implementation of java.lang.Math.abs (x)
java_lang_math_sqrt, // implementation of java.lang.Math.sqrt (x)
java_lang_math_sqrt_strict, // implementation of java.lang.StrictMath.sqrt(x)
@@ -151,6 +152,7 @@ class AbstractInterpreter: AllStatic {
case vmIntrinsics::_dsin : // fall thru
case vmIntrinsics::_dcos : // fall thru
case vmIntrinsics::_dtan : // fall thru
+ case vmIntrinsics::_dtanh : // fall thru
case vmIntrinsics::_dabs : // fall thru
case vmIntrinsics::_dsqrt : // fall thru
case vmIntrinsics::_dsqrt_strict : // fall thru
diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp
index cadc3e8a2e802..36847580d9c63 100644
--- a/src/hotspot/share/interpreter/linkResolver.cpp
+++ b/src/hotspot/share/interpreter/linkResolver.cpp
@@ -87,7 +87,7 @@ void CallInfo::set_interface(Klass* resolved_klass,
// we should pick the vtable index from the resolved method.
// In that case, the caller must call set_virtual instead of set_interface.
assert(resolved_method->method_holder()->is_interface(), "");
- assert(itable_index == resolved_method()->itable_index(), "");
+ assert(itable_index == resolved_method->itable_index(), "");
set_common(resolved_klass, resolved_method, selected_method, CallInfo::itable_call, itable_index, CHECK);
}
@@ -1541,7 +1541,7 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result,
}
// resolve the method in the receiver class, unless it is private
- if (!is_abstract_interpretation && !resolved_method()->is_private()) {
+ if (!is_abstract_interpretation && !resolved_method->is_private()) {
// do lookup based on receiver klass
// This search must match the linktime preparation search for itable initialization
// to correctly enforce loader constraints for interface method inheritance.
@@ -1590,17 +1590,17 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result,
assert(is_abstract_interpretation || vtable_index == selected_method->vtable_index(), "sanity check");
result.set_virtual(resolved_klass, resolved_method, selected_method, vtable_index, CHECK);
} else if (resolved_method->has_itable_index()) {
- int itable_index = resolved_method()->itable_index();
+ int itable_index = resolved_method->itable_index();
log_develop_trace(itables)(" -- itable index: %d", itable_index);
result.set_interface(resolved_klass, resolved_method, selected_method, itable_index, CHECK);
} else {
int index = resolved_method->vtable_index();
log_develop_trace(itables)(" -- non itable/vtable index: %d", index);
assert(index == Method::nonvirtual_vtable_index, "Oops hit another case!");
- assert(resolved_method()->is_private() ||
- (resolved_method()->is_final() && resolved_method->method_holder() == vmClasses::Object_klass()),
+ assert(resolved_method->is_private() ||
+ (resolved_method->is_final() && resolved_method->method_holder() == vmClasses::Object_klass()),
"Should only have non-virtual invokeinterface for private or final-Object methods!");
- assert(resolved_method()->can_be_statically_bound(), "Should only have non-virtual invokeinterface for statically bound methods!");
+ assert(resolved_method->can_be_statically_bound(), "Should only have non-virtual invokeinterface for statically bound methods!");
// This sets up the nonvirtual form of "virtual" call (as needed for final and private methods)
result.set_virtual(resolved_klass, resolved_method, resolved_method, index, CHECK);
}
diff --git a/src/hotspot/share/interpreter/linkResolver.hpp b/src/hotspot/share/interpreter/linkResolver.hpp
index 340c7d412d599..69bdf56137d41 100644
--- a/src/hotspot/share/interpreter/linkResolver.hpp
+++ b/src/hotspot/share/interpreter/linkResolver.hpp
@@ -99,7 +99,6 @@ class CallInfo : public StackObj {
// Materialize a java.lang.invoke.ResolvedMethodName for this resolved_method
void set_resolved_method_name(TRAPS);
- BasicType result_type() const { return selected_method()->result_type(); }
CallKind call_kind() const { return _call_kind; }
int vtable_index() const {
// Even for interface calls the vtable index could be non-negative.
diff --git a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp
index 9cd6f5ceffbe9..3f497c3360b7e 100644
--- a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp
+++ b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -192,6 +192,7 @@ void TemplateInterpreterGenerator::generate_all() {
method_entry(java_lang_math_sin )
method_entry(java_lang_math_cos )
method_entry(java_lang_math_tan )
+ method_entry(java_lang_math_tanh )
method_entry(java_lang_math_abs )
method_entry(java_lang_math_sqrt )
method_entry(java_lang_math_sqrt_strict)
@@ -457,6 +458,7 @@ address TemplateInterpreterGenerator::generate_intrinsic_entry(AbstractInterpret
case Interpreter::java_lang_math_sin : // fall thru
case Interpreter::java_lang_math_cos : // fall thru
case Interpreter::java_lang_math_tan : // fall thru
+ case Interpreter::java_lang_math_tanh : // fall thru
case Interpreter::java_lang_math_abs : // fall thru
case Interpreter::java_lang_math_log : // fall thru
case Interpreter::java_lang_math_log10 : // fall thru
diff --git a/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp b/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp
index e08d9553c3e07..27ea1b9706719 100644
--- a/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp
+++ b/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -54,6 +54,7 @@ void ZeroInterpreterGenerator::generate_all() {
method_entry(java_lang_math_sin );
method_entry(java_lang_math_cos );
method_entry(java_lang_math_tan );
+ method_entry(java_lang_math_tanh );
method_entry(java_lang_math_abs );
method_entry(java_lang_math_sqrt );
method_entry(java_lang_math_sqrt_strict);
@@ -95,6 +96,7 @@ address ZeroInterpreterGenerator::generate_method_entry(
case Interpreter::java_lang_math_sin : // fall thru
case Interpreter::java_lang_math_cos : // fall thru
case Interpreter::java_lang_math_tan : // fall thru
+ case Interpreter::java_lang_math_tanh : // fall thru
case Interpreter::java_lang_math_abs : // fall thru
case Interpreter::java_lang_math_log : // fall thru
case Interpreter::java_lang_math_log10 : // fall thru
diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp
index fa4b1c75c0573..0773de6ddbaa0 100644
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp
@@ -116,6 +116,7 @@ class CompilerToVM {
static address dsin;
static address dcos;
static address dtan;
+ static address dtanh;
static address dexp;
static address dlog;
static address dlog10;
diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
index 26c88abec0f18..1612038008a32 100644
--- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
@@ -135,6 +135,7 @@ int CompilerToVM::Data::sizeof_ZStoreBarrierEntry = sizeof(ZStoreBarrierEntry);
address CompilerToVM::Data::dsin;
address CompilerToVM::Data::dcos;
address CompilerToVM::Data::dtan;
+address CompilerToVM::Data::dtanh;
address CompilerToVM::Data::dexp;
address CompilerToVM::Data::dlog;
address CompilerToVM::Data::dlog10;
@@ -268,6 +269,19 @@ void CompilerToVM::Data::initialize(JVMCI_TRAPS) {
SET_TRIGFUNC(dpow);
#undef SET_TRIGFUNC
+
+#define SET_TRIGFUNC_OR_NULL(name) \
+ if (StubRoutines::name() != nullptr) { \
+ name = StubRoutines::name(); \
+ } else { \
+ name = nullptr; \
+ }
+
+ SET_TRIGFUNC_OR_NULL(dtanh);
+
+#undef SET_TRIGFUNC_OR_NULL
+
+
}
static jboolean is_c1_supported(vmIntrinsics::ID id){
diff --git a/src/hotspot/share/jvmci/jvmci_globals.cpp b/src/hotspot/share/jvmci/jvmci_globals.cpp
index 86d8491b73303..36740560dd23f 100644
--- a/src/hotspot/share/jvmci/jvmci_globals.cpp
+++ b/src/hotspot/share/jvmci/jvmci_globals.cpp
@@ -80,6 +80,15 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() {
CHECK_NOT_SET(LibJVMCICompilerThreadHidden, UseJVMCICompiler)
if (UseJVMCICompiler) {
+ if (!FLAG_IS_DEFAULT(EnableJVMCI) && !EnableJVMCI) {
+ jio_fprintf(defaultStream::error_stream(),
+ "Improperly specified VM option UseJVMCICompiler: EnableJVMCI cannot be disabled\n");
+ return false;
+ }
+ FLAG_SET_DEFAULT(EnableJVMCI, true);
+ }
+
+ if (EnableJVMCI) {
if (FLAG_IS_DEFAULT(UseJVMCINativeLibrary) && !UseJVMCINativeLibrary) {
char path[JVM_MAXPATHLEN];
if (os::dll_locate_lib(path, sizeof(path), Arguments::get_dll_dir(), JVMCI_SHARED_LIBRARY_NAME)) {
@@ -88,12 +97,9 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() {
FLAG_SET_DEFAULT(UseJVMCINativeLibrary, true);
}
}
- if (!FLAG_IS_DEFAULT(EnableJVMCI) && !EnableJVMCI) {
- jio_fprintf(defaultStream::error_stream(),
- "Improperly specified VM option UseJVMCICompiler: EnableJVMCI cannot be disabled\n");
- return false;
- }
- FLAG_SET_DEFAULT(EnableJVMCI, true);
+ }
+
+ if (UseJVMCICompiler) {
if (BootstrapJVMCI && UseJVMCINativeLibrary) {
jio_fprintf(defaultStream::error_stream(), "-XX:+BootstrapJVMCI is not compatible with -XX:+UseJVMCINativeLibrary\n");
return false;
diff --git a/src/hotspot/share/jvmci/jvmci_globals.hpp b/src/hotspot/share/jvmci/jvmci_globals.hpp
index 1f2c0c647ab1e..30f2e6c2c73e0 100644
--- a/src/hotspot/share/jvmci/jvmci_globals.hpp
+++ b/src/hotspot/share/jvmci/jvmci_globals.hpp
@@ -140,7 +140,7 @@ class fileStream;
product(bool, UseJVMCINativeLibrary, false, EXPERIMENTAL, \
"Execute JVMCI Java code from a shared library (\"libjvmci\") " \
"instead of loading it from class files and executing it " \
- "on the HotSpot heap. Defaults to true if EnableJVMCIProduct is " \
+ "on the HotSpot heap. Defaults to true if EnableJVMCI is " \
"true and a JVMCI native library is available.") \
\
product(double, JVMCINativeLibraryThreadFraction, 0.33, EXPERIMENTAL, \
diff --git a/src/hotspot/share/logging/logSelection.cpp b/src/hotspot/share/logging/logSelection.cpp
index aea5719b36d4f..1e7ba3a887848 100644
--- a/src/hotspot/share/logging/logSelection.cpp
+++ b/src/hotspot/share/logging/logSelection.cpp
@@ -33,11 +33,11 @@
const LogSelection LogSelection::Invalid;
-LogSelection::LogSelection() : _ntags(0), _wildcard(false), _level(LogLevel::Invalid), _tag_sets_selected(0) {
+LogSelection::LogSelection() : _ntags(0), _tags(), _wildcard(false), _level(LogLevel::Invalid), _tag_sets_selected(0) {
}
LogSelection::LogSelection(const LogTagType tags[LogTag::MaxTags], bool wildcard, LogLevelType level)
- : _ntags(0), _wildcard(wildcard), _level(level), _tag_sets_selected(0) {
+ : _ntags(0), _tags(), _wildcard(wildcard), _level(level), _tag_sets_selected(0) {
while (_ntags < LogTag::MaxTags && tags[_ntags] != LogTag::__NO_TAG) {
_tags[_ntags] = tags[_ntags];
_ntags++;
diff --git a/src/hotspot/share/nmt/mallocHeader.hpp b/src/hotspot/share/nmt/mallocHeader.hpp
index c76e61fb4b5a2..6711c2b993e6f 100644
--- a/src/hotspot/share/nmt/mallocHeader.hpp
+++ b/src/hotspot/share/nmt/mallocHeader.hpp
@@ -127,6 +127,7 @@ class MallocHeader {
inline MallocHeader(size_t size, MemTag mem_tag, uint32_t mst_marker);
+ inline static size_t malloc_overhead() { return sizeof(MallocHeader) + sizeof(uint16_t); }
inline size_t size() const { return _size; }
inline MemTag mem_tag() const { return _mem_tag; }
inline uint32_t mst_marker() const { return _mst_marker; }
diff --git a/src/hotspot/share/nmt/mallocTracker.hpp b/src/hotspot/share/nmt/mallocTracker.hpp
index 39d120433ef02..de30f32373edf 100644
--- a/src/hotspot/share/nmt/mallocTracker.hpp
+++ b/src/hotspot/share/nmt/mallocTracker.hpp
@@ -166,7 +166,7 @@ class MallocMemorySnapshot {
}
inline size_t malloc_overhead() const {
- return _all_mallocs.count() * sizeof(MallocHeader);
+ return _all_mallocs.count() * MallocHeader::malloc_overhead();
}
// Total malloc invocation count
@@ -269,7 +269,7 @@ class MallocTracker : AllStatic {
// The overhead that is incurred by switching on NMT (we need, per malloc allocation,
// space for header and 16-bit footer)
- static const size_t overhead_per_malloc = sizeof(MallocHeader) + sizeof(uint16_t);
+ static inline size_t overhead_per_malloc() { return MallocHeader::malloc_overhead(); }
// Parameter name convention:
// memblock : the beginning address for user data
diff --git a/src/hotspot/share/nmt/memTracker.hpp b/src/hotspot/share/nmt/memTracker.hpp
index 31b1e66b8a6b3..6ba1db2e7ffe6 100644
--- a/src/hotspot/share/nmt/memTracker.hpp
+++ b/src/hotspot/share/nmt/memTracker.hpp
@@ -72,7 +72,7 @@ class MemTracker : AllStatic {
// Per-malloc overhead incurred by NMT, depending on the current NMT level
static size_t overhead_per_malloc() {
- return enabled() ? MallocTracker::overhead_per_malloc : 0;
+ return enabled() ? MallocTracker::overhead_per_malloc() : 0;
}
static inline void* record_malloc(void* mem_base, size_t size, MemTag mem_tag,
diff --git a/src/hotspot/share/oops/compressedOops.cpp b/src/hotspot/share/oops/compressedOops.cpp
index 08f78b1d7734c..98a4438383a79 100644
--- a/src/hotspot/share/oops/compressedOops.cpp
+++ b/src/hotspot/share/oops/compressedOops.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 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
@@ -35,8 +35,10 @@
#include "runtime/globals.hpp"
// For UseCompressedOops.
-NarrowPtrStruct CompressedOops::_narrow_oop = { nullptr, 0, true };
-MemRegion CompressedOops::_heap_address_range;
+address CompressedOops::_base = nullptr;
+int CompressedOops::_shift = 0;
+bool CompressedOops::_use_implicit_null_checks = true;
+MemRegion CompressedOops::_heap_address_range;
// Choose the heap base address and oop encoding mode
// when compressed oops are used:
@@ -88,16 +90,16 @@ void CompressedOops::initialize(const ReservedHeapSpace& heap_space) {
void CompressedOops::set_base(address base) {
assert(UseCompressedOops, "no compressed oops?");
- _narrow_oop._base = base;
+ _base = base;
}
void CompressedOops::set_shift(int shift) {
- _narrow_oop._shift = shift;
+ _shift = shift;
}
void CompressedOops::set_use_implicit_null_checks(bool use) {
assert(UseCompressedOops, "no compressed ptrs?");
- _narrow_oop._use_implicit_null_checks = use;
+ _use_implicit_null_checks = use;
}
bool CompressedOops::is_in(void* addr) {
@@ -148,14 +150,14 @@ bool CompressedOops::is_disjoint_heap_base_address(address addr) {
// Check for disjoint base compressed oops.
bool CompressedOops::base_disjoint() {
- return _narrow_oop._base != nullptr && is_disjoint_heap_base_address(_narrow_oop._base);
+ return _base != nullptr && is_disjoint_heap_base_address(_base);
}
// Check for real heapbased compressed oops.
// We must subtract the base as the bits overlap.
// If we negate above function, we also get unscaled and zerobased.
bool CompressedOops::base_overlaps() {
- return _narrow_oop._base != nullptr && !is_disjoint_heap_base_address(_narrow_oop._base);
+ return _base != nullptr && !is_disjoint_heap_base_address(_base);
}
void CompressedOops::print_mode(outputStream* st) {
diff --git a/src/hotspot/share/oops/compressedOops.hpp b/src/hotspot/share/oops/compressedOops.hpp
index cd3f00393ca44..33af420305cba 100644
--- a/src/hotspot/share/oops/compressedOops.hpp
+++ b/src/hotspot/share/oops/compressedOops.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 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
@@ -34,23 +34,18 @@
class outputStream;
class ReservedHeapSpace;
-struct NarrowPtrStruct {
+class CompressedOops : public AllStatic {
+ friend class VMStructs;
+
// Base address for oop-within-java-object materialization.
// null if using wide oops or zero based narrow oops.
- address _base;
+ static address _base;
// Number of shift bits for encoding/decoding narrow ptrs.
- // 0 if using wide ptrs or zero based unscaled narrow ptrs,
+ // 0 if using wide oops or zero based unscaled narrow oops,
// LogMinObjAlignmentInBytes otherwise.
- int _shift;
- // Generate code with implicit null checks for narrow ptrs.
- bool _use_implicit_null_checks;
-};
-
-class CompressedOops : public AllStatic {
- friend class VMStructs;
-
- // For UseCompressedOops.
- static NarrowPtrStruct _narrow_oop;
+ static int _shift;
+ // Generate code with implicit null checks for narrow oops.
+ static bool _use_implicit_null_checks;
// The address range of the heap
static MemRegion _heap_address_range;
@@ -73,8 +68,7 @@ class CompressedOops : public AllStatic {
UnscaledNarrowOop = 0,
ZeroBasedNarrowOop = 1,
DisjointBaseNarrowOop = 2,
- HeapBasedNarrowOop = 3,
- AnyNarrowOopMode = 4
+ HeapBasedNarrowOop = 3
};
// The representation type for narrowOop is assumed to be uint32_t.
@@ -87,15 +81,13 @@ class CompressedOops : public AllStatic {
static void set_shift(int shift);
static void set_use_implicit_null_checks(bool use);
- static address base() { return _narrow_oop._base; }
+ static address base() { return _base; }
+ static address base_addr() { return (address)&_base; }
static address begin() { return (address)_heap_address_range.start(); }
static address end() { return (address)_heap_address_range.end(); }
static bool is_base(void* addr) { return (base() == (address)addr); }
- static int shift() { return _narrow_oop._shift; }
- static bool use_implicit_null_checks() { return _narrow_oop._use_implicit_null_checks; }
-
- static address ptrs_base_addr() { return (address)&_narrow_oop._base; }
- static address ptrs_base() { return _narrow_oop._base; }
+ static int shift() { return _shift; }
+ static bool use_implicit_null_checks() { return _use_implicit_null_checks; }
static bool is_in(void* addr);
static bool is_in(MemRegion mr);
diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp
index 817a35959f348..321d8add75594 100644
--- a/src/hotspot/share/oops/cpCache.cpp
+++ b/src/hotspot/share/oops/cpCache.cpp
@@ -604,6 +604,7 @@ void ConstantPoolCache::adjust_method_entries(bool * trace_name_printed) {
if (old_method == nullptr || !old_method->is_old()) {
continue;
}
+ assert(!old_method->is_deleted(), "cannot delete these methods");
Method* new_method = old_method->get_new_method();
resolved_indy_entry_at(j)->adjust_method_entry(new_method);
log_adjust("indy", old_method, new_method, trace_name_printed);
diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp
index 7288533cd33e7..42de77acca931 100644
--- a/src/hotspot/share/opto/c2_globals.hpp
+++ b/src/hotspot/share/opto/c2_globals.hpp
@@ -58,6 +58,9 @@
product(bool, StressMacroExpansion, false, DIAGNOSTIC, \
"Randomize macro node expansion order") \
\
+ product(bool, StressUnstableIfTraps, false, DIAGNOSTIC, \
+ "Randomly take unstable if traps") \
+ \
product(uint, StressSeed, 0, DIAGNOSTIC, \
"Seed for randomized stress testing (if unset, a random one is " \
"generated). The seed is recorded in the compilation log, if " \
diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp
index 2f087858efd48..117e06acd6f31 100644
--- a/src/hotspot/share/opto/c2compiler.cpp
+++ b/src/hotspot/share/opto/c2compiler.cpp
@@ -610,6 +610,7 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) {
case vmIntrinsics::_dsin:
case vmIntrinsics::_dcos:
case vmIntrinsics::_dtan:
+ case vmIntrinsics::_dtanh:
case vmIntrinsics::_dabs:
case vmIntrinsics::_fabs:
case vmIntrinsics::_iabs:
diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp
index 5edd31fa71695..ac8896705dea0 100644
--- a/src/hotspot/share/opto/cfgnode.hpp
+++ b/src/hotspot/share/opto/cfgnode.hpp
@@ -347,7 +347,6 @@ class IfNode : public MultiBranchNode {
bool is_null_check(ProjNode* proj, PhaseIterGVN* igvn);
bool is_side_effect_free_test(ProjNode* proj, PhaseIterGVN* igvn);
void reroute_side_effect_free_unc(ProjNode* proj, ProjNode* dom_proj, PhaseIterGVN* igvn);
- ProjNode* uncommon_trap_proj(CallStaticJavaNode*& call) const;
bool fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn);
static bool is_dominator_unc(CallStaticJavaNode* dom_unc, CallStaticJavaNode* unc);
@@ -442,6 +441,7 @@ class IfNode : public MultiBranchNode {
static Node* up_one_dom(Node* curr, bool linear_only = false);
bool is_zero_trip_guard() const;
Node* dominated_by(Node* prev_dom, PhaseIterGVN* igvn, bool pin_array_access_nodes);
+ ProjNode* uncommon_trap_proj(CallStaticJavaNode*& call, Deoptimization::DeoptReason reason = Deoptimization::Reason_none) const;
// Takes the type of val and filters it through the test represented
// by if_proj and returns a more refined type if one is produced.
diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp
index cf282e24c1fc8..e3f3cad4e2d8a 100644
--- a/src/hotspot/share/opto/compile.cpp
+++ b/src/hotspot/share/opto/compile.cpp
@@ -725,6 +725,11 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
method()->ensure_method_data();
}
+ if (StressLCM || StressGCM || StressIGVN || StressCCP ||
+ StressIncrementalInlining || StressMacroExpansion || StressUnstableIfTraps) {
+ initialize_stress_seed(directive);
+ }
+
Init(/*do_aliasing=*/ true);
print_compile_messages();
@@ -849,11 +854,6 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
if (failing()) return;
NOT_PRODUCT( verify_graph_edges(); )
- if (StressLCM || StressGCM || StressIGVN || StressCCP ||
- StressIncrementalInlining || StressMacroExpansion) {
- initialize_stress_seed(directive);
- }
-
// Now optimize
Optimize();
if (failing()) return;
diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp
index 8e5cd2702137a..4313b2cf907a9 100644
--- a/src/hotspot/share/opto/ifnode.cpp
+++ b/src/hotspot/share/opto/ifnode.cpp
@@ -840,9 +840,9 @@ bool IfNode::is_dominator_unc(CallStaticJavaNode* dom_unc, CallStaticJavaNode* u
}
// Return projection that leads to an uncommon trap if any
-ProjNode* IfNode::uncommon_trap_proj(CallStaticJavaNode*& call) const {
+ProjNode* IfNode::uncommon_trap_proj(CallStaticJavaNode*& call, Deoptimization::DeoptReason reason) const {
for (int i = 0; i < 2; i++) {
- call = proj_out(i)->is_uncommon_trap_proj();
+ call = proj_out(i)->is_uncommon_trap_proj(reason);
if (call != nullptr) {
return proj_out(i);
}
diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp
index c95a450272989..8bbb2f8115ec4 100644
--- a/src/hotspot/share/opto/library_call.cpp
+++ b/src/hotspot/share/opto/library_call.cpp
@@ -254,6 +254,7 @@ bool LibraryCallKit::try_to_inline(int predicate) {
case vmIntrinsics::_dsin:
case vmIntrinsics::_dcos:
case vmIntrinsics::_dtan:
+ case vmIntrinsics::_dtanh:
case vmIntrinsics::_dabs:
case vmIntrinsics::_fabs:
case vmIntrinsics::_iabs:
@@ -1879,6 +1880,9 @@ bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) {
return StubRoutines::dtan() != nullptr ?
runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dtan(), "dtan") :
runtime_math(OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dtan), "TAN");
+ case vmIntrinsics::_dtanh:
+ return StubRoutines::dtanh() != nullptr ?
+ runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dtanh(), "dtanh") : false;
case vmIntrinsics::_dexp:
return StubRoutines::dexp() != nullptr ?
runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dexp(), "dexp") :
diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp
index 3128e23d79c49..b2a1a9d5e2102 100644
--- a/src/hotspot/share/opto/loopnode.cpp
+++ b/src/hotspot/share/opto/loopnode.cpp
@@ -1918,12 +1918,28 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_
// Since stride > 0 and limit_correction <= stride + 1, we can restate this with no over- or underflow into:
// max_int - canonicalized_correction - limit_correction >= limit
// Since canonicalized_correction and limit_correction are both constants, we can replace them with a new constant:
- // final_correction = canonicalized_correction + limit_correction
+ // (v) final_correction = canonicalized_correction + limit_correction
+ //
// which gives us:
//
// Final predicate condition:
// max_int - final_correction >= limit
//
+ // However, we need to be careful that (v) does not over- or underflow.
+ // We know that:
+ // canonicalized_correction = stride - 1
+ // and
+ // limit_correction <= stride + 1
+ // and thus
+ // canonicalized_correction + limit_correction <= 2 * stride
+ // To prevent an over- or underflow of (v), we must ensure that
+ // 2 * stride <= max_int
+ // which can safely be checked without over- or underflow with
+ // (vi) stride != min_int AND abs(stride) <= max_int / 2
+ //
+ // We could try to further optimize the cases where (vi) does not hold but given that such large strides are
+ // very uncommon and the loop would only run for a very few iterations anyway, we simply bail out if (vi) fails.
+ //
// (2) Loop Limit Check Predicate for (ii):
// Using (ii): init < limit
//
@@ -1954,6 +1970,10 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_
// there is no overflow of the iv phi after the first iteration. In this case, we don't need to check (ii)
// again and can skip the predicate.
+ // Check (vi) and bail out if the stride is too big.
+ if (stride_con == min_signed_integer(iv_bt) || (ABS(stride_con) > max_signed_integer(iv_bt) / 2)) {
+ return false;
+ }
// Accounting for (LE3) and (LE4) where we use pre-incremented phis in the loop exit check.
const jlong limit_correction_for_pre_iv_exit_check = (phi_incr != nullptr) ? stride_con : 0;
diff --git a/src/hotspot/share/opto/parse.hpp b/src/hotspot/share/opto/parse.hpp
index a2690aa6704f0..484c49367cc4d 100644
--- a/src/hotspot/share/opto/parse.hpp
+++ b/src/hotspot/share/opto/parse.hpp
@@ -612,6 +612,11 @@ class Parse : public GraphKit {
// Use speculative type to optimize CmpP node
Node* optimize_cmp_with_klass(Node* c);
+ // Stress unstable if traps
+ void stress_trap(IfNode* orig_iff, Node* counter, Node* incr_store);
+ // Increment counter used by StressUnstableIfTraps
+ void increment_trap_stress_counter(Node*& counter, Node*& incr_store);
+
public:
#ifndef PRODUCT
// Handle PrintOpto, etc.
diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp
index cbd9323c3a93a..6b7cb4eaa99e3 100644
--- a/src/hotspot/share/opto/parse2.cpp
+++ b/src/hotspot/share/opto/parse2.cpp
@@ -1371,10 +1371,27 @@ inline int Parse::repush_if_args() {
return bc_depth;
}
+// Used by StressUnstableIfTraps
+static volatile int _trap_stress_counter = 0;
+
+void Parse::increment_trap_stress_counter(Node*& counter, Node*& incr_store) {
+ Node* counter_addr = makecon(TypeRawPtr::make((address)&_trap_stress_counter));
+ counter = make_load(control(), counter_addr, TypeInt::INT, T_INT, Compile::AliasIdxRaw, MemNode::unordered);
+ counter = _gvn.transform(new AddINode(counter, intcon(1)));
+ incr_store = store_to_memory(control(), counter_addr, counter, T_INT, Compile::AliasIdxRaw, MemNode::unordered);
+}
+
//----------------------------------do_ifnull----------------------------------
void Parse::do_ifnull(BoolTest::mask btest, Node *c) {
int target_bci = iter().get_dest();
+ Node* counter = nullptr;
+ Node* incr_store = nullptr;
+ bool do_stress_trap = StressUnstableIfTraps && ((C->random() % 2) == 0);
+ if (do_stress_trap) {
+ increment_trap_stress_counter(counter, incr_store);
+ }
+
Block* branch_block = successor_for_bci(target_bci);
Block* next_block = successor_for_bci(iter().next_bci());
@@ -1439,6 +1456,10 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) {
} else { // Path is live.
adjust_map_after_if(BoolTest(btest).negate(), c, 1.0-prob, next_block);
}
+
+ if (do_stress_trap) {
+ stress_trap(iff, counter, incr_store);
+ }
}
//------------------------------------do_if------------------------------------
@@ -1468,6 +1489,13 @@ void Parse::do_if(BoolTest::mask btest, Node* c) {
return;
}
+ Node* counter = nullptr;
+ Node* incr_store = nullptr;
+ bool do_stress_trap = StressUnstableIfTraps && ((C->random() % 2) == 0);
+ if (do_stress_trap) {
+ increment_trap_stress_counter(counter, incr_store);
+ }
+
// Sanity check the probability value
assert(0.0f < prob && prob < 1.0f,"Bad probability in Parser");
@@ -1550,9 +1578,58 @@ void Parse::do_if(BoolTest::mask btest, Node* c) {
} else {
adjust_map_after_if(untaken_btest, c, untaken_prob, next_block);
}
+
+ if (do_stress_trap) {
+ stress_trap(iff, counter, incr_store);
+ }
+}
+
+// Force unstable if traps to be taken randomly to trigger intermittent bugs such as incorrect debug information.
+// Add another if before the unstable if that checks a "random" condition at runtime (a simple shared counter) and
+// then either takes the trap or executes the original, unstable if.
+void Parse::stress_trap(IfNode* orig_iff, Node* counter, Node* incr_store) {
+ // Search for an unstable if trap
+ CallStaticJavaNode* trap = nullptr;
+ assert(orig_iff->Opcode() == Op_If && orig_iff->outcnt() == 2, "malformed if");
+ ProjNode* trap_proj = orig_iff->uncommon_trap_proj(trap, Deoptimization::Reason_unstable_if);
+ if (trap == nullptr || !trap->jvms()->should_reexecute()) {
+ // No suitable trap found. Remove unused counter load and increment.
+ C->gvn_replace_by(incr_store, incr_store->in(MemNode::Memory));
+ return;
+ }
+
+ // Remove trap from optimization list since we add another path to the trap.
+ bool success = C->remove_unstable_if_trap(trap, true);
+ assert(success, "Trap already modified");
+
+ // Add a check before the original if that will trap with a certain frequency and execute the original if otherwise
+ int freq_log = (C->random() % 31) + 1; // Random logarithmic frequency in [1, 31]
+ Node* mask = intcon(right_n_bits(freq_log));
+ counter = _gvn.transform(new AndINode(counter, mask));
+ Node* cmp = _gvn.transform(new CmpINode(counter, intcon(0)));
+ Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::mask::eq));
+ IfNode* iff = _gvn.transform(new IfNode(orig_iff->in(0), bol, orig_iff->_prob, orig_iff->_fcnt))->as_If();
+ Node* if_true = _gvn.transform(new IfTrueNode(iff));
+ Node* if_false = _gvn.transform(new IfFalseNode(iff));
+ assert(!if_true->is_top() && !if_false->is_top(), "trap always / never taken");
+
+ // Trap
+ assert(trap_proj->outcnt() == 1, "some other nodes are dependent on the trap projection");
+
+ Node* trap_region = new RegionNode(3);
+ trap_region->set_req(1, trap_proj);
+ trap_region->set_req(2, if_true);
+ trap->set_req(0, _gvn.transform(trap_region));
+
+ // Don't trap, execute original if
+ orig_iff->set_req(0, if_false);
}
bool Parse::path_is_suitable_for_uncommon_trap(float prob) const {
+ // Randomly skip emitting an uncommon trap
+ if (StressUnstableIfTraps && ((C->random() % 2) == 0)) {
+ return false;
+ }
// Don't want to speculate on uncommon traps when running with -Xcomp
if (!UseInterpreter) {
return false;
diff --git a/src/hotspot/share/runtime/basicLock.inline.hpp b/src/hotspot/share/runtime/basicLock.inline.hpp
index f78537372057d..d977a62a923f4 100644
--- a/src/hotspot/share/runtime/basicLock.inline.hpp
+++ b/src/hotspot/share/runtime/basicLock.inline.hpp
@@ -45,7 +45,7 @@ inline void BasicLock::set_displaced_header(markWord header) {
inline ObjectMonitor* BasicLock::object_monitor_cache() const {
assert(UseObjectMonitorTable, "must be");
-#if defined(X86) || defined(AARCH64) || defined(RISCV64) || defined(LOONGARCH64)
+#if defined(X86) || defined(AARCH64) || defined(RISCV64) || defined(PPC64) || defined(S390) || defined(LOONGARCH64)
return reinterpret_cast(get_metadata());
#else
// Other platforms do not make use of the cache yet,
diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp
index 7722df41916e5..a36252dacbf52 100644
--- a/src/hotspot/share/runtime/os.cpp
+++ b/src/hotspot/share/runtime/os.cpp
@@ -38,6 +38,7 @@
#include "code/codeCache.hpp"
#include "code/vtableStubs.hpp"
#include "gc/shared/gcVMOperations.hpp"
+#include "gc/shared/oopStorageSet.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
#include "logging/log.hpp"
@@ -1323,6 +1324,11 @@ void os::print_location(outputStream* st, intptr_t x, bool verbose) {
}
#endif
+ // Ask if any OopStorage knows about this address.
+ if (OopStorageSet::print_containing(addr, st)) {
+ return;
+ }
+
// Still nothing? If NMT is enabled, we can ask what it thinks...
if (MemTracker::print_containing_region(addr, st)) {
return;
diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp
index c13f64fca4bed..a2b8c1da64490 100644
--- a/src/hotspot/share/runtime/stubRoutines.cpp
+++ b/src/hotspot/share/runtime/stubRoutines.cpp
@@ -171,6 +171,7 @@ address StubRoutines::_dlibm_sin_cos_huge = nullptr;
address StubRoutines::_dlibm_reduce_pi04l = nullptr;
address StubRoutines::_dlibm_tan_cot_huge = nullptr;
address StubRoutines::_dtan = nullptr;
+address StubRoutines::_dtanh = nullptr;
address StubRoutines::_f2hf = nullptr;
address StubRoutines::_hf2f = nullptr;
diff --git a/src/hotspot/share/runtime/stubRoutines.hpp b/src/hotspot/share/runtime/stubRoutines.hpp
index f5b932569be81..b58c591bbf75c 100644
--- a/src/hotspot/share/runtime/stubRoutines.hpp
+++ b/src/hotspot/share/runtime/stubRoutines.hpp
@@ -281,6 +281,7 @@ class StubRoutines: AllStatic {
static address _dlibm_reduce_pi04l;
static address _dlibm_tan_cot_huge;
static address _dtan;
+ static address _dtanh;
static address _fmod;
static address _f2hf;
@@ -472,6 +473,7 @@ class StubRoutines: AllStatic {
static address dlibm_sin_cos_huge() { return _dlibm_sin_cos_huge; }
static address dlibm_tan_cot_huge() { return _dlibm_tan_cot_huge; }
static address dtan() { return _dtan; }
+ static address dtanh() { return _dtanh; }
// These are versions of the java.lang.Float::floatToFloat16() and float16ToFloat()
// methods which perform the same operations as the intrinsic version.
diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp
index 41abd97c66983..fd02249e16948 100644
--- a/src/hotspot/share/runtime/vmStructs.cpp
+++ b/src/hotspot/share/runtime/vmStructs.cpp
@@ -379,9 +379,9 @@
/* CompressedOops */ \
/******************/ \
\
- static_field(CompressedOops, _narrow_oop._base, address) \
- static_field(CompressedOops, _narrow_oop._shift, int) \
- static_field(CompressedOops, _narrow_oop._use_implicit_null_checks, bool) \
+ static_field(CompressedOops, _base, address) \
+ static_field(CompressedOops, _shift, int) \
+ static_field(CompressedOops, _use_implicit_null_checks, bool) \
\
/***************************/ \
/* CompressedKlassPointers */ \
diff --git a/src/java.base/macosx/native/libjli/java_md_macosx.m b/src/java.base/macosx/native/libjli/java_md_macosx.m
index 4ac2f2c10a215..c5e7ba580a503 100644
--- a/src/java.base/macosx/native/libjli/java_md_macosx.m
+++ b/src/java.base/macosx/native/libjli/java_md_macosx.m
@@ -60,115 +60,79 @@
#define LD_LIBRARY_PATH "DYLD_FALLBACK_LIBRARY_PATH"
/*
- * If a processor / os combination has the ability to run binaries of
- * two data models and cohabitation of jre/jdk bits with both data
- * models is supported, then DUAL_MODE is defined. MacOSX is a hybrid
- * system in that, the universal library can contain all types of libraries
- * 32/64 and client/server, thus the spawn is capable of linking with the
- * appropriate library as requested.
+ * Following is the high level flow of the launcher
+ * code residing in the common java.c and this
+ * macosx specific java_md_macosx file:
*
- * Notes:
- * 1. VM. DUAL_MODE is disabled, and not supported, however, it is left here in
- * for experimentation and perhaps enable it in the future.
- * 2. At the time of this writing, the universal library contains only
- * a server 64-bit server JVM.
- * 3. "-client" command line option is supported merely as a command line flag,
- * for, compatibility reasons, however, a server VM will be launched.
- */
-
-/*
- * Flowchart of launcher execs and options processing on unix
+ * - JLI_Launch function, which is the entry point
+ * to the launcher, calls CreateExecutionEnvironment.
+ *
+ * - CreateExecutionEnvironment does the following
+ * (not necessarily in this order):
+ * - determines the relevant JVM type that needs
+ * to be ultimately created
+ * - determines the path and asserts the presence
+ * of libjava and relevant libjvm library
+ * - removes any JVM selection options from the
+ * arguments that were passed to the launcher
+ *
+ * - CreateExecutionEnvironment then creates a new
+ * thread, within the same process, to launch the
+ * application's main() Java method and parks the
+ * current thread, on which CreateExecutionEnvironment
+ * was invoked, in Apple's Cocoa event loop. Before
+ * doing so, CreateExecutionEnvironment maintains a
+ * state flag to keep note that a new thread has
+ * been spawned.
+ *
+ * - The newly created thread (in which the application's
+ * main() method will ultimately run) starts right from
+ * the beginning of the current process' main function,
+ * which effectively means that JLI_Launch is re-invoked
+ * on this new thread and the same above sequence of code
+ * flow repeats again. During this "recursive" call, when
+ * at the point of creating a new thread in
+ * CreateExecutionEnvironment, the CreateExecutionEnvironment
+ * will check for the state flag to see if a new thread
+ * has already been spawned and upon noticing that it
+ * has, it will skip spawning any more threads and will
+ * return back from CreateExecutionEnvironment.
+ *
+ * - The control returns back from CreateExecutionEnvironment
+ * to JLI_Launch, and the thread on which the control
+ * returns is the thread on which the application's main()
+ * Java method will be invoked.
+ *
+ * - JLI_Launch then invokes LoadJavaVM which dlopen()s the
+ * JVM library and asserts the presence of JNI Invocation
+ * Functions "JNI_CreateJavaVM", "JNI_GetDefaultJavaVMInitArgs"
+ * and "JNI_GetCreatedJavaVMs" in that library. It then sets
+ * internal function pointers in the launcher to point to
+ * those functions.
+ *
+ * - JLI_Launch then translates any -J options by invoking
+ * TranslateApplicationArgs.
+ *
+ * - JLI_Launch then invokes ParseArguments to parse/process
+ * the launcher arguments.
*
- * The selection of the proper vm shared library to open depends on
- * several classes of command line options, including vm "flavor"
- * options (-client, -server) and the data model options, -d32 and
- * -d64, as well as a version specification which may have come from
- * the command line or from the manifest of an executable jar file.
- * The vm selection options are not passed to the running
- * virtual machine; they must be screened out by the launcher.
+ * - JLI_Launch then ultimately calls JVMInit.
*
- * The version specification (if any) is processed first by the
- * platform independent routine SelectVersion. This may result in
- * the exec of the specified launcher version.
+ * - JVMInit then invokes JavaMain.
*
- * Now, in most cases,the launcher will dlopen the target libjvm.so. All
- * required libraries are loaded by the runtime linker, using the known paths
- * baked into the shared libraries at compile time. Therefore,
- * in most cases, the launcher will only exec, if the data models are
- * mismatched, and will not set any environment variables, regardless of the
- * data models.
+ * - JavaMain, before launching the application, invokes
+ * PostJVMInit.
*
+ * - PostJVMInit invokes ShowSplashScreen which displays
+ * a splash screen for the application, if applicable.
*
+ * - Control then returns back from PostJVMInit into
+ * JavaMain, which then loads the application's main
+ * class and invokes the relevant main() Java method.
*
- * Main
- * (incoming argv)
- * |
- * \|/
- * CreateExecutionEnvironment
- * (determines desired data model)
- * |
- * |
- * \|/
- * Have Desired Model ? --> NO --> Is Dual-Mode ? --> NO --> Exit(with error)
- * | |
- * | |
- * | \|/
- * | YES
- * | |
- * | |
- * | \|/
- * | CheckJvmType
- * | (removes -client, -server etc.)
- * | |
- * | |
- * \|/ \|/
- * YES Find the desired executable/library
- * | |
- * | |
- * \|/ \|/
- * CheckJvmType POINT A
- * (removes -client, -server, etc.)
- * |
- * |
- * \|/
- * TranslateDashJArgs...
- * (Prepare to pass args to vm)
- * |
- * |
- * \|/
- * ParseArguments
- * (processes version options,
- * creates argument list for vm,
- * etc.)
- * |
- * |
- * \|/
- * POINT A
- * |
- * |
- * \|/
- * Path is desired JRE ? YES --> Continue
- * NO
- * |
- * |
- * \|/
- * Paths have well known
- * jvm paths ? --> NO --> Continue
- * YES
- * |
- * |
- * \|/
- * Does libjvm.so exist
- * in any of them ? --> NO --> Continue
- * YES
- * |
- * |
- * \|/
- * Re-exec / Spawn
- * |
- * |
- * \|/
- * Main
+ * - JavaMain then returns back an integer result which
+ * then gets propagated as a return value all the way
+ * out of the JLI_Launch function.
*/
/* Store the name of the executable once computed */
diff --git a/src/java.base/share/classes/java/io/DataInputStream.java b/src/java.base/share/classes/java/io/DataInputStream.java
index eab7a6e2f189a..59377aca429ca 100644
--- a/src/java.base/share/classes/java/io/DataInputStream.java
+++ b/src/java.base/share/classes/java/io/DataInputStream.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, Alibaba Group Holding Limited. 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,8 +26,11 @@
package java.io;
+import jdk.internal.access.JavaLangAccess;
+import jdk.internal.access.SharedSecrets;
import jdk.internal.util.ByteArray;
+import java.nio.charset.StandardCharsets;
import java.util.Objects;
/**
@@ -45,6 +49,7 @@
* @since 1.0
*/
public class DataInputStream extends FilterInputStream implements DataInput {
+ private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private static final char[] EMPTY_CHAR_ARRAY = new char[0];
@@ -573,18 +578,16 @@ public final String readUTF() throws IOException {
*/
public static final String readUTF(DataInput in) throws IOException {
int utflen = in.readUnsignedShort();
- byte[] bytearr;
- char[] chararr;
+ byte[] bytearr = null;
if (in instanceof DataInputStream dis) {
- if (dis.bytearr.length < utflen) {
- dis.bytearr = new byte[utflen*2];
- dis.chararr = new char[utflen*2];
+ if (dis.bytearr.length >= utflen) {
+ bytearr = dis.bytearr;
}
- chararr = dis.chararr;
- bytearr = dis.bytearr;
- } else {
+ }
+ boolean trusted = false;
+ if (bytearr == null) {
bytearr = new byte[utflen];
- chararr = new char[utflen];
+ trusted = true;
}
int c, char2, char3;
@@ -592,12 +595,35 @@ public static final String readUTF(DataInput in) throws IOException {
int chararr_count=0;
in.readFully(bytearr, 0, utflen);
+ int ascii = JLA.countPositives(bytearr, 0, utflen);
+ if (ascii == utflen) {
+ String str;
+ if (trusted) {
+ str = JLA.newStringNoRepl(bytearr, StandardCharsets.ISO_8859_1);
+ } else {
+ str = new String(bytearr, 0, utflen, StandardCharsets.ISO_8859_1);
+ }
+ return str;
+ }
+ if (trusted && in instanceof DataInputStream dis) {
+ dis.bytearr = bytearr;
+ trusted = false;
+ }
- while (count < utflen) {
- c = (int) bytearr[count] & 0xff;
- if (c > 127) break;
- count++;
- chararr[chararr_count++]=(char)c;
+ char[] chararr;
+ if (in instanceof DataInputStream dis) {
+ if (dis.chararr.length < (utflen << 1)) {
+ dis.chararr = new char[utflen << 1];
+ }
+ chararr = dis.chararr;
+ } else {
+ chararr = new char[utflen];
+ }
+
+ if (ascii != 0) {
+ JLA.inflateBytesToChars(bytearr, 0, chararr, 0, ascii);
+ count += ascii;
+ chararr_count += ascii;
}
while (count < utflen) {
diff --git a/src/java.base/share/classes/java/lang/Math.java b/src/java.base/share/classes/java/lang/Math.java
index 044982a588af8..6b576c88b4710 100644
--- a/src/java.base/share/classes/java/lang/Math.java
+++ b/src/java.base/share/classes/java/lang/Math.java
@@ -2737,6 +2737,7 @@ public static double cosh(double x) {
* @return The hyperbolic tangent of {@code x}.
* @since 1.5
*/
+ @IntrinsicCandidate
public static double tanh(double x) {
return StrictMath.tanh(x);
}
diff --git a/src/java.base/share/classes/java/lang/ThreadBuilders.java b/src/java.base/share/classes/java/lang/ThreadBuilders.java
index ca29dc4f53589..234807d4cc2a7 100644
--- a/src/java.base/share/classes/java/lang/ThreadBuilders.java
+++ b/src/java.base/share/classes/java/lang/ThreadBuilders.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -34,6 +34,7 @@
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;
import jdk.internal.misc.Unsafe;
+import jdk.internal.invoke.MhUtil;
import jdk.internal.vm.ContinuationSupport;
/**
@@ -273,15 +274,9 @@ public ThreadFactory factory() {
* Base ThreadFactory implementation.
*/
private abstract static class BaseThreadFactory implements ThreadFactory {
- private static final VarHandle COUNT;
- static {
- try {
- MethodHandles.Lookup l = MethodHandles.lookup();
- COUNT = l.findVarHandle(BaseThreadFactory.class, "count", long.class);
- } catch (Exception e) {
- throw new InternalError(e);
- }
- }
+ private static final VarHandle COUNT = MhUtil.findVarHandle(
+ MethodHandles.lookup(), "count", long.class);
+
private final String name;
private final int characteristics;
private final UncaughtExceptionHandler uhe;
diff --git a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java
index c4474a248b520..50bfa0b7aa6fb 100644
--- a/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java
+++ b/src/java.base/share/classes/java/lang/classfile/AnnotationValue.java
@@ -60,7 +60,7 @@ public sealed interface AnnotationValue {
/**
* Models an annotation value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_ANNOTATION}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_ANNOTATION}.
*
* @since 22
*/
@@ -73,7 +73,7 @@ sealed interface OfAnnotation extends AnnotationValue
/**
* Models an array value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_ARRAY}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_ARRAY}.
*
* @since 22
*/
@@ -131,7 +131,7 @@ sealed interface OfConstant extends AnnotationValue {
/**
* Models a string value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_STRING}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_STRING}.
*
* @since 22
*/
@@ -159,7 +159,7 @@ default String resolvedValue() {
/**
* Models a double value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_DOUBLE}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_DOUBLE}.
*
* @since 22
*/
@@ -187,7 +187,7 @@ default Double resolvedValue() {
/**
* Models a float value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_FLOAT}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_FLOAT}.
*
* @since 22
*/
@@ -215,7 +215,7 @@ default Float resolvedValue() {
/**
* Models a long value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_LONG}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_LONG}.
*
* @since 22
*/
@@ -243,7 +243,7 @@ default Long resolvedValue() {
/**
* Models an int value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_INT}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_INT}.
*
* @since 22
*/
@@ -271,7 +271,7 @@ default Integer resolvedValue() {
/**
* Models a short value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_SHORT}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_SHORT}.
*
* @since 22
*/
@@ -302,7 +302,7 @@ default Short resolvedValue() {
/**
* Models a char value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_CHAR}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_CHAR}.
*
* @since 22
*/
@@ -333,7 +333,7 @@ default Character resolvedValue() {
/**
* Models a byte value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_BYTE}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_BYTE}.
*
* @since 22
*/
@@ -364,7 +364,7 @@ default Byte resolvedValue() {
/**
* Models a boolean value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_BOOLEAN}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_BOOLEAN}.
*
* @since 22
*/
@@ -395,7 +395,7 @@ default Boolean resolvedValue() {
/**
* Models a class value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_CLASS}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_CLASS}.
*
* @since 22
*/
@@ -413,7 +413,7 @@ default ClassDesc classSymbol() {
/**
* Models an enum value of an element-value pair.
- * The {@linkplain #tag tag} of this value is {@value ClassFile#AEV_ENUM}.
+ * The {@linkplain #tag tag} of this value is {@value TAG_ENUM}.
*
* @since 22
*/
@@ -432,9 +432,52 @@ default ClassDesc classSymbol() {
Utf8Entry constantName();
}
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfByte}. */
+ int TAG_BYTE = 'B';
+
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfChar}. */
+ int TAG_CHAR = 'C';
+
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfDouble}. */
+ int TAG_DOUBLE = 'D';
+
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfFloat}. */
+ int TAG_FLOAT = 'F';
+
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfInt}. */
+ int TAG_INT = 'I';
+
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfLong}. */
+ int TAG_LONG = 'J';
+
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfShort}. */
+ int TAG_SHORT = 'S';
+
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfBoolean}. */
+ int TAG_BOOLEAN = 'Z';
+
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfString}. */
+ int TAG_STRING = 's';
+
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfEnum}. */
+ int TAG_ENUM = 'e';
+
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfClass}. */
+ int TAG_CLASS = 'c';
+
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfAnnotation}. */
+ int TAG_ANNOTATION = '@';
+
+ /** The {@link #tag() tag} indicating the value of an element-value pair is {@link OfArray}. */
+ int TAG_ARRAY = '[';
+
/**
* {@return the tag character for this value as per JVMS {@jvms 4.7.16.1}}
* The tag characters have a one-to-one mapping to the types of annotation element values.
+ *
+ * @apiNote
+ * {@code TAG_}-prefixed constants in this class, such as {@link #TAG_INT},
+ * describe the possible return values of this method.
*/
char tag();
diff --git a/src/java.base/share/classes/java/lang/classfile/ClassFile.java b/src/java.base/share/classes/java/lang/classfile/ClassFile.java
index a305878d3ebf2..284503ee62714 100644
--- a/src/java.base/share/classes/java/lang/classfile/ClassFile.java
+++ b/src/java.base/share/classes/java/lang/classfile/ClassFile.java
@@ -512,903 +512,75 @@ default List verify(Path path) throws IOException {
/** 0xCAFEBABE */
int MAGIC_NUMBER = 0xCAFEBABE;
- /** The integer value used to encode the NOP instruction. */
- int NOP = 0;
-
- /** The integer value used to encode the ACONST_NULL instruction. */
- int ACONST_NULL = 1;
-
- /** The integer value used to encode the ICONST_M1 instruction. */
- int ICONST_M1 = 2;
-
- /** The integer value used to encode the ICONST_0 instruction. */
- int ICONST_0 = 3;
-
- /** The integer value used to encode the ICONST_1 instruction. */
- int ICONST_1 = 4;
-
- /** The integer value used to encode the ICONST_2 instruction. */
- int ICONST_2 = 5;
-
- /** The integer value used to encode the ICONST_3 instruction. */
- int ICONST_3 = 6;
-
- /** The integer value used to encode the ICONST_4 instruction. */
- int ICONST_4 = 7;
-
- /** The integer value used to encode the ICONST_5 instruction. */
- int ICONST_5 = 8;
-
- /** The integer value used to encode the LCONST_0 instruction. */
- int LCONST_0 = 9;
-
- /** The integer value used to encode the LCONST_1 instruction. */
- int LCONST_1 = 10;
-
- /** The integer value used to encode the FCONST_0 instruction. */
- int FCONST_0 = 11;
-
- /** The integer value used to encode the FCONST_1 instruction. */
- int FCONST_1 = 12;
-
- /** The integer value used to encode the FCONST_2 instruction. */
- int FCONST_2 = 13;
-
- /** The integer value used to encode the DCONST_0 instruction. */
- int DCONST_0 = 14;
-
- /** The integer value used to encode the DCONST_1 instruction. */
- int DCONST_1 = 15;
-
- /** The integer value used to encode the BIPUSH instruction. */
- int BIPUSH = 16;
-
- /** The integer value used to encode the SIPUSH instruction. */
- int SIPUSH = 17;
-
- /** The integer value used to encode the LDC instruction. */
- int LDC = 18;
-
- /** The integer value used to encode the LDC_W instruction. */
- int LDC_W = 19;
-
- /** The integer value used to encode the LDC2_W instruction. */
- int LDC2_W = 20;
-
- /** The integer value used to encode the ILOAD instruction. */
- int ILOAD = 21;
-
- /** The integer value used to encode the LLOAD instruction. */
- int LLOAD = 22;
-
- /** The integer value used to encode the FLOAD instruction. */
- int FLOAD = 23;
-
- /** The integer value used to encode the DLOAD instruction. */
- int DLOAD = 24;
-
- /** The integer value used to encode the ALOAD instruction. */
- int ALOAD = 25;
-
- /** The integer value used to encode the ILOAD_0 instruction. */
- int ILOAD_0 = 26;
-
- /** The integer value used to encode the ILOAD_1 instruction. */
- int ILOAD_1 = 27;
-
- /** The integer value used to encode the ILOAD_2 instruction. */
- int ILOAD_2 = 28;
-
- /** The integer value used to encode the ILOAD_3 instruction. */
- int ILOAD_3 = 29;
-
- /** The integer value used to encode the LLOAD_0 instruction. */
- int LLOAD_0 = 30;
-
- /** The integer value used to encode the LLOAD_1 instruction. */
- int LLOAD_1 = 31;
-
- /** The integer value used to encode the LLOAD_2 instruction. */
- int LLOAD_2 = 32;
-
- /** The integer value used to encode the LLOAD_3 instruction. */
- int LLOAD_3 = 33;
-
- /** The integer value used to encode the FLOAD_0 instruction. */
- int FLOAD_0 = 34;
-
- /** The integer value used to encode the FLOAD_1 instruction. */
- int FLOAD_1 = 35;
-
- /** The integer value used to encode the FLOAD_2 instruction. */
- int FLOAD_2 = 36;
-
- /** The integer value used to encode the FLOAD_3 instruction. */
- int FLOAD_3 = 37;
-
- /** The integer value used to encode the DLOAD_0 instruction. */
- int DLOAD_0 = 38;
-
- /** The integer value used to encode the DLOAD_1 instruction. */
- int DLOAD_1 = 39;
-
- /** The integer value used to encode the DLOAD_2 instruction. */
- int DLOAD_2 = 40;
-
- /** The integer value used to encode the DLOAD_3 instruction. */
- int DLOAD_3 = 41;
-
- /** The integer value used to encode the ALOAD_0 instruction. */
- int ALOAD_0 = 42;
-
- /** The integer value used to encode the ALOAD_1 instruction. */
- int ALOAD_1 = 43;
-
- /** The integer value used to encode the ALOAD_2 instruction. */
- int ALOAD_2 = 44;
-
- /** The integer value used to encode the ALOAD_3 instruction. */
- int ALOAD_3 = 45;
-
- /** The integer value used to encode the IALOAD instruction. */
- int IALOAD = 46;
-
- /** The integer value used to encode the LALOAD instruction. */
- int LALOAD = 47;
-
- /** The integer value used to encode the FALOAD instruction. */
- int FALOAD = 48;
-
- /** The integer value used to encode the DALOAD instruction. */
- int DALOAD = 49;
-
- /** The integer value used to encode the AALOAD instruction. */
- int AALOAD = 50;
-
- /** The integer value used to encode the BALOAD instruction. */
- int BALOAD = 51;
-
- /** The integer value used to encode the CALOAD instruction. */
- int CALOAD = 52;
-
- /** The integer value used to encode the SALOAD instruction. */
- int SALOAD = 53;
-
- /** The integer value used to encode the ISTORE instruction. */
- int ISTORE = 54;
-
- /** The integer value used to encode the LSTORE instruction. */
- int LSTORE = 55;
-
- /** The integer value used to encode the FSTORE instruction. */
- int FSTORE = 56;
-
- /** The integer value used to encode the DSTORE instruction. */
- int DSTORE = 57;
-
- /** The integer value used to encode the ASTORE instruction. */
- int ASTORE = 58;
-
- /** The integer value used to encode the ISTORE_0 instruction. */
- int ISTORE_0 = 59;
-
- /** The integer value used to encode the ISTORE_1 instruction. */
- int ISTORE_1 = 60;
-
- /** The integer value used to encode the ISTORE_2 instruction. */
- int ISTORE_2 = 61;
-
- /** The integer value used to encode the ISTORE_3 instruction. */
- int ISTORE_3 = 62;
-
- /** The integer value used to encode the LSTORE_0 instruction. */
- int LSTORE_0 = 63;
-
- /** The integer value used to encode the LSTORE_1 instruction. */
- int LSTORE_1 = 64;
-
- /** The integer value used to encode the LSTORE_2 instruction. */
- int LSTORE_2 = 65;
-
- /** The integer value used to encode the LSTORE_3 instruction. */
- int LSTORE_3 = 66;
-
- /** The integer value used to encode the FSTORE_0 instruction. */
- int FSTORE_0 = 67;
-
- /** The integer value used to encode the FSTORE_1 instruction. */
- int FSTORE_1 = 68;
-
- /** The integer value used to encode the FSTORE_2 instruction. */
- int FSTORE_2 = 69;
-
- /** The integer value used to encode the FSTORE_3 instruction. */
- int FSTORE_3 = 70;
-
- /** The integer value used to encode the DSTORE_0 instruction. */
- int DSTORE_0 = 71;
-
- /** The integer value used to encode the DSTORE_1 instruction. */
- int DSTORE_1 = 72;
-
- /** The integer value used to encode the DSTORE_2 instruction. */
- int DSTORE_2 = 73;
-
- /** The integer value used to encode the DSTORE_3 instruction. */
- int DSTORE_3 = 74;
-
- /** The integer value used to encode the ASTORE_0 instruction. */
- int ASTORE_0 = 75;
-
- /** The integer value used to encode the ASTORE_1 instruction. */
- int ASTORE_1 = 76;
-
- /** The integer value used to encode the ASTORE_2 instruction. */
- int ASTORE_2 = 77;
-
- /** The integer value used to encode the ASTORE_3 instruction. */
- int ASTORE_3 = 78;
-
- /** The integer value used to encode the IASTORE instruction. */
- int IASTORE = 79;
-
- /** The integer value used to encode the LASTORE instruction. */
- int LASTORE = 80;
-
- /** The integer value used to encode the FASTORE instruction. */
- int FASTORE = 81;
-
- /** The integer value used to encode the DASTORE instruction. */
- int DASTORE = 82;
-
- /** The integer value used to encode the AASTORE instruction. */
- int AASTORE = 83;
-
- /** The integer value used to encode the BASTORE instruction. */
- int BASTORE = 84;
-
- /** The integer value used to encode the CASTORE instruction. */
- int CASTORE = 85;
-
- /** The integer value used to encode the SASTORE instruction. */
- int SASTORE = 86;
-
- /** The integer value used to encode the POP instruction. */
- int POP = 87;
-
- /** The integer value used to encode the POP2 instruction. */
- int POP2 = 88;
-
- /** The integer value used to encode the DUP instruction. */
- int DUP = 89;
-
- /** The integer value used to encode the DUP_X1 instruction. */
- int DUP_X1 = 90;
-
- /** The integer value used to encode the DUP_X2 instruction. */
- int DUP_X2 = 91;
-
- /** The integer value used to encode the DUP2 instruction. */
- int DUP2 = 92;
-
- /** The integer value used to encode the DUP2_X1 instruction. */
- int DUP2_X1 = 93;
-
- /** The integer value used to encode the DUP2_X2 instruction. */
- int DUP2_X2 = 94;
-
- /** The integer value used to encode the SWAP instruction. */
- int SWAP = 95;
-
- /** The integer value used to encode the IADD instruction. */
- int IADD = 96;
-
- /** The integer value used to encode the LADD instruction. */
- int LADD = 97;
-
- /** The integer value used to encode the FADD instruction. */
- int FADD = 98;
-
- /** The integer value used to encode the DADD instruction. */
- int DADD = 99;
-
- /** The integer value used to encode the ISUB instruction. */
- int ISUB = 100;
-
- /** The integer value used to encode the LSUB instruction. */
- int LSUB = 101;
-
- /** The integer value used to encode the FSUB instruction. */
- int FSUB = 102;
-
- /** The integer value used to encode the DSUB instruction. */
- int DSUB = 103;
-
- /** The integer value used to encode the IMUL instruction. */
- int IMUL = 104;
-
- /** The integer value used to encode the LMUL instruction. */
- int LMUL = 105;
-
- /** The integer value used to encode the FMUL instruction. */
- int FMUL = 106;
-
- /** The integer value used to encode the DMUL instruction. */
- int DMUL = 107;
-
- /** The integer value used to encode the IDIV instruction. */
- int IDIV = 108;
-
- /** The integer value used to encode the LDIV instruction. */
- int LDIV = 109;
-
- /** The integer value used to encode the FDIV instruction. */
- int FDIV = 110;
-
- /** The integer value used to encode the DDIV instruction. */
- int DDIV = 111;
-
- /** The integer value used to encode the IREM instruction. */
- int IREM = 112;
-
- /** The integer value used to encode the LREM instruction. */
- int LREM = 113;
-
- /** The integer value used to encode the FREM instruction. */
- int FREM = 114;
-
- /** The integer value used to encode the DREM instruction. */
- int DREM = 115;
-
- /** The integer value used to encode the INEG instruction. */
- int INEG = 116;
-
- /** The integer value used to encode the LNEG instruction. */
- int LNEG = 117;
-
- /** The integer value used to encode the FNEG instruction. */
- int FNEG = 118;
-
- /** The integer value used to encode the DNEG instruction. */
- int DNEG = 119;
-
- /** The integer value used to encode the ISHL instruction. */
- int ISHL = 120;
-
- /** The integer value used to encode the LSHL instruction. */
- int LSHL = 121;
-
- /** The integer value used to encode the ISHR instruction. */
- int ISHR = 122;
-
- /** The integer value used to encode the LSHR instruction. */
- int LSHR = 123;
-
- /** The integer value used to encode the IUSHR instruction. */
- int IUSHR = 124;
-
- /** The integer value used to encode the LUSHR instruction. */
- int LUSHR = 125;
-
- /** The integer value used to encode the IAND instruction. */
- int IAND = 126;
-
- /** The integer value used to encode the LAND instruction. */
- int LAND = 127;
-
- /** The integer value used to encode the IOR instruction. */
- int IOR = 128;
-
- /** The integer value used to encode the LOR instruction. */
- int LOR = 129;
-
- /** The integer value used to encode the IXOR instruction. */
- int IXOR = 130;
-
- /** The integer value used to encode the LXOR instruction. */
- int LXOR = 131;
-
- /** The integer value used to encode the IINC instruction. */
- int IINC = 132;
-
- /** The integer value used to encode the I2L instruction. */
- int I2L = 133;
-
- /** The integer value used to encode the I2F instruction. */
- int I2F = 134;
-
- /** The integer value used to encode the I2D instruction. */
- int I2D = 135;
-
- /** The integer value used to encode the L2I instruction. */
- int L2I = 136;
-
- /** The integer value used to encode the L2F instruction. */
- int L2F = 137;
-
- /** The integer value used to encode the L2D instruction. */
- int L2D = 138;
-
- /** The integer value used to encode the F2I instruction. */
- int F2I = 139;
-
- /** The integer value used to encode the F2L instruction. */
- int F2L = 140;
-
- /** The integer value used to encode the F2D instruction. */
- int F2D = 141;
-
- /** The integer value used to encode the D2I instruction. */
- int D2I = 142;
-
- /** The integer value used to encode the D2L instruction. */
- int D2L = 143;
-
- /** The integer value used to encode the D2F instruction. */
- int D2F = 144;
-
- /** The integer value used to encode the I2B instruction. */
- int I2B = 145;
-
- /** The integer value used to encode the I2C instruction. */
- int I2C = 146;
-
- /** The integer value used to encode the I2S instruction. */
- int I2S = 147;
-
- /** The integer value used to encode the LCMP instruction. */
- int LCMP = 148;
-
- /** The integer value used to encode the FCMPL instruction. */
- int FCMPL = 149;
-
- /** The integer value used to encode the FCMPG instruction. */
- int FCMPG = 150;
-
- /** The integer value used to encode the DCMPL instruction. */
- int DCMPL = 151;
-
- /** The integer value used to encode the DCMPG instruction. */
- int DCMPG = 152;
-
- /** The integer value used to encode the IFEQ instruction. */
- int IFEQ = 153;
-
- /** The integer value used to encode the IFNE instruction. */
- int IFNE = 154;
-
- /** The integer value used to encode the IFLT instruction. */
- int IFLT = 155;
-
- /** The integer value used to encode the IFGE instruction. */
- int IFGE = 156;
-
- /** The integer value used to encode the IFGT instruction. */
- int IFGT = 157;
-
- /** The integer value used to encode the IFLE instruction. */
- int IFLE = 158;
-
- /** The integer value used to encode the IF_ICMPEQ instruction. */
- int IF_ICMPEQ = 159;
-
- /** The integer value used to encode the IF_ICMPNE instruction. */
- int IF_ICMPNE = 160;
-
- /** The integer value used to encode the IF_ICMPLT instruction. */
- int IF_ICMPLT = 161;
-
- /** The integer value used to encode the IF_ICMPGE instruction. */
- int IF_ICMPGE = 162;
-
- /** The integer value used to encode the IF_ICMPGT instruction. */
- int IF_ICMPGT = 163;
-
- /** The integer value used to encode the IF_ICMPLE instruction. */
- int IF_ICMPLE = 164;
-
- /** The integer value used to encode the IF_ACMPEQ instruction. */
- int IF_ACMPEQ = 165;
-
- /** The integer value used to encode the IF_ACMPNE instruction. */
- int IF_ACMPNE = 166;
-
- /** The integer value used to encode the GOTO instruction. */
- int GOTO = 167;
-
- /** The integer value used to encode the JSR instruction. */
- int JSR = 168;
-
- /** The integer value used to encode the RET instruction. */
- int RET = 169;
-
- /** The integer value used to encode the TABLESWITCH instruction. */
- int TABLESWITCH = 170;
-
- /** The integer value used to encode the LOOKUPSWITCH instruction. */
- int LOOKUPSWITCH = 171;
-
- /** The integer value used to encode the IRETURN instruction. */
- int IRETURN = 172;
-
- /** The integer value used to encode the LRETURN instruction. */
- int LRETURN = 173;
-
- /** The integer value used to encode the FRETURN instruction. */
- int FRETURN = 174;
-
- /** The integer value used to encode the DRETURN instruction. */
- int DRETURN = 175;
-
- /** The integer value used to encode the ARETURN instruction. */
- int ARETURN = 176;
-
- /** The integer value used to encode the RETURN instruction. */
- int RETURN = 177;
-
- /** The integer value used to encode the GETSTATIC instruction. */
- int GETSTATIC = 178;
-
- /** The integer value used to encode the PUTSTATIC instruction. */
- int PUTSTATIC = 179;
-
- /** The integer value used to encode the GETFIELD instruction. */
- int GETFIELD = 180;
-
- /** The integer value used to encode the PUTFIELD instruction. */
- int PUTFIELD = 181;
-
- /** The integer value used to encode the INVOKEVIRTUAL instruction. */
- int INVOKEVIRTUAL = 182;
-
- /** The integer value used to encode the INVOKESPECIAL instruction. */
- int INVOKESPECIAL = 183;
-
- /** The integer value used to encode the INVOKESTATIC instruction. */
- int INVOKESTATIC = 184;
-
- /** The integer value used to encode the INVOKEINTERFACE instruction. */
- int INVOKEINTERFACE = 185;
-
- /** The integer value used to encode the INVOKEDYNAMIC instruction. */
- int INVOKEDYNAMIC = 186;
-
- /** The integer value used to encode the NEW instruction. */
- int NEW = 187;
-
- /** The integer value used to encode the NEWARRAY instruction. */
- int NEWARRAY = 188;
-
- /** The integer value used to encode the ANEWARRAY instruction. */
- int ANEWARRAY = 189;
-
- /** The integer value used to encode the ARRAYLENGTH instruction. */
- int ARRAYLENGTH = 190;
-
- /** The integer value used to encode the ATHROW instruction. */
- int ATHROW = 191;
-
- /** The integer value used to encode the CHECKCAST instruction. */
- int CHECKCAST = 192;
-
- /** The integer value used to encode the INSTANCEOF instruction. */
- int INSTANCEOF = 193;
-
- /** The integer value used to encode the MONITORENTER instruction. */
- int MONITORENTER = 194;
-
- /** The integer value used to encode the MONITOREXIT instruction. */
- int MONITOREXIT = 195;
-
- /** The integer value used to encode the WIDE instruction. */
- int WIDE = 196;
-
- /** The integer value used to encode the MULTIANEWARRAY instruction. */
- int MULTIANEWARRAY = 197;
-
- /** The integer value used to encode the IFNULL instruction. */
- int IFNULL = 198;
-
- /** The integer value used to encode the IFNONNULL instruction. */
- int IFNONNULL = 199;
-
- /** The integer value used to encode the GOTO_W instruction. */
- int GOTO_W = 200;
-
- /** The integer value used to encode the JSR_W instruction. */
- int JSR_W = 201;
-
- /** The value of PUBLIC access and property modifier. */
+ /** The bit mask of PUBLIC access and property modifier. */
int ACC_PUBLIC = 0x0001;
- /** The value of PROTECTED access and property modifier. */
+ /** The bit mask of PROTECTED access and property modifier. */
int ACC_PROTECTED = 0x0004;
- /** The value of PRIVATE access and property modifier. */
+ /** The bit mask of PRIVATE access and property modifier. */
int ACC_PRIVATE = 0x0002;
- /** The value of INTERFACE access and property modifier. */
+ /** The bit mask of INTERFACE access and property modifier. */
int ACC_INTERFACE = 0x0200;
- /** The value of ENUM access and property modifier. */
+ /** The bit mask of ENUM access and property modifier. */
int ACC_ENUM = 0x4000;
- /** The value of ANNOTATION access and property modifier. */
+ /** The bit mask of ANNOTATION access and property modifier. */
int ACC_ANNOTATION = 0x2000;
- /** The value of SUPER access and property modifier. */
+ /** The bit mask of SUPER access and property modifier. */
int ACC_SUPER = 0x0020;
- /** The value of ABSTRACT access and property modifier. */
+ /** The bit mask of ABSTRACT access and property modifier. */
int ACC_ABSTRACT = 0x0400;
- /** The value of VOLATILE access and property modifier. */
+ /** The bit mask of VOLATILE access and property modifier. */
int ACC_VOLATILE = 0x0040;
- /** The value of TRANSIENT access and property modifier. */
+ /** The bit mask of TRANSIENT access and property modifier. */
int ACC_TRANSIENT = 0x0080;
- /** The value of SYNTHETIC access and property modifier. */
+ /** The bit mask of SYNTHETIC access and property modifier. */
int ACC_SYNTHETIC = 0x1000;
- /** The value of STATIC access and property modifier. */
+ /** The bit mask of STATIC access and property modifier. */
int ACC_STATIC = 0x0008;
- /** The value of FINAL access and property modifier. */
+ /** The bit mask of FINAL access and property modifier. */
int ACC_FINAL = 0x0010;
- /** The value of SYNCHRONIZED access and property modifier. */
+ /** The bit mask of SYNCHRONIZED access and property modifier. */
int ACC_SYNCHRONIZED = 0x0020;
- /** The value of BRIDGE access and property modifier. */
+ /** The bit mask of BRIDGE access and property modifier. */
int ACC_BRIDGE = 0x0040;
- /** The value of VARARGS access and property modifier. */
+ /** The bit mask of VARARGS access and property modifier. */
int ACC_VARARGS = 0x0080;
- /** The value of NATIVE access and property modifier. */
+ /** The bit mask of NATIVE access and property modifier. */
int ACC_NATIVE = 0x0100;
- /** The value of STRICT access and property modifier. */
+ /** The bit mask of STRICT access and property modifier. */
int ACC_STRICT = 0x0800;
- /** The value of MODULE access and property modifier. */
+ /** The bit mask of MODULE access and property modifier. */
int ACC_MODULE = 0x8000;
- /** The value of OPEN access and property modifier. */
+ /** The bit mask of OPEN access and property modifier. */
int ACC_OPEN = 0x20;
- /** The value of MANDATED access and property modifier. */
+ /** The bit mask of MANDATED access and property modifier. */
int ACC_MANDATED = 0x8000;
- /** The value of TRANSITIVE access and property modifier. */
+ /** The bit mask of TRANSITIVE access and property modifier. */
int ACC_TRANSITIVE = 0x20;
- /** The value of STATIC_PHASE access and property modifier. */
+ /** The bit mask of STATIC_PHASE access and property modifier. */
int ACC_STATIC_PHASE = 0x40;
- /** The value of STATEMENT {@link CharacterRangeInfo} kind. */
- int CRT_STATEMENT = 0x0001;
-
- /** The value of BLOCK {@link CharacterRangeInfo} kind. */
- int CRT_BLOCK = 0x0002;
-
- /** The value of ASSIGNMENT {@link CharacterRangeInfo} kind. */
- int CRT_ASSIGNMENT = 0x0004;
-
- /** The value of FLOW_CONTROLLER {@link CharacterRangeInfo} kind. */
- int CRT_FLOW_CONTROLLER = 0x0008;
-
- /** The value of FLOW_TARGET {@link CharacterRangeInfo} kind. */
- int CRT_FLOW_TARGET = 0x0010;
-
- /** The value of INVOKE {@link CharacterRangeInfo} kind. */
- int CRT_INVOKE = 0x0020;
-
- /** The value of CREATE {@link CharacterRangeInfo} kind. */
- int CRT_CREATE = 0x0040;
-
- /** The value of BRANCH_TRUE {@link CharacterRangeInfo} kind. */
- int CRT_BRANCH_TRUE = 0x0080;
-
- /** The value of BRANCH_FALSE {@link CharacterRangeInfo} kind. */
- int CRT_BRANCH_FALSE = 0x0100;
-
- /** The value of constant pool tag CLASS. */
- int TAG_CLASS = 7;
-
- /** The value of constant pool tag CONSTANTDYNAMIC. */
- int TAG_CONSTANTDYNAMIC = 17;
-
- /** The value of constant pool tag DOUBLE. */
- int TAG_DOUBLE = 6;
-
- /** The value of constant pool tag FIELDREF. */
- int TAG_FIELDREF = 9;
-
- /** The value of constant pool tag FLOAT. */
- int TAG_FLOAT = 4;
-
- /** The value of constant pool tag INTEGER. */
- int TAG_INTEGER = 3;
-
- /** The value of constant pool tag INTERFACEMETHODREF. */
- int TAG_INTERFACEMETHODREF = 11;
-
- /** The value of constant pool tag INVOKEDYNAMIC. */
- int TAG_INVOKEDYNAMIC = 18;
-
- /** The value of constant pool tag LONG. */
- int TAG_LONG = 5;
-
- /** The value of constant pool tag METHODHANDLE. */
- int TAG_METHODHANDLE = 15;
-
- /** The value of constant pool tag METHODREF. */
- int TAG_METHODREF = 10;
-
- /** The value of constant pool tag METHODTYPE. */
- int TAG_METHODTYPE = 16;
-
- /** The value of constant pool tag MODULE. */
- int TAG_MODULE = 19;
-
- /** The value of constant pool tag NAMEANDTYPE. */
- int TAG_NAMEANDTYPE = 12;
-
- /** The value of constant pool tag PACKAGE. */
- int TAG_PACKAGE = 20;
-
- /** The value of constant pool tag STRING. */
- int TAG_STRING = 8;
-
- /** The value of constant pool tag UNICODE. */
- int TAG_UNICODE = 2;
-
- /** The value of constant pool tag UTF8. */
- int TAG_UTF8 = 1;
-
- // annotation element values
-
- /** The value of annotation element value type AEV_BYTE. */
- int AEV_BYTE = 'B';
-
- /** The value of annotation element value type AEV_CHAR. */
- int AEV_CHAR = 'C';
-
- /** The value of annotation element value type AEV_DOUBLE. */
- int AEV_DOUBLE = 'D';
-
- /** The value of annotation element value type AEV_FLOAT. */
- int AEV_FLOAT = 'F';
-
- /** The value of annotation element value type AEV_INT. */
- int AEV_INT = 'I';
-
- /** The value of annotation element value type AEV_LONG. */
- int AEV_LONG = 'J';
-
- /** The value of annotation element value type AEV_SHORT. */
- int AEV_SHORT = 'S';
-
- /** The value of annotation element value type AEV_BOOLEAN. */
- int AEV_BOOLEAN = 'Z';
-
- /** The value of annotation element value type AEV_STRING. */
- int AEV_STRING = 's';
-
- /** The value of annotation element value type AEV_ENUM. */
- int AEV_ENUM = 'e';
-
- /** The value of annotation element value type AEV_CLASS. */
- int AEV_CLASS = 'c';
-
- /** The value of annotation element value type AEV_ANNOTATION. */
- int AEV_ANNOTATION = '@';
-
- /** The value of annotation element value type AEV_ARRAY. */
- int AEV_ARRAY = '[';
-
- //type annotations
-
- /** The value of type annotation target type CLASS_TYPE_PARAMETER. */
- int TAT_CLASS_TYPE_PARAMETER = 0x00;
-
- /** The value of type annotation target type METHOD_TYPE_PARAMETER. */
- int TAT_METHOD_TYPE_PARAMETER = 0x01;
-
- /** The value of type annotation target type CLASS_EXTENDS. */
- int TAT_CLASS_EXTENDS = 0x10;
-
- /** The value of type annotation target type CLASS_TYPE_PARAMETER_BOUND. */
- int TAT_CLASS_TYPE_PARAMETER_BOUND = 0x11;
-
- /** The value of type annotation target type METHOD_TYPE_PARAMETER_BOUND. */
- int TAT_METHOD_TYPE_PARAMETER_BOUND = 0x12;
-
- /** The value of type annotation target type FIELD. */
- int TAT_FIELD = 0x13;
-
- /** The value of type annotation target type METHOD_RETURN. */
- int TAT_METHOD_RETURN = 0x14;
-
- /** The value of type annotation target type METHOD_RECEIVER. */
- int TAT_METHOD_RECEIVER = 0x15;
-
- /** The value of type annotation target type METHOD_FORMAL_PARAMETER. */
- int TAT_METHOD_FORMAL_PARAMETER = 0x16;
-
- /** The value of type annotation target type THROWS. */
- int TAT_THROWS = 0x17;
-
- /** The value of type annotation target type LOCAL_VARIABLE. */
- int TAT_LOCAL_VARIABLE = 0x40;
-
- /** The value of type annotation target type RESOURCE_VARIABLE. */
- int TAT_RESOURCE_VARIABLE = 0x41;
-
- /** The value of type annotation target type EXCEPTION_PARAMETER. */
- int TAT_EXCEPTION_PARAMETER = 0x42;
-
- /** The value of type annotation target type INSTANCEOF. */
- int TAT_INSTANCEOF = 0x43;
-
- /** The value of type annotation target type NEW. */
- int TAT_NEW = 0x44;
-
- /** The value of type annotation target type CONSTRUCTOR_REFERENCE. */
- int TAT_CONSTRUCTOR_REFERENCE = 0x45;
-
- /** The value of type annotation target type METHOD_REFERENCE. */
- int TAT_METHOD_REFERENCE = 0x46;
-
- /** The value of type annotation target type CAST. */
- int TAT_CAST = 0x47;
-
- /** The value of type annotation target type CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT. */
- int TAT_CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
-
- /** The value of type annotation target type METHOD_INVOCATION_TYPE_ARGUMENT. */
- int TAT_METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
-
- /** The value of type annotation target type CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT. */
- int TAT_CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
-
- /** The value of type annotation target type METHOD_REFERENCE_TYPE_ARGUMENT. */
- int TAT_METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
-
- //stackmap verification types
-
- /** The value of verification type TOP. */
- int VT_TOP = 0;
-
- /** The value of verification type INTEGER. */
- int VT_INTEGER = 1;
-
- /** The value of verification type FLOAT. */
- int VT_FLOAT = 2;
-
- /** The value of verification type DOUBLE. */
- int VT_DOUBLE = 3;
-
- /** The value of verification type LONG. */
- int VT_LONG = 4;
-
- /** The value of verification type NULL. */
- int VT_NULL = 5;
-
- /** The value of verification type UNINITIALIZED_THIS. */
- int VT_UNINITIALIZED_THIS = 6;
-
- /** The value of verification type OBJECT. */
- int VT_OBJECT = 7;
-
- /** The value of verification type UNINITIALIZED. */
- int VT_UNINITIALIZED = 8;
-
- /** The value of default class access flags */
- int DEFAULT_CLASS_FLAGS = ACC_PUBLIC;
-
/** The class major version of JAVA_1. */
int JAVA_1_VERSION = 45;
diff --git a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java
index 5f4e5b72a1919..16f513801a249 100644
--- a/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java
+++ b/src/java.base/share/classes/java/lang/classfile/CodeBuilder.java
@@ -615,36 +615,77 @@ default CodeBuilder loadConstant(ConstantDesc value) {
if (value == null || value == ConstantDescs.NULL)
return aconst_null();
if (value instanceof Number) {
- if (value instanceof Integer iVal)
- return switch (iVal) {
- case -1 -> iconst_m1();
- case 0 -> iconst_0();
- case 1 -> iconst_1();
- case 2 -> iconst_2();
- case 3 -> iconst_3();
- case 4 -> iconst_4();
- case 5 -> iconst_5();
- default -> (iVal >= Byte.MIN_VALUE && iVal <= Byte.MAX_VALUE) ? bipush(iVal)
- : (iVal >= Short.MIN_VALUE && iVal <= Short.MAX_VALUE) ? sipush(iVal)
- : ldc(constantPool().intEntry(iVal));
- };
- if (value instanceof Long lVal)
- return lVal == 0L ? lconst_0()
- : lVal == 1L ? lconst_1()
- : ldc(constantPool().longEntry(lVal));
- if (value instanceof Float fVal)
- return Float.floatToRawIntBits(fVal) == 0 ? fconst_0()
- : fVal == 1.0f ? fconst_1()
- : fVal == 2.0f ? fconst_2()
- : ldc(constantPool().floatEntry(fVal));
- if (value instanceof Double dVal)
- return Double.doubleToRawLongBits(dVal) == 0L ? dconst_0()
- : dVal == 1.0d ? dconst_1()
- : ldc(constantPool().doubleEntry(dVal));
+ if (value instanceof Integer) return loadConstant((int) value);
+ if (value instanceof Long ) return loadConstant((long) value);
+ if (value instanceof Float ) return loadConstant((float) value);
+ if (value instanceof Double ) return loadConstant((double) value);
}
return ldc(value);
}
+
+ /**
+ * Generate an instruction pushing a constant int value onto the operand stack.
+ * This is identical to {@link #loadConstant(ConstantDesc) loadConstant(Integer.valueOf(value))}.
+ * @param value the int value
+ * @return this builder
+ * @since 24
+ */
+ default CodeBuilder loadConstant(int value) {
+ return switch (value) {
+ case -1 -> iconst_m1();
+ case 0 -> iconst_0();
+ case 1 -> iconst_1();
+ case 2 -> iconst_2();
+ case 3 -> iconst_3();
+ case 4 -> iconst_4();
+ case 5 -> iconst_5();
+ default -> (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE ) ? bipush(value)
+ : (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) ? sipush(value)
+ : ldc(constantPool().intEntry(value));
+ };
+ }
+
+ /**
+ * Generate an instruction pushing a constant long value onto the operand stack.
+ * This is identical to {@link #loadConstant(ConstantDesc) loadConstant(Long.valueOf(value))}.
+ * @param value the long value
+ * @return this builder
+ * @since 24
+ */
+ default CodeBuilder loadConstant(long value) {
+ return value == 0l ? lconst_0()
+ : value == 1l ? lconst_1()
+ : ldc(constantPool().longEntry(value));
+ }
+
+ /**
+ * Generate an instruction pushing a constant float value onto the operand stack.
+ * This is identical to {@link #loadConstant(ConstantDesc) loadConstant(Float.valueOf(value))}.
+ * @param value the float value
+ * @return this builder
+ * @since 24
+ */
+ default CodeBuilder loadConstant(float value) {
+ return Float.floatToRawIntBits(value) == 0 ? fconst_0()
+ : value == 1.0f ? fconst_1()
+ : value == 2.0f ? fconst_2()
+ : ldc(constantPool().floatEntry(value));
+ }
+
+ /**
+ * Generate an instruction pushing a constant double value onto the operand stack.
+ * This is identical to {@link #loadConstant(ConstantDesc) loadConstant(Double.valueOf(value))}.
+ * @param value the double value
+ * @return this builder
+ * @since 24
+ */
+ default CodeBuilder loadConstant(double value) {
+ return Double.doubleToRawLongBits(value) == 0l ? dconst_0()
+ : value == 1.0d ? dconst_1()
+ : ldc(constantPool().doubleEntry(value));
+ }
+
/**
* Generate a do nothing instruction
* @return this builder
diff --git a/src/java.base/share/classes/java/lang/classfile/Opcode.java b/src/java.base/share/classes/java/lang/classfile/Opcode.java
index ab991d983453d..735510dbcea3b 100644
--- a/src/java.base/share/classes/java/lang/classfile/Opcode.java
+++ b/src/java.base/share/classes/java/lang/classfile/Opcode.java
@@ -24,6 +24,7 @@
*/
package java.lang.classfile;
+import jdk.internal.classfile.impl.RawBytecodeHelper;
import jdk.internal.javac.PreviewFeature;
/**
@@ -40,658 +41,658 @@
public enum Opcode {
/** Do nothing */
- NOP(ClassFile.NOP, 1, Kind.NOP),
+ NOP(RawBytecodeHelper.NOP, 1, Kind.NOP),
/** Push null */
- ACONST_NULL(ClassFile.ACONST_NULL, 1, Kind.CONSTANT),
+ ACONST_NULL(RawBytecodeHelper.ACONST_NULL, 1, Kind.CONSTANT),
/** Push int constant -1 */
- ICONST_M1(ClassFile.ICONST_M1, 1, Kind.CONSTANT),
+ ICONST_M1(RawBytecodeHelper.ICONST_M1, 1, Kind.CONSTANT),
/** Push int constant 0 */
- ICONST_0(ClassFile.ICONST_0, 1, Kind.CONSTANT),
+ ICONST_0(RawBytecodeHelper.ICONST_0, 1, Kind.CONSTANT),
/** Push int constant 1 */
- ICONST_1(ClassFile.ICONST_1, 1, Kind.CONSTANT),
+ ICONST_1(RawBytecodeHelper.ICONST_1, 1, Kind.CONSTANT),
/** Push int constant 2 */
- ICONST_2(ClassFile.ICONST_2, 1, Kind.CONSTANT),
+ ICONST_2(RawBytecodeHelper.ICONST_2, 1, Kind.CONSTANT),
/** Push int constant 3 */
- ICONST_3(ClassFile.ICONST_3, 1, Kind.CONSTANT),
+ ICONST_3(RawBytecodeHelper.ICONST_3, 1, Kind.CONSTANT),
/** Push int constant 4 */
- ICONST_4(ClassFile.ICONST_4, 1, Kind.CONSTANT),
+ ICONST_4(RawBytecodeHelper.ICONST_4, 1, Kind.CONSTANT),
/** Push int constant 5 */
- ICONST_5(ClassFile.ICONST_5, 1, Kind.CONSTANT),
+ ICONST_5(RawBytecodeHelper.ICONST_5, 1, Kind.CONSTANT),
/** Push long constant 0 */
- LCONST_0(ClassFile.LCONST_0, 1, Kind.CONSTANT),
+ LCONST_0(RawBytecodeHelper.LCONST_0, 1, Kind.CONSTANT),
/** Push long constant 1 */
- LCONST_1(ClassFile.LCONST_1, 1, Kind.CONSTANT),
+ LCONST_1(RawBytecodeHelper.LCONST_1, 1, Kind.CONSTANT),
/** Push float constant 0 */
- FCONST_0(ClassFile.FCONST_0, 1, Kind.CONSTANT),
+ FCONST_0(RawBytecodeHelper.FCONST_0, 1, Kind.CONSTANT),
/** Push float constant 1 */
- FCONST_1(ClassFile.FCONST_1, 1, Kind.CONSTANT),
+ FCONST_1(RawBytecodeHelper.FCONST_1, 1, Kind.CONSTANT),
/** Push float constant 2 */
- FCONST_2(ClassFile.FCONST_2, 1, Kind.CONSTANT),
+ FCONST_2(RawBytecodeHelper.FCONST_2, 1, Kind.CONSTANT),
/** Push double constant 0 */
- DCONST_0(ClassFile.DCONST_0, 1, Kind.CONSTANT),
+ DCONST_0(RawBytecodeHelper.DCONST_0, 1, Kind.CONSTANT),
/** Push double constant 1 */
- DCONST_1(ClassFile.DCONST_1, 1, Kind.CONSTANT),
+ DCONST_1(RawBytecodeHelper.DCONST_1, 1, Kind.CONSTANT),
/** Push byte */
- BIPUSH(ClassFile.BIPUSH, 2, Kind.CONSTANT),
+ BIPUSH(RawBytecodeHelper.BIPUSH, 2, Kind.CONSTANT),
/** Push short */
- SIPUSH(ClassFile.SIPUSH, 3, Kind.CONSTANT),
+ SIPUSH(RawBytecodeHelper.SIPUSH, 3, Kind.CONSTANT),
/** Push item from run-time constant pool */
- LDC(ClassFile.LDC, 2, Kind.CONSTANT),
+ LDC(RawBytecodeHelper.LDC, 2, Kind.CONSTANT),
/** Push item from run-time constant pool (wide index) */
- LDC_W(ClassFile.LDC_W, 3, Kind.CONSTANT),
+ LDC_W(RawBytecodeHelper.LDC_W, 3, Kind.CONSTANT),
/** Push long or double from run-time constant pool (wide index) */
- LDC2_W(ClassFile.LDC2_W, 3, Kind.CONSTANT),
+ LDC2_W(RawBytecodeHelper.LDC2_W, 3, Kind.CONSTANT),
/** Load int from local variable */
- ILOAD(ClassFile.ILOAD, 2, Kind.LOAD),
+ ILOAD(RawBytecodeHelper.ILOAD, 2, Kind.LOAD),
/** Load long from local variable */
- LLOAD(ClassFile.LLOAD, 2, Kind.LOAD),
+ LLOAD(RawBytecodeHelper.LLOAD, 2, Kind.LOAD),
/** Load float from local variable */
- FLOAD(ClassFile.FLOAD, 2, Kind.LOAD),
+ FLOAD(RawBytecodeHelper.FLOAD, 2, Kind.LOAD),
/** Load double from local variable */
- DLOAD(ClassFile.DLOAD, 2, Kind.LOAD),
+ DLOAD(RawBytecodeHelper.DLOAD, 2, Kind.LOAD),
/** Load reference from local variable */
- ALOAD(ClassFile.ALOAD, 2, Kind.LOAD),
+ ALOAD(RawBytecodeHelper.ALOAD, 2, Kind.LOAD),
/** Load int from local variable 0 */
- ILOAD_0(ClassFile.ILOAD_0, 1, Kind.LOAD),
+ ILOAD_0(RawBytecodeHelper.ILOAD_0, 1, Kind.LOAD),
/** Load int from local variable 1 */
- ILOAD_1(ClassFile.ILOAD_1, 1, Kind.LOAD),
+ ILOAD_1(RawBytecodeHelper.ILOAD_1, 1, Kind.LOAD),
/** Load int from local variable 2 */
- ILOAD_2(ClassFile.ILOAD_2, 1, Kind.LOAD),
+ ILOAD_2(RawBytecodeHelper.ILOAD_2, 1, Kind.LOAD),
/** Load int from local variable3 */
- ILOAD_3(ClassFile.ILOAD_3, 1, Kind.LOAD),
+ ILOAD_3(RawBytecodeHelper.ILOAD_3, 1, Kind.LOAD),
/** Load long from local variable 0 */
- LLOAD_0(ClassFile.LLOAD_0, 1, Kind.LOAD),
+ LLOAD_0(RawBytecodeHelper.LLOAD_0, 1, Kind.LOAD),
/** Load long from local variable 1 */
- LLOAD_1(ClassFile.LLOAD_1, 1, Kind.LOAD),
+ LLOAD_1(RawBytecodeHelper.LLOAD_1, 1, Kind.LOAD),
/** Load long from local variable 2 */
- LLOAD_2(ClassFile.LLOAD_2, 1, Kind.LOAD),
+ LLOAD_2(RawBytecodeHelper.LLOAD_2, 1, Kind.LOAD),
/** Load long from local variable 3 */
- LLOAD_3(ClassFile.LLOAD_3, 1, Kind.LOAD),
+ LLOAD_3(RawBytecodeHelper.LLOAD_3, 1, Kind.LOAD),
/** Load float from local variable 0 */
- FLOAD_0(ClassFile.FLOAD_0, 1, Kind.LOAD),
+ FLOAD_0(RawBytecodeHelper.FLOAD_0, 1, Kind.LOAD),
/** Load float from local variable 1 */
- FLOAD_1(ClassFile.FLOAD_1, 1, Kind.LOAD),
+ FLOAD_1(RawBytecodeHelper.FLOAD_1, 1, Kind.LOAD),
/** Load float from local variable 2 */
- FLOAD_2(ClassFile.FLOAD_2, 1, Kind.LOAD),
+ FLOAD_2(RawBytecodeHelper.FLOAD_2, 1, Kind.LOAD),
/** Load float from local variable 3 */
- FLOAD_3(ClassFile.FLOAD_3, 1, Kind.LOAD),
+ FLOAD_3(RawBytecodeHelper.FLOAD_3, 1, Kind.LOAD),
/** Load double from local variable 0 */
- DLOAD_0(ClassFile.DLOAD_0, 1, Kind.LOAD),
+ DLOAD_0(RawBytecodeHelper.DLOAD_0, 1, Kind.LOAD),
/** Load double from local variable 1 */
- DLOAD_1(ClassFile.DLOAD_1, 1, Kind.LOAD),
+ DLOAD_1(RawBytecodeHelper.DLOAD_1, 1, Kind.LOAD),
/** Load double from local variable 2 */
- DLOAD_2(ClassFile.DLOAD_2, 1, Kind.LOAD),
+ DLOAD_2(RawBytecodeHelper.DLOAD_2, 1, Kind.LOAD),
/** Load double from local variable 3 */
- DLOAD_3(ClassFile.DLOAD_3, 1, Kind.LOAD),
+ DLOAD_3(RawBytecodeHelper.DLOAD_3, 1, Kind.LOAD),
/** Load reference from local variable 0 */
- ALOAD_0(ClassFile.ALOAD_0, 1, Kind.LOAD),
+ ALOAD_0(RawBytecodeHelper.ALOAD_0, 1, Kind.LOAD),
/** Load reference from local variable 1 */
- ALOAD_1(ClassFile.ALOAD_1, 1, Kind.LOAD),
+ ALOAD_1(RawBytecodeHelper.ALOAD_1, 1, Kind.LOAD),
/** Load reference from local variable 2 */
- ALOAD_2(ClassFile.ALOAD_2, 1, Kind.LOAD),
+ ALOAD_2(RawBytecodeHelper.ALOAD_2, 1, Kind.LOAD),
/** Load reference from local variable 3 */
- ALOAD_3(ClassFile.ALOAD_3, 1, Kind.LOAD),
+ ALOAD_3(RawBytecodeHelper.ALOAD_3, 1, Kind.LOAD),
/** Load int from array */
- IALOAD(ClassFile.IALOAD, 1, Kind.ARRAY_LOAD),
+ IALOAD(RawBytecodeHelper.IALOAD, 1, Kind.ARRAY_LOAD),
/** Load long from array */
- LALOAD(ClassFile.LALOAD, 1, Kind.ARRAY_LOAD),
+ LALOAD(RawBytecodeHelper.LALOAD, 1, Kind.ARRAY_LOAD),
/** Load float from array */
- FALOAD(ClassFile.FALOAD, 1, Kind.ARRAY_LOAD),
+ FALOAD(RawBytecodeHelper.FALOAD, 1, Kind.ARRAY_LOAD),
/** Load double from array */
- DALOAD(ClassFile.DALOAD, 1, Kind.ARRAY_LOAD),
+ DALOAD(RawBytecodeHelper.DALOAD, 1, Kind.ARRAY_LOAD),
/** Load reference from array */
- AALOAD(ClassFile.AALOAD, 1, Kind.ARRAY_LOAD),
+ AALOAD(RawBytecodeHelper.AALOAD, 1, Kind.ARRAY_LOAD),
/** Load byte from array */
- BALOAD(ClassFile.BALOAD, 1, Kind.ARRAY_LOAD),
+ BALOAD(RawBytecodeHelper.BALOAD, 1, Kind.ARRAY_LOAD),
/** Load char from array */
- CALOAD(ClassFile.CALOAD, 1, Kind.ARRAY_LOAD),
+ CALOAD(RawBytecodeHelper.CALOAD, 1, Kind.ARRAY_LOAD),
/** Load short from array */
- SALOAD(ClassFile.SALOAD, 1, Kind.ARRAY_LOAD),
+ SALOAD(RawBytecodeHelper.SALOAD, 1, Kind.ARRAY_LOAD),
/** Store int into local variable */
- ISTORE(ClassFile.ISTORE, 2, Kind.STORE),
+ ISTORE(RawBytecodeHelper.ISTORE, 2, Kind.STORE),
/** Store long into local variable */
- LSTORE(ClassFile.LSTORE, 2, Kind.STORE),
+ LSTORE(RawBytecodeHelper.LSTORE, 2, Kind.STORE),
/** Store float into local variable */
- FSTORE(ClassFile.FSTORE, 2, Kind.STORE),
+ FSTORE(RawBytecodeHelper.FSTORE, 2, Kind.STORE),
/** Store double into local variable */
- DSTORE(ClassFile.DSTORE, 2, Kind.STORE),
+ DSTORE(RawBytecodeHelper.DSTORE, 2, Kind.STORE),
/** Store reference into local variable */
- ASTORE(ClassFile.ASTORE, 2, Kind.STORE),
+ ASTORE(RawBytecodeHelper.ASTORE, 2, Kind.STORE),
/** Store int into local variable 0 */
- ISTORE_0(ClassFile.ISTORE_0, 1, Kind.STORE),
+ ISTORE_0(RawBytecodeHelper.ISTORE_0, 1, Kind.STORE),
/** Store int into local variable 1 */
- ISTORE_1(ClassFile.ISTORE_1, 1, Kind.STORE),
+ ISTORE_1(RawBytecodeHelper.ISTORE_1, 1, Kind.STORE),
/** Store int into local variable 2 */
- ISTORE_2(ClassFile.ISTORE_2, 1, Kind.STORE),
+ ISTORE_2(RawBytecodeHelper.ISTORE_2, 1, Kind.STORE),
/** Store int into local variable 3 */
- ISTORE_3(ClassFile.ISTORE_3, 1, Kind.STORE),
+ ISTORE_3(RawBytecodeHelper.ISTORE_3, 1, Kind.STORE),
/** Store long into local variable 0 */
- LSTORE_0(ClassFile.LSTORE_0, 1, Kind.STORE),
+ LSTORE_0(RawBytecodeHelper.LSTORE_0, 1, Kind.STORE),
/** Store long into local variable 1 */
- LSTORE_1(ClassFile.LSTORE_1, 1, Kind.STORE),
+ LSTORE_1(RawBytecodeHelper.LSTORE_1, 1, Kind.STORE),
/** Store long into local variable 2 */
- LSTORE_2(ClassFile.LSTORE_2, 1, Kind.STORE),
+ LSTORE_2(RawBytecodeHelper.LSTORE_2, 1, Kind.STORE),
/** Store long into local variable 3 */
- LSTORE_3(ClassFile.LSTORE_3, 1, Kind.STORE),
+ LSTORE_3(RawBytecodeHelper.LSTORE_3, 1, Kind.STORE),
/** Store float into local variable 0 */
- FSTORE_0(ClassFile.FSTORE_0, 1, Kind.STORE),
+ FSTORE_0(RawBytecodeHelper.FSTORE_0, 1, Kind.STORE),
/** Store float into local variable 1 */
- FSTORE_1(ClassFile.FSTORE_1, 1, Kind.STORE),
+ FSTORE_1(RawBytecodeHelper.FSTORE_1, 1, Kind.STORE),
/** Store float into local variable 2 */
- FSTORE_2(ClassFile.FSTORE_2, 1, Kind.STORE),
+ FSTORE_2(RawBytecodeHelper.FSTORE_2, 1, Kind.STORE),
/** Store float into local variable 3 */
- FSTORE_3(ClassFile.FSTORE_3, 1, Kind.STORE),
+ FSTORE_3(RawBytecodeHelper.FSTORE_3, 1, Kind.STORE),
/** Store double into local variable 0 */
- DSTORE_0(ClassFile.DSTORE_0, 1, Kind.STORE),
+ DSTORE_0(RawBytecodeHelper.DSTORE_0, 1, Kind.STORE),
/** Store double into local variable 1 */
- DSTORE_1(ClassFile.DSTORE_1, 1, Kind.STORE),
+ DSTORE_1(RawBytecodeHelper.DSTORE_1, 1, Kind.STORE),
/** Store double into local variable 2 */
- DSTORE_2(ClassFile.DSTORE_2, 1, Kind.STORE),
+ DSTORE_2(RawBytecodeHelper.DSTORE_2, 1, Kind.STORE),
/** Store double into local variable 3 */
- DSTORE_3(ClassFile.DSTORE_3, 1, Kind.STORE),
+ DSTORE_3(RawBytecodeHelper.DSTORE_3, 1, Kind.STORE),
/** Store reference into local variable 0 */
- ASTORE_0(ClassFile.ASTORE_0, 1, Kind.STORE),
+ ASTORE_0(RawBytecodeHelper.ASTORE_0, 1, Kind.STORE),
/** Store reference into local variable 1 */
- ASTORE_1(ClassFile.ASTORE_1, 1, Kind.STORE),
+ ASTORE_1(RawBytecodeHelper.ASTORE_1, 1, Kind.STORE),
/** Store reference into local variable 2 */
- ASTORE_2(ClassFile.ASTORE_2, 1, Kind.STORE),
+ ASTORE_2(RawBytecodeHelper.ASTORE_2, 1, Kind.STORE),
/** Store reference into local variable 3 */
- ASTORE_3(ClassFile.ASTORE_3, 1, Kind.STORE),
+ ASTORE_3(RawBytecodeHelper.ASTORE_3, 1, Kind.STORE),
/** Store into int array */
- IASTORE(ClassFile.IASTORE, 1, Kind.ARRAY_STORE),
+ IASTORE(RawBytecodeHelper.IASTORE, 1, Kind.ARRAY_STORE),
/** Store into long array */
- LASTORE(ClassFile.LASTORE, 1, Kind.ARRAY_STORE),
+ LASTORE(RawBytecodeHelper.LASTORE, 1, Kind.ARRAY_STORE),
/** Store into float array */
- FASTORE(ClassFile.FASTORE, 1, Kind.ARRAY_STORE),
+ FASTORE(RawBytecodeHelper.FASTORE, 1, Kind.ARRAY_STORE),
/** Store into double array */
- DASTORE(ClassFile.DASTORE, 1, Kind.ARRAY_STORE),
+ DASTORE(RawBytecodeHelper.DASTORE, 1, Kind.ARRAY_STORE),
/** Store into reference array */
- AASTORE(ClassFile.AASTORE, 1, Kind.ARRAY_STORE),
+ AASTORE(RawBytecodeHelper.AASTORE, 1, Kind.ARRAY_STORE),
/** Store into byte array */
- BASTORE(ClassFile.BASTORE, 1, Kind.ARRAY_STORE),
+ BASTORE(RawBytecodeHelper.BASTORE, 1, Kind.ARRAY_STORE),
/** Store into char array */
- CASTORE(ClassFile.CASTORE, 1, Kind.ARRAY_STORE),
+ CASTORE(RawBytecodeHelper.CASTORE, 1, Kind.ARRAY_STORE),
/** Store into short array */
- SASTORE(ClassFile.SASTORE, 1, Kind.ARRAY_STORE),
+ SASTORE(RawBytecodeHelper.SASTORE, 1, Kind.ARRAY_STORE),
/** Pop the top operand stack value */
- POP(ClassFile.POP, 1, Kind.STACK),
+ POP(RawBytecodeHelper.POP, 1, Kind.STACK),
/** Pop the top one or two operand stack values */
- POP2(ClassFile.POP2, 1, Kind.STACK),
+ POP2(RawBytecodeHelper.POP2, 1, Kind.STACK),
/** Duplicate the top operand stack value */
- DUP(ClassFile.DUP, 1, Kind.STACK),
+ DUP(RawBytecodeHelper.DUP, 1, Kind.STACK),
/** Duplicate the top operand stack value and insert two values down */
- DUP_X1(ClassFile.DUP_X1, 1, Kind.STACK),
+ DUP_X1(RawBytecodeHelper.DUP_X1, 1, Kind.STACK),
/** Duplicate the top operand stack value and insert two or three values down */
- DUP_X2(ClassFile.DUP_X2, 1, Kind.STACK),
+ DUP_X2(RawBytecodeHelper.DUP_X2, 1, Kind.STACK),
/** Duplicate the top one or two operand stack values */
- DUP2(ClassFile.DUP2, 1, Kind.STACK),
+ DUP2(RawBytecodeHelper.DUP2, 1, Kind.STACK),
/** Duplicate the top one or two operand stack values and insert two or three values down */
- DUP2_X1(ClassFile.DUP2_X1, 1, Kind.STACK),
+ DUP2_X1(RawBytecodeHelper.DUP2_X1, 1, Kind.STACK),
/** Duplicate the top one or two operand stack values and insert two, three, or four values down */
- DUP2_X2(ClassFile.DUP2_X2, 1, Kind.STACK),
+ DUP2_X2(RawBytecodeHelper.DUP2_X2, 1, Kind.STACK),
/** Swap the top two operand stack values */
- SWAP(ClassFile.SWAP, 1, Kind.STACK),
+ SWAP(RawBytecodeHelper.SWAP, 1, Kind.STACK),
/** Add int */
- IADD(ClassFile.IADD, 1, Kind.OPERATOR),
+ IADD(RawBytecodeHelper.IADD, 1, Kind.OPERATOR),
/** Add long */
- LADD(ClassFile.LADD, 1, Kind.OPERATOR),
+ LADD(RawBytecodeHelper.LADD, 1, Kind.OPERATOR),
/** Add float */
- FADD(ClassFile.FADD, 1, Kind.OPERATOR),
+ FADD(RawBytecodeHelper.FADD, 1, Kind.OPERATOR),
/** Add double */
- DADD(ClassFile.DADD, 1, Kind.OPERATOR),
+ DADD(RawBytecodeHelper.DADD, 1, Kind.OPERATOR),
/** Subtract int */
- ISUB(ClassFile.ISUB, 1, Kind.OPERATOR),
+ ISUB(RawBytecodeHelper.ISUB, 1, Kind.OPERATOR),
/** Subtract long */
- LSUB(ClassFile.LSUB, 1, Kind.OPERATOR),
+ LSUB(RawBytecodeHelper.LSUB, 1, Kind.OPERATOR),
/** Subtract float */
- FSUB(ClassFile.FSUB, 1, Kind.OPERATOR),
+ FSUB(RawBytecodeHelper.FSUB, 1, Kind.OPERATOR),
/** Subtract double */
- DSUB(ClassFile.DSUB, 1, Kind.OPERATOR),
+ DSUB(RawBytecodeHelper.DSUB, 1, Kind.OPERATOR),
/** Multiply int */
- IMUL(ClassFile.IMUL, 1, Kind.OPERATOR),
+ IMUL(RawBytecodeHelper.IMUL, 1, Kind.OPERATOR),
/** Multiply long */
- LMUL(ClassFile.LMUL, 1, Kind.OPERATOR),
+ LMUL(RawBytecodeHelper.LMUL, 1, Kind.OPERATOR),
/** Multiply float */
- FMUL(ClassFile.FMUL, 1, Kind.OPERATOR),
+ FMUL(RawBytecodeHelper.FMUL, 1, Kind.OPERATOR),
/** Multiply double */
- DMUL(ClassFile.DMUL, 1, Kind.OPERATOR),
+ DMUL(RawBytecodeHelper.DMUL, 1, Kind.OPERATOR),
/** Divide int */
- IDIV(ClassFile.IDIV, 1, Kind.OPERATOR),
+ IDIV(RawBytecodeHelper.IDIV, 1, Kind.OPERATOR),
/** Divide long */
- LDIV(ClassFile.LDIV, 1, Kind.OPERATOR),
+ LDIV(RawBytecodeHelper.LDIV, 1, Kind.OPERATOR),
/** Divide float */
- FDIV(ClassFile.FDIV, 1, Kind.OPERATOR),
+ FDIV(RawBytecodeHelper.FDIV, 1, Kind.OPERATOR),
/** Divide double */
- DDIV(ClassFile.DDIV, 1, Kind.OPERATOR),
+ DDIV(RawBytecodeHelper.DDIV, 1, Kind.OPERATOR),
/** Remainder int */
- IREM(ClassFile.IREM, 1, Kind.OPERATOR),
+ IREM(RawBytecodeHelper.IREM, 1, Kind.OPERATOR),
/** Remainder long */
- LREM(ClassFile.LREM, 1, Kind.OPERATOR),
+ LREM(RawBytecodeHelper.LREM, 1, Kind.OPERATOR),
/** Remainder float */
- FREM(ClassFile.FREM, 1, Kind.OPERATOR),
+ FREM(RawBytecodeHelper.FREM, 1, Kind.OPERATOR),
/** Remainder double */
- DREM(ClassFile.DREM, 1, Kind.OPERATOR),
+ DREM(RawBytecodeHelper.DREM, 1, Kind.OPERATOR),
/** Negate int */
- INEG(ClassFile.INEG, 1, Kind.OPERATOR),
+ INEG(RawBytecodeHelper.INEG, 1, Kind.OPERATOR),
/** Negate long */
- LNEG(ClassFile.LNEG, 1, Kind.OPERATOR),
+ LNEG(RawBytecodeHelper.LNEG, 1, Kind.OPERATOR),
/** Negate float */
- FNEG(ClassFile.FNEG, 1, Kind.OPERATOR),
+ FNEG(RawBytecodeHelper.FNEG, 1, Kind.OPERATOR),
/** Negate double */
- DNEG(ClassFile.DNEG, 1, Kind.OPERATOR),
+ DNEG(RawBytecodeHelper.DNEG, 1, Kind.OPERATOR),
/** Shift left int */
- ISHL(ClassFile.ISHL, 1, Kind.OPERATOR),
+ ISHL(RawBytecodeHelper.ISHL, 1, Kind.OPERATOR),
/** Shift left long */
- LSHL(ClassFile.LSHL, 1, Kind.OPERATOR),
+ LSHL(RawBytecodeHelper.LSHL, 1, Kind.OPERATOR),
/** Shift right int */
- ISHR(ClassFile.ISHR, 1, Kind.OPERATOR),
+ ISHR(RawBytecodeHelper.ISHR, 1, Kind.OPERATOR),
/** Shift right long */
- LSHR(ClassFile.LSHR, 1, Kind.OPERATOR),
+ LSHR(RawBytecodeHelper.LSHR, 1, Kind.OPERATOR),
/** Logical shift right int */
- IUSHR(ClassFile.IUSHR, 1, Kind.OPERATOR),
+ IUSHR(RawBytecodeHelper.IUSHR, 1, Kind.OPERATOR),
/** Logical shift right long */
- LUSHR(ClassFile.LUSHR, 1, Kind.OPERATOR),
+ LUSHR(RawBytecodeHelper.LUSHR, 1, Kind.OPERATOR),
/** Boolean AND int */
- IAND(ClassFile.IAND, 1, Kind.OPERATOR),
+ IAND(RawBytecodeHelper.IAND, 1, Kind.OPERATOR),
/** Boolean AND long */
- LAND(ClassFile.LAND, 1, Kind.OPERATOR),
+ LAND(RawBytecodeHelper.LAND, 1, Kind.OPERATOR),
/** Boolean OR int */
- IOR(ClassFile.IOR, 1, Kind.OPERATOR),
+ IOR(RawBytecodeHelper.IOR, 1, Kind.OPERATOR),
/** Boolean OR long */
- LOR(ClassFile.LOR, 1, Kind.OPERATOR),
+ LOR(RawBytecodeHelper.LOR, 1, Kind.OPERATOR),
/** Boolean XOR int */
- IXOR(ClassFile.IXOR, 1, Kind.OPERATOR),
+ IXOR(RawBytecodeHelper.IXOR, 1, Kind.OPERATOR),
/** Boolean XOR long */
- LXOR(ClassFile.LXOR, 1, Kind.OPERATOR),
+ LXOR(RawBytecodeHelper.LXOR, 1, Kind.OPERATOR),
/** Increment local variable by constant */
- IINC(ClassFile.IINC, 3, Kind.INCREMENT),
+ IINC(RawBytecodeHelper.IINC, 3, Kind.INCREMENT),
/** Convert int to long */
- I2L(ClassFile.I2L, 1, Kind.CONVERT),
+ I2L(RawBytecodeHelper.I2L, 1, Kind.CONVERT),
/** Convert int to float */
- I2F(ClassFile.I2F, 1, Kind.CONVERT),
+ I2F(RawBytecodeHelper.I2F, 1, Kind.CONVERT),
/** Convert int to double */
- I2D(ClassFile.I2D, 1, Kind.CONVERT),
+ I2D(RawBytecodeHelper.I2D, 1, Kind.CONVERT),
/** Convert long to int */
- L2I(ClassFile.L2I, 1, Kind.CONVERT),
+ L2I(RawBytecodeHelper.L2I, 1, Kind.CONVERT),
/** Convert long to float */
- L2F(ClassFile.L2F, 1, Kind.CONVERT),
+ L2F(RawBytecodeHelper.L2F, 1, Kind.CONVERT),
/** Convert long to double */
- L2D(ClassFile.L2D, 1, Kind.CONVERT),
+ L2D(RawBytecodeHelper.L2D, 1, Kind.CONVERT),
/** Convert float to int */
- F2I(ClassFile.F2I, 1, Kind.CONVERT),
+ F2I(RawBytecodeHelper.F2I, 1, Kind.CONVERT),
/** Convert float to long */
- F2L(ClassFile.F2L, 1, Kind.CONVERT),
+ F2L(RawBytecodeHelper.F2L, 1, Kind.CONVERT),
/** Convert float to double */
- F2D(ClassFile.F2D, 1, Kind.CONVERT),
+ F2D(RawBytecodeHelper.F2D, 1, Kind.CONVERT),
/** Convert double to int */
- D2I(ClassFile.D2I, 1, Kind.CONVERT),
+ D2I(RawBytecodeHelper.D2I, 1, Kind.CONVERT),
/** Convert double to long */
- D2L(ClassFile.D2L, 1, Kind.CONVERT),
+ D2L(RawBytecodeHelper.D2L, 1, Kind.CONVERT),
/** Convert double to float */
- D2F(ClassFile.D2F, 1, Kind.CONVERT),
+ D2F(RawBytecodeHelper.D2F, 1, Kind.CONVERT),
/** Convert int to byte */
- I2B(ClassFile.I2B, 1, Kind.CONVERT),
+ I2B(RawBytecodeHelper.I2B, 1, Kind.CONVERT),
/** Convert int to char */
- I2C(ClassFile.I2C, 1, Kind.CONVERT),
+ I2C(RawBytecodeHelper.I2C, 1, Kind.CONVERT),
/** Convert int to short */
- I2S(ClassFile.I2S, 1, Kind.CONVERT),
+ I2S(RawBytecodeHelper.I2S, 1, Kind.CONVERT),
/** Compare long */
- LCMP(ClassFile.LCMP, 1, Kind.OPERATOR),
+ LCMP(RawBytecodeHelper.LCMP, 1, Kind.OPERATOR),
/** Compare float */
- FCMPL(ClassFile.FCMPL, 1, Kind.OPERATOR),
+ FCMPL(RawBytecodeHelper.FCMPL, 1, Kind.OPERATOR),
/** Compare float */
- FCMPG(ClassFile.FCMPG, 1, Kind.OPERATOR),
+ FCMPG(RawBytecodeHelper.FCMPG, 1, Kind.OPERATOR),
/** Compare double */
- DCMPL(ClassFile.DCMPL, 1, Kind.OPERATOR),
+ DCMPL(RawBytecodeHelper.DCMPL, 1, Kind.OPERATOR),
/** Compare double */
- DCMPG(ClassFile.DCMPG, 1, Kind.OPERATOR),
+ DCMPG(RawBytecodeHelper.DCMPG, 1, Kind.OPERATOR),
/** Branch if int comparison with zero succeeds */
- IFEQ(ClassFile.IFEQ, 3, Kind.BRANCH),
+ IFEQ(RawBytecodeHelper.IFEQ, 3, Kind.BRANCH),
/** Branch if int comparison with zero succeeds */
- IFNE(ClassFile.IFNE, 3, Kind.BRANCH),
+ IFNE(RawBytecodeHelper.IFNE, 3, Kind.BRANCH),
/** Branch if int comparison with zero succeeds */
- IFLT(ClassFile.IFLT, 3, Kind.BRANCH),
+ IFLT(RawBytecodeHelper.IFLT, 3, Kind.BRANCH),
/** Branch if int comparison with zero succeeds */
- IFGE(ClassFile.IFGE, 3, Kind.BRANCH),
+ IFGE(RawBytecodeHelper.IFGE, 3, Kind.BRANCH),
/** Branch if int comparison with zero succeeds */
- IFGT(ClassFile.IFGT, 3, Kind.BRANCH),
+ IFGT(RawBytecodeHelper.IFGT, 3, Kind.BRANCH),
/** Branch if int comparison with zero succeeds */
- IFLE(ClassFile.IFLE, 3, Kind.BRANCH),
+ IFLE(RawBytecodeHelper.IFLE, 3, Kind.BRANCH),
/** Branch if int comparison succeeds */
- IF_ICMPEQ(ClassFile.IF_ICMPEQ, 3, Kind.BRANCH),
+ IF_ICMPEQ(RawBytecodeHelper.IF_ICMPEQ, 3, Kind.BRANCH),
/** Branch if int comparison succeeds */
- IF_ICMPNE(ClassFile.IF_ICMPNE, 3, Kind.BRANCH),
+ IF_ICMPNE(RawBytecodeHelper.IF_ICMPNE, 3, Kind.BRANCH),
/** Branch if int comparison succeeds */
- IF_ICMPLT(ClassFile.IF_ICMPLT, 3, Kind.BRANCH),
+ IF_ICMPLT(RawBytecodeHelper.IF_ICMPLT, 3, Kind.BRANCH),
/** Branch if int comparison succeeds */
- IF_ICMPGE(ClassFile.IF_ICMPGE, 3, Kind.BRANCH),
+ IF_ICMPGE(RawBytecodeHelper.IF_ICMPGE, 3, Kind.BRANCH),
/** Branch if int comparison succeeds */
- IF_ICMPGT(ClassFile.IF_ICMPGT, 3, Kind.BRANCH),
+ IF_ICMPGT(RawBytecodeHelper.IF_ICMPGT, 3, Kind.BRANCH),
/** Branch if int comparison succeeds */
- IF_ICMPLE(ClassFile.IF_ICMPLE, 3, Kind.BRANCH),
+ IF_ICMPLE(RawBytecodeHelper.IF_ICMPLE, 3, Kind.BRANCH),
/** Branch if reference comparison succeeds */
- IF_ACMPEQ(ClassFile.IF_ACMPEQ, 3, Kind.BRANCH),
+ IF_ACMPEQ(RawBytecodeHelper.IF_ACMPEQ, 3, Kind.BRANCH),
/** Branch if reference comparison succeeds */
- IF_ACMPNE(ClassFile.IF_ACMPNE, 3, Kind.BRANCH),
+ IF_ACMPNE(RawBytecodeHelper.IF_ACMPNE, 3, Kind.BRANCH),
/** Branch always */
- GOTO(ClassFile.GOTO, 3, Kind.BRANCH),
+ GOTO(RawBytecodeHelper.GOTO, 3, Kind.BRANCH),
/**
* Jump subroutine is discontinued opcode
* @see java.lang.classfile.instruction.DiscontinuedInstruction
*/
- JSR(ClassFile.JSR, 3, Kind.DISCONTINUED_JSR),
+ JSR(RawBytecodeHelper.JSR, 3, Kind.DISCONTINUED_JSR),
/**
* Return from subroutine is discontinued opcode
* @see java.lang.classfile.instruction.DiscontinuedInstruction
*/
- RET(ClassFile.RET, 2, Kind.DISCONTINUED_RET),
+ RET(RawBytecodeHelper.RET, 2, Kind.DISCONTINUED_RET),
/** Access jump table by index and jump */
- TABLESWITCH(ClassFile.TABLESWITCH, -1, Kind.TABLE_SWITCH),
+ TABLESWITCH(RawBytecodeHelper.TABLESWITCH, -1, Kind.TABLE_SWITCH),
/** Access jump table by key match and jump */
- LOOKUPSWITCH(ClassFile.LOOKUPSWITCH, -1, Kind.LOOKUP_SWITCH),
+ LOOKUPSWITCH(RawBytecodeHelper.LOOKUPSWITCH, -1, Kind.LOOKUP_SWITCH),
/** Return int from method */
- IRETURN(ClassFile.IRETURN, 1, Kind.RETURN),
+ IRETURN(RawBytecodeHelper.IRETURN, 1, Kind.RETURN),
/** Return long from method */
- LRETURN(ClassFile.LRETURN, 1, Kind.RETURN),
+ LRETURN(RawBytecodeHelper.LRETURN, 1, Kind.RETURN),
/** Return float from method */
- FRETURN(ClassFile.FRETURN, 1, Kind.RETURN),
+ FRETURN(RawBytecodeHelper.FRETURN, 1, Kind.RETURN),
/** Return double from method */
- DRETURN(ClassFile.DRETURN, 1, Kind.RETURN),
+ DRETURN(RawBytecodeHelper.DRETURN, 1, Kind.RETURN),
/** Return reference from method */
- ARETURN(ClassFile.ARETURN, 1, Kind.RETURN),
+ ARETURN(RawBytecodeHelper.ARETURN, 1, Kind.RETURN),
/** Return void from method */
- RETURN(ClassFile.RETURN, 1, Kind.RETURN),
+ RETURN(RawBytecodeHelper.RETURN, 1, Kind.RETURN),
/** Get static field from class */
- GETSTATIC(ClassFile.GETSTATIC, 3, Kind.FIELD_ACCESS),
+ GETSTATIC(RawBytecodeHelper.GETSTATIC, 3, Kind.FIELD_ACCESS),
/** Set static field in class */
- PUTSTATIC(ClassFile.PUTSTATIC, 3, Kind.FIELD_ACCESS),
+ PUTSTATIC(RawBytecodeHelper.PUTSTATIC, 3, Kind.FIELD_ACCESS),
/** Fetch field from object */
- GETFIELD(ClassFile.GETFIELD, 3, Kind.FIELD_ACCESS),
+ GETFIELD(RawBytecodeHelper.GETFIELD, 3, Kind.FIELD_ACCESS),
/** Set field in object */
- PUTFIELD(ClassFile.PUTFIELD, 3, Kind.FIELD_ACCESS),
+ PUTFIELD(RawBytecodeHelper.PUTFIELD, 3, Kind.FIELD_ACCESS),
/** Invoke instance method; dispatch based on class */
- INVOKEVIRTUAL(ClassFile.INVOKEVIRTUAL, 3, Kind.INVOKE),
+ INVOKEVIRTUAL(RawBytecodeHelper.INVOKEVIRTUAL, 3, Kind.INVOKE),
/**
* Invoke instance method; direct invocation of instance initialization
* methods and methods of the current class and its supertypes
*/
- INVOKESPECIAL(ClassFile.INVOKESPECIAL, 3, Kind.INVOKE),
+ INVOKESPECIAL(RawBytecodeHelper.INVOKESPECIAL, 3, Kind.INVOKE),
/** Invoke a class (static) method */
- INVOKESTATIC(ClassFile.INVOKESTATIC, 3, Kind.INVOKE),
+ INVOKESTATIC(RawBytecodeHelper.INVOKESTATIC, 3, Kind.INVOKE),
/** Invoke interface method */
- INVOKEINTERFACE(ClassFile.INVOKEINTERFACE, 5, Kind.INVOKE),
+ INVOKEINTERFACE(RawBytecodeHelper.INVOKEINTERFACE, 5, Kind.INVOKE),
/** Invoke a dynamically-computed call site */
- INVOKEDYNAMIC(ClassFile.INVOKEDYNAMIC, 5, Kind.INVOKE_DYNAMIC),
+ INVOKEDYNAMIC(RawBytecodeHelper.INVOKEDYNAMIC, 5, Kind.INVOKE_DYNAMIC),
/** Create new object */
- NEW(ClassFile.NEW, 3, Kind.NEW_OBJECT),
+ NEW(RawBytecodeHelper.NEW, 3, Kind.NEW_OBJECT),
/** Create new array */
- NEWARRAY(ClassFile.NEWARRAY, 2, Kind.NEW_PRIMITIVE_ARRAY),
+ NEWARRAY(RawBytecodeHelper.NEWARRAY, 2, Kind.NEW_PRIMITIVE_ARRAY),
/** Create new array of reference */
- ANEWARRAY(ClassFile.ANEWARRAY, 3, Kind.NEW_REF_ARRAY),
+ ANEWARRAY(RawBytecodeHelper.ANEWARRAY, 3, Kind.NEW_REF_ARRAY),
/** Get length of array */
- ARRAYLENGTH(ClassFile.ARRAYLENGTH, 1, Kind.OPERATOR),
+ ARRAYLENGTH(RawBytecodeHelper.ARRAYLENGTH, 1, Kind.OPERATOR),
/** Throw exception or error */
- ATHROW(ClassFile.ATHROW, 1, Kind.THROW_EXCEPTION),
+ ATHROW(RawBytecodeHelper.ATHROW, 1, Kind.THROW_EXCEPTION),
/** Check whether object is of given type */
- CHECKCAST(ClassFile.CHECKCAST, 3, Kind.TYPE_CHECK),
+ CHECKCAST(RawBytecodeHelper.CHECKCAST, 3, Kind.TYPE_CHECK),
/** Determine if object is of given type */
- INSTANCEOF(ClassFile.INSTANCEOF, 3, Kind.TYPE_CHECK),
+ INSTANCEOF(RawBytecodeHelper.INSTANCEOF, 3, Kind.TYPE_CHECK),
/** Enter monitor for object */
- MONITORENTER(ClassFile.MONITORENTER, 1, Kind.MONITOR),
+ MONITORENTER(RawBytecodeHelper.MONITORENTER, 1, Kind.MONITOR),
/** Exit monitor for object */
- MONITOREXIT(ClassFile.MONITOREXIT, 1, Kind.MONITOR),
+ MONITOREXIT(RawBytecodeHelper.MONITOREXIT, 1, Kind.MONITOR),
/** Create new multidimensional array */
- MULTIANEWARRAY(ClassFile.MULTIANEWARRAY, 4, Kind.NEW_MULTI_ARRAY),
+ MULTIANEWARRAY(RawBytecodeHelper.MULTIANEWARRAY, 4, Kind.NEW_MULTI_ARRAY),
/** Branch if reference is null */
- IFNULL(ClassFile.IFNULL, 3, Kind.BRANCH),
+ IFNULL(RawBytecodeHelper.IFNULL, 3, Kind.BRANCH),
/** Branch if reference not null */
- IFNONNULL(ClassFile.IFNONNULL, 3, Kind.BRANCH),
+ IFNONNULL(RawBytecodeHelper.IFNONNULL, 3, Kind.BRANCH),
/** Branch always (wide index) */
- GOTO_W(ClassFile.GOTO_W, 5, Kind.BRANCH),
+ GOTO_W(RawBytecodeHelper.GOTO_W, 5, Kind.BRANCH),
/**
* Jump subroutine (wide index) is discontinued opcode
* @see java.lang.classfile.instruction.DiscontinuedInstruction
*/
- JSR_W(ClassFile.JSR_W, 5, Kind.DISCONTINUED_JSR),
+ JSR_W(RawBytecodeHelper.JSR_W, 5, Kind.DISCONTINUED_JSR),
/** Load int from local variable (wide index) */
- ILOAD_W((ClassFile.WIDE << 8) | ClassFile.ILOAD, 4, Kind.LOAD),
+ ILOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ILOAD, 4, Kind.LOAD),
/** Load long from local variable (wide index) */
- LLOAD_W((ClassFile.WIDE << 8) | ClassFile.LLOAD, 4, Kind.LOAD),
+ LLOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.LLOAD, 4, Kind.LOAD),
/** Load float from local variable (wide index) */
- FLOAD_W((ClassFile.WIDE << 8) | ClassFile.FLOAD, 4, Kind.LOAD),
+ FLOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.FLOAD, 4, Kind.LOAD),
/** Load double from local variable (wide index) */
- DLOAD_W((ClassFile.WIDE << 8) | ClassFile.DLOAD, 4, Kind.LOAD),
+ DLOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.DLOAD, 4, Kind.LOAD),
/** Load reference from local variable (wide index) */
- ALOAD_W((ClassFile.WIDE << 8) | ClassFile.ALOAD, 4, Kind.LOAD),
+ ALOAD_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ALOAD, 4, Kind.LOAD),
/** Store int into local variable (wide index) */
- ISTORE_W((ClassFile.WIDE << 8) | ClassFile.ISTORE, 4, Kind.STORE),
+ ISTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ISTORE, 4, Kind.STORE),
/** Store long into local variable (wide index) */
- LSTORE_W((ClassFile.WIDE << 8) | ClassFile.LSTORE, 4, Kind.STORE),
+ LSTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.LSTORE, 4, Kind.STORE),
/** Store float into local variable (wide index) */
- FSTORE_W((ClassFile.WIDE << 8) | ClassFile.FSTORE, 4, Kind.STORE),
+ FSTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.FSTORE, 4, Kind.STORE),
/** Store double into local variable (wide index) */
- DSTORE_W((ClassFile.WIDE << 8) | ClassFile.DSTORE, 4, Kind.STORE),
+ DSTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.DSTORE, 4, Kind.STORE),
/** Store reference into local variable (wide index) */
- ASTORE_W((ClassFile.WIDE << 8) | ClassFile.ASTORE, 4, Kind.STORE),
+ ASTORE_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.ASTORE, 4, Kind.STORE),
/**
* Return from subroutine (wide index) is discontinued opcode
* @see java.lang.classfile.instruction.DiscontinuedInstruction
*/
- RET_W((ClassFile.WIDE << 8) | ClassFile.RET, 4, Kind.DISCONTINUED_RET),
+ RET_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.RET, 4, Kind.DISCONTINUED_RET),
/** Increment local variable by constant (wide index) */
- IINC_W((ClassFile.WIDE << 8) | ClassFile.IINC, 6, Kind.INCREMENT);
+ IINC_W((RawBytecodeHelper.WIDE << 8) | RawBytecodeHelper.IINC, 6, Kind.INCREMENT);
/**
* Kinds of opcodes.
@@ -1085,13 +1086,13 @@ public static enum Kind {
/**
* {@return the opcode value} For {@linkplain #isWide() wide} pseudo-opcodes, returns the
- * first 2 bytes of the instruction, which are the {@code wide} opcode and the functional
- * local variable opcode, as a U2 value.
+ * first 2 bytes of the instruction, which are the wide opcode {@code 196} ({@code 0xC4})
+ * and the functional opcode, as a U2 value.
*/
public int bytecode() { return bytecode; }
/**
- * {@return true if this is a pseudo-opcode modified by {@code wide}}
+ * {@return true if this is a pseudo-opcode modified by wide opcode}
*
* @see #ILOAD_W
* @see #LLOAD_W
diff --git a/src/java.base/share/classes/java/lang/classfile/TypeAnnotation.java b/src/java.base/share/classes/java/lang/classfile/TypeAnnotation.java
index b6c9aec76a1a3..139c8eef835dc 100644
--- a/src/java.base/share/classes/java/lang/classfile/TypeAnnotation.java
+++ b/src/java.base/share/classes/java/lang/classfile/TypeAnnotation.java
@@ -31,31 +31,10 @@
import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
import jdk.internal.classfile.impl.TargetInfoImpl;
import jdk.internal.classfile.impl.UnboundAttribute;
-
-import static java.lang.classfile.ClassFile.TAT_CAST;
-import static java.lang.classfile.ClassFile.TAT_CLASS_EXTENDS;
-import static java.lang.classfile.ClassFile.TAT_CLASS_TYPE_PARAMETER;
-import static java.lang.classfile.ClassFile.TAT_CLASS_TYPE_PARAMETER_BOUND;
-import static java.lang.classfile.ClassFile.TAT_CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT;
-import static java.lang.classfile.ClassFile.TAT_CONSTRUCTOR_REFERENCE;
-import static java.lang.classfile.ClassFile.TAT_CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT;
-import static java.lang.classfile.ClassFile.TAT_EXCEPTION_PARAMETER;
-import static java.lang.classfile.ClassFile.TAT_FIELD;
-import static java.lang.classfile.ClassFile.TAT_INSTANCEOF;
-import static java.lang.classfile.ClassFile.TAT_LOCAL_VARIABLE;
-import static java.lang.classfile.ClassFile.TAT_METHOD_FORMAL_PARAMETER;
-import static java.lang.classfile.ClassFile.TAT_METHOD_INVOCATION_TYPE_ARGUMENT;
-import static java.lang.classfile.ClassFile.TAT_METHOD_RECEIVER;
-import static java.lang.classfile.ClassFile.TAT_METHOD_REFERENCE;
-import static java.lang.classfile.ClassFile.TAT_METHOD_REFERENCE_TYPE_ARGUMENT;
-import static java.lang.classfile.ClassFile.TAT_METHOD_RETURN;
-import static java.lang.classfile.ClassFile.TAT_METHOD_TYPE_PARAMETER;
-import static java.lang.classfile.ClassFile.TAT_METHOD_TYPE_PARAMETER_BOUND;
-import static java.lang.classfile.ClassFile.TAT_NEW;
-import static java.lang.classfile.ClassFile.TAT_RESOURCE_VARIABLE;
-import static java.lang.classfile.ClassFile.TAT_THROWS;
import jdk.internal.javac.PreviewFeature;
+import static java.lang.classfile.TypeAnnotation.TargetInfo.*;
+
/**
* Models a {@code type_annotation} structure (JVMS {@jvms 4.7.20}). This model
* indicates the annotated type within a declaration or expression and the part
@@ -87,70 +66,70 @@ public sealed interface TypeAnnotation
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
public enum TargetType {
/** For annotations on a class type parameter declaration. */
- CLASS_TYPE_PARAMETER(TAT_CLASS_TYPE_PARAMETER, 1),
+ CLASS_TYPE_PARAMETER(TARGET_CLASS_TYPE_PARAMETER, 1),
/** For annotations on a method type parameter declaration. */
- METHOD_TYPE_PARAMETER(TAT_METHOD_TYPE_PARAMETER, 1),
+ METHOD_TYPE_PARAMETER(TARGET_METHOD_TYPE_PARAMETER, 1),
/** For annotations on the type of an "extends" or "implements" clause. */
- CLASS_EXTENDS(TAT_CLASS_EXTENDS, 2),
+ CLASS_EXTENDS(TARGET_CLASS_EXTENDS, 2),
/** For annotations on a bound of a type parameter of a class. */
- CLASS_TYPE_PARAMETER_BOUND(TAT_CLASS_TYPE_PARAMETER_BOUND, 2),
+ CLASS_TYPE_PARAMETER_BOUND(TARGET_CLASS_TYPE_PARAMETER_BOUND, 2),
/** For annotations on a bound of a type parameter of a method. */
- METHOD_TYPE_PARAMETER_BOUND(TAT_METHOD_TYPE_PARAMETER_BOUND, 2),
+ METHOD_TYPE_PARAMETER_BOUND(TARGET_METHOD_TYPE_PARAMETER_BOUND, 2),
/** For annotations on a field. */
- FIELD(TAT_FIELD, 0),
+ FIELD(TARGET_FIELD, 0),
/** For annotations on a method return type. */
- METHOD_RETURN(TAT_METHOD_RETURN, 0),
+ METHOD_RETURN(TARGET_METHOD_RETURN, 0),
/** For annotations on the method receiver. */
- METHOD_RECEIVER(TAT_METHOD_RECEIVER, 0),
+ METHOD_RECEIVER(TARGET_METHOD_RECEIVER, 0),
/** For annotations on a method parameter. */
- METHOD_FORMAL_PARAMETER(TAT_METHOD_FORMAL_PARAMETER, 1),
+ METHOD_FORMAL_PARAMETER(TARGET_METHOD_FORMAL_PARAMETER, 1),
/** For annotations on a throws clause in a method declaration. */
- THROWS(TAT_THROWS, 2),
+ THROWS(TARGET_THROWS, 2),
/** For annotations on a local variable. */
- LOCAL_VARIABLE(TAT_LOCAL_VARIABLE, -1),
+ LOCAL_VARIABLE(TARGET_LOCAL_VARIABLE, -1),
/** For annotations on a resource variable. */
- RESOURCE_VARIABLE(TAT_RESOURCE_VARIABLE, -1),
+ RESOURCE_VARIABLE(TARGET_RESOURCE_VARIABLE, -1),
/** For annotations on an exception parameter. */
- EXCEPTION_PARAMETER(TAT_EXCEPTION_PARAMETER, 2),
+ EXCEPTION_PARAMETER(TARGET_EXCEPTION_PARAMETER, 2),
/** For annotations on a type test. */
- INSTANCEOF(TAT_INSTANCEOF, 2),
+ INSTANCEOF(TARGET_INSTANCEOF, 2),
/** For annotations on an object creation expression. */
- NEW(TAT_NEW, 2),
+ NEW(TARGET_NEW, 2),
/** For annotations on a constructor reference receiver. */
- CONSTRUCTOR_REFERENCE(TAT_CONSTRUCTOR_REFERENCE, 2),
+ CONSTRUCTOR_REFERENCE(TARGET_CONSTRUCTOR_REFERENCE, 2),
/** For annotations on a method reference receiver. */
- METHOD_REFERENCE(TAT_METHOD_REFERENCE, 2),
+ METHOD_REFERENCE(TARGET_METHOD_REFERENCE, 2),
/** For annotations on a typecast. */
- CAST(TAT_CAST, 3),
+ CAST(TARGET_CAST, 3),
/** For annotations on a type argument of an object creation expression. */
- CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT(TAT_CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT, 3),
+ CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT(TARGET_CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT, 3),
/** For annotations on a type argument of a method call. */
- METHOD_INVOCATION_TYPE_ARGUMENT(TAT_METHOD_INVOCATION_TYPE_ARGUMENT, 3),
+ METHOD_INVOCATION_TYPE_ARGUMENT(TARGET_METHOD_INVOCATION_TYPE_ARGUMENT, 3),
/** For annotations on a type argument of a constructor reference. */
- CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT(TAT_CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT, 3),
+ CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT(TARGET_CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT, 3),
/** For annotations on a type argument of a method reference. */
- METHOD_REFERENCE_TYPE_ARGUMENT(TAT_METHOD_REFERENCE_TYPE_ARGUMENT, 3);
+ METHOD_REFERENCE_TYPE_ARGUMENT(TARGET_METHOD_REFERENCE_TYPE_ARGUMENT, 3);
private final int targetTypeValue;
private final int sizeIfFixed;
@@ -162,6 +141,11 @@ private TargetType(int targetTypeValue, int sizeIfFixed) {
/**
* {@return the target type value}
+ *
+ * @apiNote
+ * {@code TARGET_}-prefixed constants in {@link TargetInfo}, such as {@link
+ * TargetInfo#TARGET_CLASS_TYPE_PARAMETER}, describe the possible return
+ * values of this method.
*/
public int targetTypeValue() {
return targetTypeValue;
@@ -214,6 +198,146 @@ static TypeAnnotation of(TargetInfo targetInfo, List targetPa
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
sealed interface TargetInfo {
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}.
+ */
+ int TARGET_CLASS_TYPE_PARAMETER = 0x00;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
+ */
+ int TARGET_METHOD_TYPE_PARAMETER = 0x01;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#CLASS_EXTENDS CLASS_EXTENDS}.
+ */
+ int TARGET_CLASS_EXTENDS = 0x10;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#CLASS_TYPE_PARAMETER_BOUND
+ * CLASS_TYPE_PARAMETER_BOUND}.
+ */
+ int TARGET_CLASS_TYPE_PARAMETER_BOUND = 0x11;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#METHOD_TYPE_PARAMETER_BOUND
+ * METHOD_TYPE_PARAMETER_BOUND}.
+ */
+ int TARGET_METHOD_TYPE_PARAMETER_BOUND = 0x12;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#FIELD FIELD}.
+ */
+ int TARGET_FIELD = 0x13;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#METHOD_RETURN METHOD_RETURN}.
+ */
+ int TARGET_METHOD_RETURN = 0x14;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#METHOD_RECEIVER METHOD_RECEIVER}.
+ */
+ int TARGET_METHOD_RECEIVER = 0x15;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#METHOD_FORMAL_PARAMETER
+ * METHOD_FORMAL_PARAMETER}.
+ */
+ int TARGET_METHOD_FORMAL_PARAMETER = 0x16;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#THROWS THROWS}.
+ */
+ int TARGET_THROWS = 0x17;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#LOCAL_VARIABLE LOCAL_VARIABLE}.
+ */
+ int TARGET_LOCAL_VARIABLE = 0x40;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#RESOURCE_VARIABLE RESOURCE_VARIABLE}.
+ */
+ int TARGET_RESOURCE_VARIABLE = 0x41;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#EXCEPTION_PARAMETER EXCEPTION_PARAMETER}.
+ */
+ int TARGET_EXCEPTION_PARAMETER = 0x42;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#INSTANCEOF INSTANCEOF}.
+ */
+ int TARGET_INSTANCEOF = 0x43;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#NEW NEW}.
+ */
+ int TARGET_NEW = 0x44;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#CONSTRUCTOR_REFERENCE
+ * CONSTRUCTOR_REFERENCE}.
+ */
+ int TARGET_CONSTRUCTOR_REFERENCE = 0x45;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#METHOD_REFERENCE METHOD_REFERENCE}.
+ */
+ int TARGET_METHOD_REFERENCE = 0x46;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#CAST CAST}.
+ */
+ int TARGET_CAST = 0x47;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}.
+ */
+ int TARGET_CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#METHOD_INVOCATION_TYPE_ARGUMENT
+ * METHOD_INVOCATION_TYPE_ARGUMENT}.
+ */
+ int TARGET_METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}.
+ */
+ int TARGET_CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
+
+ /**
+ * The {@linkplain TargetType#targetTypeValue() value} of type annotation {@linkplain
+ * #targetType target type} {@link TargetType#METHOD_REFERENCE_TYPE_ARGUMENT
+ * METHOD_REFERENCE_TYPE_ARGUMENT}.
+ */
+ int TARGET_METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
+
/**
* {@return the type of the target}
*/
diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/CharacterRangeInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/CharacterRangeInfo.java
index 37abcb027132e..126ba1037cefb 100644
--- a/src/java.base/share/classes/java/lang/classfile/attribute/CharacterRangeInfo.java
+++ b/src/java.base/share/classes/java/lang/classfile/attribute/CharacterRangeInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 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
@@ -24,6 +24,8 @@
*/
package java.lang.classfile.attribute;
+import java.lang.classfile.instruction.CharacterRange;
+
import jdk.internal.classfile.impl.UnboundAttribute;
import jdk.internal.javac.PreviewFeature;
@@ -70,17 +72,17 @@ public sealed interface CharacterRangeInfo
* The value of the flags item describes the kind of range. Multiple flags
* may be set within flags.
*
- *
{@link java.lang.classfile.ClassFile#CRT_STATEMENT} Range is a Statement
+ *
{@link CharacterRange#FLAG_STATEMENT} Range is a Statement
* (except ExpressionStatement), StatementExpression {@jls 14.8}, as well as each
* VariableDeclaratorId = VariableInitializer of
* LocalVariableDeclarationStatement {@jls 14.4} or FieldDeclaration {@jls 8.3} in the
* grammar.
- *
{@link java.lang.classfile.ClassFile#CRT_BLOCK} Range is a Block in the
+ *
{@link CharacterRange#FLAG_BLOCK} Range is a Block in the
* grammar.
- *
{@link java.lang.classfile.ClassFile#CRT_ASSIGNMENT} Range is an assignment
+ *
{@link CharacterRange#FLAG_ASSIGNMENT} Range is an assignment
* expression - Expression1 AssignmentOperator Expression1 in the grammar as
* well as increment and decrement expressions (both prefix and postfix).
- *
{@link java.lang.classfile.ClassFile#CRT_FLOW_CONTROLLER} An expression
+ *
{@link CharacterRange#FLAG_FLOW_CONTROLLER} An expression
* whose value will effect control flow. {@code Flowcon} in the following:
*
{@link java.lang.classfile.ClassFile#CRT_CREATE} New object creation. For
+ *
{@link CharacterRange#FLAG_CREATE} New object creation. For
* example: new Creator.
- *
{@link java.lang.classfile.ClassFile#CRT_BRANCH_TRUE} A condition encoded
+ *
{@link CharacterRange#FLAG_BRANCH_TRUE} A condition encoded
* in the branch instruction immediately contained in the code range for
* this item is not inverted towards the corresponding branch condition in
* the source code. I.e. actual jump occurs if and only if the the source
@@ -119,7 +121,7 @@ public sealed interface CharacterRangeInfo
* if<cond>, ifnonull, ifnull or goto. CRT_BRANCH_TRUE and
* CRT_BRANCH_FALSE are special kinds of entries that can be used to
* determine what branch of a condition was chosen during the runtime.
- *
{@link java.lang.classfile.ClassFile#CRT_BRANCH_FALSE} A condition encoded
+ *
{@link CharacterRange#FLAG_BRANCH_FALSE} A condition encoded
* in the branch instruction immediately contained in the code range for
* this item is inverted towards the corresponding branch condition in the
* source code. I.e. actual jump occurs if and only if the the source code
@@ -134,6 +136,7 @@ public sealed interface CharacterRangeInfo
* All bits of the flags item not assigned above are reserved for future use. They should be set to zero in generated class files and should be ignored by Java virtual machine implementations.
*
* @return the flags
+ * @see CharacterRange#flags()
*/
int flags();
diff --git a/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java b/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java
index 46caa66ef9adf..3415c89174ae9 100644
--- a/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java
+++ b/src/java.base/share/classes/java/lang/classfile/attribute/StackMapFrameInfo.java
@@ -32,7 +32,6 @@
import java.lang.classfile.constantpool.ClassEntry;
import jdk.internal.classfile.impl.StackMapDecoder;
import jdk.internal.classfile.impl.TemporaryConstantPool;
-import static java.lang.classfile.ClassFile.*;
import jdk.internal.javac.PreviewFeature;
/**
@@ -85,8 +84,39 @@ public static StackMapFrameInfo of(Label target,
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
sealed interface VerificationTypeInfo {
+ /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#TOP TOP}. */
+ int ITEM_TOP = 0;
+
+ /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#INTEGER INTEGER}. */
+ int ITEM_INTEGER = 1;
+
+ /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#FLOAT FLOAT}. */
+ int ITEM_FLOAT = 2;
+
+ /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#DOUBLE DOUBLE}. */
+ int ITEM_DOUBLE = 3;
+
+ /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#LONG LONG}. */
+ int ITEM_LONG = 4;
+
+ /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#NULL NULL}. */
+ int ITEM_NULL = 5;
+
+ /** The {@link #tag() tag} for verification type info {@link SimpleVerificationTypeInfo#UNINITIALIZED_THIS UNINITIALIZED_THIS}. */
+ int ITEM_UNINITIALIZED_THIS = 6;
+
+ /** The {@link #tag() tag} for verification type info {@link ObjectVerificationTypeInfo OBJECT}. */
+ int ITEM_OBJECT = 7;
+
+ /** The {@link #tag() tag} for verification type info {@link UninitializedVerificationTypeInfo UNINITIALIZED}. */
+ int ITEM_UNINITIALIZED = 8;
+
/**
* {@return the tag of the type info}
+ *
+ * @apiNote
+ * {@code ITEM_}-prefixed constants in this class, such as {@link #ITEM_TOP}, describe the
+ * possible return values of this method.
*/
int tag();
}
@@ -100,25 +130,25 @@ sealed interface VerificationTypeInfo {
public enum SimpleVerificationTypeInfo implements VerificationTypeInfo {
/** verification type top */
- ITEM_TOP(VT_TOP),
+ TOP(ITEM_TOP),
/** verification type int */
- ITEM_INTEGER(VT_INTEGER),
+ INTEGER(ITEM_INTEGER),
/** verification type float */
- ITEM_FLOAT(VT_FLOAT),
+ FLOAT(ITEM_FLOAT),
/** verification type double */
- ITEM_DOUBLE(VT_DOUBLE),
+ DOUBLE(ITEM_DOUBLE),
/** verification type long */
- ITEM_LONG(VT_LONG),
+ LONG(ITEM_LONG),
/** verification type null */
- ITEM_NULL(VT_NULL),
+ NULL(ITEM_NULL),
/** verification type uninitializedThis */
- ITEM_UNINITIALIZED_THIS(VT_UNINITIALIZED_THIS);
+ UNINITIALIZED_THIS(ITEM_UNINITIALIZED_THIS);
private final int tag;
@@ -134,7 +164,7 @@ public int tag() {
}
/**
- * A stack value for an object type.
+ * A stack value for an object type. Its {@link #tag() tag} is {@value #ITEM_OBJECT}.
*
* @since 22
*/
@@ -173,7 +203,7 @@ default ClassDesc classSymbol() {
}
/**
- * An uninitialized stack value.
+ * An uninitialized stack value. Its {@link #tag() tag} is {@value #ITEM_UNINITIALIZED}.
*
* @since 22
*/
diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java
index c8b74a139280e..d2af4c7c11ae5 100644
--- a/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java
+++ b/src/java.base/share/classes/java/lang/classfile/constantpool/PoolEntry.java
@@ -38,6 +38,57 @@ public sealed interface PoolEntry
LoadableConstantEntry, MemberRefEntry, ModuleEntry, NameAndTypeEntry,
PackageEntry {
+ /** The {@linkplain #tag tag} for {@link ClassEntry CONSTANT_Class} constant kind. */
+ int TAG_CLASS = 7;
+
+ /** The {@linkplain #tag tag} for {@link DoubleEntry CONSTANT_Double} constant kind. */
+ int TAG_DOUBLE = 6;
+
+ /** The {@linkplain #tag tag} for {@link ConstantDynamicEntry CONSTANT_Dynamic} constant kind. */
+ int TAG_DYNAMIC = 17;
+
+ /** The {@linkplain #tag tag} for {@link FieldRefEntry CONSTANT_Fieldref} constant kind. */
+ int TAG_FIELDREF = 9;
+
+ /** The {@linkplain #tag tag} for {@link FloatEntry CONSTANT_Float} constant kind. */
+ int TAG_FLOAT = 4;
+
+ /** The {@linkplain #tag tag} for {@link IntegerEntry CONSTANT_Integer} constant kind. */
+ int TAG_INTEGER = 3;
+
+ /** The {@linkplain #tag tag} for {@link InterfaceMethodRefEntry CONSTANT_InterfaceMethodref} constant kind. */
+ int TAG_INTERFACE_METHODREF = 11;
+
+ /** The {@linkplain #tag tag} for {@link InvokeDynamicEntry CONSTANT_InvokeDynamic} constant kind. */
+ int TAG_INVOKE_DYNAMIC = 18;
+
+ /** The {@linkplain #tag tag} for {@link LongEntry CONSTANT_Long} constant kind. */
+ int TAG_LONG = 5;
+
+ /** The {@linkplain #tag tag} for {@link MethodHandleEntry CONSTANT_MethodHandle} constant kind. */
+ int TAG_METHOD_HANDLE = 15;
+
+ /** The {@linkplain #tag tag} for {@link MethodRefEntry CONSTANT_Methodref} constant kind. */
+ int TAG_METHODREF = 10;
+
+ /** The {@linkplain #tag tag} for {@link MethodTypeEntry CONSTANT_MethodType} constant kind. */
+ int TAG_METHOD_TYPE = 16;
+
+ /** The {@linkplain #tag tag} for {@link ModuleEntry CONSTANT_Module} constant kind. */
+ int TAG_MODULE = 19;
+
+ /** The {@linkplain #tag tag} for {@link NameAndTypeEntry CONSTANT_NameAndType} constant kind. */
+ int TAG_NAME_AND_TYPE = 12;
+
+ /** The {@linkplain #tag tag} for {@link PackageEntry CONSTANT_Package} constant kind. */
+ int TAG_PACKAGE = 20;
+
+ /** The {@linkplain #tag tag} for {@link StringEntry CONSTANT_String} constant kind. */
+ int TAG_STRING = 8;
+
+ /** The {@linkplain #tag tag} for {@link Utf8Entry CONSTANT_Utf8} constant kind. */
+ int TAG_UTF8 = 1;
+
/**
* {@return the constant pool this entry is from}
*/
@@ -45,6 +96,10 @@ public sealed interface PoolEntry
/**
* {@return the constant pool tag that describes the type of this entry}
+ *
+ * @apiNote
+ * {@code TAG_}-prefixed constants in this class, such as {@link #TAG_UTF8},
+ * describe the possible return values of this method.
*/
byte tag();
diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java b/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java
index 89a54caeaf2fe..fca3279cd2228 100644
--- a/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java
+++ b/src/java.base/share/classes/java/lang/classfile/instruction/CharacterRange.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 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
@@ -29,6 +29,7 @@
import java.lang.classfile.CodeModel;
import java.lang.classfile.Label;
import java.lang.classfile.PseudoInstruction;
+import java.lang.classfile.attribute.CharacterRangeInfo;
import java.lang.classfile.attribute.CharacterRangeTableAttribute;
import jdk.internal.classfile.impl.AbstractPseudoInstruction;
import jdk.internal.classfile.impl.BoundCharacterRange;
@@ -45,6 +46,34 @@
@PreviewFeature(feature = PreviewFeature.Feature.CLASSFILE_API)
public sealed interface CharacterRange extends PseudoInstruction
permits AbstractPseudoInstruction.UnboundCharacterRange, BoundCharacterRange {
+
+ /** The bit mask of STATEMENT {@link CharacterRangeInfo} kind. */
+ int FLAG_STATEMENT = 0x0001;
+
+ /** The bit mask of BLOCK {@link CharacterRangeInfo} kind. */
+ int FLAG_BLOCK = 0x0002;
+
+ /** The bit mask of ASSIGNMENT {@link CharacterRangeInfo} kind. */
+ int FLAG_ASSIGNMENT = 0x0004;
+
+ /** The bit mask of FLOW_CONTROLLER {@link CharacterRangeInfo} kind. */
+ int FLAG_FLOW_CONTROLLER = 0x0008;
+
+ /** The bit mask of FLOW_TARGET {@link CharacterRangeInfo} kind. */
+ int FLAG_FLOW_TARGET = 0x0010;
+
+ /** The bit mask of INVOKE {@link CharacterRangeInfo} kind. */
+ int FLAG_INVOKE = 0x0020;
+
+ /** The bit mask of CREATE {@link CharacterRangeInfo} kind. */
+ int FLAG_CREATE = 0x0040;
+
+ /** The bit mask of BRANCH_TRUE {@link CharacterRangeInfo} kind. */
+ int FLAG_BRANCH_TRUE = 0x0080;
+
+ /** The bit mask of BRANCH_FALSE {@link CharacterRangeInfo} kind. */
+ int FLAG_BRANCH_FALSE = 0x0100;
+
/**
* {@return the start of the instruction range}
*/
@@ -75,15 +104,15 @@ public sealed interface CharacterRange extends PseudoInstruction
* A flags word, indicating the kind of range. Multiple flag bits
* may be set. Valid flags include:
*
diff --git a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
index 6031b55a107b2..4a905a3030b9a 100644
--- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
+++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
@@ -1645,7 +1645,7 @@ private void bogusMethod(ClassBuilder clb, Object os) {
clb.withMethodBody("dummy", MTD_void, ACC_STATIC, new Consumer<>() {
@Override
public void accept(CodeBuilder cob) {
- cob.loadConstant(os.toString());
+ cob.ldc(os.toString());
cob.pop();
cob.return_();
}
diff --git a/src/java.base/share/classes/java/lang/invoke/Invokers.java b/src/java.base/share/classes/java/lang/invoke/Invokers.java
index 1f4314f5421d2..9990370ae25b6 100644
--- a/src/java.base/share/classes/java/lang/invoke/Invokers.java
+++ b/src/java.base/share/classes/java/lang/invoke/Invokers.java
@@ -25,6 +25,7 @@
package java.lang.invoke;
+import jdk.internal.invoke.MhUtil;
import jdk.internal.vm.annotation.DontInline;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.Hidden;
@@ -681,16 +682,9 @@ private static NamedFunction getNamedFunction(String name, MethodType type)
}
private static class Lazy {
- private static final MethodHandle MH_asSpreader;
-
- static {
- try {
- MH_asSpreader = IMPL_LOOKUP.findVirtual(MethodHandle.class, "asSpreader",
- MethodType.methodType(MethodHandle.class, Class.class, int.class));
- } catch (ReflectiveOperationException ex) {
- throw newInternalError(ex);
- }
- }
+ private static final MethodHandle MH_asSpreader = MhUtil.findVirtual(
+ IMPL_LOOKUP, MethodHandle.class, "asSpreader",
+ MethodType.methodType(MethodHandle.class, Class.class, int.class));
}
static {
diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java
index edcecce37e05d..104248c27e61a 100644
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -1879,8 +1879,7 @@ void updateForm(Function updater) {
if (oldForm != newForm) {
assert (newForm.customized == null || newForm.customized == this);
newForm.prepare(); // as in MethodHandle.
- UNSAFE.putReference(this, FORM_OFFSET, newForm);
- UNSAFE.fullFence();
+ UNSAFE.putReferenceRelease(this, FORM_OFFSET, newForm); // properly publish newForm
}
} finally {
updateInProgress = false;
diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index 6a73266ae80a4..9e292373f9caf 100644
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -39,7 +39,9 @@
import sun.reflect.misc.ReflectUtil;
import sun.security.util.SecurityConstants;
+import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
+import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
import java.lang.invoke.LambdaForm.BasicType;
import java.lang.invoke.MethodHandleImpl.Intrinsic;
@@ -2242,85 +2244,70 @@ private static ClassFileDumper defaultDumper() {
private static final ClassFileDumper DEFAULT_DUMPER = ClassFileDumper.getInstance(
"jdk.invoke.MethodHandle.dumpClassFiles", "DUMP_CLASS_FILES");
- static class ClassFile {
- final String name; // internal name
- final int accessFlags;
- final byte[] bytes;
- ClassFile(String name, int accessFlags, byte[] bytes) {
- this.name = name;
- this.accessFlags = accessFlags;
- this.bytes = bytes;
+ /**
+ * This method checks the class file version and the structure of `this_class`.
+ * and checks if the bytes is a class or interface (ACC_MODULE flag not set)
+ * that is in the named package.
+ *
+ * @throws IllegalArgumentException if ACC_MODULE flag is set in access flags
+ * or the class is not in the given package name.
+ */
+ static String validateAndFindInternalName(byte[] bytes, String pkgName) {
+ int magic = readInt(bytes, 0);
+ if (magic != ClassFile.MAGIC_NUMBER) {
+ throw new ClassFormatError("Incompatible magic value: " + magic);
}
+ // We have to read major and minor this way as ClassFile API throws IAE
+ // yet we want distinct ClassFormatError and UnsupportedClassVersionError
+ int minor = readUnsignedShort(bytes, 4);
+ int major = readUnsignedShort(bytes, 6);
- static ClassFile newInstanceNoCheck(String name, byte[] bytes) {
- return new ClassFile(name, 0, bytes);
+ if (!VM.isSupportedClassFileVersion(major, minor)) {
+ throw new UnsupportedClassVersionError("Unsupported class file version " + major + "." + minor);
}
- /**
- * This method checks the class file version and the structure of `this_class`.
- * and checks if the bytes is a class or interface (ACC_MODULE flag not set)
- * that is in the named package.
- *
- * @throws IllegalArgumentException if ACC_MODULE flag is set in access flags
- * or the class is not in the given package name.
- */
- static ClassFile newInstance(byte[] bytes, String pkgName) {
- var cf = readClassFile(bytes);
-
- // check if it's in the named package
- int index = cf.name.lastIndexOf('/');
- String pn = (index == -1) ? "" : cf.name.substring(0, index).replace('/', '.');
- if (!pn.equals(pkgName)) {
- throw newIllegalArgumentException(cf.name + " not in same package as lookup class");
- }
- return cf;
+ String name;
+ ClassDesc sym;
+ int accessFlags;
+ try {
+ ClassModel cm = ClassFile.of().parse(bytes);
+ var thisClass = cm.thisClass();
+ name = thisClass.asInternalName();
+ sym = thisClass.asSymbol();
+ accessFlags = cm.flags().flagsMask();
+ } catch (IllegalArgumentException e) {
+ ClassFormatError cfe = new ClassFormatError();
+ cfe.initCause(e);
+ throw cfe;
+ }
+ // must be a class or interface
+ if ((accessFlags & ACC_MODULE) != 0) {
+ throw newIllegalArgumentException("Not a class or interface: ACC_MODULE flag is set");
}
- private static ClassFile readClassFile(byte[] bytes) {
- int magic = readInt(bytes, 0);
- if (magic != 0xCAFEBABE) {
- throw new ClassFormatError("Incompatible magic value: " + magic);
- }
- int minor = readUnsignedShort(bytes, 4);
- int major = readUnsignedShort(bytes, 6);
- if (!VM.isSupportedClassFileVersion(major, minor)) {
- throw new UnsupportedClassVersionError("Unsupported class file version " + major + "." + minor);
- }
-
- String name;
- int accessFlags;
- try {
- ClassModel cm = java.lang.classfile.ClassFile.of().parse(bytes);
- name = cm.thisClass().asInternalName();
- accessFlags = cm.flags().flagsMask();
- } catch (IllegalArgumentException e) {
- ClassFormatError cfe = new ClassFormatError();
- cfe.initCause(e);
- throw cfe;
- }
- // must be a class or interface
- if ((accessFlags & ACC_MODULE) != 0) {
- throw newIllegalArgumentException("Not a class or interface: ACC_MODULE flag is set");
- }
- return new ClassFile(name, accessFlags, bytes);
+ String pn = sym.packageName();
+ if (!pn.equals(pkgName)) {
+ throw newIllegalArgumentException(name + " not in same package as lookup class");
}
- private static int readInt(byte[] bytes, int offset) {
- if ((offset+4) > bytes.length) {
- throw new ClassFormatError("Invalid ClassFile structure");
- }
- return ((bytes[offset] & 0xFF) << 24)
- | ((bytes[offset + 1] & 0xFF) << 16)
- | ((bytes[offset + 2] & 0xFF) << 8)
- | (bytes[offset + 3] & 0xFF);
+ return name;
+ }
+
+ private static int readInt(byte[] bytes, int offset) {
+ if ((offset + 4) > bytes.length) {
+ throw new ClassFormatError("Invalid ClassFile structure");
}
+ return ((bytes[offset] & 0xFF) << 24)
+ | ((bytes[offset + 1] & 0xFF) << 16)
+ | ((bytes[offset + 2] & 0xFF) << 8)
+ | (bytes[offset + 3] & 0xFF);
+ }
- private static int readUnsignedShort(byte[] bytes, int offset) {
- if ((offset+2) > bytes.length) {
- throw new ClassFormatError("Invalid ClassFile structure");
- }
- return ((bytes[offset] & 0xFF) << 8) | (bytes[offset + 1] & 0xFF);
+ private static int readUnsignedShort(byte[] bytes, int offset) {
+ if ((offset+2) > bytes.length) {
+ throw new ClassFormatError("Invalid ClassFile structure");
}
+ return ((bytes[offset] & 0xFF) << 8) | (bytes[offset + 1] & 0xFF);
}
/*
@@ -2334,23 +2321,22 @@ private static int readUnsignedShort(byte[] bytes, int offset) {
* {@code bytes} denotes a class in a different package than the lookup class
*/
private ClassDefiner makeClassDefiner(byte[] bytes) {
- ClassFile cf = ClassFile.newInstance(bytes, lookupClass().getPackageName());
- return new ClassDefiner(this, cf, STRONG_LOADER_LINK, defaultDumper());
+ var internalName = validateAndFindInternalName(bytes, lookupClass().getPackageName());
+ return new ClassDefiner(this, internalName, bytes, STRONG_LOADER_LINK, defaultDumper());
}
/**
* Returns a ClassDefiner that creates a {@code Class} object of a normal class
* from the given bytes. No package name check on the given bytes.
*
- * @param name internal name
+ * @param internalName internal name
* @param bytes class bytes
* @param dumper dumper to write the given bytes to the dumper's output directory
* @return ClassDefiner that defines a normal class of the given bytes.
*/
- ClassDefiner makeClassDefiner(String name, byte[] bytes, ClassFileDumper dumper) {
+ ClassDefiner makeClassDefiner(String internalName, byte[] bytes, ClassFileDumper dumper) {
// skip package name validation
- ClassFile cf = ClassFile.newInstanceNoCheck(name, bytes);
- return new ClassDefiner(this, cf, STRONG_LOADER_LINK, dumper);
+ return new ClassDefiner(this, internalName, bytes, STRONG_LOADER_LINK, dumper);
}
/**
@@ -2368,8 +2354,8 @@ ClassDefiner makeClassDefiner(String name, byte[] bytes, ClassFileDumper dumper)
* {@code bytes} denotes a class in a different package than the lookup class
*/
ClassDefiner makeHiddenClassDefiner(byte[] bytes, ClassFileDumper dumper) {
- ClassFile cf = ClassFile.newInstance(bytes, lookupClass().getPackageName());
- return makeHiddenClassDefiner(cf, false, dumper, 0);
+ var internalName = validateAndFindInternalName(bytes, lookupClass().getPackageName());
+ return makeHiddenClassDefiner(internalName, bytes, false, dumper, 0);
}
/**
@@ -2391,51 +2377,53 @@ ClassDefiner makeHiddenClassDefiner(byte[] bytes, ClassFileDumper dumper) {
private ClassDefiner makeHiddenClassDefiner(byte[] bytes,
boolean accessVmAnnotations,
int flags) {
- ClassFile cf = ClassFile.newInstance(bytes, lookupClass().getPackageName());
- return makeHiddenClassDefiner(cf, accessVmAnnotations, defaultDumper(), flags);
+ var internalName = validateAndFindInternalName(bytes, lookupClass().getPackageName());
+ return makeHiddenClassDefiner(internalName, bytes, accessVmAnnotations, defaultDumper(), flags);
}
/**
* Returns a ClassDefiner that creates a {@code Class} object of a hidden class
* from the given bytes and the given options. No package name check on the given bytes.
*
- * @param name internal name that specifies the prefix of the hidden class
+ * @param internalName internal name that specifies the prefix of the hidden class
* @param bytes class bytes
* @param dumper dumper to write the given bytes to the dumper's output directory
* @return ClassDefiner that defines a hidden class of the given bytes and options.
*/
- ClassDefiner makeHiddenClassDefiner(String name, byte[] bytes, ClassFileDumper dumper) {
+ ClassDefiner makeHiddenClassDefiner(String internalName, byte[] bytes, ClassFileDumper dumper) {
Objects.requireNonNull(dumper);
// skip name and access flags validation
- return makeHiddenClassDefiner(ClassFile.newInstanceNoCheck(name, bytes), false, dumper, 0);
+ return makeHiddenClassDefiner(internalName, bytes, false, dumper, 0);
}
/**
* Returns a ClassDefiner that creates a {@code Class} object of a hidden class
* from the given bytes and the given options. No package name check on the given bytes.
*
- * @param name internal name that specifies the prefix of the hidden class
+ * @param internalName internal name that specifies the prefix of the hidden class
* @param bytes class bytes
* @param flags class options flag mask
* @param dumper dumper to write the given bytes to the dumper's output directory
* @return ClassDefiner that defines a hidden class of the given bytes and options.
*/
- ClassDefiner makeHiddenClassDefiner(String name, byte[] bytes, ClassFileDumper dumper, int flags) {
+ ClassDefiner makeHiddenClassDefiner(String internalName, byte[] bytes, ClassFileDumper dumper, int flags) {
Objects.requireNonNull(dumper);
// skip name and access flags validation
- return makeHiddenClassDefiner(ClassFile.newInstanceNoCheck(name, bytes), false, dumper, flags);
+ return makeHiddenClassDefiner(internalName, bytes, false, dumper, flags);
}
/**
* Returns a ClassDefiner that creates a {@code Class} object of a hidden class
* from the given class file and options.
*
- * @param cf ClassFile
+ * @param internalName internal name
+ * @param bytes Class byte array
* @param flags class option flag mask
* @param accessVmAnnotations true to give the hidden class access to VM annotations
* @param dumper dumper to write the given bytes to the dumper's output directory
*/
- private ClassDefiner makeHiddenClassDefiner(ClassFile cf,
+ private ClassDefiner makeHiddenClassDefiner(String internalName,
+ byte[] bytes,
boolean accessVmAnnotations,
ClassFileDumper dumper,
int flags) {
@@ -2446,27 +2434,12 @@ private ClassDefiner makeHiddenClassDefiner(ClassFile cf,
flags |= ACCESS_VM_ANNOTATIONS;
}
- return new ClassDefiner(this, cf, flags, dumper);
+ return new ClassDefiner(this, internalName, bytes, flags, dumper);
}
- static class ClassDefiner {
- private final Lookup lookup;
- private final String name; // internal name
- private final byte[] bytes;
- private final int classFlags;
- private final ClassFileDumper dumper;
-
- private ClassDefiner(Lookup lookup, ClassFile cf, int flags, ClassFileDumper dumper) {
- assert ((flags & HIDDEN_CLASS) != 0 || (flags & STRONG_LOADER_LINK) == STRONG_LOADER_LINK);
- this.lookup = lookup;
- this.bytes = cf.bytes;
- this.name = cf.name;
- this.classFlags = flags;
- this.dumper = dumper;
- }
-
- String internalName() {
- return name;
+ record ClassDefiner(Lookup lookup, String internalName, byte[] bytes, int classFlags, ClassFileDumper dumper) {
+ ClassDefiner {
+ assert ((classFlags & HIDDEN_CLASS) != 0 || (classFlags & STRONG_LOADER_LINK) == STRONG_LOADER_LINK);
}
Class> defineClass(boolean initialize) {
@@ -2495,7 +2468,7 @@ Class> defineClass(boolean initialize, Object classData) {
Class> c = null;
try {
c = SharedSecrets.getJavaLangAccess()
- .defineClass(loader, lookupClass, name, bytes, pd, initialize, classFlags, classData);
+ .defineClass(loader, lookupClass, internalName, bytes, pd, initialize, classFlags, classData);
assert !isNestmate() || c.getNestHost() == lookupClass.getNestHost();
return c;
} finally {
diff --git a/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java b/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java
index 50ba77d8f96f9..65872e360a73f 100644
--- a/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java
+++ b/src/java.base/share/classes/java/lang/invoke/MutableCallSite.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -26,7 +26,8 @@
package java.lang.invoke;
import java.util.Objects;
-import java.util.concurrent.atomic.AtomicInteger;
+
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
/**
* A {@code MutableCallSite} is a {@link CallSite} whose target variable
@@ -274,11 +275,10 @@ public final MethodHandle dynamicInvoker() {
*/
public static void syncAll(MutableCallSite[] sites) {
if (sites.length == 0) return;
- STORE_BARRIER.lazySet(0);
+ UNSAFE.storeFence();
for (MutableCallSite site : sites) {
Objects.requireNonNull(site); // trigger NPE on first null
}
// FIXME: NYI
}
- private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
}
diff --git a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java
index 2e56d03c6ad89..abdcaf5ae1fa2 100644
--- a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java
+++ b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java
@@ -114,11 +114,18 @@ final class ProxyGenerator {
private static final Method OBJECT_EQUALS_METHOD;
private static final Method OBJECT_TO_STRING_METHOD;
+ private static final String OBJECT_HASH_CODE_SIG;
+ private static final String OBJECT_EQUALS_SIG;
+ private static final String OBJECT_TO_STRING_SIG;
+
static {
try {
OBJECT_HASH_CODE_METHOD = Object.class.getMethod("hashCode");
+ OBJECT_HASH_CODE_SIG = OBJECT_HASH_CODE_METHOD.toShortSignature();
OBJECT_EQUALS_METHOD = Object.class.getMethod("equals", Object.class);
+ OBJECT_EQUALS_SIG = OBJECT_EQUALS_METHOD.toShortSignature();
OBJECT_TO_STRING_METHOD = Object.class.getMethod("toString");
+ OBJECT_TO_STRING_SIG = OBJECT_TO_STRING_METHOD.toShortSignature();
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
@@ -446,9 +453,9 @@ private byte[] generateClassFile() {
* java.lang.Object take precedence over duplicate methods in the
* proxy interfaces.
*/
- addProxyMethod(new ProxyMethod(OBJECT_HASH_CODE_METHOD, "m0"));
- addProxyMethod(new ProxyMethod(OBJECT_EQUALS_METHOD, "m1"));
- addProxyMethod(new ProxyMethod(OBJECT_TO_STRING_METHOD, "m2"));
+ addProxyMethod(new ProxyMethod(OBJECT_HASH_CODE_METHOD, OBJECT_HASH_CODE_SIG, "m0"));
+ addProxyMethod(new ProxyMethod(OBJECT_EQUALS_METHOD, OBJECT_EQUALS_SIG, "m1"));
+ addProxyMethod(new ProxyMethod(OBJECT_TO_STRING_METHOD, OBJECT_TO_STRING_SIG, "m2"));
/*
* Accumulate all of the methods from the proxy interfaces.
@@ -526,7 +533,7 @@ private void addProxyMethod(Method m, Class> fromClass) {
return;
}
}
- sigmethods.add(new ProxyMethod(m, sig, m.getSharedParameterTypes(), returnType,
+ sigmethods.add(new ProxyMethod(m, sig, returnType,
exceptionTypes, fromClass, "m" + proxyMethodCount++));
}
@@ -617,11 +624,11 @@ private void generateLookupAccessor(ClassBuilder clb) {
Label failLabel = cob.newLabel();
ClassEntry mhl = cp.classEntry(CD_MethodHandles_Lookup);
ClassEntry iae = cp.classEntry(CD_IllegalAccessException);
- cob.aload(cob.parameterSlot(0))
+ cob.aload(0)
.invokevirtual(cp.methodRefEntry(mhl, cp.nameAndTypeEntry("lookupClass", MTD_Class)))
.ldc(proxyCE)
.if_acmpne(failLabel)
- .aload(cob.parameterSlot(0))
+ .aload(0)
.invokevirtual(cp.methodRefEntry(mhl, cp.nameAndTypeEntry("hasFullPrivilegeAccess", MTD_boolean)))
.ifeq(failLabel)
.invokestatic(CD_MethodHandles, "lookup", MTD_MethodHandles$Lookup)
@@ -629,7 +636,7 @@ private void generateLookupAccessor(ClassBuilder clb) {
.labelBinding(failLabel)
.new_(iae)
.dup()
- .aload(cob.parameterSlot(0))
+ .aload(0)
.invokevirtual(cp.methodRefEntry(mhl, cp.nameAndTypeEntry("toString", MTD_String)))
.invokespecial(cp.methodRefEntry(iae, exInit))
.athrow()
@@ -650,18 +657,16 @@ private class ProxyMethod {
private final Method method;
private final String shortSignature;
private final Class> fromClass;
- private final Class>[] parameterTypes;
private final Class> returnType;
private final String methodFieldName;
private Class>[] exceptionTypes;
private final FieldRefEntry methodField;
- private ProxyMethod(Method method, String sig, Class>[] parameterTypes,
+ private ProxyMethod(Method method, String sig,
Class> returnType, Class>[] exceptionTypes,
Class> fromClass, String methodFieldName) {
this.method = method;
this.shortSignature = sig;
- this.parameterTypes = parameterTypes;
this.returnType = returnType;
this.exceptionTypes = exceptionTypes;
this.fromClass = fromClass;
@@ -670,14 +675,17 @@ private ProxyMethod(Method method, String sig, Class>[] parameterTypes,
cp.nameAndTypeEntry(methodFieldName, CD_Method));
}
+ private Class>[] parameterTypes() {
+ return method.getSharedParameterTypes();
+ }
+
/**
* Create a new specific ProxyMethod with a specific field name
*
* @param method The method for which to create a proxy
*/
- private ProxyMethod(Method method, String methodFieldName) {
- this(method, method.toShortSignature(),
- method.getSharedParameterTypes(), method.getReturnType(),
+ private ProxyMethod(Method method, String sig, String methodFieldName) {
+ this(method, sig, method.getReturnType(),
method.getSharedExceptionTypes(), method.getDeclaringClass(), methodFieldName);
}
@@ -685,17 +693,18 @@ private ProxyMethod(Method method, String methodFieldName) {
* Generate this method, including the code and exception table entry.
*/
private void generateMethod(ClassBuilder clb) {
- var desc = methodTypeDesc(returnType, parameterTypes);
+ var desc = methodTypeDesc(returnType, parameterTypes());
int accessFlags = (method.isVarArgs()) ? ACC_VARARGS | ACC_PUBLIC | ACC_FINAL
: ACC_PUBLIC | ACC_FINAL;
- var catchList = computeUniqueCatchList(exceptionTypes);
clb.withMethod(method.getName(), desc, accessFlags, mb ->
mb.with(ExceptionsAttribute.of(toClassEntries(cp, List.of(exceptionTypes))))
.withCode(cob -> {
+ var catchList = computeUniqueCatchList(exceptionTypes);
cob.aload(cob.receiverSlot())
.getfield(handlerField)
.aload(cob.receiverSlot())
.getstatic(methodField);
+ Class>[] parameterTypes = parameterTypes();
if (parameterTypes.length > 0) {
// Create an array and fill with the parameters converting primitives to wrappers
cob.loadConstant(parameterTypes.length)
@@ -784,6 +793,7 @@ private void codeFieldInitialization(CodeBuilder cob) {
var cp = cob.constantPool();
codeClassForName(cob, fromClass);
+ Class>[] parameterTypes = parameterTypes();
cob.ldc(method.getName())
.loadConstant(parameterTypes.length)
.anewarray(classCE);
@@ -817,10 +827,14 @@ private void codeFieldInitialization(CodeBuilder cob) {
* loader is anticipated at local variable index 0.
*/
private void codeClassForName(CodeBuilder cob, Class> cl) {
- cob.ldc(cl.getName())
- .iconst_0() // false
- .aload(0)// classLoader
- .invokestatic(classForName);
+ if (cl == Object.class) {
+ cob.ldc(objectCE);
+ } else {
+ cob.ldc(cl.getName())
+ .iconst_0() // false
+ .aload(0)// classLoader
+ .invokestatic(classForName);
+ }
}
@Override
diff --git a/src/java.base/share/classes/java/net/HttpURLConnection.java b/src/java.base/share/classes/java/net/HttpURLConnection.java
index b405fb10a1655..625fd30424eea 100644
--- a/src/java.base/share/classes/java/net/HttpURLConnection.java
+++ b/src/java.base/share/classes/java/net/HttpURLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -373,8 +373,7 @@ protected HttpURLConnection (URL u) {
/**
* Sets whether HTTP redirects (requests with response code 3xx) should
- * be automatically followed by this class. True by default. Applets
- * cannot change this variable.
+ * be automatically followed by this class. True by default.
*
* If there is a security manager, this method first calls
* the security manager's {@code checkSetFactory} method
diff --git a/src/java.base/share/classes/java/net/Socket.java b/src/java.base/share/classes/java/net/Socket.java
index 23c225fbb2d29..309fa7a80d099 100644
--- a/src/java.base/share/classes/java/net/Socket.java
+++ b/src/java.base/share/classes/java/net/Socket.java
@@ -27,6 +27,7 @@
import jdk.internal.event.SocketReadEvent;
import jdk.internal.event.SocketWriteEvent;
+import jdk.internal.invoke.MhUtil;
import sun.security.util.SecurityConstants;
import java.io.InputStream;
@@ -102,14 +103,10 @@
public class Socket implements java.io.Closeable {
private static final VarHandle STATE, IN, OUT;
static {
- try {
- MethodHandles.Lookup l = MethodHandles.lookup();
- STATE = l.findVarHandle(Socket.class, "state", int.class);
- IN = l.findVarHandle(Socket.class, "in", InputStream.class);
- OUT = l.findVarHandle(Socket.class, "out", OutputStream.class);
- } catch (Exception e) {
- throw new InternalError(e);
- }
+ MethodHandles.Lookup l = MethodHandles.lookup();
+ STATE = MhUtil.findVarHandle(l, "state", int.class);
+ IN = MhUtil.findVarHandle(l, "in", InputStream.class);
+ OUT = MhUtil.findVarHandle(l, "out", OutputStream.class);
}
// the underlying SocketImpl, may be null, may be swapped when connecting
diff --git a/src/java.base/share/classes/java/nio/channels/SelectionKey.java b/src/java.base/share/classes/java/nio/channels/SelectionKey.java
index ca6df2a7aa054..79029e6365353 100644
--- a/src/java.base/share/classes/java/nio/channels/SelectionKey.java
+++ b/src/java.base/share/classes/java/nio/channels/SelectionKey.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -25,6 +25,8 @@
package java.nio.channels;
+import jdk.internal.invoke.MhUtil;
+
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
@@ -429,15 +431,9 @@ public final boolean isAcceptable() {
// -- Attachments --
- private static final VarHandle ATTACHMENT;
- static {
- try {
- MethodHandles.Lookup l = MethodHandles.lookup();
- ATTACHMENT = l.findVarHandle(SelectionKey.class, "attachment", Object.class);
- } catch (Exception e) {
- throw new InternalError(e);
- }
- }
+ private static final VarHandle ATTACHMENT = MhUtil.findVarHandle(
+ MethodHandles.lookup(), "attachment", Object.class);
+
private volatile Object attachment;
/**
diff --git a/src/java.base/share/classes/java/nio/channels/spi/AbstractSelectionKey.java b/src/java.base/share/classes/java/nio/channels/spi/AbstractSelectionKey.java
index 0a79ca321dd33..3005fc9522c64 100644
--- a/src/java.base/share/classes/java/nio/channels/spi/AbstractSelectionKey.java
+++ b/src/java.base/share/classes/java/nio/channels/spi/AbstractSelectionKey.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -30,6 +30,7 @@
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
+import jdk.internal.invoke.MhUtil;
import sun.nio.ch.SelectionKeyImpl;
import sun.nio.ch.SelectorImpl;
@@ -46,15 +47,8 @@
public abstract class AbstractSelectionKey
extends SelectionKey
{
- private static final VarHandle INVALID;
- static {
- try {
- MethodHandles.Lookup l = MethodHandles.lookup();
- INVALID = l.findVarHandle(AbstractSelectionKey.class, "invalid", boolean.class);
- } catch (Exception e) {
- throw new InternalError(e);
- }
- }
+ private static final VarHandle INVALID = MhUtil.findVarHandle(
+ MethodHandles.lookup(), "invalid", boolean.class);
/**
* Initializes a new instance of this class.
diff --git a/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java b/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java
index 7ea5f89221834..71dc8620eb804 100644
--- a/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java
+++ b/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java
@@ -32,6 +32,8 @@
import java.nio.channels.Selector;
import java.util.HashSet;
import java.util.Set;
+
+import jdk.internal.invoke.MhUtil;
import sun.nio.ch.Interruptible;
import sun.nio.ch.SelectorImpl;
@@ -72,15 +74,9 @@
public abstract class AbstractSelector
extends Selector
{
- private static final VarHandle CLOSED;
- static {
- try {
- MethodHandles.Lookup l = MethodHandles.lookup();
- CLOSED = l.findVarHandle(AbstractSelector.class, "closed", boolean.class);
- } catch (Exception e) {
- throw new InternalError(e);
- }
- }
+ private static final VarHandle CLOSED = MhUtil.findVarHandle(
+ MethodHandles.lookup(), "closed", boolean.class);
+
private volatile boolean closed;
// The provider that created this selector
diff --git a/src/java.base/share/classes/java/nio/charset/spi/CharsetProvider.java b/src/java.base/share/classes/java/nio/charset/spi/CharsetProvider.java
index 87ff0d07854ef..11d36ee242d56 100644
--- a/src/java.base/share/classes/java/nio/charset/spi/CharsetProvider.java
+++ b/src/java.base/share/classes/java/nio/charset/spi/CharsetProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -36,7 +36,7 @@
* zero-argument constructor and some number of associated charset
* implementation classes. Charset providers may be installed in an instance
* of the Java platform as extensions. Providers may also be made available by
- * adding them to the applet or application class path or by some other
+ * adding them to the application class path or by some other
* platform-specific means. Charset providers are looked up via the current
* thread's {@link java.lang.Thread#getContextClassLoader() context class
* loader}.
diff --git a/src/java.base/share/classes/java/security/Policy.java b/src/java.base/share/classes/java/security/Policy.java
index 838366b7e3862..37f7cc3d9a686 100644
--- a/src/java.base/share/classes/java/security/Policy.java
+++ b/src/java.base/share/classes/java/security/Policy.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -896,5 +896,15 @@ public UnsupportedEmptyCollection() {
@Override public Enumeration elements() {
return perms.elements();
}
+
+ /**
+ * If this object is readonly, no new objects can be added to it using {@code add}.
+ *
+ * @return {@code true} if this object is marked as readonly, {@code false} otherwise.
+ */
+ @Override
+ public boolean isReadOnly() {
+ return perms.isReadOnly();
+ }
}
}
diff --git a/src/java.base/share/classes/java/security/Security.java b/src/java.base/share/classes/java/security/Security.java
index 0cdd22340dfbf..6628b717eb073 100644
--- a/src/java.base/share/classes/java/security/Security.java
+++ b/src/java.base/share/classes/java/security/Security.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -25,22 +25,39 @@
package java.security;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
import java.net.MalformedURLException;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.io.*;
+import java.net.URI;
import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import jdk.internal.access.JavaSecurityPropertiesAccess;
+import jdk.internal.access.SharedSecrets;
import jdk.internal.event.EventHelper;
import jdk.internal.event.SecurityPropertyModificationEvent;
-import jdk.internal.access.SharedSecrets;
import jdk.internal.util.StaticProperty;
+import sun.security.jca.GetInstance;
+import sun.security.jca.ProviderList;
+import sun.security.jca.Providers;
import sun.security.util.Debug;
import sun.security.util.PropertyExpander;
-import sun.security.jca.*;
-
/**
*
This class centralizes all security properties and common security
* methods. One of its primary uses is to manage providers.
@@ -63,7 +80,17 @@ public final class Security {
Debug.getInstance("properties");
/* The java.security properties */
- private static Properties props;
+ private static final Properties props = new Properties() {
+ @Override
+ public synchronized Object put(Object key, Object val) {
+ if (key instanceof String strKey && val instanceof String strVal &&
+ SecPropLoader.isInclude(strKey)) {
+ SecPropLoader.loadInclude(strVal);
+ return null;
+ }
+ return super.put(key, val);
+ }
+ };
/* cache a copy for recording purposes */
private static Properties initialSecurityProperties;
@@ -74,11 +101,220 @@ private static class ProviderProperty {
Provider provider;
}
+ private static final class SecPropLoader {
+ private enum LoadingMode {OVERRIDE, APPEND}
+
+ private static final String OVERRIDE_SEC_PROP =
+ "security.overridePropertiesFile";
+
+ private static final String EXTRA_SYS_PROP =
+ "java.security.properties";
+
+ private static Path currentPath;
+
+ private static final Set activePaths = new HashSet<>();
+
+ static void loadAll() {
+ // first load the master properties file to
+ // determine the value of OVERRIDE_SEC_PROP
+ loadMaster();
+ loadExtra();
+ }
+
+ static boolean isInclude(String key) {
+ return "include".equals(key);
+ }
+
+ static void checkReservedKey(String key)
+ throws IllegalArgumentException {
+ if (isInclude(key)) {
+ throw new IllegalArgumentException("Key '" + key +
+ "' is reserved and cannot be used as a " +
+ "Security property name.");
+ }
+ }
+
+ private static void loadMaster() {
+ try {
+ loadFromPath(Path.of(StaticProperty.javaHome(), "conf",
+ "security", "java.security"), LoadingMode.APPEND);
+ } catch (IOException e) {
+ throw new InternalError("Error loading java.security file", e);
+ }
+ }
+
+ private static void loadExtra() {
+ if ("true".equalsIgnoreCase(props.getProperty(OVERRIDE_SEC_PROP))) {
+ String propFile = System.getProperty(EXTRA_SYS_PROP);
+ if (propFile != null) {
+ LoadingMode mode = LoadingMode.APPEND;
+ if (propFile.startsWith("=")) {
+ mode = LoadingMode.OVERRIDE;
+ propFile = propFile.substring(1);
+ }
+ try {
+ loadExtraHelper(propFile, mode);
+ } catch (Exception e) {
+ if (sdebug != null) {
+ sdebug.println("unable to load security " +
+ "properties from " + propFile);
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+ private static void loadExtraHelper(String propFile, LoadingMode mode)
+ throws Exception {
+ propFile = PropertyExpander.expand(propFile);
+ if (propFile.isEmpty()) {
+ throw new IOException("Empty extra properties file path");
+ }
+
+ // Try to interpret propFile as a path
+ Exception error;
+ if ((error = loadExtraFromPath(propFile, mode)) == null) {
+ return;
+ }
+
+ // Try to interpret propFile as a file URL
+ URI uri = null;
+ try {
+ uri = new URI(propFile);
+ } catch (Exception ignore) {}
+ if (uri != null && "file".equalsIgnoreCase(uri.getScheme()) &&
+ (error = loadExtraFromFileUrl(uri, mode)) == null) {
+ return;
+ }
+
+ // Try to interpret propFile as a URL
+ URL url;
+ try {
+ url = newURL(propFile);
+ } catch (MalformedURLException ignore) {
+ // URL has no scheme: previous error is more accurate
+ throw error;
+ }
+ loadFromUrl(url, mode);
+ }
+
+ private static Exception loadExtraFromPath(String propFile,
+ LoadingMode mode) throws Exception {
+ Path path;
+ try {
+ path = Path.of(propFile);
+ if (!Files.exists(path)) {
+ return new FileNotFoundException(propFile);
+ }
+ } catch (InvalidPathException e) {
+ return e;
+ }
+ loadFromPath(path, mode);
+ return null;
+ }
+
+
+ private static Exception loadExtraFromFileUrl(URI uri, LoadingMode mode)
+ throws Exception {
+ Path path;
+ try {
+ path = Path.of(uri);
+ } catch (Exception e) {
+ return e;
+ }
+ loadFromPath(path, mode);
+ return null;
+ }
+
+ private static void reset(LoadingMode mode) {
+ if (mode == LoadingMode.OVERRIDE) {
+ if (sdebug != null) {
+ sdebug.println(
+ "overriding other security properties files!");
+ }
+ props.clear();
+ }
+ }
+
+ static void loadInclude(String propFile) {
+ String expPropFile = PropertyExpander.expandNonStrict(propFile);
+ if (sdebug != null) {
+ sdebug.println("processing include: '" + propFile + "'" +
+ (propFile.equals(expPropFile) ? "" :
+ " (expanded to '" + expPropFile + "')"));
+ }
+ try {
+ Path path = Path.of(expPropFile);
+ if (!path.isAbsolute()) {
+ if (currentPath == null) {
+ throw new InternalError("Cannot resolve '" +
+ expPropFile + "' relative path when included " +
+ "from a non-regular properties file " +
+ "(e.g. HTTP served file)");
+ }
+ path = currentPath.resolveSibling(path);
+ }
+ loadFromPath(path, LoadingMode.APPEND);
+ } catch (IOException | InvalidPathException e) {
+ throw new InternalError("Unable to include '" + expPropFile +
+ "'", e);
+ }
+ }
+
+ private static void loadFromPath(Path path, LoadingMode mode)
+ throws IOException {
+ boolean isRegularFile = Files.isRegularFile(path);
+ if (isRegularFile) {
+ path = path.toRealPath();
+ } else if (Files.isDirectory(path)) {
+ throw new IOException("Is a directory");
+ } else {
+ path = path.toAbsolutePath();
+ }
+ if (activePaths.contains(path)) {
+ throw new InternalError("Cyclic include of '" + path + "'");
+ }
+ try (InputStream is = Files.newInputStream(path)) {
+ reset(mode);
+ Path previousPath = currentPath;
+ currentPath = isRegularFile ? path : null;
+ activePaths.add(path);
+ try {
+ debugLoad(true, path);
+ props.load(is);
+ debugLoad(false, path);
+ } finally {
+ activePaths.remove(path);
+ currentPath = previousPath;
+ }
+ }
+ }
+
+ private static void loadFromUrl(URL url, LoadingMode mode)
+ throws IOException {
+ try (InputStream is = url.openStream()) {
+ reset(mode);
+ debugLoad(true, url);
+ props.load(is);
+ debugLoad(false, url);
+ }
+ }
+
+ private static void debugLoad(boolean start, Object source) {
+ if (sdebug != null) {
+ int level = activePaths.isEmpty() ? 1 : activePaths.size();
+ sdebug.println((start ?
+ ">".repeat(level) + " starting to process " :
+ "<".repeat(level) + " finished processing ") + source);
+ }
+ }
+ }
+
static {
// doPrivileged here because there are multiple
// things in initialize that might require privs.
- // (the FileInputStream call and the File.exists call,
- // the securityPropFile call, etc)
+ // (the FileInputStream call and the File.exists call, etc)
@SuppressWarnings("removal")
var dummy = AccessController.doPrivileged((PrivilegedAction
*/
@@ -348,11 +349,9 @@ private PassFailJFrame(final Builder builder)
builder.positionWindows
.positionTestWindows(unmodifiableList(builder.testWindows),
builder.instructionUIHandler));
- } else if (builder.testWindows.size() == 1) {
+ } else {
Window window = builder.testWindows.get(0);
positionTestWindow(window, builder.position);
- } else {
- positionTestWindow(null, builder.position);
}
}
showAllWindows();
@@ -501,6 +500,7 @@ private static JTextComponent configurePlainText(String instructions,
JTextArea text = new JTextArea(instructions, rows, columns);
text.setLineWrap(true);
text.setWrapStyleWord(true);
+ text.setBorder(createEmptyBorder(4, 4, 4, 4));
return text;
}
@@ -1111,9 +1111,10 @@ public static void forceFail(String reason) {
/**
* Adds a {@code message} to the log area, if enabled by
- * {@link Builder#logArea()} or {@link Builder#logArea(int)}.
+ * {@link Builder#logArea() logArea()} or
+ * {@link Builder#logArea(int) logArea(int)}.
*
- * @param message to log
+ * @param message the message to log
*/
public static void log(String message) {
System.out.println("PassFailJFrame: " + message);
@@ -1122,7 +1123,8 @@ public static void log(String message) {
/**
* Clears the log area, if enabled by
- * {@link Builder#logArea()} or {@link Builder#logArea(int)}.
+ * {@link Builder#logArea() logArea()} or
+ * {@link Builder#logArea(int) logArea(int)}.
*/
public static void logClear() {
System.out.println("\nPassFailJFrame: log cleared\n");
@@ -1131,7 +1133,9 @@ public static void logClear() {
/**
* Replaces the log area content with provided {@code text}, if enabled by
- * {@link Builder#logArea()} or {@link Builder#logArea(int)}.
+ * {@link Builder#logArea() logArea()} or
+ * {@link Builder#logArea(int) logArea(int)}.
+ *
* @param text new text for the log area
*/
public static void logSet(String text) {
@@ -1182,11 +1186,45 @@ public Builder testTimeOut(long testTimeOut) {
return this;
}
+ /**
+ * Sets the number of rows for displaying the instruction text.
+ * The default value is the number of lines in the text plus 1:
+ * {@code ((int) instructions.lines().count() + 1)}.
+ *
+ * @param rows the number of rows for instruction text
+ * @return this builder
+ */
public Builder rows(int rows) {
this.rows = rows;
return this;
}
+ private int getDefaultRows() {
+ return (int) instructions.lines().count() + 1;
+ }
+
+ /**
+ * Adds a certain number of rows for displaying the instruction text.
+ *
+ * @param rowsAdd the number of rows to add to the number of rows
+ * @return this builder
+ * @see #rows
+ */
+ public Builder rowsAdd(int rowsAdd) {
+ if (rows == 0) {
+ rows = getDefaultRows();
+ }
+ rows += rowsAdd;
+
+ return this;
+ }
+
+ /**
+ * Sets the number of columns for displaying the instruction text.
+ *
+ * @param columns the number of columns for instruction text
+ * @return this builder
+ */
public Builder columns(int columns) {
this.columns = columns;
return this;
@@ -1481,7 +1519,7 @@ private void validate() {
}
if (rows == 0) {
- rows = ROWS;
+ rows = getDefaultRows();
}
if (columns == 0) {
diff --git a/test/jdk/java/lang/Math/HyperbolicTests.java b/test/jdk/java/lang/Math/HyperbolicTests.java
index cf583ed7b5f27..4534396ee06dd 100644
--- a/test/jdk/java/lang/Math/HyperbolicTests.java
+++ b/test/jdk/java/lang/Math/HyperbolicTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -969,6 +969,400 @@ static int testTanh() {
failures += testTanhCaseWithUlpDiff(d, 1.0, 2.5);
}
+ failures += testTanhAdditionalTests();
+
+ return failures;
+ }
+
+ /**
+ * Test accuracy of {Math, StrictMath}.tanh using quad precision
+ * tanh implementation as the reference. There are additional tests.
+ * The specified accuracy is 2.5 ulps.
+ *
+ */
+ static int testTanhAdditionalTests() {
+ int failures = 0;
+ /*
+ * Array elements below are generated using a quad precision tanh
+ * implementation (libquadmath). Rounded to a double, the quad result
+ * *should* be correctly rounded, unless we are quite unlucky.
+ * Assuming the quad value is a correctly rounded double, the
+ * allowed error is 3.0 ulps instead of 2.5 since the quad
+ * value rounded to double can have its own 1/2 ulp error.
+ */
+ double[][] testCases = {
+ // x tanh(x)
+ {1.09951162777600024414062500000000000e+12, 1.00000000000000000000000000000000000e+00},
+ {1.56250000000000416333634234433702659e-02, 1.56237285584089068255495133849899136e-02},
+ {1.61254882812500000000000000000000000e+01, 9.99999999999980293529906376885389048e-01},
+ {2.53165043529127054000582575099542737e-01, 2.47891535884497437358843835970604812e-01},
+ {2.05669906337718799704816774465143681e+00, 9.67821952180774991463712302156014956e-01},
+ {8.73243486124784240587359818164259195e+00, 9.99999947984421044859570034536492937e-01},
+ {1.35302734375000000000000000000000000e+00, 8.74765946489987955543753077657414741e-01},
+ {7.51299319580434721288497712521348149e-01, 6.35923468395323117288273690770900477e-01},
+ {9.53088818012631927567568368431238923e-02, 9.50213381512267711017656118902912332e-02},
+ {7.64443165964961757197215774795040488e-01, 6.43686625696507143760198874608796949e-01},
+ {9.80772770147126660145175947036477737e-02, 9.77640088885469645387119927980991050e-02},
+ {8.00000000000000044408920985006261617e-01, 6.64036770267848988511881426480887109e-01},
+ {6.58800443825626694943631278533757722e-03, 6.58790912948844334160953310959647563e-03},
+ {3.50634723606509357551885841530747712e+00, 9.98200861366828007281302037717336212e-01},
+ {8.80951107580675074615328412619419396e-01, 7.06895478355484050029724917425086249e-01},
+ {9.41693953354077795125931515940465033e-01, 7.35999567964351009171211613664845735e-01},
+ {4.86714106743433794211028953213826753e-01, 4.51604571680788935707314000261162601e-01},
+ {4.99999999970896114032115065128891729e-01, 4.62117157237121073362068671381593592e-01},
+ {1.27999999999999971578290569595992565e+02, 1.00000000000000000000000000000000000e+00},
+ {1.00000000000000022204460492503130808e+00, 7.61594155955764981372495044941331753e-01},
+ {1.09951162777600024414062500000000000e+12, 1.00000000000000000000000000000000000e+00},
+ {5.00000000000000777156117237609578297e-01, 4.62117157260010369694985045764006657e-01},
+ {3.90625000000001474514954580286030250e-03, 3.90623013190635482599726614938805467e-03},
+ {1.56250000000000659194920871186695877e-02, 1.56237285584089311057499113400637264e-02},
+ {1.25000000000001332267629550187848508e-01, 1.24353001771597519720531117125519878e-01},
+ {1.56250000000005169475958410885141348e-02, 1.56237285584093820237573019342883109e-02},
+ {2.00000000000022737367544323205947876e+00, 9.64027580075832948084133680630298643e-01},
+ {6.25000000000080352391407245704613160e-02, 6.24187467475205184231888372622987839e-02},
+ {2.50000000000049737991503207013010979e-01, 2.44918662403755883728363950973251081e-01},
+ {2.50000000000454747350886464118957520e-01, 2.44918662404136598540089724354621762e-01},
+ {7.81250000001537658889105841808486730e-03, 7.81234105817638947180855590780540396e-03},
+ {8.00000000002179945113311987370252609e+00, 9.99999774929675899622836792366347278e-01},
+ {8.00000000002182787284255027770996094e+00, 9.99999774929675899635630557632573807e-01},
+ {1.00000000004506106598967107856879011e+00, 7.61594155974689379640247120538425632e-01},
+ {5.00000000024432678102925819985102862e-01, 4.62117157279224782806433798595181278e-01},
+ {5.00000000124148025193449029757175595e-01, 4.62117157357645691462301850285961295e-01},
+ {1.25000000043655745685100555419921875e-01, 1.24353001814576875736126314329404676e-01},
+ {1.56250130385160446166992187500000000e-02, 1.56237415937421937398207048034470765e-02},
+ {6.25000596046447753906250000000000000e-02, 6.24188061199314157260056878713262148e-02},
+ {6.25001570879248902201652526855468750e-02, 6.24189032234056148184566765458350515e-02},
+ {3.12509536743164062500000000000000000e-02, 3.12407841896026978197614959195842857e-02},
+ {1.00024414062500000000000000000000000e+00, 7.61696669690972358277739369649969500e-01},
+ {1.25091552734375000000000000000000000e-01, 1.24443137738349286849917747910445080e-01},
+ {6.25703578334750876166481248219497502e-02, 6.24888301519391612116796252071905868e-02},
+ {2.52525252525252597024518763646483421e-01, 2.47290965006585965880182136581880733e-01},
+ {1.00000000164410457817454336293394590e-03, 9.99999668310902934017090322313224382e-04},
+ {1.00000000966720672609944209341392707e-03, 9.99999676333997058845099107943491685e-04},
+ {5.13687551499984795810860305209644139e-01, 4.72813376851263299460550751434331149e-01},
+ {1.03125000000000000000000000000000000e+00, 7.74409187434213568286703209738132986e-01},
+ {1.03372912114974835340319714305223897e+00, 7.75399652279487427958938283855319050e-01},
+ {8.73243486124791523650401359191164374e+00, 9.99999947984421044867146689152891277e-01},
+ {5.46364074509520181166521979321260005e-01, 4.97790203319363272413440879555555135e-01},
+ {5.48776992118357842542764046811498702e-01, 4.99603030846724465253358333732665160e-01},
+ {8.62884521484375000000000000000000000e-03, 8.62863106199946057455229821459862778e-03},
+ {5.56840723899044820477399753144709393e-01, 5.05629619734278492036257594911833276e-01},
+ {1.12042968912429174999090264464030042e+00, 8.07718324543002512898290101804260243e-01},
+ {2.80761718750000000000000000000000000e-01, 2.73609921989813966516244201735889906e-01},
+ {4.50982142857161694138312668655999005e+00, 9.99758010610690750512553927515350523e-01},
+ {1.79803946803892764072507759465224808e-02, 1.79784572761372499903768063141254578e-02},
+ {2.90674624105783541150316295897937380e-01, 2.82755618405959946459876962574827861e-01},
+ {3.00000000019552404140199541870970279e-01, 2.91312612469484033539387970973996561e-01},
+ {1.52306844600212459850396840010944288e-01, 1.51139964502163284820786391222343666e-01},
+ {1.21913138136517762433186362613923848e+00, 8.39397762830401796350294214789399315e-01},
+ {1.91612901016097944562055488404439529e-02, 1.91589453912240029886209020645693670e-02},
+ {1.23194037796136601770058405236341059e+00, 8.43141232466373734055029303451281784e-01},
+ {5.14544145441922751160745974630117416e+00, 9.99932120037417992977353814124626761e-01},
+ {1.29608715898613313655118872702587396e+00, 8.60712461444305632100271902930674052e-01},
+ {1.35302734375000000000000000000000000e+00, 8.74765946489987955543753077657414741e-01},
+ {6.89141205308152926534148718928918242e-01, 5.97430012402391408227990740295335202e-01},
+ {2.16702398900134561576802383342510439e-02, 2.16668484172600518601166701940771309e-02},
+ {6.95330121814107471323040954302996397e-01, 6.01395252733578654705526153849150843e-01},
+ {1.70127028180982076566857275068400668e-04, 1.70127026539641570641832179464678521e-04},
+ {6.98731899876564921392230189667316154e-01, 6.03562246839061712657431798989209285e-01},
+ {2.82308042901865396956395670713391155e+00, 9.92962754889608618611084237181745775e-01},
+ {8.85009765625000000000000000000000000e-02, 8.82706391518277914218106043840064600e-02},
+ {1.44086021505376304929768593865446746e+00, 8.93870759190524111186764508137227647e-01},
+ {4.52708479240923750142044923450157512e-02, 4.52399464814195843886615749285771251e-02},
+ {7.42434201630502221824770003877347335e-01, 6.30613596749571014884527941122811076e-01},
+ {7.47314453125000000000000000000000000e-01, 6.33544059591028741704251380359792317e-01},
+ {2.33572976827208893257914468222224968e-02, 2.33530509808936286709795071423335732e-02},
+ {7.51392746195329142011587464367039502e-01, 6.35979110106607807348963004903609067e-01},
+ {7.51649175412362091641682582121575251e-01, 6.36131796640758591543062918907122080e-01},
+ {7.62560692649938864917658065678551793e-01, 6.42582785959772486552828548950126373e-01},
+ {7.64660852335945273594575155584607273e-01, 6.43814099671361386286313072270915932e-01},
+ {1.92871093750000000000000000000000000e-01, 1.90514597602311764623059750704793759e-01},
+ {2.43864313521849479515779535176989157e-02, 2.43815983142663741885939851467013521e-02},
+ {3.97705078125000000000000000000000000e-01, 3.77983627858614640283948547303348236e-01},
+ {7.98034667968750000000000000000000000e-01, 6.62936606884708330125541187161682941e-01},
+ {7.99316406250000000000000000000000000e-01, 6.63654430152659513562528989372441102e-01},
+ {1.99890136718750000000000000000000000e-01, 1.97269734600247465099938891830640889e-01},
+ {2.00000000008910994164779140191967599e-01, 1.97375320233467849151455260287892058e-01},
+ {4.00000000093461316463816501709516160e-01, 3.79948962335194012629557116519596150e-01},
+ {2.00000000069810862646235705142316874e-01, 1.97375320291995240418209079080646997e-01},
+ {1.00000000056612609045103567950718571e-01, 9.96679946810060529704707312198636589e-02},
+ {1.00000000080404896629637789828848327e-01, 9.96679947045619948897444345018478492e-02},
+ {1.66666666666666696272613990004174411e+00, 9.31109608667577693190680177920119455e-01},
+ {1.31034851074218750000000000000000000e-02, 1.31027351970209980614612589861988504e-02},
+ {8.43444227005861080215254332870244980e-01, 6.87629045782656322925865941652078512e-01},
+ {4.25596815032856623517432126391213387e-01, 4.01634947321531793299729470086813678e-01},
+ {8.54614885269050605920426733064232394e-01, 6.93472710492835200064966331725774025e-01},
+ {8.63777419830865200722769259300548583e-01, 6.98198780318331041148483592329099127e-01},
+ {2.70117449276632004551146337689715438e-02, 2.70051772786722224566765342032635559e-02},
+ {2.16282487792377908775165451515931636e-01, 2.12971988592557031781365419455581001e-01},
+ {1.73204653003120601084674490266479552e+00, 9.39297315789076214802641716736658105e-01},
+ {2.71436010781672190650404274947504746e-02, 2.71369367992428389623549774823710978e-02},
+ {8.69092640155437079485523099720012397e-01, 7.00912831250687651307196017605464473e-01},
+ {2.78015136718750000000000000000000000e-02, 2.77943530651526982827985645341156701e-02},
+ {9.10156250000000000000000000000000000e-01, 7.21207240669352050307412688531998165e-01},
+ {2.27787862235060922788676407435559668e-01, 2.23928183342045426304404589794035157e-01},
+ {5.71524498377538048288215577485971153e-02, 5.70903033991663026980553749418981725e-02},
+ {3.66406250000000000000000000000000000e+00, 9.98687254335130669671645868977829517e-01},
+ {5.72863132979952241474741470028675394e-02, 5.72237295373843844708720164610859507e-02},
+ {1.15265335196343660095763539175095502e-01, 1.14757558082362397172277983632352767e-01},
+ {9.22871508732805212460448274214286357e-01, 7.27253018562057912939305739474564638e-01},
+ {1.44882202148437500000000000000000000e-02, 1.44872065663080247568859985337817684e-02},
+ {2.33459472656250000000000000000000000e-01, 2.29308506606965514793638071915067313e-01},
+ {4.67608948699241744328958247933769599e-01, 4.36265367328226513916944408221096440e-01},
+ {2.34375000000000000000000000000000000e-01, 2.30175711032132981819570603563403063e-01},
+ {2.93977526337722387672624080323657836e-02, 2.93892867747176836833509722656208701e-02},
+ {1.89257812500000000000000000000000000e+00, 9.55597542193888546329823463414294394e-01},
+ {2.95798696005085230698039566732404637e-02, 2.95712454656271068251835101101858187e-02},
+ {1.89360756176453159937977943627629429e+00, 9.55686843743833788059988471898348142e-01},
+ {4.74943000289441419337066463413066231e-01, 4.42184502480986035803118250513914071e-01},
+ {4.76562500000000000000000000000000000e-01, 4.43486412595195826790440814160101630e-01},
+ {9.59027831303091549131067949929274619e-01, 7.43842915769532264613887042424467929e-01},
+ {3.09784640940728682456661857713697827e-02, 3.09685582448730820784897541732374591e-02},
+ {1.98437499999999977795539507496869192e+00, 9.62906870975765387287608356129776957e-01},
+ {9.97205648659918675313917901803506538e-01, 7.60418100316000600203658397859135661e-01},
+ {3.90291213989257769131913100579822640e-03, 3.90289232268659551022766662201699736e-03},
+ {3.90481948852539019131913100579822640e-03, 3.90479964225138860483705936617354227e-03},
+ {3.12423706054687500000000000000000000e-02, 3.12322094954161727499363714231262395e-02},
+ {3.90535406768321947598709975579822640e-03, 3.90533421325712750455622728849037270e-03},
+ {7.81154632568359288263826201159645279e-03, 7.81138744204279466358299901763388375e-03},
+ {1.24999789521095569511111023075500270e-01, 1.24352794547462473786771370350680283e-01},
+ {9.99999444341875043384959553804947063e-01, 7.61593922593510941370556728778707492e-01},
+ {9.99999895691871532044103787484345958e-01, 7.61594112149023829770882693858011645e-01},
+ {2.49999998130078865399283927217766177e-01, 2.44918660645955495851244772320875652e-01},
+ {2.49999998603016110321206610933586489e-01, 2.44918661090523528987141309434443089e-01},
+ {4.99999999970896114032115065128891729e-01, 4.62117157237121073362068671381593592e-01},
+ {9.99999999999829358721115113439736888e-01, 7.61594155955693223160706417649502130e-01},
+ {3.12499999999979183318288278314867057e-02, 3.12398314460291771315638233977623908e-02},
+ {6.24999999999973701592104191604448715e-02, 6.24187467475098948954758673929811576e-02},
+ {9.99999999999998556710067987296497449e-01, 7.61594155955764281974719327416526334e-01},
+ {1.27999999999999971578290569595992565e+02, 1.00000000000000000000000000000000000e+00},
+ {3.44827586206896546938693859374325257e-02, 3.44690977543900329082306735053903756e-02},
+ {6.89655172413793093877387718748650514e-02, 6.88563859490195017187269420471893052e-02},
+ {1.03448275862068964081608157812297577e-01, 1.03080829858086020470241143281488892e-01},
+ {1.37931034482758618775477543749730103e-01, 1.37062928881132531260309423128680656e-01},
+ {1.72413793103448287347134737501619384e-01, 1.70725445282084714146447066718646674e-01},
+ {2.06896551724137955918791931253508665e-01, 2.03994088403983264406130799853712156e-01},
+ {2.41379310344827624490449125005397946e-01, 2.36798141876826809207868665407968027e-01},
+ {2.75862068965517293062106318757287227e-01, 2.69071023201531202536913498454407638e-01},
+ {3.10344827586206961633763512509176508e-01, 3.00750767242988858303859696730149916e-01},
+ {3.44827586206896630205420706261065789e-01, 3.31780427497542984412066808006924260e-01},
+ {3.79310344827586298777077900012955070e-01, 3.62108391409330839416919529705937418e-01},
+ {4.13793103448275967348735093764844351e-01, 3.91688608393346163715111892758489641e-01},
+ {4.48275862068965635920392287516733631e-01, 4.20480731486975012003415012347372452e-01},
+ {4.82758620689655304492049481268622912e-01, 4.48450175615929701255698232730127770e-01},
+ {5.17241379310344973063706675020512193e-01, 4.75568097261544496368767486763625886e-01},
+ {5.51724137931034586124212637514574453e-01, 5.01811301809605377924874787743959204e-01},
+ {5.86206896551724199184718600008636713e-01, 5.27162086020673527345538794213535134e-01},
+ {6.20689655172413812245224562502698973e-01, 5.51608023880856575817362987825134405e-01},
+ {6.55172413793103425305730524996761233e-01, 5.75141704579102279221464447290041163e-01},
+ {6.89655172413793038366236487490823492e-01, 5.97760431534850182076591161239096491e-01},
+ {7.24137931034482651426742449984885752e-01, 6.19465891301270655454827665546029664e-01},
+ {7.58620689655172264487248412478948012e-01, 6.40263800834536321750527885396253899e-01},
+ {7.93103448275861877547754374973010272e-01, 6.60163541092833363676687202005166905e-01},
+ {8.27586206896551490608260337467072532e-01, 6.79177784255529339466238655218797135e-01},
+ {8.62068965517241103668766299961134791e-01, 6.97322121077226884958095667604561029e-01},
+ {8.96551724137930716729272262455197051e-01, 7.14614694054361357412620518070189428e-01},
+ {9.31034482758620329789778224949259311e-01, 7.31075841220047215751737025073520835e-01},
+ {9.65517241379309942850284187443321571e-01, 7.46727754527182387965057729340710925e-01},
+ {9.99999999999999555910790149937383831e-01, 7.61594155955764701613384757931622516e-01},
+ {1.26765060022822940149670320537600000e+30, 1.00000000000000000000000000000000000e+00},
+ {1.33436905287182034855574634496000000e+30, 1.00000000000000000000000000000000000e+00},
+ {1.40108750551541129561478948454400000e+30, 1.00000000000000000000000000000000000e+00},
+ {1.46780595815900224267383262412800000e+30, 1.00000000000000000000000000000000000e+00},
+ {1.53452441080259318973287576371200000e+30, 1.00000000000000000000000000000000000e+00},
+ {1.60124286344618413679191890329600000e+30, 1.00000000000000000000000000000000000e+00},
+ {1.66796131608977508385096204288000000e+30, 1.00000000000000000000000000000000000e+00},
+ {1.73467976873336603091000518246400000e+30, 1.00000000000000000000000000000000000e+00},
+ {1.80139822137695697796904832204800000e+30, 1.00000000000000000000000000000000000e+00},
+ {1.86811667402054792502809146163200000e+30, 1.00000000000000000000000000000000000e+00},
+ {1.93483512666413887208713460121600000e+30, 1.00000000000000000000000000000000000e+00},
+ {2.00155357930772981914617774080000000e+30, 1.00000000000000000000000000000000000e+00},
+ {2.06827203195132076620522088038400000e+30, 1.00000000000000000000000000000000000e+00},
+ {2.13499048459491171326426401996800000e+30, 1.00000000000000000000000000000000000e+00},
+ {2.20170893723850266032330715955200000e+30, 1.00000000000000000000000000000000000e+00},
+ {2.26842738988209360738235029913600000e+30, 1.00000000000000000000000000000000000e+00},
+ {2.33514584252568455444139343872000000e+30, 1.00000000000000000000000000000000000e+00},
+ {2.40186429516927550150043657830400000e+30, 1.00000000000000000000000000000000000e+00},
+ {2.46858274781286644855947971788800000e+30, 1.00000000000000000000000000000000000e+00},
+ {2.53530120045645739561852285747200000e+30, 1.00000000000000000000000000000000000e+00},
+ {1.60693804425899027554196209234116260e+60, 1.00000000000000000000000000000000000e+00},
+ {1.69151373079893703825155926128281056e+60, 1.00000000000000000000000000000000000e+00},
+ {1.77608941733888380096115643022445853e+60, 1.00000000000000000000000000000000000e+00},
+ {1.86066510387883056367075359916610649e+60, 1.00000000000000000000000000000000000e+00},
+ {1.94524079041877732638035076810775445e+60, 1.00000000000000000000000000000000000e+00},
+ {2.02981647695872408908994793704940241e+60, 1.00000000000000000000000000000000000e+00},
+ {2.11439216349867085179954510599105038e+60, 1.00000000000000000000000000000000000e+00},
+ {2.19896785003861761450914227493269834e+60, 1.00000000000000000000000000000000000e+00},
+ {2.28354353657856437721873944387434630e+60, 1.00000000000000000000000000000000000e+00},
+ {2.36811922311851113992833661281599426e+60, 1.00000000000000000000000000000000000e+00},
+ {2.45269490965845790263793378175764222e+60, 1.00000000000000000000000000000000000e+00},
+ {2.53727059619840466534753095069929019e+60, 1.00000000000000000000000000000000000e+00},
+ {2.62184628273835142805712811964093815e+60, 1.00000000000000000000000000000000000e+00},
+ {2.70642196927829819076672528858258611e+60, 1.00000000000000000000000000000000000e+00},
+ {2.79099765581824495347632245752423407e+60, 1.00000000000000000000000000000000000e+00},
+ {2.87557334235819171618591962646588203e+60, 1.00000000000000000000000000000000000e+00},
+ {2.96014902889813847889551679540753000e+60, 1.00000000000000000000000000000000000e+00},
+ {3.04472471543808524160511396434917796e+60, 1.00000000000000000000000000000000000e+00},
+ {3.12930040197803200431471113329082592e+60, 1.00000000000000000000000000000000000e+00},
+ {3.21387608851797876702430830223247388e+60, 1.00000000000000000000000000000000000e+00},
+ {1.07150860718626732094842504906000181e+301, 1.00000000000000000000000000000000000e+00},
+ {1.12790379703817606470289337889334663e+301, 1.00000000000000000000000000000000000e+00},
+ {1.18429898689008480845736170872669145e+301, 1.00000000000000000000000000000000000e+00},
+ {1.24069417674199355221183003856003627e+301, 1.00000000000000000000000000000000000e+00},
+ {1.29708936659390229596629836839338109e+301, 1.00000000000000000000000000000000000e+00},
+ {1.35348455644581103972076669822672591e+301, 1.00000000000000000000000000000000000e+00},
+ {1.40987974629771978347523502806007073e+301, 1.00000000000000000000000000000000000e+00},
+ {1.46627493614962852722970335789341555e+301, 1.00000000000000000000000000000000000e+00},
+ {1.52267012600153727098417168772676037e+301, 1.00000000000000000000000000000000000e+00},
+ {1.57906531585344601473864001756010519e+301, 1.00000000000000000000000000000000000e+00},
+ {1.63546050570535475849310834739345001e+301, 1.00000000000000000000000000000000000e+00},
+ {1.69185569555726350224757667722679483e+301, 1.00000000000000000000000000000000000e+00},
+ {1.74825088540917224600204500706013965e+301, 1.00000000000000000000000000000000000e+00},
+ {1.80464607526108098975651333689348447e+301, 1.00000000000000000000000000000000000e+00},
+ {1.86104126511298973351098166672682928e+301, 1.00000000000000000000000000000000000e+00},
+ {1.91743645496489847726544999656017410e+301, 1.00000000000000000000000000000000000e+00},
+ {1.97383164481680722101991832639351892e+301, 1.00000000000000000000000000000000000e+00},
+ {2.03022683466871596477438665622686374e+301, 1.00000000000000000000000000000000000e+00},
+ {2.08662202452062470852885498606020856e+301, 1.00000000000000000000000000000000000e+00},
+ {2.14301721437253345228332331589355338e+301, 1.00000000000000000000000000000000000e+00},
+ {4.94065645841246544176568792868221372e-324, 4.94065645841246544176568792868221372e-324},
+ {4.94065645841246544176568792868221372e-324, 4.94065645841246544176568792868221372e-324},
+ {4.99999999999999944488848768742172979e-01, 4.62117157260009714845699443492203290e-01},
+ {5.00000000000000000000000000000000000e-01, 4.62117157260009758502318483643672557e-01},
+ {5.00000000000000111022302462515654042e-01, 4.62117157260009845815556563946604302e-01},
+ {5.49306144334054669009503868437604979e-01, 4.99999999999999867483910937482244858e-01},
+ {5.49306144334054780031806330953259021e-01, 4.99999999999999950750637784368995452e-01},
+ {5.49306144334054891054108793468913063e-01, 5.00000000000000034017364631255736851e-01},
+ {2.19999999999999964472863211994990706e+01, 9.99999999999999999844377355177323009e-01},
+ {2.20000000000000000000000000000000000e+01, 9.99999999999999999844377355177324068e-01},
+ {2.20000000000000035527136788005009294e+01, 9.99999999999999999844377355177325223e-01},
+ {6.93147180559945397249066445510834455e-01, 6.00000000000000056212373967393698031e-01},
+ {6.93147180559945286226763982995180413e-01, 5.99999999999999985158100391383682202e-01},
+ {6.93147180559945175204461520479526371e-01, 5.99999999999999914103826815373657032e-01},
+ {3.46573590279972698624533222755417228e-01, 3.33333333333333372369704144023402903e-01},
+ {3.46573590279972643113381991497590207e-01, 3.33333333333333323026458605127557235e-01},
+ {3.46573590279972587602230760239763185e-01, 3.33333333333333273683213066231709688e-01},
+ {1.73286795139986349312266611377708614e-01, 1.71572875253809923708199182915954510e-01},
+ {1.73286795139986321556690995748795103e-01, 1.71572875253809896769671427846052946e-01},
+ {1.73286795139986293801115380119881593e-01, 1.71572875253809869831143672776151118e-01},
+ {8.66433975699931746561333056888543069e-02, 8.64272337258898029408455765418952337e-02},
+ {8.66433975699931607783454978743975516e-02, 8.64272337258897891667202185946638536e-02},
+ {8.66433975699931469005576900599407963e-02, 8.64272337258897753925948606474324374e-02},
+ {4.33216987849965873280666528444271535e-02, 4.32946174993891841617996586480128793e-02},
+ {4.33216987849965803891727489371987758e-02, 4.32946174993891772359121833444914284e-02},
+ {4.33216987849965734502788450299703982e-02, 4.32946174993891703100247080409699774e-02},
+ {2.16608493924982936640333264222135767e-02, 2.16574623262262954492383391751347008e-02},
+ {2.16608493924982901945863744685993879e-02, 2.16574623262262919814187163069359478e-02},
+ {2.16608493924982867251394225149851991e-02, 2.16574623262262885135990934387371889e-02},
+ {2.16608493924982867251394225149851991e-02, 2.16574623262262885135990934387371889e-02},
+ {2.16608493924982901945863744685993879e-02, 2.16574623262262919814187163069359478e-02},
+ {2.16608493924982936640333264222135767e-02, 2.16574623262262954492383391751347008e-02},
+ {4.33216987849965734502788450299703982e-02, 4.32946174993891703100247080409699774e-02},
+ {4.33216987849965803891727489371987758e-02, 4.32946174993891772359121833444914284e-02},
+ {4.33216987849965873280666528444271535e-02, 4.32946174993891841617996586480128793e-02},
+ {8.66433975699931469005576900599407963e-02, 8.64272337258897753925948606474324374e-02},
+ {8.66433975699931607783454978743975516e-02, 8.64272337258897891667202185946638536e-02},
+ {8.66433975699931746561333056888543069e-02, 8.64272337258898029408455765418952337e-02},
+ {1.73286795139986293801115380119881593e-01, 1.71572875253809869831143672776151118e-01},
+ {1.73286795139986321556690995748795103e-01, 1.71572875253809896769671427846052946e-01},
+ {1.73286795139986349312266611377708614e-01, 1.71572875253809923708199182915954510e-01},
+ {3.46573590279972587602230760239763185e-01, 3.33333333333333273683213066231709688e-01},
+ {3.46573590279972643113381991497590207e-01, 3.33333333333333323026458605127557235e-01},
+ {3.46573590279972698624533222755417228e-01, 3.33333333333333372369704144023402903e-01},
+ {6.93147180559945175204461520479526371e-01, 5.99999999999999914103826815373657032e-01},
+ {6.93147180559945286226763982995180413e-01, 5.99999999999999985158100391383682202e-01},
+ {6.93147180559945397249066445510834455e-01, 6.00000000000000056212373967393698031e-01},
+ {7.09782712893383859409368596971035004e+02, 1.00000000000000000000000000000000000e+00},
+ {7.09782712893383973096206318587064743e+02, 1.00000000000000000000000000000000000e+00},
+ {7.09782712893384086783044040203094482e+02, 1.00000000000000000000000000000000000e+00},
+ {7.41782712893384086783044040203094482e+02, 1.00000000000000000000000000000000000e+00},
+ {7.41782712893383973096206318587064743e+02, 1.00000000000000000000000000000000000e+00},
+ {7.41782712893383859409368596971035004e+02, 1.00000000000000000000000000000000000e+00},
+ {7.10475860073943749739555642008781433e+02, 1.00000000000000000000000000000000000e+00},
+ {7.10475860073943863426393363624811172e+02, 1.00000000000000000000000000000000000e+00},
+ {7.10475860073943977113231085240840912e+02, 1.00000000000000000000000000000000000e+00},
+ {7.09782712893384086783044040203094482e+02, 1.00000000000000000000000000000000000e+00},
+ {7.09782712893383973096206318587064743e+02, 1.00000000000000000000000000000000000e+00},
+ {7.09782712893383859409368596971035004e+02, 1.00000000000000000000000000000000000e+00},
+ {9.22337203685477478400000000000000000e+18, 1.00000000000000000000000000000000000e+00},
+ {9.22337203685477580800000000000000000e+18, 1.00000000000000000000000000000000000e+00},
+ {9.22337203685477785600000000000000000e+18, 1.00000000000000000000000000000000000e+00},
+ {1.34217727999999985098838806152343750e+08, 1.00000000000000000000000000000000000e+00},
+ {1.34217728000000000000000000000000000e+08, 1.00000000000000000000000000000000000e+00},
+ {1.34217728000000029802322387695312500e+08, 1.00000000000000000000000000000000000e+00},
+ {1.67772159999999981373548507690429688e+07, 1.00000000000000000000000000000000000e+00},
+ {1.67772160000000000000000000000000000e+07, 1.00000000000000000000000000000000000e+00},
+ {1.67772160000000037252902984619140625e+07, 1.00000000000000000000000000000000000e+00},
+ {3.19999999999999964472863211994990706e+01, 9.99999999999999999999999999679237812e-01},
+ {3.20000000000000000000000000000000000e+01, 9.99999999999999999999999999679237812e-01},
+ {3.20000000000000071054273576010018587e+01, 9.99999999999999999999999999679237812e-01},
+ {1.59999999999999982236431605997495353e+01, 9.99999999999974671668901811879331665e-01},
+ {1.60000000000000000000000000000000000e+01, 9.99999999999974671668901811969315927e-01},
+ {1.60000000000000035527136788005009294e+01, 9.99999999999974671668901812149284547e-01},
+ {7.99999999999999911182158029987476766e+00, 9.99999774929675889809619027791781323e-01},
+ {8.00000000000000000000000000000000000e+00, 9.99999774929675889810018832956368404e-01},
+ {8.00000000000000177635683940025046468e+00, 9.99999774929675889810818443285542469e-01},
+ {3.99999999999999955591079014993738383e+00, 9.99329299739067043196741615068852355e-01},
+ {4.00000000000000000000000000000000000e+00, 9.99329299739067043792243344341724993e-01},
+ {4.00000000000000088817841970012523234e+00, 9.99329299739067044983246802887468536e-01},
+ {1.99999999999999977795539507496869192e+00, 9.64027580075816868258779231952432911e-01},
+ {2.00000000000000000000000000000000000e+00, 9.64027580075816883946413724100923171e-01},
+ {2.00000000000000044408920985006261617e+00, 9.64027580075816915321682708397883469e-01},
+ {9.99999999999999888977697537484345958e-01, 7.61594155955764841492939901436512668e-01},
+ {1.00000000000000000000000000000000000e+00, 7.61594155955764888119458282604793657e-01},
+ {1.00000000000000022204460492503130808e+00, 7.61594155955764981372495044941331753e-01},
+ {4.99999999999999944488848768742172979e-01, 4.62117157260009714845699443492203290e-01},
+ {5.00000000000000000000000000000000000e-01, 4.62117157260009758502318483643672557e-01},
+ {5.00000000000000111022302462515654042e-01, 4.62117157260009845815556563946604302e-01},
+ {2.49999999999999972244424384371086489e-01, 2.44918662403709103187147915631612892e-01},
+ {2.50000000000000000000000000000000000e-01, 2.44918662403709129277801131491016945e-01},
+ {2.50000000000000055511151231257827021e-01, 2.44918662403709181459107563209824042e-01},
+ {1.24999999999999986122212192185543245e-01, 1.24353001771596194391460985792144305e-01},
+ {1.25000000000000000000000000000000000e-01, 1.24353001771596208054647275805892707e-01},
+ {1.25000000000000027755575615628913511e-01, 1.24353001771596235381019855833389378e-01},
+ {6.24999999999999930611060960927716224e-02, 6.24187467475125075782836114480350829e-02},
+ {6.25000000000000000000000000000000000e-02, 6.24187467475125144901428911942113317e-02},
+ {6.25000000000000138777878078144567553e-02, 6.24187467475125283138614506865638292e-02},
+ {3.12499999999999965305530480463858112e-02, 3.12398314460312533021176543496182149e-02},
+ {3.12500000000000000000000000000000000e-02, 3.12398314460312567681786791091369499e-02},
+ {3.12500000000000069388939039072283776e-02, 3.12398314460312637003007286281744168e-02},
+ {1.56249999999999982652765240231929056e-02, 1.56237285584088634680488027509294906e-02},
+ {1.56250000000000000000000000000000000e-02, 1.56237285584088652023488311762919065e-02},
+ {1.56250000000000034694469519536141888e-02, 1.56237285584088686709488880270167445e-02},
+ {6.10351562499999932237364219655972875e-05, 6.10351561742087681889301535131725312e-05},
+ {6.10351562500000000000000000000000000e-05, 6.10351561742087749651937063040263414e-05},
+ {6.10351562500000135525271560688054251e-05, 6.10351561742087885177208118857339557e-05},
+ {9.31322574615478412227423430871540641e-10, 9.31322574615478411958158908556102005e-10},
+ {9.31322574615478515625000000000000000e-10, 9.31322574615478515355735477684561274e-10},
+ {9.31322574615478722420153138256918718e-10, 9.31322574615478722150888615941479902e-10},
+ {2.77555756156289104291028806826931429e-17, 2.77555756156289104291028806826931349e-17},
+ {2.77555756156289135105907917022705078e-17, 2.77555756156289135105907917022704998e-17},
+ {2.77555756156289196735666137414252376e-17, 2.77555756156289196735666137414252322e-17},
+ {1.79769313486231570814527423731704357e+308, 1.00000000000000000000000000000000000e+00},
+ {1.79769313486231570814527423731704357e+308, 1.00000000000000000000000000000000000e+00},
+ {1.79769313486231570814527423731704357e+308, 1.00000000000000000000000000000000000e+00},
+ {1.79769313486231550856124328384506240e+308, 1.00000000000000000000000000000000000e+00},
+ {3.14159265358979311599796346854418516e+00, 9.96272076220749943353314537833579484e-01},
+ {1.57079632679489655799898173427209258e+00, 9.17152335667274336647462811870662140e-01},
+ {1.00000000000000022204460492503130808e+00, 7.61594155955764981372495044941331753e-01},
+ {1.00000000000000000000000000000000000e+00, 7.61594155955764888119458282604793657e-01},
+ {9.99999999999999888977697537484345958e-01, 7.61594155955764841492939901436512668e-01},
+ {7.85398163397448278999490867136046290e-01, 6.55794202632672418203926030568705821e-01},
+ {2.22507385850720187715587855857894824e-308, 2.22507385850720187715587855857894824e-308},
+ {2.22507385850720138309023271733240406e-308, 2.22507385850720138309023271733240406e-308},
+ {2.22507385850720088902458687608585989e-308, 2.22507385850720088902458687608585989e-308},
+ {2.22507385850720039495894103483931571e-308, 2.22507385850720039495894103483931571e-308},
+ {9.88131291682493088353137585736442745e-324, 9.88131291682493088353137585736442745e-324},
+ {4.94065645841246544176568792868221372e-324, 4.94065645841246544176568792868221372e-324},
+ };
+
+ for (int i = 0; i < testCases.length; i++) {
+ double[] testCase = testCases[i];
+ failures += testTanhCaseWithUlpDiff(testCase[0],
+ testCase[1],
+ 3.0);
+ }
+
return failures;
}
diff --git a/test/jdk/java/lang/invoke/TestLambdaFormCustomization.java b/test/jdk/java/lang/invoke/TestLambdaFormCustomization.java
new file mode 100644
index 0000000000000..60ba4af590e78
--- /dev/null
+++ b/test/jdk/java/lang/invoke/TestLambdaFormCustomization.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+
+/**
+ * @test
+ * @bug 8340812
+ * @summary Verify that LambdaForm customization via MethodHandle::updateForm is thread safe.
+ * @run main TestLambdaFormCustomization
+ * @run main/othervm -Djava.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD=0 TestLambdaFormCustomization
+ */
+public class TestLambdaFormCustomization {
+
+ String str = "test";
+ static final String value = "test" + 42;
+
+ // Trigger concurrent LambdaForm customization for VarHandle invokers
+ void test() throws NoSuchFieldException, IllegalAccessException {
+ VarHandle varHandle = MethodHandles.lookup().in(getClass()).findVarHandle(getClass(), "str", String.class);
+
+ ArrayList threads = new ArrayList<>();
+ for (int threadIdx = 0; threadIdx < 10; threadIdx++) {
+ threads.add(new Thread(() -> {
+ for (int i = 0; i < 1000; i++) {
+ varHandle.compareAndExchange(this, value, value);
+ varHandle.compareAndExchange(this, value, value);
+ varHandle.compareAndExchange(this, value, value);
+ }
+ }));
+ }
+ threads.forEach(Thread::start);
+ threads.forEach(t -> {
+ try {
+ t.join();
+ } catch (Throwable e) {
+ throw new IllegalStateException(e);
+ }
+ });
+ }
+
+ public static void main(String[] args) throws Exception {
+ TestLambdaFormCustomization t = new TestLambdaFormCustomization();
+ for (int i = 0; i < 4000; ++i) {
+ t.test();
+ }
+ }
+}
diff --git a/test/jdk/java/net/InetAddress/ptr/Lookup.java b/test/jdk/java/net/InetAddress/ptr/Lookup.java
index 79c53190c24d0..1248916023ec0 100644
--- a/test/jdk/java/net/InetAddress/ptr/Lookup.java
+++ b/test/jdk/java/net/InetAddress/ptr/Lookup.java
@@ -114,6 +114,9 @@ public static void main(String args[]) throws IOException {
// Now check that a reverse lookup will succeed with the dual stack.
InetAddress ia = InetAddress.getByName(addr);
String name = ia.getHostName();
+ // output details of dual stack lookup by address
+ System.out.println("dual stack lookup for addr " + addr + " returned IP address " + ia);
+ System.out.println(" with hostname " + name);
System.out.println("(default) " + addr + "--> " + name
+ " (reversed IPv4: " + ipv4Reversed + ")");
diff --git a/test/jdk/java/net/ipv6tests/Tests.java b/test/jdk/java/net/ipv6tests/Tests.java
index 398a3e716936c..7a6917a60382f 100644
--- a/test/jdk/java/net/ipv6tests/Tests.java
+++ b/test/jdk/java/net/ipv6tests/Tests.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -123,7 +123,8 @@ public static void datagramEcho (DatagramSocket s1, DatagramSocket s2,
}
dprintln ("dest2 = " + dest2);
-
+ dprintln ("sender endpoint = " + s1.getLocalSocketAddress());
+ dprintln ("echo endpoint = " + s2.getLocalSocketAddress());
DatagramPacket r1 = new DatagramPacket (new byte[256], 256);
DatagramPacket r2 = new DatagramPacket (new byte[256], 256);
diff --git a/test/jdk/java/nio/file/Files/Links.java b/test/jdk/java/nio/file/Files/Links.java
index a87647e08a639..23059b0829abb 100644
--- a/test/jdk/java/nio/file/Files/Links.java
+++ b/test/jdk/java/nio/file/Files/Links.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4313887 6838333 6863864
+ * @bug 4313887 6838333 6863864 8340329
* @summary Unit test for java.nio.file.Files createSymbolicLink,
* readSymbolicLink, and createLink methods
* @library ..
@@ -45,7 +45,7 @@ static void assertTrue(boolean okay) {
}
/**
- * Exercise createSymbolicLink and readLink methods
+ * Exercise createSymbolicLink and readSymbolicLink methods
*/
static void testSymLinks(Path dir) throws IOException {
final Path link = dir.resolve("link");
@@ -131,6 +131,27 @@ static void testSymLinks(Path dir) throws IOException {
Files.deleteIfExists(mydir);
Files.deleteIfExists(link);
}
+
+ // Check message of NotLinkException
+ try {
+ Files.createDirectory(mydir);
+
+ try {
+ Path mytarget = Files.readSymbolicLink(mydir);
+ } catch (NotLinkException expected) {
+ String filename = mydir.getFileName().toString();
+ String message = expected.getMessage();
+ boolean okay = message.contains(filename);
+ if (!okay) {
+ System.err.println("Message \"" + message + "\"" +
+ " does not contain the filename \"" +
+ filename + "\"");
+ assertTrue(okay);
+ }
+ }
+ } finally {
+ Files.deleteIfExists(mydir);
+ }
}
/**
diff --git a/test/jdk/java/security/Security/ConfigFileTest.java b/test/jdk/java/security/Security/ConfigFileTest.java
index b9264b937ec74..caf657005e1ba 100644
--- a/test/jdk/java/security/Security/ConfigFileTest.java
+++ b/test/jdk/java/security/Security/ConfigFileTest.java
@@ -21,155 +21,907 @@
* questions.
*/
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpServer;
import jdk.test.lib.Utils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.util.FileUtils;
+import sun.net.www.ParseUtil;
+import java.io.Closeable;
import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
import java.io.UncheckedIOException;
-import java.nio.file.*;
-
-import java.security.Provider;
+import java.lang.reflect.Method;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.nio.CharBuffer;
+import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
import java.security.Security;
+import java.time.Instant;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
-import java.util.Optional;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Stream;
/*
* @test
- * @summary Throw error if default java.security file is missing
- * @bug 8155246 8292297 8292177 8281658
+ * @summary Tests security properties passed through java.security,
+ * java.security.properties or included from other properties files.
+ * @bug 8155246 8292297 8292177 8281658 8319332
+ * @modules java.base/sun.net.www
* @library /test/lib
* @run main ConfigFileTest
*/
+
public class ConfigFileTest {
+ static final String SEPARATOR_THIN = "----------------------------";
+
+ private static void printTestHeader(String testName) {
+ System.out.println();
+ System.out.println(SEPARATOR_THIN);
+ System.out.println(testName);
+ System.out.println(SEPARATOR_THIN);
+ System.out.println();
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (args.length == 1 && Executor.RUNNER_ARG.equals(args[0])) {
+ // Executed by a test-launched JVM.
+ // Force the initialization of java.security.Security.
+ Security.getProviders();
+ Security.setProperty("postInitTest", "shouldNotRecord");
+ System.out.println(FilesManager.LAST_FILE_PROP_NAME + ": " +
+ Security.getProperty(FilesManager.LAST_FILE_PROP_NAME));
+ assertTestSecuritySetPropertyShouldNotInclude();
+ } else {
+ // Executed by the test JVM.
+ try (FilesManager filesMgr = new FilesManager()) {
+ for (Method m : ConfigFileTest.class.getDeclaredMethods()) {
+ if (m.getName().startsWith("test")) {
+ printTestHeader(m.getName());
+ Executor.run(m, filesMgr);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Success cases
+ */
+
+ static void testShowSettings(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ // Sanity test passing the -XshowSettings:security option.
+ ex.addJvmArg("-XshowSettings:security");
+ ex.setMasterFile(filesMgr.newMasterFile());
+ ex.assertSuccess();
+ ex.getOutputAnalyzer()
+ .shouldContain("Security properties:")
+ .shouldContain("Security provider static configuration:")
+ .shouldContain("Security TLS configuration");
+ }
- private static final String EXPECTED_DEBUG_OUTPUT =
- "Initial security property: crypto.policy=unlimited";
+ static void testIncludeBasic(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ PropsFile masterFile = filesMgr.newMasterFile();
+ ExtraPropsFile extraFile = filesMgr.newExtraFile();
+ PropsFile file0 = filesMgr.newFile("file0.properties");
+ PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
+ PropsFile file2 = filesMgr.newFile("dir1/dir2/file2.properties");
- private static final String UNEXPECTED_DEBUG_OUTPUT =
- "Initial security property: postInitTest=shouldNotRecord";
+ masterFile.addAbsoluteInclude(file0);
+ extraFile.addRelativeInclude(file2);
+ file2.addAbsoluteInclude(file1);
- private static boolean overrideDetected = false;
+ ex.setMasterFile(masterFile);
+ ex.setExtraFile(extraFile, Executor.ExtraMode.FILE_URI, false);
+ ex.assertSuccess();
+ }
- private static Path COPY_JDK_DIR = Path.of("./jdk-8155246-tmpdir");
- private static Path COPIED_JAVA = COPY_JDK_DIR.resolve("bin", "java");
+ static void testRepeatedInclude(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ PropsFile masterFile = filesMgr.newMasterFile();
+ PropsFile file0 = filesMgr.newFile("file0.properties");
+ PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
- public static void main(String[] args) throws Exception {
- Path copyJdkDir = Path.of("./jdk-8155246-tmpdir");
- Path copiedJava = Optional.of(
- Path.of(copyJdkDir.toString(), "bin", "java"))
- .orElseThrow(() -> new RuntimeException("Unable to locate new JDK")
- );
-
- if (args.length == 1) {
- // set up is complete. Run code to exercise loading of java.security
- Provider[] provs = Security.getProviders();
- Security.setProperty("postInitTest", "shouldNotRecord");
- System.out.println(Arrays.toString(provs) + "NumProviders: " + provs.length);
+ masterFile.addAbsoluteInclude(file0);
+ masterFile.addAbsoluteInclude(file1);
+ masterFile.addAbsoluteInclude(file0);
+ file1.addRelativeInclude(file0);
+
+ ex.setMasterFile(masterFile);
+ ex.assertSuccess();
+ }
+
+ static void testIncludeWithOverrideAll(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ PropsFile masterFile = filesMgr.newMasterFile();
+ ExtraPropsFile extraFile = filesMgr.newExtraFile();
+ PropsFile file0 = filesMgr.newFile("file0.properties");
+ PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
+
+ masterFile.addRelativeInclude(file0);
+ extraFile.addAbsoluteInclude(file1);
+
+ ex.setMasterFile(masterFile);
+ ex.setExtraFile(extraFile, Executor.ExtraMode.HTTP_SERVED, true);
+ ex.assertSuccess();
+ }
+
+ static void extraPropertiesByHelper(Executor ex, FilesManager filesMgr,
+ Executor.ExtraMode mode) throws Exception {
+ ExtraPropsFile extraFile = filesMgr.newExtraFile();
+ PropsFile file0 = filesMgr.newFile("file0.properties");
+
+ extraFile.addRelativeInclude(file0);
+
+ ex.setMasterFile(filesMgr.newMasterFile());
+ ex.setExtraFile(extraFile, mode, true);
+ ex.assertSuccess();
+ }
+
+ static void testExtraPropertiesByPathAbsolute(Executor ex,
+ FilesManager filesMgr) throws Exception {
+ extraPropertiesByHelper(ex, filesMgr, Executor.ExtraMode.PATH_ABS);
+ }
+
+ static void testExtraPropertiesByPathRelative(Executor ex,
+ FilesManager filesMgr) throws Exception {
+ extraPropertiesByHelper(ex, filesMgr, Executor.ExtraMode.PATH_REL);
+ }
+
+ static void specialCharsIncludes(Executor ex, FilesManager filesMgr,
+ char specialChar, Executor.ExtraMode extraMode,
+ boolean useRelativeIncludes) throws Exception {
+ String suffix = specialChar + ".properties";
+ ExtraPropsFile extraFile;
+ PropsFile file0, file1;
+ try {
+ extraFile = filesMgr.newExtraFile("extra" + suffix);
+ file0 = filesMgr.newFile("file0" + suffix);
+ file1 = filesMgr.newFile("file1" + suffix);
+ } catch (InvalidPathException ipe) {
+ // The platform encoding may not allow to create files with some
+ // special characters. Skip the test in these cases.
+ return;
+ }
+
+ if (useRelativeIncludes) {
+ extraFile.addRelativeInclude(file0);
} else {
- Files.createDirectory(copyJdkDir);
- Path jdkTestDir = Path.of(Optional.of(System.getProperty("test.jdk"))
- .orElseThrow(() -> new RuntimeException("Couldn't load JDK Test Dir"))
- );
-
- copyJDK(jdkTestDir, copyJdkDir);
- String extraPropsFile = Path.of(System.getProperty("test.src"), "override.props").toString();
-
- // sanity test -XshowSettings:security option
- exerciseShowSettingsSecurity(buildCommand("-cp", System.getProperty("test.classes"),
- "-Djava.security.debug=all", "-XshowSettings:security", "ConfigFileTest", "runner"));
-
- // exercise some debug flags while we're here
- // regular JDK install - should expect success
- exerciseSecurity(0, "java",
- buildCommand("-cp", System.getProperty("test.classes"),
- "-Djava.security.debug=all", "-Djavax.net.debug=all", "ConfigFileTest", "runner"));
-
- // given an overriding security conf file that doesn't exist, we shouldn't
- // overwrite the properties from original/master security conf file
- exerciseSecurity(0, "SUN version",
- buildCommand("-cp", System.getProperty("test.classes"),
- "-Djava.security.debug=all", "-Djavax.net.debug=all",
- "-Djava.security.properties==file:///" + extraPropsFile + "badFileName",
- "ConfigFileTest", "runner"));
-
- // test JDK launch with customized properties file
- exerciseSecurity(0, "NumProviders: 6",
- buildCommand("-cp", System.getProperty("test.classes"),
- "-Djava.security.debug=all", "-Djavax.net.debug=all",
- "-Djava.security.properties==file:///" + extraPropsFile,
- "ConfigFileTest", "runner"));
-
- // delete the master conf file
- Files.delete(Path.of(copyJdkDir.toString(), "conf",
- "security","java.security"));
-
- // launch JDK without java.security file being present or specified
- exerciseSecurity(1, "Error loading java.security file",
- buildCommand("-cp", System.getProperty("test.classes"),
- "-Djava.security.debug=all", "-Djavax.net.debug=all",
- "ConfigFileTest", "runner"));
-
- // test the override functionality also. Should not be allowed since
- // "security.overridePropertiesFile=true" Security property is missing.
- exerciseSecurity(1, "Error loading java.security file",
- buildCommand("-cp", System.getProperty("test.classes"),
- "-Djava.security.debug=all", "-Djavax.net.debug=all",
- "-Djava.security.properties==file:///" + extraPropsFile, "ConfigFileTest", "runner"));
-
- if (!overrideDetected) {
- throw new RuntimeException("Override scenario not seen");
+ extraFile.addAbsoluteInclude(file0);
+ }
+ extraFile.addAbsoluteInclude(file1);
+
+ ex.setMasterFile(filesMgr.newMasterFile());
+ ex.setExtraFile(extraFile, extraMode, false);
+ ex.assertSuccess();
+ }
+
+ static void testUnicodeIncludes1(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ specialCharsIncludes(ex, filesMgr, '\u2022',
+ Executor.ExtraMode.PATH_ABS, true);
+ }
+
+ static void testUnicodeIncludes2(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ specialCharsIncludes(ex, filesMgr, '\u2022',
+ Executor.ExtraMode.FILE_URI, true);
+ }
+
+ static void testUnicodeIncludes3(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ // Backward compatibility check. Malformed URLs such as
+ // file:/tmp/extra•.properties are supported for the extra file.
+ // However, relative includes are not allowed in these cases.
+ specialCharsIncludes(ex, filesMgr, '\u2022',
+ Executor.ExtraMode.RAW_FILE_URI1, false);
+ }
+
+ static void testUnicodeIncludes4(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ // Backward compatibility check. Malformed URLs such as
+ // file:///tmp/extra•.properties are supported for the extra file.
+ // However, relative includes are not allowed in these cases.
+ specialCharsIncludes(ex, filesMgr, '\u2022',
+ Executor.ExtraMode.RAW_FILE_URI2, false);
+ }
+
+ static void testSpaceIncludes1(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ specialCharsIncludes(ex, filesMgr, ' ',
+ Executor.ExtraMode.PATH_ABS, true);
+ }
+
+ static void testSpaceIncludes2(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ specialCharsIncludes(ex, filesMgr, ' ',
+ Executor.ExtraMode.FILE_URI, true);
+ }
+
+ static void testSpaceIncludes3(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ // Backward compatibility check. Malformed URLs such as
+ // file:/tmp/extra .properties are supported for the extra file.
+ // However, relative includes are not allowed in these cases.
+ specialCharsIncludes(ex, filesMgr, ' ',
+ Executor.ExtraMode.RAW_FILE_URI1, false);
+ }
+
+ static void testSpaceIncludes4(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ // Backward compatibility check. Malformed URLs such as
+ // file:///tmp/extra .properties are supported for the extra file.
+ // However, relative includes are not allowed in these cases.
+ specialCharsIncludes(ex, filesMgr, ' ',
+ Executor.ExtraMode.RAW_FILE_URI2, false);
+ }
+
+ static void notOverrideOnFailureHelper(Executor ex, FilesManager filesMgr,
+ String nonExistentExtraFile) throws Exception {
+ // An overriding extra properties file that does not exist
+ // should not erase properties from the master file.
+ ex.setIgnoredExtraFile(nonExistentExtraFile, true);
+ ex.setMasterFile(filesMgr.newMasterFile());
+ ex.assertSuccess();
+ ex.getOutputAnalyzer().shouldContain("unable to load security " +
+ "properties from " + nonExistentExtraFile);
+ }
+
+ static void testNotOverrideOnEmptyFailure(Executor ex,
+ FilesManager filesMgr) throws Exception {
+ notOverrideOnFailureHelper(ex, filesMgr, "");
+ ex.getOutputAnalyzer()
+ .shouldContain("Empty extra properties file path");
+ }
+
+ static void testNotOverrideOnURLFailure(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ notOverrideOnFailureHelper(ex, filesMgr,
+ "file:///nonExistentFile.properties");
+ }
+
+ static void testNotOverrideOnPathFailure(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ notOverrideOnFailureHelper(ex, filesMgr, "nonExistentFile.properties");
+ }
+
+ static void testNotOverrideOnDirFailure(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ notOverrideOnFailureHelper(ex, filesMgr, "file:///");
+ ex.getOutputAnalyzer().shouldContain("Is a directory");
+ }
+
+ static void testNotOverrideOnBadFileURLFailure(Executor ex,
+ FilesManager filesMgr) throws Exception {
+ notOverrideOnFailureHelper(ex, filesMgr, "file:///%00");
+ }
+
+ static void testDisabledExtraPropertiesFile(Executor ex,
+ FilesManager filesMgr) throws Exception {
+ PropsFile masterFile = filesMgr.newMasterFile();
+ PropsFile file0 = filesMgr.newFile("file0.properties");
+
+ masterFile.addRawProperty("security.overridePropertiesFile", "false");
+
+ ex.setMasterFile(masterFile);
+ ex.setIgnoredExtraFile(file0.path.toString(), true);
+ ex.assertSuccess();
+ }
+
+ static final String SECURITY_SET_PROP_FILE_PATH =
+ "testSecuritySetPropertyShouldNotInclude.propsFilePath";
+
+ static void testSecuritySetPropertyShouldNotInclude(Executor ex,
+ FilesManager filesMgr) throws Exception {
+ PropsFile masterFile = filesMgr.newMasterFile();
+ PropsFile file0 = filesMgr.newFile("file0.properties");
+
+ ex.addSystemProp(SECURITY_SET_PROP_FILE_PATH, file0.path.toString());
+ ex.setMasterFile(masterFile);
+ ex.assertSuccess();
+ }
+
+ static void assertTestSecuritySetPropertyShouldNotInclude() {
+ // This check is executed by the launched JVM.
+ String propsFilePath = System.getProperty(SECURITY_SET_PROP_FILE_PATH);
+ if (propsFilePath != null) {
+ String name = Path.of(propsFilePath).getFileName().toString();
+ String setPropInvokeRepr = "Security.setProperty(\"include\", " +
+ "\"" + propsFilePath + "\")";
+ try {
+ Security.setProperty("include", propsFilePath);
+ throw new RuntimeException(setPropInvokeRepr + " was " +
+ "expected to throw IllegalArgumentException.");
+ } catch (IllegalArgumentException expected) {}
+ if (FilesManager.APPLIED_PROP_VALUE.equals(
+ Security.getProperty(name))) {
+ throw new RuntimeException(setPropInvokeRepr + " caused " +
+ "a file inclusion.");
}
+ try {
+ Security.getProperty("include");
+ throw new RuntimeException("Security.getProperty(\"include\")" +
+ " was expected to throw IllegalArgumentException.");
+ } catch (IllegalArgumentException expected) {}
}
}
- private static ProcessBuilder buildCommand(String... command) {
- ArrayList args = new ArrayList<>();
- args.add(COPIED_JAVA.toString());
- Collections.addAll(args, Utils.prependTestJavaOpts(command));
- return new ProcessBuilder(args);
+ /*
+ * Error cases
+ */
+
+ static void testCannotResolveRelativeFromHTTPServed(Executor ex,
+ FilesManager filesMgr) throws Exception {
+ ExtraPropsFile extraFile = filesMgr.newExtraFile();
+ PropsFile file0 = filesMgr.newFile("file0.properties");
+
+ extraFile.addRelativeInclude(file0);
+
+ ex.setMasterFile(filesMgr.newMasterFile());
+ ex.setExtraFile(extraFile, Executor.ExtraMode.HTTP_SERVED, true);
+ ex.assertError("InternalError: Cannot resolve '" + file0.fileName +
+ "' relative path when included from a non-regular " +
+ "properties file (e.g. HTTP served file)");
}
- private static void exerciseSecurity(int exitCode, String output, ProcessBuilder process) throws Exception {
- OutputAnalyzer oa = ProcessTools.executeProcess(process);
- oa.shouldHaveExitValue(exitCode)
- .shouldContain(output);
+ static void testCannotIncludeCycles(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ PropsFile masterFile = filesMgr.newMasterFile();
+ PropsFile file0 = filesMgr.newFile("file0.properties");
+ PropsFile file1 = filesMgr.newFile("dir1/file1.properties");
+
+ // Includes chain: master -> file0 -> file1 -> master.
+ file1.addRelativeInclude(masterFile);
+ file0.addRelativeInclude(file1);
+ masterFile.addRelativeInclude(file0);
- // extra checks on debug output
- if (exitCode != 1) {
- if (oa.getStderr().contains("overriding other security properties files!")) {
- overrideDetected = true;
- // master file is not in use - only provider properties are set in custom file
- oa.shouldContain("security.provider.2=SunRsaSign")
- .shouldNotContain(EXPECTED_DEBUG_OUTPUT)
- .shouldNotContain(UNEXPECTED_DEBUG_OUTPUT);
+ ex.setMasterFile(masterFile);
+ ex.assertError(
+ "InternalError: Cyclic include of '" + masterFile.path + "'");
+ }
+
+ static void testCannotIncludeURL(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ PropsFile masterFile = filesMgr.newMasterFile();
+ ExtraPropsFile extraFile = filesMgr.newExtraFile();
+
+ masterFile.addRawProperty("include", extraFile.url.toString());
+
+ ex.setMasterFile(masterFile);
+ ex.assertError("InternalError: Unable to include 'http://127.0.0.1:");
+ }
+
+ static void testCannotIncludeNonexistentFile(Executor ex,
+ FilesManager filesMgr) throws Exception {
+ PropsFile masterFile = filesMgr.newMasterFile();
+
+ String nonexistentPath = "/nonExistentFile.properties";
+ masterFile.addRawProperty("include", nonexistentPath);
+
+ ex.setMasterFile(masterFile);
+ ex.assertError(
+ "InternalError: Unable to include '" + nonexistentPath + "'");
+ }
+
+ static void testMustHaveMasterFile(Executor ex, FilesManager filesMgr)
+ throws Exception {
+ // Launch a JDK without a master java.security file present.
+ ex.assertError("InternalError: Error loading java.security file");
+ }
+
+ static void testMustHaveMasterFileEvenWithExtraFile(Executor ex,
+ FilesManager filesMgr) throws Exception {
+ // Launch a JDK without a master java.security file present, but with an
+ // extra file passed. Since the "security.overridePropertiesFile=true"
+ // security property is missing, it should fail anyway.
+ ex.setExtraFile(
+ filesMgr.newExtraFile(), Executor.ExtraMode.FILE_URI, true);
+ ex.assertError("InternalError: Error loading java.security file");
+ }
+}
+
+sealed class PropsFile permits ExtraPropsFile {
+ protected static final class Include {
+ final PropsFile propsFile;
+ final String value;
+
+ private Include(PropsFile propsFile, String value) {
+ this.propsFile = propsFile;
+ this.value = value;
+ }
+
+ static Include of(PropsFile propsFile) {
+ return new Include(propsFile, propsFile.path.toString());
+ }
+
+ static Include of(PropsFile propsFile, String value) {
+ return new Include(propsFile, value);
+ }
+ }
+
+ protected final List includes = new ArrayList<>();
+ protected final PrintWriter writer;
+ protected boolean includedFromExtra = false;
+ final String fileName;
+ final Path path;
+
+ PropsFile(String fileName, Path path) throws IOException {
+ this.fileName = fileName;
+ this.path = path;
+ this.writer = new PrintWriter(Files.newOutputStream(path,
+ StandardOpenOption.CREATE, StandardOpenOption.APPEND), true);
+ }
+
+ private static String escape(String text, boolean escapeSpace) {
+ StringBuilder sb = new StringBuilder(text.length());
+ CharBuffer cb = CharBuffer.wrap(text);
+ while (cb.hasRemaining()) {
+ char c = cb.get();
+ if (c == '\\' || escapeSpace && c == ' ') {
+ sb.append('\\');
+ }
+ if (Character.UnicodeBlock.of(c) ==
+ Character.UnicodeBlock.BASIC_LATIN) {
+ sb.append(c);
} else {
- oa.shouldContain(EXPECTED_DEBUG_OUTPUT)
- .shouldNotContain(UNEXPECTED_DEBUG_OUTPUT);
+ sb.append("\\u%04x".formatted((int) c));
}
}
+ return sb.toString();
}
- // exercise the -XshowSettings:security launcher
- private static void exerciseShowSettingsSecurity(ProcessBuilder process) throws Exception {
- OutputAnalyzer oa = ProcessTools.executeProcess(process);
- oa.shouldHaveExitValue(0)
- .shouldContain("Security properties:")
- .shouldContain("Security provider static configuration:")
- .shouldContain("Security TLS configuration");
+ private void addRawProperty(String key, String value, String sep) {
+ writer.println(escape(key, true) + sep + escape(value, false));
+ }
+
+ protected void addIncludeDefinition(Include include) {
+ if (include.propsFile instanceof ExtraPropsFile) {
+ throw new RuntimeException("ExtraPropsFile should not be included");
+ }
+ includes.add(include);
+ addRawProperty("include", include.value, " ");
+ }
+
+ void addComment(String comment) {
+ writer.println("# " + comment);
+ }
+
+ void addRawProperty(String key, String value) {
+ addRawProperty(key, value, "=");
+ }
+
+ void addAbsoluteInclude(PropsFile propsFile) {
+ addIncludeDefinition(Include.of(propsFile));
+ }
+
+ void addRelativeInclude(PropsFile propsFile) {
+ addIncludeDefinition(Include.of(propsFile,
+ path.getParent().relativize(propsFile.path).toString()));
+ }
+
+ void assertApplied(OutputAnalyzer oa) {
+ oa.shouldContain(Executor.INITIAL_PROP_LOG_MSG + fileName + "=" +
+ FilesManager.APPLIED_PROP_VALUE);
+ for (Include include : includes) {
+ include.propsFile.assertApplied(oa);
+ oa.shouldContain("processing include: '" + include.value + "'");
+ oa.shouldContain("finished processing " + include.propsFile.path);
+ }
+ }
+
+ void assertWasOverwritten(OutputAnalyzer oa) {
+ oa.shouldNotContain(Executor.INITIAL_PROP_LOG_MSG + fileName + "=" +
+ FilesManager.APPLIED_PROP_VALUE);
+ for (Include include : includes) {
+ if (!include.propsFile.includedFromExtra) {
+ include.propsFile.assertWasOverwritten(oa);
+ }
+ oa.shouldContain("processing include: '" + include.value + "'");
+ oa.shouldContain("finished processing " + include.propsFile.path);
+ }
+ }
+
+ void markAsIncludedFromExtra() {
+ includedFromExtra = true;
+ for (Include include : includes) {
+ include.propsFile.markAsIncludedFromExtra();
+ }
+ }
+
+ PropsFile getLastFile() {
+ return includes.isEmpty() ?
+ this : includes.getLast().propsFile.getLastFile();
}
- private static void copyJDK(Path src, Path dst) throws Exception {
- Files.walk(src)
- .skip(1)
- .forEach(file -> {
+ void close() {
+ writer.close();
+ }
+}
+
+final class ExtraPropsFile extends PropsFile {
+ private final Map systemProps = new LinkedHashMap<>();
+ final URI url;
+
+ ExtraPropsFile(String fileName, URI url, Path path) throws IOException {
+ super(fileName, path);
+ this.url = url;
+ }
+
+ @Override
+ protected void addIncludeDefinition(Include include) {
+ if (includes.isEmpty()) {
+ String propName = "props.fileName";
+ systemProps.put(propName, include.propsFile.fileName);
+ include = Include.of(include.propsFile,
+ include.value.replace(include.propsFile.fileName,
+ "${props.none}${" + propName + "}"));
+ }
+ include.propsFile.markAsIncludedFromExtra();
+ super.addIncludeDefinition(include);
+ }
+
+ Map getSystemProperties() {
+ return Collections.unmodifiableMap(systemProps);
+ }
+}
+
+final class FilesManager implements Closeable {
+ private static final Path ROOT_DIR =
+ Path.of(ConfigFileTest.class.getSimpleName()).toAbsolutePath();
+ private static final Path PROPS_DIR = ROOT_DIR.resolve("properties");
+ private static final Path JDK_DIR = ROOT_DIR.resolve("jdk");
+ private static final Path MASTER_FILE =
+ JDK_DIR.resolve("conf/security/java.security");
+ private static final Path MASTER_FILE_TEMPLATE =
+ MASTER_FILE.resolveSibling("java.security.template");
+ static final String JAVA_EXECUTABLE =
+ JDK_DIR.resolve("bin/java").toString();
+ static final String LAST_FILE_PROP_NAME = "last-file";
+ static final String APPLIED_PROP_VALUE = "applied";
+
+ private final List createdFiles;
+ private final Set fileNamesInUse;
+ private final HttpServer httpServer;
+ private final URI serverUri;
+ private final long masterFileLines;
+
+ FilesManager() throws Exception {
+ createdFiles = new ArrayList<>();
+ fileNamesInUse = new HashSet<>();
+ httpServer = HttpServer.create(
+ new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0);
+ httpServer.createContext("/", this::handleRequest);
+ InetSocketAddress address = httpServer.getAddress();
+ httpServer.start();
+ serverUri = new URI("http", null, address.getHostString(),
+ address.getPort(), null, null, null);
+ copyJDK();
+ try (Stream s = Files.lines(MASTER_FILE_TEMPLATE)) {
+ masterFileLines = s.count();
+ }
+ }
+
+ private static void copyJDK() throws Exception {
+ Path testJDK = Path.of(Objects.requireNonNull(
+ System.getProperty("test.jdk"), "unspecified test.jdk"));
+ if (!Files.exists(testJDK)) {
+ throw new RuntimeException("test.jdk -> nonexistent JDK");
+ }
+ Files.createDirectories(JDK_DIR);
+ try (Stream pathStream = Files.walk(testJDK)) {
+ pathStream.skip(1).forEach((Path file) -> {
try {
- Files.copy(file, dst.resolve(src.relativize(file)), StandardCopyOption.COPY_ATTRIBUTES);
+ Files.copy(file, JDK_DIR.resolve(testJDK.relativize(file)),
+ StandardCopyOption.COPY_ATTRIBUTES);
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
});
+ }
+ Files.move(MASTER_FILE, MASTER_FILE_TEMPLATE);
+ }
+
+ private void handleRequest(HttpExchange x) throws IOException {
+ String rawPath = x.getRequestURI().getRawPath();
+ Path f = ROOT_DIR.resolve(x.getRequestURI().getPath().substring(1));
+ int statusCode;
+ byte[] responseBody;
+ // Check for unescaped space, unresolved parent or backward slash.
+ if (rawPath.matches("^.*( |(\\.|%2[Ee]){2}|\\\\|%5[Cc]).*$")) {
+ statusCode = HttpURLConnection.HTTP_BAD_REQUEST;
+ responseBody = new byte[0];
+ } else if (Files.isRegularFile(f)) {
+ x.getResponseHeaders().add("Content-type", "text/plain");
+ statusCode = HttpURLConnection.HTTP_OK;
+ responseBody = Files.readAllBytes(f);
+ } else {
+ statusCode = HttpURLConnection.HTTP_NOT_FOUND;
+ responseBody = new byte[0];
+ }
+ System.out.println("[" + Instant.now() + "] " +
+ getClass().getSimpleName() + ": " +
+ x.getRequestMethod() + " " + rawPath + " -> " +
+ statusCode + " (" + responseBody.length + " bytes)");
+ try (OutputStream responseStream = x.getResponseBody()) {
+ x.sendResponseHeaders(statusCode, responseBody.length);
+ responseStream.write(responseBody);
+ }
+ }
+
+ @FunctionalInterface
+ private interface PropsFileBuilder {
+ PropsFile build(String fileName, Path path) throws IOException;
+ }
+
+ private PropsFile newFile(Path path, PropsFileBuilder builder)
+ throws IOException {
+ String fileName = path.getFileName().toString();
+ if (!fileNamesInUse.add(fileName)) {
+ // Names must be unique in order for the special
+ // property = to work.
+ throw new RuntimeException(fileName + " is repeated");
+ }
+ Files.createDirectories(path.getParent());
+ PropsFile propsFile = builder.build(fileName, path);
+ propsFile.addComment("Property to determine if this properties file " +
+ "was parsed and not overwritten:");
+ propsFile.addRawProperty(fileName, APPLIED_PROP_VALUE);
+ propsFile.addComment(ConfigFileTest.SEPARATOR_THIN);
+ propsFile.addComment("Property to be overwritten by every properties " +
+ "file (master, extra or included):");
+ propsFile.addRawProperty(LAST_FILE_PROP_NAME, fileName);
+ propsFile.addComment(ConfigFileTest.SEPARATOR_THIN);
+ createdFiles.add(propsFile);
+ return propsFile;
+ }
+
+ PropsFile newFile(String relPathStr) throws IOException {
+ return newFile(PROPS_DIR.resolve(relPathStr), PropsFile::new);
+ }
+
+ PropsFile newMasterFile() throws IOException {
+ Files.copy(MASTER_FILE_TEMPLATE, MASTER_FILE);
+ return newFile(MASTER_FILE, PropsFile::new);
+ }
+
+ ExtraPropsFile newExtraFile() throws IOException {
+ return newExtraFile("extra.properties");
+ }
+
+ ExtraPropsFile newExtraFile(String extraFileName) throws IOException {
+ return (ExtraPropsFile) newFile(PROPS_DIR.resolve(extraFileName),
+ (fileName, path) -> {
+ URI uri = serverUri.resolve(ParseUtil.encodePath(
+ ROOT_DIR.relativize(path).toString()));
+ return new ExtraPropsFile(fileName, uri, path);
+ });
+ }
+
+ void reportCreatedFiles() throws IOException {
+ for (PropsFile propsFile : createdFiles) {
+ System.err.println();
+ System.err.println(propsFile.path.toString());
+ System.err.println(ConfigFileTest.SEPARATOR_THIN.repeat(3));
+ try (Stream lines = Files.lines(propsFile.path)) {
+ long lineNumber = 1L;
+ Iterator it = lines.iterator();
+ while (it.hasNext()) {
+ String line = it.next();
+ if (!propsFile.path.equals(MASTER_FILE) ||
+ lineNumber > masterFileLines) {
+ System.err.println(line);
+ }
+ lineNumber++;
+ }
+ }
+ System.err.println();
+ }
+ }
+
+ void clear() throws IOException {
+ if (!createdFiles.isEmpty()) {
+ for (PropsFile propsFile : createdFiles) {
+ propsFile.close();
+ Files.delete(propsFile.path);
+ }
+ FileUtils.deleteFileTreeUnchecked(PROPS_DIR);
+ createdFiles.clear();
+ fileNamesInUse.clear();
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ clear();
+ httpServer.stop(0);
+ FileUtils.deleteFileTreeUnchecked(ROOT_DIR);
+ }
+}
+
+final class Executor {
+ enum ExtraMode {
+ HTTP_SERVED, FILE_URI, RAW_FILE_URI1, RAW_FILE_URI2, PATH_ABS, PATH_REL
+ }
+ static final String RUNNER_ARG = "runner";
+ static final String INITIAL_PROP_LOG_MSG = "Initial security property: ";
+ private static final String OVERRIDING_LOG_MSG =
+ "overriding other security properties files!";
+ private static final String[] ALWAYS_UNEXPECTED_LOG_MSGS = {
+ "java.lang.AssertionError",
+ INITIAL_PROP_LOG_MSG + "postInitTest=shouldNotRecord",
+ INITIAL_PROP_LOG_MSG + "include=",
+ };
+ private static final Path CWD = Path.of(".").toAbsolutePath();
+ private static final String JAVA_SEC_PROPS = "java.security.properties";
+ private static final String CLASS_PATH = Objects.requireNonNull(
+ System.getProperty("test.classes"), "unspecified test.classes");
+ private static final String DEBUG_ARG =
+ "-Xrunjdwp:transport=dt_socket,address=localhost:8000,suspend=y";
+ private final Map systemProps = new LinkedHashMap<>(
+ Map.of("java.security.debug", "all", "javax.net.debug", "all",
+ // Ensure we get UTF-8 debug outputs in Windows:
+ "stderr.encoding", "UTF-8", "stdout.encoding", "UTF-8"));
+ private final List jvmArgs = new ArrayList<>(
+ List.of(FilesManager.JAVA_EXECUTABLE, "-enablesystemassertions",
+ // Uncomment DEBUG_ARG to debug test-launched JVMs:
+ "-classpath", CLASS_PATH//, DEBUG_ARG
+ ));
+ private PropsFile masterPropsFile;
+ private ExtraPropsFile extraPropsFile;
+ private boolean expectedOverrideAll = false;
+ private OutputAnalyzer oa;
+
+ static void run(Method m, FilesManager filesMgr) throws Exception {
+ try {
+ m.invoke(null, new Executor(), filesMgr);
+ } catch (Throwable e) {
+ filesMgr.reportCreatedFiles();
+ throw e;
+ } finally {
+ filesMgr.clear();
+ }
+ }
+
+ void addSystemProp(String key, String value) {
+ systemProps.put(key, value);
+ }
+
+ private void setRawExtraFile(String extraFile, boolean overrideAll) {
+ addSystemProp(JAVA_SEC_PROPS, (overrideAll ? "=" : "") + extraFile);
+ }
+
+ void setMasterFile(PropsFile masterPropsFile) {
+ this.masterPropsFile = masterPropsFile;
+ }
+
+ void setExtraFile(ExtraPropsFile extraPropsFile, ExtraMode mode,
+ boolean overrideAll) {
+ this.extraPropsFile = extraPropsFile;
+ expectedOverrideAll = overrideAll;
+ setRawExtraFile(switch (mode) {
+ case HTTP_SERVED -> extraPropsFile.url.toString();
+ case FILE_URI -> extraPropsFile.path.toUri().toString();
+ case RAW_FILE_URI1 -> "file:" + extraPropsFile.path;
+ case RAW_FILE_URI2 -> "file://" +
+ (extraPropsFile.path.startsWith("/") ? "" : "/") +
+ extraPropsFile.path;
+ case PATH_ABS -> extraPropsFile.path.toString();
+ case PATH_REL -> CWD.relativize(extraPropsFile.path).toString();
+ }, overrideAll);
+ }
+
+ void setIgnoredExtraFile(String extraPropsFile, boolean overrideAll) {
+ setRawExtraFile(extraPropsFile, overrideAll);
+ expectedOverrideAll = false;
+ }
+
+ void addJvmArg(String arg) {
+ jvmArgs.add(arg);
+ }
+
+ private void execute(boolean successExpected) throws Exception {
+ List command = new ArrayList<>(jvmArgs);
+ Collections.addAll(command, Utils.getTestJavaOpts());
+ addSystemPropertiesAsJvmArgs(command);
+ command.add(ConfigFileTest.class.getSimpleName());
+ command.add(RUNNER_ARG);
+ oa = ProcessTools.executeProcess(new ProcessBuilder(command));
+ oa.shouldHaveExitValue(successExpected ? 0 : 1);
+ for (String output : ALWAYS_UNEXPECTED_LOG_MSGS) {
+ oa.shouldNotContain(output);
+ }
+ }
+
+ private void addSystemPropertiesAsJvmArgs(List command) {
+ Map allSystemProps = new LinkedHashMap<>(systemProps);
+ if (extraPropsFile != null) {
+ allSystemProps.putAll(extraPropsFile.getSystemProperties());
+ }
+ for (Map.Entry e : allSystemProps.entrySet()) {
+ command.add("-D" + e.getKey() + "=" + e.getValue());
+ }
+ }
+
+ void assertSuccess() throws Exception {
+ execute(true);
+
+ // Ensure every file was processed by checking a unique property used as
+ // a flag. Each file defines =applied.
+ //
+ // For example:
+ //
+ // file0
+ // ---------------
+ // file0=applied
+ // include file1
+ //
+ // file1
+ // ---------------
+ // file1=applied
+ //
+ // The assertion would be file0 == applied AND file1 == applied.
+ //
+ if (extraPropsFile != null) {
+ extraPropsFile.assertApplied(oa);
+ }
+ if (expectedOverrideAll) {
+ // When overriding with an extra file, check that neither
+ // the master file nor its includes are visible.
+ oa.shouldContain(OVERRIDING_LOG_MSG);
+ masterPropsFile.assertWasOverwritten(oa);
+ } else {
+ oa.shouldNotContain(OVERRIDING_LOG_MSG);
+ masterPropsFile.assertApplied(oa);
+ }
+
+ // Ensure the last included file overwrote a fixed property. Each file
+ // defines last-file=.
+ //
+ // For example:
+ //
+ // file0
+ // ---------------
+ // last-file=file0
+ // include file1
+ //
+ // file1
+ // ---------------
+ // last-file=file1
+ //
+ // The assertion would be last-file == file1.
+ //
+ PropsFile lastFile = (extraPropsFile == null ?
+ masterPropsFile : extraPropsFile).getLastFile();
+ oa.shouldContain(FilesManager.LAST_FILE_PROP_NAME + "=" +
+ lastFile.fileName);
+ oa.stdoutShouldContain(FilesManager.LAST_FILE_PROP_NAME + ": " +
+ lastFile.fileName);
+ }
+
+ void assertError(String message) throws Exception {
+ execute(false);
+ oa.shouldContain(message);
+ }
+
+ OutputAnalyzer getOutputAnalyzer() {
+ return oa;
}
}
diff --git a/test/jdk/java/security/Security/override.props b/test/jdk/java/security/Security/override.props
deleted file mode 100644
index d0190f576fd82..0000000000000
--- a/test/jdk/java/security/Security/override.props
+++ /dev/null
@@ -1,7 +0,0 @@
-# exercise ServiceLoader and legacy (class load) approach
-security.provider.1=sun.security.provider.Sun
-security.provider.2=SunRsaSign
-security.provider.3=sun.security.ssl.SunJSSE
-security.provider.4=com.sun.crypto.provider.SunJCE
-security.provider.5=SunJGSS
-security.provider.6=SunSASL
\ No newline at end of file
diff --git a/test/jdk/java/security/Security/signedfirst/DynStatic.java b/test/jdk/java/security/Security/signedfirst/DynStatic.java
index 59e30de54623f..17fab4cac5bfa 100644
--- a/test/jdk/java/security/Security/signedfirst/DynStatic.java
+++ b/test/jdk/java/security/Security/signedfirst/DynStatic.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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
@@ -33,7 +33,6 @@
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.util.List;
import jdk.test.lib.compiler.CompilerUtils;
import jdk.test.lib.process.ProcessTools;
@@ -52,9 +51,8 @@ public class DynStatic {
Paths.get(TEST_SRC, "DynSignedProvFirst.java");
private static final Path STATIC_SRC =
Paths.get(TEST_SRC, "StaticSignedProvFirst.java");
-
- private static final String STATIC_PROPS =
- Paths.get(TEST_SRC, "Static.props").toString();
+ private static final Path STATIC_PROPS =
+ Paths.get(TEST_SRC, "Static.props");
public static void main(String[] args) throws Exception {
@@ -89,7 +87,7 @@ public static void main(String[] args) throws Exception {
// Run the StaticSignedProvFirst test program
ProcessTools.executeTestJava("-classpath",
TEST_CLASSES.toString() + File.pathSeparator + "exp.jar",
- "-Djava.security.properties=file:" + STATIC_PROPS,
+ "-Djava.security.properties=" + STATIC_PROPS.toUri(),
"StaticSignedProvFirst")
.shouldContain("test passed");
}
diff --git a/test/jdk/java/util/zip/ZipFile/CenSizeTooLarge.java b/test/jdk/java/util/zip/ZipFile/CenSizeTooLarge.java
index 4336377e0c898..3a5430d0573e8 100644
--- a/test/jdk/java/util/zip/ZipFile/CenSizeTooLarge.java
+++ b/test/jdk/java/util/zip/ZipFile/CenSizeTooLarge.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 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
@@ -34,9 +34,7 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
-import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
-import java.util.Arrays;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
@@ -46,6 +44,10 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
public class CenSizeTooLarge {
+
+ // Entry names produced in this test are fixed-length
+ public static final int NAME_LENGTH = 10;
+
// Maximum allowed CEN size allowed by the ZipFile implementation
static final int MAX_CEN_SIZE = Integer.MAX_VALUE - ZipFile.ENDHDR - 1;
@@ -59,11 +61,10 @@ public class CenSizeTooLarge {
* fields respectively. The combined length of any
* directory record and these three fields SHOULD NOT
* generally exceed 65,535 bytes.
- *
- * Since ZipOutputStream does not enforce the 'combined length' clause,
- * we simply use 65,535 (0xFFFF) for the purpose of this test.
+ *.
+ * Create a maximum extra field which does not exceed 65,535 bytes
*/
- static final int MAX_EXTRA_FIELD_SIZE = 65_535;
+ static final int MAX_EXTRA_FIELD_SIZE = 65_535 - ZipFile.CENHDR - NAME_LENGTH;
// Data size (unsigned short)
// Field size minus the leading header 'tag' and 'data size' fields (2 bytes each)
@@ -72,9 +73,6 @@ public class CenSizeTooLarge {
// Tag for the 'unknown' field type, specified in APPNOTE.txt 'Third party mappings'
static final short UNKNOWN_ZIP_TAG = (short) 0x9902;
- // Entry names produced in this test are fixed-length
- public static final int NAME_LENGTH = 10;
-
// Use a shared LocalDateTime on all entries to save processing time
static final LocalDateTime TIME_LOCAL = LocalDateTime.now();
@@ -84,16 +82,16 @@ public class CenSizeTooLarge {
// The number of entries needed to exceed the MAX_CEN_SIZE
static final int NUM_ENTRIES = (MAX_CEN_SIZE / CEN_HEADER_SIZE) + 1;
- // Helps SparseOutputStream detect write of the last CEN entry
- private static final String LAST_CEN_COMMENT = "LastCEN";
- private static final byte[] LAST_CEN_COMMENT_BYTES = LAST_CEN_COMMENT.getBytes(StandardCharsets.UTF_8);
-
// Expected ZipException message when the CEN does not fit in a Java byte array
private static final String CEN_TOO_LARGE_MESSAGE = "invalid END header (central directory size too large)";
// Zip file to create for testing
private File hugeZipFile;
+ private static final byte[] EXTRA_BYTES = makeLargeExtraField();
+ // Helps SparseOutputStream detect write of the last CEN entry
+ private static final byte[] LAST_EXTRA_BYTES = makeLargeExtraField();
+
/**
* Create a zip file with a CEN size which does not fit within a Java byte array
*/
@@ -125,23 +123,18 @@ public void setup() throws IOException {
// Set the time/date field for faster processing
entry.setTimeLocal(TIME_LOCAL);
- if (i == NUM_ENTRIES -1) {
- // Help SparseOutputStream detect the last CEN entry write
- entry.setComment(LAST_CEN_COMMENT);
- }
// Add the entry
zip.putNextEntry(entry);
-
-
}
// Finish writing the last entry
zip.closeEntry();
// Before the CEN headers are written, set the extra data on each entry
- byte[] extra = makeLargeExtraField();
for (ZipEntry entry : entries) {
- entry.setExtra(extra);
+ entry.setExtra(EXTRA_BYTES);
}
+ // Help SparseOutputSream detect the last entry
+ entries[entries.length-1].setExtra(LAST_EXTRA_BYTES);
}
}
@@ -165,7 +158,7 @@ public void centralDirectoryTooLargeToFitInByteArray() {
* Data Size (Two byte short)
* Data Block (Contents depend on field type)
*/
- private byte[] makeLargeExtraField() {
+ private static byte[] makeLargeExtraField() {
// Make a maximally sized extra field
byte[] extra = new byte[MAX_EXTRA_FIELD_SIZE];
// Little-endian ByteBuffer for updating the header fields
@@ -203,7 +196,7 @@ public void write(byte[] b, int off, int len) throws IOException {
// but instead simply advance the position, creating a sparse file
channel.position(position);
// Check for last CEN record
- if (Arrays.equals(LAST_CEN_COMMENT_BYTES, 0, LAST_CEN_COMMENT_BYTES.length, b, off, len)) {
+ if (b == LAST_EXTRA_BYTES) {
// From here on, write actual bytes
sparse = false;
}
diff --git a/test/jdk/java/util/zip/ZipFile/ReadAfterClose.java b/test/jdk/java/util/zip/ZipFile/ReadAfterClose.java
new file mode 100644
index 0000000000000..a083daf766871
--- /dev/null
+++ b/test/jdk/java/util/zip/ZipFile/ReadAfterClose.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/* @test
+ @bug 8340684
+ @summary Verify unspecified, but long-standing behavior when reading
+ from an input stream obtained using ZipFile::getInputStream after
+ the ZipFile has been closed.
+ @run junit ReadAfterClose
+ */
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Stream;
+import java.util.zip.CRC32;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class ReadAfterClose {
+
+ // ZIP file used in this test
+ private Path zip = Path.of("read-after-close.zip");
+
+ /**
+ * Create a sample ZIP file for use by this test
+ * @throws IOException if an unexpected IOException occurs
+ */
+ @BeforeEach
+ public void setUp() throws IOException {
+ byte[] content = "hello".repeat(1000).getBytes(StandardCharsets.UTF_8);
+ try (OutputStream out = Files.newOutputStream(zip);
+ ZipOutputStream zo = new ZipOutputStream(out)) {
+ {
+ zo.putNextEntry(new ZipEntry("deflated.txt"));
+ zo.write(content);
+ }
+ {
+ ZipEntry entry = new ZipEntry("stored.txt");
+ entry.setMethod(ZipEntry.STORED);
+ CRC32 crc = new CRC32();
+ crc.update(content);
+ entry.setCrc(crc.getValue());
+ entry.setSize(content.length);
+ zo.putNextEntry(entry);
+ zo.write(content);
+ }
+ }
+ }
+
+ /**
+ * Delete the ZIP file produced by this test
+ * @throws IOException if an unexpected IOException occurs
+ */
+ @AfterEach
+ public void cleanup() throws IOException {
+ Files.deleteIfExists(zip);
+ }
+
+ /**
+ * Produce arguments with a variation of stored / deflated entries,
+ * and read behavior before closing the ZipFile.
+ * @return
+ */
+ public static Stream arguments() {
+ return Stream.of(
+ Arguments.of("stored.txt", true),
+ Arguments.of("stored.txt", false),
+ Arguments.of("deflated.txt", true),
+ Arguments.of("deflated.txt", false)
+ );
+ }
+ /**
+ * Attempting to read from an InputStream obtained by ZipFile.getInputStream
+ * after the backing ZipFile is closed should throw IOException
+ *
+ * @throws IOException if an unexpected IOException occurs
+ */
+ @ParameterizedTest
+ @MethodSource("arguments")
+ public void readAfterClose(String entryName, boolean readFirst) throws IOException {
+ // Retain a reference to an input stream backed by a closed ZipFile
+ InputStream in;
+ try (ZipFile zf = new ZipFile(zip.toFile())) {
+ in = zf.getInputStream(new ZipEntry(entryName));
+ // Optionally consume a single byte from the stream before closing
+ if (readFirst) {
+ in.read();
+ }
+ }
+
+ assertThrows(IOException.class, () -> {
+ in.read();
+ });
+ }
+}
\ No newline at end of file
diff --git a/test/jdk/java/util/zip/ZipOutputStream/ZipOutputStreamMaxCenHdrTest.java b/test/jdk/java/util/zip/ZipOutputStream/ZipOutputStreamMaxCenHdrTest.java
new file mode 100644
index 0000000000000..286e043c2256f
--- /dev/null
+++ b/test/jdk/java/util/zip/ZipOutputStream/ZipOutputStreamMaxCenHdrTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/* @test
+ * @bug 8336025
+ * @summary Verify that ZipOutputStream throws a ZipException when the
+ * CEN header size + name length + comment length + extra length exceeds
+ * 65,535 bytes
+ * @run junit ZipOutputStreamMaxCenHdrTest
+ */
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class ZipOutputStreamMaxCenHdrTest {
+
+ // CEN header size + name length + comment length + extra length
+ // should not exceed 65,535 bytes per the PKWare APP.NOTE
+ // 4.4.10, 4.4.11, & 4.4.12.
+ static final int MAX_COMBINED_CEN_HEADER_SIZE = 0xFFFF;
+
+ // Maximum possible size of name length + comment length + extra length
+ // for entries in order to not exceed 65,489 bytes minus 46 bytes for the CEN
+ // header length
+ static final int MAX_NAME_COMMENT_EXTRA_SIZE =
+ MAX_COMBINED_CEN_HEADER_SIZE - ZipFile.CENHDR;
+
+ // Tag for the 'unknown' field type, specified in APPNOTE.txt 'Third party mappings'
+ static final short UNKNOWN_ZIP_TAG = (short) 0x9902;
+
+ // ZIP file to be used by the tests
+ static final Path ZIP_FILE = Path.of("maxCENHdrTest.zip");
+
+ /**
+ * Clean up prior to test run
+ *
+ * @throws IOException if an error occurs
+ */
+ @BeforeEach
+ public void startUp() throws IOException {
+ Files.deleteIfExists(ZIP_FILE);
+ }
+
+ /**
+ * Validate a ZipException is thrown when the combined CEN Header, name
+ * length, comment length, and extra data length exceeds 65,535 bytes when
+ * the ZipOutputStream is closed.
+ */
+ @ParameterizedTest
+ @ValueSource(ints = {MAX_COMBINED_CEN_HEADER_SIZE,
+ MAX_COMBINED_CEN_HEADER_SIZE - 1,
+ MAX_NAME_COMMENT_EXTRA_SIZE,
+ MAX_NAME_COMMENT_EXTRA_SIZE - 1})
+ void setCommentTest(int length) throws IOException {
+ boolean expectZipException = length > MAX_NAME_COMMENT_EXTRA_SIZE;
+ final byte[] bytes = new byte[length];
+ Arrays.fill(bytes, (byte) 'a');
+ ZipEntry zipEntry = new ZipEntry("");
+ // The comment length will trigger the ZipException
+ zipEntry.setComment(new String(bytes, StandardCharsets.UTF_8));
+ boolean receivedException = writeZipEntry(zipEntry, expectZipException);
+ assertEquals(receivedException, expectZipException);
+ }
+
+ /**
+ * Validate an ZipException is thrown when the combined CEN Header, name
+ * length, comment length, and extra data length exceeds 65,535 bytes when
+ * the ZipOutputStream is closed.
+ */
+ @ParameterizedTest
+ @ValueSource(ints = {MAX_COMBINED_CEN_HEADER_SIZE,
+ MAX_COMBINED_CEN_HEADER_SIZE - 1,
+ MAX_NAME_COMMENT_EXTRA_SIZE,
+ MAX_NAME_COMMENT_EXTRA_SIZE - 1})
+ void setNameTest(int length) throws IOException {
+ boolean expectZipException = length > MAX_NAME_COMMENT_EXTRA_SIZE;
+ final byte[] bytes = new byte[length];
+ Arrays.fill(bytes, (byte) 'a');
+ // The name length will trigger the ZipException
+ ZipEntry zipEntry = new ZipEntry(new String(bytes, StandardCharsets.UTF_8));
+ boolean receivedException = writeZipEntry(zipEntry, expectZipException);
+ assertEquals(receivedException, expectZipException);
+ }
+
+ /**
+ * Validate an ZipException is thrown when the combined CEN Header, name
+ * length, comment length, and extra data length exceeds 65,535 bytes when
+ * the ZipOutputStream is closed.
+ */
+ @ParameterizedTest
+ @ValueSource(ints = {MAX_COMBINED_CEN_HEADER_SIZE,
+ MAX_COMBINED_CEN_HEADER_SIZE - 1,
+ MAX_NAME_COMMENT_EXTRA_SIZE,
+ MAX_NAME_COMMENT_EXTRA_SIZE - 1})
+ void setExtraTest(int length) throws IOException {
+ boolean expectZipException = length > MAX_NAME_COMMENT_EXTRA_SIZE;
+ final byte[] bytes = new byte[length];
+ // Little-endian ByteBuffer for updating the header fields
+ ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);
+ // We use the 'unknown' tag, specified in APPNOTE.TXT, 4.6.1 Third party mappings'
+ buffer.putShort(UNKNOWN_ZIP_TAG);
+ // Size of the actual (empty) data
+ buffer.putShort((short) (length - 2 * Short.BYTES));
+ ZipEntry zipEntry = new ZipEntry("");
+ // The extra data length will trigger the ZipException
+ zipEntry.setExtra(bytes);
+ boolean receivedException = writeZipEntry(zipEntry, expectZipException);
+ assertEquals(receivedException, expectZipException);
+ }
+
+ /**
+ * Write a single Zip entry using ZipOutputStream
+ * @param zipEntry the ZipEntry to write
+ * @param expectZipException true if a ZipException is expected, false otherwse
+ * @return true if a ZipException was thrown
+ * @throws IOException if an error occurs
+ */
+ private static boolean writeZipEntry(ZipEntry zipEntry, boolean expectZipException)
+ throws IOException {
+ boolean receivedException = false;
+ try (ZipOutputStream zos = new ZipOutputStream(
+ new BufferedOutputStream(Files.newOutputStream(ZIP_FILE)))) {
+ zos.putNextEntry(zipEntry);
+ if (expectZipException) {
+ ZipException ex = assertThrows(ZipException.class, zos::close);
+ assertTrue(ex.getMessage().matches(".*bad header size.*"),
+ "Unexpected ZipException message: " + ex.getMessage());
+ receivedException = true;
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Received Unexpected Exception", e);
+ }
+ return receivedException;
+ }
+}
diff --git a/test/jdk/jdk/classfile/ConstantDescSymbolsTest.java b/test/jdk/jdk/classfile/ConstantDescSymbolsTest.java
index 7c97c9dd5a9b1..b5d3ba5d584fb 100644
--- a/test/jdk/jdk/classfile/ConstantDescSymbolsTest.java
+++ b/test/jdk/jdk/classfile/ConstantDescSymbolsTest.java
@@ -23,11 +23,14 @@
/*
* @test
- * @bug 8304031 8338406
+ * @bug 8304031 8338406 8338546
* @summary Testing handling of various constant descriptors in ClassFile API.
+ * @modules java.base/jdk.internal.constant
+ * java.base/jdk.internal.classfile.impl
* @run junit ConstantDescSymbolsTest
*/
+import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.constant.ClassDesc;
import java.lang.constant.DynamicConstantDesc;
import java.lang.constant.MethodHandleDesc;
@@ -36,8 +39,14 @@
import java.lang.invoke.MethodType;
import java.util.function.Supplier;
import java.lang.classfile.ClassFile;
+import java.util.stream.Stream;
+
+import jdk.internal.classfile.impl.AbstractPoolEntry;
+import jdk.internal.constant.ConstantUtils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
import static java.lang.classfile.ClassFile.ACC_PUBLIC;
import static java.lang.constant.ConstantDescs.*;
@@ -102,4 +111,58 @@ record CondyBoot(MethodHandles.Lookup lookup, String name, Class> type) {}
assertEquals(DEFAULT_NAME, cb.name);
assertEquals(CondyBoot.class, cb.type);
}
+
+ static Stream classOrInterfaceEntries() {
+ return Stream.of(
+ CD_Object, CD_Float, CD_Long, CD_String, ClassDesc.of("Ape"),
+ CD_String.nested("Whatever"), CD_MethodHandles_Lookup, ClassDesc.ofInternalName("one/Two"),
+ ClassDesc.ofDescriptor("La/b/C;"), ConstantDescSymbolsTest.class.describeConstable().orElseThrow(),
+ CD_Boolean, CD_ConstantBootstraps, CD_MethodHandles
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("classOrInterfaceEntries")
+ void testConstantPoolBuilderClassOrInterfaceEntry(ClassDesc cd) {
+ assertTrue(cd.isClassOrInterface());
+ ConstantPoolBuilder cp = ConstantPoolBuilder.of();
+ var internal = ConstantUtils.dropFirstAndLastChar(cd.descriptorString());
+
+ // 1. ClassDesc
+ var ce = cp.classEntry(cd);
+ assertSame(cd, ce.asSymbol(), "Symbol propagation on create");
+
+ // 1.1. Bare addition
+ assertTrue(ce.name().equalsString(internal), "Adding to bare pool");
+
+ // 1.2. Lookup existing
+ assertSame(ce, cp.classEntry(cd), "Finding by identical CD");
+
+ // 1.3. Lookup existing - equal but different ClassDesc
+ var cd1 = ClassDesc.ofDescriptor(cd.descriptorString());
+ assertSame(ce, cp.classEntry(cd1), "Finding by another equal CD");
+
+ // 1.3.1. Lookup existing - equal but different ClassDesc, equal but different string
+ var cd2 = ClassDesc.ofDescriptor("" + cd.descriptorString());
+ assertSame(ce, cp.classEntry(cd2), "Finding by another equal CD");
+
+ // 1.4. Lookup existing - with utf8 internal name
+ var utf8 = cp.utf8Entry(internal);
+ assertSame(ce, cp.classEntry(utf8), "Finding CD by UTF8");
+
+ // 2. ClassEntry exists, no ClassDesc
+ cp = ConstantPoolBuilder.of();
+ utf8 = cp.utf8Entry(internal);
+ ce = cp.classEntry(utf8);
+ var found = cp.classEntry(cd);
+ assertSame(ce, found, "Finding non-CD CEs with CD");
+ assertEquals(cd, ce.asSymbol(), "Symbol propagation on find");
+
+ // 3. Utf8Entry exists, no ClassEntry
+ cp = ConstantPoolBuilder.of();
+ utf8 = cp.utf8Entry(internal);
+ ce = cp.classEntry(cd);
+ assertSame(utf8, ce.name(), "Reusing existing utf8 entry");
+ assertEquals(cd, ce.asSymbol(), "Symbol propagation on create with utf8");
+ }
}
diff --git a/test/jdk/jdk/classfile/LimitsTest.java b/test/jdk/jdk/classfile/LimitsTest.java
index 9c7b8d9e72d4a..a1899ac1c842b 100644
--- a/test/jdk/jdk/classfile/LimitsTest.java
+++ b/test/jdk/jdk/classfile/LimitsTest.java
@@ -28,6 +28,7 @@
* @run junit LimitsTest
*/
import java.lang.classfile.Attributes;
+import java.lang.classfile.constantpool.PoolEntry;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
import java.lang.constant.MethodTypeDesc;
@@ -36,12 +37,10 @@
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.attribute.LineNumberInfo;
import java.lang.classfile.attribute.LineNumberTableAttribute;
-import java.lang.classfile.attribute.LocalVariableInfo;
import java.lang.classfile.attribute.LocalVariableTableAttribute;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.constantpool.ConstantPoolException;
import java.lang.classfile.constantpool.IntegerEntry;
-import java.lang.classfile.instruction.LocalVariable;
import java.util.List;
import jdk.internal.classfile.impl.BufWriterImpl;
@@ -113,13 +112,13 @@ void testReadingOutOfBounds() {
@Test
void testInvalidClassEntry() {
assertThrows(ConstantPoolException.class, () -> ClassFile.of().parse(new byte[]{(byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE,
- 0, 0, 0, 0, 0, 2, ClassFile.TAG_METHODREF, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}).thisClass());
+ 0, 0, 0, 0, 0, 2, PoolEntry.TAG_METHODREF, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}).thisClass());
}
@Test
void testInvalidUtf8Entry() {
var cp = ClassFile.of().parse(new byte[]{(byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE,
- 0, 0, 0, 0, 0, 3, ClassFile.TAG_INTEGER, 0, 0, 0, 0, ClassFile.TAG_NAMEANDTYPE, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}).constantPool();
+ 0, 0, 0, 0, 0, 3, PoolEntry.TAG_INTEGER, 0, 0, 0, 0, PoolEntry.TAG_NAME_AND_TYPE, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}).constantPool();
assertTrue(cp.entryByIndex(1) instanceof IntegerEntry); //parse valid int entry first
assertThrows(ConstantPoolException.class, () -> cp.entryByIndex(2));
}
diff --git a/test/jdk/jdk/classfile/StackMapsTest.java b/test/jdk/jdk/classfile/StackMapsTest.java
index 09be56f0de2a1..1ccd7255ed4b9 100644
--- a/test/jdk/jdk/classfile/StackMapsTest.java
+++ b/test/jdk/jdk/classfile/StackMapsTest.java
@@ -385,9 +385,9 @@ void testDeadCodeCountersWithCustomSMTA() {
StackMapTableAttribute.of(List.of(
StackMapFrameInfo.of(f2,
List.of(),
- List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.ITEM_LONG)),
+ List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.LONG)),
StackMapFrameInfo.of(f3,
- List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.ITEM_LONG),
+ List.of(StackMapFrameInfo.SimpleVerificationTypeInfo.LONG),
List.of()))));
}
));
diff --git a/test/jdk/jdk/classfile/UtilTest.java b/test/jdk/jdk/classfile/UtilTest.java
index d9d8240ae9149..be66d9305808c 100644
--- a/test/jdk/jdk/classfile/UtilTest.java
+++ b/test/jdk/jdk/classfile/UtilTest.java
@@ -23,18 +23,25 @@
/*
* @test
+ * @bug 8338546
* @summary Testing ClassFile Util.
+ * @library java.base
+ * @modules java.base/jdk.internal.constant
+ * java.base/jdk.internal.classfile.impl
+ * @build java.base/jdk.internal.classfile.impl.*
* @run junit UtilTest
*/
-import java.lang.classfile.ClassFile;
import java.lang.classfile.Opcode;
import java.lang.constant.MethodTypeDesc;
-import java.lang.invoke.MethodHandles;
import java.util.Arrays;
-import java.util.BitSet;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
import jdk.internal.classfile.impl.RawBytecodeHelper;
import jdk.internal.classfile.impl.Util;
+import jdk.internal.classfile.impl.UtilAccess;
+import jdk.internal.constant.ConstantUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@@ -84,6 +91,50 @@ private void assertSlots(String methodDesc, int slots) {
assertEquals(Util.parameterSlots(MethodTypeDesc.ofDescriptor(methodDesc)), slots);
}
+ @Test
+ void testPow31() {
+ int p = 1;
+ // Our calculation only prepares up to 65536,
+ // max length of CP Utf8 + 1
+ for (int i = 0; i <= 65536; i++) {
+ final int t = i;
+ assertEquals(p, Util.pow31(i), () -> "31's power to " + t);
+ p *= 31;
+ }
+ }
+
+ @ParameterizedTest
+ @ValueSource(classes = {
+ Long.class,
+ Object.class,
+ Util.class,
+ Test.class,
+ CopyOnWriteArrayList.class,
+ AtomicReferenceFieldUpdater.class
+ })
+ void testInternalNameHash(Class> type) {
+ var cd = type.describeConstable().orElseThrow();
+ assertEquals(ConstantUtils.binaryToInternal(type.getName()).hashCode(), Util.internalNameHash(cd.descriptorString()));
+ }
+
+ // Ensures the initialization statement of the powers array is filling in the right values
+ @Test
+ void testPowersArray() {
+ int[] powers = new int[7 * UtilAccess.significantOctalDigits()];
+ for (int i = 1, k = 31; i <= 7; i++, k *= 31) {
+ int t = powers[UtilAccess.powersIndex(i, 0)] = k;
+
+ for (int j = 1; j < UtilAccess.significantOctalDigits(); j++) {
+ t *= t;
+ t *= t;
+ t *= t;
+ powers[UtilAccess.powersIndex(i, j)] = t;
+ }
+ }
+
+ assertArrayEquals(powers, UtilAccess.powersTable());
+ }
+
@Test
void testOpcodeLengthTable() {
var lengths = new byte[0x100];
diff --git a/test/jdk/jdk/classfile/VerifierSelfTest.java b/test/jdk/jdk/classfile/VerifierSelfTest.java
index d0943d2eee9f5..b6a2f08c9ecd7 100644
--- a/test/jdk/jdk/classfile/VerifierSelfTest.java
+++ b/test/jdk/jdk/classfile/VerifierSelfTest.java
@@ -29,6 +29,7 @@
* @run junit VerifierSelfTest
*/
import java.io.IOException;
+import java.lang.classfile.constantpool.PoolEntry;
import java.lang.constant.ClassDesc;
import static java.lang.constant.ConstantDescs.*;
import java.lang.invoke.MethodHandleInfo;
@@ -116,7 +117,7 @@ public void writeBody(BufWriterImpl b) {
void testInvalidClassNameEntry() {
var cc = ClassFile.of();
var bytes = cc.parse(new byte[]{(byte)0xCA, (byte)0xFE, (byte)0xBA, (byte)0xBE,
- 0, 0, 0, 0, 0, 2, ClassFile.TAG_INTEGER, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
+ 0, 0, 0, 0, 0, 2, PoolEntry.TAG_INTEGER, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
assertTrue(cc.verify(bytes).stream().anyMatch(e -> e.getMessage().contains("expected ClassEntry")));
}
diff --git a/test/jdk/jdk/classfile/helpers/ClassRecord.java b/test/jdk/jdk/classfile/helpers/ClassRecord.java
index 329e41fa0f484..e7a239015f605 100644
--- a/test/jdk/jdk/classfile/helpers/ClassRecord.java
+++ b/test/jdk/jdk/classfile/helpers/ClassRecord.java
@@ -22,21 +22,13 @@
*/
package helpers;
-import java.io.IOException;
-import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.RecordComponent;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
@@ -53,9 +45,10 @@
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;
-import static java.lang.classfile.ClassFile.*;
import static java.lang.classfile.Attributes.*;
+import static java.lang.classfile.constantpool.PoolEntry.*;
import static helpers.ClassRecord.CompatibilityFilter.By_ClassBuilder;
+import static jdk.internal.classfile.impl.RawBytecodeHelper.*;
/**
* ClassRecord
@@ -916,17 +909,17 @@ public static ConstantPoolEntryRecord ofCPEntry(PoolEntry cpInfo) {
CpFieldRefRecord.ofFieldRefEntry((FieldRefEntry) cpInfo);
case TAG_METHODREF ->
CpMethodRefRecord.ofMethodRefEntry((MethodRefEntry) cpInfo);
- case TAG_INTERFACEMETHODREF ->
+ case TAG_INTERFACE_METHODREF ->
CpInterfaceMethodRefRecord.ofInterfaceMethodRefEntry((InterfaceMethodRefEntry) cpInfo);
- case TAG_NAMEANDTYPE ->
+ case TAG_NAME_AND_TYPE ->
CpNameAndTypeRecord.ofNameAndTypeEntry((NameAndTypeEntry) cpInfo);
- case TAG_METHODHANDLE ->
+ case TAG_METHOD_HANDLE ->
CpMethodHandleRecord.ofMethodHandleEntry((MethodHandleEntry) cpInfo);
- case TAG_METHODTYPE ->
+ case TAG_METHOD_TYPE ->
new CpMethodTypeRecord(((MethodTypeEntry) cpInfo).descriptor().stringValue());
- case TAG_CONSTANTDYNAMIC ->
+ case TAG_DYNAMIC ->
CpConstantDynamicRecord.ofConstantDynamicEntry((ConstantDynamicEntry) cpInfo);
- case TAG_INVOKEDYNAMIC ->
+ case TAG_INVOKE_DYNAMIC ->
CpInvokeDynamicRecord.ofInvokeDynamicEntry((InvokeDynamicEntry) cpInfo);
case TAG_MODULE ->
new CpModuleRecord(((ModuleEntry) cpInfo).name().stringValue());
diff --git a/test/jdk/jdk/classfile/java.base/jdk/internal/classfile/impl/UtilAccess.java b/test/jdk/jdk/classfile/java.base/jdk/internal/classfile/impl/UtilAccess.java
new file mode 100644
index 0000000000000..27cefd6d9441a
--- /dev/null
+++ b/test/jdk/jdk/classfile/java.base/jdk/internal/classfile/impl/UtilAccess.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ *
+ * 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 jdk.internal.classfile.impl;
+
+public final class UtilAccess {
+ public static int significantOctalDigits() {
+ return Util.SIGNIFICANT_OCTAL_DIGITS;
+ }
+
+ public static int powersIndex(int digit, int index) {
+ return Util.powersIndex(digit, index);
+ }
+
+ public static int[] powersTable() {
+ return Util.powers;
+ }
+
+ public static int reverse31() {
+ return Util.INVERSE_31;
+ }
+}
diff --git a/test/jdk/jdk/jfr/event/compiler/TestDeoptimization.java b/test/jdk/jdk/jfr/event/compiler/TestDeoptimization.java
index 32c634fc59a90..daf562a765fbe 100644
--- a/test/jdk/jdk/jfr/event/compiler/TestDeoptimization.java
+++ b/test/jdk/jdk/jfr/event/compiler/TestDeoptimization.java
@@ -53,6 +53,7 @@ public static void dummyMethod(boolean b) {
* @requires vm.hasJFR
* @requires vm.compMode != "Xint"
* @requires vm.flavor == "server" & (vm.opt.TieredStopAtLevel == 4 | vm.opt.TieredStopAtLevel == null)
+ * @requires vm.opt.StressUnstableIfTraps == null | !vm.opt.StressUnstableIfTraps
* @library /test/lib
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
diff --git a/test/jdk/sun/awt/image/BytePackedRaster/DitherTest.java b/test/jdk/sun/awt/image/BytePackedRaster/DitherTest.java
new file mode 100644
index 0000000000000..29b42b49fe778
--- /dev/null
+++ b/test/jdk/sun/awt/image/BytePackedRaster/DitherTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 1999, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 4184283
+ * @summary Checks rendering of dithered byte packed image does not crash.
+ */
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.IndexColorModel;
+import java.awt.image.MemoryImageSource;
+import java.awt.image.WritableRaster;
+
+public class DitherTest extends Component {
+
+ final static int NOOP = 0;
+ final static int RED = 1;
+ final static int GREEN = 2;
+ final static int BLUE = 3;
+ final static int ALPHA = 4;
+ final static int SATURATION = 5;
+
+ final static byte red[] = {(byte)0, (byte)132, (byte)0, (byte)132, (byte)0, (byte)132,
+ (byte)0, (byte)198, (byte)198, (byte)165, (byte)255, (byte)165, (byte)132,
+ (byte)255, (byte)0, (byte)255};
+
+ final static byte green[] = {(byte)0, (byte)0, (byte)130, (byte)130, (byte)0,
+ (byte)0, (byte)130, (byte)195, (byte)223, (byte)203, (byte)251, (byte)162,
+ (byte)132, (byte)0, (byte)255, (byte)255};
+
+ final static byte blue[] = {(byte)0, (byte)0, (byte)0, (byte)0, (byte)132, (byte)132,
+ (byte)132, (byte)198, (byte)198, (byte)247, (byte)247, (byte)165, (byte)132,
+ (byte)0, (byte)0, (byte)0};
+
+ static IndexColorModel cm16 = new IndexColorModel( 4, 16, red, green, blue);
+
+
+ public static void main(String args[]) {
+
+ int imageWidth = 256;
+ int imageHeight = 256;
+ WritableRaster raster = cm16.createCompatibleWritableRaster(imageWidth, imageHeight);
+ BufferedImage intermediateImage = new BufferedImage(cm16, raster, false, null);
+ Image calculatedImage = calculateImage();
+
+ Graphics2D ig = intermediateImage.createGraphics();
+ // Clear background and fill a red rectangle just to prove that we can draw on intermediateImage
+ ig.setColor(Color.white);
+ ig.fillRect(0,0,imageWidth,imageHeight);
+ ig.drawImage(calculatedImage, 0, 0, imageWidth, imageHeight, null);
+ ig.setColor(Color.red);
+ ig.fillRect(0,0,5,5);
+
+ BufferedImage destImage = new BufferedImage(imageWidth, imageWidth, BufferedImage.TYPE_INT_RGB);
+ Graphics2D dg = destImage.createGraphics();
+ dg.drawImage(intermediateImage, 0, 0, imageWidth, imageHeight, null);
+ }
+
+ private static void applymethod(int c[], int method, int step, int total, int vals[]) {
+ if (method == NOOP)
+ return;
+ int val = ((total < 2)
+ ? vals[0]
+ : vals[0] + ((vals[1] - vals[0]) * step / (total - 1)));
+ switch (method) {
+ case RED:
+ c[0] = val;
+ break;
+ case GREEN:
+ c[1] = val;
+ break;
+ case BLUE:
+ c[2] = val;
+ break;
+ case ALPHA:
+ c[3] = val;
+ break;
+ case SATURATION:
+ int max = Math.max(Math.max(c[0], c[1]), c[2]);
+ int min = max * (255 - val) / 255;
+ if (c[0] == 0) c[0] = min;
+ if (c[1] == 0) c[1] = min;
+ if (c[2] == 0) c[2] = min;
+ break;
+ }
+ }
+
+ private static Image calculateImage() {
+
+ int xvals[] = { 0, 255 };
+ int yvals[] = { 0, 255 };
+ int xmethod = RED;
+ int ymethod = BLUE;
+ int width = 256;
+ int height = 256;
+ int pixels[] = new int[width * height];
+ int c[] = new int[4];
+ int index = 0;
+ for (int j = 0; j < height; j++) {
+ for (int i = 0; i < width; i++) {
+ c[0] = c[1] = c[2] = 0;
+ c[3] = 255;
+ if (xmethod < ymethod) {
+ applymethod(c, xmethod, i, width, xvals);
+ applymethod(c, ymethod, j, height, yvals);
+ } else {
+ applymethod(c, ymethod, j, height, yvals);
+ applymethod(c, xmethod, i, width, xvals);
+ }
+ pixels[index++] = ((c[3] << 24) |
+ (c[0] << 16) |
+ (c[1] << 8) |
+ (c[2] << 0));
+ }
+ }
+
+ DitherTest dt = new DitherTest();
+ return dt.createImage(new MemoryImageSource(width, height, ColorModel.getRGBdefault(), pixels, 0, width));
+ }
+}
+
diff --git a/test/jdk/sun/awt/image/BytePackedRaster/MultiOp.java b/test/jdk/sun/awt/image/BytePackedRaster/MultiOp.java
new file mode 100644
index 0000000000000..2c396792548f2
--- /dev/null
+++ b/test/jdk/sun/awt/image/BytePackedRaster/MultiOp.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 1999, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 4213160
+ * @summary Should generate a black image
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.IndexColorModel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.awt.geom.AffineTransform;
+
+public class MultiOp {
+
+ public static void main(String[] argv) {
+
+ int width = 256;
+ int height = 256;
+
+ int pixelBits = 2; // 1, 2, 4, or 8
+ // 1 and 8 make the code throw ImagingOpException, 2 and 4
+ // make the code SEGV on Sol.
+
+ byte[] lut1Arr = new byte[] {0, (byte)255 };
+ byte[] lut2Arr = new byte[] {0, (byte)85, (byte)170, (byte)255};
+ byte[] lut4Arr = new byte[] {0, (byte)17, (byte)34, (byte)51,
+ (byte)68, (byte)85,(byte) 102, (byte)119,
+ (byte)136, (byte)153, (byte)170, (byte)187,
+ (byte)204, (byte)221, (byte)238, (byte)255};
+ byte[] lut8Arr = new byte[256];
+ for (int i = 0; i < 256; i++) {
+ lut8Arr[i] = (byte)i;
+ }
+
+ // Create the binary image
+ int bytesPerRow = width * pixelBits / 8;
+ byte[] imageData = new byte[height * bytesPerRow];
+ ColorModel cm = null;
+
+ switch (pixelBits) {
+ case 1:
+ cm = new IndexColorModel(pixelBits, lut1Arr.length,
+ lut1Arr, lut1Arr, lut1Arr);
+ break;
+ case 2:
+ cm = new IndexColorModel(pixelBits, lut2Arr.length,
+ lut2Arr, lut2Arr, lut2Arr);
+ break;
+ case 4:
+ cm = new IndexColorModel(pixelBits, lut4Arr.length,
+ lut4Arr, lut4Arr, lut4Arr);
+ break;
+ case 8:
+ cm = new IndexColorModel(pixelBits, lut8Arr.length,
+ lut8Arr, lut8Arr, lut8Arr);
+ break;
+ default:
+ {new Exception("Invalid # of bit per pixel").printStackTrace();}
+ }
+
+ DataBuffer db = new DataBufferByte(imageData, imageData.length);
+ WritableRaster r = Raster.createPackedRaster(db, width, height,
+ pixelBits, null);
+ BufferedImage srcImage = new BufferedImage(cm, r, false, null);
+
+ BufferedImage destImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = destImage.createGraphics();
+ AffineTransform af = AffineTransform.getScaleInstance(.5, .5);
+ // This draw image is the problem
+ g.drawImage(srcImage, af, null);
+ int blackPixel = Color.black.getRGB();
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ if (destImage.getRGB(x, y) != blackPixel) {
+ throw new RuntimeException("Not black");
+ }
+ }
+ }
+ }
+}
diff --git a/test/jdk/sun/awt/image/ImageRepresentation/ByteBinaryBitmask.java b/test/jdk/sun/awt/image/ImageRepresentation/ByteBinaryBitmask.java
new file mode 100644
index 0000000000000..26edca7f09b72
--- /dev/null
+++ b/test/jdk/sun/awt/image/ImageRepresentation/ByteBinaryBitmask.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2002, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 4673490
+ * @summary This test verifies that Toolkit images with a 1-bit
+ * IndexColorModel (known as ByteBinary) and a transparent index are rendered properly.
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.IndexColorModel;
+
+public class ByteBinaryBitmask {
+
+ public static void main(String argv[]) throws Exception {
+
+ /* Create the image */
+ int w = 16, h = 16;
+ byte[] bw = { (byte)255, (byte)0, };
+ IndexColorModel icm = new IndexColorModel(1, 2, bw, bw, bw, 0);
+ BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY, icm);
+ Graphics2D g2d = img.createGraphics();
+ g2d.setColor(Color.white);
+ g2d.fillRect(0, 0, w, h);
+ g2d.setColor(Color.black);
+ int xoff = 5;
+ g2d.fillRect(xoff, 5, 1, 10); // 1 pixel wide
+
+ int dw = 200, dh = 50;
+ BufferedImage dest = new BufferedImage(dw, dh, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = dest.createGraphics();
+ g.setColor(Color.green);
+ g.fillRect(0, 0, dw, dh);
+ int x1 = 10;
+ int x2 = 50;
+ int x3 = 90;
+ int x4 = 130;
+ g.drawImage(img, x1, 10, null);
+ g.drawImage(img, x2, 10, null);
+ g.drawImage(img, x3, 10, null);
+ g.drawImage(img, x4, 10, null);
+
+ int blackPix = Color.black.getRGB();
+ for (int y = 0; y < dh; y++) {
+ boolean isBlack = false;
+ for (int x = 0; x < dw; x++) {
+ int rgb = dest.getRGB(x, y);
+ if (rgb == blackPix) {
+ /* Src image has a one pixel wide vertical rect at off "xoff" and
+ * this is drawn at x1/x2/x3/x4) so the sum of those are the x locations
+ * to expect black.
+ */
+ if (x != (x1 + xoff) && x != (x2 + xoff) && x != (x3 + xoff) && x!= (x4 + xoff)) {
+ throw new RuntimeException("wrong x location: " +x);
+ }
+ if (isBlack) {
+ throw new RuntimeException("black after black");
+ }
+ }
+ isBlack = rgb == blackPix;
+ }
+ }
+ }
+}
diff --git a/test/jdk/sun/awt/image/ImageRepresentation/CustomSourceCM.java b/test/jdk/sun/awt/image/ImageRepresentation/CustomSourceCM.java
new file mode 100644
index 0000000000000..c56b4ef88c807
--- /dev/null
+++ b/test/jdk/sun/awt/image/ImageRepresentation/CustomSourceCM.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1999, 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 4192756
+ * @summary Tests that using a non-default colormodel generates correct images under 16/24 bit mode
+ */
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.DirectColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.MemoryImageSource;
+import java.util.Arrays;
+
+/*
+ * NOTE: This bug only appears under specific conditions. If the background of
+ * the surface is red, then you are not running under the conditions necessary
+ * to test for the regression so the results of this test will be inconclusive.
+ *
+ * The test should be run under any of the following screen depths/surfaces:
+ *
+ * 15-bit, otherwise known as 555 RGB or 32768 (thousands) colors
+ * 16-bit, otherwise known as 565 RGB or 65536 (thousands) colors
+ * 24-bit, otherwise known as 16777216 (millions) colors
+ *
+ * The test draws 2 rectangles. Both rectangles should be half black (left)
+ * and half blue (right). If the top rectangle is all black, the test fails.
+ * If the background is red, the results are inconclusive (see above).
+*/
+
+public class CustomSourceCM extends Component {
+
+ public static int IMG_W = 80;
+ public static int IMG_H = 30;
+
+ static void test(int imageType) {
+
+ int w = IMG_W + 20;
+ int h = IMG_H * 2 + 40;
+ BufferedImage bi = new BufferedImage(w, h, imageType);
+
+ DirectColorModel dcm;
+
+ /* the next dozen lines or so are intended to help
+ * ascertain if the destination surface is of the type
+ * that exhibited the original bug, making the background
+ * white in those cases. It is not strictly necessary.
+ * It is only for a manual tester to be able to tell by looking.
+ * The real test is the check for black and blue later on.
+ */
+ Graphics2D g = bi.createGraphics();
+ g.setColor(Color.red);
+ g.fillRect(0, 0, w, h);
+
+ ColorModel cm = bi.getColorModel();
+ if (cm instanceof ComponentColorModel) {
+ g.setColor(Color.white);
+ g.fillRect(0, 0, w, h);
+ } else if (cm instanceof DirectColorModel) {
+ dcm = (DirectColorModel) cm;
+ if (dcm.getPixelSize() < 24) {
+ g.setColor(Color.white);
+ g.fillRect(0, 0, w, h);
+ }
+ }
+
+ // Construct a ColorModel and data for a 16-bit 565 image...
+ dcm = new DirectColorModel(16, 0x1f, 0x7e0, 0xf800);
+
+ // Create an image which is black on the left, blue on the right.
+ int[] pixels = new int[IMG_W * IMG_H];
+ int blue = dcm.getBlueMask();
+ int off = 0;
+ for (int y = 0; y < IMG_H; y++) {
+ Arrays.fill(pixels, off, off+IMG_W/2, 0);
+ Arrays.fill(pixels, off+IMG_W/2, off+IMG_W, blue);
+ off += IMG_W;
+ }
+ MemoryImageSource mis = new MemoryImageSource(IMG_W, IMG_H, dcm,
+ pixels, 0, IMG_W);
+ CustomSourceCM comp = new CustomSourceCM();
+ Image img = comp.createImage(mis);
+
+ // Draw the image on to the surface.
+ g.drawImage(img, 10, 10, null);
+
+ // Create a similar effect with 2 fillrects, below the image.
+ g.setColor(Color.black);
+ g.fillRect(10, 60, IMG_W/2, IMG_H);
+ g.setColor(Color.blue);
+ g.fillRect(10+IMG_W/2, 60, IMG_W/2, IMG_H);
+
+ // Now sample points in the image to confirm they are the expected color.
+ int bluePix = Color.blue.getRGB();
+ int blackPix = Color.black.getRGB();
+ int black_topLeft = bi.getRGB(10+IMG_W/4, 10+IMG_H/2);
+ int blue_topRight = bi.getRGB(10+IMG_W*3/4, 10+IMG_H/2);
+ int black_bottomLeft = bi.getRGB(10+IMG_W/4, 60+IMG_H/2);
+ int blue_bottomRight = bi.getRGB(10+IMG_W*3/4, 60+IMG_H/2);
+ if ((black_topLeft != blackPix) || (black_bottomLeft != blackPix) ||
+ (blue_topRight != bluePix) || (blue_bottomRight != bluePix)) {
+
+ String fileName = "failed " + imageType + ".png";
+ try {
+ javax.imageio.ImageIO.write(bi, "png", new java.io.File(fileName));
+ } catch (Exception e) { };
+ throw new RuntimeException("unexpected colors");
+ }
+ }
+
+ public static void main(String argv[]) {
+ test(BufferedImage.TYPE_USHORT_555_RGB);
+ test(BufferedImage.TYPE_USHORT_565_RGB);
+ test(BufferedImage.TYPE_3BYTE_BGR);
+ }
+}
diff --git a/test/jdk/sun/java2d/loops/ARGBBgToRGB.java b/test/jdk/sun/java2d/loops/ARGBBgToRGB.java
new file mode 100644
index 0000000000000..55764af2c1354
--- /dev/null
+++ b/test/jdk/sun/java2d/loops/ARGBBgToRGB.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 4238978
+ * @summary This test verifies that the correct blitting loop is being used.
+ * The correct output should have a yellow border on the top and
+ * left sides of a red box. The incorrect output would have only
+ * a red box -- no yellow border."
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+public class ARGBBgToRGB {
+
+ public static void main(String[] argv) {
+ BufferedImage bi = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D big = bi.createGraphics();
+ big.setColor(Color.red);
+ big.fillRect(30, 30, 150, 150);
+
+ BufferedImage bi2 = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D big2 = bi2.createGraphics();
+ big2.drawImage(bi, 0, 0, Color.yellow, null);
+
+ int expectYellowPix = bi2.getRGB(0, 0);
+ int expectRedPix = bi2.getRGB(50, 50);
+ if ((expectYellowPix != Color.yellow.getRGB()) ||
+ (expectRedPix != Color.red.getRGB()))
+ {
+ throw new RuntimeException("Unexpected colors " + expectYellowPix + " " + expectRedPix);
+ }
+ }
+}
diff --git a/test/jdk/sun/java2d/loops/CopyNegative.java b/test/jdk/sun/java2d/loops/CopyNegative.java
new file mode 100644
index 0000000000000..0b8296918ac63
--- /dev/null
+++ b/test/jdk/sun/java2d/loops/CopyNegative.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1999, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 4188744
+ * @summary This test verifies that copyArea performs correctly for negative offset values.
+ * The correct output shows that the text area is moved to the left and down,
+ * leaving some garbage on the right and the top.
+ * The incorrect copy would show the text area garbled and no text is legible.
+ * @library /java/awt/regtesthelpers
+ * @build PassFailJFrame
+ * @run main/manual CopyNegative
+ */
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.Panel;
+
+public class CopyNegative extends Panel {
+
+ private static final String INSTRUCTIONS = """
+ This test verifies that copyArea performs correctly for negative offset values.
+ The test draws text in an image, then copies the contents repeatedly.
+ The correct output shows that the text is moved to the left and down,
+ leaving some garbage on the top / right and some legible text at the bottom left.
+ The incorrect copy would show the whole text area garbled and no text is legible.
+ """;
+
+ public static void main(String[] argv) throws Exception {
+ PassFailJFrame.builder()
+ .title("CopyNegativeTest")
+ .instructions(INSTRUCTIONS)
+ .testUI(CopyNegative::createUI)
+ .testTimeOut(5)
+ .rows(10)
+ .columns(50)
+ .build()
+ .awaitAndCheck();
+ }
+
+ Image img;
+
+ static final int W = 200, H = 200;
+
+ static Frame createUI() {
+ Frame f = new Frame("CopyNegative");
+ f.add(new CopyNegative());
+ f.pack();
+ return f;
+ }
+
+ public Dimension getPreferredSize() {
+ return new Dimension(W, H);
+ }
+
+ private void doCopy() {
+ Graphics g = img.getGraphics();
+ g.setColor(Color.white);
+ g.fillRect(0, 0, W, H);
+ g.setColor(Color.black);
+ String text = "Some Text To Display, it is long enough to fill the entire display line.";
+ StringBuffer sb = new StringBuffer(text);
+
+ for (int i = 1; i < 50; i++) {
+ g.drawString(sb.toString(), 5,20 * i - 10);
+ sb.insert(0, Integer.toString(i));
+ }
+ for (int i = 0 ; i < 20 ; i++ ) {
+ g.copyArea(0, 0, W, H, -3, 3);
+ }
+ }
+
+ public void paint(Graphics g) {
+ img = createImage(W, H);
+ doCopy();
+ g.drawImage(img, 0, 0, this);
+ }
+
+}
diff --git a/test/jdk/sun/java2d/loops/DitheredSolidFill.java b/test/jdk/sun/java2d/loops/DitheredSolidFill.java
new file mode 100644
index 0000000000000..509b0bbe3b234
--- /dev/null
+++ b/test/jdk/sun/java2d/loops/DitheredSolidFill.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1999, 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 4181172
+ * @summary Confirm that solid white fill is not dithered on an 8-bit indexed surface.
+ * The test draws two areas filled with white solid color.
+ * The upper left square is filled in aliasing mode and
+ * the lower right square is filled in anti-aliasing mode.
+ */
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+
+public class DitheredSolidFill {
+
+ public static void main(String args[]) {
+ BufferedImage bi = new BufferedImage(120, 120, BufferedImage.TYPE_BYTE_INDEXED);
+ Graphics2D g2D = bi.createGraphics();
+
+ g2D.setColor(Color.black);
+ g2D.fillRect(0, 0, 100, 100);
+
+ g2D.setColor(Color.white);
+ g2D.fillRect(5, 5, 40, 40);
+ checkPixels(bi, 5, 5, 40, 40);
+
+ g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2D.fillRect(55, 55, 40, 40);
+ checkPixels(bi, 55, 55, 40, 40);
+ }
+
+ static void checkPixels(BufferedImage bi, int x, int y, int w, int h) {
+ // pixel can be off white, but must be the same in all cases.
+ int expectedPix = bi.getRGB(x, y);
+ for (int x0 = x; x0 < x + w; x0++) {
+ for (int y0 = y; y0 < y + h; y0++) {
+ if (bi.getRGB(x0, y0) != expectedPix) {
+ try {
+ javax.imageio.ImageIO.write(bi, "png", new java.io.File("failed.png"));
+ } catch (Exception e) {
+ }
+ throw new RuntimeException("Not expected pix : " +
+ Integer.toHexString(bi.getRGB(x0, y0)) +
+ " at " + x0 + "," + y0);
+ }
+ }
+ }
+ }
+}
diff --git a/test/jdk/sun/java2d/loops/OffsetCalculationTest.java b/test/jdk/sun/java2d/loops/OffsetCalculationTest.java
new file mode 100644
index 0000000000000..fe30107f22a9f
--- /dev/null
+++ b/test/jdk/sun/java2d/loops/OffsetCalculationTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1999, 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.
+ *
+ * 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.
+ */
+
+/*
+ @test
+ @bug 4236576
+ @summary tests that a BufferedImage in TYPE_3BYTE_BGR format is correctly
+ drawn when there is an offset between the Graphics clip bounds
+ and the clip box of the underlying device context.
+ @run main OffsetCalculationTest
+*/
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBuffer;
+
+public class OffsetCalculationTest {
+
+ public static void main(String[] args) {
+ BufferedImage srcImage = new BufferedImage(500, 500, BufferedImage.TYPE_3BYTE_BGR);
+
+ DataBuffer buffer = srcImage.getRaster().getDataBuffer();
+ for (int i = 2; i < buffer.getSize(); i+=3) {
+ // setting each pixel to blue via the data buffer elements.
+ buffer.setElem(i - 2, 0xff);
+ buffer.setElem(i - 1, 0);
+ buffer.setElem(i, 0);
+ }
+
+ int w = 200, h = 200;
+ BufferedImage destImage = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
+ Graphics2D g = destImage.createGraphics();
+ Rectangle r = new Rectangle(0, 0, w, h);
+ g.setClip(r.x - 1, r.y, r.width + 1, r.height);
+ g.drawImage(srcImage, 0, 0, null);
+
+ int bluepix = Color.blue.getRGB();
+ for (int y = 0; y < w; y++) {
+ for (int x = 0; x < h; x++) {
+ if (destImage.getRGB(x, y) != bluepix) {
+ throw new RuntimeException("Not Blue");
+ }
+ }
+ }
+ }
+}
diff --git a/test/jdk/sun/java2d/loops/XORClearRect.java b/test/jdk/sun/java2d/loops/XORClearRect.java
new file mode 100644
index 0000000000000..f5c30581cf1f3
--- /dev/null
+++ b/test/jdk/sun/java2d/loops/XORClearRect.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1999, 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 4088173
+ * @summary This interactive test verifies that the XOR mode is not affecting
+ * the clearRect() call. The correct output looks like:
+ *
+ * \ /
+ * \ /
+ * The backgound is blue.
+ * The lines outside the central rectangle are green.
+ * The central rectangle is also blue (the result of clearRect())
+ * / \
+ * / \
+ *
+ * @key headful
+ * @run main XORClearRect
+ */
+
+import java.awt.Color;
+import java.awt.EventQueue;
+import java.awt.Graphics;
+import java.awt.Frame;
+import java.awt.Panel;
+import java.awt.Point;
+import java.awt.Robot;
+
+public class XORClearRect extends Panel {
+
+ public static void main(String args[]) throws Exception {
+ EventQueue.invokeAndWait(XORClearRect::createUI);
+ try {
+ Robot robot = new Robot();
+ robot.waitForIdle();
+ robot.delay(2000);
+ Point p = frame.getLocationOnScreen();
+ int pix = robot.getPixelColor(p.x + 100, p.y + 100).getRGB();
+ if (pix != Color.blue.getRGB()) {
+ throw new RuntimeException("Not blue");
+ }
+ } finally {
+ if (frame != null) {
+ EventQueue.invokeAndWait(frame::dispose);
+ }
+ }
+ }
+
+ static volatile Frame frame;
+
+ static void createUI() {
+ frame = new Frame("XORClearRect");
+ frame.setBackground(Color.blue);
+ XORClearRect xor = new XORClearRect();
+ frame.add(xor);
+ frame.setSize(200,200);
+ frame.setVisible(true);
+ }
+
+ public XORClearRect() {
+ setBackground(Color.blue);
+ }
+
+ public void paint(Graphics g) {
+ g.setColor(Color.green);
+ g.drawLine(0,0,200,200);
+ g.drawLine(0,200,200,0);
+ g.setXORMode(Color.blue);
+ g.clearRect(50,50,100,100); //expecting the rectangle to be filled
+ // with the background color (blue)
+ }
+}
diff --git a/test/jdk/tools/launcher/MultipleJRERemoved.java b/test/jdk/tools/launcher/MultipleJRERemoved.java
deleted file mode 100644
index 551ffc885f275..0000000000000
--- a/test/jdk/tools/launcher/MultipleJRERemoved.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, 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.
- *
- * 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.
- */
-
-/**
- * @test
- * @bug 8067437
- * @summary Verify Multiple JRE version support has been removed.
- * @modules jdk.compiler
- * jdk.zipfs
- * @build TestHelper
- * @run main MultipleJRERemoved
- */
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.util.*;
-import java.util.jar.Attributes;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.zip.ZipEntry;
-
-public class MultipleJRERemoved extends TestHelper {
-
- public static final String VERSION_JAR = "version.jar";
- public static final String PRINT_VERSION_CLASS = "PrintVersion";
- private final File javaFile = new File(PRINT_VERSION_CLASS + ".java");
- private final File clsFile = new File(PRINT_VERSION_CLASS + ".class");
-
- private MultipleJRERemoved() {
- }
-
- /**
- * @param args the command line arguments
- * @throws java.io.FileNotFoundException
- */
- public static void main(String[] args) throws Exception {
- MultipleJRERemoved a = new MultipleJRERemoved();
- a.run(args);
- }
-
- /**
- * Check all combinations of flags: "-version:", "-jre-restrict-search", "-jre-no-restrict-search". Test expects to see errors.
- */
- @Test
- public void allFlagCombinations() throws IOException {
- final Pattern newLine = Pattern.compile("\n");
- createJar(Collections.emptyMap());
-
- for (Flag flag1 : Flag.values()) {
- for (Flag flag2 : Flag.values()) {
- for (Flag flag3 : Flag.values()) {
- List flags = Stream.of(flag1, flag2, flag3)
- .filter(f -> !Flag.EMPTY.equals(f))
- .collect(Collectors.toList());
-
- if (flags.size() == 0) continue;
-
- List flagValues = flags.stream()
- .map(Flag::value)
- .collect(Collectors.toList());
-
- List errorMessages = flags.stream()
- .map(Flag::errorMessage)
- .flatMap(newLine::splitAsStream)
- .collect(Collectors.toList());
-
- List jarCmd = new ArrayList<>();
- jarCmd.add(javaCmd);
- jarCmd.addAll(flagValues);
- jarCmd.add("-jar");
- jarCmd.add("version.jar");
-
- check(jarCmd, errorMessages);
-
- List cmd = new ArrayList<>();
- cmd.add(javaCmd);
- cmd.addAll(flagValues);
- cmd.add(PRINT_VERSION_CLASS);
-
- check(cmd, errorMessages);
- }
- }
- }
- }
-
- private void check(List cmd, List errorMessages) {
- TestResult tr = doExec(cmd.toArray(new String[cmd.size()]));
- tr.checkNegative();
- tr.isNotZeroOutput();
- errorMessages.forEach(tr::contains);
-
- if (!tr.testStatus) {
- System.out.println(tr);
- throw new RuntimeException("test case: failed\n" + cmd);
- }
- }
-
- /**
- * Verifies that java -help output doesn't contain information about "mJRE" flags.
- */
- @Test
- public void javaHelp() {
- TestResult tr = doExec(javaCmd, "-help");
- tr.checkPositive();
- tr.isNotZeroOutput();
- tr.notContains("-version:");
- tr.notContains("-jre-restrict-search");
- tr.notContains("-jre-no-restrict-search");
- tr.notContains("-no-jre-restrict-search"); //it's not a typo in flag name.
- if (!tr.testStatus) {
- System.out.println(tr);
- throw new RuntimeException("Failed. java -help output contains obsolete flags.\n");
- }
- }
-
- /**
- * Verifies that java -jar version.jar output ignores "mJRE" manifest directives.
- */
- @Test
- public void manifestDirectives() throws IOException {
- Map manifest = new TreeMap<>();
- manifest.put("JRE-Version", "1.8");
- manifest.put("JRE-Restrict-Search", "1.8");
- createJar(manifest);
-
- TestResult tr = doExec(javaCmd, "-jar", VERSION_JAR);
- tr.checkPositive();
- tr.contains(System.getProperty("java.version"));
- if (!tr.testStatus) {
- System.out.println(tr);
- throw new RuntimeException("Failed.\n");
- }
- }
-
- private void emitFile() throws IOException {
- List scr = new ArrayList<>();
- scr.add("public class PrintVersion {");
- scr.add(" public static void main(String... args) {");
- scr.add(" System.out.println(System.getProperty(\"java.version\"));");
- scr.add(" }");
- scr.add("}");
- createFile(javaFile, scr);
- compile(javaFile.getName());
- }
-
- private void createJar(Map manifestAttributes) throws IOException {
- emitFile();
-
- Manifest manifest = new Manifest();
- final Attributes mainAttributes = manifest.getMainAttributes();
- mainAttributes.putValue("Manifest-Version", "1.0");
- mainAttributes.putValue("Main-Class", PRINT_VERSION_CLASS);
- manifestAttributes.forEach(mainAttributes::putValue);
-
- try (JarOutputStream jar = new JarOutputStream(new FileOutputStream(VERSION_JAR), manifest)) {
- jar.putNextEntry(new ZipEntry(PRINT_VERSION_CLASS + ".class"));
- jar.write(Files.readAllBytes(clsFile.toPath()));
- jar.closeEntry();
- } finally {
- javaFile.delete();
- }
- }
-
- private enum Flag {
- EMPTY("", ""),
- VERSION("-version:1.9", "Error: Specifying an alternate JDK/JRE version is no longer supported.\n" +
- "The use of the flag '-version:' is no longer valid.\n" +
- "Please download and execute the appropriate version."),
- JRE_RESTRICT_SEARCH("-jre-restrict-search", "Error: Specifying an alternate JDK/JRE is no longer supported.\n" +
- "The related flags -jre-restrict-search | -jre-no-restrict-search are also no longer valid."),
- JRE_NO_RESTRICT_SEARCH("-jre-no-restrict-search", "Error: Specifying an alternate JDK/JRE is no longer supported.\n" +
- "The related flags -jre-restrict-search | -jre-no-restrict-search are also no longer valid.");
- private final String flag;
- private final String errorMessage;
-
- Flag(String flag, String errorMessage) {
- this.flag = flag;
- this.errorMessage = errorMessage;
- }
-
- String value() {
- return flag;
- }
-
- String errorMessage() {
- return errorMessage;
- }
- }
-}
diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java
index 795a658afa591..5aa703c5b26c2 100644
--- a/test/jtreg-ext/requires/VMProps.java
+++ b/test/jtreg-ext/requires/VMProps.java
@@ -386,6 +386,7 @@ protected void vmOptFinalFlags(SafeMap map) {
vmOptFinalFlag(map, "EnableJVMCI");
vmOptFinalFlag(map, "EliminateAllocations");
vmOptFinalFlag(map, "UseCompressedOops");
+ vmOptFinalFlag(map, "UseLargePages");
vmOptFinalFlag(map, "UseVectorizedMismatchIntrinsic");
vmOptFinalFlag(map, "ZGenerational");
}
diff --git a/test/langtools/jdk/javadoc/doclet/testMarkdown/TestMarkdownCodeBlocks.java b/test/langtools/jdk/javadoc/doclet/testMarkdown/TestMarkdownCodeBlocks.java
index 8f1c76b9e474d..dda8a76868e12 100644
--- a/test/langtools/jdk/javadoc/doclet/testMarkdown/TestMarkdownCodeBlocks.java
+++ b/test/langtools/jdk/javadoc/doclet/testMarkdown/TestMarkdownCodeBlocks.java
@@ -486,4 +486,107 @@ public int hashCode() {