From 62a4be03cfcb5dcae77358ff25fdc9e2e9660575 Mon Sep 17 00:00:00 2001
From: Albert Mingkun Yang
Date: Tue, 13 Feb 2024 08:47:00 +0000
Subject: [PATCH 01/36] 8325635: Serial: Inline
verify_used_region_at_save_marks
Reviewed-by: stefank, tschatzl
---
src/hotspot/share/gc/serial/cardTableRS.cpp | 19 ++++++-------------
src/hotspot/share/gc/serial/cardTableRS.hpp | 3 ---
2 files changed, 6 insertions(+), 16 deletions(-)
diff --git a/src/hotspot/share/gc/serial/cardTableRS.cpp b/src/hotspot/share/gc/serial/cardTableRS.cpp
index 5d431b3eb1a05..87c0eba819298 100644
--- a/src/hotspot/share/gc/serial/cardTableRS.cpp
+++ b/src/hotspot/share/gc/serial/cardTableRS.cpp
@@ -32,27 +32,20 @@
#include "utilities/align.hpp"
void CardTableRS::scan_old_to_young_refs(TenuredSpace* sp) {
- verify_used_region_at_save_marks(sp);
-
+ const MemRegion ur = sp->used_region();
const MemRegion urasm = sp->used_region_at_save_marks();
- if (!urasm.is_empty()) {
- OldGenScanClosure cl(SerialHeap::heap()->young_gen());
- non_clean_card_iterate(sp, urasm, &cl);
- }
-}
-
-#ifdef ASSERT
-void CardTableRS::verify_used_region_at_save_marks(Space* sp) const {
- MemRegion ur = sp->used_region();
- MemRegion urasm = sp->used_region_at_save_marks();
assert(ur.contains(urasm),
"Did you forget to call save_marks()? "
"[" PTR_FORMAT ", " PTR_FORMAT ") is not contained in "
"[" PTR_FORMAT ", " PTR_FORMAT ")",
p2i(urasm.start()), p2i(urasm.end()), p2i(ur.start()), p2i(ur.end()));
+
+ if (!urasm.is_empty()) {
+ OldGenScanClosure cl(SerialHeap::heap()->young_gen());
+ non_clean_card_iterate(sp, urasm, &cl);
+ }
}
-#endif
void CardTableRS::maintain_old_to_young_invariant(TenuredGeneration* old_gen,
bool is_young_gen_empty) {
diff --git a/src/hotspot/share/gc/serial/cardTableRS.hpp b/src/hotspot/share/gc/serial/cardTableRS.hpp
index 545185fb54048..7ad6f8aef0b13 100644
--- a/src/hotspot/share/gc/serial/cardTableRS.hpp
+++ b/src/hotspot/share/gc/serial/cardTableRS.hpp
@@ -30,7 +30,6 @@
#include "oops/oop.hpp"
class OldGenScanClosure;
-class Space;
class TenuredGeneration;
class TenuredSpace;
@@ -63,8 +62,6 @@ class CardTableRS : public CardTable {
void scan_old_to_young_refs(TenuredSpace* sp);
- virtual void verify_used_region_at_save_marks(Space* sp) const NOT_DEBUG_RETURN;
-
void inline_write_ref_field_gc(void* field) {
CardValue* byte = byte_for(field);
*byte = dirty_card_val();
From 4513da949670dfd29ca64183edc78ca44432aeb3 Mon Sep 17 00:00:00 2001
From: Matthias Baesken
Date: Tue, 13 Feb 2024 09:03:47 +0000
Subject: [PATCH 02/36] 8325470: [AIX] use fclose after fopen in read_psinfo
Reviewed-by: mdoerr, kbarrett
---
src/hotspot/os/aix/os_perf_aix.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/hotspot/os/aix/os_perf_aix.cpp b/src/hotspot/os/aix/os_perf_aix.cpp
index e1719df48c331..b5ae1a6a725a5 100644
--- a/src/hotspot/os/aix/os_perf_aix.cpp
+++ b/src/hotspot/os/aix/os_perf_aix.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2022, IBM Corp.
+ * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, IBM Corp.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -87,6 +87,7 @@ static bool read_psinfo(const u_longlong_t& pid, psinfo_t& psinfo) {
}
len = fread(&psinfo, 1, sizeof(psinfo_t), fp);
+ fclose(fp);
return len == sizeof(psinfo_t);
}
From 5dbf13730ee2b57f089c57e9e7ee8ab65d4a67af Mon Sep 17 00:00:00 2001
From: Axel Boldt-Christmas
Date: Tue, 13 Feb 2024 09:32:58 +0000
Subject: [PATCH 03/36] 8319797: Recursive lightweight locking: Runtime
implementation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Stefan Karlsson
Co-authored-by: Erik Österlund
Reviewed-by: rkennke, dcubed, coleenp, stefank
---
src/hotspot/share/prims/whitebox.cpp | 11 +
.../share/runtime/abstract_vm_version.hpp | 5 +-
src/hotspot/share/runtime/lockStack.cpp | 23 +-
src/hotspot/share/runtime/lockStack.hpp | 35 +-
.../share/runtime/lockStack.inline.hpp | 137 +++++-
src/hotspot/share/runtime/objectMonitor.hpp | 1 +
.../share/runtime/objectMonitor.inline.hpp | 8 +-
src/hotspot/share/runtime/synchronizer.cpp | 108 ++++-
test/hotspot/gtest/runtime/test_lockStack.cpp | 427 ++++++++++++++++++
test/hotspot/jtreg/TEST.groups | 3 +-
test/hotspot/jtreg/gtest/LockStackGtests.java | 32 ++
.../lockStack/TestLockStackCapacity.java | 108 +++++
test/lib/jdk/test/whitebox/WhiteBox.java | 6 +-
13 files changed, 856 insertions(+), 48 deletions(-)
create mode 100644 test/hotspot/gtest/runtime/test_lockStack.cpp
create mode 100644 test/hotspot/jtreg/gtest/LockStackGtests.java
create mode 100644 test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java
diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp
index 99ed98cdfac4c..dbb9566cd22c6 100644
--- a/src/hotspot/share/prims/whitebox.cpp
+++ b/src/hotspot/share/prims/whitebox.cpp
@@ -85,6 +85,7 @@
#include "runtime/javaCalls.hpp"
#include "runtime/javaThread.inline.hpp"
#include "runtime/jniHandles.inline.hpp"
+#include "runtime/lockStack.hpp"
#include "runtime/os.hpp"
#include "runtime/stackFrameStream.inline.hpp"
#include "runtime/synchronizer.hpp"
@@ -1847,6 +1848,14 @@ WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
return (jboolean) obj_oop->mark().has_monitor();
WB_END
+WB_ENTRY(jint, WB_getLockStackCapacity(JNIEnv* env))
+ return (jint) LockStack::CAPACITY;
+WB_END
+
+WB_ENTRY(jboolean, WB_supportsRecursiveLightweightLocking(JNIEnv* env))
+ return (jboolean) VM_Version::supports_recursive_lightweight_locking();
+WB_END
+
WB_ENTRY(jboolean, WB_DeflateIdleMonitors(JNIEnv* env, jobject wb))
log_info(monitorinflation)("WhiteBox initiated DeflateIdleMonitors");
return ObjectSynchronizer::request_deflate_idle_monitors_from_wb();
@@ -2829,6 +2838,8 @@ static JNINativeMethod methods[] = {
(void*)&WB_AddModuleExportsToAll },
{CC"deflateIdleMonitors", CC"()Z", (void*)&WB_DeflateIdleMonitors },
{CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
+ {CC"getLockStackCapacity", CC"()I", (void*)&WB_getLockStackCapacity },
+ {CC"supportsRecursiveLightweightLocking", CC"()Z", (void*)&WB_supportsRecursiveLightweightLocking },
{CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
{CC"forceClassLoaderStatsSafepoint", CC"()V", (void*)&WB_ForceClassLoaderStatsSafepoint },
{CC"getConstantPool0", CC"(Ljava/lang/Class;)J", (void*)&WB_GetConstantPool },
diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp
index ec3b7177a6658..6fca13ece855f 100644
--- a/src/hotspot/share/runtime/abstract_vm_version.hpp
+++ b/src/hotspot/share/runtime/abstract_vm_version.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
@@ -187,6 +187,9 @@ class Abstract_VM_Version: AllStatic {
// Does platform support stack watermark barriers for concurrent stack processing?
constexpr static bool supports_stack_watermark_barrier() { return false; }
+ // Is recursive lightweight locking implemented for this platform?
+ constexpr static bool supports_recursive_lightweight_locking() { return false; }
+
// Does platform support float16 instructions?
static bool supports_float16() { return false; }
diff --git a/src/hotspot/share/runtime/lockStack.cpp b/src/hotspot/share/runtime/lockStack.cpp
index b4a3bf1e8e6c0..d7dcbdda7e968 100644
--- a/src/hotspot/share/runtime/lockStack.cpp
+++ b/src/hotspot/share/runtime/lockStack.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2022, Red Hat, Inc. All rights reserved.
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+ * 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
@@ -25,20 +26,30 @@
#include "precompiled.hpp"
#include "memory/allocation.hpp"
+#include "runtime/globals.hpp"
#include "runtime/lockStack.inline.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/stackWatermark.hpp"
#include "runtime/stackWatermarkSet.inline.hpp"
#include "runtime/thread.hpp"
#include "utilities/copy.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/globalDefinitions.hpp"
#include "utilities/ostream.hpp"
+#include
+
const int LockStack::lock_stack_offset = in_bytes(JavaThread::lock_stack_offset());
const int LockStack::lock_stack_top_offset = in_bytes(JavaThread::lock_stack_top_offset());
const int LockStack::lock_stack_base_offset = in_bytes(JavaThread::lock_stack_base_offset());
LockStack::LockStack(JavaThread* jt) :
_top(lock_stack_base_offset), _base() {
+ // Make sure the layout of the object is compatible with the emitted code's assumptions.
+ STATIC_ASSERT(sizeof(_bad_oop_sentinel) == oopSize);
+ STATIC_ASSERT(sizeof(_base[0]) == oopSize);
+ STATIC_ASSERT(std::is_standard_layout::value);
+ STATIC_ASSERT(offsetof(LockStack, _bad_oop_sentinel) == offsetof(LockStack, _base) - oopSize);
#ifdef ASSERT
for (int i = 0; i < CAPACITY; i++) {
_base[i] = nullptr;
@@ -62,11 +73,21 @@ uint32_t LockStack::end_offset() {
void LockStack::verify(const char* msg) const {
assert(LockingMode == LM_LIGHTWEIGHT, "never use lock-stack when light weight locking is disabled");
assert((_top <= end_offset()), "lockstack overflow: _top %d end_offset %d", _top, end_offset());
- assert((_top >= start_offset()), "lockstack underflow: _top %d end_offset %d", _top, start_offset());
+ assert((_top >= start_offset()), "lockstack underflow: _top %d start_offset %d", _top, start_offset());
if (SafepointSynchronize::is_at_safepoint() || (Thread::current()->is_Java_thread() && is_owning_thread())) {
int top = to_index(_top);
for (int i = 0; i < top; i++) {
assert(_base[i] != nullptr, "no zapped before top");
+ if (VM_Version::supports_recursive_lightweight_locking()) {
+ oop o = _base[i];
+ for (; i < top - 1; i++) {
+ // Consecutive entries may be the same
+ if (_base[i + 1] != o) {
+ break;
+ }
+ }
+ }
+
for (int j = i + 1; j < top; j++) {
assert(_base[i] != _base[j], "entries must be unique: %s", msg);
}
diff --git a/src/hotspot/share/runtime/lockStack.hpp b/src/hotspot/share/runtime/lockStack.hpp
index d5216793aea10..17b0a1ca836ee 100644
--- a/src/hotspot/share/runtime/lockStack.hpp
+++ b/src/hotspot/share/runtime/lockStack.hpp
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2022, Red Hat, Inc. All rights reserved.
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+ * 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
@@ -35,10 +36,12 @@ class OopClosure;
class outputStream;
class LockStack {
+ friend class LockStackTest;
friend class VMStructs;
JVMCI_ONLY(friend class JVMCIVMStructs;)
-private:
+public:
static const int CAPACITY = 8;
+private:
// TODO: It would be very useful if JavaThread::lock_stack_offset() and friends were constexpr,
// but this is currently not the case because we're using offset_of() which is non-constexpr,
@@ -51,6 +54,9 @@ class LockStack {
// We do this instead of a simple index into the array because this allows for
// efficient addressing in generated code.
uint32_t _top;
+ // The _bad_oop_sentinel acts as a sentinel value to elide underflow checks in generated code.
+ // The correct layout is statically asserted in the constructor.
+ const uintptr_t _bad_oop_sentinel = badOopVal;
oop _base[CAPACITY];
// Get the owning thread of this lock-stack.
@@ -75,14 +81,35 @@ class LockStack {
static uint32_t start_offset();
static uint32_t end_offset();
- // Return true if we have room to push onto this lock-stack, false otherwise.
- inline bool can_push() const;
+ // Returns true if the lock-stack is full. False otherwise.
+ inline bool is_full() const;
// Pushes an oop on this lock-stack.
inline void push(oop o);
+ // Get the oldest oop from this lock-stack.
+ // Precondition: This lock-stack must not be empty.
+ inline oop bottom() const;
+
+ // Is the lock-stack empty.
+ inline bool is_empty() const;
+
+ // Check if object is recursive.
+ // Precondition: This lock-stack must contain the oop.
+ inline bool is_recursive(oop o) const;
+
+ // Try recursive enter.
+ // Precondition: This lock-stack must not be full.
+ inline bool try_recursive_enter(oop o);
+
+ // Try recursive exit.
+ // Precondition: This lock-stack must contain the oop.
+ inline bool try_recursive_exit(oop o);
+
// Removes an oop from an arbitrary location of this lock-stack.
- inline void remove(oop o);
+ // Precondition: This lock-stack must contain the oop.
+ // Returns the number of oops removed.
+ inline size_t remove(oop o);
// Tests whether the oop is on this lock-stack.
inline bool contains(oop o) const;
diff --git a/src/hotspot/share/runtime/lockStack.inline.hpp b/src/hotspot/share/runtime/lockStack.inline.hpp
index be63c51d8e5e1..7a9874a9291d5 100644
--- a/src/hotspot/share/runtime/lockStack.inline.hpp
+++ b/src/hotspot/share/runtime/lockStack.inline.hpp
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2022, Red Hat, Inc. All rights reserved.
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+ * 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
@@ -26,14 +27,20 @@
#ifndef SHARE_RUNTIME_LOCKSTACK_INLINE_HPP
#define SHARE_RUNTIME_LOCKSTACK_INLINE_HPP
+#include "runtime/lockStack.hpp"
+
#include "memory/iterator.hpp"
#include "runtime/javaThread.hpp"
-#include "runtime/lockStack.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/stackWatermark.hpp"
#include "runtime/stackWatermarkSet.inline.hpp"
+#include "utilities/align.hpp"
+#include "utilities/globalDefinitions.hpp"
inline int LockStack::to_index(uint32_t offset) {
+ assert(is_aligned(offset, oopSize), "Bad alignment: %u", offset);
+ assert((offset <= end_offset()), "lockstack overflow: offset %d end_offset %d", offset, end_offset());
+ assert((offset >= start_offset()), "lockstack underflow: offset %d start_offset %d", offset, start_offset());
return (offset - lock_stack_base_offset) / oopSize;
}
@@ -42,8 +49,8 @@ JavaThread* LockStack::get_thread() const {
return reinterpret_cast(addr - lock_stack_offset);
}
-inline bool LockStack::can_push() const {
- return to_index(_top) < CAPACITY;
+inline bool LockStack::is_full() const {
+ return to_index(_top) == CAPACITY;
}
inline bool LockStack::is_owning_thread() const {
@@ -61,32 +68,132 @@ inline void LockStack::push(oop o) {
verify("pre-push");
assert(oopDesc::is_oop(o), "must be");
assert(!contains(o), "entries must be unique");
- assert(can_push(), "must have room");
+ assert(!is_full(), "must have room");
assert(_base[to_index(_top)] == nullptr, "expect zapped entry");
_base[to_index(_top)] = o;
_top += oopSize;
verify("post-push");
}
-inline void LockStack::remove(oop o) {
+inline oop LockStack::bottom() const {
+ assert(to_index(_top) > 0, "must contain an oop");
+ return _base[0];
+}
+
+inline bool LockStack::is_empty() const {
+ return to_index(_top) == 0;
+}
+
+inline bool LockStack::is_recursive(oop o) const {
+ if (!VM_Version::supports_recursive_lightweight_locking()) {
+ return false;
+ }
+ verify("pre-is_recursive");
+
+ // This will succeed iff there is a consecutive run of oops on the
+ // lock-stack with a length of at least 2.
+
+ assert(contains(o), "at least one entry must exist");
+ int end = to_index(_top);
+ // Start iterating from the top because the runtime code is more
+ // interested in the balanced locking case when the top oop on the
+ // lock-stack matches o. This will cause the for loop to break out
+ // in the first loop iteration if it is non-recursive.
+ for (int i = end - 1; i > 0; i--) {
+ if (_base[i - 1] == o && _base[i] == o) {
+ verify("post-is_recursive");
+ return true;
+ }
+ if (_base[i] == o) {
+ // o can only occur in one consecutive run on the lock-stack.
+ // Only one of the two oops checked matched o, so this run
+ // must be of length 1 and thus not be recursive. Stop the search.
+ break;
+ }
+ }
+
+ verify("post-is_recursive");
+ return false;
+}
+
+inline bool LockStack::try_recursive_enter(oop o) {
+ if (!VM_Version::supports_recursive_lightweight_locking()) {
+ return false;
+ }
+ verify("pre-try_recursive_enter");
+
+ // This will succeed iff the top oop on the stack matches o.
+ // When successful o will be pushed to the lock-stack creating
+ // a consecutive run at least 2 oops that matches o on top of
+ // the lock-stack.
+
+ assert(!is_full(), "precond");
+
+ int end = to_index(_top);
+ if (end == 0 || _base[end - 1] != o) {
+ // Topmost oop does not match o.
+ verify("post-try_recursive_enter");
+ return false;
+ }
+
+ _base[end] = o;
+ _top += oopSize;
+ verify("post-try_recursive_enter");
+ return true;
+}
+
+inline bool LockStack::try_recursive_exit(oop o) {
+ if (!VM_Version::supports_recursive_lightweight_locking()) {
+ return false;
+ }
+ verify("pre-try_recursive_exit");
+
+ // This will succeed iff the top two oops on the stack matches o.
+ // When successful the top oop will be popped of the lock-stack.
+ // When unsuccessful the lock may still be recursive, in which
+ // case the locking is unbalanced. This case is handled externally.
+
+ assert(contains(o), "entries must exist");
+
+ int end = to_index(_top);
+ if (end <= 1 || _base[end - 1] != o || _base[end - 2] != o) {
+ // The two topmost oops do not match o.
+ verify("post-try_recursive_exit");
+ return false;
+ }
+
+ _top -= oopSize;
+ DEBUG_ONLY(_base[to_index(_top)] = nullptr;)
+ verify("post-try_recursive_exit");
+ return true;
+}
+
+inline size_t LockStack::remove(oop o) {
verify("pre-remove");
assert(contains(o), "entry must be present: " PTR_FORMAT, p2i(o));
+
int end = to_index(_top);
+ int inserted = 0;
for (int i = 0; i < end; i++) {
- if (_base[i] == o) {
- int last = end - 1;
- for (; i < last; i++) {
- _base[i] = _base[i + 1];
+ if (_base[i] != o) {
+ if (inserted != i) {
+ _base[inserted] = _base[i];
}
- _top -= oopSize;
-#ifdef ASSERT
- _base[to_index(_top)] = nullptr;
-#endif
- break;
+ inserted++;
}
}
- assert(!contains(o), "entries must be unique: " PTR_FORMAT, p2i(o));
+
+#ifdef ASSERT
+ for (int i = inserted; i < end; i++) {
+ _base[i] = nullptr;
+ }
+#endif
+
+ uint32_t removed = end - inserted;
+ _top -= removed * oopSize;
+ assert(!contains(o), "entry must have been removed: " PTR_FORMAT, p2i(o));
verify("post-remove");
+ return removed;
}
inline bool LockStack::contains(oop o) const {
diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp
index 81a5c10a3b3b8..d69cf5eba8c95 100644
--- a/src/hotspot/share/runtime/objectMonitor.hpp
+++ b/src/hotspot/share/runtime/objectMonitor.hpp
@@ -295,6 +295,7 @@ class ObjectMonitor : public CHeapObj {
int contentions() const;
void add_to_contentions(int value);
intx recursions() const { return _recursions; }
+ void set_recursions(size_t recursions);
// JVM/TI GetObjectMonitorUsage() needs this:
ObjectWaiter* first_waiter() { return _WaitSet; }
diff --git a/src/hotspot/share/runtime/objectMonitor.inline.hpp b/src/hotspot/share/runtime/objectMonitor.inline.hpp
index 36790925b7146..b371663eeb326 100644
--- a/src/hotspot/share/runtime/objectMonitor.inline.hpp
+++ b/src/hotspot/share/runtime/objectMonitor.inline.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -102,6 +102,12 @@ inline void ObjectMonitor::add_to_contentions(int value) {
Atomic::add(&_contentions, value);
}
+inline void ObjectMonitor::set_recursions(size_t recursions) {
+ assert(_recursions == 0, "must be");
+ assert(has_owner(), "must be owned");
+ _recursions = checked_cast(recursions);
+}
+
// Clear _owner field; current value must match old_value.
inline void ObjectMonitor::release_clear_owner(void* old_value) {
#ifdef ASSERT
diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp
index 6f10e817b5e07..3a4eb4d0d1a2c 100644
--- a/src/hotspot/share/runtime/synchronizer.cpp
+++ b/src/hotspot/share/runtime/synchronizer.cpp
@@ -393,6 +393,19 @@ bool ObjectSynchronizer::quick_enter(oop obj, JavaThread* current,
return false;
}
+ if (LockingMode == LM_LIGHTWEIGHT) {
+ LockStack& lock_stack = current->lock_stack();
+ if (lock_stack.is_full()) {
+ // Always go into runtime if the lock stack is full.
+ return false;
+ }
+ if (lock_stack.try_recursive_enter(obj)) {
+ // Recursive lock successful.
+ current->inc_held_monitor_count();
+ return true;
+ }
+ }
+
const markWord mark = obj->mark();
if (mark.has_monitor()) {
@@ -559,21 +572,53 @@ bool ObjectSynchronizer::enter_fast_impl(Handle obj, BasicLock* lock, JavaThread
if (LockingMode == LM_LIGHTWEIGHT) {
// Fast-locking does not use the 'lock' argument.
LockStack& lock_stack = locking_thread->lock_stack();
- if (lock_stack.can_push()) {
- markWord mark = obj()->mark_acquire();
- while (mark.is_neutral()) {
- // Retry until a lock state change has been observed. cas_set_mark() may collide with non lock bits modifications.
- // Try to swing into 'fast-locked' state.
- assert(!lock_stack.contains(obj()), "thread must not already hold the lock");
- const markWord locked_mark = mark.set_fast_locked();
- const markWord old_mark = obj()->cas_set_mark(locked_mark, mark);
- if (old_mark == mark) {
- // Successfully fast-locked, push object to lock-stack and return.
- lock_stack.push(obj());
- return true;
- }
- mark = old_mark;
+ if (lock_stack.is_full()) {
+ // We unconditionally make room on the lock stack by inflating
+ // the least recently locked object on the lock stack.
+
+ // About the choice to inflate least recently locked object.
+ // First we must chose to inflate a lock, either some lock on
+ // the lock-stack or the lock that is currently being entered
+ // (which may or may not be on the lock-stack).
+ // Second the best lock to inflate is a lock which is entered
+ // in a control flow where there are only a very few locks being
+ // used, as the costly part of inflated locking is inflation,
+ // not locking. But this property is entirely program dependent.
+ // Third inflating the lock currently being entered on when it
+ // is not present on the lock-stack will result in a still full
+ // lock-stack. This creates a scenario where every deeper nested
+ // monitorenter must call into the runtime.
+ // The rational here is as follows:
+ // Because we cannot (currently) figure out the second, and want
+ // to avoid the third, we inflate a lock on the lock-stack.
+ // The least recently locked lock is chosen as it is the lock
+ // with the longest critical section.
+
+ log_info(monitorinflation)("LockStack capacity exceeded, inflating.");
+ ObjectMonitor* monitor = inflate_for(locking_thread, lock_stack.bottom(), inflate_cause_vm_internal);
+ assert(monitor->owner() == Thread::current(), "must be owner=" PTR_FORMAT " current=" PTR_FORMAT " mark=" PTR_FORMAT,
+ p2i(monitor->owner()), p2i(Thread::current()), monitor->object()->mark_acquire().value());
+ assert(!lock_stack.is_full(), "must have made room here");
+ }
+
+ markWord mark = obj()->mark_acquire();
+ while (mark.is_neutral()) {
+ // Retry until a lock state change has been observed. cas_set_mark() may collide with non lock bits modifications.
+ // Try to swing into 'fast-locked' state.
+ assert(!lock_stack.contains(obj()), "thread must not already hold the lock");
+ const markWord locked_mark = mark.set_fast_locked();
+ const markWord old_mark = obj()->cas_set_mark(locked_mark, mark);
+ if (old_mark == mark) {
+ // Successfully fast-locked, push object to lock-stack and return.
+ lock_stack.push(obj());
+ return true;
}
+ mark = old_mark;
+ }
+
+ if (mark.is_fast_locked() && lock_stack.try_recursive_enter(obj())) {
+ // Recursive lock successful.
+ return true;
}
// Failed to fast lock.
@@ -618,15 +663,28 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current)
markWord mark = object->mark();
if (LockingMode == LM_LIGHTWEIGHT) {
// Fast-locking does not use the 'lock' argument.
- while (mark.is_fast_locked()) {
- // Retry until a lock state change has been observed. cas_set_mark() may collide with non lock bits modifications.
- const markWord unlocked_mark = mark.set_unlocked();
- const markWord old_mark = object->cas_set_mark(unlocked_mark, mark);
- if (old_mark == mark) {
- current->lock_stack().remove(object);
- return;
+ LockStack& lock_stack = current->lock_stack();
+ if (mark.is_fast_locked() && lock_stack.try_recursive_exit(object)) {
+ // Recursively unlocked.
+ return;
+ }
+
+ if (mark.is_fast_locked() && lock_stack.is_recursive(object)) {
+ // This lock is recursive but is not at the top of the lock stack so we're
+ // doing an unbalanced exit. We have to fall thru to inflation below and
+ // let ObjectMonitor::exit() do the unlock.
+ } else {
+ while (mark.is_fast_locked()) {
+ // Retry until a lock state change has been observed. cas_set_mark() may collide with non lock bits modifications.
+ const markWord unlocked_mark = mark.set_unlocked();
+ const markWord old_mark = object->cas_set_mark(unlocked_mark, mark);
+ if (old_mark == mark) {
+ size_t recursions = lock_stack.remove(object) - 1;
+ assert(recursions == 0, "must not be recursive here");
+ return;
+ }
+ mark = old_mark;
}
- mark = old_mark;
}
} else if (LockingMode == LM_LEGACY) {
markWord dhw = lock->displaced_header();
@@ -1375,7 +1433,8 @@ ObjectMonitor* ObjectSynchronizer::inflate_impl(JavaThread* inflating_thread, oo
if (LockingMode == LM_LIGHTWEIGHT && inf->is_owner_anonymous() &&
inflating_thread != nullptr && inflating_thread->lock_stack().contains(object)) {
inf->set_owner_from_anonymous(inflating_thread);
- inflating_thread->lock_stack().remove(object);
+ size_t removed = inflating_thread->lock_stack().remove(object);
+ inf->set_recursions(removed - 1);
}
return inf;
}
@@ -1421,7 +1480,8 @@ ObjectMonitor* ObjectSynchronizer::inflate_impl(JavaThread* inflating_thread, oo
if (old_mark == mark) {
// Success! Return inflated monitor.
if (own) {
- inflating_thread->lock_stack().remove(object);
+ size_t removed = inflating_thread->lock_stack().remove(object);
+ monitor->set_recursions(removed - 1);
}
// Once the ObjectMonitor is configured and object is associated
// with the ObjectMonitor, it is safe to allow async deflation:
diff --git a/test/hotspot/gtest/runtime/test_lockStack.cpp b/test/hotspot/gtest/runtime/test_lockStack.cpp
new file mode 100644
index 0000000000000..43e8959ed260d
--- /dev/null
+++ b/test/hotspot/gtest/runtime/test_lockStack.cpp
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2023, 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.
+ */
+
+#include "precompiled.hpp"
+#include "runtime/interfaceSupport.inline.hpp"
+#include "runtime/lockStack.inline.hpp"
+#include "runtime/os.hpp"
+#include "unittest.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class LockStackTest : public ::testing::Test {
+public:
+ static void push_raw(LockStack& ls, oop obj) {
+ ls._base[ls.to_index(ls._top)] = obj;
+ ls._top += oopSize;
+ }
+
+ static void pop_raw(LockStack& ls) {
+ ls._top -= oopSize;
+#ifdef ASSERT
+ ls._base[ls.to_index(ls._top)] = nullptr;
+#endif
+ }
+
+ static oop at(LockStack& ls, int index) {
+ return ls._base[index];
+ }
+
+ static size_t size(LockStack& ls) {
+ return ls.to_index(ls._top);
+ }
+};
+
+#define recursive_enter(ls, obj) \
+ do { \
+ bool ret = ls.try_recursive_enter(obj); \
+ EXPECT_TRUE(ret); \
+ } while (false)
+
+#define recursive_exit(ls, obj) \
+ do { \
+ bool ret = ls.try_recursive_exit(obj); \
+ EXPECT_TRUE(ret); \
+ } while (false)
+
+TEST_VM_F(LockStackTest, is_recursive) {
+ if (LockingMode != LM_LIGHTWEIGHT || !VM_Version::supports_recursive_lightweight_locking()) {
+ return;
+ }
+
+ JavaThread* THREAD = JavaThread::current();
+ // the thread should be in vm to use locks
+ ThreadInVMfromNative ThreadInVMfromNative(THREAD);
+
+ LockStack& ls = THREAD->lock_stack();
+
+ EXPECT_TRUE(ls.is_empty());
+
+ oop obj0 = Universe::int_mirror();
+ oop obj1 = Universe::float_mirror();
+
+ push_raw(ls, obj0);
+
+ // 0
+ EXPECT_FALSE(ls.is_recursive(obj0));
+
+ push_raw(ls, obj1);
+
+ // 0, 1
+ EXPECT_FALSE(ls.is_recursive(obj0));
+ EXPECT_FALSE(ls.is_recursive(obj1));
+
+ push_raw(ls, obj1);
+
+ // 0, 1, 1
+ EXPECT_FALSE(ls.is_recursive(obj0));
+ EXPECT_TRUE(ls.is_recursive(obj1));
+
+ pop_raw(ls);
+ pop_raw(ls);
+ push_raw(ls, obj0);
+
+ // 0, 0
+ EXPECT_TRUE(ls.is_recursive(obj0));
+
+ push_raw(ls, obj0);
+
+ // 0, 0, 0
+ EXPECT_TRUE(ls.is_recursive(obj0));
+
+ pop_raw(ls);
+ push_raw(ls, obj1);
+
+ // 0, 0, 1
+ EXPECT_TRUE(ls.is_recursive(obj0));
+ EXPECT_FALSE(ls.is_recursive(obj1));
+
+ push_raw(ls, obj1);
+
+ // 0, 0, 1, 1
+ EXPECT_TRUE(ls.is_recursive(obj0));
+ EXPECT_TRUE(ls.is_recursive(obj1));
+
+ // Clear stack
+ pop_raw(ls);
+ pop_raw(ls);
+ pop_raw(ls);
+ pop_raw(ls);
+
+ EXPECT_TRUE(ls.is_empty());
+}
+
+TEST_VM_F(LockStackTest, try_recursive_enter) {
+ if (LockingMode != LM_LIGHTWEIGHT || !VM_Version::supports_recursive_lightweight_locking()) {
+ return;
+ }
+
+ JavaThread* THREAD = JavaThread::current();
+ // the thread should be in vm to use locks
+ ThreadInVMfromNative ThreadInVMfromNative(THREAD);
+
+ LockStack& ls = THREAD->lock_stack();
+
+ EXPECT_TRUE(ls.is_empty());
+
+ oop obj0 = Universe::int_mirror();
+ oop obj1 = Universe::float_mirror();
+
+ ls.push(obj0);
+
+ // 0
+ EXPECT_FALSE(ls.is_recursive(obj0));
+
+ ls.push(obj1);
+
+ // 0, 1
+ EXPECT_FALSE(ls.is_recursive(obj0));
+ EXPECT_FALSE(ls.is_recursive(obj1));
+
+ recursive_enter(ls, obj1);
+
+ // 0, 1, 1
+ EXPECT_FALSE(ls.is_recursive(obj0));
+ EXPECT_TRUE(ls.is_recursive(obj1));
+
+ recursive_exit(ls, obj1);
+ pop_raw(ls);
+ recursive_enter(ls, obj0);
+
+ // 0, 0
+ EXPECT_TRUE(ls.is_recursive(obj0));
+
+ recursive_enter(ls, obj0);
+
+ // 0, 0, 0
+ EXPECT_TRUE(ls.is_recursive(obj0));
+
+ recursive_exit(ls, obj0);
+ push_raw(ls, obj1);
+
+ // 0, 0, 1
+ EXPECT_TRUE(ls.is_recursive(obj0));
+ EXPECT_FALSE(ls.is_recursive(obj1));
+
+ recursive_enter(ls, obj1);
+
+ // 0, 0, 1, 1
+ EXPECT_TRUE(ls.is_recursive(obj0));
+ EXPECT_TRUE(ls.is_recursive(obj1));
+
+ // Clear stack
+ pop_raw(ls);
+ pop_raw(ls);
+ pop_raw(ls);
+ pop_raw(ls);
+
+ EXPECT_TRUE(ls.is_empty());
+}
+
+TEST_VM_F(LockStackTest, contains) {
+ if (LockingMode != LM_LIGHTWEIGHT) {
+ return;
+ }
+
+ const bool test_recursive = VM_Version::supports_recursive_lightweight_locking();
+
+ JavaThread* THREAD = JavaThread::current();
+ // the thread should be in vm to use locks
+ ThreadInVMfromNative ThreadInVMfromNative(THREAD);
+
+ LockStack& ls = THREAD->lock_stack();
+
+ EXPECT_TRUE(ls.is_empty());
+
+ oop obj0 = Universe::int_mirror();
+ oop obj1 = Universe::float_mirror();
+
+ EXPECT_FALSE(ls.contains(obj0));
+
+ ls.push(obj0);
+
+ // 0
+ EXPECT_TRUE(ls.contains(obj0));
+ EXPECT_FALSE(ls.contains(obj1));
+
+ if (test_recursive) {
+ push_raw(ls, obj0);
+
+ // 0, 0
+ EXPECT_TRUE(ls.contains(obj0));
+ EXPECT_FALSE(ls.contains(obj1));
+ }
+
+ push_raw(ls, obj1);
+
+ // 0, 0, 1
+ EXPECT_TRUE(ls.contains(obj0));
+ EXPECT_TRUE(ls.contains(obj1));
+
+ if (test_recursive) {
+ push_raw(ls, obj1);
+
+ // 0, 0, 1, 1
+ EXPECT_TRUE(ls.contains(obj0));
+ EXPECT_TRUE(ls.contains(obj1));
+ }
+
+ pop_raw(ls);
+ if (test_recursive) {
+ pop_raw(ls);
+ pop_raw(ls);
+ }
+ push_raw(ls, obj1);
+
+ // 0, 1
+ EXPECT_TRUE(ls.contains(obj0));
+ EXPECT_TRUE(ls.contains(obj1));
+
+ // Clear stack
+ pop_raw(ls);
+ pop_raw(ls);
+
+ EXPECT_TRUE(ls.is_empty());
+}
+
+TEST_VM_F(LockStackTest, remove) {
+ if (LockingMode != LM_LIGHTWEIGHT) {
+ return;
+ }
+
+ const bool test_recursive = VM_Version::supports_recursive_lightweight_locking();
+
+ JavaThread* THREAD = JavaThread::current();
+ // the thread should be in vm to use locks
+ ThreadInVMfromNative ThreadInVMfromNative(THREAD);
+
+ LockStack& ls = THREAD->lock_stack();
+
+ EXPECT_TRUE(ls.is_empty());
+
+ oop obj0 = Universe::int_mirror();
+ oop obj1 = Universe::float_mirror();
+ oop obj2 = Universe::short_mirror();
+ oop obj3 = Universe::long_mirror();
+
+ push_raw(ls, obj0);
+
+ // 0
+ {
+ size_t removed = ls.remove(obj0);
+ EXPECT_EQ(removed, 1u);
+ EXPECT_FALSE(ls.contains(obj0));
+ }
+
+ if (test_recursive) {
+ push_raw(ls, obj0);
+ push_raw(ls, obj0);
+
+ // 0, 0
+ {
+ size_t removed = ls.remove(obj0);
+ EXPECT_EQ(removed, 2u);
+ EXPECT_FALSE(ls.contains(obj0));
+ }
+ }
+
+ push_raw(ls, obj0);
+ push_raw(ls, obj1);
+
+ // 0, 1
+ {
+ size_t removed = ls.remove(obj0);
+ EXPECT_EQ(removed, 1u);
+ EXPECT_FALSE(ls.contains(obj0));
+ EXPECT_TRUE(ls.contains(obj1));
+
+ ls.remove(obj1);
+ EXPECT_TRUE(ls.is_empty());
+ }
+
+ push_raw(ls, obj0);
+ push_raw(ls, obj1);
+
+ // 0, 1
+ {
+ size_t removed = ls.remove(obj1);
+ EXPECT_EQ(removed, 1u);
+ EXPECT_FALSE(ls.contains(obj1));
+ EXPECT_TRUE(ls.contains(obj0));
+
+ ls.remove(obj0);
+ EXPECT_TRUE(ls.is_empty());
+ }
+
+ if (test_recursive) {
+ push_raw(ls, obj0);
+ push_raw(ls, obj0);
+ push_raw(ls, obj1);
+
+ // 0, 0, 1
+ {
+ size_t removed = ls.remove(obj0);
+ EXPECT_EQ(removed, 2u);
+ EXPECT_FALSE(ls.contains(obj0));
+ EXPECT_TRUE(ls.contains(obj1));
+
+ ls.remove(obj1);
+ EXPECT_TRUE(ls.is_empty());
+ }
+
+ push_raw(ls, obj0);
+ push_raw(ls, obj1);
+ push_raw(ls, obj1);
+
+ // 0, 1, 1
+ {
+ size_t removed = ls.remove(obj1);
+ EXPECT_EQ(removed, 2u);
+ EXPECT_FALSE(ls.contains(obj1));
+ EXPECT_TRUE(ls.contains(obj0));
+
+ ls.remove(obj0);
+ EXPECT_TRUE(ls.is_empty());
+ }
+
+ push_raw(ls, obj0);
+ push_raw(ls, obj1);
+ push_raw(ls, obj1);
+ push_raw(ls, obj2);
+ push_raw(ls, obj2);
+ push_raw(ls, obj2);
+ push_raw(ls, obj2);
+ push_raw(ls, obj3);
+
+ // 0, 1, 1, 2, 2, 2, 2, 3
+ {
+ EXPECT_EQ(size(ls), 8u);
+
+ size_t removed = ls.remove(obj1);
+ EXPECT_EQ(removed, 2u);
+
+ EXPECT_TRUE(ls.contains(obj0));
+ EXPECT_FALSE(ls.contains(obj1));
+ EXPECT_TRUE(ls.contains(obj2));
+ EXPECT_TRUE(ls.contains(obj3));
+
+ EXPECT_EQ(at(ls, 0), obj0);
+ EXPECT_EQ(at(ls, 1), obj2);
+ EXPECT_EQ(at(ls, 2), obj2);
+ EXPECT_EQ(at(ls, 3), obj2);
+ EXPECT_EQ(at(ls, 4), obj2);
+ EXPECT_EQ(at(ls, 5), obj3);
+ EXPECT_EQ(size(ls), 6u);
+
+ removed = ls.remove(obj2);
+ EXPECT_EQ(removed, 4u);
+
+ EXPECT_TRUE(ls.contains(obj0));
+ EXPECT_FALSE(ls.contains(obj1));
+ EXPECT_FALSE(ls.contains(obj2));
+ EXPECT_TRUE(ls.contains(obj3));
+
+ EXPECT_EQ(at(ls, 0), obj0);
+ EXPECT_EQ(at(ls, 1), obj3);
+ EXPECT_EQ(size(ls), 2u);
+
+ removed = ls.remove(obj0);
+ EXPECT_EQ(removed, 1u);
+
+ EXPECT_FALSE(ls.contains(obj0));
+ EXPECT_FALSE(ls.contains(obj1));
+ EXPECT_FALSE(ls.contains(obj2));
+ EXPECT_TRUE(ls.contains(obj3));
+
+ EXPECT_EQ(at(ls, 0), obj3);
+ EXPECT_EQ(size(ls), 1u);
+
+ removed = ls.remove(obj3);
+ EXPECT_EQ(removed, 1u);
+
+ EXPECT_TRUE(ls.is_empty());
+ EXPECT_EQ(size(ls), 0u);
+ }
+ }
+
+ EXPECT_TRUE(ls.is_empty());
+}
diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups
index 7c48edcb10520..22ce64b980135 100644
--- a/test/hotspot/jtreg/TEST.groups
+++ b/test/hotspot/jtreg/TEST.groups
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 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
@@ -142,6 +142,7 @@ serviceability_ttf_virtual = \
tier1_common = \
sanity/BasicVMTest.java \
gtest/GTestWrapper.java \
+ gtest/LockStackGtests.java \
gtest/MetaspaceGtests.java \
gtest/LargePageGtests.java \
gtest/NMTGtests.java \
diff --git a/test/hotspot/jtreg/gtest/LockStackGtests.java b/test/hotspot/jtreg/gtest/LockStackGtests.java
new file mode 100644
index 0000000000000..e426b2c56f3b3
--- /dev/null
+++ b/test/hotspot/jtreg/gtest/LockStackGtests.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023, 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
+ * @summary Run LockStack gtests with LockingMode=2
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.xml
+ * @requires vm.flagless
+ * @run main/native GTestWrapper --gtest_filter=LockStackTest* -XX:LockingMode=2
+ */
diff --git a/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java b/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java
new file mode 100644
index 0000000000000..01ba1f4f12c65
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java
@@ -0,0 +1,108 @@
+/*
+ * 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 TestLockStackCapacity
+ * @summary Tests the interaction between recursive lightweight locking and
+ * when the lock stack capacity is exceeded.
+ * @requires vm.flagless
+ * @library /testlibrary /test/lib
+ * @build jdk.test.whitebox.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xint -XX:LockingMode=2 TestLockStackCapacity
+ */
+
+import jdk.test.lib.Asserts;
+import jdk.test.whitebox.WhiteBox;
+import jtreg.SkippedException;
+
+public class TestLockStackCapacity {
+ static final WhiteBox WB = WhiteBox.getWhiteBox();
+ static final int LockingMode = WB.getIntVMFlag("LockingMode").intValue();
+ static final int LM_LIGHTWEIGHT = 2;
+
+ static class SynchronizedObject {
+ static final SynchronizedObject OUTER = new SynchronizedObject();
+ static final SynchronizedObject INNER = new SynchronizedObject();
+ static final int LockStackCapacity = WB.getLockStackCapacity();
+
+ synchronized void runInner(int depth) {
+ assertNotInflated();
+ if (depth == 1) {
+ return;
+ } else {
+ runInner(depth - 1);
+ }
+ assertNotInflated();
+ }
+
+ synchronized void runOuter(int depth, SynchronizedObject inner) {
+ assertNotInflated();
+ if (depth == 1) {
+ inner.runInner(LockStackCapacity);
+ } else {
+ runOuter(depth - 1, inner);
+ }
+ assertInflated();
+ }
+
+ public static void runTest() {
+ // Test Requires a capacity of at least 2.
+ Asserts.assertGTE(LockStackCapacity, 2);
+
+ // Just checking
+ OUTER.assertNotInflated();
+ INNER.assertNotInflated();
+
+ synchronized(OUTER) {
+ OUTER.assertNotInflated();
+ INNER.assertNotInflated();
+ OUTER.runOuter(LockStackCapacity - 1, INNER);
+
+ OUTER.assertInflated();
+ INNER.assertNotInflated();
+ }
+ }
+
+ void assertNotInflated() {
+ Asserts.assertFalse(WB.isMonitorInflated(this));
+ }
+
+ void assertInflated() {
+ Asserts.assertTrue(WB.isMonitorInflated(this));
+ }
+ }
+
+ public static void main(String... args) throws Exception {
+ if (LockingMode != LM_LIGHTWEIGHT) {
+ throw new SkippedException("Test only valid for LM_LIGHTWEIGHT");
+ }
+
+ if (!WB.supportsRecursiveLightweightLocking()) {
+ throw new SkippedException("Test only valid if LM_LIGHTWEIGHT supports recursion");
+ }
+
+ SynchronizedObject.runTest();
+ }
+}
diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java
index 2d33182331d4f..2402e39974e3d 100644
--- a/test/lib/jdk/test/whitebox/WhiteBox.java
+++ b/test/lib/jdk/test/whitebox/WhiteBox.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -119,6 +119,10 @@ public boolean isMonitorInflated(Object obj) {
return isMonitorInflated0(obj);
}
+ public native int getLockStackCapacity();
+
+ public native boolean supportsRecursiveLightweightLocking();
+
public native void forceSafepoint();
public native void forceClassLoaderStatsSafepoint();
From 618af397b4c636c89049f7398c14f37f0065df59 Mon Sep 17 00:00:00 2001
From: Albert Mingkun Yang
Date: Tue, 13 Feb 2024 09:41:12 +0000
Subject: [PATCH 04/36] 8325633: Use stricter assertion in callers of
Space::is_aligned
Reviewed-by: tschatzl, sjohanss
---
src/hotspot/share/gc/serial/defNewGeneration.cpp | 6 +++---
src/hotspot/share/gc/shared/space.cpp | 4 ++--
src/hotspot/share/gc/shared/space.hpp | 5 -----
3 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp
index b85041c80a512..52858683c0887 100644
--- a/src/hotspot/share/gc/serial/defNewGeneration.cpp
+++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp
@@ -335,9 +335,9 @@ void DefNewGeneration::compute_space_boundaries(uintx minimum_eden_size,
char *to_end = to_start + survivor_size;
assert(to_end == _virtual_space.high(), "just checking");
- assert(Space::is_aligned(eden_start), "checking alignment");
- assert(Space::is_aligned(from_start), "checking alignment");
- assert(Space::is_aligned(to_start), "checking alignment");
+ assert(is_aligned(eden_start, SpaceAlignment), "checking alignment");
+ assert(is_aligned(from_start, SpaceAlignment), "checking alignment");
+ assert(is_aligned(to_start, SpaceAlignment), "checking alignment");
MemRegion edenMR((HeapWord*)eden_start, (HeapWord*)from_start);
MemRegion fromMR((HeapWord*)from_start, (HeapWord*)to_start);
diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp
index 069b672b54426..82e32a17b432d 100644
--- a/src/hotspot/share/gc/shared/space.cpp
+++ b/src/hotspot/share/gc/shared/space.cpp
@@ -197,7 +197,7 @@ inline HeapWord* ContiguousSpace::allocate_impl(size_t size) {
if (pointer_delta(end(), obj) >= size) {
HeapWord* new_top = obj + size;
set_top(new_top);
- assert(is_aligned(obj) && is_aligned(new_top), "checking alignment");
+ assert(is_object_aligned(obj) && is_object_aligned(new_top), "checking alignment");
return obj;
} else {
return nullptr;
@@ -215,7 +215,7 @@ inline HeapWord* ContiguousSpace::par_allocate_impl(size_t size) {
// the old top value: the exchange succeeded
// otherwise: the new value of the top is returned.
if (result == obj) {
- assert(is_aligned(obj) && is_aligned(new_top), "checking alignment");
+ assert(is_object_aligned(obj) && is_object_aligned(new_top), "checking alignment");
return obj;
}
} else {
diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp
index 8e6f4f88a6bad..dbfed7fe759f4 100644
--- a/src/hotspot/share/gc/shared/space.hpp
+++ b/src/hotspot/share/gc/shared/space.hpp
@@ -122,11 +122,6 @@ class Space: public CHeapObj {
// given address.
bool is_in_reserved(const void* p) const { return _bottom <= p && p < _end; }
- // Test whether p is double-aligned
- static bool is_aligned(void* p) {
- return ::is_aligned(p, sizeof(double));
- }
-
// Size computations. Sizes are in bytes.
size_t capacity() const { return byte_size(bottom(), end()); }
virtual size_t used() const = 0;
From ec20b0aa2ed711daeea5d0a09102093b3a2a49ec Mon Sep 17 00:00:00 2001
From: Magnus Ihse Bursie
Date: Tue, 13 Feb 2024 09:51:33 +0000
Subject: [PATCH 05/36] 8325626: Allow selection of non-matching configurations
using CONF=!string
Reviewed-by: erikj, jwaters
---
doc/building.html | 29 ++++++++++++++++++++---------
doc/building.md | 25 +++++++++++++++++++------
make/Global.gmk | 7 +++----
make/InitSupport.gmk | 10 ++++++++--
4 files changed, 50 insertions(+), 21 deletions(-)
diff --git a/doc/building.html b/doc/building.html
index d51e74d1454be..96d2916de41e4 100644
--- a/doc/building.html
+++ b/doc/building.html
@@ -2166,15 +2166,26 @@ Using Multiple
configure
from there, e.g.
mkdir build/<name> && cd build/<name> && bash ../../configure
.
Then you can build that configuration using
-make CONF_NAME=<name>
or
-make CONF=<pattern>
, where
-<pattern>
is a substring matching one or several
-configurations, e.g. CONF=debug
. The special empty pattern
-(CONF=
) will match all available configuration, so
-make CONF= hotspot
will build the hotspot
-target for all configurations. Alternatively, you can execute
-make
in the configuration directory, e.g.
-cd build/<name> && make
.
+make CONF=<selector>
, where
+<selector>
is interpreted as follows:
+
+If <selector>
exacly matches the name of a
+configuration, this and only this configuration will be selected.
+If <selector>
matches (i.e. is a substring of)
+the names of several configurations, then all these configurations will
+be selected.
+If <selector>
is empty (i.e. CONF=
),
+then all configurations will be selected.
+If <selector>
begins with !
, then
+all configurations not matching the string following
+!
will be selected.
+
+A more specialized version, CONF_NAME=<name>
also
+exists, which will only match if the given <name>
+exactly matches a single configuration.
+Alternatively, you can execute make
in the configuration
+directory, e.g. cd build/<name> && make
.
+make CONF_NAME=<name>
or
Handling Reconfigurations
If you update the repository and part of the configure script has
changed, the build system will force you to re-run
diff --git a/doc/building.md b/doc/building.md
index 9d928a3924557..61daed2270bbe 100644
--- a/doc/building.md
+++ b/doc/building.md
@@ -1952,12 +1952,25 @@ configuration with the name ``. Alternatively, you can create a directory
under `build` and run `configure` from there, e.g. `mkdir build/ && cd
build/ && bash ../../configure`.
-Then you can build that configuration using `make CONF_NAME=` or `make
-CONF=`, where `` is a substring matching one or several
-configurations, e.g. `CONF=debug`. The special empty pattern (`CONF=`) will
-match *all* available configuration, so `make CONF= hotspot` will build the
-`hotspot` target for all configurations. Alternatively, you can execute `make`
-in the configuration directory, e.g. `cd build/ && make`.
+Then you can build that configuration using `make CONF=`, where
+`` is interpreted as follows:
+
+* If `` exacly matches the name of a configuration, this and only
+ this configuration will be selected.
+* If `` matches (i.e. is a substring of) the names of several
+ configurations, then all these configurations will be selected.
+* If `` is empty (i.e. `CONF=`), then all configurations will be
+ selected.
+* If `` begins with `!`, then all configurations **not** matching the
+ string following `!` will be selected.
+
+A more specialized version, `CONF_NAME=` also exists, which will only
+match if the given `` exactly matches a single configuration.
+
+Alternatively, you can execute `make` in the configuration directory, e.g. `cd
+build/ && make`.
+
+`make CONF_NAME=` or
### Handling Reconfigurations
diff --git a/make/Global.gmk b/make/Global.gmk
index e5e76b475b941..1df6c5fb6bc4b 100644
--- a/make/Global.gmk
+++ b/make/Global.gmk
@@ -87,10 +87,9 @@ help:
$(info $(_) # (gensrc, java, copy, libs, launchers, gendata))
$(info )
$(info Make control variables)
- $(info $(_) CONF= # Build all configurations (note, assignment is empty))
- $(info $(_) CONF= # Build the configuration(s) with a name matching)
- $(info $(_) # )
- $(info $(_) CONF_NAME= # Build the configuration with exactly the )
+ $(info $(_) CONF= # Select which configuration(s) to build)
+ $(info $(_) CONF= # Select all configurations (note, assignment is empty))
+ $(info $(_) CONF_NAME= # Select the configuration with the name )
$(info $(_) SPEC= # Build the configuration given by the spec file)
$(info $(_) LOG= # Change the log level from warn to )
$(info $(_) # Available log levels are:)
diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk
index 31c80e2f7267f..9ea01d375ced9 100644
--- a/make/InitSupport.gmk
+++ b/make/InitSupport.gmk
@@ -202,8 +202,14 @@ ifeq ($(HAS_SPEC),)
matching_confs := $$(strip $$(all_confs))
else
# Otherwise select those that contain the given CONF string
- matching_confs := $$(strip $$(foreach var, $$(all_confs), \
- $$(if $$(findstring $$(CONF), $$(var)), $$(var))))
+ ifeq ($$(patsubst !%,,$$(CONF)),)
+ # A CONF starting with ! means we should negate the search term
+ matching_confs := $$(strip $$(foreach var, $$(all_confs), \
+ $$(if $$(findstring $$(subst !,,$$(CONF)), $$(var)), ,$$(var))))
+ else
+ matching_confs := $$(strip $$(foreach var, $$(all_confs), \
+ $$(if $$(findstring $$(CONF), $$(var)), $$(var))))
+ endif
ifneq ($$(filter $$(CONF), $$(matching_confs)), )
# If we found an exact match, use that
matching_confs := $$(CONF)
From c266800a3a7dd44416b0b4df3bdd78410241d74b Mon Sep 17 00:00:00 2001
From: Magnus Ihse Bursie
Date: Tue, 13 Feb 2024 10:00:13 +0000
Subject: [PATCH 06/36] 8325558: Add jcheck whitespace checking for properties
files
Reviewed-by: naoto, dfuchs, joehw
---
.jcheck/conf | 2 +-
.../sun/net/www/content-types.properties | 418 +++++++++---------
.../sun/net/www/content-types.properties | 400 ++++++++---------
.../plugins/common/iio-plugin.properties | 2 +-
.../tools/script/shell/messages.properties | 12 +-
.../rowset/RowSetResourceBundle.properties | 14 +-
.../rowset/RowSetResourceBundle_de.properties | 14 +-
.../rowset/RowSetResourceBundle_es.properties | 14 +-
.../rowset/RowSetResourceBundle_fr.properties | 14 +-
.../rowset/RowSetResourceBundle_it.properties | 14 +-
.../rowset/RowSetResourceBundle_ja.properties | 14 +-
.../rowset/RowSetResourceBundle_ko.properties | 14 +-
.../RowSetResourceBundle_pt_BR.properties | 14 +-
.../rowset/RowSetResourceBundle_sv.properties | 14 +-
.../RowSetResourceBundle_zh_CN.properties | 14 +-
.../RowSetResourceBundle_zh_TW.properties | 12 +-
.../resource/xmlsecurity_en.properties | 2 +-
.../internal/impl/msg/DOMMessages.properties | 22 +-
.../impl/msg/DOMMessages_de.properties | 22 +-
.../impl/msg/DOMMessages_es.properties | 22 +-
.../impl/msg/DOMMessages_fr.properties | 22 +-
.../impl/msg/DOMMessages_it.properties | 22 +-
.../impl/msg/DOMMessages_ja.properties | 22 +-
.../impl/msg/DOMMessages_ko.properties | 22 +-
.../impl/msg/DOMMessages_pt_BR.properties | 22 +-
.../impl/msg/DOMMessages_sv.properties | 22 +-
.../impl/msg/DOMMessages_zh_CN.properties | 2 +-
.../internal/impl/msg/SAXMessages.properties | 4 +-
.../impl/msg/SAXMessages_de.properties | 4 +-
.../impl/msg/SAXMessages_es.properties | 4 +-
.../impl/msg/SAXMessages_fr.properties | 4 +-
.../impl/msg/SAXMessages_it.properties | 4 +-
.../impl/msg/SAXMessages_ja.properties | 4 +-
.../impl/msg/SAXMessages_ko.properties | 4 +-
.../impl/msg/SAXMessages_pt_BR.properties | 4 +-
.../impl/msg/SAXMessages_sv.properties | 4 +-
.../impl/msg/SAXMessages_zh_CN.properties | 2 +-
.../impl/msg/SAXMessages_zh_TW.properties | 2 +-
.../impl/msg/XIncludeMessages.properties | 2 +-
.../impl/msg/XIncludeMessages_de.properties | 2 +-
.../impl/msg/XIncludeMessages_es.properties | 2 +-
.../impl/msg/XIncludeMessages_fr.properties | 2 +-
.../impl/msg/XIncludeMessages_it.properties | 2 +-
.../impl/msg/XIncludeMessages_ja.properties | 2 +-
.../impl/msg/XIncludeMessages_ko.properties | 2 +-
.../msg/XIncludeMessages_pt_BR.properties | 2 +-
.../impl/msg/XIncludeMessages_sv.properties | 2 +-
.../msg/XIncludeMessages_zh_CN.properties | 2 +-
.../internal/impl/msg/XMLMessages.properties | 11 +-
.../impl/msg/XMLMessages_de.properties | 9 +-
.../impl/msg/XMLMessages_es.properties | 8 +-
.../impl/msg/XMLMessages_fr.properties | 8 +-
.../impl/msg/XMLMessages_it.properties | 8 +-
.../impl/msg/XMLMessages_ja.properties | 9 +-
.../impl/msg/XMLMessages_ko.properties | 8 +-
.../impl/msg/XMLMessages_pt_BR.properties | 8 +-
.../impl/msg/XMLMessages_sv.properties | 8 +-
.../impl/msg/XMLMessages_zh_CN.properties | 5 +-
.../impl/msg/XMLMessages_zh_TW.properties | 2 +-
.../impl/msg/XMLSchemaMessages.properties | 2 +-
.../impl/msg/XMLSchemaMessages_de.properties | 2 +-
.../impl/msg/XMLSchemaMessages_es.properties | 2 +-
.../impl/msg/XMLSchemaMessages_fr.properties | 2 +-
.../impl/msg/XMLSchemaMessages_it.properties | 2 +-
.../impl/msg/XMLSchemaMessages_ko.properties | 2 +-
.../msg/XMLSchemaMessages_pt_BR.properties | 2 +-
.../impl/msg/XMLSchemaMessages_sv.properties | 2 +-
.../impl/msg/XPointerMessages.properties | 8 +-
.../impl/msg/XPointerMessages_de.properties | 6 +-
.../impl/msg/XPointerMessages_es.properties | 8 +-
.../impl/msg/XPointerMessages_fr.properties | 8 +-
.../impl/msg/XPointerMessages_it.properties | 8 +-
.../impl/msg/XPointerMessages_ja.properties | 8 +-
.../impl/msg/XPointerMessages_ko.properties | 8 +-
.../msg/XPointerMessages_pt_BR.properties | 8 +-
.../impl/msg/XPointerMessages_sv.properties | 8 +-
.../msg/XPointerMessages_zh_CN.properties | 2 +-
.../serialver/resources/serialver.properties | 12 +-
.../sun/tools/jar/resources/jar.properties | 4 +-
.../tools/jlink/resources/jlink.properties | 2 +-
.../tools/jlink/resources/jlink_de.properties | 2 +-
.../tools/jlink/resources/jlink_ja.properties | 2 +-
.../jlink/resources/jlink_zh_CN.properties | 2 +-
.../resources/ext/LocaleNames_de.properties | 10 +-
.../resources/ext/LocaleNames_sv.properties | 2 +-
.../agent/resources/agent_ja.properties | 2 +-
.../common/config/files/catalog2.properties | 8 +-
.../common/config/files/customJaxp.properties | 8 +-
.../common/config/files/jaxpImpls.properties | 8 +-
.../javax/net/ssl/Stapling/TEST.properties | 2 +-
.../src/resources/TextAreaTest.properties | 2 +-
.../resources/FileChooserDemo.properties | 12 +-
.../table/resources/TableDemo.properties | 7 +-
.../resources/ToggleButtonDemo.properties | 10 +-
.../foo/jdk/test/foo/resources/foo.properties | 2 +-
95 files changed, 756 insertions(+), 761 deletions(-)
diff --git a/.jcheck/conf b/.jcheck/conf
index 18228df5dfe46..b374bde90a538 100644
--- a/.jcheck/conf
+++ b/.jcheck/conf
@@ -15,7 +15,7 @@ version=0
domain=openjdk.org
[checks "whitespace"]
-files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java|.*\.cc|.*\.hh|.*\.m|.*\.mm|.*\.md|.*\.gmk|.*\.m4|.*\.ac|Makefile
+files=.*\.cpp|.*\.hpp|.*\.c|.*\.h|.*\.java|.*\.cc|.*\.hh|.*\.m|.*\.mm|.*\.md|.*\.properties|.*\.gmk|.*\.m4|.*\.ac|Makefile
ignore-tabs=.*\.gmk|Makefile
[checks "merge"]
diff --git a/src/java.base/unix/classes/sun/net/www/content-types.properties b/src/java.base/unix/classes/sun/net/www/content-types.properties
index 0dbece5902fc5..e056c3ccebef5 100644
--- a/src/java.base/unix/classes/sun/net/www/content-types.properties
+++ b/src/java.base/unix/classes/sun/net/www/content-types.properties
@@ -26,376 +26,376 @@ temp.file.template: /tmp/%s
# The "real" types.
#
application/octet-stream: \
- description=Generic Binary Stream;\
- file_extensions=.saveme,.dump,.hqx,.arc,.o,.a,.bin,.exe,.z
+ description=Generic Binary Stream;\
+ file_extensions=.saveme,.dump,.hqx,.arc,.o,.a,.bin,.exe,.z
application/oda: \
- description=ODA Document;\
- file_extensions=.oda
+ description=ODA Document;\
+ file_extensions=.oda
application/pdf: \
- description=Adobe PDF Format;\
- file_extensions=.pdf
+ description=Adobe PDF Format;\
+ file_extensions=.pdf
application/postscript: \
- description=Postscript File;\
- file_extensions=.eps,.ai,.ps;\
- icon=ps;\
- action=application;\
- application=imagetool %s
+ description=Postscript File;\
+ file_extensions=.eps,.ai,.ps;\
+ icon=ps;\
+ action=application;\
+ application=imagetool %s
application/x-dvi: \
- description=TeX DVI File;\
- file_extensions=.dvi;\
- action=application;\
- application=xdvi %s
+ description=TeX DVI File;\
+ file_extensions=.dvi;\
+ action=application;\
+ application=xdvi %s
application/x-hdf: \
- description=Hierarchical Data Format;\
- file_extensions=.hdf;\
- action=save
+ description=Hierarchical Data Format;\
+ file_extensions=.hdf;\
+ action=save
application/x-latex: \
- description=LaTeX Source;\
- file_extensions=.latex
+ description=LaTeX Source;\
+ file_extensions=.latex
application/x-netcdf: \
- description=Unidata netCDF Data Format;\
- file_extensions=.nc,.cdf;\
- action=save
+ description=Unidata netCDF Data Format;\
+ file_extensions=.nc,.cdf;\
+ action=save
application/x-tex: \
- description=TeX Source;\
- file_extensions=.tex
+ description=TeX Source;\
+ file_extensions=.tex
application/x-texinfo: \
- description=Gnu Texinfo;\
- file_extensions=.texinfo,.texi
+ description=Gnu Texinfo;\
+ file_extensions=.texinfo,.texi
application/x-troff: \
- description=Troff Source;\
- file_extensions=.t,.tr,.roff;\
- action=application;\
- application=xterm -title troff -e sh -c \"nroff %s | col | more -w\"
+ description=Troff Source;\
+ file_extensions=.t,.tr,.roff;\
+ action=application;\
+ application=xterm -title troff -e sh -c \"nroff %s | col | more -w\"
application/x-troff-man: \
- description=Troff Manpage Source;\
- file_extensions=.man;\
- action=application;\
- application=xterm -title troff -e sh -c \"nroff -man %s | col | more -w\"
+ description=Troff Manpage Source;\
+ file_extensions=.man;\
+ action=application;\
+ application=xterm -title troff -e sh -c \"nroff -man %s | col | more -w\"
application/x-troff-me: \
- description=Troff ME Macros;\
- file_extensions=.me;\
- action=application;\
- application=xterm -title troff -e sh -c \"nroff -me %s | col | more -w\"
+ description=Troff ME Macros;\
+ file_extensions=.me;\
+ action=application;\
+ application=xterm -title troff -e sh -c \"nroff -me %s | col | more -w\"
application/x-troff-ms: \
- description=Troff MS Macros;\
- file_extensions=.ms;\
- action=application;\
- application=xterm -title troff -e sh -c \"nroff -ms %s | col | more -w\"
+ description=Troff MS Macros;\
+ file_extensions=.ms;\
+ action=application;\
+ application=xterm -title troff -e sh -c \"nroff -ms %s | col | more -w\"
application/x-wais-source: \
- description=Wais Source;\
- file_extensions=.src,.wsrc
+ description=Wais Source;\
+ file_extensions=.src,.wsrc
application/zip: \
- description=Zip File;\
- file_extensions=.zip;\
- icon=zip;\
- action=save
+ description=Zip File;\
+ file_extensions=.zip;\
+ icon=zip;\
+ action=save
application/x-bcpio: \
- description=Old Binary CPIO Archive;\
- file_extensions=.bcpio; action=save
+ description=Old Binary CPIO Archive;\
+ file_extensions=.bcpio; action=save
application/x-cpio: \
- description=Unix CPIO Archive;\
- file_extensions=.cpio; action=save
+ description=Unix CPIO Archive;\
+ file_extensions=.cpio; action=save
application/x-gtar: \
- description=Gnu Tar Archive;\
- file_extensions=.gtar;\
- icon=tar;\
- action=save
+ description=Gnu Tar Archive;\
+ file_extensions=.gtar;\
+ icon=tar;\
+ action=save
application/x-shar: \
- description=Shell Archive;\
- file_extensions=.sh,.shar;\
- action=save
+ description=Shell Archive;\
+ file_extensions=.sh,.shar;\
+ action=save
application/x-sv4cpio: \
- description=SVR4 CPIO Archive;\
- file_extensions=.sv4cpio; action=save
+ description=SVR4 CPIO Archive;\
+ file_extensions=.sv4cpio; action=save
application/x-sv4crc: \
- description=SVR4 CPIO with CRC;\
- file_extensions=.sv4crc; action=save
+ description=SVR4 CPIO with CRC;\
+ file_extensions=.sv4crc; action=save
application/x-tar: \
- description=Tar Archive;\
- file_extensions=.tar;\
- icon=tar;\
- action=save
+ description=Tar Archive;\
+ file_extensions=.tar;\
+ icon=tar;\
+ action=save
application/x-ustar: \
- description=US Tar Archive;\
- file_extensions=.ustar;\
- action=save
+ description=US Tar Archive;\
+ file_extensions=.ustar;\
+ action=save
audio/aac: \
- description=Advanced Audio Coding Audio;\
- file_extensions=.aac
+ description=Advanced Audio Coding Audio;\
+ file_extensions=.aac
audio/basic: \
- description=Basic Audio;\
- file_extensions=.snd,.au;\
- icon=audio;\
- action=application;\
- application=audiotool %s
+ description=Basic Audio;\
+ file_extensions=.snd,.au;\
+ icon=audio;\
+ action=application;\
+ application=audiotool %s
audio/flac: \
- description=Free Lossless Audio Codec Audio;\
- file_extensions=.flac
+ description=Free Lossless Audio Codec Audio;\
+ file_extensions=.flac
audio/mp4: \
- description=MPEG-4 Audio;\
- file_extensions=.m4a
+ description=MPEG-4 Audio;\
+ file_extensions=.m4a
audio/mpeg: \
- description=MPEG Audio;\
- file_extensions=.mp2,.mp3
+ description=MPEG Audio;\
+ file_extensions=.mp2,.mp3
audio/ogg: \
- description=Ogg Audio;\
- file_extensions=.oga,.ogg,.opus,.spx
+ description=Ogg Audio;\
+ file_extensions=.oga,.ogg,.opus,.spx
audio/x-aiff: \
- description=Audio Interchange Format File;\
- file_extensions=.aifc,.aif,.aiff;\
- icon=aiff
+ description=Audio Interchange Format File;\
+ file_extensions=.aifc,.aif,.aiff;\
+ icon=aiff
audio/x-wav: \
- description=Wav Audio;\
- file_extensions=.wav;\
- icon=wav
+ description=Wav Audio;\
+ file_extensions=.wav;\
+ icon=wav
image/gif: \
- description=GIF Image;\
- file_extensions=.gif;\
- icon=gif;\
- action=browser
+ description=GIF Image;\
+ file_extensions=.gif;\
+ icon=gif;\
+ action=browser
image/ief: \
- description=Image Exchange Format;\
- file_extensions=.ief
+ description=Image Exchange Format;\
+ file_extensions=.ief
image/jpeg: \
- description=JPEG Image;\
- file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
- icon=jpeg;\
- action=browser;\
- application=imagetool %s
+ description=JPEG Image;\
+ file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
+ icon=jpeg;\
+ action=browser;\
+ application=imagetool %s
image/svg+xml: \
- description=Scalable Vector Graphics;\
- file_extensions=.svg,.svgz
+ description=Scalable Vector Graphics;\
+ file_extensions=.svg,.svgz
image/tiff: \
- description=TIFF Image;\
- file_extensions=.tif,.tiff;\
- icon=tiff
+ description=TIFF Image;\
+ file_extensions=.tif,.tiff;\
+ icon=tiff
image/vnd.fpx: \
- description=FlashPix Image;\
- file_extensions=.fpx,.fpix
+ description=FlashPix Image;\
+ file_extensions=.fpx,.fpix
image/x-cmu-rast: \
- description=CMU Raster Image;\
- file_extensions=.ras
+ description=CMU Raster Image;\
+ file_extensions=.ras
image/x-portable-anymap: \
- description=PBM Anymap Format;\
- file_extensions=.pnm
+ description=PBM Anymap Format;\
+ file_extensions=.pnm
image/x-portable-bitmap: \
- description=PBM Bitmap Format;\
- file_extensions=.pbm
+ description=PBM Bitmap Format;\
+ file_extensions=.pbm
image/x-portable-graymap: \
- description=PBM Graymap Format;\
- file_extensions=.pgm
+ description=PBM Graymap Format;\
+ file_extensions=.pgm
image/x-portable-pixmap: \
- description=PBM Pixmap Format;\
- file_extensions=.ppm
+ description=PBM Pixmap Format;\
+ file_extensions=.ppm
image/x-rgb: \
- description=RGB Image;\
- file_extensions=.rgb
+ description=RGB Image;\
+ file_extensions=.rgb
image/x-xbitmap: \
- description=X Bitmap Image;\
- file_extensions=.xbm,.xpm
+ description=X Bitmap Image;\
+ file_extensions=.xbm,.xpm
image/x-xwindowdump: \
- description=X Window Dump Image;\
- file_extensions=.xwd
+ description=X Window Dump Image;\
+ file_extensions=.xwd
image/png: \
- description=PNG Image;\
- file_extensions=.png;\
- icon=png;\
- action=browser
+ description=PNG Image;\
+ file_extensions=.png;\
+ icon=png;\
+ action=browser
image/bmp: \
- description=Bitmap Image;\
- file_extensions=.bmp;
+ description=Bitmap Image;\
+ file_extensions=.bmp;
image/webp: \
- description=WEBP image;\
- file_extensions=.webp;
+ description=WEBP image;\
+ file_extensions=.webp;
text/css: \
- description=CSS File;\
- file_extensions=.css;
+ description=CSS File;\
+ file_extensions=.css;
text/html: \
- description=HTML Document;\
- file_extensions=.htm,.html;\
- icon=html
+ description=HTML Document;\
+ file_extensions=.htm,.html;\
+ icon=html
text/javascript: \
- description=JavaScript File;\
- file_extensions=.js;
+ description=JavaScript File;\
+ file_extensions=.js;
text/plain: \
- description=Plain Text;\
- file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el,.php,.adoc,.py;\
- icon=text;\
- action=browser
+ description=Plain Text;\
+ file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el,.php,.adoc,.py;\
+ icon=text;\
+ action=browser
text/tab-separated-values: \
- description=Tab Separated Values Text;\
- file_extensions=.tsv
+ description=Tab Separated Values Text;\
+ file_extensions=.tsv
text/x-setext: \
- description=Structure Enhanced Text;\
- file_extensions=.etx
+ description=Structure Enhanced Text;\
+ file_extensions=.etx
text/csv: \
- description=CSV File;\
- file_extensions=.csv;
+ description=CSV File;\
+ file_extensions=.csv;
text/markdown: \
- description=Markdown File;\
- file_extensions=.md,.markdown
+ description=Markdown File;\
+ file_extensions=.md,.markdown
video/mp4: \
- description=MPEG-4 Video;\
- file_extensions=.m4v,.mp4
+ description=MPEG-4 Video;\
+ file_extensions=.m4v,.mp4
video/mpeg: \
- description=MPEG Video Clip;\
- file_extensions=.mpg,.mpe,.mpeg;\
- icon=mpeg;\
- action=application;\
- application=mpeg_play %s
+ description=MPEG Video Clip;\
+ file_extensions=.mpg,.mpe,.mpeg;\
+ icon=mpeg;\
+ action=application;\
+ application=mpeg_play %s
video/ogg: \
- description=Ogg Video;\
- file_extensions=.ogv
+ description=Ogg Video;\
+ file_extensions=.ogv
video/quicktime: \
- description=QuickTime Video Clip;\
- file_extensions=.mov,.qt
+ description=QuickTime Video Clip;\
+ file_extensions=.mov,.qt
video/webm: \
- description=WebM Video;\
- file_extensions=.webm
+ description=WebM Video;\
+ file_extensions=.webm
application/x-troff-msvideo: \
- description=AVI Video;\
- file_extensions=.avi;\
- icon=avi
+ description=AVI Video;\
+ file_extensions=.avi;\
+ icon=avi
video/x-sgi-movie: \
- description=SGI Movie;\
- file_extensions=.movie,.mv
+ description=SGI Movie;\
+ file_extensions=.movie,.mv
message/rfc822: \
- description=Internet Email Message;\
- file_extensions=.mime
+ description=Internet Email Message;\
+ file_extensions=.mime
application/xml: \
- description=XML document;\
- file_extensions=.xml
+ description=XML document;\
+ file_extensions=.xml
application/rtf: \
- description=WordPad Document;\
- file_extensions=.rtf;
+ description=WordPad Document;\
+ file_extensions=.rtf;
application/gzip: \
- description=GZip File;\
- file_extensions=.gz;
+ description=GZip File;\
+ file_extensions=.gz;
application/vnd.oasis.opendocument.presentation: \
- description=OpenDocument presentation document;\
- file_extensions=.odp;
+ description=OpenDocument presentation document;\
+ file_extensions=.odp;
application/vnd.oasis.opendocument.spreadsheet: \
- description=OpenDocument spreadsheet document;\
- file_extensions=.ods;
+ description=OpenDocument spreadsheet document;\
+ file_extensions=.ods;
application/vnd.oasis.opendocument.text: \
- description=OpenDocument text document;\
- file_extensions=.odt;
+ description=OpenDocument text document;\
+ file_extensions=.odt;
application/vnd.ms-excel: \
- description=Microsoft Excel File;\
- file_extensions=.xls;
+ description=Microsoft Excel File;\
+ file_extensions=.xls;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: \
- description=XLSX File;\
- file_extensions=.xlsx;
+ description=XLSX File;\
+ file_extensions=.xlsx;
application/vnd.openxmlformats-officedocument.presentationml.presentation: \
- description=PPTX File;\
- file_extensions=.pptx;
+ description=PPTX File;\
+ file_extensions=.pptx;
application/vnd.ms-powerpoint: \
- description=Microsoft PowerPoint File;\
- file_extensions=.ppt;
+ description=Microsoft PowerPoint File;\
+ file_extensions=.ppt;
application/x-7z-compressed: \
- description=7-Zip File;\
- file_extensions=.7z;
+ description=7-Zip File;\
+ file_extensions=.7z;
application/msword: \
- description=Microsoft Word File;\
- file_extensions=.doc;
+ description=Microsoft Word File;\
+ file_extensions=.doc;
application/vnd.openxmlformats-officedocument.wordprocessingml.document: \
- description=DOCX File;\
- file_extensions=.docx;
+ description=DOCX File;\
+ file_extensions=.docx;
application/vnd.rar: \
- description=RAR File;\
- file_extensions=.rar;
+ description=RAR File;\
+ file_extensions=.rar;
application/json: \
- description=JSON File;\
- file_extensions=.json;
+ description=JSON File;\
+ file_extensions=.json;
application/bz2: \
- description=BZ2 File;\
- file_extensions=.bz2;
+ description=BZ2 File;\
+ file_extensions=.bz2;
application/java-archive: \
- description=JAR File;\
- file_extensions=.jar;
+ description=JAR File;\
+ file_extensions=.jar;
application/wasm: \
- description=WebAssembly File;\
- file_extensions=.wasm;
+ description=WebAssembly File;\
+ file_extensions=.wasm;
diff --git a/src/java.base/windows/classes/sun/net/www/content-types.properties b/src/java.base/windows/classes/sun/net/www/content-types.properties
index dcd2e5843c04f..24ce247783377 100644
--- a/src/java.base/windows/classes/sun/net/www/content-types.properties
+++ b/src/java.base/windows/classes/sun/net/www/content-types.properties
@@ -26,369 +26,369 @@ temp.file.template: c:\\temp\\%s
# The "real" types.
#
application/octet-stream: \
- description=Generic Binary Stream;\
- file_extensions=.saveme,.dump,.hqx,.arc,.obj,.lib,.bin,.exe
+ description=Generic Binary Stream;\
+ file_extensions=.saveme,.dump,.hqx,.arc,.obj,.lib,.bin,.exe
application/oda: \
- description=ODA Document;\
- file_extensions=.oda
+ description=ODA Document;\
+ file_extensions=.oda
application/pdf: \
- description=Adobe PDF Format;\
- file_extensions=.pdf
+ description=Adobe PDF Format;\
+ file_extensions=.pdf
application/postscript: \
- description=Postscript File;\
- file_extensions=.eps,.ai,.ps;\
- icon=ps
+ description=Postscript File;\
+ file_extensions=.eps,.ai,.ps;\
+ icon=ps
application/rtf: \
- description=WordPad Document;\
- file_extensions=.rtf;\
- action=application;\
- application=wordpad.exe %s
+ description=WordPad Document;\
+ file_extensions=.rtf;\
+ action=application;\
+ application=wordpad.exe %s
application/gzip: \
- description=GZip File;\
- file_extensions=.gz;
+ description=GZip File;\
+ file_extensions=.gz;
application/x-dvi: \
- description=TeX DVI File;\
- file_extensions=.dvi
+ description=TeX DVI File;\
+ file_extensions=.dvi
application/x-hdf: \
- description=Hierarchical Data Format;\
- file_extensions=.hdf;\
- action=save
+ description=Hierarchical Data Format;\
+ file_extensions=.hdf;\
+ action=save
application/x-latex: \
- description=LaTeX Source;\
- file_extensions=.latex
+ description=LaTeX Source;\
+ file_extensions=.latex
application/x-netcdf: \
- description=Unidata netCDF Data Format;\
- file_extensions=.nc,.cdf;\
- action=save
+ description=Unidata netCDF Data Format;\
+ file_extensions=.nc,.cdf;\
+ action=save
application/x-tex: \
- description=TeX Source;\
- file_extensions=.tex
+ description=TeX Source;\
+ file_extensions=.tex
application/x-texinfo: \
- description=Gnu Texinfo;\
- file_extensions=.texinfo,.texi
+ description=Gnu Texinfo;\
+ file_extensions=.texinfo,.texi
application/x-troff: \
- description=Troff Source;\
- file_extensions=.t,.tr,.roff
+ description=Troff Source;\
+ file_extensions=.t,.tr,.roff
application/x-troff-man: \
- description=Troff Manpage Source;\
- file_extensions=.man
+ description=Troff Manpage Source;\
+ file_extensions=.man
application/x-troff-me: \
- description=Troff ME Macros;\
- file_extensions=.me
+ description=Troff ME Macros;\
+ file_extensions=.me
application/x-troff-ms: \
- description=Troff MS Macros;\
- file_extensions=.ms
+ description=Troff MS Macros;\
+ file_extensions=.ms
application/x-wais-source: \
- description=Wais Source;\
- file_extensions=.src,.wsrc
+ description=Wais Source;\
+ file_extensions=.src,.wsrc
application/zip: \
- description=Zip File;\
- file_extensions=.zip;\
- icon=zip;\
- action=save
+ description=Zip File;\
+ file_extensions=.zip;\
+ icon=zip;\
+ action=save
application/x-bcpio: \
- description=Old Binary CPIO Archive;\
- file_extensions=.bcpio;\
- action=save
+ description=Old Binary CPIO Archive;\
+ file_extensions=.bcpio;\
+ action=save
application/x-cpio: \
- description=Unix CPIO Archive;\
- file_extensions=.cpio;\
- action=save
+ description=Unix CPIO Archive;\
+ file_extensions=.cpio;\
+ action=save
application/x-gtar: \
- description=Gnu Tar Archive;\
- file_extensions=.gtar;\
- icon=tar;\
- action=save
+ description=Gnu Tar Archive;\
+ file_extensions=.gtar;\
+ icon=tar;\
+ action=save
application/x-shar: \
- description=Shell Archive;\
- file_extensions=.sh,.shar;\
- action=save
+ description=Shell Archive;\
+ file_extensions=.sh,.shar;\
+ action=save
application/x-sv4cpio: \
- description=SVR4 CPIO Archive;\
- file_extensions=.sv4cpio;\
- action=save
+ description=SVR4 CPIO Archive;\
+ file_extensions=.sv4cpio;\
+ action=save
application/x-sv4crc: \
- description=SVR4 CPIO with CRC;\
- file_extensions=.sv4crc;\
- action=save
+ description=SVR4 CPIO with CRC;\
+ file_extensions=.sv4crc;\
+ action=save
application/x-tar: \
- description=Tar Archive;\
- file_extensions=.tar;\
- icon=tar;\
- action=save
+ description=Tar Archive;\
+ file_extensions=.tar;\
+ icon=tar;\
+ action=save
application/x-ustar: \
- description=US Tar Archive;\
- file_extensions=.ustar;\
- action=save
+ description=US Tar Archive;\
+ file_extensions=.ustar;\
+ action=save
audio/aac: \
- description=Advanced Audio Coding Audio;\
- file_extensions=.aac
+ description=Advanced Audio Coding Audio;\
+ file_extensions=.aac
audio/basic: \
- description=Basic Audio;\
- file_extensions=.snd,.au;\
- icon=audio
+ description=Basic Audio;\
+ file_extensions=.snd,.au;\
+ icon=audio
audio/flac: \
- description=Free Lossless Audio Codec Audio;\
- file_extensions=.flac
+ description=Free Lossless Audio Codec Audio;\
+ file_extensions=.flac
audio/mp4: \
- description=MPEG-4 Audio;\
- file_extensions=.m4a
+ description=MPEG-4 Audio;\
+ file_extensions=.m4a
audio/mpeg: \
- description=MPEG Audio;\
- file_extensions=.mp2,.mp3
+ description=MPEG Audio;\
+ file_extensions=.mp2,.mp3
audio/ogg: \
- description=Ogg Audio;\
- file_extensions=.oga,.ogg,.opus,.spx
+ description=Ogg Audio;\
+ file_extensions=.oga,.ogg,.opus,.spx
audio/x-aiff: \
- description=Audio Interchange Format File;\
- file_extensions=.aifc,.aif,.aiff;\
- icon=aiff
+ description=Audio Interchange Format File;\
+ file_extensions=.aifc,.aif,.aiff;\
+ icon=aiff
audio/x-wav: \
- description=Wav Audio;\
- file_extensions=.wav;\
- icon=wav;\
- action=application;\
- application=mplayer.exe %s
+ description=Wav Audio;\
+ file_extensions=.wav;\
+ icon=wav;\
+ action=application;\
+ application=mplayer.exe %s
image/gif: \
- description=GIF Image;\
- file_extensions=.gif;\
- icon=gif;\
- action=browser
+ description=GIF Image;\
+ file_extensions=.gif;\
+ icon=gif;\
+ action=browser
image/ief: \
- description=Image Exchange Format;\
- file_extensions=.ief
+ description=Image Exchange Format;\
+ file_extensions=.ief
image/jpeg: \
- description=JPEG Image;\
- file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
- icon=jpeg;\
- action=browser
+ description=JPEG Image;\
+ file_extensions=.jfif,.jfif-tbnl,.jpe,.jpg,.jpeg;\
+ icon=jpeg;\
+ action=browser
image/svg+xml: \
- description=Scalable Vector Graphics;\
- file_extensions=.svg,.svgz
+ description=Scalable Vector Graphics;\
+ file_extensions=.svg,.svgz
image/tiff: \
- description=TIFF Image;\
- file_extensions=.tif,.tiff;\
- icon=tiff
+ description=TIFF Image;\
+ file_extensions=.tif,.tiff;\
+ icon=tiff
image/vnd.fpx: \
- description=FlashPix Image;\
- file_extensions=.fpx,.fpix
+ description=FlashPix Image;\
+ file_extensions=.fpx,.fpix
image/x-cmu-rast: \
- description=CMU Raster Image;\
- file_extensions=.ras
+ description=CMU Raster Image;\
+ file_extensions=.ras
image/x-portable-anymap: \
- description=PBM Anymap Image;\
- file_extensions=.pnm
+ description=PBM Anymap Image;\
+ file_extensions=.pnm
image/x-portable-bitmap: \
- description=PBM Bitmap Image;\
- file_extensions=.pbm
+ description=PBM Bitmap Image;\
+ file_extensions=.pbm
image/x-portable-graymap: \
- description=PBM Graymap Image;\
- file_extensions=.pgm
+ description=PBM Graymap Image;\
+ file_extensions=.pgm
image/x-portable-pixmap: \
- description=PBM Pixmap Image;\
- file_extensions=.ppm
+ description=PBM Pixmap Image;\
+ file_extensions=.ppm
image/x-rgb: \
- description=RGB Image;\
- file_extensions=.rgb
+ description=RGB Image;\
+ file_extensions=.rgb
image/x-xbitmap: \
- description=X Bitmap Image;\
- file_extensions=.xbm,.xpm
+ description=X Bitmap Image;\
+ file_extensions=.xbm,.xpm
image/x-xwindowdump: \
- description=X Window Dump Image;\
- file_extensions=.xwd
+ description=X Window Dump Image;\
+ file_extensions=.xwd
image/png: \
- description=PNG Image;\
- file_extensions=.png;\
- icon=png;\
- action=browser
+ description=PNG Image;\
+ file_extensions=.png;\
+ icon=png;\
+ action=browser
image/bmp: \
- description=Bitmap Image;\
- file_extensions=.bmp;
+ description=Bitmap Image;\
+ file_extensions=.bmp;
image/webp: \
- description=WEBP image;\
- file_extensions=.webp;
+ description=WEBP image;\
+ file_extensions=.webp;
text/css: \
- description=CSS File;\
- file_extensions=.css;
+ description=CSS File;\
+ file_extensions=.css;
text/html: \
- description=HTML Document;\
- file_extensions=.htm,.html;\
- icon=html
+ description=HTML Document;\
+ file_extensions=.htm,.html;\
+ icon=html
text/javascript: \
description=JavaScript File;\
file_extensions=.js;
text/plain: \
- description=Plain Text;\
- file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el,.php,.adoc,.py;\
- icon=text;\
- action=browser
+ description=Plain Text;\
+ file_extensions=.text,.c,.cc,.c++,.h,.pl,.txt,.java,.el,.php,.adoc,.py;\
+ icon=text;\
+ action=browser
text/tab-separated-values: \
- description=Tab Separated Values Text;\
- file_extensions=.tsv
+ description=Tab Separated Values Text;\
+ file_extensions=.tsv
text/x-setext: \
- description=Structure Enhanced Text;\
- file_extensions=.etx
+ description=Structure Enhanced Text;\
+ file_extensions=.etx
text/csv: \
- description=CSV File;\
- file_extensions=.csv;
+ description=CSV File;\
+ file_extensions=.csv;
text/markdown: \
- description=Markdown File;\
- file_extensions=.md,.markdown
+ description=Markdown File;\
+ file_extensions=.md,.markdown
video/mp4: \
- description=MPEG-4 Video;\
- file_extensions=.m4v,.mp4
+ description=MPEG-4 Video;\
+ file_extensions=.m4v,.mp4
video/mpeg: \
- description=MPEG Video Clip;\
- file_extensions=.mpg,.mpe,.mpeg;\
- icon=mpeg
+ description=MPEG Video Clip;\
+ file_extensions=.mpg,.mpe,.mpeg;\
+ icon=mpeg
video/ogg: \
- description=Ogg Video;\
- file_extensions=.ogv
+ description=Ogg Video;\
+ file_extensions=.ogv
video/quicktime: \
- description=QuickTime Video Clip;\
- file_extensions=.mov,.qt
+ description=QuickTime Video Clip;\
+ file_extensions=.mov,.qt
video/webm: \
- description=WebM Video;\
- file_extensions=.webm
+ description=WebM Video;\
+ file_extensions=.webm
application/x-troff-msvideo: \
- description=AVI Video;\
- file_extensions=.avi;\
- icon=avi;\
- action=application;\
- application=mplayer.exe %s
+ description=AVI Video;\
+ file_extensions=.avi;\
+ icon=avi;\
+ action=application;\
+ application=mplayer.exe %s
video/x-sgi-movie: \
- description=SGI Movie;\
- file_extensions=.movie,.mv
+ description=SGI Movie;\
+ file_extensions=.movie,.mv
message/rfc822: \
- description=Internet Email Message;\
- file_extensions=.mime
+ description=Internet Email Message;\
+ file_extensions=.mime
application/xml: \
- description=XML document;\
- file_extensions=.xml
+ description=XML document;\
+ file_extensions=.xml
application/vnd.oasis.opendocument.presentation: \
- description=OpenDocument presentation document;\
- file_extensions=.odp;
+ description=OpenDocument presentation document;\
+ file_extensions=.odp;
application/vnd.oasis.opendocument.spreadsheet: \
- description=OpenDocument spreadsheet document;\
- file_extensions=.ods;
+ description=OpenDocument spreadsheet document;\
+ file_extensions=.ods;
application/vnd.oasis.opendocument.text: \
- description=OpenDocument text document;\
- file_extensions=.odt;
+ description=OpenDocument text document;\
+ file_extensions=.odt;
application/vnd.ms-excel: \
- description=Microsoft Excel File;\
- file_extensions=.xls;
+ description=Microsoft Excel File;\
+ file_extensions=.xls;
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: \
- description=XLSX File;\
- file_extensions=.xlsx;
+ description=XLSX File;\
+ file_extensions=.xlsx;
application/vnd.openxmlformats-officedocument.presentationml.presentation: \
- description=PPTX File;\
- file_extensions=.pptx;
+ description=PPTX File;\
+ file_extensions=.pptx;
application/vnd.ms-powerpoint: \
- description=Microsoft PowerPoint File;\
- file_extensions=.ppt;
+ description=Microsoft PowerPoint File;\
+ file_extensions=.ppt;
application/x-7z-compressed: \
- description=7-Zip File;\
- file_extensions=.7z;
+ description=7-Zip File;\
+ file_extensions=.7z;
application/msword: \
- description=Microsoft Word File;\
- file_extensions=.doc;
+ description=Microsoft Word File;\
+ file_extensions=.doc;
application/vnd.openxmlformats-officedocument.wordprocessingml.document: \
- description=DOCX File;\
- file_extensions=.docx;
+ description=DOCX File;\
+ file_extensions=.docx;
application/vnd.rar: \
- description=RAR File;\
- file_extensions=.rar;
+ description=RAR File;\
+ file_extensions=.rar;
application/json: \
- description=JSON File;\
- file_extensions=.json;
+ description=JSON File;\
+ file_extensions=.json;
application/bz2: \
- description=BZ2 File;\
- file_extensions=.bz2;
+ description=BZ2 File;\
+ file_extensions=.bz2;
application/java-archive: \
- description=JAR File;\
- file_extensions=.jar;
+ description=JAR File;\
+ file_extensions=.jar;
application/wasm: \
- description=WebAssembly File;\
- file_extensions=.wasm;
+ description=WebAssembly File;\
+ file_extensions=.wasm;
diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/iio-plugin.properties b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/iio-plugin.properties
index 5b9e47b921530..214d9d69b652a 100644
--- a/src/java.desktop/share/classes/com/sun/imageio/plugins/common/iio-plugin.properties
+++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/common/iio-plugin.properties
@@ -8,7 +8,7 @@
# Common properties
ImageUtil0=The supplied Raster does not represent a binary data set.
ImageUtil1=The provided sample model is null.
-ImageUtil2=The provided image cannot be encoded using:
+ImageUtil2=The provided image cannot be encoded using:
GetNumImages0=Input has not been set.
GetNumImages1=seekForwardOnly and allowSearch cannot both be true.
diff --git a/src/java.scripting/share/classes/com/sun/tools/script/shell/messages.properties b/src/java.scripting/share/classes/com/sun/tools/script/shell/messages.properties
index 2e17668b26019..096842465b65e 100644
--- a/src/java.scripting/share/classes/com/sun/tools/script/shell/messages.properties
+++ b/src/java.scripting/share/classes/com/sun/tools/script/shell/messages.properties
@@ -24,22 +24,22 @@
#
string.script.error=\
- script error: {0}
+ script error: {0}
file.script.error=\
- script error in file {0} : {1}
+ script error in file {0} : {1}
file.not.found=\
- script file {0} is not found
+ script file {0} is not found
engine.not.found=\
- script engine for language {0} can not be found
+ script engine for language {0} can not be found
engine.info=\
- Language {0} {1} implementation "{2}" {3}
+ Language {0} {1} implementation "{2}" {3}
encoding.unsupported=\
- encoding {0} is not supported
+ encoding {0} is not supported
main.usage=\
Usage: {0} [options] [arguments...]\n\
diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle.properties
index 83738d94afdf2..9f30c93e1beaa 100644
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle.properties
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle.properties
@@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = getInt Failed on value ( {0} ) in column {1}
cachedrowsetimpl.longfail = getLong Failed on value ( {0} ) in column {1}
cachedrowsetimpl.floatfail = getFloat failed on value ( {0} ) in column {1}
cachedrowsetimpl.doublefail = getDouble failed on value ( {0} ) in column {1}
-cachedrowsetimpl.dtypemismt = Data Type Mismatch
+cachedrowsetimpl.dtypemismt = Data Type Mismatch
cachedrowsetimpl.datefail = getDate Failed on value ( {0} ) in column {1} no conversion available
cachedrowsetimpl.timefail = getTime failed on value ( {0} ) in column {1} no conversion available
cachedrowsetimpl.posupdate = Positioned updates not supported
@@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Use column name as argument to unsetMatchColumn
cachedrowsetimpl.unsetmatch2 = Use column ID as argument to unsetMatchColumn
cachedrowsetimpl.numrows = Number of rows is less than zero or less than fetch size
cachedrowsetimpl.startpos = Start position cannot be negative
-cachedrowsetimpl.nextpage = Populate data before calling
+cachedrowsetimpl.nextpage = Populate data before calling
cachedrowsetimpl.pagesize = Page size cannot be less than zero
cachedrowsetimpl.pagesize1 = Page size cannot be greater than maxRows
cachedrowsetimpl.fwdonly = ResultSet is forward only
@@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Invalid writer
webrowsetimpl.invalidrd = Invalid reader
#FilteredRowSetImpl exceptions
-filteredrowsetimpl.relative = relative : Invalid cursor operation
+filteredrowsetimpl.relative = relative : Invalid cursor operation
filteredrowsetimpl.absolute = absolute : Invalid cursor operation
filteredrowsetimpl.notallowed = This value is not allowed through the filter
@@ -123,15 +123,15 @@ crsreader.caldetected = Detected a Calendar
#CachedRowSetWriter exceptions
crswriter.connect = Unable to get connection
crswriter.tname = writeData cannot determine table name
-crswriter.params1 = Value of params1 : {0}
-crswriter.params2 = Value of params2 : {0}
-crswriter.conflictsno = conflicts while synchronizing
+crswriter.params1 = Value of params1 : {0}
+crswriter.params2 = Value of params2 : {0}
+crswriter.conflictsno = conflicts while synchronizing
#InsertRow exceptions
insertrow.novalue = No value has been inserted
#SyncResolverImpl exceptions
-syncrsimpl.indexval = Index value out of range
+syncrsimpl.indexval = Index value out of range
syncrsimpl.noconflict = This column not in conflict
syncrsimpl.syncnotpos = Synchronization is not possible
syncrsimpl.valtores = Value to be resolved can either be in the database or in cachedrowset
diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties
index 333a5c9e4faaf..1cccbe3774916 100644
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties
@@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = getInt bei Wert ( {0} ) in Spalte {1} nicht erfolgrei
cachedrowsetimpl.longfail = getLong bei Wert ( {0} ) in Spalte {1} nicht erfolgreich
cachedrowsetimpl.floatfail = getFloat bei Wert ( {0} ) in Spalte {1} nicht erfolgreich
cachedrowsetimpl.doublefail = getDouble bei Wert ( {0} ) in Spalte {1} nicht erfolgreich
-cachedrowsetimpl.dtypemismt = Keine Datentypübereinstimmung
+cachedrowsetimpl.dtypemismt = Keine Datentypübereinstimmung
cachedrowsetimpl.datefail = getDate bei Wert ( {0} ) in Spalte {1} nicht erfolgreich. Keine Konvertierung möglich
cachedrowsetimpl.timefail = getTime bei Wert ( {0} ) in Spalte {1} nicht erfolgreich. Keine Konvertierung möglich
cachedrowsetimpl.posupdate = Positionierte Updates werden nicht unterstützt
@@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Spaltenname als Argument für unsetMatchColumn ve
cachedrowsetimpl.unsetmatch2 = Spalten-ID als Argument für unsetMatchColumn verwenden
cachedrowsetimpl.numrows = Zeilenanzahl ist kleiner als null oder kleiner als Abrufgröße
cachedrowsetimpl.startpos = Startposition darf keinen Negativwert aufweisen
-cachedrowsetimpl.nextpage = Daten müssen vor dem Aufruf ausgefüllt werden
+cachedrowsetimpl.nextpage = Daten müssen vor dem Aufruf ausgefüllt werden
cachedrowsetimpl.pagesize = Seitengröße darf nicht kleiner als null sein
cachedrowsetimpl.pagesize1 = Seitengröße darf nicht größer als maxRows sein
cachedrowsetimpl.fwdonly = ResultSet kann nur vorwärts gerichtet sein
@@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Ungültiger Writer
webrowsetimpl.invalidrd = Ungültiger Reader
#FilteredRowSetImpl exceptions
-filteredrowsetimpl.relative = relative: Ungültiger Cursorvorgang
+filteredrowsetimpl.relative = relative: Ungültiger Cursorvorgang
filteredrowsetimpl.absolute = absolute: Ungültiger Cursorvorgang
filteredrowsetimpl.notallowed = Kein zulässiger Wert im Filter
@@ -123,15 +123,15 @@ crsreader.caldetected = Kalender festgestellt
#CachedRowSetWriter exceptions
crswriter.connect = Verbindung kann nicht hergestellt werden
crswriter.tname = writeData kann Tabellennamen nicht bestimmen
-crswriter.params1 = Wert für params1: {0}
-crswriter.params2 = Wert für params2: {0}
-crswriter.conflictsno = Konflikte beim Synchronisieren
+crswriter.params1 = Wert für params1: {0}
+crswriter.params2 = Wert für params2: {0}
+crswriter.conflictsno = Konflikte beim Synchronisieren
#InsertRow exceptions
insertrow.novalue = Es wurde kein Wert eingefügt
#SyncResolverImpl exceptions
-syncrsimpl.indexval = Indexwert liegt außerhalb des Bereichs
+syncrsimpl.indexval = Indexwert liegt außerhalb des Bereichs
syncrsimpl.noconflict = Kein Konflikt bei dieser Spalte
syncrsimpl.syncnotpos = Keine Synchronisierung möglich
syncrsimpl.valtores = Aufzulösender Wert kann sich entweder in der Datenbank oder in cachedrowset befinden
diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_es.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_es.properties
index f60fdc07675a3..3793ed8528870 100644
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_es.properties
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_es.properties
@@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = Fallo de getInt en valor ( {0} ) de columna {1}
cachedrowsetimpl.longfail = Fallo de getLong en valor ( {0} ) de columna {1}
cachedrowsetimpl.floatfail = Fallo de getFloat en valor ( {0} ) de columna {1}
cachedrowsetimpl.doublefail = Fallo de getDouble en valor ( {0} ) de columna {1}
-cachedrowsetimpl.dtypemismt = Discordancia entre Tipos de Datos
+cachedrowsetimpl.dtypemismt = Discordancia entre Tipos de Datos
cachedrowsetimpl.datefail = Fallo de getDate en valor ( {0} ) de columna {1}. No es posible convertir
cachedrowsetimpl.timefail = Fallo de getTime en valor ( {0} ) de columna {1}. No es posible convertir
cachedrowsetimpl.posupdate = Actualizaciones posicionadas no soportadas
@@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Use el nombre de columna como argumento en unsetM
cachedrowsetimpl.unsetmatch2 = Use el identificador de columna como argumento en unsetMatchColumn
cachedrowsetimpl.numrows = El número de filas es menor que cero o menor que el tamaño recuperado
cachedrowsetimpl.startpos = La posición de inicio no puede ser negativa
-cachedrowsetimpl.nextpage = Rellene los datos antes de realizar la llamada
+cachedrowsetimpl.nextpage = Rellene los datos antes de realizar la llamada
cachedrowsetimpl.pagesize = El tamaño de página no puede ser menor que cero
cachedrowsetimpl.pagesize1 = El tamaño de página no puede ser mayor que maxRows
cachedrowsetimpl.fwdonly = ResultSet sólo se reenvía
@@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Escritor no válido
webrowsetimpl.invalidrd = Lector no válido
#FilteredRowSetImpl exceptions
-filteredrowsetimpl.relative = relative: Operación de cursor no válida
+filteredrowsetimpl.relative = relative: Operación de cursor no válida
filteredrowsetimpl.absolute = absolute: Operación de cursor no válida
filteredrowsetimpl.notallowed = El filtro no admite este valor
@@ -123,15 +123,15 @@ crsreader.caldetected = Calendario Detectado
#CachedRowSetWriter exceptions
crswriter.connect = No se ha podido obtener una conexión
crswriter.tname = writeData no puede determinar el nombre de tabla
-crswriter.params1 = Valor de params1: {0}
-crswriter.params2 = Valor de params2: {0}
-crswriter.conflictsno = conflictos en la sincronización
+crswriter.params1 = Valor de params1: {0}
+crswriter.params2 = Valor de params2: {0}
+crswriter.conflictsno = conflictos en la sincronización
#InsertRow exceptions
insertrow.novalue = No se ha insertado ningún valor
#SyncResolverImpl exceptions
-syncrsimpl.indexval = El valor de índice está fuera de rango
+syncrsimpl.indexval = El valor de índice está fuera de rango
syncrsimpl.noconflict = Esta columna no está en conflicto
syncrsimpl.syncnotpos = No se puede sincronizar
syncrsimpl.valtores = El valor que se debe resolver puede estar en la base de datos o en cachedrowset
diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_fr.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_fr.properties
index 358ab13f1ebc8..48dc5e0d12dd5 100644
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_fr.properties
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_fr.properties
@@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = Echec de getInt pour la valeur ({0}) de la colonne {1
cachedrowsetimpl.longfail = Echec de getLong pour la valeur ({0}) de la colonne {1}
cachedrowsetimpl.floatfail = Echec de getFloat pour la valeur ({0}) de la colonne {1}
cachedrowsetimpl.doublefail = Echec de getDouble pour la valeur ({0}) de la colonne {1}
-cachedrowsetimpl.dtypemismt = Le type de données ne correspond pas
+cachedrowsetimpl.dtypemismt = Le type de données ne correspond pas
cachedrowsetimpl.datefail = Echec de getDate pour la valeur ({0}) de la colonne {1} - Aucune conversion possible
cachedrowsetimpl.timefail = Echec de getTime pour la valeur ({0}) de la colonne {1} - Aucune conversion possible
cachedrowsetimpl.posupdate = Mises à jour choisies non prises en charge
@@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Utiliser le nom de colonne comme argument pour un
cachedrowsetimpl.unsetmatch2 = Utiliser l'ID de colonne comme argument pour unsetMatchColumn
cachedrowsetimpl.numrows = Le nombre de lignes est inférieur à zéro ou à la taille d'extraction
cachedrowsetimpl.startpos = La position de départ ne peut pas être négative
-cachedrowsetimpl.nextpage = Entrer les données avant l'appel
+cachedrowsetimpl.nextpage = Entrer les données avant l'appel
cachedrowsetimpl.pagesize = La taille de la page ne peut pas être négative
cachedrowsetimpl.pagesize1 = La taille de la page ne peut pas être supérieure à maxRows
cachedrowsetimpl.fwdonly = ResultSet va en avant seulement
@@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Processus d'écriture non valide
webrowsetimpl.invalidrd = Processus de lecture non valide
#FilteredRowSetImpl exceptions
-filteredrowsetimpl.relative = relative : opération de curseur non valide
+filteredrowsetimpl.relative = relative : opération de curseur non valide
filteredrowsetimpl.absolute = absolute : opération de curseur non valide
filteredrowsetimpl.notallowed = Cette valeur n'est pas autorisée via le filtre
@@ -123,15 +123,15 @@ crsreader.caldetected = Un calendrier a été détecté
#CachedRowSetWriter exceptions
crswriter.connect = Impossible d'obtenir la connexion
crswriter.tname = writeData ne peut pas déterminer le nom de la table
-crswriter.params1 = Valeur de params1 : {0}
-crswriter.params2 = Valeur de params2 : {0}
-crswriter.conflictsno = conflits lors de la synchronisation
+crswriter.params1 = Valeur de params1 : {0}
+crswriter.params2 = Valeur de params2 : {0}
+crswriter.conflictsno = conflits lors de la synchronisation
#InsertRow exceptions
insertrow.novalue = Aucune valeur n'a été insérée
#SyncResolverImpl exceptions
-syncrsimpl.indexval = Valeur d'index hors plage
+syncrsimpl.indexval = Valeur d'index hors plage
syncrsimpl.noconflict = Cette colonne n'est pas en conflit
syncrsimpl.syncnotpos = La synchronisation est impossible
syncrsimpl.valtores = La valeur à résoudre peut être soit dans la base de données, soit dans CachedrowSet
diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_it.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_it.properties
index 8858052319997..7ab025d8c823b 100644
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_it.properties
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_it.properties
@@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = getInt non riuscito per il valore ( {0} ) nella colon
cachedrowsetimpl.longfail = getLong non riuscito per il valore ( {0} ) nella colonna {1}
cachedrowsetimpl.floatfail = getFloat non riuscito per il valore ( {0} ) nella colonna {1}
cachedrowsetimpl.doublefail = getDouble non riuscito per il valore ( {0} ) nella colonna {1}
-cachedrowsetimpl.dtypemismt = Mancata corrispondenza tipo di dati
+cachedrowsetimpl.dtypemismt = Mancata corrispondenza tipo di dati
cachedrowsetimpl.datefail = getDate non riuscito per il valore ( {0} ) nella colonna {1}. Nessuna conversione disponibile.
cachedrowsetimpl.timefail = getTime non riuscito per il valore ( {0} ) nella colonna {1}. Nessuna conversione disponibile.
cachedrowsetimpl.posupdate = Aggiornamenti posizionati non supportati
@@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Utilizzare il nome di colonna come argomento per
cachedrowsetimpl.unsetmatch2 = Utilizzare l'ID di colonna come argomento per unsetMatchColumn
cachedrowsetimpl.numrows = Il numero di righe è inferiore a zero o alla dimensione di recupero
cachedrowsetimpl.startpos = La posizione iniziale non può essere negativa
-cachedrowsetimpl.nextpage = Inserire i dati prima di chiamare
+cachedrowsetimpl.nextpage = Inserire i dati prima di chiamare
cachedrowsetimpl.pagesize = La dimensione della pagina non può essere inferiore a zero
cachedrowsetimpl.pagesize1 = La dimensione della pagina non può essere superiore a maxRows
cachedrowsetimpl.fwdonly = ResultSet è a solo inoltro
@@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Processo di scrittura non valido
webrowsetimpl.invalidrd = Processo di lettura non valido
#FilteredRowSetImpl exceptions
-filteredrowsetimpl.relative = relative: operazione cursore non valida
+filteredrowsetimpl.relative = relative: operazione cursore non valida
filteredrowsetimpl.absolute = absolute: operazione cursore non valida
filteredrowsetimpl.notallowed = Questo valore non è consentito nel filtro
@@ -123,15 +123,15 @@ crsreader.caldetected = È stato rilevato un calendario
#CachedRowSetWriter exceptions
crswriter.connect = Impossibile stabilire una connessione
crswriter.tname = writeData non riesce a determinare il nome di tabella
-crswriter.params1 = Valore dei parametri 1: {0}
-crswriter.params2 = Valore dei parametri 2: {0}
-crswriter.conflictsno = Conflitti durante la sincronizzazione
+crswriter.params1 = Valore dei parametri 1: {0}
+crswriter.params2 = Valore dei parametri 2: {0}
+crswriter.conflictsno = Conflitti durante la sincronizzazione
#InsertRow exceptions
insertrow.novalue = Non è stato inserito alcun valore
#SyncResolverImpl exceptions
-syncrsimpl.indexval = Valore indice non compreso nell'intervallo
+syncrsimpl.indexval = Valore indice non compreso nell'intervallo
syncrsimpl.noconflict = Questa colonna non è in conflitto
syncrsimpl.syncnotpos = Impossibile eseguire la sincronizzazione
syncrsimpl.valtores = Il valore da risolvere può essere nel database o in cachedrowset
diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties
index e5aebb2904e93..e2f906f74cded 100644
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties
@@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = 列{1}の値({0})でgetIntが失敗しました
cachedrowsetimpl.longfail = 列{1}の値({0})でgetLongが失敗しました
cachedrowsetimpl.floatfail = 列{1}の値({0})でgetFloatが失敗しました
cachedrowsetimpl.doublefail = 列{1}の値({0})でgetDoubleが失敗しました
-cachedrowsetimpl.dtypemismt = データ型の不一致
+cachedrowsetimpl.dtypemismt = データ型の不一致
cachedrowsetimpl.datefail = 列{1}の値({0})でgetDateが失敗。変換できません
cachedrowsetimpl.timefail = 列{1}の値({0})でgetTimeが失敗。変換できません
cachedrowsetimpl.posupdate = 位置決めされた更新がサポートされません
@@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = unsetMatchColumnへの引数として列名を使
cachedrowsetimpl.unsetmatch2 = unsetMatchColumnへの引数として列IDを使用してください
cachedrowsetimpl.numrows = 行数がゼロまたはフェッチ・サイズより小さいです
cachedrowsetimpl.startpos = 開始位置を負にすることはできません
-cachedrowsetimpl.nextpage = 呼出し前にデータを移入します
+cachedrowsetimpl.nextpage = 呼出し前にデータを移入します
cachedrowsetimpl.pagesize = ページ・サイズをゼロより小さくすることはできません
cachedrowsetimpl.pagesize1 = ページ・サイズをmaxRowsより大きくすることができません
cachedrowsetimpl.fwdonly = ResultSetは順方向のみです
@@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = 無効なライター
webrowsetimpl.invalidrd = 無効なリーダー
#FilteredRowSetImpl exceptions
-filteredrowsetimpl.relative = relative: 無効なカーソル操作
+filteredrowsetimpl.relative = relative: 無効なカーソル操作
filteredrowsetimpl.absolute = absolute: 無効なカーソル操作
filteredrowsetimpl.notallowed = この値はフィルタで許容されません
@@ -123,15 +123,15 @@ crsreader.caldetected = カレンダを検出しました
#CachedRowSetWriter exceptions
crswriter.connect = 接続を取得できません
crswriter.tname = writeDataが表名を判別できません
-crswriter.params1 = params1の値: {0}
-crswriter.params2 = params2の値: {0}
-crswriter.conflictsno = 同期中に競合が発生します
+crswriter.params1 = params1の値: {0}
+crswriter.params2 = params2の値: {0}
+crswriter.conflictsno = 同期中に競合が発生します
#InsertRow exceptions
insertrow.novalue = 値は挿入されていません
#SyncResolverImpl exceptions
-syncrsimpl.indexval = 範囲外の索引値
+syncrsimpl.indexval = 範囲外の索引値
syncrsimpl.noconflict = この列は競合していません
syncrsimpl.syncnotpos = 同期できません
syncrsimpl.valtores = 解決される値はデータベースまたはcachedrowsetにある可能性があります
diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties
index f52cbead25242..9f01b1051aa97 100644
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties
@@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = {1} 열의 값({0})에서 getInt를 실패했습니
cachedrowsetimpl.longfail = {1} 열의 값({0})에서 getLong을 실패했습니다.
cachedrowsetimpl.floatfail = {1} 열의 값({0})에서 getFloat를 실패했습니다.
cachedrowsetimpl.doublefail = {1} 열의 값({0})에서 getDouble을 실패했습니다.
-cachedrowsetimpl.dtypemismt = 데이터 유형이 일치하지 않습니다.
+cachedrowsetimpl.dtypemismt = 데이터 유형이 일치하지 않습니다.
cachedrowsetimpl.datefail = {1} 열의 값({0})에서 getDate를 실패했습니다. 변환할 수 없습니다.
cachedrowsetimpl.timefail = {1} 열의 값({0})에서 getTime을 실패했습니다. 변환할 수 없습니다.
cachedrowsetimpl.posupdate = 위치가 지정된 업데이트가 지원되지 않습니다.
@@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = 열 이름을 unsetMatchColumn의 인수로 사
cachedrowsetimpl.unsetmatch2 = 열 ID를 unsetMatchColumn의 인수로 사용하십시오.
cachedrowsetimpl.numrows = 행 수가 0보다 작거나 인출 크기보다 작습니다.
cachedrowsetimpl.startpos = 시작 위치는 음수일 수 없습니다.
-cachedrowsetimpl.nextpage = 호출하기 전에 데이터를 채우십시오.
+cachedrowsetimpl.nextpage = 호출하기 전에 데이터를 채우십시오.
cachedrowsetimpl.pagesize = 페이지 크기는 0보다 작을 수 없습니다.
cachedrowsetimpl.pagesize1 = 페이지 크기는 maxRows보다 클 수 없습니다.
cachedrowsetimpl.fwdonly = ResultSet는 전달 전용입니다.
@@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = 기록 장치가 부적합합니다.
webrowsetimpl.invalidrd = 읽기 프로그램이 부적합합니다.
#FilteredRowSetImpl exceptions
-filteredrowsetimpl.relative = 상대: 커서 작업이 부적합합니다.
+filteredrowsetimpl.relative = 상대: 커서 작업이 부적합합니다.
filteredrowsetimpl.absolute = 절대: 커서 작업이 부적합합니다.
filteredrowsetimpl.notallowed = 이 값은 필터를 통과할 수 없습니다.
@@ -123,15 +123,15 @@ crsreader.caldetected = 달력을 감지함
#CachedRowSetWriter exceptions
crswriter.connect = 접속할 수 없습니다.
crswriter.tname = writeData에서 테이블 이름을 확인할 수 없습니다.
-crswriter.params1 = params1의 값: {0}
-crswriter.params2 = params2의 값: {0}
-crswriter.conflictsno = 동기화하는 중 충돌함
+crswriter.params1 = params1의 값: {0}
+crswriter.params2 = params2의 값: {0}
+crswriter.conflictsno = 동기화하는 중 충돌함
#InsertRow exceptions
insertrow.novalue = 값이 삽입되지 않았습니다.
#SyncResolverImpl exceptions
-syncrsimpl.indexval = 인덱스 값이 범위를 벗어났습니다.
+syncrsimpl.indexval = 인덱스 값이 범위를 벗어났습니다.
syncrsimpl.noconflict = 이 열은 충돌하지 않습니다.
syncrsimpl.syncnotpos = 동기화할 수 없습니다.
syncrsimpl.valtores = 분석할 값이 데이터베이스 또는 cachedrowset에 있을 수 있습니다.
diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_pt_BR.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_pt_BR.properties
index fb24edc87cd8a..4f0d136918152 100644
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_pt_BR.properties
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_pt_BR.properties
@@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = Falha em getInt no valor ( {0} ) na coluna {1}
cachedrowsetimpl.longfail = Falha em getLong no valor ( {0} ) na coluna {1}
cachedrowsetimpl.floatfail = Falha em getFloat no valor ( {0} ) na coluna {1}
cachedrowsetimpl.doublefail = Falha em getDouble no valor ( {0} ) na coluna {1}
-cachedrowsetimpl.dtypemismt = Tipo de Dados Incompatível
+cachedrowsetimpl.dtypemismt = Tipo de Dados Incompatível
cachedrowsetimpl.datefail = Falha em getDate no valor ( {0} ) na coluna {1} sem conversão disponível
cachedrowsetimpl.timefail = Falha em getTime no valor ( {0} ) na coluna {1} sem conversão disponível
cachedrowsetimpl.posupdate = Atualizações posicionadas não suportadas
@@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Usar o nome da coluna como argumento para unsetMa
cachedrowsetimpl.unsetmatch2 = Usar o ID da coluna como argumento para unsetMatchColumn
cachedrowsetimpl.numrows = O número de linhas é menor do que zero ou menor do que o tamanho obtido
cachedrowsetimpl.startpos = A posição de início não pode ser negativa
-cachedrowsetimpl.nextpage = Preencher dados antes de chamar
+cachedrowsetimpl.nextpage = Preencher dados antes de chamar
cachedrowsetimpl.pagesize = O tamanho da página não pode ser menor do que zero
cachedrowsetimpl.pagesize1 = O tamanho da página não pode ser maior do que maxRows
cachedrowsetimpl.fwdonly = ResultSet é somente para frente
@@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Gravador inválido
webrowsetimpl.invalidrd = Leitor inválido
#FilteredRowSetImpl exceptions
-filteredrowsetimpl.relative = relative : Operação inválida do cursor
+filteredrowsetimpl.relative = relative : Operação inválida do cursor
filteredrowsetimpl.absolute = absolute : Operação inválida do cursor
filteredrowsetimpl.notallowed = Este valor não é permitido no filtro
@@ -123,15 +123,15 @@ crsreader.caldetected = Calendário Detectado
#CachedRowSetWriter exceptions
crswriter.connect = Não é possível obter a conexão
crswriter.tname = writeData não pode determinar o nome da tabela
-crswriter.params1 = Valor de params1 : {0}
-crswriter.params2 = Valor de params2 : {0}
-crswriter.conflictsno = conflitos durante a sincronização
+crswriter.params1 = Valor de params1 : {0}
+crswriter.params2 = Valor de params2 : {0}
+crswriter.conflictsno = conflitos durante a sincronização
#InsertRow exceptions
insertrow.novalue = Nenhum valor foi inserido
#SyncResolverImpl exceptions
-syncrsimpl.indexval = Valor de índice fora da faixa
+syncrsimpl.indexval = Valor de índice fora da faixa
syncrsimpl.noconflict = Está coluna não está em conflito
syncrsimpl.syncnotpos = A sincronização não é possível
syncrsimpl.valtores = O valor a ser decidido pode estar no banco de dados ou no conjunto de linhas armazenado no cache
diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_sv.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_sv.properties
index 8529c9169b4d4..3bc14d48f9fa5 100644
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_sv.properties
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_sv.properties
@@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = getInt utfördes inte för värdet ({0}) i kolumnen {
cachedrowsetimpl.longfail = getLong utfördes inte för värdet ({0}) i kolumnen {1}
cachedrowsetimpl.floatfail = getFloat utfördes inte för värdet ({0}) i kolumnen {1}
cachedrowsetimpl.doublefail = getDouble utfördes inte för värdet ({0}) i kolumnen {1}
-cachedrowsetimpl.dtypemismt = Felmatchad datatyp
+cachedrowsetimpl.dtypemismt = Felmatchad datatyp
cachedrowsetimpl.datefail = getDate utfördes inte för värdet ({0}) i kolumnen {1}, ingen konvertering tillgänglig
cachedrowsetimpl.timefail = getTime utfördes inte för värdet ({0}) i kolumnen {1}, ingen konvertering tillgänglig
cachedrowsetimpl.posupdate = Det finns inte stöd för positionerad uppdatering
@@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = Använd kolumnnamn som argument för unsetMatchCo
cachedrowsetimpl.unsetmatch2 = Använd kolumn-id som argument för unsetMatchColumn
cachedrowsetimpl.numrows = Antalet rader understiger noll eller är mindre än hämtningsstorleken
cachedrowsetimpl.startpos = Startpositionen får inte vara negativ
-cachedrowsetimpl.nextpage = Fyll i data innan anrop
+cachedrowsetimpl.nextpage = Fyll i data innan anrop
cachedrowsetimpl.pagesize = Sidstorleken får inte understiga noll
cachedrowsetimpl.pagesize1 = Sidstorleken får inte överstiga maxRows
cachedrowsetimpl.fwdonly = ResultSet kan endast gå framåt
@@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = Ogiltig skrivfunktion
webrowsetimpl.invalidrd = Ogiltig läsare
#FilteredRowSetImpl exceptions
-filteredrowsetimpl.relative = relative: Ogiltig marköråtgärd
+filteredrowsetimpl.relative = relative: Ogiltig marköråtgärd
filteredrowsetimpl.absolute = absolute: Ogiltig marköråtgärd
filteredrowsetimpl.notallowed = Detta värde kommer att filtreras bort
@@ -123,15 +123,15 @@ crsreader.caldetected = En kalender har identifierats
#CachedRowSetWriter exceptions
crswriter.connect = Kan inte upprätta anslutning
crswriter.tname = writeData kan inte fastställa tabellnamnet
-crswriter.params1 = Parametervärde1: {0}
-crswriter.params2 = Parametervärde2: {0}
-crswriter.conflictsno = orsakar konflikt vid synkronisering
+crswriter.params1 = Parametervärde1: {0}
+crswriter.params2 = Parametervärde2: {0}
+crswriter.conflictsno = orsakar konflikt vid synkronisering
#InsertRow exceptions
insertrow.novalue = Inget värde har infogats
#SyncResolverImpl exceptions
-syncrsimpl.indexval = Indexvärdet ligger utanför intervallet
+syncrsimpl.indexval = Indexvärdet ligger utanför intervallet
syncrsimpl.noconflict = Kolumnen orsakar ingen konflikt
syncrsimpl.syncnotpos = Synkronisering är inte möjlig
syncrsimpl.valtores = Värdet som ska fastställas kan antingen finnas i databasen eller i cachedrowset
diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties
index c7469edd5c484..d9b4052f00aa8 100644
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties
@@ -41,7 +41,7 @@ cachedrowsetimpl.intfail = 对列 {1} 中的值 ({0}) 执行 getInt 失败
cachedrowsetimpl.longfail = 对列 {1} 中的值 ({0}) 执行 getLong 失败
cachedrowsetimpl.floatfail = 对列 {1} 中的值 ({0}) 执行 getFloat 失败
cachedrowsetimpl.doublefail = 对列 {1} 中的值 ({0}) 执行 getDouble 失败
-cachedrowsetimpl.dtypemismt = 数据类型不匹配
+cachedrowsetimpl.dtypemismt = 数据类型不匹配
cachedrowsetimpl.datefail = 对列 {1} 中的值 ({0}) 执行 getDate 失败, 无可用转换
cachedrowsetimpl.timefail = 对列 {1} 中的值 ({0}) 执行 getTime 失败, 无可用转换
cachedrowsetimpl.posupdate = 不支持定位更新
@@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = 使用列名作为 unsetMatchColumn 的参数
cachedrowsetimpl.unsetmatch2 = 使用列 ID 作为 unsetMatchColumn 的参数
cachedrowsetimpl.numrows = 行数小于零或小于要提取的行数
cachedrowsetimpl.startpos = 起始位置不能为负数
-cachedrowsetimpl.nextpage = 在调用之前先填充数据
+cachedrowsetimpl.nextpage = 在调用之前先填充数据
cachedrowsetimpl.pagesize = 页面大小不能小于零
cachedrowsetimpl.pagesize1 = 页面大小不能大于 maxRows
cachedrowsetimpl.fwdonly = ResultSet 的类型为仅向前类型
@@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = 写进程无效
webrowsetimpl.invalidrd = 读进程无效
#FilteredRowSetImpl exceptions
-filteredrowsetimpl.relative = relative: 光标操作无效
+filteredrowsetimpl.relative = relative: 光标操作无效
filteredrowsetimpl.absolute = absolute: 光标操作无效
filteredrowsetimpl.notallowed = 不允许此值通过筛选器
@@ -123,15 +123,15 @@ crsreader.caldetected = 检测到日历
#CachedRowSetWriter exceptions
crswriter.connect = 无法获取连接
crswriter.tname = writeData 无法确定表名
-crswriter.params1 = params1 的值: {0}
-crswriter.params2 = params2 的值: {0}
-crswriter.conflictsno = 同步时发生冲突
+crswriter.params1 = params1 的值: {0}
+crswriter.params2 = params2 的值: {0}
+crswriter.conflictsno = 同步时发生冲突
#InsertRow exceptions
insertrow.novalue = 尚未插入任何值
#SyncResolverImpl exceptions
-syncrsimpl.indexval = 索引值超出范围
+syncrsimpl.indexval = 索引值超出范围
syncrsimpl.noconflict = 此列不冲突
syncrsimpl.syncnotpos = 不能同步
syncrsimpl.valtores = 要解析的值可以在数据库中, 也可以在 CachedRowSet 中
diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_TW.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_TW.properties
index c9a38a280e36d..d1539384bd90d 100644
--- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_TW.properties
+++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_TW.properties
@@ -70,7 +70,7 @@ cachedrowsetimpl.unsetmatch1 = 使用欄名作為 unsetMatchColumn 的引數
cachedrowsetimpl.unsetmatch2 = 使用欄 ID 作為 unsetMatchColumn 的引數
cachedrowsetimpl.numrows = 列數小於零或小於擷取大小
cachedrowsetimpl.startpos = 起始位置不能為負數
-cachedrowsetimpl.nextpage = 在呼叫之前植入資料
+cachedrowsetimpl.nextpage = 在呼叫之前植入資料
cachedrowsetimpl.pagesize = 頁面大小不能小於零
cachedrowsetimpl.pagesize1 = 頁面大小不能大於 maxRows
cachedrowsetimpl.fwdonly = ResultSet 只能向前進行
@@ -84,7 +84,7 @@ webrowsetimpl.invalidwr = 寫入器無效
webrowsetimpl.invalidrd = 讀取器無效
#FilteredRowSetImpl exceptions
-filteredrowsetimpl.relative = relative: 游標作業無效
+filteredrowsetimpl.relative = relative: 游標作業無效
filteredrowsetimpl.absolute = absolute: 游標作業無效
filteredrowsetimpl.notallowed = 不允許此值通過篩選
@@ -123,15 +123,15 @@ crsreader.caldetected = 偵測到行事曆
#CachedRowSetWriter exceptions
crswriter.connect = 無法取得連線
crswriter.tname = writeData 不能決定表格名稱
-crswriter.params1 = params1 的值: {0}
-crswriter.params2 = params2 的值: {0}
-crswriter.conflictsno = 同步化時發生衝突
+crswriter.params1 = params1 的值: {0}
+crswriter.params2 = params2 的值: {0}
+crswriter.conflictsno = 同步化時發生衝突
#InsertRow exceptions
insertrow.novalue = 尚未插入值
#SyncResolverImpl exceptions
-syncrsimpl.indexval = 索引值超出範圍
+syncrsimpl.indexval = 索引值超出範圍
syncrsimpl.noconflict = 此欄不衝突
syncrsimpl.syncnotpos = 不可能同步化
syncrsimpl.valtores = 要解析的值可位於資料庫或 cachedrowset 中
diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_en.properties b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_en.properties
index db9c2d544633b..d95071e0bad50 100644
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_en.properties
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/xmlsecurity_en.properties
@@ -128,7 +128,7 @@ signature.Transform.NullPointerTransform = Null pointer as URI. Programming bug?
signature.Transform.UnknownTransform = Unknown transformation. No handler installed for URI {0}
signature.Transform.XPathError = Error evaluating XPath expression
signature.Transform.node = Current Node: {0}
-signature.Transform.nodeAndType = Current Node: {0}, type: {1}
+signature.Transform.nodeAndType = Current Node: {0}, type: {1}
signature.Util.BignumNonPositive = bigInteger.signum() must be positive
signature.Util.NonTextNode = Not a text node
signature.Util.TooManyChilds = Too many childs of Type {0} in {1}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages.properties
index 05f67d5b088bf..0472b424c6d29 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages.properties
@@ -21,28 +21,28 @@
# The messages are arranged in key and value tuples in a ListResourceBundle.
BadMessageKey = The error message corresponding to the message key can not be found.
- FormatFailed = An internal error occurred while formatting the following message:\n
+ FormatFailed = An internal error occurred while formatting the following message:\n
# DOM Core
# exception codes
-DOMSTRING_SIZE_ERR = The specified range of text does not fit into a DOMString.
-HIERARCHY_REQUEST_ERR = An attempt was made to insert a node where it is not permitted.
+DOMSTRING_SIZE_ERR = The specified range of text does not fit into a DOMString.
+HIERARCHY_REQUEST_ERR = An attempt was made to insert a node where it is not permitted.
INDEX_SIZE_ERR = The index or size is negative, or greater than the allowed value.
INUSE_ATTRIBUTE_ERR = An attempt is made to add an attribute that is already in use elsewhere.
-INVALID_ACCESS_ERR = A parameter or an operation is not supported by the underlying object.
-INVALID_CHARACTER_ERR = An invalid or illegal XML character is specified.
-INVALID_MODIFICATION_ERR = An attempt is made to modify the type of the underlying object.
-INVALID_STATE_ERR = An attempt is made to use an object that is not, or is no longer, usable.
+INVALID_ACCESS_ERR = A parameter or an operation is not supported by the underlying object.
+INVALID_CHARACTER_ERR = An invalid or illegal XML character is specified.
+INVALID_MODIFICATION_ERR = An attempt is made to modify the type of the underlying object.
+INVALID_STATE_ERR = An attempt is made to use an object that is not, or is no longer, usable.
NAMESPACE_ERR = An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.
NOT_FOUND_ERR = An attempt is made to reference a node in a context where it does not exist.
-NOT_SUPPORTED_ERR = The implementation does not support the requested type of object or operation.
+NOT_SUPPORTED_ERR = The implementation does not support the requested type of object or operation.
NO_DATA_ALLOWED_ERR = Data is specified for a node which does not support data.
NO_MODIFICATION_ALLOWED_ERR = An attempt is made to modify an object where modifications are not allowed.
-SYNTAX_ERR = An invalid or illegal string is specified.
+SYNTAX_ERR = An invalid or illegal string is specified.
VALIDATION_ERR = A call to a method such as insertBefore or removeChild would make the Node invalid with respect to document grammar.
WRONG_DOCUMENT_ERR = A node is used in a different document than the one that created it.
-TYPE_MISMATCH_ERR = The value type for this parameter name is incompatible with the expected value type.
+TYPE_MISMATCH_ERR = The value type for this parameter name is incompatible with the expected value type.
#error messages or exceptions
FEATURE_NOT_SUPPORTED = The parameter {0} is recognized but the requested value cannot be set.
@@ -77,7 +77,7 @@ INVALID_NODE_TYPE_ERR = The container of a boundary-point of a Range is being se
#Events
-UNSPECIFIED_EVENT_TYPE_ERR = The Event's type was not specified by initializing the event before the method was called.
+UNSPECIFIED_EVENT_TYPE_ERR = The Event's type was not specified by initializing the event before the method was called.
jaxp-schema-support=Both the setSchema method and the schemaLanguage property is used
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties
index 2c3e7226b30de..3613fca907706 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties
@@ -21,28 +21,28 @@
# The messages are arranged in key and value tuples in a ListResourceBundle.
BadMessageKey = Die zum Meldungsschlüssel gehörige Fehlermeldung kann nicht gefunden werden.
- FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n
+ FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n
# DOM Core
# exception codes
-DOMSTRING_SIZE_ERR = Der angegebene Textbereich passt nicht in eine DOMString.
-HIERARCHY_REQUEST_ERR = Es wurde versucht, einen Knoten an einer Stelle einzufügen, an der dies nicht zulässig ist.
+DOMSTRING_SIZE_ERR = Der angegebene Textbereich passt nicht in eine DOMString.
+HIERARCHY_REQUEST_ERR = Es wurde versucht, einen Knoten an einer Stelle einzufügen, an der dies nicht zulässig ist.
INDEX_SIZE_ERR = Index oder Größe ist negativ oder größer als der zulässige Wert.
INUSE_ATTRIBUTE_ERR = Es wurde versucht, ein Attribut hinzuzufügen, das bereits an einer anderen Stelle verwendet wird.
-INVALID_ACCESS_ERR = Ein Parameter oder Vorgang wird nicht vom zugrunde liegenden Objekt unterstützt.
-INVALID_CHARACTER_ERR = Ungültiges oder unzulässiges XML-Zeichen angegeben.
-INVALID_MODIFICATION_ERR = Es wurde versucht, den Typ des zugrunde liegenden Objekts zu ändern.
-INVALID_STATE_ERR = Es wurde versucht, ein Objekt zu ändern, das nicht verwendet werden kann.
+INVALID_ACCESS_ERR = Ein Parameter oder Vorgang wird nicht vom zugrunde liegenden Objekt unterstützt.
+INVALID_CHARACTER_ERR = Ungültiges oder unzulässiges XML-Zeichen angegeben.
+INVALID_MODIFICATION_ERR = Es wurde versucht, den Typ des zugrunde liegenden Objekts zu ändern.
+INVALID_STATE_ERR = Es wurde versucht, ein Objekt zu ändern, das nicht verwendet werden kann.
NAMESPACE_ERR = Es wurde versucht, ein Objekt auf eine Weise zu erstellen oder zu ändern, die falsch in Bezug auf Namespaces ist.
NOT_FOUND_ERR = Es wurde versucht, einen Knoten in einem Kontext zu referenzieren, in dem er nicht vorhanden ist.
-NOT_SUPPORTED_ERR = Der angeforderte Typ des Objekts oder Vorgangs wird nicht von der Implementierung unterstützt.
+NOT_SUPPORTED_ERR = Der angeforderte Typ des Objekts oder Vorgangs wird nicht von der Implementierung unterstützt.
NO_DATA_ALLOWED_ERR = Daten wurden für einen Knoten angegeben, der keine Daten unterstützt.
NO_MODIFICATION_ALLOWED_ERR = Es wurde versucht, ein Objekt zu ändern, bei dem Änderungen nicht zulässig sind.
-SYNTAX_ERR = Ungültige oder unzulässige Zeichenfolge angegeben.
+SYNTAX_ERR = Ungültige oder unzulässige Zeichenfolge angegeben.
VALIDATION_ERR = Aufruf einer Methode wie insertBefore oder removeChild würde die Dokumentgrammatik des Knotens ungültig machen.
WRONG_DOCUMENT_ERR = Ein Knoten wird in einem anderen Dokument verwendet als dem, von dem er erstellt wurde.
-TYPE_MISMATCH_ERR = Der Werttyp für diesen Parameternamen ist nicht mit dem erwarteten Werttyp kompatibel.
+TYPE_MISMATCH_ERR = Der Werttyp für diesen Parameternamen ist nicht mit dem erwarteten Werttyp kompatibel.
#error messages or exceptions
FEATURE_NOT_SUPPORTED = Parameter {0} wird erkannt, aber der angeforderte Wert kann nicht festgelegt werden.
@@ -77,7 +77,7 @@ INVALID_NODE_TYPE_ERR = Container eines Grenzwertes eines Bereichs wird entweder
#Events
-UNSPECIFIED_EVENT_TYPE_ERR = Der Ereignistyp wurde nicht durch Initialisieren des Ereignisses vor dem Aufruf der Methode angegeben.
+UNSPECIFIED_EVENT_TYPE_ERR = Der Ereignistyp wurde nicht durch Initialisieren des Ereignisses vor dem Aufruf der Methode angegeben.
jaxp-schema-support=setSchema-Methode und schemaLanguage-Eigenschaft werden verwendet
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_es.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_es.properties
index deebc5b808b0a..4d190c073c535 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_es.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_es.properties
@@ -29,28 +29,28 @@
# The messages are arranged in key and value tuples in a ListResourceBundle.
BadMessageKey = No se ha encontrado el mensaje de error correspondiente a la clave de mensaje.
- FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n
+ FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n
# DOM Core
# exception codes
-DOMSTRING_SIZE_ERR = El rango especificado de texto no cabe en una cadena DOM.
-HIERARCHY_REQUEST_ERR = Se ha realizado un intento de insertar un nodo donde no está permitido.
+DOMSTRING_SIZE_ERR = El rango especificado de texto no cabe en una cadena DOM.
+HIERARCHY_REQUEST_ERR = Se ha realizado un intento de insertar un nodo donde no está permitido.
INDEX_SIZE_ERR = El índice o tamaño es negativo o superior al valor permitido.
INUSE_ATTRIBUTE_ERR = Se ha realizado un intento de agregar un atributo que ya se está utilizando en otro lugar.
-INVALID_ACCESS_ERR = El objeto subyacente no soporta un parámetro o una operación.
-INVALID_CHARACTER_ERR = Se ha especificado un carácter XML no válido o no permitido.
-INVALID_MODIFICATION_ERR = Se ha realizado un intento de modificar el tipo de objeto subyacente.
-INVALID_STATE_ERR = Se ha realizado un intento de utilizar un objeto que ya no se puede utilizar.
+INVALID_ACCESS_ERR = El objeto subyacente no soporta un parámetro o una operación.
+INVALID_CHARACTER_ERR = Se ha especificado un carácter XML no válido o no permitido.
+INVALID_MODIFICATION_ERR = Se ha realizado un intento de modificar el tipo de objeto subyacente.
+INVALID_STATE_ERR = Se ha realizado un intento de utilizar un objeto que ya no se puede utilizar.
NAMESPACE_ERR = Se ha realizado un intento de crear o cambiar un objeto de un modo incorrecto con respecto a los espacios de nombres.
NOT_FOUND_ERR = Se ha realizado un intento de hacer referencia a un nodo en un contexto en el que no existe.
-NOT_SUPPORTED_ERR = La implantación no soporta el tipo solicitado de objeto u operación.
+NOT_SUPPORTED_ERR = La implantación no soporta el tipo solicitado de objeto u operación.
NO_DATA_ALLOWED_ERR = Se han especificado datos para un nodo que no soporta datos.
NO_MODIFICATION_ALLOWED_ERR = Se ha realizado un intento de modificar un objeto en el que no están permitidas las modificaciones.
-SYNTAX_ERR = Se ha especificado una cadena no válida o no permitida.
+SYNTAX_ERR = Se ha especificado una cadena no válida o no permitida.
VALIDATION_ERR = Una llamada a un método como insertBefore o removeChild invalidaría el nodo con respecto a la gramática del documento.
WRONG_DOCUMENT_ERR = Se ha utilizado un nodo en un documento distinto al que lo creó.
-TYPE_MISMATCH_ERR = El tipo de valor para este nombre de parámetro no es compatible con el tipo de valor esperado.
+TYPE_MISMATCH_ERR = El tipo de valor para este nombre de parámetro no es compatible con el tipo de valor esperado.
#error messages or exceptions
FEATURE_NOT_SUPPORTED = Se reconoce el parámetro {0} pero no se puede definir el valor solicitado.
@@ -85,7 +85,7 @@ INVALID_NODE_TYPE_ERR = El contenedor de un punto de límite de un rango se est
#Events
-UNSPECIFIED_EVENT_TYPE_ERR = No se ha especificado el tipo de evento mediante la inicialización del evento antes de que se llame al método.
+UNSPECIFIED_EVENT_TYPE_ERR = No se ha especificado el tipo de evento mediante la inicialización del evento antes de que se llame al método.
jaxp-schema-support=Se utiliza tanto el método setSchema como la propiedad schemaLanguage
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_fr.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_fr.properties
index 24e427d88ec7c..deff1f741a023 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_fr.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_fr.properties
@@ -29,28 +29,28 @@
# The messages are arranged in key and value tuples in a ListResourceBundle.
BadMessageKey = Le message d'erreur correspondant à la clé de message est introuvable.
- FormatFailed = Une erreur interne est survenue lors du formatage du message suivant :\n
+ FormatFailed = Une erreur interne est survenue lors du formatage du message suivant :\n
# DOM Core
# exception codes
-DOMSTRING_SIZE_ERR = La plage de texte indiquée ne tient pas dans un élément DOMString.
-HIERARCHY_REQUEST_ERR = Tentative d'insertion d'un noeud à un emplacement non autorisé.
+DOMSTRING_SIZE_ERR = La plage de texte indiquée ne tient pas dans un élément DOMString.
+HIERARCHY_REQUEST_ERR = Tentative d'insertion d'un noeud à un emplacement non autorisé.
INDEX_SIZE_ERR = L'index ou la taille est négatif ou dépasse la valeur autorisée.
INUSE_ATTRIBUTE_ERR = Tentative d'ajout d'un attribut déjà utilisé ailleurs.
-INVALID_ACCESS_ERR = Un paramètre ou une opération n'est pas pris en charge par l'objet sous-jacent.
-INVALID_CHARACTER_ERR = Un caractère XML non valide ou non admis est indiqué.
-INVALID_MODIFICATION_ERR = Tentative de modification du type de l'objet sous-jacent.
-INVALID_STATE_ERR = Tentative d'utilisation d'un objet qui n'est pas ou plus utilisable.
+INVALID_ACCESS_ERR = Un paramètre ou une opération n'est pas pris en charge par l'objet sous-jacent.
+INVALID_CHARACTER_ERR = Un caractère XML non valide ou non admis est indiqué.
+INVALID_MODIFICATION_ERR = Tentative de modification du type de l'objet sous-jacent.
+INVALID_STATE_ERR = Tentative d'utilisation d'un objet qui n'est pas ou plus utilisable.
NAMESPACE_ERR = Tentative de création ou de modification d'un objet incorrecte par rapport aux espaces de noms.
NOT_FOUND_ERR = Tentative de référencement d'un noeud dans un contexte où il n'existe pas.
-NOT_SUPPORTED_ERR = L'implémentation ne prend pas en charge le type d'objet ou d'opération demandé.
+NOT_SUPPORTED_ERR = L'implémentation ne prend pas en charge le type d'objet ou d'opération demandé.
NO_DATA_ALLOWED_ERR = Des données ont été indiquées pour un noeud ne prenant pas en charge les données.
NO_MODIFICATION_ALLOWED_ERR = Tentative de modification d'un objet pour lequel les modifications ne sont pas autorisées.
-SYNTAX_ERR = Une chaîne non valide ou non admise est indiquée.
+SYNTAX_ERR = Une chaîne non valide ou non admise est indiquée.
VALIDATION_ERR = L'appel d'une méthode comme insertBefore ou removeChild risque de rendre le noeud non valide par rapport à la grammaire de document.
WRONG_DOCUMENT_ERR = Un noeud est utilisé dans un document différent de celui l'ayant créé.
-TYPE_MISMATCH_ERR = Le type de valeur pour ce nom de paramètre n'est pas compatible avec le type de valeur attendu.
+TYPE_MISMATCH_ERR = Le type de valeur pour ce nom de paramètre n'est pas compatible avec le type de valeur attendu.
#error messages or exceptions
FEATURE_NOT_SUPPORTED = Le paramètre {0} est reconnu mais la valeur demandée ne peut pas être définie.
@@ -85,7 +85,7 @@ INVALID_NODE_TYPE_ERR = Le conteneur d'un point de limite d'une plage est défin
#Events
-UNSPECIFIED_EVENT_TYPE_ERR = Le type d'événement n'a pas été indiqué en initialisant l'événement avant l'appel de la méthode.
+UNSPECIFIED_EVENT_TYPE_ERR = Le type d'événement n'a pas été indiqué en initialisant l'événement avant l'appel de la méthode.
jaxp-schema-support=La méthode setSchema et la propriété schemaLanguage sont utilisées
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_it.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_it.properties
index 29afb91340f90..879fcf5a866cf 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_it.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_it.properties
@@ -29,28 +29,28 @@
# The messages are arranged in key and value tuples in a ListResourceBundle.
BadMessageKey = Impossibile trovare il messaggio di errore corrispondente alla chiave di messaggio.
- FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n
+ FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n
# DOM Core
# exception codes
-DOMSTRING_SIZE_ERR = L'intervallo di testo specificato non si adatta in DOMString.
-HIERARCHY_REQUEST_ERR = Si è tentato di inserire un nodo in un punto in cui non è consentito.
+DOMSTRING_SIZE_ERR = L'intervallo di testo specificato non si adatta in DOMString.
+HIERARCHY_REQUEST_ERR = Si è tentato di inserire un nodo in un punto in cui non è consentito.
INDEX_SIZE_ERR = L'indice o la dimensione è negativa o maggiore del valore consentito.
INUSE_ATTRIBUTE_ERR = Si è tentato di aggiungere un attributo già in uso altrove.
-INVALID_ACCESS_ERR = Un parametro o un'operazione non è supportata dall'oggetto di base.
-INVALID_CHARACTER_ERR = È stato specificato un carattere XML non valido.
-INVALID_MODIFICATION_ERR = Si è tentato di modificare il tipo dell'oggetto di base.
-INVALID_STATE_ERR = Si è tentato di utilizzare un oggetto che non è o non è più utilizzabile.
+INVALID_ACCESS_ERR = Un parametro o un'operazione non è supportata dall'oggetto di base.
+INVALID_CHARACTER_ERR = È stato specificato un carattere XML non valido.
+INVALID_MODIFICATION_ERR = Si è tentato di modificare il tipo dell'oggetto di base.
+INVALID_STATE_ERR = Si è tentato di utilizzare un oggetto che non è o non è più utilizzabile.
NAMESPACE_ERR = Si è tentato di creare o modificare un oggetto in modo errato per quel che riguarda gli spazi di nomi.
NOT_FOUND_ERR = Si è tentato di fare riferimento a un nodo in un contesto in cui non esiste.
-NOT_SUPPORTED_ERR = L'implementazione non supporta il tipo richiesto di oggetto o operazione.
+NOT_SUPPORTED_ERR = L'implementazione non supporta il tipo richiesto di oggetto o operazione.
NO_DATA_ALLOWED_ERR = Sono stati specificati dati per un nodo che non supporta dati.
NO_MODIFICATION_ALLOWED_ERR = Si è tentato di modificare un oggetto non modificabile.
-SYNTAX_ERR = È stata specificata una stringa non valida.
+SYNTAX_ERR = È stata specificata una stringa non valida.
VALIDATION_ERR = Se si richiama un metodo come insertBefore o removeChild, il nodo non sarà valido per quel che riguarda la grammatica del documento.
WRONG_DOCUMENT_ERR = Un nodo è utilizzato in un documento diverso da quello che lo ha creato.
-TYPE_MISMATCH_ERR = Il tipo di valore per questo nome parametro non è compatibile con il tipo di valore previsto.
+TYPE_MISMATCH_ERR = Il tipo di valore per questo nome parametro non è compatibile con il tipo di valore previsto.
#error messages or exceptions
FEATURE_NOT_SUPPORTED = Il parametro {0} è stato riconosciuto, ma non è possibile impostare il valore richiesto.
@@ -85,7 +85,7 @@ INVALID_NODE_TYPE_ERR = Il contenitore di un punto limite di un intervallo è st
#Events
-UNSPECIFIED_EVENT_TYPE_ERR = Il tipo di evento non è stato specificato inizializzando l'evento prima che fosse richiamato il metodo.
+UNSPECIFIED_EVENT_TYPE_ERR = Il tipo di evento non è stato specificato inizializzando l'evento prima che fosse richiamato il metodo.
jaxp-schema-support=Sono stati utilizzati sia il metodo setSchema che la proprietà schemaLanguage
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties
index b358fc8a32487..a04e36923c3b4 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties
@@ -21,28 +21,28 @@
# The messages are arranged in key and value tuples in a ListResourceBundle.
BadMessageKey = メッセージ・キーに対応するエラー・メッセージが見つかりません。
- FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n
+ FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n
# DOM Core
# exception codes
-DOMSTRING_SIZE_ERR = 指定したテキスト範囲はDOMStringに収まりません。
-HIERARCHY_REQUEST_ERR = 許可されていない場所でノードを挿入しようとしました。
+DOMSTRING_SIZE_ERR = 指定したテキスト範囲はDOMStringに収まりません。
+HIERARCHY_REQUEST_ERR = 許可されていない場所でノードを挿入しようとしました。
INDEX_SIZE_ERR = 索引またはサイズが負か、許容値より大きくなっています。
INUSE_ATTRIBUTE_ERR = 他の場所ですでに使用されている属性を追加しようとしました。
-INVALID_ACCESS_ERR = 基礎となるオブジェクトでパラメータまたは操作がサポートされていません。
-INVALID_CHARACTER_ERR = 無効または不正なXML文字が指定されています。
-INVALID_MODIFICATION_ERR = 基礎となるオブジェクトのタイプを変更しようとしました。
-INVALID_STATE_ERR = 使用できないか、今後使用できなくなるオブジェクトを使用しようとしました。
+INVALID_ACCESS_ERR = 基礎となるオブジェクトでパラメータまたは操作がサポートされていません。
+INVALID_CHARACTER_ERR = 無効または不正なXML文字が指定されています。
+INVALID_MODIFICATION_ERR = 基礎となるオブジェクトのタイプを変更しようとしました。
+INVALID_STATE_ERR = 使用できないか、今後使用できなくなるオブジェクトを使用しようとしました。
NAMESPACE_ERR = ネームスペースに関して不適切な方法でオブジェクトを作成または変更しようとしました。
NOT_FOUND_ERR = コンテキストに存在しないノードを参照しようとしました。
-NOT_SUPPORTED_ERR = リクエストしたタイプのオブジェクトまたは操作は実装でサポートされていません。
+NOT_SUPPORTED_ERR = リクエストしたタイプのオブジェクトまたは操作は実装でサポートされていません。
NO_DATA_ALLOWED_ERR = データをサポートしていないノードに対してデータが指定されています。
NO_MODIFICATION_ALLOWED_ERR = 変更が許可されていないオブジェクトを変更しようとしました。
-SYNTAX_ERR = 無効または不正な文字列が指定されています。
+SYNTAX_ERR = 無効または不正な文字列が指定されています。
VALIDATION_ERR = insertBefore、removeChildなどのメソッドを呼び出すと、ドキュメントの構文に関してノードが無効になります。
WRONG_DOCUMENT_ERR = ノードが、そのノードを作成したものとは異なるドキュメントで使用されています。
-TYPE_MISMATCH_ERR = このパラメータ名の値タイプは、予想した値タイプと互換性がありません。
+TYPE_MISMATCH_ERR = このパラメータ名の値タイプは、予想した値タイプと互換性がありません。
#error messages or exceptions
FEATURE_NOT_SUPPORTED = パラメータ{0}は認識されますが、リクエストした値は設定できません。
@@ -77,7 +77,7 @@ INVALID_NODE_TYPE_ERR = Rangeの境界点のコンテナが、無効なタイプ
#Events
-UNSPECIFIED_EVENT_TYPE_ERR = メソッドを呼び出す前のイベントの初期化で、イベントのタイプが指定されませんでした。
+UNSPECIFIED_EVENT_TYPE_ERR = メソッドを呼び出す前のイベントの初期化で、イベントのタイプが指定されませんでした。
jaxp-schema-support=setSchemaメソッドおよびschemaLanguageプロパティの両方が使用されています
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ko.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ko.properties
index 3d56d383201ef..b702d09928449 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ko.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ko.properties
@@ -29,28 +29,28 @@
# The messages are arranged in key and value tuples in a ListResourceBundle.
BadMessageKey = 메시지 키에 해당하는 오류 메시지를 찾을 수 없습니다.
- FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n
+ FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n
# DOM Core
# exception codes
-DOMSTRING_SIZE_ERR = 텍스트의 지정된 범위가 DOMString에 맞지 않습니다.
-HIERARCHY_REQUEST_ERR = 삽입이 허용되지 않는 노드를 삽입하려고 시도했습니다.
+DOMSTRING_SIZE_ERR = 텍스트의 지정된 범위가 DOMString에 맞지 않습니다.
+HIERARCHY_REQUEST_ERR = 삽입이 허용되지 않는 노드를 삽입하려고 시도했습니다.
INDEX_SIZE_ERR = 인덱스 또는 크기가 음수이거나 허용되는 값보다 큽니다.
INUSE_ATTRIBUTE_ERR = 다른 위치에서 이미 사용 중인 속성을 추가하려고 시도했습니다.
-INVALID_ACCESS_ERR = 기본 객체에서 매개변수 또는 작업을 지원하지 않습니다.
-INVALID_CHARACTER_ERR = 부적합하거나 잘못된 XML 문자가 지정되었습니다.
-INVALID_MODIFICATION_ERR = 기본 객체의 유형을 수정하려고 시도했습니다.
-INVALID_STATE_ERR = 사용할 수 없거나 더 이상 사용이 허가되지 않은 객체를 사용하려고 시도했습니다.
+INVALID_ACCESS_ERR = 기본 객체에서 매개변수 또는 작업을 지원하지 않습니다.
+INVALID_CHARACTER_ERR = 부적합하거나 잘못된 XML 문자가 지정되었습니다.
+INVALID_MODIFICATION_ERR = 기본 객체의 유형을 수정하려고 시도했습니다.
+INVALID_STATE_ERR = 사용할 수 없거나 더 이상 사용이 허가되지 않은 객체를 사용하려고 시도했습니다.
NAMESPACE_ERR = 네임스페이스에 대해 올바르지 않은 방식으로 객체를 생성하거나 변경하려고 시도했습니다.
NOT_FOUND_ERR = 존재하지 않는 컨텍스트의 노드를 참조하려고 시도했습니다.
-NOT_SUPPORTED_ERR = 구현에서 요청된 유형의 객체 또는 작업을 지원하지 않습니다.
+NOT_SUPPORTED_ERR = 구현에서 요청된 유형의 객체 또는 작업을 지원하지 않습니다.
NO_DATA_ALLOWED_ERR = 데이터를 지원하지 않는 노드에 대해 데이터가 지정되었습니다.
NO_MODIFICATION_ALLOWED_ERR = 수정이 허용되지 않는 객체를 수정하려고 시도했습니다.
-SYNTAX_ERR = 부적합하거나 잘못된 문자열이 지정되었습니다.
+SYNTAX_ERR = 부적합하거나 잘못된 문자열이 지정되었습니다.
VALIDATION_ERR = insertBefore 또는 removeChild와 같은 메소드를 호출하면 노드가 문서 문법에 대해 부적합해집니다.
WRONG_DOCUMENT_ERR = 노드가 생성된 문서가 아닌 다른 문서에서 사용되었습니다.
-TYPE_MISMATCH_ERR = 이 매개변수 이름에 대한 값 유형이 필요한 값 유형과 호환되지 않습니다.
+TYPE_MISMATCH_ERR = 이 매개변수 이름에 대한 값 유형이 필요한 값 유형과 호환되지 않습니다.
#error messages or exceptions
FEATURE_NOT_SUPPORTED = {0} 매개변수가 인식되었지만 요청된 값을 설정할 수 없습니다.
@@ -85,7 +85,7 @@ INVALID_NODE_TYPE_ERR = 범위의 경계 지점 컨테이너가 부적합한 유
#Events
-UNSPECIFIED_EVENT_TYPE_ERR = 메소드가 호출되기 전에 이벤트를 초기화하여 이벤트 유형이 지정되지 않았습니다.
+UNSPECIFIED_EVENT_TYPE_ERR = 메소드가 호출되기 전에 이벤트를 초기화하여 이벤트 유형이 지정되지 않았습니다.
jaxp-schema-support=setSchema 메소드와 schemaLanguage 속성이 모두 사용되었습니다.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_pt_BR.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_pt_BR.properties
index 6ddb17e4e94da..f72410c4cfc66 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_pt_BR.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_pt_BR.properties
@@ -29,28 +29,28 @@
# The messages are arranged in key and value tuples in a ListResourceBundle.
BadMessageKey = Não foi possível encontrar a mensagem de erro correspondente à chave da mensagem.
- FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n
+ FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n
# DOM Core
# exception codes
-DOMSTRING_SIZE_ERR = A faixa de texto especificada não se ajusta a DOMString.
-HIERARCHY_REQUEST_ERR = Houve uma tentativa de inserir um nó onde não era permitido.
+DOMSTRING_SIZE_ERR = A faixa de texto especificada não se ajusta a DOMString.
+HIERARCHY_REQUEST_ERR = Houve uma tentativa de inserir um nó onde não era permitido.
INDEX_SIZE_ERR = O índice ou o tamanho é negativo ou maior que o valor permitido.
INUSE_ATTRIBUTE_ERR = Houve uma tentativa de adicionar um atributo que já está sendo usado em outro lugar.
-INVALID_ACCESS_ERR = Um parâmetro ou uma operação não suportado pelo objeto subjacente.
-INVALID_CHARACTER_ERR = Um caractere XML inválido ou ilegal foi especificado.
-INVALID_MODIFICATION_ERR = Houve uma tentativa de modificar o tipo de objeto subjacente.
-INVALID_STATE_ERR = Houve uma tentativa de usar um objeto que não é mais utilizável.
+INVALID_ACCESS_ERR = Um parâmetro ou uma operação não suportado pelo objeto subjacente.
+INVALID_CHARACTER_ERR = Um caractere XML inválido ou ilegal foi especificado.
+INVALID_MODIFICATION_ERR = Houve uma tentativa de modificar o tipo de objeto subjacente.
+INVALID_STATE_ERR = Houve uma tentativa de usar um objeto que não é mais utilizável.
NAMESPACE_ERR = Houve uma tentativa de criar ou alterar um objeto de uma forma incorreta em relação aos namespaces.
NOT_FOUND_ERR = Houve uma tentativa de fazer referência a um nó em um contexto no qual ele não existe.
-NOT_SUPPORTED_ERR = A implementação não suporta o tipo solicitado de objeto ou operação.
+NOT_SUPPORTED_ERR = A implementação não suporta o tipo solicitado de objeto ou operação.
NO_DATA_ALLOWED_ERR = Os dados foram especificados para um nó que não suporta dados.
NO_MODIFICATION_ALLOWED_ERR = Foi feita uma tentativa de modificar um objeto no qual não são permitidas modificações.
-SYNTAX_ERR = Uma string inválida ou ilegal foi especificada.
+SYNTAX_ERR = Uma string inválida ou ilegal foi especificada.
VALIDATION_ERR = Uma chamada para um método como insertBefore ou removeChild tornaria o Nó inválido em relação à gramática do documento.
WRONG_DOCUMENT_ERR = Um nó é usado em um documento diferente daquele que foi criado.
-TYPE_MISMATCH_ERR = O tipo de valor do nome deste parâmetro é incompatível com o tipo de valor esperado.
+TYPE_MISMATCH_ERR = O tipo de valor do nome deste parâmetro é incompatível com o tipo de valor esperado.
#error messages or exceptions
FEATURE_NOT_SUPPORTED = O parâmetro {0} é reconhecido, mas o valor solicitado não pode ser definido.
@@ -85,7 +85,7 @@ INVALID_NODE_TYPE_ERR = O container de um ponto-limite de uma Faixa está sendo
#Events
-UNSPECIFIED_EVENT_TYPE_ERR = O tipo de Evento não foi especificado por meio da inicialização do evento antes do método ser chamado.
+UNSPECIFIED_EVENT_TYPE_ERR = O tipo de Evento não foi especificado por meio da inicialização do evento antes do método ser chamado.
jaxp-schema-support=O método setSchema e a propriedade schemaLanguage foram usados
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_sv.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_sv.properties
index c4e3e4238f732..eb03257c11992 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_sv.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_sv.properties
@@ -29,28 +29,28 @@
# The messages are arranged in key and value tuples in a ListResourceBundle.
BadMessageKey = Hittar inte felmeddelandet som motsvarar meddelandenyckeln.
- FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n
+ FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n
# DOM Core
# exception codes
-DOMSTRING_SIZE_ERR = Angivet textintervall ryms inte i DOMString.
-HIERARCHY_REQUEST_ERR = Ett försök gjordes att infoga nod där det inte är tillåtet.
+DOMSTRING_SIZE_ERR = Angivet textintervall ryms inte i DOMString.
+HIERARCHY_REQUEST_ERR = Ett försök gjordes att infoga nod där det inte är tillåtet.
INDEX_SIZE_ERR = Index eller storlek är negativt tal eller större än tillåtet värde.
INUSE_ATTRIBUTE_ERR = Ett försök görs att lägga till ett attribut som redan används på annan plats.
-INVALID_ACCESS_ERR = En parameter eller en åtgärd stöds inte av underliggande objekt.
-INVALID_CHARACTER_ERR = Ett ogiltigt eller otillåtet XML-tecken har angetts.
-INVALID_MODIFICATION_ERR = Ett försök görs att ändra typ av underliggande objekt.
-INVALID_STATE_ERR = Ett försök görs att använda ett objekt som inte (längre) är användbar.
+INVALID_ACCESS_ERR = En parameter eller en åtgärd stöds inte av underliggande objekt.
+INVALID_CHARACTER_ERR = Ett ogiltigt eller otillåtet XML-tecken har angetts.
+INVALID_MODIFICATION_ERR = Ett försök görs att ändra typ av underliggande objekt.
+INVALID_STATE_ERR = Ett försök görs att använda ett objekt som inte (längre) är användbar.
NAMESPACE_ERR = Ett försök görs att skapa eller ändra ett objekt på ett felaktigt sätt avseende namnrymder.
NOT_FOUND_ERR = Ett försök görs att skapa referens till en nod i ett sammanhang där den inte finns.
-NOT_SUPPORTED_ERR = Implementeringen saknar stöd för begärd typ av objekt eller åtgärd.
+NOT_SUPPORTED_ERR = Implementeringen saknar stöd för begärd typ av objekt eller åtgärd.
NO_DATA_ALLOWED_ERR = Data anges för en nod som inte stöder data.
NO_MODIFICATION_ALLOWED_ERR = Försöker ändra ett objekt där ändringar inte är tillåtna.
-SYNTAX_ERR = En ogiltig eller otillåten sträng anges.
+SYNTAX_ERR = En ogiltig eller otillåten sträng anges.
VALIDATION_ERR = Ett anrop till en metod som insertBefore eller removeChild skulle göra noden ogiltig med aktuell dokumentgrammatik.
WRONG_DOCUMENT_ERR = En nod används i ett annat dokument än det som skapade noden.
-TYPE_MISMATCH_ERR = Värdetypen för detta parameternamn är inkompatibelt med förväntad värdetyp.
+TYPE_MISMATCH_ERR = Värdetypen för detta parameternamn är inkompatibelt med förväntad värdetyp.
#error messages or exceptions
FEATURE_NOT_SUPPORTED = Parametern {0} kan identifieras, men det begärda värdet kan inte anges.
@@ -85,7 +85,7 @@ INVALID_NODE_TYPE_ERR = En container med gränspunktsintervall anges till nod av
#Events
-UNSPECIFIED_EVENT_TYPE_ERR = Händelsetyp specificerades inte när händelsen initierades före metodanrop.
+UNSPECIFIED_EVENT_TYPE_ERR = Händelsetyp specificerades inte när händelsen initierades före metodanrop.
jaxp-schema-support=Både setSchema-metoden och schemaLanguage-egenskapen används
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties
index dac97e7fe406b..dcf11c533e264 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties
@@ -21,7 +21,7 @@
# The messages are arranged in key and value tuples in a ListResourceBundle.
BadMessageKey = 找不到与消息关键字对应的错误消息。
- FormatFailed = 设置以下消息的格式时出现内部错误:\n
+ FormatFailed = 设置以下消息的格式时出现内部错误:\n
# DOM Core
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages.properties
index 01ca9e977fe3c..4d475edea5203 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages.properties
@@ -26,7 +26,7 @@ FormatFailed = An internal error occurred while formatting the following message
# JAXP messages
schema-not-supported = The specified schema language is not supported.
-jaxp-order-not-supported = Property ''{0}'' must be set before setting property ''{1}''.
+jaxp-order-not-supported = Property ''{0}'' must be set before setting property ''{1}''.
schema-already-specified = Property ''{0}'' cannot be set when a non-null Schema object has already been specified.
# feature messages
@@ -48,4 +48,4 @@ incompatible-class = The value specified for property ''{0}'' cannot be casted t
start-document-not-called=Property "{0}" should be called after startDocument event is thrown
nullparameter=the name parameter for "{0}" is null
errorHandlerNotSet=Warning\: validation was turned on but an org.xml.sax.ErrorHandler was not set, which is probably not what is desired. Parser will use a default ErrorHandler to print the first {0} errors. Please call the 'setErrorHandler' method to fix this.
-errorHandlerDebugMsg=Error\: URI \= "{0}", Line \= "{1}", \: {2}
+errorHandlerDebugMsg=Error\: URI \= "{0}", Line \= "{1}", \: {2}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties
index 9196318a4182b..877150e9793de 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties
@@ -26,7 +26,7 @@ FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler au
# JAXP messages
schema-not-supported = Die angegebene Schemasprache wird nicht unterstützt.
-jaxp-order-not-supported = Eigenschaft "{0}" muss vor der Eigenschaft "{1}" festgelegt werden.
+jaxp-order-not-supported = Eigenschaft "{0}" muss vor der Eigenschaft "{1}" festgelegt werden.
schema-already-specified = Eigenschaft "{0}" kann nicht festgelegt werden, wenn bereits ein Schemaobjekt ungleich null angegeben wurde.
# feature messages
@@ -48,4 +48,4 @@ incompatible-class = Der für Eigenschaft "{0}" angegebene Wert kann nicht in {1
start-document-not-called=Eigenschaft "{0}" sollte aufgerufen werden, nachdem das startDocument-Ereignis ausgelöst wurde
nullparameter=Namensparameter für "{0}" ist null
errorHandlerNotSet=Warnung: Validierung wurde eingeschaltet, aber es wurde kein org.xml.sax.ErrorHandler festgelegt. Dies ist wahrscheinlich nicht beabsichtigt. Parser druckt die ersten {0} Fehler mit einem Standard-ErrorHandler. Rufen Sie die Methode "setErrorHandler" auf, um dies zu beheben.
-errorHandlerDebugMsg=Fehler: URI = "{0}", Zeile = "{1}", : {2}
+errorHandlerDebugMsg=Fehler: URI = "{0}", Zeile = "{1}", : {2}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_es.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_es.properties
index fa89d4adeaad1..04612301ad98e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_es.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_es.properties
@@ -34,7 +34,7 @@ FormatFailed = Se ha producido un error interno al formatear el siguiente mensaj
# JAXP messages
schema-not-supported = El idioma del esquema especificado no está soportado.
-jaxp-order-not-supported = La propiedad ''{0}'' debe definirse antes de definir la propiedad ''{1}''.
+jaxp-order-not-supported = La propiedad ''{0}'' debe definirse antes de definir la propiedad ''{1}''.
schema-already-specified = La propiedad ''{0}'' no puede definirse cuando un objeto de esquema no nulo ya se haya especificado.
# feature messages
@@ -56,4 +56,4 @@ incompatible-class = El valor especificado para la propiedad ''{0}'' no se puede
start-document-not-called=La propiedad "{0}" debe llamarse después de que se haya devuelto el evento startDocument
nullparameter=el parámetro de nombre para "{0}" es nulo
errorHandlerNotSet=Advertencia: se activó la validación pero no se definió un org.xml.sax.ErrorHandler, lo cual probablemente sea un resultado no deseado. El analizador utilizará un ErrorHandler por defecto para imprimir los primeros {0} errores. Llame al método ''setErrorHandler'' para solucionarlo.
-errorHandlerDebugMsg=Error: URI = "{0}", Línea = "{1}", : {2}
+errorHandlerDebugMsg=Error: URI = "{0}", Línea = "{1}", : {2}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_fr.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_fr.properties
index 1f0e371e45f04..65067a9e85788 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_fr.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_fr.properties
@@ -34,7 +34,7 @@ FormatFailed = Une erreur interne est survenue lors du formatage du message suiv
# JAXP messages
schema-not-supported = La langue de schéma indiquée n'est pas prise en charge.
-jaxp-order-not-supported = La propriété ''{0}'' doit être définie avant la propriété ''{1}''.
+jaxp-order-not-supported = La propriété ''{0}'' doit être définie avant la propriété ''{1}''.
schema-already-specified = La propriété ''{0}'' ne peut pas être définie lorsqu''un objet de schéma non NULL a déjà été indiqué.
# feature messages
@@ -56,4 +56,4 @@ incompatible-class = La valeur indiquée pour la propriété ''{0}'' ne peut pas
start-document-not-called=La propriété "{0}" doit être appelée après qu''un événement startDocument est généré
nullparameter=le paramètre de nom pour "{0}" est NULL
errorHandlerNotSet=Avertissement : la validation a été activée mais aucun élément org.xml.sax.ErrorHandler n''a été défini, ce qui devrait probablement être le cas. L''analyseur utilisera un gestionnaire d''erreurs par défaut pour imprimer les {0} premières erreurs. Appelez la méthode ''setErrorHandler'' pour résoudre ce problème.
-errorHandlerDebugMsg=Erreur : URI = "{0}", ligne = "{1}", : {2}
+errorHandlerDebugMsg=Erreur : URI = "{0}", ligne = "{1}", : {2}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_it.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_it.properties
index ea999e0171b10..10dbcb494dda7 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_it.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_it.properties
@@ -34,7 +34,7 @@ FormatFailed = Si è verificato un errore interno durante la formattazione del s
# JAXP messages
schema-not-supported = La lingua dello schema specificata non è supportata.
-jaxp-order-not-supported = Impostare la proprietà ''{0}'' prima di impostare la proprietà ''{1}''.
+jaxp-order-not-supported = Impostare la proprietà ''{0}'' prima di impostare la proprietà ''{1}''.
schema-already-specified = Impossibile impostare la proprietà ''{0}'' se è già stato specificato un oggetto di schema non nullo.
# feature messages
@@ -56,4 +56,4 @@ incompatible-class = Impossibile eseguire la conversione cast del valore specifi
start-document-not-called=Richiamare la proprietà "{0}" dopo l''esecuzione dell''evento startDocument
nullparameter=il parametro del nome per "{0}" è nullo
errorHandlerNotSet=Avvertenza: la convalida è stata attivata, ma org.xml.sax.ErrorHandler non è stato impostato, il che potrebbe essere un errore. Il parser utilizzerà un ErrorHandler predefinito per visualizzare i primi {0} errori. Richiamare il metodo ''setErrorHandler'' per correggere questo problema.
-errorHandlerDebugMsg=Errore: URI = "{0}", riga = "{1}", : {2}
+errorHandlerDebugMsg=Errore: URI = "{0}", riga = "{1}", : {2}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties
index ed8af93692c17..27201b883f955 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties
@@ -26,7 +26,7 @@ FormatFailed = 次のメッセージの書式設定中に内部エラーが発
# JAXP messages
schema-not-supported = 指定したスキーマ言語はサポートされていません。
-jaxp-order-not-supported = プロパティ''{1}''を設定する前にプロパティ''{0}''を設定する必要があります。
+jaxp-order-not-supported = プロパティ''{1}''を設定する前にプロパティ''{0}''を設定する必要があります。
schema-already-specified = null以外のスキーマ・オブジェクトがすでに指定されている場合、プロパティ''{0}''は設定できません。
# feature messages
@@ -48,4 +48,4 @@ incompatible-class = プロパティ''{0}''に指定した値は{1}にキャス
start-document-not-called=startDocumentイベントがスローされた後、プロパティ"{0}"を呼び出す必要があります
nullparameter="{0}"の名前パラメータがnullです
errorHandlerNotSet=警告: 検証はオンになっていますが、org.xml.sax.ErrorHandlerが設定されていません。必要とされているハンドラはこのハンドラではない可能性があります。パーサーでは、デフォルトのErrorHandlerを使用して最初の{0}エラーが出力されます。この問題を修正するには、''setErrorHandler''メソッドを呼び出してください。
-errorHandlerDebugMsg=エラー: URI = "{0}"、行 = "{1}"、: {2}
+errorHandlerDebugMsg=エラー: URI = "{0}"、行 = "{1}"、: {2}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ko.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ko.properties
index 5b9e80a351f0d..7f5078f6d26e5 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ko.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ko.properties
@@ -34,7 +34,7 @@ FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가
# JAXP messages
schema-not-supported = 지정된 스키마 언어는 지원되지 않습니다.
-jaxp-order-not-supported = ''{1}'' 속성을 설정하기 전에 ''{0}'' 속성을 설정해야 합니다.
+jaxp-order-not-supported = ''{1}'' 속성을 설정하기 전에 ''{0}'' 속성을 설정해야 합니다.
schema-already-specified = 널이 아닌 스키마 객체가 이미 지정된 경우 ''{0}'' 속성을 설정할 수 없습니다.
# feature messages
@@ -56,4 +56,4 @@ incompatible-class = ''{0}'' 속성에 대해 지정된 값의 데이터형을 {
start-document-not-called="{0}" 속성은 startDocument 이벤트가 발생된 후 호출해야 합니다.
nullparameter="{0}"에 대한 이름 매개변수가 널입니다.
errorHandlerNotSet=경고: 검증이 설정되었지만 org.xml.sax.ErrorHandler가 적절히 설정되지 않았습니다. 구문 분석기가 기본 ErrorHandler를 사용하여 처음 {0}개의 오류를 인쇄합니다. 이 오류를 수정하려면 ''setErrorHandler'' 메소드를 호출하십시오.
-errorHandlerDebugMsg=오류: URI = "{0}", 행 = "{1}", : {2}
+errorHandlerDebugMsg=오류: URI = "{0}", 행 = "{1}", : {2}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_pt_BR.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_pt_BR.properties
index b60b2f5e5530f..7aab380d73980 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_pt_BR.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_pt_BR.properties
@@ -34,7 +34,7 @@ FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n
# JAXP messages
schema-not-supported = O idioma do esquema especificado não é suportado.
-jaxp-order-not-supported = A propriedade ''{0}'' deve ser definida antes da definição da propriedade ''{1}''.
+jaxp-order-not-supported = A propriedade ''{0}'' deve ser definida antes da definição da propriedade ''{1}''.
schema-already-specified = A propriedade ''{0}'' não pode ser definida quando um objeto do Esquema não nulo já tiver sido especificado.
# feature messages
@@ -56,4 +56,4 @@ incompatible-class = O valor especificado para a propriedade ''{0}'' não pode s
start-document-not-called=A propriedade "{0}" deve ser chamada após o evento startDocument ser lançado
nullparameter=o parâmetro de nome de "{0}" é nulo
errorHandlerNotSet=Advertência: A validação foi ativada, mas um org.xml.sax.ErrorHandler não foi definido, provavelmente porque não era necessário. O parser usará um ErrorHandler padrão para imprimir os primeiros {0} erros. Chame o método ''setErrorHandler'' para corrigir o problema.
-errorHandlerDebugMsg=Erro: URI = "{0}", Linha = "{1}", : {2}
+errorHandlerDebugMsg=Erro: URI = "{0}", Linha = "{1}", : {2}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_sv.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_sv.properties
index cdd56145d37d6..847074319d7e4 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_sv.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_sv.properties
@@ -34,7 +34,7 @@ FormatFailed = Ett internt fel inträffade vid formatering av följande meddelan
# JAXP messages
schema-not-supported = Angivet schemaspråk stöds inte.
-jaxp-order-not-supported = Egenskapen ''{0}'' måste anges före inställning av egenskapen ''{1}''.
+jaxp-order-not-supported = Egenskapen ''{0}'' måste anges före inställning av egenskapen ''{1}''.
schema-already-specified = Egenskapen ''{0}'' kan inte anges om ett Schema-objekt som är icke-null redan har angetts.
# feature messages
@@ -56,4 +56,4 @@ incompatible-class = Värdet angivet för egenskapen ''{0}'' kan inte omvandlas
start-document-not-called=Egenskapen "{0}" bör anropas efter startDocument-händelsen utlöses
nullparameter=namnparametern för "{0}" är null
errorHandlerNotSet=Varning: valideringen startades, men det fanns ingen angiven org.xml.sax.ErrorHandler. Parser använder ErrorHandler av standardtyp vid utskrift av de första {0} felen. Korrigera felet genom anrop av setErrorHandler-metoden.
-errorHandlerDebugMsg=Fel: URI = "{0}", Rad = "{1}", : {2}
+errorHandlerDebugMsg=Fel: URI = "{0}", Rad = "{1}", : {2}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties
index 617839234d5ed..5657e071bd470 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties
@@ -48,4 +48,4 @@ incompatible-class = 为属性 ''{0}'' 指定的值不能转换为{1}。
start-document-not-called=应在抛出 startDocument 事件后调用属性 "{0}"
nullparameter="{0}" 的名称参数为空值
errorHandlerNotSet=警告: 已启用验证, 但未设置 org.xml.sax.ErrorHandler, 这可能不是预期结果。解析器将使用默认 ErrorHandler 来输出前 {0} 个错误。请调用 ''setErrorHandler'' 方法以解决此问题。
-errorHandlerDebugMsg=错误: URI = "{0}", 行 = "{1}", : {2}
+errorHandlerDebugMsg=错误: URI = "{0}", 行 = "{1}", : {2}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_TW.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_TW.properties
index e98bda31111de..7c513b7341301 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_TW.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_TW.properties
@@ -56,4 +56,4 @@ incompatible-class = 為屬性 ''{0}'' 指定的值不可轉換為 {1}。
start-document-not-called=發生 startDocument 事件之後,應呼叫屬性 "{0}"。
nullparameter="{0}" 的名稱參數為空值
errorHandlerNotSet=警告: 已開啟驗證,但是未設定 org.xml.sax.ErrorHandler,這可能不是所要的狀態。剖析器將使用預設的 ErrorHandler 來列印第一個 {0} 錯誤。請呼叫 ''setErrorHandler'' 方法來修正此問題。
-errorHandlerDebugMsg=錯誤: URI = "{0}",行 = "{1}",: {2}
+errorHandlerDebugMsg=錯誤: URI = "{0}",行 = "{1}",: {2}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages.properties
index ae6e486f79d76..9b037ac8d9ff5 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages.properties
@@ -17,7 +17,7 @@
# Messages for message reporting
BadMessageKey = The error message corresponding to the message key can not be found.
-FormatFailed = An internal error occurred while formatting the following message:\n
+FormatFailed = An internal error occurred while formatting the following message:\n
# Messages for erroneous input
NoFallback = An 'include' with href ''{0}''failed, and no 'fallback' element was found.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties
index 90ae689b94974..22e552e8b1eca 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties
@@ -17,7 +17,7 @@
# Messages for message reporting
BadMessageKey = Die zum Meldungsschlüssel gehörige Fehlermeldung kann nicht gefunden werden.
-FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n
+FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n
# Messages for erroneous input
NoFallback = "include" mit href "{0}" nicht erfolgreich, und es wurde kein "fallback"-Element gefunden.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_es.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_es.properties
index 73267cde35550..0e12106d26b04 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_es.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_es.properties
@@ -25,7 +25,7 @@
# Messages for message reporting
BadMessageKey = No se ha encontrado el mensaje de error correspondiente a la clave de mensaje.
-FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n
+FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n
# Messages for erroneous input
NoFallback = Ha fallado un elemento ''include'' con href ''{0}'' y no se ha encontrado ningún elemento ''fallback''.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_fr.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_fr.properties
index 1057584d33bee..556ab78c3e8c9 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_fr.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_fr.properties
@@ -25,7 +25,7 @@
# Messages for message reporting
BadMessageKey = Le message d'erreur correspondant à la clé de message est introuvable.
-FormatFailed = Une erreur interne est survenue lors du formatage du message suivant :\n
+FormatFailed = Une erreur interne est survenue lors du formatage du message suivant :\n
# Messages for erroneous input
NoFallback = Echec d''un élément ''include'' avec l''attribut href ''{0}'' ; aucun élément ''fallback'' n''a été trouvé.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_it.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_it.properties
index de42b2936a931..4fbd4e2dbb3ac 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_it.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_it.properties
@@ -25,7 +25,7 @@
# Messages for message reporting
BadMessageKey = Impossibile trovare il messaggio di errore corrispondente alla chiave di messaggio.
-FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n
+FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n
# Messages for erroneous input
NoFallback = Errore dell''elemento ''include'' con href ''{0}''. Non è stato trovato alcune elemento ''fallback''.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties
index f9d95d50ec440..3bde121bf5b0b 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties
@@ -17,7 +17,7 @@
# Messages for message reporting
BadMessageKey = メッセージ・キーに対応するエラー・メッセージが見つかりません。
-FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n
+FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n
# Messages for erroneous input
NoFallback = href ''{0}''を含む''include''が失敗し、''fallback''要素が見つかりませんでした。
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ko.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ko.properties
index ea4863bd912e5..a9aeadb7891f7 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ko.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ko.properties
@@ -25,7 +25,7 @@
# Messages for message reporting
BadMessageKey = 메시지 키에 해당하는 오류 메시지를 찾을 수 없습니다.
-FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n
+FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n
# Messages for erroneous input
NoFallback = href ''{0}''을(를) 사용한 ''include''를 실패했으며 ''fallback'' 요소를 찾을 수 없습니다.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_pt_BR.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_pt_BR.properties
index dcf3c0ddafb49..d3819a3c64e7d 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_pt_BR.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_pt_BR.properties
@@ -25,7 +25,7 @@
# Messages for message reporting
BadMessageKey = Não foi possível encontrar a mensagem de erro correspondente à chave da mensagem.
-FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n
+FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n
# Messages for erroneous input
NoFallback = Falha em um ''include'' com href ''{0}'' e não foi encontrado elemento ''fallback''.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_sv.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_sv.properties
index 6dcef94cca6ff..e51be5c17ab47 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_sv.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_sv.properties
@@ -25,7 +25,7 @@
# Messages for message reporting
BadMessageKey = Hittar inte felmeddelandet som motsvarar meddelandenyckeln.
-FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n
+FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n
# Messages for erroneous input
NoFallback = Ett ''include'' med href ''{0}'' utfördes inte, hittade inget återskapningselement (''fallback'').
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties
index 0efe76a5df5de..b8648ce6baef3 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties
@@ -17,7 +17,7 @@
# Messages for message reporting
BadMessageKey = 找不到与消息关键字对应的错误消息。
-FormatFailed = 设置以下消息的格式时出现内部错误:\n
+FormatFailed = 设置以下消息的格式时出现内部错误:\n
# Messages for erroneous input
NoFallback = 带有 href ''{0}'' 的 ''include'' 失败, 并且找不到 ''fallback'' 元素。
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties
index 6e106bd532bfd..78a34631d0b3d 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages.properties
@@ -24,7 +24,7 @@
# @version
BadMessageKey = The error message corresponding to the message key can not be found.
- FormatFailed = An internal error occurred while formatting the following message:\n
+ FormatFailed = An internal error occurred while formatting the following message:\n
# Document messages
PrematureEOF=Premature end of file.
@@ -131,7 +131,7 @@
EncodingDeclRequired = The encoding declaration is required in the text declaration.
NoMorePseudoAttributes = No more pseudo attributes are allowed.
MorePseudoAttributes = More pseudo attributes are expected.
- PseudoAttrNameExpected = A pseudo attribute name is expected.
+ PseudoAttrNameExpected = A pseudo attribute name is expected.
# 4.3.2 Well-Formed Parsed Entities
CommentNotInOneEntity = The comment must be entirely contained within the same parsed entity.
PINotInOneEntity = The processing instruction must be entirely contained within the same parsed entity.
@@ -139,7 +139,7 @@
EncodingDeclInvalid = Invalid encoding name \"{0}\".
EncodingByteOrderUnsupported = Given byte order for encoding \"{0}\" is not supported.
InvalidByte = Invalid byte {0} of {1}-byte UTF-8 sequence.
- ExpectedByte = Expected byte {0} of {1}-byte UTF-8 sequence.
+ ExpectedByte = Expected byte {0} of {1}-byte UTF-8 sequence.
InvalidHighSurrogate = High surrogate bits in UTF-8 sequence must not exceed 0x10 but found 0x{0}.
OperationNotSupported = Operation \"{0}\" not supported by {1} reader.
InvalidASCII = Byte \"{0}\" is not a member of the (7-bit) ASCII character set.
@@ -219,7 +219,7 @@
MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = White space is required before \"NDATA\" in the declaration for the entity \"{0}\".
MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = The notation name is required after \"NDATA\" in the declaration for the entity \"{0}\".
EntityDeclUnterminated = The declaration for the entity \"{0}\" must end with ''>''.
- MSG_DUPLICATE_ENTITY_DEFINITION = Entity \"{0}\" is declared more than once.
+ MSG_DUPLICATE_ENTITY_DEFINITION = Entity \"{0}\" is declared more than once.
# 4.2.2 External Entities
ExternalIDRequired = The external entity declaration must begin with either \"SYSTEM\" or \"PUBLIC\".
MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = White space is required between \"PUBLIC\" and the public identifier.
@@ -275,7 +275,7 @@
RootElementTypeMustMatchDoctypedecl = Document root element \"{1}\", must match DOCTYPE root \"{0}\".
UndeclaredElementInContentSpec = The content model of element \"{0}\" refers to the undeclared element \"{1}\".
UniqueNotationName = The declaration for the notation \"{0}\" is not unique. A given Name must not be declared in more than one notation declaration.
- ENTITYFailedInitializeGrammar = ENTITYDatatype Validator: Failed Need to call initialize method with a valid Grammar reference.
+ ENTITYFailedInitializeGrammar = ENTITYDatatype Validator: Failed Need to call initialize method with a valid Grammar reference.
ENTITYNotUnparsed = ENTITY \"{0}\" is not unparsed.
ENTITYNotValid = ENTITY \"{0}\" is not valid.
EmptyList = Value of type ENTITIES, IDREFS, and NMTOKENS cannot be empty list.
@@ -330,4 +330,3 @@
# Implementation Property DTD
JDK_DTD_DENY = JAXP00010008: DOCTYPE is disallowed when the DTD property is set to deny. \
Refer to: property jdk.xml.dtd.support in java.xml/module-summary.
-
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties
index 7407d4da3e09c..9227a61a60852 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties
@@ -24,7 +24,7 @@
# @version
BadMessageKey = Die zum Meldungsschlüssel gehörige Fehlermeldung kann nicht gefunden werden.
- FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n
+ FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n
# Document messages
PrematureEOF=Vorzeitiges Dateiende.
@@ -131,7 +131,7 @@
EncodingDeclRequired = Codierungsdeklaration ist in der Textdeklaration erforderlich.
NoMorePseudoAttributes = Es sind keine weiteren Pseudoattribute zulässig.
MorePseudoAttributes = Es werden weitere Pseudoattribute erwartet.
- PseudoAttrNameExpected = Pseudoattributname wird erwartet.
+ PseudoAttrNameExpected = Pseudoattributname wird erwartet.
# 4.3.2 Well-Formed Parsed Entities
CommentNotInOneEntity = Kommentar muss vollständig in derselben geparsten Entity enthalten sein.
PINotInOneEntity = Verarbeitungsanweisung muss vollständig in derselben geparsten Entity enthalten sein.
@@ -139,7 +139,7 @@
EncodingDeclInvalid = Ungültiger Codierungsname "{0}".
EncodingByteOrderUnsupported = Angegebene Bytereihenfolge für die Codierung von "{0}" wird nicht unterstützt.
InvalidByte = Ungültiges Byte {0} von {1}-Byte-UTF-8-Sequenz.
- ExpectedByte = Byte {0} von {1}-Byte-UTF-8-Sequenz erwartet.
+ ExpectedByte = Byte {0} von {1}-Byte-UTF-8-Sequenz erwartet.
InvalidHighSurrogate = High-Surrogate-Bits in UTF-8-Sequenz dürfen 0x10 nicht überschreiten, gefunden wurde aber 0x{0}.
OperationNotSupported = Vorgang "{0}" nicht unterstützt von {1}-Reader.
InvalidASCII = Byte "{0}" gehört nicht zum (7-Bit) ASCII-Zeichensatz.
@@ -219,7 +219,7 @@
MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = Leerstelle vor "NDATA" in der Deklaration für die Entity "{0} erforderlich.
MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = Notationsname ist nach "NDATA" in der Deklaration für die Entity "{0} erforderlich.
EntityDeclUnterminated = Deklaration für Entity "{0}" muss mit ">" enden.
- MSG_DUPLICATE_ENTITY_DEFINITION = Entity "{0}" wurde mehrmals deklariert.
+ MSG_DUPLICATE_ENTITY_DEFINITION = Entity "{0}" wurde mehrmals deklariert.
# 4.2.2 External Entities
ExternalIDRequired = Externe Entitydeklaration muss mit "SYSTEM" oder "PUBLIC" beginnen.
MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = Leerstelle zwischen "PUBLIC" und der öffentlichen ID erforderlich.
@@ -329,4 +329,3 @@
# Implementation Property DTD
JDK_DTD_DENY = JAXP00010008: DOCTYPE ist nicht zulässig, wenn die DTD-Eigenschaft auf Ablehnen gesetzt wurde. Weitere Informationen: Eigenschaft jdk.xml.dtd.support in java.xml/module-summary.
-
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties
index 9639bf0b5647a..f20c7db51646d 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_es.properties
@@ -4,7 +4,7 @@
# @version
BadMessageKey = No se ha encontrado el mensaje de error correspondiente a la clave de mensaje.
- FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n
+ FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n
# Document messages
PrematureEOF=Final de archivo prematuro.
@@ -111,7 +111,7 @@
EncodingDeclRequired = La declaración de codificación es necesaria en la declaración de texto.
NoMorePseudoAttributes = No se permiten más pseudo atributos.
MorePseudoAttributes = Se esperan más pseudo atributos.
- PseudoAttrNameExpected = Se espera el nombre de un pseudo atributo.
+ PseudoAttrNameExpected = Se espera el nombre de un pseudo atributo.
# 4.3.2 Well-Formed Parsed Entities
CommentNotInOneEntity = El comentario debe incluirse totalmente en la misma entidad analizada.
PINotInOneEntity = La instrucción de procesamiento debe incluirse totalmente en la misma entidad analizada.
@@ -119,7 +119,7 @@
EncodingDeclInvalid = Nombre de codificación no válido "{0}".
EncodingByteOrderUnsupported = El orden de bytes proporcionado para la codificación "{0}" no está soportado.
InvalidByte = Byte no válido {0} de la secuencia UTF-8 de {1} bytes
- ExpectedByte = Byte esperado {0} de la secuencia UTF-8 de {1} bytes.
+ ExpectedByte = Byte esperado {0} de la secuencia UTF-8 de {1} bytes.
InvalidHighSurrogate = Los bits de sustitución superior en la secuencia UTF-8 no deben exceder 0x10 pero se han encontrado 0x{0}.
OperationNotSupported = La operación "{0}" no está soportada por el lector {1}.
InvalidASCII = El byte "{0}"no es un miembro del juego de caracteres ASCII (7 bits).
@@ -199,7 +199,7 @@
MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = Es necesario un espacio en blanco antes de "NDATA" en la declaración para la entidad "{0}".
MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = El nombre de notación es necesario después de "NDATA" en la declaración para la entidad "{0}".
EntityDeclUnterminated = La declaración para la entidad "{0}" debe finalizar en ''>''.
- MSG_DUPLICATE_ENTITY_DEFINITION = La entidad "{0}" se ha declarado más de una vez.
+ MSG_DUPLICATE_ENTITY_DEFINITION = La entidad "{0}" se ha declarado más de una vez.
# 4.2.2 External Entities
ExternalIDRequired = La declaración de entidad externa debe empezar por "SYSTEM" o "PUBLIC".
MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = Es necesario un espacio en blanco entre "PUBLIC" y el identificador público.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties
index 4300c2f7e4562..a47daba87f00c 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_fr.properties
@@ -4,7 +4,7 @@
# @version
BadMessageKey = Le message d'erreur correspondant à la clé de message est introuvable.
- FormatFailed = Une erreur interne s'est produite pendant la mise en forme du message suivant :\n
+ FormatFailed = Une erreur interne s'est produite pendant la mise en forme du message suivant :\n
# Document messages
PrematureEOF=Fin prématurée du fichier.
@@ -111,7 +111,7 @@
EncodingDeclRequired = La déclaration d'encodage est obligatoire dans la déclaration textuelle.
NoMorePseudoAttributes = Aucun autre pseudo-attribut n'est autorisé.
MorePseudoAttributes = D'autres pseudo-attributs sont attendus.
- PseudoAttrNameExpected = Un nom de pseudo-attribut est attendu.
+ PseudoAttrNameExpected = Un nom de pseudo-attribut est attendu.
# 4.3.2 Well-Formed Parsed Entities
CommentNotInOneEntity = Le commentaire doit être entièrement inclus dans la même entité analysée.
PINotInOneEntity = L'instruction de traitement doit être entièrement incluse dans la même entité analysée.
@@ -119,7 +119,7 @@
EncodingDeclInvalid = Nom d''encodage "{0}" non valide.
EncodingByteOrderUnsupported = L''ordre des octets donné pour encoder "{0}" n''est pas pris en charge.
InvalidByte = Octet {0} de la séquence UTF-8 à {1} octets non valide.
- ExpectedByte = Octet {0} de la séquence UTF-8 à {1} octets attendu.
+ ExpectedByte = Octet {0} de la séquence UTF-8 à {1} octets attendu.
InvalidHighSurrogate = Les bits de substitution supérieurs (High surrogate) dans la séquence UTF-8 ne doivent pas dépasser 0x10 mais des bits 0x{0} ont été détectés.
OperationNotSupported = Opération "{0}" non prise en charge par le lecteur {1}.
InvalidASCII = L''octet "{0}" n''appartient pas au jeu de caractères ASCII (7 bits).
@@ -199,7 +199,7 @@
MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = Un espace est obligatoire avant "NDATA" dans la déclaration de l''entité "{0}".
MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = Le nom de notation est obligatoire après "NDATA" dans la déclaration de l''entité "{0}".
EntityDeclUnterminated = La déclaration de l''entité "{0}" doit se terminer par ''>''.
- MSG_DUPLICATE_ENTITY_DEFINITION = L''entité "{0}" est déclarée plusieurs fois.
+ MSG_DUPLICATE_ENTITY_DEFINITION = L''entité "{0}" est déclarée plusieurs fois.
# 4.2.2 External Entities
ExternalIDRequired = La déclaration d'entité externe doit commencer par "SYSTEM" ou "PUBLIC".
MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = Un espace est obligatoire entre "PUBLIC" et l'identificateur public.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties
index 0ec786a1bbb15..7af820eb7c097 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_it.properties
@@ -4,7 +4,7 @@
# @version
BadMessageKey = Impossibile trovare il messaggio di errore corrispondente alla chiave di messaggio.
- FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n
+ FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n
# Document messages
PrematureEOF=Fine del file anticipata.
@@ -111,7 +111,7 @@
EncodingDeclRequired = La dichiarazione di codifica è obbligatoria nella dichiarazione di testo.
NoMorePseudoAttributes = Non sono consentiti altri attributi pseudo.
MorePseudoAttributes = Sono previsti altri attributi pseudo.
- PseudoAttrNameExpected = È previsto un nome attributo pseudo.
+ PseudoAttrNameExpected = È previsto un nome attributo pseudo.
# 4.3.2 Well-Formed Parsed Entities
CommentNotInOneEntity = Il commento deve essere compreso completamente all'interno della stessa entità analizzata.
PINotInOneEntity = L'istruzione di elaborazione deve essere compresa completamente all'interno della stessa entità analizzata.
@@ -119,7 +119,7 @@
EncodingDeclInvalid = Nome codifica "{0}" non valido.
EncodingByteOrderUnsupported = L''ordine di byte specificato per la codifica "{0}" non è supportato.
InvalidByte = Byte non valido {0} della sequenza UTF-8 a {1} byte.
- ExpectedByte = È previsto il byte {0} della sequenza UTF-8 a {1} byte.
+ ExpectedByte = È previsto il byte {0} della sequenza UTF-8 a {1} byte.
InvalidHighSurrogate = I bit per surrogato alto nella sequenza UTF-8 non devono superare 0x10, ma è stato trovato 0x{0}.
OperationNotSupported = Operazione "{0}" non supportata dal processo di lettura {1}.
InvalidASCII = Il byte "{0}" non fa parte del set di caratteri ASCII (a 7 bit).
@@ -199,7 +199,7 @@
MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = È richiesto uno spazio prima di "NDATA" nella dichiarazione dell''entità "{0}".
MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = Il nome notazione è obbligatorio dopo "NDATA" nella dichiarazione dell''entità "{0}".
EntityDeclUnterminated = La dichiarazione per l''entità "{0}" deve terminare con ''>''.
- MSG_DUPLICATE_ENTITY_DEFINITION = L''entità "{0}" è stata dichiarata più volte.
+ MSG_DUPLICATE_ENTITY_DEFINITION = L''entità "{0}" è stata dichiarata più volte.
# 4.2.2 External Entities
ExternalIDRequired = La dichiarazione di entità esterna deve iniziare con "SYSTEM" o "PUBLIC".
MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = È richiesto uno spazio tra "PUBLIC" e l'identificativo pubblico.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties
index 7204dfddd3ec0..ef0edf1b18874 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties
@@ -24,7 +24,7 @@
# @version
BadMessageKey = メッセージ・キーに対応するエラー・メッセージが見つかりません。
- FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n
+ FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n
# Document messages
PrematureEOF=途中でファイルの末尾に達しました。
@@ -131,7 +131,7 @@
EncodingDeclRequired = テキスト宣言にはエンコーディング宣言が必要です。
NoMorePseudoAttributes = これ以上の疑似属性は指定できません。
MorePseudoAttributes = 疑似属性がさらに必要です。
- PseudoAttrNameExpected = 疑似属性名が必要です。
+ PseudoAttrNameExpected = 疑似属性名が必要です。
# 4.3.2 Well-Formed Parsed Entities
CommentNotInOneEntity = コメントは、同じ解析済エンティティ内に完全に含まれている必要があります。
PINotInOneEntity = 処理命令は、同じ解析済エンティティ内に完全に含まれている必要があります。
@@ -139,7 +139,7 @@
EncodingDeclInvalid = エンコーディング名"{0}"が無効です。
EncodingByteOrderUnsupported = エンコーディング"{0}"に指定されたバイト順はサポートされていません。
InvalidByte = {1}バイトのUTF-8シーケンスのバイト{0}が無効です。
- ExpectedByte = {1}バイトのUTF-8シーケンスのバイト{0}が必要です。
+ ExpectedByte = {1}バイトのUTF-8シーケンスのバイト{0}が必要です。
InvalidHighSurrogate = UTF-8シーケンスの上位サロゲート・ビットの上限は0x10ですが、0x{0}が検出されました。
OperationNotSupported = 操作"{0}"は{1}リーダーでサポートされていません。
InvalidASCII = バイト"{0}"は、(7ビット) ASCII文字セットのメンバーではありません。
@@ -219,7 +219,7 @@
MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = エンティティ"{0}"の宣言では、"NDATA"の前に空白が必要です。
MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = エンティティ"{0}"の宣言では、"NDATA"の後に表記名が必要です。
EntityDeclUnterminated = エンティティ"{0}"の宣言は''>''で終了する必要があります。
- MSG_DUPLICATE_ENTITY_DEFINITION = エンティティ"{0}"が複数回宣言されています。
+ MSG_DUPLICATE_ENTITY_DEFINITION = エンティティ"{0}"が複数回宣言されています。
# 4.2.2 External Entities
ExternalIDRequired = 外部エンティティ宣言の先頭には"SYSTEM"または"PUBLIC"が必要です。
MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = "PUBLIC"と公開識別子の間には空白が必要です。
@@ -329,4 +329,3 @@
# Implementation Property DTD
JDK_DTD_DENY = JAXP00010008: DTDプロパティが拒否に設定されている場合、DOCTYPEは指定できません。参照: java.xml/module-summaryのプロパティjdk.xml.dtd.support。
-
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ko.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ko.properties
index 4dbf9a5fb2959..e63654de23c1a 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ko.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ko.properties
@@ -4,7 +4,7 @@
# @version
BadMessageKey = 메시지 키에 해당하는 오류 메시지를 찾을 수 없습니다.
- FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n
+ FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n
# Document messages
PrematureEOF=예기치 않은 파일의 끝입니다.
@@ -111,7 +111,7 @@
EncodingDeclRequired = 텍스트 선언에는 인코딩 선언이 필요합니다.
NoMorePseudoAttributes = 의사 속성은 더 이상 허용되지 않습니다.
MorePseudoAttributes = 의사 속성이 더 필요합니다.
- PseudoAttrNameExpected = 의사 속성 이름이 필요합니다.
+ PseudoAttrNameExpected = 의사 속성 이름이 필요합니다.
# 4.3.2 Well-Formed Parsed Entities
CommentNotInOneEntity = 주석은 구문이 분석된 동일한 엔티티에 완전히 포함되어야 합니다.
PINotInOneEntity = 처리 명령은 구문이 분석된 동일한 엔티티에 완전히 포함되어야 합니다.
@@ -119,7 +119,7 @@
EncodingDeclInvalid = "{0}"은(는) 부적합한 인코딩 이름입니다.
EncodingByteOrderUnsupported = "{0}" 인코딩에 대해 제공된 바이트 순서는 지원되지 않습니다.
InvalidByte = {0}은(는) {1}바이트 UTF-8 시퀀스에 대해 부적합한 바이트입니다.
- ExpectedByte = {1}바이트 UTF-8 시퀀스에 필요한 바이트는 {0}입니다.
+ ExpectedByte = {1}바이트 UTF-8 시퀀스에 필요한 바이트는 {0}입니다.
InvalidHighSurrogate = UTF-8 시퀀스의 높은 대리 비트는 0x10을 초과하지 않아야 하지만 0x{0}이(가) 발견되었습니다.
OperationNotSupported = {1} 읽기 프로그램은 "{0}" 작업을 지원하지 않습니다.
InvalidASCII = 바이트 "{0}"은(는) (7비트) ASCII 문자 집합에 속하지 않습니다.
@@ -199,7 +199,7 @@
MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = "{0}" 엔티티에 대한 선언에서는 "NDATA" 앞에 공백이 필요합니다.
MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = "{0}" 엔티티에 대한 선언에서는 "NDATA" 다음에 표기법 이름이 필요합니다.
EntityDeclUnterminated = "{0}" 엔티티에 대한 선언은 ''>''로 끝나야 합니다.
- MSG_DUPLICATE_ENTITY_DEFINITION = "{0}" 엔티티가 두 번 이상 선언되었습니다.
+ MSG_DUPLICATE_ENTITY_DEFINITION = "{0}" 엔티티가 두 번 이상 선언되었습니다.
# 4.2.2 External Entities
ExternalIDRequired = 외부 엔티티 선언은 "SYSTEM" 또는 "PUBLIC"으로 시작해야 합니다.
MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = "PUBLIC"과 공용 식별자 사이에는 공백이 필요합니다.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_pt_BR.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_pt_BR.properties
index 4dbf741007fba..4be5baae0d097 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_pt_BR.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_pt_BR.properties
@@ -4,7 +4,7 @@
# @version
BadMessageKey = Não foi possível encontrar a mensagem de erro correspondente à chave da mensagem.
- FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n
+ FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n
# Document messages
PrematureEOF=Fim prematuro do arquivo.
@@ -111,7 +111,7 @@
EncodingDeclRequired = A declaração de codificação é necessária na declaração de texto.
NoMorePseudoAttributes = Não são mais permitidos pseudo-atributos.
MorePseudoAttributes = São esperados mais pseudo-atributos.
- PseudoAttrNameExpected = É esperado um nome de um pseudo-atributo.
+ PseudoAttrNameExpected = É esperado um nome de um pseudo-atributo.
# 4.3.2 Well-Formed Parsed Entities
CommentNotInOneEntity = O comentário deve estar totalmente contido na mesma entidade submetida a parsing.
PINotInOneEntity = A instrução de processamento deve estar totalmente contida na mesma entidade submetida a parsing.
@@ -119,7 +119,7 @@
EncodingDeclInvalid = Nome da codificação inválida "{0}".
EncodingByteOrderUnsupported = A ordem de bytes fornecida para codificação "{0}" não é suportada.
InvalidByte = Byte inválido {0} da sequência UTF-8 do byte {1}.
- ExpectedByte = Esperava {0} byte da sequência UTF-8 do byte {1}.
+ ExpectedByte = Esperava {0} byte da sequência UTF-8 do byte {1}.
InvalidHighSurrogate = Os bits substitutos altos na sequência da UTF-8 não devem exceder 0x10 mas foi encontrado 0x{0}.
OperationNotSupported = A operação "{0}" não é suportada pelo leitor {1}.
InvalidASCII = O byte "{0}" não é membro do conjunto de caracteres ASCII (7 bits).
@@ -199,7 +199,7 @@
MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = O espaço em branco é necessário antes de "NDATA" na declaração da entidade "{0}".
MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = O nome da notação é necessário após "NDATA" na declaração da entidade "{0}".
EntityDeclUnterminated = A declaração da entidade "{0}" deve terminar com ''>''.
- MSG_DUPLICATE_ENTITY_DEFINITION = A entidade "{0}" foi declarada mais de uma vez.
+ MSG_DUPLICATE_ENTITY_DEFINITION = A entidade "{0}" foi declarada mais de uma vez.
# 4.2.2 External Entities
ExternalIDRequired = A declaração da entidade externa deve começar com "SYSTEM" ou "PUBLIC".
MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = O espaço em branco é necessário entre "PUBLIC" e o identificador público.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_sv.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_sv.properties
index b94d0f982a35a..b27963ef058e8 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_sv.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_sv.properties
@@ -4,7 +4,7 @@
# @version
BadMessageKey = Hittar inte felmeddelandet som motsvarar meddelandenyckeln.
- FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n
+ FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n
# Document messages
PrematureEOF=Filen har avslutats för tidigt.
@@ -111,7 +111,7 @@
EncodingDeclRequired = Koddeklaration krävs i textdeklarationen.
NoMorePseudoAttributes = Inga fler pseudoattribut är tillåtna.
MorePseudoAttributes = Ytterligare pseudoattribut förväntas.
- PseudoAttrNameExpected = Ett pseudoattributnamn förväntas.
+ PseudoAttrNameExpected = Ett pseudoattributnamn förväntas.
# 4.3.2 Well-Formed Parsed Entities
CommentNotInOneEntity = Kommentaren måste finnas med inom samma tolkade enhet.
PINotInOneEntity = Bearbetningsinstruktionen måste finnas med inom samma tolkade enhet.
@@ -119,7 +119,7 @@
EncodingDeclInvalid = Ogiltigt kodnamn, "{0}".
EncodingByteOrderUnsupported = Angiven byteordningsföljd i kodning "{0}" stöds inte.
InvalidByte = Ogiltig byte {0} i UTF-8-sekvensen för {1}-byte.
- ExpectedByte = Förväntad byte {0} i UTF-8-sekvensen för {1}-byte.
+ ExpectedByte = Förväntad byte {0} i UTF-8-sekvensen för {1}-byte.
InvalidHighSurrogate = Höga surrogatbitar i UTF-8-sekvens får inte överskrida 0x10, men 0x{0} hittades.
OperationNotSupported = Åtgärden "{0}" stöds inte i läsaren {1}.
InvalidASCII = Byte "{0}" ingår inte i ASCII-teckenuppsättningen (7 bitar).
@@ -199,7 +199,7 @@
MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = Tomt utrymme krävs före "NDATA" i deklarationen för enheten "{0}".
MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = Notationsnamnet måste anges efter "NDATA" i deklarationen för enheten "{0}".
EntityDeclUnterminated = Deklarationen för enheten "{0}" måste avslutas med ''>''.
- MSG_DUPLICATE_ENTITY_DEFINITION = Enheten "{0}" har deklarerats mer än en gång.
+ MSG_DUPLICATE_ENTITY_DEFINITION = Enheten "{0}" har deklarerats mer än en gång.
# 4.2.2 External Entities
ExternalIDRequired = Den externa enhetsdeklarationen måste inledas med antingen "SYSTEM" eller "PUBLIC".
MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = Tomt utrymme krävs mellan "PUBLIC" och den allmänna identifieraren.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties
index de68714fa2e19..0b937ce7623d9 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties
@@ -24,7 +24,7 @@
# @version
BadMessageKey = 找不到与消息关键字对应的错误消息。
- FormatFailed = 设置以下消息的格式时出现内部错误:\n
+ FormatFailed = 设置以下消息的格式时出现内部错误:\n
# Document messages
PrematureEOF=文件提前结束。
@@ -219,7 +219,7 @@
MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = 在实体 "{0}" 的声明中的 "NDATA" 前面需要有空格。
MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = 在实体 "{0}" 的声明中的 "NDATA" 后面需要有记号名称。
EntityDeclUnterminated = 实体 "{0}" 的声明必须以 ''>'' 结尾。
- MSG_DUPLICATE_ENTITY_DEFINITION = 实体 "{0}" 声明了多次。
+ MSG_DUPLICATE_ENTITY_DEFINITION = 实体 "{0}" 声明了多次。
# 4.2.2 External Entities
ExternalIDRequired = 外部实体声明必须以 "SYSTEM" 或 "PUBLIC" 开头。
MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = 在 "PUBLIC" 和公共标识符之间需要有空格。
@@ -329,4 +329,3 @@
# Implementation Property DTD
JDK_DTD_DENY = JAXP00010008:当 DTD 属性设置为拒绝时,不允许使用 DOCTYPE。请参阅:java.xml/module-summary 中的属性 jdk.xml.dtd.support。
-
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_TW.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_TW.properties
index 44671abcfd848..976fde3085c67 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_TW.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_TW.properties
@@ -199,7 +199,7 @@
MSG_SPACE_REQUIRED_BEFORE_NDATA_IN_UNPARSED_ENTITYDECL = 在實體 "{0}" 的宣告中,"NDATA" 之前需要空格。
MSG_NOTATION_NAME_REQUIRED_FOR_UNPARSED_ENTITYDECL = 在實體 "{0}" 的宣告中,"NDATA" 之後需要表示法名稱。
EntityDeclUnterminated = 實體 "{0}" 的宣告結尾必須為 ''>''。
- MSG_DUPLICATE_ENTITY_DEFINITION = 實體 "{0}" 宣告超過一次以上。
+ MSG_DUPLICATE_ENTITY_DEFINITION = 實體 "{0}" 宣告超過一次以上。
# 4.2.2 External Entities
ExternalIDRequired = 外部實體宣告的開頭必須為 "SYSTEM" 或 "PUBLIC"。
MSG_SPACE_REQUIRED_BEFORE_PUBIDLITERAL_IN_EXTERNALID = "PUBLIC" 與公用 ID 之間需要空格。
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties
index 47d8b7e9f535e..f6402e8f65e49 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties
@@ -107,7 +107,7 @@
#schema valid (3.X.3)
- schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed due to restriction set by the accessExternalSchema property.
+ schema_reference.access = schema_reference: Failed to read schema document ''{0}'', because ''{1}'' access is not allowed due to restriction set by the accessExternalSchema property.
schema_reference.4 = schema_reference.4: Failed to read schema document ''{0}'', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not .
src-annotation = src-annotation: elements can only contain and elements, but ''{0}'' was found.
src-attribute.1 = src-attribute.1: The properties ''default'' and ''fixed'' cannot both be present in attribute declaration ''{0}''. Use only one of them.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties
index 9ed8feb5ef027..1144488773e72 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties
@@ -107,7 +107,7 @@
#schema valid (3.X.3)
- schema_reference.access = schema_reference: Schemadokument ''{0}'' konnte nicht gelesen werden, weil der ''{1}''-Zugriff wegen der von der Eigenschaft accessExternalSchema festgelegten Einschränkung nicht zulässig ist.
+ schema_reference.access = schema_reference: Schemadokument ''{0}'' konnte nicht gelesen werden, weil der ''{1}''-Zugriff wegen der von der Eigenschaft accessExternalSchema festgelegten Einschränkung nicht zulässig ist.
schema_reference.4 = schema_reference.4: Schemadokument ''{0}'' konnte nicht gelesen werden, da 1) das Dokument nicht gefunden werden konnte; 2) das Dokument nicht gelesen werden konnte; 3) das Root-Element des Dokuments nicht ist.
src-annotation = src-annotation: -Elemente können nur - und -Elemente enthalten, aber es wurde ''{0}'' gefunden.
src-attribute.1 = src-attribute.1: Die Eigenschaften ''default'' und ''fixed'' können nicht beide in der Attributdeklaration ''{0}'' vorhanden sein. Verwenden Sie nur eine dieser Eigenschaften.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_es.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_es.properties
index fd3310a044288..9b5e412696b3e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_es.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_es.properties
@@ -115,7 +115,7 @@
#schema valid (3.X.3)
- schema_reference.access = schema_reference: fallo al leer el documento de esquema ''{0}'' porque no se permite el acceso ''{1}'' debido a una restricción definida por la propiedad accessExternalSchema.
+ schema_reference.access = schema_reference: fallo al leer el documento de esquema ''{0}'' porque no se permite el acceso ''{1}'' debido a una restricción definida por la propiedad accessExternalSchema.
schema_reference.4 = schema_reference.4: Fallo al leer el documento de esquema ''{0}'', porque 1) no se ha encontrado el documento; 2) no se ha podido leer el documento; 3) el elemento raíz del documento no es .
src-annotation = src-annotation: Los elementos de sólo pueden contener elementos de y , pero se ha encontrado ''{0}''.
src-attribute.1 = src-attribute.1: Las propiedades ''default'' y ''fixed'' no pueden estar presentes de forma simultánea en la declaración de atributo ''{0}''. Utilice sólo una de ellas.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_fr.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_fr.properties
index 7d320d2f18736..a955e5d11f3e8 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_fr.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_fr.properties
@@ -115,7 +115,7 @@
#schema valid (3.X.3)
- schema_reference.access = schema_reference : échec de la lecture du document de schéma ''{0}'', car l''accès ''{1}'' n''est pas autorisé en raison d''une restriction définie par la propriété accessExternalSchema.
+ schema_reference.access = schema_reference : échec de la lecture du document de schéma ''{0}'', car l''accès ''{1}'' n''est pas autorisé en raison d''une restriction définie par la propriété accessExternalSchema.
schema_reference.4 = schema_reference.4 : Echec de la lecture du document de schéma ''{0}'' pour les raisons suivantes : 1) Le document est introuvable ; 2) Le document n''a pas pu être lu ; 3) L''élément racine du document n''est pas .
src-annotation = src-annotation : Les éléments ne peuvent contenir que des éléments et , mais ''{0}'' a été trouvé.
src-attribute.1 = src-attribute.1 : Les propriétés ''default'' et ''fixed'' ne peuvent pas figurer simultanément dans la déclaration d''attribut ''{0}''. Utilisez uniquement l''une d''entre elles.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_it.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_it.properties
index 7b640448b2c5c..04578cdc31439 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_it.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_it.properties
@@ -115,7 +115,7 @@
#schema valid (3.X.3)
- schema_reference.access = schema_reference: lettura del documento di schema ''{0}'' non riuscita. Accesso ''{1}'' non consentito a causa della limitazione definita dalla proprietà accessExternalSchema.
+ schema_reference.access = schema_reference: lettura del documento di schema ''{0}'' non riuscita. Accesso ''{1}'' non consentito a causa della limitazione definita dalla proprietà accessExternalSchema.
schema_reference.4 = schema_reference.4: lettura del documento di schema "{0}" non riuscita perché 1) non è stato possibile trovare il documento; 2) non è stato possibile leggere il documento; 3) l''elemento radice del documento non è .
src-annotation = src-annotation: possono essere contenuti soltanto elementi e , ma è stato trovato ''{0}''.
src-attribute.1 = src-attribute.1: le proprietà ''default'' e ''fixed'' non possono essere entrambi presenti nella dichiarazione di attributo ''{0}''. Utilizzarne solo una.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ko.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ko.properties
index 043edbf28670b..91949ed6c9c46 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ko.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ko.properties
@@ -115,7 +115,7 @@
#schema valid (3.X.3)
- schema_reference.access = schema_reference: accessExternalSchema 속성으로 설정된 제한으로 인해 ''{1}'' 액세스가 허용되지 않으므로 스키마 문서 ''{0}'' 읽기를 실패했습니다.
+ schema_reference.access = schema_reference: accessExternalSchema 속성으로 설정된 제한으로 인해 ''{1}'' 액세스가 허용되지 않으므로 스키마 문서 ''{0}'' 읽기를 실패했습니다.
schema_reference.4 = schema_reference.4: 스키마 문서 ''{0}'' 읽기를 실패했습니다. 원인: 1) 문서를 찾을 수 없습니다. 2) 문서를 읽을 수 없습니다. 3) 문서의 루트 요소가 가 아닙니다.
src-annotation = src-annotation: 요소에는 및 요소만 포함될 수 있지만 ''{0}''이(가) 발견되었습니다.
src-attribute.1 = src-attribute.1: ''default'' 및 ''fixed'' 속성은 속성 선언 ''{0}''에 함께 존재할 수 없습니다. 하나만 사용하십시오.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_pt_BR.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_pt_BR.properties
index 8874db17b19de..563091b4bd021 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_pt_BR.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_pt_BR.properties
@@ -115,7 +115,7 @@
#schema valid (3.X.3)
- schema_reference.access = schema_reference: falha ao ler o documento de esquema ''{0}'' porque o acesso a ''{1}'' não é permitido em decorrência de uma restrição definida pela propriedade accessExternalSchema.
+ schema_reference.access = schema_reference: falha ao ler o documento de esquema ''{0}'' porque o acesso a ''{1}'' não é permitido em decorrência de uma restrição definida pela propriedade accessExternalSchema.
schema_reference.4 = schema_reference.4: Falha ao ler o documento do esquema ''{0}'' porque 1) não foi possível encontrar o documento; 2) não foi possível ler o documento; 3) o elemento-raiz do documento não é .
src-annotation = src-annotation: os elementos de podem conter somente os elementos e , mas foi encontrado ''{0}''.
src-attribute.1 = src-attribute.1: As propriedades ''padrão'' e ''fixed'' não podem estar presentes na declaração do atributo ''{0}''. Use somente uma delas.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_sv.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_sv.properties
index ca6d235f8df9e..6cfcddc13920b 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_sv.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_sv.properties
@@ -115,7 +115,7 @@
#schema valid (3.X.3)
- schema_reference.access = schema_reference: Kunde inte läsa schemadokumentet ''{0}'' eftersom ''{1}''-åtkomst inte tillåts på grund av begränsning som anges av egenskapen accessExternalSchema.
+ schema_reference.access = schema_reference: Kunde inte läsa schemadokumentet ''{0}'' eftersom ''{1}''-åtkomst inte tillåts på grund av begränsning som anges av egenskapen accessExternalSchema.
schema_reference.4 = schema_reference.4: Läsning av schemadokument ''{0}'' utfördes inte på grund av 1) det går inte att hitta dokumentet; 2) det går inte att läsa dokumentet; 3) dokumentets rotelement är inte .
src-annotation = src-annotation: element för får endast innehålla element för och , men ''{0}'' hittades.
src-attribute.1 = src-attribute.1: Båda egenskaperna ''default'' och ''fixed'' kan inte samtidigt ingå i attributdeklarationen ''{0}''. Använd en av dem.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages.properties
index ccc25233dacc3..bd71b3488485e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages.properties
@@ -21,14 +21,14 @@
# Messages for message reporting
BadMessageKey = The error message corresponding to the message key can not be found.
-FormatFailed = An internal error occurred while formatting the following message:\n
+FormatFailed = An internal error occurred while formatting the following message:\n
# XPointer Framework Error Messages
XPointerProcessingError = XPointerProcessingError: An error occurred while processing the XPointer expression.
InvalidXPointerToken = InvalidXPointerToken: The XPointer expression contains the invalid token ''{0}''
InvalidXPointerExpression = InvalidXPointerExpression: The XPointer expression ''{0}'' is invalid.
-MultipleShortHandPointers = MultipleShortHandPointers: The XPointer expression ''{0}'' is invalid. It has more than one ShortHand Pointer.
-SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: The XPointer expression ''{0}'' is invalid. The SchemeData was not followed by a '')'' character.
+MultipleShortHandPointers = MultipleShortHandPointers: The XPointer expression ''{0}'' is invalid. It has more than one ShortHand Pointer.
+SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: The XPointer expression ''{0}'' is invalid. The SchemeData was not followed by a '')'' character.
SchemeUnsupported = SchemeUnsupported: The XPointer scheme ''{0}'' is not supported.
InvalidShortHandPointer = InvalidShortHandPointer: The NCName of the ShortHand Pointer ''{0}'' is invalid.
UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: The XPointer expression ''{0}'' is invalid. The number of open parenthesis ''{1}'' is not equal to the number of close parenthesis ''{2}''.
@@ -39,4 +39,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: The element() scheme XPoi
InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: The Element Scheme XPointer expression ''{0}'' is invalid.
XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: An error occurred while processing the XPointer element() Scheme expression.
InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: The element() Scheme contains a ShortHand Pointer ''{0}'' with an invalid NCName.
-InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: The element() Scheme contains an invalid child sequence character ''{0}''.
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: The element() Scheme contains an invalid child sequence character ''{0}''.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties
index ca3bf6fac5ac8..fcd8b9e5a0ca0 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties
@@ -21,14 +21,14 @@
# Messages for message reporting
BadMessageKey = Die zum Meldungsschlüssel gehörige Fehlermeldung kann nicht gefunden werden.
-FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n
+FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n
# XPointer Framework Error Messages
XPointerProcessingError = XPointerProcessingError: Beim Verarbeiten des XPointer-Ausdrucks ist ein Fehler aufgetreten.
InvalidXPointerToken = InvalidXPointerToken: XPointer-Ausdruck enthält das ungültige Token "{0}"
InvalidXPointerExpression = InvalidXPointerExpression: XPointer-Ausdruck "{0}" ist ungültig.
MultipleShortHandPointers = MultipleShortHandPointers: XPointer-Ausdruck "{0}" ist ungültig. Mehrere ShortHand-Zeiger vorhanden.
-SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer-Ausdruck "{0}" ist ungültig. Auf SchemeData folgte kein ")"-Zeichen.
+SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer-Ausdruck "{0}" ist ungültig. Auf SchemeData folgte kein ")"-Zeichen.
SchemeUnsupported = SchemeUnsupported: XPointer-Schema "{0}" wird nicht unterstützt.
InvalidShortHandPointer = InvalidShortHandPointer: NCName von ShortHand-Zeiger "{0}" ist ungültig.
UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: XPointer-Ausdruck "{0}" ist ungültig. Die Anzahl der öffnenden Klammern "{1}" entspricht nicht der Anzahl der schließenden Klammern "{2}".
@@ -39,4 +39,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: element()-Schema-XPointer
InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: Elementschema-XPointer-Ausdruck "{0}" ist ungültig.
XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: Beim Verarbeiten des XPointer-element()-Schemaausdrucks ist ein Fehler aufgetreten.
InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: element()-Schema enthält einen ShortHand-Zeiger "{0}" mit einem ungültigen NCName.
-InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element()-Schema enthält ein untergeordnetes Sequenzzeichen "{0}".
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element()-Schema enthält ein untergeordnetes Sequenzzeichen "{0}".
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_es.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_es.properties
index d90c9a7d5b7be..6f9ae6734cc41 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_es.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_es.properties
@@ -29,14 +29,14 @@
# Messages for message reporting
BadMessageKey = No se ha encontrado el mensaje de error que corresponde a la clave de mensaje.
-FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n
+FormatFailed = Se ha producido un error interno al formatear el siguiente mensaje:\n
# XPointer Framework Error Messages
XPointerProcessingError = XPointerProcessingError: Se ha producido un error al procesar la expresión XPointer.
InvalidXPointerToken = InvalidXPointerToken: La expresión XPointer contiene el token no válido ''{0}''
InvalidXPointerExpression = InvalidXPointerExpression: La expresión XPointer ''{0}'' no es válida.
-MultipleShortHandPointers = MultipleShortHandPointers: La expresión XPointer ''{0}'' no es válida. Tiene más de un puntero abreviado.
-SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: La expresión XPointer ''{0}'' no es válida. SchemeData no viene seguido de un carácter '')''.
+MultipleShortHandPointers = MultipleShortHandPointers: La expresión XPointer ''{0}'' no es válida. Tiene más de un puntero abreviado.
+SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: La expresión XPointer ''{0}'' no es válida. SchemeData no viene seguido de un carácter '')''.
SchemeUnsupported = SchemeUnsupported: El esquema XPointer ''{0}'' no está soportado.
InvalidShortHandPointer = InvalidShortHandPointer: El valor de NCName del puntero abreviado ''{0}'' no es válido.
UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: La expresión XPointer ''{0}'' no es válida. El número de paréntesis de apertura ''{1}'' no es igual al número de paréntesis de cierre ''{2}''.
@@ -47,4 +47,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: La expresión XPointer de
InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: La expresión XPointer del esquema de elemento ''{0}'' no es válida.
XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: Se ha producido un error al procesar la expresión de esquema XPointer element().
InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: El esquema element() contiene un puntero abreviado ''{0}'' con un valor de NCName no válido.
-InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: El esquema element() contiene un carácter de secuencia secundaria no válido ''{0}''.
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: El esquema element() contiene un carácter de secuencia secundaria no válido ''{0}''.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_fr.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_fr.properties
index 65c0d2040d26e..256a737cf7d39 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_fr.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_fr.properties
@@ -29,14 +29,14 @@
# Messages for message reporting
BadMessageKey = Le message d'erreur correspondant à la clé de message est introuvable.
-FormatFailed = Une erreur interne est survenue lors de la mise en forme du message suivant :\n
+FormatFailed = Une erreur interne est survenue lors de la mise en forme du message suivant :\n
# XPointer Framework Error Messages
XPointerProcessingError = XPointerProcessingError : une erreur est survenue lors du traitement de l'expression XPointer.
InvalidXPointerToken = InvalidXPointerToken : l''expression XPointer contient le jeton non valide ''{0}''
InvalidXPointerExpression = InvalidXPointerExpression : l''expression XPointer ''{0}'' n''est pas valide.
-MultipleShortHandPointers = MultipleShortHandPointers : l''expression XPointer ''{0}'' n''est pas valide. Elle contient plusieurs pointeurs ShortHand.
-SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis : l''expression XPointer ''{0}'' n''est pas valide. L''élément SchemeData n''est pas suivi d''un caractère '')''.
+MultipleShortHandPointers = MultipleShortHandPointers : l''expression XPointer ''{0}'' n''est pas valide. Elle contient plusieurs pointeurs ShortHand.
+SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis : l''expression XPointer ''{0}'' n''est pas valide. L''élément SchemeData n''est pas suivi d''un caractère '')''.
SchemeUnsupported = SchemeUnsupported : le processus XPointer ''{0}'' n''est pas pris en charge.
InvalidShortHandPointer = InvalidShortHandPointer : le NCName du pointeur ShortHand ''{0}'' n''est pas valide.
UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression : l''expression XPointer ''{0}'' n''est pas valide. Le nombre de parenthèses ouvrantes ''{1}'' est différent du nombre de parenthèses fermantes ''{2}''.
@@ -47,4 +47,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken : l''expression XPointer d
InvalidElementSchemeXPointer = InvalidElementSchemeXPointer : l''expression XPointer de processus d''élément ''{0}'' n''est pas valide.
XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError : une erreur est survenue lors du traitement de l'expression de processus element() XPointer.
InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData : le processus element() contient un pointeur ShortHand ''{0}'' avec un NCName non valide.
-InvalidChildSequenceCharacter = InvalidChildSequenceCharacter : le processus element() contient un caractère de séquence enfant non valide ''{0}''.
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter : le processus element() contient un caractère de séquence enfant non valide ''{0}''.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_it.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_it.properties
index d5822b7e7dc7f..553046c372587 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_it.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_it.properties
@@ -29,14 +29,14 @@
# Messages for message reporting
BadMessageKey = Impossibile trovare il messaggio di errore corrispondente alla chiave di messaggio.
-FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n
+FormatFailed = Si è verificato un errore interno durante la formattazione del seguente messaggio:\n
# XPointer Framework Error Messages
XPointerProcessingError = XPointerProcessingError: si è verificato un errore durante l'elaborazione dell'espressione XPointer.
InvalidXPointerToken = InvalidXPointerToken: l''espressione XPointer contiene il token non valido ''{0}''.
InvalidXPointerExpression = InvalidXPointerExpression: l''espressione XPointer ''{0}'' non è valida.
-MultipleShortHandPointers = MultipleShortHandPointers: l''espressione XPointer ''{0}'' non è valida. Contiene più puntatori ShortHand.
-SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: l''espressione XPointer ''{0}'' non è valida. SchemeData non è seguito da un carattere '')''.
+MultipleShortHandPointers = MultipleShortHandPointers: l''espressione XPointer ''{0}'' non è valida. Contiene più puntatori ShortHand.
+SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: l''espressione XPointer ''{0}'' non è valida. SchemeData non è seguito da un carattere '')''.
SchemeUnsupported = SchemeUnsupported: lo schema XPointer ''{0}'' non è supportato.
InvalidShortHandPointer = InvalidShortHandPointer: NCName del puntatore ShortHand ''{0}'' non valido.
UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: l''espressione XPointer ''{0}'' non è valida. Il numero di parentesi aperte ''{1}'' non corrisponde al numero di parentesi chiuse ''{2}''.
@@ -47,4 +47,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: l''espressione XPointer d
InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: l''espressione XPointer ''{0}'' dello schema di elemento non è valida.
XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: si è verificato un errore durante l'elaborazione dell'espressione di schema element() XPointer.
InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: lo schema element() contiene un puntatore ShortHand ''{0}'' con NCName non valido.
-InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: lo schema element() contiene un carattere di sequenza secondaria ''{0}'' non valido.
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: lo schema element() contiene un carattere di sequenza secondaria ''{0}'' non valido.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties
index 0038baa4d6cc3..d56c65126ce3c 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties
@@ -21,14 +21,14 @@
# Messages for message reporting
BadMessageKey = メッセージ・キーに対応するエラー・メッセージが見つかりません。
-FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n
+FormatFailed = 次のメッセージの書式設定中に内部エラーが発生しました:\n
# XPointer Framework Error Messages
XPointerProcessingError = XPointerProcessingError: XPointer式の処理中にエラーが発生しました。
InvalidXPointerToken = InvalidXPointerToken: XPointer式に無効なトークン''{0}''が含まれています
InvalidXPointerExpression = InvalidXPointerExpression: XPointer式''{0}''が無効です。
-MultipleShortHandPointers = MultipleShortHandPointers: XPointer式''{0}''が無効です。複数のShortHandポインタが含まれています。
-SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer式''{0}''が無効です。SchemeDataの後に'')''文字がありません。
+MultipleShortHandPointers = MultipleShortHandPointers: XPointer式''{0}''が無効です。複数のShortHandポインタが含まれています。
+SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer式''{0}''が無効です。SchemeDataの後に'')''文字がありません。
SchemeUnsupported = SchemeUnsupported: XPointerスキーム''{0}''はサポートされていません。
InvalidShortHandPointer = InvalidShortHandPointer: ShortHandポインタ''{0}''のNCNameが無効です。
UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: XPointer式''{0}''が無効です。左丸カッコ''{1}''の数が右丸カッコ''{2}''の数と一致しません。
@@ -39,4 +39,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: element() Scheme XPointer
InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: Element Scheme XPointer式''{0}''が無効です。
XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: XPointer element() Scheme式の処理中にエラーが発生しました。
InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: element() Schemeに無効なNCNameを持つShortHandポインタ''{0}''が含まれています。
-InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element() Schemeに無効な子シーケンス文字''{0}''が含まれています。
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element() Schemeに無効な子シーケンス文字''{0}''が含まれています。
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ko.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ko.properties
index 2e920adf16541..3580222cffa3f 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ko.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ko.properties
@@ -29,14 +29,14 @@
# Messages for message reporting
BadMessageKey = 메시지 키에 해당하는 오류 메시지를 찾을 수 없습니다.
-FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n
+FormatFailed = 다음 메시지의 형식을 지정하는 중 내부 오류가 발생했습니다.\n
# XPointer Framework Error Messages
XPointerProcessingError = XPointerProcessingError: XPointer 표현식을 처리하는 중 오류가 발생했습니다.
InvalidXPointerToken = InvalidXPointerToken: XPointer 표현식에 부적합한 토큰 ''{0}''이(가) 포함되어 있습니다.
InvalidXPointerExpression = InvalidXPointerExpression: XPointer 표현식 ''{0}''이(가) 부적합합니다.
-MultipleShortHandPointers = MultipleShortHandPointers: XPointer 표현식 ''{0}''이(가) 부적합합니다. ShortHand Pointer가 두 개 이상 포함되어 있습니다.
-SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer 표현식 ''{0}''이(가) 부적합합니다. SchemeData 뒤에 '')'' 문자가 없습니다.
+MultipleShortHandPointers = MultipleShortHandPointers: XPointer 표현식 ''{0}''이(가) 부적합합니다. ShortHand Pointer가 두 개 이상 포함되어 있습니다.
+SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer 표현식 ''{0}''이(가) 부적합합니다. SchemeData 뒤에 '')'' 문자가 없습니다.
SchemeUnsupported = SchemeUnsupported: XPointer 체계 ''{0}''은(는) 지원되지 않습니다.
InvalidShortHandPointer = InvalidShortHandPointer: ShortHand Pointer ''{0}''의 NCName이 부적합합니다.
UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: XPointer 표현식 ''{0}''이(가) 부적합합니다. 여는 괄호의 개수 ''{1}''과(와) 닫는 괄호의 개수 ''{2}''이(가) 일치하지 않습니다.
@@ -47,4 +47,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: element() 체계 XPointer
InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: 요소 체계 XPointer 표현식 ''{0}''이(가) 부적합합니다.
XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: XPointer element() 체계 표현식을 처리하는 중 오류가 발생했습니다.
InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: element() 체계에 NCName이 부적합한 ShortHand Pointer ''{0}''이(가) 포함되어 있습니다.
-InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element() 체계에 부적합한 하위 시퀀스 문자 ''{0}''이(가) 포함되어 있습니다.
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element() 체계에 부적합한 하위 시퀀스 문자 ''{0}''이(가) 포함되어 있습니다.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_pt_BR.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_pt_BR.properties
index 2d5522e7989ee..4ee319e06e992 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_pt_BR.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_pt_BR.properties
@@ -29,14 +29,14 @@
# Messages for message reporting
BadMessageKey = Não foi possível encontrar a mensagem de erro correspondente à chave da mensagem.
-FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n
+FormatFailed = Ocorreu um erro interno ao formatar a mensagem a seguir:\n
# XPointer Framework Error Messages
XPointerProcessingError = XPointerProcessingError: Ocorreu um erro ao processar a expressão XPointer.
InvalidXPointerToken = InvalidXPointerToken: A expressão XPointer contém o token inválido ''{0}''
InvalidXPointerExpression = InvalidXPointerExpression: A expressão XPointer ''{0}'' é inválida.
-MultipleShortHandPointers = MultipleShortHandPointers: A expressão XPointer ''{0}'' é inválida. Tem mais de um Ponteiro ShortHand.
-SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: A expressão XPointer ''{0}'' é inválida. O SchemeData não foi seguida por um caractere '')".
+MultipleShortHandPointers = MultipleShortHandPointers: A expressão XPointer ''{0}'' é inválida. Tem mais de um Ponteiro ShortHand.
+SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: A expressão XPointer ''{0}'' é inválida. O SchemeData não foi seguida por um caractere '')".
SchemeUnsupported = SchemeUnsupported: O esquema XPointer ''{0}'' não é suportado.
InvalidShortHandPointer = InvalidShortHandPointer: O NCName do Ponteiro do ShortHand ''{0}'' é inválido.
UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: A expressão XPointer ''{0}'' é inválida. O número de parênteses de abertura ''{1}'' não é igual ao número de parênteses de fechamento ''{2}''.
@@ -47,4 +47,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: A expressão XPointer do
InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: A expressão XPointer do Esquema do Elemento ''{0}'' é inválida.
XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: Ocorreu um erro ao processoar a expressão do Esquema do element() do XPointer.
InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: O Esquema do element() contém um Ponteiro de ShortHand ''{0}'' com um NCName inválido.
-InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: O Esquema de element() contém um caractere de sequência filho inválido ''{0}''.
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: O Esquema de element() contém um caractere de sequência filho inválido ''{0}''.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_sv.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_sv.properties
index 2247d08110558..f00c5353de8cd 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_sv.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_sv.properties
@@ -29,14 +29,14 @@
# Messages for message reporting
BadMessageKey = Hittar inte felmeddelandet som motsvarar meddelandenyckeln.
-FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n
+FormatFailed = Ett internt fel inträffade vid formatering av följande meddelande:\n
# XPointer Framework Error Messages
XPointerProcessingError = XPointerProcessingError: Ett fel inträffade vid bearbetning av XPointer-uttrycket.
InvalidXPointerToken = InvalidXPointerToken: XPointer-uttrycket innehåller ogiltigt tecken, ''{0}''
InvalidXPointerExpression = InvalidXPointerExpression: XPointer-uttrycket ''{0}'' är ogiltigt.
-MultipleShortHandPointers = MultipleShortHandPointers: XPointer-uttrycket ''{0}'' är ogiltigt. Det innehåller fler än en ShortHand Pointer.
-SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer-uttrycket ''{0}'' är ogiltigt. SchemeData efterföljdes inte av ett '')''-tecken.
+MultipleShortHandPointers = MultipleShortHandPointers: XPointer-uttrycket ''{0}'' är ogiltigt. Det innehåller fler än en ShortHand Pointer.
+SchemeDataNotFollowedByCloseParenthesis = SchemeDataNotFollowedByCloseParenthesis: XPointer-uttrycket ''{0}'' är ogiltigt. SchemeData efterföljdes inte av ett '')''-tecken.
SchemeUnsupported = SchemeUnsupported: XPointer-schemat ''{0}'' stöds inte.
InvalidShortHandPointer = InvalidShortHandPointer: NCName i ShortHand-pekaren ''{0}'' är ogiltigt.
UnbalancedParenthesisInXPointerExpression = UnbalancedParenthesisInXPointerExpression: XPointer-uttrycket ''{0}'' är ogiltigt. Antalet vänsterparenteser ''{1}'' är inte samma som antalet högerparenteser ''{2}''.
@@ -47,4 +47,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: XPointer-uttrycket i elem
InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: XPointer-uttrycket ''{0}'' i elementschemat är ogiltigt.
XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: Ett fel inträffade vid bearbetning av schemauttrycket i XPointer element().
InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: element()-schemat innehåller ShortHand-pekaren ''{0}'' med ogiltigt NCName.
-InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element()-schemat innehåller ett ogiltigt tecken ''{0}'' i underordnad sekvens.
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: element()-schemat innehåller ett ogiltigt tecken ''{0}'' i underordnad sekvens.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties
index 140c91a4673b4..f9c7a1ab9337f 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties
@@ -21,7 +21,7 @@
# Messages for message reporting
BadMessageKey = 找不到与消息关键字对应的错误消息。
-FormatFailed = 设置以下消息的格式时出现内部错误:\n
+FormatFailed = 设置以下消息的格式时出现内部错误:\n
# XPointer Framework Error Messages
XPointerProcessingError = XPointerProcessingError: 处理 XPointer 表达式时出错。
diff --git a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver.properties b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver.properties
index 0d5242018d35c..2da648dcb259f 100644
--- a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver.properties
+++ b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver.properties
@@ -24,14 +24,14 @@
#
NotSerializable=\
- Class {0} is not Serializable.
+ Class {0} is not Serializable.
ClassNotFound=\
- Class {0} not found.
+ Class {0} not found.
error.parsing.classpath=\
- Error parsing classpath {0}.
+ Error parsing classpath {0}.
error.missing.classpath=\
- Missing argument for -classpath option
+ Missing argument for -classpath option
invalid.flag=\
- Invalid flag {0}.
+ Invalid flag {0}.
usage=\
- use: serialver [-classpath classpath] [classname...]
+ use: serialver [-classpath classpath] [classname...]
diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties
index d0cb53b8a0dc0..463068c517c23 100644
--- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties
+++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties
@@ -46,8 +46,8 @@ error.bad.cflag=\
error.bad.uflag=\
'u' flag requires manifest, 'e' flag or input files to be specified!
error.bad.eflag=\
- 'e' flag and manifest with the 'Main-Class' attribute cannot be specified \n\
- together!
+ 'e' flag and manifest with the 'Main-Class' attribute cannot be specified \n\
+ together!
error.bad.dflag=\
'-d, --describe-module' option requires no input file(s) to be specified
error.bad.reason=\
diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties
index 196d8e9b41637..e09eadbb3d0ff 100644
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties
@@ -62,7 +62,7 @@ main.opt.launcher=\
\ --launcher =[/]\n\
\ Add a launcher command of the given\n\
\ name for the module and the main class\n\
-\ if specified
+\ if specified
main.opt.bind-services=\
\ --bind-services Link in service provider modules and\n\
diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties
index a48a494895ea4..833b56ee5f381 100644
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties
@@ -41,7 +41,7 @@ main.opt.limit-modules=\ --limit-modules [,...] Begrenzt den Ber
main.opt.output=\ --output Ort des Ausgabepfads
-main.opt.launcher=\ --launcher =[/]\n Fügt einen Launcher-Befehl mit dem angegebenen\n Namen für das Modul und die Hauptklasse hinzu,\n falls angegeben
+main.opt.launcher=\ --launcher =[/]\n Fügt einen Launcher-Befehl mit dem angegebenen\n Namen für das Modul und die Hauptklasse hinzu,\n falls angegeben
main.opt.bind-services=\ --bind-services Bindet Serviceprovidermodule und ihre\n Abhängigkeiten ein
diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties
index df378866f9125..e54e62bafed9e 100644
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties
@@ -41,7 +41,7 @@ main.opt.limit-modules=\ --limit-modules [,...] 参照可能な
main.opt.output=\ --output 出力パスの場所
-main.opt.launcher=\ --launcher =[/]\n モジュールおよびメイン・クラス(指定した場合)に\n 指定された名前の起動ツール・コマンドを\n 追加します
+main.opt.launcher=\ --launcher =[/]\n モジュールおよびメイン・クラス(指定した場合)に\n 指定された名前の起動ツール・コマンドを\n 追加します
main.opt.bind-services=\ --bind-services サービス・プロバイダ・モジュールとその依存性\n 内でリンクします
diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties
index fae2369fedcdc..9c44e826b9358 100644
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties
@@ -41,7 +41,7 @@ main.opt.limit-modules=\ --limit-modules <模块>[,<模块>...] 限制可
main.opt.output=\ --output <路径> 输出路径的位置
-main.opt.launcher=\ --launcher <名称>=<模块>[/<主类>]\n 为模块和主类添加给定\n 名称的启动程序命令\n (如果指定)
+main.opt.launcher=\ --launcher <名称>=<模块>[/<主类>]\n 为模块和主类添加给定\n 名称的启动程序命令\n (如果指定)
main.opt.bind-services=\ --bind-services 链接服务提供方模块及其\n 被依赖对象
diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_de.properties b/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_de.properties
index afe1e7e168f55..ef06daa85776d 100644
--- a/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_de.properties
+++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_de.properties
@@ -186,12 +186,12 @@ arg=Aragonisch
arm=Armenisch
arn=Mapudungun
art=Kunstsprache
-asm=Assamesisch
+asm=Assamesisch
ast=Asturisch
ath=Athapaskisch
aus=Australisch
ava=Avarisch
-ave=Avestisch
+ave=Avestisch
aze=Aserbaidschanisch
bai=Bamileke-Sprache
bak=Baschkirisch
@@ -235,7 +235,7 @@ cpe=Kreolisch-Englische Sprache
cpf=Kreolisch-Französische Sprache
cpp=Kreolisch-Portugiesische Sprache
crh=Krimtatarisch
-crp=Kreolische Sprache
+crp=Kreolische Sprache
csb=Kaschubisch
cus=Kuschitisch
cze=Tschechisch
@@ -253,7 +253,7 @@ eng=Englisch
enm=Mittelenglisch
est=Estnisch
fan=Pangwe
-fao=Färöisch
+fao=Färöisch
fij=Fidschi
fin=Finnisch
fiu=Finnougrisch
@@ -433,7 +433,7 @@ snd=Zinti-Sprache
sog=Sogdisch
som=Somalisch
son=Songhai-Sprache
-sot=Süd-Sotho
+sot=Süd-Sotho
spa=Spanisch
srd=Sardisch
srn=Srananisch
diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sv.properties b/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sv.properties
index cc201fdbe3fb8..da7fddb29253a 100644
--- a/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sv.properties
+++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/LocaleNames_sv.properties
@@ -789,7 +789,7 @@ AE=Förenade Arabemiraten
AG=Antigua och Barbuda
AL=Albanien
AM=Armenien
-AN=Nederländska Antillerna
+AN=Nederländska Antillerna
AQ=Antarktis
AS=Amerikanska Samoa
AT=Österrike
diff --git a/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_ja.properties b/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_ja.properties
index e61dfd6ec37bd..c63e5bd73857a 100644
--- a/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_ja.properties
+++ b/src/jdk.management.agent/share/classes/jdk/internal/agent/resources/agent_ja.properties
@@ -24,7 +24,7 @@
#
agent.err.error = エラー
-agent.err.exception = エージェントが例外をスローしました
+agent.err.exception = エージェントが例外をスローしました
agent.err.warning = 警告
agent.err.configfile.notfound = 構成ファイルが見つかりません
diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/config/files/catalog2.properties b/test/jaxp/javax/xml/jaxp/unittest/common/config/files/catalog2.properties
index 06c25c3ba816c..c4a6e6bd10e53 100644
--- a/test/jaxp/javax/xml/jaxp/unittest/common/config/files/catalog2.properties
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/config/files/catalog2.properties
@@ -1,13 +1,13 @@
################################################################################
# XML Library (java.xml) Configuration File
#
-# This file is in java.util.Properties format and typically located in the conf
+# This file is in java.util.Properties format and typically located in the conf
# directory of the Java installation. It may contain key/value pairs for specifying
# the implementation class of a factory and/or properties that have corresponding
-# system properties.
+# system properties.
#
-# This file can be replaced by specifying a filename with the java.xml.config.file
-# system property. For example java -Djava.xml.config.file=myfile
+# This file can be replaced by specifying a filename with the java.xml.config.file
+# system property. For example java -Djava.xml.config.file=myfile
################################################################################
# ---- Config File: for testing the CATALOG property ----
diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/config/files/customJaxp.properties b/test/jaxp/javax/xml/jaxp/unittest/common/config/files/customJaxp.properties
index 610e0d08d1285..42a86e342ad2f 100644
--- a/test/jaxp/javax/xml/jaxp/unittest/common/config/files/customJaxp.properties
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/config/files/customJaxp.properties
@@ -1,13 +1,13 @@
################################################################################
# XML Library (java.xml) Configuration File
#
-# This file is in java.util.Properties format and typically located in the conf
+# This file is in java.util.Properties format and typically located in the conf
# directory of the Java installation. It may contain key/value pairs for specifying
# the implementation class of a factory and/or properties that have corresponding
-# system properties.
+# system properties.
#
-# This file can be replaced by specifying a filename with the jdk.xml.config.file
-# system property. For example java -Djava.xml.config.file=myfile
+# This file can be replaced by specifying a filename with the jdk.xml.config.file
+# system property. For example java -Djava.xml.config.file=myfile
################################################################################
# ---- Custom Configuration File ----
diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/config/files/jaxpImpls.properties b/test/jaxp/javax/xml/jaxp/unittest/common/config/files/jaxpImpls.properties
index 787543f185e6f..e937d612d69e3 100644
--- a/test/jaxp/javax/xml/jaxp/unittest/common/config/files/jaxpImpls.properties
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/config/files/jaxpImpls.properties
@@ -1,17 +1,17 @@
################################################################################
# XML Library (java.xml) Configuration File
#
-# This file is in java.util.Properties format and typically located in the conf
+# This file is in java.util.Properties format and typically located in the conf
# directory of the Java installation. It may contain key/value pairs for specifying
# the implementation class of a factory and/or properties that have corresponding
-# system properties.
+# system properties.
#
-# This file can be replaced by specifying a filename with the jdk.xml.config.file
+# This file can be replaced by specifying a filename with the jdk.xml.config.file
# system property. For example java -Djava.xml.config.file=myfile
################################################################################
# ---- Configuration for test ----
-#
+#
# Factory implementation class
javax.xml.parsers.DocumentBuilderFactory=common.config.DOMImplTest
javax.xml.parsers.SAXParserFactory=common.config.SAXImplTest
diff --git a/test/jdk/javax/net/ssl/Stapling/TEST.properties b/test/jdk/javax/net/ssl/Stapling/TEST.properties
index f4117a3ced2b7..f5039eb9e0a97 100644
--- a/test/jdk/javax/net/ssl/Stapling/TEST.properties
+++ b/test/jdk/javax/net/ssl/Stapling/TEST.properties
@@ -2,4 +2,4 @@ modules = \
java.base/sun.security.provider.certpath \
java.base/sun.security.util \
java.base/sun.security.validator \
- java.base/sun.security.x509
+ java.base/sun.security.x509
diff --git a/test/jdk/performance/client/SwingMark/src/resources/TextAreaTest.properties b/test/jdk/performance/client/SwingMark/src/resources/TextAreaTest.properties
index 07df149851b5d..a3a8e39ce5919 100644
--- a/test/jdk/performance/client/SwingMark/src/resources/TextAreaTest.properties
+++ b/test/jdk/performance/client/SwingMark/src/resources/TextAreaTest.properties
@@ -29,4 +29,4 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Resource bundle for Menu Test
-DisplayString=Swing is Fast!!!
+DisplayString=Swing is Fast!!!
diff --git a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/filechooser/resources/FileChooserDemo.properties b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/filechooser/resources/FileChooserDemo.properties
index c5c4c99bedad0..36eef6c8b3d67 100644
--- a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/filechooser/resources/FileChooserDemo.properties
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/filechooser/resources/FileChooserDemo.properties
@@ -8,18 +8,18 @@ FileChooserDemo.cancel.text = Cancel
FileChooserDemo.filter.blur = blur
FileChooserDemo.filter.edge = edge
-FileChooserDemo.filter.sharpen = sharpen
+FileChooserDemo.filter.sharpen = sharpen
FileChooserDemo.filter.darken = darken
FileChooserDemo.filter.brighten = brighten
FileChooserDemo.filter.lesscontrast = less contrast
FileChooserDemo.filter.morecontrast = more contrast
FileChooserDemo.filter.gray = gray
-FileChooserDemo.applyfilter.tooltip = Apply filter
-FileChooserDemo.rotateleft.tooltip = Rotate left
-FileChooserDemo.rotateright.tooltip = Rotate right
-FileChooserDemo.fliphorizontal.tooltip = Flip horizontal
-FileChooserDemo.flipvertical.tooltip = Flip vertical
+FileChooserDemo.applyfilter.tooltip = Apply filter
+FileChooserDemo.rotateleft.tooltip = Rotate left
+FileChooserDemo.rotateright.tooltip = Rotate right
+FileChooserDemo.fliphorizontal.tooltip = Flip horizontal
+FileChooserDemo.flipvertical.tooltip = Flip vertical
FileChooserDemo.preview.type = Type:
FileChooserDemo.preview.size = Size:
diff --git a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/TableDemo.properties b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/TableDemo.properties
index 1210d3f9c540f..4ce5a8f4cbb04 100644
--- a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/TableDemo.properties
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/table/resources/TableDemo.properties
@@ -9,9 +9,9 @@ TableDemo.searchLabel=Search Titles and Recipients
TableDemo.winnersLabel=Show Only Winners
TableDemo.noDataStatusLabel=No data loaded
-TableDemo.loadingStatusLabel=Loading data:
-TableDemo.rowCountLabel=Showing
-TableDemo.searchCountLabel=Search found
+TableDemo.loadingStatusLabel=Loading data:\u0020
+TableDemo.rowCountLabel=Showing\u0020
+TableDemo.searchCountLabel=Search found\u0020
TableDemo.yearColumnTitle=Year
TableDemo.categoryColumnTitle=Award Category
@@ -19,4 +19,3 @@ TableDemo.movieTitleColumnTitle=Movie Title
TableDemo.nomineesColumnTitle=Nominee(s)
TableDemo.imdbLinkNotFound=Unable to locate IMDB URL for
-
diff --git a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/resources/ToggleButtonDemo.properties b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/resources/ToggleButtonDemo.properties
index 241368aacaaa9..61676a284a836 100644
--- a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/resources/ToggleButtonDemo.properties
+++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/togglebutton/resources/ToggleButtonDemo.properties
@@ -1,6 +1,6 @@
### Button Demo ###
-ToggleButtonDemo.accessible_description=The ButtonDemo shows examples of using JButton, JRadioButton, JToggleButton, and JCheckBox
+ToggleButtonDemo.accessible_description=The ButtonDemo shows examples of using JButton, JRadioButton, JToggleButton, and JCheckBox
ToggleButtonDemo.tooltip=JButton, JRadioButton, JToggleButton, JCheckbox demos
ToggleButtonDemo.name=Button Demo
@@ -18,16 +18,16 @@ ToggleButtonDemo.imagetogglebuttons=Image Toggle Buttons
ToggleButtonDemo.textcheckboxes=Text CheckBoxes
ToggleButtonDemo.imagecheckboxes=Image CheckBoxes
-ToggleButtonDemo.button1=One
+ToggleButtonDemo.button1=One
ToggleButtonDemo.button2=Two
ToggleButtonDemo.button3=Three!
-ToggleButtonDemo.radio1=Radio One
+ToggleButtonDemo.radio1=Radio One
ToggleButtonDemo.radio2=Radio Two
ToggleButtonDemo.radio3=Radio Three
ToggleButtonDemo.radioX=Three(HTML!)
-ToggleButtonDemo.check1=One
+ToggleButtonDemo.check1=One
ToggleButtonDemo.check2=Two
ToggleButtonDemo.check3=Three
ToggleButtonDemo.checkX=Three(HTML!)
@@ -35,7 +35,7 @@ ToggleButtonDemo.checkX=Three(HTML!)
ToggleButtonDemo.customradio=A custom "chrome" radio button.
ToggleButtonDemo.customcheck=A custom lightbulb checkbox.
-ToggleButtonDemo.phone=Phone
+ToggleButtonDemo.phone=Phone
ToggleButtonDemo.write=Write
ToggleButtonDemo.peace=Peace
diff --git a/test/jdk/tools/jmod/src/foo/jdk/test/foo/resources/foo.properties b/test/jdk/tools/jmod/src/foo/jdk/test/foo/resources/foo.properties
index 8f6224de14467..99b4d5bfb9250 100644
--- a/test/jdk/tools/jmod/src/foo/jdk/test/foo/resources/foo.properties
+++ b/test/jdk/tools/jmod/src/foo/jdk/test/foo/resources/foo.properties
@@ -1 +1 @@
-name = foo
+name = foo
From 088e54f5602f5f46fde1e5e335ae323d8e4516be Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?=
Date: Tue, 13 Feb 2024 11:08:51 +0000
Subject: [PATCH 07/36] 8325650: Table of contents scroll timeout not long
enough
Reviewed-by: jjg
---
.../doclets/formats/html/resources/script.js.template | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template
index 9ec4b1c56704b..e08ff5db68c5e 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template
@@ -363,7 +363,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
scrollTimeout = setTimeout(() => {
scrollTimeout = null;
handleScroll();
- }, 50);
+ }, 100);
}
function handleScroll() {
if (!sidebar || !sidebar.offsetParent || sidebar.classList.contains("hide-sidebar")) {
@@ -445,7 +445,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
// Resize handler
function handleResize(e) {
if (expanded) {
- if (windowWidth != window.innerWidth) {
+ if (windowWidth !== window.innerWidth) {
collapse();
} else {
expand();
From f8d8eecf8041a8baa76ba0091f2842dcb0275cb3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?=
Date: Tue, 13 Feb 2024 11:21:03 +0000
Subject: [PATCH 08/36] 8325325: Breadcrumb navigation shows preview link for
modules and packages
Reviewed-by: jjg
---
.../doclets/formats/html/ClassUseWriter.java | 17 +++----
.../doclets/formats/html/ClassWriter.java | 11 ++---
.../doclets/formats/html/DocFilesHandler.java | 10 +----
.../formats/html/HtmlDocletWriter.java | 26 +++++++++--
.../doclets/formats/html/ModuleWriter.java | 5 +--
.../formats/html/PackageUseWriter.java | 6 +--
.../doclets/formats/html/PackageWriter.java | 7 +--
.../testModules/TestModulePackages.java | 4 +-
.../doclet/testNavigation/TestNavigation.java | 2 +-
.../doclet/testPreview/TestPreview.java | 45 ++++++++++++++++---
.../testPreview/api/preview/package-info.java | 31 +++++++++++++
11 files changed, 114 insertions(+), 50 deletions(-)
create mode 100644 test/langtools/jdk/javadoc/doclet/testPreview/api/preview/package-info.java
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
index e0b126dfacf59..ddc8710e517bc 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
@@ -34,7 +34,6 @@
import java.util.TreeSet;
import javax.lang.model.element.Element;
-import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
@@ -43,7 +42,6 @@
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.TagName;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Text;
import jdk.javadoc.internal.doclets.formats.html.Navigation.PageMode;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
@@ -422,15 +420,14 @@ protected HtmlTree getClassUseHeader() {
protected Navigation getNavBar(PageMode pageMode, Element element) {
List subnavLinks = new ArrayList<>();
if (configuration.showModules) {
- ModuleElement mdle = utils.elementUtils.getModuleOf(typeElement);
- subnavLinks.add(getModuleLink(mdle, Text.of(mdle.getQualifiedName())));
+ subnavLinks.add(getBreadcrumbLink(utils.elementUtils.getModuleOf(typeElement), false));
+ }
+ // We may generate a class-use page for an otherwise undocumented page in the condition below.
+ boolean isUndocumented = options.noDeprecated() && utils.isDeprecated(typeElement);
+ subnavLinks.add(getBreadcrumbLink(utils.containingPackage(typeElement), isUndocumented));
+ if (!isUndocumented) {
+ subnavLinks.add(getBreadcrumbLink(typeElement, true));
}
- PackageElement pkg = utils.containingPackage(typeElement);
- subnavLinks.add(getPackageLink(pkg, getLocalizedPackageName(pkg)));
- subnavLinks.add(getLink(
- new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.PLAIN, typeElement)
- .style(HtmlStyle.currentSelection)
- .skipPreview(true)));
return super.getNavBar(pageMode, element).setSubNavLinks(subnavLinks);
}
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java
index f74921464bbd7..b550b35e4d329 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java
@@ -35,7 +35,6 @@
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.ModuleElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
@@ -454,14 +453,10 @@ protected Content getClassContentHeader() {
protected Navigation getNavBar(PageMode pageMode, Element element) {
List subnavLinks = new ArrayList<>();
if (configuration.showModules) {
- ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(typeElement);
- subnavLinks.add(getModuleLink(mdle, Text.of(mdle.getQualifiedName())));
+ subnavLinks.add(getBreadcrumbLink(utils.elementUtils.getModuleOf(typeElement), false));
}
- PackageElement pkg = utils.containingPackage(typeElement);
- subnavLinks.add(getPackageLink(pkg, getLocalizedPackageName(pkg)));
- subnavLinks.add(getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.PLAIN, typeElement)
- .style(HtmlStyle.currentSelection)
- .skipPreview(true)));
+ subnavLinks.add(getBreadcrumbLink(utils.containingPackage(typeElement), false));
+ subnavLinks.add(getBreadcrumbLink(typeElement, true));
return super.getNavBar(pageMode, element).setSubNavLinks(subnavLinks);
}
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandler.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandler.java
index 93fd296280b07..47b2b6b41fe6f 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandler.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DocFilesHandler.java
@@ -30,9 +30,7 @@
import com.sun.source.doctree.StartElementTree;
import com.sun.source.util.DocTreeFactory;
import jdk.javadoc.internal.doclets.formats.html.markup.BodyContents;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Text;
import jdk.javadoc.internal.doclets.toolkit.DocFileElement;
import jdk.javadoc.internal.doclets.toolkit.DocletException;
import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
@@ -220,14 +218,10 @@ protected Navigation getNavBar(PageMode pageMode, Element element) {
List subnavLinks = new ArrayList<>();
var pkg = dfElement.getPackageElement();
if (configuration.showModules) {
- var mdle = utils.elementUtils.getModuleOf(element);
- subnavLinks.add(links.createLink(pathToRoot.resolve(docPaths.moduleSummary(mdle)),
- Text.of(mdle.getQualifiedName()),
- pkg.isUnnamed() ? HtmlStyle.currentSelection : null, ""));
+ subnavLinks.add(getBreadcrumbLink(utils.elementUtils.getModuleOf(element), pkg.isUnnamed()));
}
if (!pkg.isUnnamed()) {
- subnavLinks.add(links.createLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY),
- getLocalizedPackageName(pkg), HtmlStyle.currentSelection, ""));
+ subnavLinks.add(getBreadcrumbLink(pkg, true));
}
return super.getNavBar(pageMode, element).setSubNavLinks(subnavLinks);
}
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
index 73ce7bb784fdb..4eb05aeb695f6 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
@@ -31,7 +31,6 @@
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
@@ -84,13 +83,11 @@
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
import jdk.javadoc.internal.doclets.formats.html.markup.Head;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlId;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.Links;
-import jdk.javadoc.internal.doclets.formats.html.markup.ListBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
import jdk.javadoc.internal.doclets.formats.html.markup.Script;
import jdk.javadoc.internal.doclets.formats.html.markup.TagName;
@@ -634,6 +631,29 @@ protected DocPath pathString(PackageElement packageElement, DocPath name) {
return pathToRoot.resolve(docPaths.forPackage(packageElement).resolve(name));
}
+ /**
+ * {@return a content element containing a breadcrumb navigtation link for {@code elem}}
+ * Only module, package and type elements can appear in breadcrumb navigation.
+ *
+ * @param elem the element
+ * @param selected whether to use the style for current page element
+ */
+ protected Content getBreadcrumbLink(Element elem, boolean selected) {
+ HtmlTree link = switch (elem) {
+ case ModuleElement mdle -> links.createLink(pathToRoot.resolve(docPaths.moduleSummary(mdle)),
+ Text.of(mdle.getQualifiedName()));
+ case PackageElement pkg -> links.createLink(pathString(pkg, DocPaths.PACKAGE_SUMMARY),
+ getLocalizedPackageName(pkg));
+ case TypeElement type -> links.createLink(pathString(type, docPaths.forName(type)),
+ utils.getSimpleName(type));
+ default -> throw new IllegalArgumentException(Objects.toString(elem));
+ };
+ if (selected) {
+ link.setStyle(HtmlStyle.currentSelection);
+ }
+ return link;
+ }
+
/**
* {@return the link to the given package}
*
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java
index bf362e478ff62..24718c089bcb6 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriter.java
@@ -277,10 +277,7 @@ protected Content getModuleHeader(String heading) {
@Override
protected Navigation getNavBar(PageMode pageMode, Element element) {
return super.getNavBar(pageMode, element)
- .setSubNavLinks(List.of(
- links.createLink(pathToRoot.resolve(docPaths.moduleSummary(mdle)),
- Text.of(mdle.getQualifiedName()),
- HtmlStyle.currentSelection, "")));
+ .setSubNavLinks(List.of(getBreadcrumbLink(mdle, true)));
}
protected Content getContentHeader() {
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java
index 75009ad20663d..e8705923d945d 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java
@@ -220,11 +220,9 @@ private HtmlTree getBody() {
protected Navigation getNavBar(PageMode pageMode, Element element) {
List subnavLinks = new ArrayList<>();
if (configuration.showModules) {
- var mdle = utils.elementUtils.getModuleOf(packageElement);
- subnavLinks.add(getModuleLink(mdle, Text.of(mdle.getQualifiedName())));
+ subnavLinks.add(getBreadcrumbLink(utils.elementUtils.getModuleOf(packageElement), false));
}
- subnavLinks.add(links.createLink(pathString(packageElement, DocPaths.PACKAGE_SUMMARY),
- getLocalizedPackageName(packageElement), HtmlStyle.currentSelection, ""));
+ subnavLinks.add(getBreadcrumbLink(packageElement, true));
return super.getNavBar(pageMode, element).setSubNavLinks(subnavLinks);
}
}
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriter.java
index f9d3164a1d538..2983eeaaf58ed 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriter.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriter.java
@@ -272,12 +272,9 @@ private List findRelatedPackages() {
protected Navigation getNavBar(PageMode pageMode, Element element) {
List subnavLinks = new ArrayList<>();
if (configuration.showModules) {
- ModuleElement mdle = configuration.docEnv.getElementUtils().getModuleOf(packageElement);
- subnavLinks.add(links.createLink(pathToRoot.resolve(docPaths.moduleSummary(mdle)),
- Text.of(mdle.getQualifiedName())));
+ subnavLinks.add(getBreadcrumbLink(utils.elementUtils.getModuleOf(packageElement), false));
}
- subnavLinks.add(links.createLink(pathString(packageElement, DocPaths.PACKAGE_SUMMARY),
- getLocalizedPackageName(packageElement), HtmlStyle.currentSelection, ""));
+ subnavLinks.add(getBreadcrumbLink(packageElement, true));
return super.getNavBar(pageMode, element).setSubNavLinks(subnavLinks);
}
diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestModulePackages.java b/test/langtools/jdk/javadoc/doclet/testModules/TestModulePackages.java
index 810d24c672e89..b4367efa9f716 100644
--- a/test/langtools/jdk/javadoc/doclet/testModules/TestModulePackages.java
+++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModulePackages.java
@@ -172,7 +172,7 @@ public void exportSameName(Path base) throws Exception {
>
p
>
- C
+ C
""");
checkOutput("o/p/C.html", true,
@@ -182,7 +182,7 @@ public void exportSameName(Path base) throws Exception {
>
p
>
- C
+ C
""");
checkOutput("type-search-index.js", true,
diff --git a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java
index 157bf956c53be..53cd7e204eb85 100644
--- a/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java
+++ b/test/langtools/jdk/javadoc/doclet/testNavigation/TestNavigation.java
@@ -412,7 +412,7 @@ public void testUnnamedPackage(Path base) throws Exception {
Unnamed Package
>
- C
+ C
""");
}
diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java
index f8f9d80e1e431..76d422eb5a97c 100644
--- a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java
+++ b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2022, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8250768 8261976 8277300 8282452 8287597
+ * @bug 8250768 8261976 8277300 8282452 8287597 8325325
* @summary test generated docs for items declared using preview
* @library ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@@ -77,7 +77,7 @@ public void testPreviewAPIJavadoc() {
checkExit(Exit.OK);
checkOutput("preview-list.html", true,
- """
+ """
Contents
""",
- """
+ """
+
+
+
+
+
+
+
+
+
Test Feature
+
+ """,
+ """
Record Classes
@@ -105,7 +122,7 @@ public void testPreviewAPIJavadoc() {
""",
- """
+ """
Methods
@@ -121,6 +138,24 @@ public void testPreviewAPIJavadoc() {
Returns the value of the i
record component.
""");
+
+ // 8325325: Breadcrumb navigation links should not contain PREVIEW link
+ checkOutput("java.base/preview/package-summary.html", true,
+ """
+
+ java.base
+ >
+ preview
+ """);
+ checkOutput("java.base/preview/Core.html", true,
+ """
+
+ java.base
+ >
+ preview
+ >
+ Core
+ """);
}
@Test
diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/api/preview/package-info.java b/test/langtools/jdk/javadoc/doclet/testPreview/api/preview/package-info.java
new file mode 100644
index 0000000000000..050d5512013da
--- /dev/null
+++ b/test/langtools/jdk/javadoc/doclet/testPreview/api/preview/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+/**
+ * Preview package.
+ */
+@PreviewFeature(feature=Feature.TEST)
+package preview;
+
+import jdk.internal.javac.PreviewFeature;
+import jdk.internal.javac.PreviewFeature.Feature;
From c3c1cdd1b017654469f214c62457cde248474f2f Mon Sep 17 00:00:00 2001
From: Johannes Bechberger
Date: Tue, 13 Feb 2024 12:31:31 +0000
Subject: [PATCH 09/36] 8325731: Installation instructions for Debian/Ubuntu
don't mention autoconf
Reviewed-by: ihse
---
doc/building.html | 2 +-
doc/building.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/building.html b/doc/building.html
index 96d2916de41e4..8a0acada254ac 100644
--- a/doc/building.html
+++ b/doc/building.html
@@ -526,7 +526,7 @@ Linux
The basic tooling is provided as part of the core operating system,
but you will most likely need to install developer packages.
For apt-based distributions (Debian, Ubuntu, etc), try this:
-sudo apt-get install build-essential
+sudo apt-get install build-essential autoconf
For rpm-based distributions (Fedora, Red Hat, etc), try this:
sudo yum groupinstall "Development Tools"
For Alpine Linux, aside from basic tooling, install the GNU versions
diff --git a/doc/building.md b/doc/building.md
index 61daed2270bbe..ed8a06693551d 100644
--- a/doc/building.md
+++ b/doc/building.md
@@ -349,7 +349,7 @@ will most likely need to install developer packages.
For apt-based distributions (Debian, Ubuntu, etc), try this:
```
-sudo apt-get install build-essential
+sudo apt-get install build-essential autoconf
```
For rpm-based distributions (Fedora, Red Hat, etc), try this:
From 71ff2d717798f1f314b97d97dfbc2b859fb47ae3 Mon Sep 17 00:00:00 2001
From: Stefan Karlsson
Date: Tue, 13 Feb 2024 12:59:42 +0000
Subject: [PATCH 10/36] 8325616: JFR ZGC Allocation Stall events should record
stack traces
Reviewed-by: eosterlund, tschatzl, egahlin
---
src/hotspot/share/jfr/metadata/metadata.xml | 2 +-
src/jdk.jfr/share/conf/jfr/default.jfc | 1 +
src/jdk.jfr/share/conf/jfr/profile.jfc | 1 +
3 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml
index 34925674f8aaa..78cd95840b22d 100644
--- a/src/hotspot/share/jfr/metadata/metadata.xml
+++ b/src/hotspot/share/jfr/metadata/metadata.xml
@@ -1138,7 +1138,7 @@
-
+
diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc
index cd6d45bf285b7..1ea936ae20d5d 100644
--- a/src/jdk.jfr/share/conf/jfr/default.jfc
+++ b/src/jdk.jfr/share/conf/jfr/default.jfc
@@ -833,6 +833,7 @@
true
+ true
0 ms
diff --git a/src/jdk.jfr/share/conf/jfr/profile.jfc b/src/jdk.jfr/share/conf/jfr/profile.jfc
index dc9c5c326f26a..0b018d33058ce 100644
--- a/src/jdk.jfr/share/conf/jfr/profile.jfc
+++ b/src/jdk.jfr/share/conf/jfr/profile.jfc
@@ -833,6 +833,7 @@
true
+ true
0 ms
From 7ec2badd2179709819ff4f7c61d9b2da67e13cec Mon Sep 17 00:00:00 2001
From: Albert Mingkun Yang
Date: Tue, 13 Feb 2024 13:22:53 +0000
Subject: [PATCH 11/36] 8323520: Drop unnecessary virtual specifier in Space
Reviewed-by: stefank
---
src/hotspot/share/gc/shared/space.hpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp
index dbfed7fe759f4..41c1d2a0d75cb 100644
--- a/src/hotspot/share/gc/shared/space.hpp
+++ b/src/hotspot/share/gc/shared/space.hpp
@@ -77,8 +77,8 @@ class Space: public CHeapObj {
// Accessors
HeapWord* bottom() const { return _bottom; }
HeapWord* end() const { return _end; }
- virtual void set_bottom(HeapWord* value) { _bottom = value; }
- virtual void set_end(HeapWord* value) { _end = value; }
+ void set_bottom(HeapWord* value) { _bottom = value; }
+ void set_end(HeapWord* value) { _end = value; }
HeapWord* saved_mark_word() const { return _saved_mark_word; }
From 7cd25ed605469e3946a204b7b18d975c9768f2df Mon Sep 17 00:00:00 2001
From: Cesar Soares Lucas
Date: Tue, 13 Feb 2024 13:50:59 +0000
Subject: [PATCH 12/36] 8322854: Incorrect rematerialization of scalar replaced
objects in C2
Reviewed-by: kvn, thartmann
---
src/hotspot/share/opto/macro.cpp | 9 ++-
.../c2/TestReduceAllocationAndMemoryLoop.java | 70 +++++++++++++++++++
2 files changed, 76 insertions(+), 3 deletions(-)
create mode 100644 test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndMemoryLoop.java
diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp
index 262fff7f8e9e6..c2aa017197e9f 100644
--- a/src/hotspot/share/opto/macro.cpp
+++ b/src/hotspot/share/opto/macro.cpp
@@ -167,7 +167,8 @@ void PhaseMacroExpand::eliminate_gc_barrier(Node* p2x) {
// Search for a memory operation for the specified memory slice.
static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_mem, Node *alloc, PhaseGVN *phase) {
Node *orig_mem = mem;
- Node *alloc_mem = alloc->in(TypeFunc::Memory);
+ Node *alloc_mem = alloc->as_Allocate()->proj_out_or_null(TypeFunc::Memory, /*io_use:*/false);
+ assert(alloc_mem != nullptr, "Allocation without a memory projection.");
const TypeOopPtr *tinst = phase->C->get_adr_type(alias_idx)->isa_oopptr();
while (true) {
if (mem == alloc_mem || mem == start_mem ) {
@@ -371,7 +372,8 @@ Node *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *
return nullptr; // Give up: phi tree too deep
}
Node *start_mem = C->start()->proj_out_or_null(TypeFunc::Memory);
- Node *alloc_mem = alloc->in(TypeFunc::Memory);
+ Node *alloc_mem = alloc->proj_out_or_null(TypeFunc::Memory, /*io_use:*/false);
+ assert(alloc_mem != nullptr, "Allocation without a memory projection.");
uint length = mem->req();
GrowableArray values(length, length, nullptr);
@@ -456,7 +458,8 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, Node *sfpt_ctl, BasicType
int offset = adr_t->offset();
Node *start_mem = C->start()->proj_out_or_null(TypeFunc::Memory);
Node *alloc_ctrl = alloc->in(TypeFunc::Control);
- Node *alloc_mem = alloc->in(TypeFunc::Memory);
+ Node *alloc_mem = alloc->proj_out_or_null(TypeFunc::Memory, /*io_use:*/false);
+ assert(alloc_mem != nullptr, "Allocation without a memory projection.");
VectorSet visited;
bool done = sfpt_mem == alloc_mem;
diff --git a/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndMemoryLoop.java b/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndMemoryLoop.java
new file mode 100644
index 0000000000000..765dcee7c5b3c
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/c2/TestReduceAllocationAndMemoryLoop.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.
+ */
+
+/*
+ * @test
+ * @bug 8322854
+ * @summary Check that the RAM optimization works when there is a memory loop.
+ * @library /test/lib /
+ * @requires vm.compiler2.enabled
+ * @run main/othervm -XX:CompileCommand=compileonly,*TestReduceAllocationAndMemoryLoop*::test*
+ * -XX:-TieredCompilation -Xbatch
+ * compiler.c2.TestReduceAllocationAndMemoryLoop
+ */
+
+package compiler.c2;
+
+public class TestReduceAllocationAndMemoryLoop {
+ public static void main(String[] args) throws Exception {
+ // Warmup
+ for (int i = 0; i < 50_000; ++i) {
+ test(false, 10);
+ }
+
+ // Trigger deoptimization
+ MyClass obj = test(false, 11);
+ if (obj.val != 42) {
+ throw new RuntimeException("Test failed, val = " + obj.val);
+ }
+ }
+
+ static class MyClass {
+ final int val;
+
+ public MyClass(int val) {
+ this.val = val;
+ }
+ }
+
+ public static MyClass test(boolean alwaysFalse, int limit) {
+ for (int i = 0; ; ++i) {
+ MyClass obj = new MyClass(42);
+ if (alwaysFalse || i > 10) {
+ return obj;
+ }
+ if (i == limit) {
+ return null;
+ }
+ }
+ }
+}
From 57b04e1b5df9fc3d63e530225039c8522cdf7a41 Mon Sep 17 00:00:00 2001
From: Albert Mingkun Yang
Date: Tue, 13 Feb 2024 15:00:36 +0000
Subject: [PATCH 13/36] 8325748: Serial: Move Generation::promote to
TenuredGeneration
Reviewed-by: stefank
---
src/hotspot/share/gc/serial/generation.cpp | 31 -------------------
src/hotspot/share/gc/serial/generation.hpp | 9 ------
.../share/gc/serial/tenuredGeneration.cpp | 30 ++++++++++++++++++
.../share/gc/serial/tenuredGeneration.hpp | 8 +++++
4 files changed, 38 insertions(+), 40 deletions(-)
diff --git a/src/hotspot/share/gc/serial/generation.cpp b/src/hotspot/share/gc/serial/generation.cpp
index 0d1f6590b7545..c1c195aaf38bd 100644
--- a/src/hotspot/share/gc/serial/generation.cpp
+++ b/src/hotspot/share/gc/serial/generation.cpp
@@ -27,7 +27,6 @@
#include "gc/serial/generation.hpp"
#include "gc/serial/serialHeap.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
-#include "gc/shared/continuationGCSupport.inline.hpp"
#include "gc/shared/gcLocker.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTrace.hpp"
@@ -92,33 +91,3 @@ size_t Generation::max_contiguous_available() const {
}
return MAX2(avail, old_avail);
}
-
-// Ignores "ref" and calls allocate().
-oop Generation::promote(oop obj, size_t obj_size) {
- assert(obj_size == obj->size(), "bad obj_size passed in");
-
-#ifndef PRODUCT
- if (SerialHeap::heap()->promotion_should_fail()) {
- return nullptr;
- }
-#endif // #ifndef PRODUCT
-
- // Allocate new object.
- HeapWord* result = allocate(obj_size, false);
- if (result == nullptr) {
- // Promotion of obj into gen failed. Try to expand and allocate.
- result = expand_and_allocate(obj_size, false);
- if (result == nullptr) {
- return nullptr;
- }
- }
-
- // Copy to new location.
- Copy::aligned_disjoint_words(cast_from_oop(obj), result, obj_size);
- oop new_obj = cast_to_oop(result);
-
- // Transform object if it is a stack chunk.
- ContinuationGCSupport::transform_stack_chunk(new_obj);
-
- return new_obj;
-}
diff --git a/src/hotspot/share/gc/serial/generation.hpp b/src/hotspot/share/gc/serial/generation.hpp
index c64b994d31766..2239046a4e93c 100644
--- a/src/hotspot/share/gc/serial/generation.hpp
+++ b/src/hotspot/share/gc/serial/generation.hpp
@@ -142,15 +142,6 @@ class Generation: public CHeapObj {
// Thread-local allocation buffers
virtual bool supports_tlab_allocation() const { return false; }
- // "obj" is the address of an object in a younger generation. Allocate space
- // for "obj" in the current (or some higher) generation, and copy "obj" into
- // the newly allocated space, if possible, returning the result (or null if
- // the allocation failed).
- //
- // The "obj_size" argument is just obj->size(), passed along so the caller can
- // avoid repeating the virtual call to retrieve it.
- virtual oop promote(oop obj, size_t obj_size);
-
// Returns "true" iff collect() should subsequently be called on this
// this generation. See comment below.
// This is a generic implementation which can be overridden.
diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp
index 954b063336d9c..508ee971c5f7a 100644
--- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp
+++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp
@@ -29,6 +29,7 @@
#include "gc/serial/serialHeap.hpp"
#include "gc/serial/tenuredGeneration.inline.hpp"
#include "gc/shared/collectorCounters.hpp"
+#include "gc/shared/continuationGCSupport.inline.hpp"
#include "gc/shared/gcLocker.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTrace.hpp"
@@ -413,6 +414,35 @@ bool TenuredGeneration::promotion_attempt_is_safe(size_t max_promotion_in_bytes)
return res;
}
+oop TenuredGeneration::promote(oop obj, size_t obj_size) {
+ assert(obj_size == obj->size(), "bad obj_size passed in");
+
+#ifndef PRODUCT
+ if (SerialHeap::heap()->promotion_should_fail()) {
+ return nullptr;
+ }
+#endif // #ifndef PRODUCT
+
+ // Allocate new object.
+ HeapWord* result = allocate(obj_size, false);
+ if (result == nullptr) {
+ // Promotion of obj into gen failed. Try to expand and allocate.
+ result = expand_and_allocate(obj_size, false);
+ if (result == nullptr) {
+ return nullptr;
+ }
+ }
+
+ // Copy to new location.
+ Copy::aligned_disjoint_words(cast_from_oop(obj), result, obj_size);
+ oop new_obj = cast_to_oop(result);
+
+ // Transform object if it is a stack chunk.
+ ContinuationGCSupport::transform_stack_chunk(new_obj);
+
+ return new_obj;
+}
+
void TenuredGeneration::collect(bool full,
bool clear_all_soft_refs,
size_t size,
diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.hpp
index 4e506343113a7..a2461540a3530 100644
--- a/src/hotspot/share/gc/serial/tenuredGeneration.hpp
+++ b/src/hotspot/share/gc/serial/tenuredGeneration.hpp
@@ -160,6 +160,14 @@ class TenuredGeneration: public Generation {
// might be attempted in the worst case.
bool promotion_attempt_is_safe(size_t max_promoted_in_bytes) const;
+ // "obj" is the address of an object in young-gen. Allocate space for "obj"
+ // in the old-gen, and copy "obj" into the newly allocated space, if
+ // possible, returning the result (or null if the allocation failed).
+ //
+ // The "obj_size" argument is just obj->size(), passed along so the caller can
+ // avoid repeating the virtual call to retrieve it.
+ oop promote(oop obj, size_t obj_size);
+
virtual void verify();
virtual void print_on(outputStream* st) const;
};
From 13d9e8ff38536287b82c54bb63bd2d20f65615dc Mon Sep 17 00:00:00 2001
From: Roger Riggs
Date: Tue, 13 Feb 2024 15:16:50 +0000
Subject: [PATCH 14/36] 8325590: Regression in round-tripping UTF-16 strings
after JDK-8311906
Reviewed-by: alanb, redestad
---
.../share/classes/java/lang/String.java | 4 +-
.../java/nio/file/Files/ReadWriteString.java | 40 ++++++++++++++++---
2 files changed, 37 insertions(+), 7 deletions(-)
diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java
index b6e3805653ad4..4ec3e8b6a94eb 100644
--- a/src/java.base/share/classes/java/lang/String.java
+++ b/src/java.base/share/classes/java/lang/String.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -841,7 +841,7 @@ private static String newStringNoRepl1(byte[] src, Charset cs) {
}
if (COMPACT_STRINGS) {
byte[] val = StringUTF16.compress(ca, 0, caLen);
- int coder = StringUTF16.coderFromArrayLen(val, len);
+ byte coder = StringUTF16.coderFromArrayLen(val, caLen);
return new String(val, coder);
}
return new String(StringUTF16.toBytes(ca, 0, caLen), UTF16);
diff --git a/test/jdk/java/nio/file/Files/ReadWriteString.java b/test/jdk/java/nio/file/Files/ReadWriteString.java
index 885cbb771dc26..8b5241fa1cf05 100644
--- a/test/jdk/java/nio/file/Files/ReadWriteString.java
+++ b/test/jdk/java/nio/file/Files/ReadWriteString.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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,8 +29,13 @@
import java.nio.charset.UnmappableCharacterException;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.nio.charset.StandardCharsets.US_ASCII;
-import static java.nio.charset.StandardCharsets.UTF_16;
import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.nio.charset.StandardCharsets.UTF_16;
+import static java.nio.charset.StandardCharsets.UTF_16BE;
+import static java.nio.charset.StandardCharsets.UTF_16LE;
+import static java.nio.charset.StandardCharsets.UTF_32;
+import static java.nio.charset.StandardCharsets.UTF_32BE;
+import static java.nio.charset.StandardCharsets.UTF_32LE;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
@@ -40,15 +45,15 @@
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.Callable;
+import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
-import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/* @test
- * @bug 8201276 8205058 8209576 8287541 8288589
+ * @bug 8201276 8205058 8209576 8287541 8288589 8325590
* @build ReadWriteString PassThroughFileSystem
* @run testng ReadWriteString
* @summary Unit test for methods for Files readString and write methods.
@@ -61,6 +66,7 @@ public class ReadWriteString {
// data for text files
final String TEXT_UNICODE = "\u201CHello\u201D";
final String TEXT_ASCII = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n abcdefghijklmnopqrstuvwxyz\n 1234567890\n";
+ final static String TEXT_PERSON_CART_WHEELING = "\ud83e\udd38";
private static final String JA_STRING = "\u65e5\u672c\u8a9e\u6587\u5b57\u5217";
private static final Charset WINDOWS_1252 = Charset.forName("windows-1252");
private static final Charset WINDOWS_31J = Charset.forName("windows-31j");
@@ -154,7 +160,16 @@ public Object[][] getReadString() {
{testFiles[1], TEXT_ASCII, US_ASCII, US_ASCII},
{testFiles[1], TEXT_ASCII, US_ASCII, UTF_8},
{testFiles[1], TEXT_UNICODE, UTF_8, null},
- {testFiles[1], TEXT_UNICODE, UTF_8, UTF_8}
+ {testFiles[1], TEXT_UNICODE, UTF_8, UTF_8},
+ {testFiles[1], TEXT_ASCII, US_ASCII, ISO_8859_1},
+ {testFiles[1], TEXT_PERSON_CART_WHEELING, UTF_16, UTF_16},
+ {testFiles[1], TEXT_PERSON_CART_WHEELING, UTF_16BE, UTF_16BE},
+ {testFiles[1], TEXT_PERSON_CART_WHEELING, UTF_16LE, UTF_16LE},
+ {testFiles[1], TEXT_PERSON_CART_WHEELING, UTF_32, UTF_32},
+ {testFiles[1], TEXT_PERSON_CART_WHEELING, UTF_32BE, UTF_32BE},
+ {testFiles[1], TEXT_PERSON_CART_WHEELING, UTF_32LE, UTF_32LE},
+ {testFiles[1], TEXT_PERSON_CART_WHEELING, WINDOWS_1252, WINDOWS_1252},
+ {testFiles[1], TEXT_PERSON_CART_WHEELING, WINDOWS_31J, WINDOWS_31J}
};
}
@@ -304,6 +319,21 @@ public void testMalformedReadBytes(byte[] data, Charset csRead, Class c) {
try {
c.call();
From 6b7c9718d68f30f47a163042d6e205945b9ff365 Mon Sep 17 00:00:00 2001
From: Brian Burkhalter
Date: Tue, 13 Feb 2024 15:53:29 +0000
Subject: [PATCH 15/36] 8325382: (fc) FileChannel.transferTo throws IOException
when position equals size
Reviewed-by: alanb
---
.../classes/sun/nio/ch/FileChannelImpl.java | 22 ++++++-------
.../nio/channels/FileChannel/Transfer.java | 33 +++++++++++++++++--
2 files changed, 41 insertions(+), 14 deletions(-)
diff --git a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java
index 2c14fa9687edd..636230d8f38b1 100644
--- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java
+++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.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
@@ -857,20 +857,18 @@ public long transferTo(long position, long count, WritableByteChannel target)
if (position > sz)
return 0;
- // Now position <= sz so remaining >= 0 and
- // remaining == 0 if and only if sz == 0
- long remaining = sz - position;
-
- // Adjust count only if remaining > 0, i.e.,
- // sz > position which means sz > 0
- if (remaining > 0 && remaining < count)
- count = remaining;
-
// System calls supporting fast transfers might not work on files
// which advertise zero size such as those in Linux /proc
if (sz > 0) {
- // Attempt a direct transfer, if the kernel supports it, limiting
- // the number of bytes according to which platform
+ // Now sz > 0 and position <= sz so remaining >= 0 and
+ // remaining == 0 if and only if sz == position
+ long remaining = sz - position;
+
+ if (remaining >= 0 && remaining < count)
+ count = remaining;
+
+ // Attempt a direct transfer, if the kernel supports it,
+ // limiting the number of bytes according to which platform
int icount = (int) Math.min(count, nd.maxDirectTransferSize());
long n;
if ((n = transferToDirect(position, icount, target)) >= 0)
diff --git a/test/jdk/java/nio/channels/FileChannel/Transfer.java b/test/jdk/java/nio/channels/FileChannel/Transfer.java
index 453230fff9598..51adba60b06df 100644
--- a/test/jdk/java/nio/channels/FileChannel/Transfer.java
+++ b/test/jdk/java/nio/channels/FileChannel/Transfer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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 4434723 4482726 4559072 4795550 5081340 5103988 6984545
+ * @bug 4434723 4482726 4559072 4795550 5081340 5103988 6984545 8325382
* @summary Test FileChannel.transferFrom and transferTo (use -Dseed=X to set PRNG seed)
* @library ..
* @library /test/lib
@@ -48,11 +48,13 @@
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
+import java.nio.file.Files;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import jdk.test.lib.RandomFactory;
+import org.testng.Assert;
import org.testng.annotations.Test;
public class Transfer {
@@ -158,6 +160,33 @@ public void testReadableByteChannel() throws Exception {
}
}
+ @Test
+ public void transferToNoThrow() throws IOException { // for bug 8325382
+ File source = File.createTempFile("before", "after");
+ source.deleteOnExit();
+
+ CharSequence csq = "Reality is greater than the sum of its parts.";
+ Files.writeString(source.toPath(), csq);
+ final long length = csq.length();
+ Assert.assertEquals(source.length(), length);
+
+ File target = File.createTempFile("before", "after");
+ target.deleteOnExit();
+
+ try (FileInputStream in = new FileInputStream(source);
+ FileOutputStream out = new FileOutputStream(target);
+ FileChannel chSource = in.getChannel();
+ FileChannel chTarget = out.getChannel()) {
+ // The count of bytes requested to transfer must exceed
+ // FileChannelImpl.MAPPED_TRANSFER_THRESHOLD which is
+ // currently 16384
+ long n = chSource.transferTo(length, 16385, chTarget);
+
+ // At the end of the input so no bytes should be transferred
+ Assert.assertEquals(n, 0);
+ }
+ }
+
@Test
public void xferTest02() throws Exception { // for bug 4482726
byte[] srcData = new byte[5000];
From 6dfa7f39411169c1d4c1aeb3b5d635ad0d625f9b Mon Sep 17 00:00:00 2001
From: Emanuel Peter
Date: Tue, 13 Feb 2024 16:07:41 +0000
Subject: [PATCH 16/36] 8325541: C2 SuperWord: refactor filter / split
Reviewed-by: chagedorn, kvn
---
src/hotspot/share/opto/superword.cpp | 353 +++++++++++++++------------
src/hotspot/share/opto/superword.hpp | 31 ++-
2 files changed, 217 insertions(+), 167 deletions(-)
diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp
index aa1edd01ab19e..eb92f58024c5d 100644
--- a/src/hotspot/share/opto/superword.cpp
+++ b/src/hotspot/share/opto/superword.cpp
@@ -517,15 +517,19 @@ bool SuperWord::SLP_extract() {
return false;
}
- extend_packlist();
+ extend_packset_with_more_pairs_by_following_use_and_def();
- combine_packs();
+ combine_pairs_to_longer_packs();
- filter_packs_for_alignment();
+ split_packs_longer_than_max_vector_size();
+ // Now we only remove packs:
construct_my_pack_map();
-
- filter_packs();
+ filter_packs_for_power_of_2_size();
+ filter_packs_for_mutual_independence();
+ filter_packs_for_alignment();
+ filter_packs_for_implemented();
+ filter_packs_for_profitable();
DEBUG_ONLY(verify_packs();)
@@ -1081,7 +1085,7 @@ bool SuperWord::independent(Node* s1, Node* s2) {
// is the smallest depth of all nodes from the nodes list. Once we have
// traversed all those nodes, and have not found another node from the
// nodes list, we know that all nodes in the nodes list are independent.
-bool SuperWord::mutually_independent(Node_List* nodes) const {
+bool SuperWord::mutually_independent(const Node_List* nodes) const {
ResourceMark rm;
Unique_Node_List worklist;
VectorSet nodes_set;
@@ -1169,9 +1173,8 @@ int SuperWord::data_size(Node* s) {
return bsize;
}
-//------------------------------extend_packlist---------------------------
// Extend packset by following use->def and def->use links from pack members.
-void SuperWord::extend_packlist() {
+void SuperWord::extend_packset_with_more_pairs_by_following_use_and_def() {
bool changed;
do {
packset_sort(_packset.length());
@@ -1192,7 +1195,7 @@ void SuperWord::extend_packlist() {
#ifndef PRODUCT
if (is_trace_superword_packset()) {
- tty->print_cr("\nAfter Superword::extend_packlist");
+ tty->print_cr("\nAfter Superword::extend_packset_with_more_pairs_by_following_use_and_def");
print_packset();
}
#endif
@@ -1478,12 +1481,13 @@ int SuperWord::adjacent_profit(Node* s1, Node* s2) { return 2; }
int SuperWord::pack_cost(int ct) { return ct; }
int SuperWord::unpack_cost(int ct) { return ct; }
-//------------------------------combine_packs---------------------------
// Combine packs A and B with A.last == B.first into A.first..,A.last,B.second,..B.last
-void SuperWord::combine_packs() {
+void SuperWord::combine_pairs_to_longer_packs() {
#ifdef ASSERT
+ assert(!_packset.is_empty(), "packset not empty");
for (int i = 0; i < _packset.length(); i++) {
assert(_packset.at(i) != nullptr, "no nullptr in packset");
+ assert(_packset.at(i)->size() == 2, "all packs are pairs");
}
#endif
@@ -1509,92 +1513,147 @@ void SuperWord::combine_packs() {
}
}
- // Split packs which have size greater then max vector size.
- for (int i = 0; i < _packset.length(); i++) {
- Node_List* p1 = _packset.at(i);
- if (p1 != nullptr) {
- uint max_vlen = max_vector_size_in_def_use_chain(p1->at(0)); // Max elements in vector
- assert(is_power_of_2(max_vlen), "sanity");
- uint psize = p1->size();
- if (!is_power_of_2(psize)) {
- // We currently only support power-of-2 sizes for vectors.
+ // Remove all nullptr from packset
+ compress_packset();
+
+ assert(!_packset.is_empty(), "must have combined some packs");
+
#ifndef PRODUCT
- if (is_trace_superword_rejections()) {
- tty->cr();
- tty->print_cr("WARNING: Removed pack[%d] with size that is not a power of 2:", i);
- print_pack(p1);
- }
+ if (is_trace_superword_packset()) {
+ tty->print_cr("\nAfter Superword::combine_pairs_to_longer_packs");
+ print_packset();
+ }
#endif
- _packset.at_put(i, nullptr);
- continue;
- }
- if (psize > max_vlen) {
- Node_List* pack = new Node_List();
- for (uint j = 0; j < psize; j++) {
- pack->push(p1->at(j));
- if (pack->size() >= max_vlen) {
- assert(is_power_of_2(pack->size()), "sanity");
- _packset.append(pack);
- pack = new Node_List();
- }
- }
- _packset.at_put(i, nullptr);
+}
+
+void SuperWord::split_packs_longer_than_max_vector_size() {
+ assert(!_packset.is_empty(), "packset not empty");
+ DEBUG_ONLY( int old_packset_length = _packset.length(); )
+
+ for (int i = 0; i < _packset.length(); i++) {
+ Node_List* pack = _packset.at(i);
+ assert(pack != nullptr, "no nullptr in packset");
+ uint max_vlen = max_vector_size_in_def_use_chain(pack->at(0));
+ assert(is_power_of_2(max_vlen), "sanity");
+ uint pack_size = pack->size();
+ if (pack_size <= max_vlen) {
+ continue;
+ }
+ // Split off the "upper" nodes into new packs
+ Node_List* new_pack = new Node_List();
+ for (uint j = max_vlen; j < pack_size; j++) {
+ Node* n = pack->at(j);
+ // is new_pack full?
+ if (new_pack->size() >= max_vlen) {
+ assert(is_power_of_2(new_pack->size()), "sanity %d", new_pack->size());
+ _packset.append(new_pack);
+ new_pack = new Node_List();
+ }
+ new_pack->push(n);
+ }
+ // remaining new_pack
+ if (new_pack->size() > 1) {
+ _packset.append(new_pack);
+ } else {
+#ifndef PRODUCT
+ if (is_trace_superword_rejections()) {
+ tty->cr();
+ tty->print_cr("WARNING: Node dropped out of odd size pack:");
+ new_pack->at(0)->dump();
+ print_pack(pack);
}
+#endif
+ }
+ // truncate
+ while (pack->size() > max_vlen) {
+ pack->pop();
}
}
- // We know that the nodes in a pair pack were independent - this gives us independence
- // at distance 1. But now that we may have more than 2 nodes in a pack, we need to check
- // if they are all mutually independent. If there is a dependence we remove the pack.
- // This is better than giving up completely - we can have partial vectorization if some
- // are rejected and others still accepted.
- //
- // Examples with dependence at distance 1 (pack pairs are not created):
- // for (int i ...) { v[i + 1] = v[i] + 5; }
- // for (int i ...) { v[i] = v[i - 1] + 5; }
- //
- // Example with independence at distance 1, but dependence at distance 2 (pack pairs are
- // created and we need to filter them out now):
- // for (int i ...) { v[i + 2] = v[i] + 5; }
- // for (int i ...) { v[i] = v[i - 2] + 5; }
- //
- // Note: dependencies are created when a later load may reference the same memory location
- // as an earlier store. This happens in "read backward" or "store forward" cases. On the
- // other hand, "read forward" or "store backward" cases do not have such dependencies:
- // for (int i ...) { v[i] = v[i + 1] + 5; }
- // for (int i ...) { v[i - 1] = v[i] + 5; }
- for (int i = 0; i < _packset.length(); i++) {
- Node_List* p = _packset.at(i);
- if (p != nullptr) {
- // reductions are trivially connected
- if (!is_marked_reduction(p->at(0)) &&
- !mutually_independent(p)) {
+ assert(old_packset_length <= _packset.length(), "we only increased the number of packs");
+
#ifndef PRODUCT
- if (is_trace_superword_rejections()) {
- tty->cr();
- tty->print_cr("WARNING: Found dependency at distance greater than 1.");
- tty->print_cr("In pack[%d]", i);
- print_pack(p);
- }
+ if (is_trace_superword_packset()) {
+ tty->print_cr("\nAfter Superword::split_packs_longer_than_max_vector_size");
+ print_packset();
+ }
#endif
- _packset.at_put(i, nullptr);
+}
+
+template
+void SuperWord::filter_packs(const char* filter_name,
+ const char* error_message,
+ FilterPredicate filter) {
+ int new_packset_length = 0;
+ for (int i = 0; i < _packset.length(); i++) {
+ Node_List* pack = _packset.at(i);
+ assert(pack != nullptr, "no nullptr in packset");
+ if (filter(pack)) {
+ assert(i >= new_packset_length, "only move packs down");
+ _packset.at_put(new_packset_length++, pack);
+ } else {
+ remove_pack_at(i);
+#ifndef PRODUCT
+ if (is_trace_superword_rejections()) {
+ tty->cr();
+ tty->print_cr("WARNING: Removed pack: %s:", error_message);
+ print_pack(pack);
}
+#endif
}
}
- // Remove all nullptr from packset
- compress_packset();
+ assert(_packset.length() >= new_packset_length, "filter only reduces number of packs");
+ _packset.trunc_to(new_packset_length);
#ifndef PRODUCT
- if (is_trace_superword_packset()) {
- tty->print_cr("\nAfter Superword::combine_packs");
+ if (is_trace_superword_packset() && filter_name != nullptr) {
+ tty->print_cr("\nAfter %s:", filter_name);
print_packset();
}
#endif
}
+void SuperWord::filter_packs_for_power_of_2_size() {
+ filter_packs("SuperWord::filter_packs_for_power_of_2_size",
+ "size is not a power of 2",
+ [&](const Node_List* pack) {
+ return is_power_of_2(pack->size());
+ });
+}
+
+// We know that the nodes in a pair pack were independent - this gives us independence
+// at distance 1. But now that we may have more than 2 nodes in a pack, we need to check
+// if they are all mutually independent. If there is a dependence we remove the pack.
+// This is better than giving up completely - we can have partial vectorization if some
+// are rejected and others still accepted.
+//
+// Examples with dependence at distance 1 (pack pairs are not created):
+// for (int i ...) { v[i + 1] = v[i] + 5; }
+// for (int i ...) { v[i] = v[i - 1] + 5; }
+//
+// Example with independence at distance 1, but dependence at distance 2 (pack pairs are
+// created and we need to filter them out now):
+// for (int i ...) { v[i + 2] = v[i] + 5; }
+// for (int i ...) { v[i] = v[i - 2] + 5; }
+//
+// Note: dependencies are created when a later load may reference the same memory location
+// as an earlier store. This happens in "read backward" or "store forward" cases. On the
+// other hand, "read forward" or "store backward" cases do not have such dependencies:
+// for (int i ...) { v[i] = v[i + 1] + 5; }
+// for (int i ...) { v[i - 1] = v[i] + 5; }
+void SuperWord::filter_packs_for_mutual_independence() {
+ filter_packs("SuperWord::filter_packs_for_mutual_independence",
+ "found dependency between nodes at distance greater than 1",
+ [&](const Node_List* pack) {
+ // reductions are trivially connected
+ return is_marked_reduction(pack->at(0)) ||
+ mutually_independent(pack);
+ });
+}
+
// Find the set of alignment solutions for load/store pack.
-const AlignmentSolution* SuperWord::pack_alignment_solution(Node_List* pack) {
+const AlignmentSolution* SuperWord::pack_alignment_solution(const Node_List* pack) {
assert(pack != nullptr && (pack->at(0)->is_Load() || pack->at(0)->is_Store()), "only load/store packs");
const MemNode* mem_ref = pack->at(0)->as_Mem();
@@ -1638,41 +1697,36 @@ void SuperWord::filter_packs_for_alignment() {
AlignmentSolution const* current = new TrivialAlignmentSolution();
int mem_ops_count = 0;
int mem_ops_rejected = 0;
- for (int i = 0; i < _packset.length(); i++) {
- Node_List* p = _packset.at(i);
- if (p != nullptr) {
- if (p->at(0)->is_Load() || p->at(0)->is_Store()) {
- mem_ops_count++;
- // Find solution for pack p, and filter with current solution.
- const AlignmentSolution* s = pack_alignment_solution(p);
- const AlignmentSolution* intersect = current->filter(s);
-#ifndef PRODUCT
- if (is_trace_align_vector()) {
- tty->print(" solution for pack: ");
- s->print();
- tty->print(" intersection with current: ");
- intersect->print();
- }
-#endif
+ filter_packs("SuperWord::filter_packs_for_alignment",
+ "rejected by AlignVector (strict alignment requirement)",
+ [&](const Node_List* pack) {
+ // Only memops need to be aligned.
+ if (!pack->at(0)->is_Load() &&
+ !pack->at(0)->is_Store()) {
+ return true; // accept all non memops
+ }
+
+ mem_ops_count++;
+ const AlignmentSolution* s = pack_alignment_solution(pack);
+ const AlignmentSolution* intersect = current->filter(s);
- if (intersect->is_empty()) {
- // Solution failed or is not compatible, remove pack i.
#ifndef PRODUCT
- if (is_trace_superword_rejections() || is_trace_align_vector()) {
- tty->print_cr("Rejected by AlignVector:");
- p->at(0)->dump();
- }
+ if (is_trace_align_vector()) {
+ tty->print(" solution for pack: ");
+ s->print();
+ tty->print(" intersection with current: ");
+ intersect->print();
+ }
#endif
- _packset.at_put(i, nullptr);
- mem_ops_rejected++;
- } else {
- // Solution is compatible.
- current = intersect;
- }
- }
- }
- }
+ if (intersect->is_empty()) {
+ mem_ops_rejected++;
+ return false; // reject because of empty solution
+ }
+
+ current = intersect;
+ return true; // accept because of non-empty solution
+ });
#ifndef PRODUCT
if (is_trace_superword_info() || is_trace_align_vector()) {
@@ -1689,16 +1743,6 @@ void SuperWord::filter_packs_for_alignment() {
// -> must change pre-limit to achieve alignment
set_align_to_ref(current->as_constrained()->mem_ref());
}
-
- // Remove all nullptr from packset
- compress_packset();
-
-#ifndef PRODUCT
- if (is_trace_superword_packset() || is_trace_align_vector()) {
- tty->print_cr("\nAfter Superword::filter_packs_for_alignment");
- print_packset();
- }
-#endif
}
// Compress packset, such that it has no nullptr entries
@@ -1716,7 +1760,7 @@ void SuperWord::compress_packset() {
//-----------------------------construct_my_pack_map--------------------------
// Construct the map from nodes to packs. Only valid after the
-// point where a node is only in one pack (after combine_packs).
+// point where a node is only in one pack (after combine_pairs_to_longer_packs).
void SuperWord::construct_my_pack_map() {
for (int i = 0; i < _packset.length(); i++) {
Node_List* p = _packset.at(i);
@@ -1735,23 +1779,22 @@ void SuperWord::construct_my_pack_map() {
}
}
-//------------------------------filter_packs---------------------------
-// Remove packs that are not implemented or not profitable.
-void SuperWord::filter_packs() {
- // Remove packs that are not implemented
- for (int i = _packset.length() - 1; i >= 0; i--) {
- Node_List* pk = _packset.at(i);
- bool impl = implemented(pk);
- if (!impl) {
-#ifndef PRODUCT
- if (is_trace_superword_rejections()) {
- tty->print_cr("Unimplemented");
- pk->at(0)->dump();
- }
-#endif
- remove_pack_at(i);
- }
- Node *n = pk->at(0);
+// Remove packs that are not implemented
+void SuperWord::filter_packs_for_implemented() {
+ filter_packs("SuperWord::filter_packs_for_implemented",
+ "Unimplemented",
+ [&](const Node_List* pack) {
+ return implemented(pack);
+ });
+}
+
+// Remove packs that are not profitable.
+void SuperWord::filter_packs_for_profitable() {
+ // Count the number of reductions vs other vector ops, for the
+ // reduction profitability heuristic.
+ for (int i = 0; i < _packset.length(); i++) {
+ Node_List* pack = _packset.at(i);
+ Node* n = pack->at(0);
if (is_marked_reduction(n)) {
_num_reductions++;
} else {
@@ -1760,28 +1803,22 @@ void SuperWord::filter_packs() {
}
// Remove packs that are not profitable
- bool changed;
- do {
- changed = false;
- for (int i = _packset.length() - 1; i >= 0; i--) {
- Node_List* pk = _packset.at(i);
- bool prof = profitable(pk);
- if (!prof) {
-#ifndef PRODUCT
- if (is_trace_superword_rejections()) {
- tty->print_cr("Unprofitable");
- pk->at(0)->dump();
- }
-#endif
- remove_pack_at(i);
- changed = true;
- }
+ while (true) {
+ int old_packset_length = _packset.length();
+ filter_packs(nullptr, // don't dump each time
+ "size is not a power of 2",
+ [&](const Node_List* pack) {
+ return profitable(pack);
+ });
+ // Repeat until stable
+ if (old_packset_length == _packset.length()) {
+ break;
}
- } while (changed);
+ }
#ifndef PRODUCT
if (is_trace_superword_packset()) {
- tty->print_cr("\nAfter Superword::filter_packs");
+ tty->print_cr("\nAfter Superword::filter_packs_for_profitable");
print_packset();
tty->cr();
}
@@ -1790,7 +1827,7 @@ void SuperWord::filter_packs() {
//------------------------------implemented---------------------------
// Can code be generated for pack p?
-bool SuperWord::implemented(Node_List* p) {
+bool SuperWord::implemented(const Node_List* p) {
bool retValue = false;
Node* p0 = p->at(0);
if (p0 != nullptr) {
@@ -1850,7 +1887,7 @@ bool SuperWord::requires_long_to_int_conversion(int opc) {
//------------------------------same_inputs--------------------------
// For pack p, are all idx operands the same?
-bool SuperWord::same_inputs(Node_List* p, int idx) {
+bool SuperWord::same_inputs(const Node_List* p, int idx) {
Node* p0 = p->at(0);
uint vlen = p->size();
Node* p0_def = p0->in(idx);
@@ -1866,7 +1903,7 @@ bool SuperWord::same_inputs(Node_List* p, int idx) {
//------------------------------profitable---------------------------
// For pack p, are all operands and all uses (with in the block) vector?
-bool SuperWord::profitable(Node_List* p) {
+bool SuperWord::profitable(const Node_List* p) {
Node* p0 = p->at(0);
uint start, end;
VectorNode::vector_operands(p0, &start, &end);
@@ -3329,7 +3366,7 @@ void SuperWord::remove_pack_at(int pos) {
Node* s = p->at(i);
set_my_pack(s, nullptr);
}
- _packset.remove_at(pos);
+ _packset.at_put(pos, nullptr);
}
void SuperWord::packset_sort(int n) {
diff --git a/src/hotspot/share/opto/superword.hpp b/src/hotspot/share/opto/superword.hpp
index 691aa97928a2c..8813284e35140 100644
--- a/src/hotspot/share/opto/superword.hpp
+++ b/src/hotspot/share/opto/superword.hpp
@@ -371,7 +371,7 @@ class SuperWord : public ResourceObj {
// is pack good for converting into one vector node replacing bunches of Cmp, Bool, CMov nodes.
static bool requires_long_to_int_conversion(int opc);
// For pack p, are all idx operands the same?
- bool same_inputs(Node_List* p, int idx);
+ bool same_inputs(const Node_List* p, int idx);
// CloneMap utilities
bool same_origin_idx(Node* a, Node* b) const;
bool same_generation(Node* a, Node* b) const;
@@ -462,7 +462,7 @@ class SuperWord : public ResourceObj {
// Is there no data path from s1 to s2 or s2 to s1?
bool independent(Node* s1, Node* s2);
// Are all nodes in nodes list mutually independent?
- bool mutually_independent(Node_List* nodes) const;
+ bool mutually_independent(const Node_List* nodes) const;
// For a node pair (s1, s2) which is isomorphic and independent,
// do s1 and s2 have similar input edges?
bool have_similar_inputs(Node* s1, Node* s2);
@@ -471,7 +471,7 @@ class SuperWord : public ResourceObj {
void set_alignment(Node* s1, Node* s2, int align);
int data_size(Node* s);
// Extend packset by following use->def and def->use links from pack members.
- void extend_packlist();
+ void extend_packset_with_more_pairs_by_following_use_and_def();
int adjust_alignment_for_type_conversion(Node* s, Node* t, int align);
// Extend the packset by visiting operand definitions of nodes in pack p
bool follow_use_defs(Node_List* p);
@@ -484,18 +484,31 @@ class SuperWord : public ResourceObj {
int adjacent_profit(Node* s1, Node* s2);
int pack_cost(int ct);
int unpack_cost(int ct);
+
// Combine packs A and B with A.last == B.first into A.first..,A.last,B.second,..B.last
- void combine_packs();
+ void combine_pairs_to_longer_packs();
+
+ void split_packs_longer_than_max_vector_size();
+
+ // Filter out packs with various filter predicates
+ template
+ void filter_packs(const char* filter_name,
+ const char* error_message,
+ FilterPredicate filter);
+ void filter_packs_for_power_of_2_size();
+ void filter_packs_for_mutual_independence();
// Ensure all packs are aligned, if AlignVector is on.
void filter_packs_for_alignment();
// Find the set of alignment solutions for load/store pack.
- const AlignmentSolution* pack_alignment_solution(Node_List* pack);
+ const AlignmentSolution* pack_alignment_solution(const Node_List* pack);
// Compress packset, such that it has no nullptr entries.
void compress_packset();
// Construct the map from nodes to packs.
void construct_my_pack_map();
- // Remove packs that are not implemented or not profitable.
- void filter_packs();
+ // Remove packs that are not implemented.
+ void filter_packs_for_implemented();
+ // Remove packs that are not profitable.
+ void filter_packs_for_profitable();
// Verify that for every pack, all nodes are mutually independent.
// Also verify that packset and my_pack are consistent.
DEBUG_ONLY(void verify_packs();)
@@ -509,9 +522,9 @@ class SuperWord : public ResourceObj {
// Create a vector operand for the nodes in pack p for operand: in(opd_idx)
Node* vector_opd(Node_List* p, int opd_idx);
// Can code be generated for pack p?
- bool implemented(Node_List* p);
+ bool implemented(const Node_List* p);
// For pack p, are all operands and all uses (with in the block) vector?
- bool profitable(Node_List* p);
+ bool profitable(const Node_List* p);
// Verify that all uses of packs are also packs, i.e. we do not need extract operations.
DEBUG_ONLY(void verify_no_extract();)
// Is use->in(u_idx) a vector use?
From 74b90aa87e7cfa52ac09bf2e57258d792f740f00 Mon Sep 17 00:00:00 2001
From: Emanuel Peter
Date: Tue, 13 Feb 2024 16:09:09 +0000
Subject: [PATCH 17/36] 8325672: C2: allocate PhaseIdealLoop::_loop_or_ctrl
from C->comp_arena()
Reviewed-by: kvn, chagedorn
---
src/hotspot/share/opto/loopnode.hpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp
index 3b281e0f77de4..b1a0d95ddf266 100644
--- a/src/hotspot/share/opto/loopnode.hpp
+++ b/src/hotspot/share/opto/loopnode.hpp
@@ -1098,6 +1098,7 @@ class PhaseIdealLoop : public PhaseTransform {
// Compute the Ideal Node to Loop mapping
PhaseIdealLoop(PhaseIterGVN& igvn, LoopOptsMode mode) :
PhaseTransform(Ideal_Loop),
+ _loop_or_ctrl(igvn.C->comp_arena()),
_igvn(igvn),
_verify_me(nullptr),
_verify_only(false),
@@ -1112,6 +1113,7 @@ class PhaseIdealLoop : public PhaseTransform {
// or only verify that the graph is valid if verify_me is null.
PhaseIdealLoop(PhaseIterGVN& igvn, const PhaseIdealLoop* verify_me = nullptr) :
PhaseTransform(Ideal_Loop),
+ _loop_or_ctrl(igvn.C->comp_arena()),
_igvn(igvn),
_verify_me(verify_me),
_verify_only(verify_me == nullptr),
From 243fb46157f6674780e54eb5219abf6b757aa2ec Mon Sep 17 00:00:00 2001
From: Doug Simon
Date: Tue, 13 Feb 2024 16:15:00 +0000
Subject: [PATCH 18/36] 8325750: Fix spelling of ForceTranslateFailure help
message
Reviewed-by: thartmann
---
.../share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
index 56c684b5e546c..d6a91a7a9c04b 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
@@ -240,8 +240,8 @@ public enum Option {
"name (a stub) or fully qualified name (an nmethod) contains this option's value as a substring."),
ForceTranslateFailure(String.class, null, "Forces HotSpotJVMCIRuntime.translate to throw an exception in the context " +
"of the peer runtime. The value is a filter that can restrict the forced failure to matching translated " +
- "objects. See HotSpotJVMCIRuntime.postTranslation for more details. This option exists soley to test " +
- "correct handling of translation failure."),
+ "objects. See HotSpotJVMCIRuntime.postTranslation for more details. This option exists solely to test " +
+ "correct handling of translation failures."),
PrintConfig(Boolean.class, false, "Prints VM configuration available via JVMCI."),
AuditHandles(Boolean.class, false, "Record stack trace along with scoped foreign object reference wrappers " +
"to debug issue with a wrapper being used after its scope has closed."),
From 842b895f093e15ecd8aa0153d712f5f81cf1cf67 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eirik=20Bj=C3=B8rsn=C3=B8s?=
Date: Tue, 13 Feb 2024 16:18:50 +0000
Subject: [PATCH 19/36] 8303891: Speed up Zip64SizeTest using a small ZIP64
file 8259866: two java.util tests failed with "IOException: There is not
enough space on the disk"
Reviewed-by: lancea, jpai
---
.../java/util/zip/ZipFile/Zip64SizeTest.java | 209 ++++++++++++------
1 file changed, 137 insertions(+), 72 deletions(-)
diff --git a/test/jdk/java/util/zip/ZipFile/Zip64SizeTest.java b/test/jdk/java/util/zip/ZipFile/Zip64SizeTest.java
index a7afa2681a0c3..ca472aa2aa75c 100644
--- a/test/jdk/java/util/zip/ZipFile/Zip64SizeTest.java
+++ b/test/jdk/java/util/zip/ZipFile/Zip64SizeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2021, 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
@@ -20,117 +20,174 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-import java.io.*;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+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.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
-import static org.testng.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
/**
* @test
- * @bug 8226530
- * @summary ZIP File System tests that leverage DirectoryStream
+ * @bug 8226530 8303891
+ * @summary Verify that ZipFile reads size fields using the Zip64 extra
+ * field when only the 'uncompressed size' field has the ZIP64 "magic value" 0xFFFFFFFF
* @compile Zip64SizeTest.java
- * @run testng Zip64SizeTest
+ * @run junit Zip64SizeTest
*/
public class Zip64SizeTest {
-
- private static final int BUFFER_SIZE = 2048;
// ZIP file to create
- private static final String ZIP_FILE_NAME = "Zip64SizeTest.zip";
- // File that will be created with a size greater than 0xFFFFFFFF
- private static final String LARGE_FILE_NAME = "LargeZipEntry.txt";
- // File that will be created with a size less than 0xFFFFFFFF
- private static final String SMALL_FILE_NAME = "SmallZipEntry.txt";
- // List of files to be added to the ZIP file
- private static final List ZIP_ENTRIES = List.of(LARGE_FILE_NAME,
- SMALL_FILE_NAME);
- private static final long LARGE_FILE_SIZE = 5L * 1024L * 1024L * 1024L; // 5GB
- private static final long SMALL_FILE_SIZE = 0x100000L; // 1024L x 1024L;
+ private static final Path ZIP_FILE = Path.of("Zip64SizeTest.zip");
+ // Contents to write to ZIP entries
+ private static final byte[] CONTENT = "Hello".getBytes(StandardCharsets.UTF_8);
+ // This opaque tag will be ignored by ZipEntry.setExtra0
+ private static final int UNKNOWN_TAG = 0x9902;
+ // Tag used when converting the extra field to a real ZIP64 extra field
+ private static final short ZIP64_TAG = 0x1;
+ // Marker value to indicate that the actual value is stored in the ZIP64 extra field
+ private static final int ZIP64_MAGIC_VALUE = 0xFFFFFFFF;
/**
- * Validate that if the size of a ZIP entry exceeds 0xFFFFFFFF, that the
- * correct size is returned from the ZIP64 Extended information.
- * @throws IOException
+ * Validate that if the 'uncompressed size' of a ZIP CEN header is 0xFFFFFFFF, then the
+ * actual size is retrieved from the corresponding ZIP64 Extended information field.
+ *
+ * @throws IOException if an unexpected IOException occurs
*/
@Test
- private static void validateZipEntrySizes() throws IOException {
- createFiles();
+ public void validateZipEntrySizes() throws IOException {
createZipFile();
System.out.println("Validating Zip Entry Sizes");
- try (ZipFile zip = new ZipFile(ZIP_FILE_NAME)) {
- ZipEntry ze = zip.getEntry(LARGE_FILE_NAME);
+ try (ZipFile zip = new ZipFile(ZIP_FILE.toFile())) {
+ ZipEntry ze = zip.getEntry("first");
System.out.printf("Entry: %s, size= %s%n", ze.getName(), ze.getSize());
- assertTrue(ze.getSize() == LARGE_FILE_SIZE);
- ze = zip.getEntry(SMALL_FILE_NAME);
+ assertEquals(CONTENT.length, ze.getSize());
+ ze = zip.getEntry("second");
System.out.printf("Entry: %s, size= %s%n", ze.getName(), ze.getSize());
- assertTrue(ze.getSize() == SMALL_FILE_SIZE);
-
+ assertEquals(CONTENT.length, ze.getSize());
}
}
/**
- * Delete the files created for use by the test
- * @throws IOException if an error occurs deleting the files
+ * Create a ZIP file with a CEN entry where the 'uncompressed size' is stored in
+ * the ZIP64 field, but the 'compressed size' is in the CEN field. This makes the
+ * ZIP64 data block 8 bytes long, which triggers the regression described in 8226530.
+ *
+ * The CEN entry for the "first" entry will have the following structure:
+ * (Note the CEN 'Uncompressed Length' being 0xFFFFFFFF and the ZIP64
+ * 'Uncompressed Size' being 5)
+ *
+ * 0081 CENTRAL HEADER #1 02014B50
+ * 0085 Created Zip Spec 14 '2.0'
+ * 0086 Created OS 00 'MS-DOS'
+ * [...] Omitted for brevity
+ * 0091 CRC F7D18982
+ * 0095 Compressed Length 00000007
+ * 0099 Uncompressed Length FFFFFFFF
+ * [...] Omitted for brevity
+ * 00AF Filename 'first'
+ * 00B4 Extra ID #0001 0001 'ZIP64'
+ * 00B6 Length 0008
+ * 00B8 Uncompressed Size 0000000000000005
+ *
+ * @throws IOException if an error occurs creating the ZIP File
*/
- private static void deleteFiles() throws IOException {
- Files.deleteIfExists(Path.of(ZIP_FILE_NAME));
- Files.deleteIfExists(Path.of(LARGE_FILE_NAME));
- Files.deleteIfExists(Path.of(SMALL_FILE_NAME));
+ private static void createZipFile() throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (ZipOutputStream zos = new ZipOutputStream(baos)) {
+
+ // The 'first' entry will store 'uncompressed size' in the Zip64 format
+ ZipEntry e1 = new ZipEntry("first");
+
+ // Make an extra field with the correct size for an 8-byte 'uncompressed size'
+ // Zip64 field. Temporarily use the 'unknown' tag 0x9902 to make
+ // ZipEntry.setExtra0 skip parsing this as a Zip64.
+ // See APPNOTE.TXT, 4.6.1 Third Party Mappings
+ byte[] opaqueExtra = createBlankExtra((short) UNKNOWN_TAG, (short) Long.BYTES);
+ e1.setExtra(opaqueExtra);
+
+ zos.putNextEntry(e1);
+ zos.write(CONTENT);
+
+ // A second entry, not in Zip64 format
+ ZipEntry e2 = new ZipEntry("second");
+ zos.putNextEntry(e2);
+ zos.write(CONTENT);
+ }
+
+ byte[] zip = baos.toByteArray();
+
+ // Update the CEN of 'first' to use the Zip64 format
+ updateCENHeaderToZip64(zip);
+ Files.write(ZIP_FILE, zip);
}
/**
- * Create the ZIP file adding an entry whose size exceeds 0xFFFFFFFF
- * @throws IOException if an error occurs creating the ZIP File
+ * Update the CEN entry of the "first" entry to use ZIP64 format for the
+ * 'uncompressed size' field. The updated extra field will have the following
+ * structure:
+ *
+ * 00B4 Extra ID #0001 0001 'ZIP64'
+ * 00B6 Length 0008
+ * 00B8 Uncompressed Size 0000000000000005
+ *
+ * @param zip the ZIP file to update to ZIP64
*/
- private static void createZipFile() throws IOException {
- try (FileOutputStream fos = new FileOutputStream(ZIP_FILE_NAME);
- ZipOutputStream zos = new ZipOutputStream(fos)) {
- System.out.printf("Creating Zip file: %s%n", ZIP_FILE_NAME);
- for (String srcFile : ZIP_ENTRIES) {
- System.out.printf("...Adding Entry: %s%n", srcFile);
- File fileToZip = new File(srcFile);
- try (FileInputStream fis = new FileInputStream(fileToZip)) {
- ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
- zipEntry.setSize(fileToZip.length());
- zos.putNextEntry(zipEntry);
- byte[] bytes = new byte[BUFFER_SIZE];
- int length;
- while ((length = fis.read(bytes)) >= 0) {
- zos.write(bytes, 0, length);
- }
- }
- }
- }
+ private static void updateCENHeaderToZip64(byte[] zip) {
+ ByteBuffer buffer = ByteBuffer.wrap(zip).order(ByteOrder.LITTLE_ENDIAN);
+ // Find the offset of the first CEN header
+ int cenOffset = buffer.getInt(zip.length- ZipFile.ENDHDR + ZipFile.ENDOFF);
+ // Find the offset of the extra field
+ int nlen = buffer.getShort(cenOffset + ZipFile.CENNAM);
+ int extraOffset = cenOffset + ZipFile.CENHDR + nlen;
+
+ // Change the header ID from 'unknown' to ZIP64
+ buffer.putShort(extraOffset, ZIP64_TAG);
+ // Update the 'uncompressed size' ZIP64 value to the actual uncompressed length
+ int fieldOffset = extraOffset
+ + Short.BYTES // TAG
+ + Short.BYTES; // data size
+ buffer.putLong(fieldOffset, CONTENT.length);
+
+ // Set the 'uncompressed size' field of the CEN to 0xFFFFFFFF
+ buffer.putInt(cenOffset + ZipFile.CENLEN, ZIP64_MAGIC_VALUE);
}
/**
- * Create the files that will be added to the ZIP file
- * @throws IOException if there is a problem creating the files
+ * Create an extra field with the given tag and data block size, and a
+ * blank data block.
+ * @return an extra field with the specified tag and size
+ * @param tag the header id of the extra field
+ * @param blockSize the size of the extra field's data block
*/
- private static void createFiles() throws IOException {
- try (RandomAccessFile largeFile = new RandomAccessFile(LARGE_FILE_NAME, "rw");
- RandomAccessFile smallFile = new RandomAccessFile(SMALL_FILE_NAME, "rw")) {
- System.out.printf("Creating %s%n", LARGE_FILE_NAME);
- largeFile.setLength(LARGE_FILE_SIZE);
- System.out.printf("Creating %s%n", SMALL_FILE_NAME);
- smallFile.setLength(SMALL_FILE_SIZE);
- }
+ private static byte[] createBlankExtra(short tag, short blockSize) {
+ int size = Short.BYTES // tag
+ + Short.BYTES // data block size
+ + blockSize; // data block;
+
+ byte[] extra = new byte[size];
+ ByteBuffer.wrap(extra).order(ByteOrder.LITTLE_ENDIAN)
+ .putShort(0, tag)
+ .putShort(Short.BYTES, blockSize);
+ return extra;
}
/**
* Make sure the needed test files do not exist prior to executing the test
* @throws IOException
*/
- @BeforeMethod
+ @BeforeEach
public void setUp() throws IOException {
deleteFiles();
}
@@ -139,8 +196,16 @@ public void setUp() throws IOException {
* Remove the files created for the test
* @throws IOException
*/
- @AfterMethod
+ @AfterEach
public void tearDown() throws IOException {
deleteFiles();
}
+
+ /**
+ * Delete the files created for use by the test
+ * @throws IOException if an error occurs deleting the files
+ */
+ private static void deleteFiles() throws IOException {
+ Files.deleteIfExists(ZIP_FILE);
+ }
}
From 628cd8a489fd54db18204c3bbaf4339d7ab5e9d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Eirik=20Bj=C3=B8rsn=C3=B8s?=
Date: Tue, 13 Feb 2024 16:26:37 +0000
Subject: [PATCH 20/36] 8303866: Allow ZipInputStream.readEnd to parse small
Zip64 ZIP files
Reviewed-by: lancea, jpai
---
.../classes/java/util/zip/ZipInputStream.java | 62 +++-
.../ZipInputStream/Zip64DataDescriptor.java | 282 ++++++++++++++++++
2 files changed, 341 insertions(+), 3 deletions(-)
create mode 100644 test/jdk/java/util/zip/ZipInputStream/Zip64DataDescriptor.java
diff --git a/src/java.base/share/classes/java/util/zip/ZipInputStream.java b/src/java.base/share/classes/java/util/zip/ZipInputStream.java
index 216a914f023da..89fe159d5754c 100644
--- a/src/java.base/share/classes/java/util/zip/ZipInputStream.java
+++ b/src/java.base/share/classes/java/util/zip/ZipInputStream.java
@@ -92,6 +92,9 @@ public class ZipInputStream extends InflaterInputStream implements ZipConstants
private ZipCoder zc;
+ // Flag to indicate readEnd should expect 64 bit Data Descriptor size fields
+ private boolean expect64BitDataDescriptor;
+
/**
* Check to make sure that this stream has not been closed
*/
@@ -521,6 +524,13 @@ private ZipEntry readLOC() throws IOException {
}
e.method = get16(tmpbuf, LOCHOW);
e.xdostime = get32(tmpbuf, LOCTIM);
+
+ // Expect 32-bit Data Descriptor size fields by default
+ expect64BitDataDescriptor = false;
+
+ long csize = get32(tmpbuf, LOCSIZ);
+ long size = get32(tmpbuf, LOCLEN);
+
if ((flag & 8) == 8) {
/* "Data Descriptor" present */
if (e.method != DEFLATED) {
@@ -529,8 +539,8 @@ private ZipEntry readLOC() throws IOException {
}
} else {
e.crc = get32(tmpbuf, LOCCRC);
- e.csize = get32(tmpbuf, LOCSIZ);
- e.size = get32(tmpbuf, LOCLEN);
+ e.csize = csize;
+ e.size = size;
}
len = get16(tmpbuf, LOCEXT);
if (len > 0) {
@@ -538,6 +548,8 @@ private ZipEntry readLOC() throws IOException {
readFully(extra, 0, len);
e.setExtra0(extra,
e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL, true);
+ // Determine if readEnd should expect 64-bit size fields in the Data Descriptor
+ expect64BitDataDescriptor = expect64BitDataDescriptor(extra, flag, csize, size);
}
return e;
}
@@ -577,7 +589,8 @@ private void readEnd(ZipEntry e) throws IOException {
if ((flag & 8) == 8) {
/* "Data Descriptor" present */
if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
- inf.getBytesRead() > ZIP64_MAGICVAL) {
+ inf.getBytesRead() > ZIP64_MAGICVAL ||
+ expect64BitDataDescriptor) {
// ZIP64 format
readFully(tmpbuf, 0, ZIP64_EXTHDR);
long sig = get32(tmpbuf, 0);
@@ -625,6 +638,49 @@ private void readEnd(ZipEntry e) throws IOException {
}
}
+ /**
+ * Determine whether the {@link #readEnd(ZipEntry)} method should interpret the
+ * 'compressed size' and 'uncompressed size' fields of the Data Descriptor record
+ * as 64-bit numbers instead of the regular 32-bit numbers.
+ *
+ * Returns true if the LOC has the 'streaming mode' flag set, at least one of the
+ * 'compressed size' and 'uncompressed size' are set to the Zip64 magic value
+ * 0xFFFFFFFF, and the LOC's extra field contains a Zip64 Extended Information Field.
+ *
+ * @param extra the LOC extra field to look for a Zip64 field in
+ * @param flag the value of the 'general purpose bit flag' field in the LOC
+ * @param csize the value of the 'compressed size' field in the LOC
+ * @param size the value of the 'uncompressed size' field in the LOC
+ */
+ private boolean expect64BitDataDescriptor(byte[] extra, int flag, long csize, long size) {
+ // The LOC's 'general purpose bit flag' 3 must indicate use of a Data Descriptor
+ if ((flag & 8) == 0) {
+ return false;
+ }
+
+ // At least one LOC size field must be marked for Zip64
+ if (csize != ZIP64_MAGICVAL && size != ZIP64_MAGICVAL) {
+ return false;
+ }
+
+ // Look for a Zip64 field
+ int headerSize = 2 * Short.BYTES; // id + size
+ if (extra != null) {
+ for (int i = 0; i + headerSize < extra.length;) {
+ int id = get16(extra, i);
+ int dsize = get16(extra, i + Short.BYTES);
+ if (i + headerSize + dsize > extra.length) {
+ return false; // Invalid size
+ }
+ if (id == ZIP64_EXTID) {
+ return true;
+ }
+ i += headerSize + dsize;
+ }
+ }
+ return false;
+ }
+
/*
* Reads bytes, blocking until all bytes are read.
*/
diff --git a/test/jdk/java/util/zip/ZipInputStream/Zip64DataDescriptor.java b/test/jdk/java/util/zip/ZipInputStream/Zip64DataDescriptor.java
new file mode 100644
index 0000000000000..3581561008424
--- /dev/null
+++ b/test/jdk/java/util/zip/ZipInputStream/Zip64DataDescriptor.java
@@ -0,0 +1,282 @@
+/*
+ * 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 8303866
+ * @summary ZipInputStream should read 8-byte data descriptors if the LOC has
+ * a ZIP64 extended information extra field
+ * @run junit Zip64DataDescriptor
+ */
+
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeEach;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
+import java.util.HexFormat;
+import java.util.zip.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class Zip64DataDescriptor {
+
+ // A byte array holding a small-sized Zip64 ZIP file, described below
+ private byte[] zip64File;
+
+ // A byte array holding a ZIP used for testing invalid Zip64 extra fields
+ private byte[] invalidZip64;
+
+ @BeforeEach
+ public void setup() throws IOException {
+ /*
+ * Structure of the ZIP64 file used below . Note the presence
+ * of a Zip64 extended information extra field and the
+ * Data Descriptor having 8-byte values for csize and size.
+ *
+ * The file was produced using the zip command on MacOS
+ * (zip 3.0, by Info-ZIP), in streamming mode (to enable Zip64),
+ * using the -fd option (to force the use of data descriptors)
+ *
+ * The following command was used:
+ * echo hello | zip -fd > hello.zip
+ *
+ * ------ Local File Header ------
+ * 000000 signature 0x04034b50
+ * 000004 version 45
+ * 000006 flags 0x0008
+ * 000008 method 8 Deflated
+ * 000010 time 0xb180 22:12
+ * 000012 date 0x565c 2023-02-28
+ * 000014 crc 0x00000000
+ * 000018 csize -1
+ * 000022 size -1
+ * 000026 nlen 1
+ * 000028 elen 20
+ * 000030 name 1 bytes '-'
+ * 000031 ext id 0x0001 Zip64 extended information extra field
+ * 000033 ext size 16
+ * 000035 z64 size 0
+ * 000043 z64 csize 0
+ *
+ * ------ File Data ------
+ * 000051 data 8 bytes
+ *
+ * ------ Data Desciptor ------
+ * 000059 signature 0x08074b50
+ * 000063 crc 0x363a3020
+ * 000067 csize 8
+ * 000075 size 6
+ * 000083 ...
+ */
+
+ String hex = """
+ 504b03042d000800080080b15c5600000000ffffffffffffffff01001400
+ 2d0100100000000000000000000000000000000000cb48cdc9c9e7020050
+ 4b070820303a3608000000000000000600000000000000504b01021e032d
+ 000800080080b15c5620303a360800000006000000010000000000000001
+ 000000b011000000002d504b050600000000010001002f00000053000000
+ 0000""";
+
+ zip64File = HexFormat.of().parseHex(hex.replaceAll("\n", ""));
+
+ // Create the ZIP file used for testing that invalid Zip64 extra fields are ignored
+ // This ZIP has the regular 4-bit data descriptor
+
+ byte[] extra = new byte[Long.BYTES + Long.BYTES + Short.BYTES * 2]; // Size of a regular Zip64 extra field
+ ByteBuffer buffer = ByteBuffer.wrap(extra).order(ByteOrder.LITTLE_ENDIAN);
+ buffer.putShort(0, (short) 123); // Not processed by ZipEntry.setExtra
+ buffer.putShort(Short.BYTES, (short) (extra.length - 4));
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (ZipOutputStream zo = new ZipOutputStream(baos)) {
+ ZipEntry ze = new ZipEntry("-");
+ ze.setExtra(extra);
+ zo.putNextEntry(ze);
+ zo.write("hello\n".getBytes(StandardCharsets.UTF_8));
+ }
+
+ invalidZip64 = baos.toByteArray();
+
+ // Set Zip64 magic values on compressed and uncompressed size fields
+ ByteBuffer.wrap(invalidZip64).order(ByteOrder.LITTLE_ENDIAN)
+ .putInt(ZipFile.LOCSIZ, 0xFFFFFFFF)
+ .putInt(ZipFile.LOCLEN, 0xFFFFFFFF);
+
+ // Set the Zip64 header ID 0x1 on the extra field in the invalid file
+ setExtraHeaderId((short) 0x1);
+ }
+
+ /*
+ * Verify that small-sized Zip64 entries can be parsed by ZipInputStream
+ */
+ @Test
+ public void shouldReadZip64Descriptor() throws IOException {
+ readZipInputStream(zip64File);
+ }
+
+ /*
+ * For maximal backward compatibility when reading Zip64 descriptors, invalid
+ * Zip64 extra data sizes should be ignored
+ */
+ @Test
+ public void shouldIgnoreInvalidExtraSize() throws IOException {
+ setExtraSize((short) 42);
+ readZipInputStream(invalidZip64);
+ }
+
+ /*
+ * Files with Zip64 magic values but no Zip64 field should be ignored
+ * when considering 8 byte data descriptors
+ */
+ @Test
+ public void shouldIgnoreNoZip64Header() throws IOException {
+ setExtraSize((short) 123);
+ readZipInputStream(invalidZip64);
+ }
+
+ /*
+ * Theoretically, ZIP files may exist with ZIP64 format, but with 4-byte
+ * data descriptors. Such files will fail to parse, as demonstrated by this test.
+ */
+ @Test
+ public void shouldFailParsingZip64With4ByteDataDescriptor() throws IOException {
+ ZipException ex = assertThrows(ZipException.class, () -> {
+ readZipInputStream(invalidZip64);
+ });
+
+ String msg = String.format("Expected exeption message to contain 'invalid entry size', was %s",
+ ex.getMessage());
+ assertTrue(ex.getMessage().contains("invalid entry size"), msg);
+ }
+
+ /*
+ * Validate that an extra data size exceeding the length of the extra field is ignored
+ */
+ @Test
+ public void shouldIgnoreExcessiveExtraSize() throws IOException {
+
+ setExtraSize(Short.MAX_VALUE);
+
+
+ readZipInputStream(invalidZip64);
+ }
+
+ /*
+ * Validate that the Data Descriptor is read with 32-bit fields if neither the
+ * LOC's 'uncompressed size' or 'compressed size' fields have the Zip64 magic value,
+ * even when there is a Zip64 field in the extra field.
+ */
+ @Test
+ public void shouldIgnoreNoMagicMarkers() throws IOException {
+ // Set compressed and uncompressed size fields to zero
+ ByteBuffer.wrap(invalidZip64).order(ByteOrder.LITTLE_ENDIAN)
+ .putInt(ZipFile.LOCSIZ, 0)
+ .putInt(ZipFile.LOCLEN, 0);
+
+
+ readZipInputStream(invalidZip64);
+ }
+
+ /*
+ * Validate that an extra data size exceeding the length of the extra field is ignored
+ */
+ @Test
+ public void shouldIgnoreTrucatedZip64Extra() throws IOException {
+
+ truncateZip64();
+
+ readZipInputStream(invalidZip64);
+ }
+
+ /**
+ * Update the Extra field header ID of the invalid file
+ */
+ private void setExtraHeaderId(short id) {
+ // Set the header ID on the extra field
+ ByteBuffer buffer = ByteBuffer.wrap(invalidZip64).order(ByteOrder.LITTLE_ENDIAN);
+ int nlen = buffer.getShort(ZipFile.LOCNAM);
+ buffer.putShort(ZipFile.LOCHDR + nlen, id);
+ }
+
+ /**
+ * Updates the 16-bit 'data size' field of the Zip64 extended information field,
+ * potentially to an invalid value.
+ * @param size the value to set in the 'data size' field.
+ */
+ private void setExtraSize(short size) {
+ ByteBuffer buffer = ByteBuffer.wrap(invalidZip64).order(ByteOrder.LITTLE_ENDIAN);
+ // Compute the offset to the Zip64 data block size field
+ short nlen = buffer.getShort(ZipFile.LOCNAM);
+ int dataSizeOffset = ZipFile.LOCHDR + nlen + Short.BYTES;
+ buffer.putShort(dataSizeOffset, size);
+ }
+
+ /**
+ * Puts a truncated Zip64 field (just the tag) at the end of the LOC extra field.
+ * The beginning of the extra field is filled with a generic extra field containing
+ * just zeros.
+ */
+ private void truncateZip64() {
+ ByteBuffer buffer = ByteBuffer.wrap(invalidZip64).order(ByteOrder.LITTLE_ENDIAN);
+ // Get the LOC name and extra sizes
+ short nlen = buffer.getShort(ZipFile.LOCNAM);
+ short elen = buffer.getShort(ZipFile.LOCEXT);
+ int cenOffset = ZipFile.LOCHDR + nlen + elen;
+
+ // Zero out the extra field
+ int estart = ZipFile.LOCHDR + nlen;
+ buffer.put(estart, new byte[elen]);
+ // Put a generic extra field in the start
+ buffer.putShort(estart, (short) 42);
+ buffer.putShort(estart + Short.BYTES, (short) (elen - 4 - 2));
+ // Put a truncated (just the tag) Zip64 field at the end
+ buffer.putShort(cenOffset - Short.BYTES, (short) 0x0001);
+ }
+
+ /*
+ * Consume and verify the ZIP file using ZipInputStream
+ */
+ private void readZipInputStream(byte[] zip) throws IOException {
+ try (ZipInputStream in = new ZipInputStream(new ByteArrayInputStream(zip))) {
+ // Read the ZIP entry, this calls readLOC
+ ZipEntry e = in.getNextEntry();
+
+ // Sanity check the zip entry
+ assertNotNull(e, "Missing zip entry");
+ assertEquals("-", e.getName());
+
+ // Read the entry data, this causes readEND to parse the data descriptor
+ assertEquals("hello\n", new String(in.readAllBytes(), StandardCharsets.UTF_8));
+
+ // There should only be a single zip entry
+ assertNull(in.getNextEntry(), "Unexpected additional zip entry");
+ }
+ }
+}
From 8765b176f97dbf334836f0aa6acd921d114304a9 Mon Sep 17 00:00:00 2001
From: Mikael Vidstedt
Date: Tue, 13 Feb 2024 21:23:39 +0000
Subject: [PATCH 21/36] 8325800: Drop unused cups declaration from Oracle build
configuration
Reviewed-by: erikj
---
make/conf/jib-profiles.js | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js
index 45a1e6528b358..af164624877a4 100644
--- a/make/conf/jib-profiles.js
+++ b/make/conf/jib-profiles.js
@@ -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
@@ -1181,12 +1181,6 @@ var getJibProfilesDependencies = function (input, common) {
revision: (input.build_cpu == "x64" ? "Xcode11.3.1-MacOSX10.15+1.2" : devkit_platform_revisions[devkit_platform])
},
- cups: {
- organization: common.organization,
- ext: "tar.gz",
- revision: "1.0118+1.0"
- },
-
jtreg: {
server: "jpg",
product: "jtreg",
From ea4193222f36b0663a8bcbf45db86def9e645945 Mon Sep 17 00:00:00 2001
From: Dmitry Cherepanov
Date: Wed, 14 Feb 2024 05:30:08 +0000
Subject: [PATCH 22/36] 8325395: Missing copyright header in StackFilter.java
Reviewed-by: egahlin
---
.../classes/jdk/jfr/events/StackFilter.java | 25 +++++++++++++++++++
.../jfr/internal/test/DeprecatedMethods.java | 4 ++-
.../jfr/internal/test/DeprecatedThing.java | 4 ++-
3 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/StackFilter.java b/src/jdk.jfr/share/classes/jdk/jfr/events/StackFilter.java
index f0c6a45bf836f..da9cac8a3945c 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/StackFilter.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/StackFilter.java
@@ -1,3 +1,28 @@
+/*
+ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
package jdk.jfr.events;
import java.lang.annotation.ElementType;
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedMethods.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedMethods.java
index 1d2973b4266da..7e425b3bdb5a9 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedMethods.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedMethods.java
@@ -4,7 +4,9 @@
*
* 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.
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedThing.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedThing.java
index dbc869c1c6ccc..6d607557caf30 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedThing.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/test/DeprecatedThing.java
@@ -4,7 +4,9 @@
*
* 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.
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
From 7f6bb71eb302e8388c959bdaa914b758a766d299 Mon Sep 17 00:00:00 2001
From: Axel Boldt-Christmas
Date: Wed, 14 Feb 2024 07:18:06 +0000
Subject: [PATCH 23/36] 8319799: Recursive lightweight locking: x86
implementation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Stefan Karlsson
Co-authored-by: Erik Österlund
Reviewed-by: rkennke, coleenp, dcubed
---
src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp | 20 +-
src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp | 82 +++--
src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 286 ++++++++++++++++--
src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp | 4 +
src/hotspot/cpu/x86/interp_masm_x86.cpp | 21 +-
src/hotspot/cpu/x86/macroAssembler_x86.cpp | 146 ++++++---
src/hotspot/cpu/x86/macroAssembler_x86.hpp | 6 +-
src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp | 8 +-
src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 8 +-
src/hotspot/cpu/x86/vm_version_x86.hpp | 6 +-
src/hotspot/cpu/x86/x86_32.ad | 29 +-
src/hotspot/cpu/x86/x86_64.ad | 27 +-
src/hotspot/share/opto/c2_CodeStubs.hpp | 22 +-
13 files changed, 526 insertions(+), 139 deletions(-)
diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
index 78361a305aeeb..5e98b2d3af4ac 100644
--- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.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
@@ -34,10 +34,12 @@
#include "oops/arrayOop.hpp"
#include "oops/markWord.hpp"
#include "runtime/basicLock.hpp"
+#include "runtime/globals.hpp"
#include "runtime/os.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/checkedCast.hpp"
+#include "utilities/globalDefinitions.hpp"
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register tmp, Label& slow_case) {
const int aligned_mask = BytesPerWord -1;
@@ -60,9 +62,6 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
jcc(Assembler::notZero, slow_case);
}
- // Load object header
- movptr(hdr, Address(obj, hdr_offset));
-
if (LockingMode == LM_LIGHTWEIGHT) {
#ifdef _LP64
const Register thread = r15_thread;
@@ -73,6 +72,8 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr
lightweight_lock(obj, hdr, thread, tmp, slow_case);
} else if (LockingMode == LM_LEGACY) {
Label done;
+ // Load object header
+ movptr(hdr, Address(obj, hdr_offset));
// and mark it as unlocked
orptr(hdr, markWord::unlocked_value);
// save unlocked object header into the displaced header location on the stack
@@ -134,9 +135,14 @@ void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_
verify_oop(obj);
if (LockingMode == LM_LIGHTWEIGHT) {
- movptr(disp_hdr, Address(obj, hdr_offset));
- andptr(disp_hdr, ~(int32_t)markWord::lock_mask_in_place);
- lightweight_unlock(obj, disp_hdr, hdr, slow_case);
+#ifdef _LP64
+ lightweight_unlock(obj, disp_hdr, r15_thread, hdr, slow_case);
+#else
+ // This relies on the implementation of lightweight_unlock being able to handle
+ // that the reg_rax and thread Register parameters may alias each other.
+ get_thread(disp_hdr);
+ lightweight_unlock(obj, disp_hdr, disp_hdr, hdr, slow_case);
+#endif
} else if (LockingMode == LM_LEGACY) {
// test if object header is pointing to the displaced header, and if so, restore
// the displaced header in the object - if the object header is not pointing to
diff --git a/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp
index b9b4e8af02c5f..6dc8d14064ad2 100644
--- a/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp
+++ b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -73,26 +73,74 @@ void C2EntryBarrierStub::emit(C2_MacroAssembler& masm) {
__ jmp(continuation(), false /* maybe_short */);
}
-#ifdef _LP64
-int C2HandleAnonOMOwnerStub::max_size() const {
- // Max size of stub has been determined by testing with 0, in which case
- // C2CodeStubList::emit() will throw an assertion and report the actual size that
- // is needed.
- return DEBUG_ONLY(36) NOT_DEBUG(21);
+int C2FastUnlockLightweightStub::max_size() const {
+ return 128;
}
-void C2HandleAnonOMOwnerStub::emit(C2_MacroAssembler& masm) {
- __ bind(entry());
- Register mon = monitor();
- Register t = tmp();
- __ movptr(Address(mon, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), r15_thread);
- __ subl(Address(r15_thread, JavaThread::lock_stack_top_offset()), oopSize);
+void C2FastUnlockLightweightStub::emit(C2_MacroAssembler& masm) {
+ assert(_t == rax, "must be");
+
+ Label restore_held_monitor_count_and_slow_path;
+
+ { // Restore lock-stack and handle the unlock in runtime.
+
+ __ bind(_push_and_slow_path);
#ifdef ASSERT
- __ movl(t, Address(r15_thread, JavaThread::lock_stack_top_offset()));
- __ movptr(Address(r15_thread, t), 0);
+ // The obj was only cleared in debug.
+ __ movl(_t, Address(_thread, JavaThread::lock_stack_top_offset()));
+ __ movptr(Address(_thread, _t), _obj);
#endif
- __ jmp(continuation());
-}
+ __ addl(Address(_thread, JavaThread::lock_stack_top_offset()), oopSize);
+ }
+
+ { // Restore held monitor count and slow path.
+
+ __ bind(restore_held_monitor_count_and_slow_path);
+ // Restore held monitor count.
+ __ increment(Address(_thread, JavaThread::held_monitor_count_offset()));
+ // increment will always result in ZF = 0 (no overflows).
+ __ jmp(slow_path_continuation());
+ }
+
+ { // Handle monitor medium path.
+
+ __ bind(_check_successor);
+
+ Label fix_zf_and_unlocked;
+ const Register monitor = _mark;
+
+#ifndef _LP64
+ __ jmpb(restore_held_monitor_count_and_slow_path);
+#else // _LP64
+ // successor null check.
+ __ cmpptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), NULL_WORD);
+ __ jccb(Assembler::equal, restore_held_monitor_count_and_slow_path);
+
+ // Release lock.
+ __ movptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD);
+
+ // Fence.
+ // Instead of MFENCE we use a dummy locked add of 0 to the top-of-stack.
+ __ lock(); __ addl(Address(rsp, 0), 0);
+
+ // Recheck successor.
+ __ cmpptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), NULL_WORD);
+ // Observed a successor after the release -> fence we have handed off the monitor
+ __ jccb(Assembler::notEqual, fix_zf_and_unlocked);
+
+ // Try to relock, if it fails the monitor has been handed over
+ // TODO: Caveat, this may fail due to deflation, which does
+ // not handle the monitor handoff. Currently only works
+ // due to the responsible thread.
+ __ xorptr(rax, rax);
+ __ lock(); __ cmpxchgptr(_thread, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
+ __ jccb (Assembler::equal, restore_held_monitor_count_and_slow_path);
#endif
+ __ bind(fix_zf_and_unlocked);
+ __ xorl(rax, rax);
+ __ jmp(unlocked_continuation());
+ }
+}
+
#undef __
diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
index 7512a366e7ea0..b6ecde62af655 100644
--- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
@@ -33,9 +33,13 @@
#include "opto/output.hpp"
#include "opto/opcodes.hpp"
#include "opto/subnode.hpp"
+#include "runtime/globals.hpp"
#include "runtime/objectMonitor.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/checkedCast.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/powerOfTwo.hpp"
+#include "utilities/sizes.hpp"
#ifdef PRODUCT
#define BLOCK_COMMENT(str) /* nothing */
@@ -554,6 +558,7 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp
RTMLockingCounters* stack_rtm_counters,
Metadata* method_data,
bool use_rtm, bool profile_rtm) {
+ assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_lock_lightweight");
// Ensure the register assignments are disjoint
assert(tmpReg == rax, "");
@@ -605,7 +610,8 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp
if (LockingMode == LM_MONITOR) {
// Clear ZF so that we take the slow path at the DONE label. objReg is known to be not 0.
testptr(objReg, objReg);
- } else if (LockingMode == LM_LEGACY) {
+ } else {
+ assert(LockingMode == LM_LEGACY, "must be");
// Attempt stack-locking ...
orptr (tmpReg, markWord::unlocked_value);
movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS
@@ -620,10 +626,6 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp
// Next instruction set ZFlag == 1 (Success) if difference is less then one page.
andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - (int)os::vm_page_size())) );
movptr(Address(boxReg, 0), tmpReg);
- } else {
- assert(LockingMode == LM_LIGHTWEIGHT, "");
- lightweight_lock(objReg, tmpReg, thread, scrReg, NO_COUNT);
- jmp(COUNT);
}
jmp(DONE_LABEL);
@@ -754,6 +756,7 @@ void C2_MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmp
// Xcheck:jni is enabled.
void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg, bool use_rtm) {
+ assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_unlock_lightweight");
assert(boxReg == rax, "");
assert_different_registers(objReg, boxReg, tmpReg);
@@ -784,23 +787,6 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t
}
// It's inflated.
- if (LockingMode == LM_LIGHTWEIGHT) {
- // If the owner is ANONYMOUS, we need to fix it - in an outline stub.
- testb(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), (int32_t) ObjectMonitor::ANONYMOUS_OWNER);
-#ifdef _LP64
- if (!Compile::current()->output()->in_scratch_emit_size()) {
- C2HandleAnonOMOwnerStub* stub = new (Compile::current()->comp_arena()) C2HandleAnonOMOwnerStub(tmpReg, boxReg);
- Compile::current()->output()->add_stub(stub);
- jcc(Assembler::notEqual, stub->entry());
- bind(stub->continuation());
- } else
-#endif
- {
- // We can't easily implement this optimization on 32 bit because we don't have a thread register.
- // Call the slow-path instead.
- jcc(Assembler::notEqual, NO_COUNT);
- }
- }
#if INCLUDE_RTM_OPT
if (use_rtm) {
@@ -922,19 +908,14 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t
jmpb (DONE_LABEL);
#endif
- if (LockingMode != LM_MONITOR) {
+ if (LockingMode == LM_LEGACY) {
bind (Stacked);
- if (LockingMode == LM_LIGHTWEIGHT) {
- mov(boxReg, tmpReg);
- lightweight_unlock(objReg, boxReg, tmpReg, NO_COUNT);
- jmp(COUNT);
- } else if (LockingMode == LM_LEGACY) {
- movptr(tmpReg, Address (boxReg, 0)); // re-fetch
- lock();
- cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box
- }
+ movptr(tmpReg, Address (boxReg, 0)); // re-fetch
+ lock();
+ cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box
// Intentional fall-thru into DONE_LABEL
}
+
bind(DONE_LABEL);
// ZFlag == 1 count in fast path
@@ -955,6 +936,247 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t
bind(NO_COUNT);
}
+void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register box, Register rax_reg,
+ Register t, Register thread) {
+ assert(LockingMode == LM_LIGHTWEIGHT, "must be");
+ assert(rax_reg == rax, "Used for CAS");
+ assert_different_registers(obj, box, rax_reg, t, thread);
+
+ // Handle inflated monitor.
+ Label inflated;
+ // Finish fast lock successfully. ZF value is irrelevant.
+ Label locked;
+ // Finish fast lock unsuccessfully. MUST jump with ZF == 0
+ Label slow_path;
+
+ if (DiagnoseSyncOnValueBasedClasses != 0) {
+ load_klass(rax_reg, obj, t);
+ movl(rax_reg, Address(rax_reg, Klass::access_flags_offset()));
+ testl(rax_reg, JVM_ACC_IS_VALUE_BASED_CLASS);
+ jcc(Assembler::notZero, slow_path);
+ }
+
+ const Register mark = t;
+
+ { // Lightweight Lock
+
+ Label push;
+
+ const Register top = box;
+
+ // Load the mark.
+ movptr(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+
+ // Prefetch top.
+ movl(top, Address(thread, JavaThread::lock_stack_top_offset()));
+
+ // Check for monitor (0b10).
+ testptr(mark, markWord::monitor_value);
+ jcc(Assembler::notZero, inflated);
+
+ // Check if lock-stack is full.
+ cmpl(top, LockStack::end_offset() - 1);
+ jcc(Assembler::greater, slow_path);
+
+ // Check if recursive.
+ cmpptr(obj, Address(thread, top, Address::times_1, -oopSize));
+ jccb(Assembler::equal, push);
+
+ // Try to lock. Transition lock bits 0b01 => 0b00
+ movptr(rax_reg, mark);
+ orptr(rax_reg, markWord::unlocked_value);
+ andptr(mark, ~(int32_t)markWord::unlocked_value);
+ lock(); cmpxchgptr(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+ jcc(Assembler::notEqual, slow_path);
+
+ bind(push);
+ // After successful lock, push object on lock-stack.
+ movptr(Address(thread, top), obj);
+ addl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize);
+ jmpb(locked);
+ }
+
+ { // Handle inflated monitor.
+ bind(inflated);
+
+ const Register tagged_monitor = mark;
+
+ // CAS owner (null => current thread).
+ xorptr(rax_reg, rax_reg);
+ lock(); cmpxchgptr(thread, Address(tagged_monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
+ jccb(Assembler::equal, locked);
+
+ // Check if recursive.
+ cmpptr(thread, rax_reg);
+ jccb(Assembler::notEqual, slow_path);
+
+ // Recursive.
+ increment(Address(tagged_monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
+ }
+
+ bind(locked);
+ increment(Address(thread, JavaThread::held_monitor_count_offset()));
+ // Set ZF = 1
+ xorl(rax_reg, rax_reg);
+
+#ifdef ASSERT
+ // Check that locked label is reached with ZF set.
+ Label zf_correct;
+ jccb(Assembler::zero, zf_correct);
+ stop("Fast Lock ZF != 1");
+#endif
+
+ bind(slow_path);
+#ifdef ASSERT
+ // Check that slow_path label is reached with ZF not set.
+ jccb(Assembler::notZero, zf_correct);
+ stop("Fast Lock ZF != 0");
+ bind(zf_correct);
+#endif
+ // C2 uses the value of ZF to determine the continuation.
+}
+
+void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread) {
+ assert(LockingMode == LM_LIGHTWEIGHT, "must be");
+ assert(reg_rax == rax, "Used for CAS");
+ assert_different_registers(obj, reg_rax, t);
+
+ // Handle inflated monitor.
+ Label inflated, inflated_check_lock_stack;
+ // Finish fast unlock successfully. MUST jump with ZF == 1
+ Label unlocked;
+
+ // Assume success.
+ decrement(Address(thread, JavaThread::held_monitor_count_offset()));
+
+ const Register mark = t;
+ const Register top = reg_rax;
+
+ Label dummy;
+ C2FastUnlockLightweightStub* stub = nullptr;
+
+ if (!Compile::current()->output()->in_scratch_emit_size()) {
+ stub = new (Compile::current()->comp_arena()) C2FastUnlockLightweightStub(obj, mark, reg_rax, thread);
+ Compile::current()->output()->add_stub(stub);
+ }
+
+ Label& push_and_slow_path = stub == nullptr ? dummy : stub->push_and_slow_path();
+ Label& check_successor = stub == nullptr ? dummy : stub->check_successor();
+
+ { // Lightweight Unlock
+
+ // Load top.
+ movl(top, Address(thread, JavaThread::lock_stack_top_offset()));
+
+ // Prefetch mark.
+ movptr(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+
+ // Check if obj is top of lock-stack.
+ cmpptr(obj, Address(thread, top, Address::times_1, -oopSize));
+ // Top of lock stack was not obj. Must be monitor.
+ jcc(Assembler::notEqual, inflated_check_lock_stack);
+
+ // Pop lock-stack.
+ DEBUG_ONLY(movptr(Address(thread, top, Address::times_1, -oopSize), 0);)
+ subl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize);
+
+ // Check if recursive.
+ cmpptr(obj, Address(thread, top, Address::times_1, -2 * oopSize));
+ jcc(Assembler::equal, unlocked);
+
+ // We elide the monitor check, let the CAS fail instead.
+
+ // Try to unlock. Transition lock bits 0b00 => 0b01
+ movptr(reg_rax, mark);
+ andptr(reg_rax, ~(int32_t)markWord::lock_mask);
+ orptr(mark, markWord::unlocked_value);
+ lock(); cmpxchgptr(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
+ jcc(Assembler::notEqual, push_and_slow_path);
+ jmp(unlocked);
+ }
+
+
+ { // Handle inflated monitor.
+ bind(inflated_check_lock_stack);
+#ifdef ASSERT
+ Label check_done;
+ subl(top, oopSize);
+ cmpl(top, in_bytes(JavaThread::lock_stack_base_offset()));
+ jcc(Assembler::below, check_done);
+ cmpptr(obj, Address(thread, top));
+ jccb(Assembler::notEqual, inflated_check_lock_stack);
+ stop("Fast Unlock lock on stack");
+ bind(check_done);
+ testptr(mark, markWord::monitor_value);
+ jccb(Assembler::notZero, inflated);
+ stop("Fast Unlock not monitor");
+#endif
+
+ bind(inflated);
+
+ // mark contains the tagged ObjectMonitor*.
+ const Register monitor = mark;
+
+#ifndef _LP64
+ // Check if recursive.
+ xorptr(reg_rax, reg_rax);
+ orptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
+ jcc(Assembler::notZero, check_successor);
+
+ // Check if the entry lists are empty.
+ movptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)));
+ orptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)));
+ jcc(Assembler::notZero, check_successor);
+
+ // Release lock.
+ movptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD);
+#else // _LP64
+ Label recursive;
+
+ // Check if recursive.
+ cmpptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), 0);
+ jccb(Assembler::notEqual, recursive);
+
+ // Check if the entry lists are empty.
+ movptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq)));
+ orptr(reg_rax, Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList)));
+ jcc(Assembler::notZero, check_successor);
+
+ // Release lock.
+ movptr(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD);
+ jmpb(unlocked);
+
+ // Recursive unlock.
+ bind(recursive);
+ decrement(Address(monitor, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)));
+ xorl(t, t);
+#endif
+ }
+
+ bind(unlocked);
+ if (stub != nullptr) {
+ bind(stub->unlocked_continuation());
+ }
+
+#ifdef ASSERT
+ // Check that unlocked label is reached with ZF set.
+ Label zf_correct;
+ jccb(Assembler::zero, zf_correct);
+ stop("Fast Unlock ZF != 1");
+#endif
+
+ if (stub != nullptr) {
+ bind(stub->slow_path_continuation());
+ }
+#ifdef ASSERT
+ // Check that stub->continuation() label is reached with ZF not set.
+ jccb(Assembler::notZero, zf_correct);
+ stop("Fast Unlock ZF != 0");
+ bind(zf_correct);
+#endif
+ // C2 uses the value of ZF to determine the continuation.
+}
+
//-------------------------------------------------------------------------------------------
// Generic instructions support for use in .ad files C2 code generation
diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp
index 151f2148372d5..26f7fb44aa939 100644
--- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp
+++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp
@@ -43,6 +43,10 @@
bool use_rtm, bool profile_rtm);
void fast_unlock(Register obj, Register box, Register tmp, bool use_rtm);
+ void fast_lock_lightweight(Register obj, Register box, Register rax_reg,
+ Register t, Register thread);
+ void fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread);
+
#if INCLUDE_RTM_OPT
void rtm_counters_update(Register abort_status, Register rtm_counters);
void branch_on_random_using_rdtsc(Register tmp, Register scr, int count, Label& brLabel);
diff --git a/src/hotspot/cpu/x86/interp_masm_x86.cpp b/src/hotspot/cpu/x86/interp_masm_x86.cpp
index f5f83ae21f475..33570f3155b15 100644
--- a/src/hotspot/cpu/x86/interp_masm_x86.cpp
+++ b/src/hotspot/cpu/x86/interp_masm_x86.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
@@ -1192,8 +1192,6 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) {
const Register thread = lock_reg;
get_thread(thread);
#endif
- // Load object header, prepare for CAS from unlocked to locked.
- movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
lightweight_lock(obj_reg, swap_reg, thread, tmp_reg, slow_case);
} else if (LockingMode == LM_LEGACY) {
// Load immediate 1 into swap_reg %rax
@@ -1311,20 +1309,13 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) {
if (LockingMode == LM_LIGHTWEIGHT) {
#ifdef _LP64
- const Register thread = r15_thread;
+ lightweight_unlock(obj_reg, swap_reg, r15_thread, header_reg, slow_case);
#else
- const Register thread = header_reg;
- get_thread(thread);
+ // This relies on the implementation of lightweight_unlock being able to handle
+ // that the reg_rax and thread Register parameters may alias each other.
+ get_thread(swap_reg);
+ lightweight_unlock(obj_reg, swap_reg, swap_reg, header_reg, slow_case);
#endif
- // Handle unstructured locking.
- Register tmp = swap_reg;
- movl(tmp, Address(thread, JavaThread::lock_stack_top_offset()));
- cmpptr(obj_reg, Address(thread, tmp, Address::times_1, -oopSize));
- jcc(Assembler::notEqual, slow_case);
- // Try to swing header from locked to unlocked.
- movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
- andptr(swap_reg, ~(int32_t)markWord::lock_mask_in_place);
- lightweight_unlock(obj_reg, swap_reg, header_reg, slow_case);
} else if (LockingMode == LM_LEGACY) {
// Load the old header from BasicLock structure
movptr(header_reg, Address(swap_reg,
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
index ba4b089c7aa6e..63a7c43c7ff9b 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.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
@@ -9877,68 +9877,116 @@ void MacroAssembler::check_stack_alignment(Register sp, const char* msg, unsigne
}
// Implements lightweight-locking.
-// Branches to slow upon failure to lock the object, with ZF cleared.
-// Falls through upon success with unspecified ZF.
//
// obj: the object to be locked
-// hdr: the (pre-loaded) header of the object, must be rax
+// reg_rax: rax
// thread: the thread which attempts to lock obj
// tmp: a temporary register
-void MacroAssembler::lightweight_lock(Register obj, Register hdr, Register thread, Register tmp, Label& slow) {
- assert(hdr == rax, "header must be in rax for cmpxchg");
- assert_different_registers(obj, hdr, thread, tmp);
-
- // First we need to check if the lock-stack has room for pushing the object reference.
- // Note: we subtract 1 from the end-offset so that we can do a 'greater' comparison, instead
- // of 'greaterEqual' below, which readily clears the ZF. This makes C2 code a little simpler and
- // avoids one branch.
- cmpl(Address(thread, JavaThread::lock_stack_top_offset()), LockStack::end_offset() - 1);
- jcc(Assembler::greater, slow);
-
- // Now we attempt to take the fast-lock.
- // Clear lock_mask bits (locked state).
- andptr(hdr, ~(int32_t)markWord::lock_mask_in_place);
- movptr(tmp, hdr);
- // Set unlocked_value bit.
- orptr(hdr, markWord::unlocked_value);
- lock();
- cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes()));
+void MacroAssembler::lightweight_lock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow) {
+ assert(reg_rax == rax, "");
+ assert_different_registers(obj, reg_rax, thread, tmp);
+
+ Label push;
+ const Register top = tmp;
+
+ // Preload the markWord. It is important that this is the first
+ // instruction emitted as it is part of C1's null check semantics.
+ movptr(reg_rax, Address(obj, oopDesc::mark_offset_in_bytes()));
+
+ // Load top.
+ movl(top, Address(thread, JavaThread::lock_stack_top_offset()));
+
+ // Check if the lock-stack is full.
+ cmpl(top, LockStack::end_offset());
+ jcc(Assembler::greaterEqual, slow);
+
+ // Check for recursion.
+ cmpptr(obj, Address(thread, top, Address::times_1, -oopSize));
+ jcc(Assembler::equal, push);
+
+ // Check header for monitor (0b10).
+ testptr(reg_rax, markWord::monitor_value);
+ jcc(Assembler::notZero, slow);
+
+ // Try to lock. Transition lock bits 0b01 => 0b00
+ movptr(tmp, reg_rax);
+ andptr(tmp, ~(int32_t)markWord::unlocked_value);
+ orptr(reg_rax, markWord::unlocked_value);
+ lock(); cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes()));
jcc(Assembler::notEqual, slow);
- // If successful, push object to lock-stack.
- movl(tmp, Address(thread, JavaThread::lock_stack_top_offset()));
- movptr(Address(thread, tmp), obj);
- incrementl(tmp, oopSize);
- movl(Address(thread, JavaThread::lock_stack_top_offset()), tmp);
+ // Restore top, CAS clobbers register.
+ movl(top, Address(thread, JavaThread::lock_stack_top_offset()));
+
+ bind(push);
+ // After successful lock, push object on lock-stack.
+ movptr(Address(thread, top), obj);
+ incrementl(top, oopSize);
+ movl(Address(thread, JavaThread::lock_stack_top_offset()), top);
}
// Implements lightweight-unlocking.
-// Branches to slow upon failure, with ZF cleared.
-// Falls through upon success, with unspecified ZF.
//
// obj: the object to be unlocked
-// hdr: the (pre-loaded) header of the object, must be rax
+// reg_rax: rax
+// thread: the thread
// tmp: a temporary register
-void MacroAssembler::lightweight_unlock(Register obj, Register hdr, Register tmp, Label& slow) {
- assert(hdr == rax, "header must be in rax for cmpxchg");
- assert_different_registers(obj, hdr, tmp);
-
- // Mark-word must be lock_mask now, try to swing it back to unlocked_value.
- movptr(tmp, hdr); // The expected old value
- orptr(tmp, markWord::unlocked_value);
- lock();
- cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes()));
+//
+// x86_32 Note: reg_rax and thread may alias each other due to limited register
+// availiability.
+void MacroAssembler::lightweight_unlock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow) {
+ assert(reg_rax == rax, "");
+ assert_different_registers(obj, reg_rax, tmp);
+ LP64_ONLY(assert_different_registers(obj, reg_rax, thread, tmp);)
+
+ Label unlocked, push_and_slow;
+ const Register top = tmp;
+
+ // Check if obj is top of lock-stack.
+ movl(top, Address(thread, JavaThread::lock_stack_top_offset()));
+ cmpptr(obj, Address(thread, top, Address::times_1, -oopSize));
jcc(Assembler::notEqual, slow);
- // Pop the lock object from the lock-stack.
-#ifdef _LP64
- const Register thread = r15_thread;
-#else
- const Register thread = rax;
- get_thread(thread);
-#endif
+
+ // Pop lock-stack.
+ DEBUG_ONLY(movptr(Address(thread, top, Address::times_1, -oopSize), 0);)
subl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize);
+
+ // Check if recursive.
+ cmpptr(obj, Address(thread, top, Address::times_1, -2 * oopSize));
+ jcc(Assembler::equal, unlocked);
+
+ // Not recursive. Check header for monitor (0b10).
+ movptr(reg_rax, Address(obj, oopDesc::mark_offset_in_bytes()));
+ testptr(reg_rax, markWord::monitor_value);
+ jcc(Assembler::notZero, push_and_slow);
+
#ifdef ASSERT
- movl(tmp, Address(thread, JavaThread::lock_stack_top_offset()));
- movptr(Address(thread, tmp), 0);
+ // Check header not unlocked (0b01).
+ Label not_unlocked;
+ testptr(reg_rax, markWord::unlocked_value);
+ jcc(Assembler::zero, not_unlocked);
+ stop("lightweight_unlock already unlocked");
+ bind(not_unlocked);
#endif
+
+ // Try to unlock. Transition lock bits 0b00 => 0b01
+ movptr(tmp, reg_rax);
+ orptr(tmp, markWord::unlocked_value);
+ lock(); cmpxchgptr(tmp, Address(obj, oopDesc::mark_offset_in_bytes()));
+ jcc(Assembler::equal, unlocked);
+
+ bind(push_and_slow);
+ // Restore lock-stack and handle the unlock in runtime.
+ if (thread == reg_rax) {
+ // On x86_32 we may lose the thread.
+ get_thread(thread);
+ }
+#ifdef ASSERT
+ movl(top, Address(thread, JavaThread::lock_stack_top_offset()));
+ movptr(Address(thread, top), obj);
+#endif
+ addl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize);
+ jmp(slow);
+
+ bind(unlocked);
}
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
index 4b30168452796..971aacb2adc7b 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.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
@@ -2031,8 +2031,8 @@ class MacroAssembler: public Assembler {
void check_stack_alignment(Register sp, const char* msg, unsigned bias = 0, Register tmp = noreg);
- void lightweight_lock(Register obj, Register hdr, Register thread, Register tmp, Label& slow);
- void lightweight_unlock(Register obj, Register hdr, Register tmp, Label& slow);
+ void lightweight_lock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow);
+ void lightweight_unlock(Register obj, Register reg_rax, Register thread, Register tmp, Label& slow);
};
/**
diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp
index 571160523cbe4..4d1078c55cd7d 100644
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.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
@@ -1713,8 +1713,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ jcc(Assembler::notEqual, slow_path_lock);
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- // Load object header
- __ movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
__ lightweight_lock(obj_reg, swap_reg, thread, lock_reg, slow_path_lock);
}
__ bind(count_mon);
@@ -1872,9 +1870,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ dec_held_monitor_count();
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- __ movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
- __ andptr(swap_reg, ~(int32_t)markWord::lock_mask_in_place);
- __ lightweight_unlock(obj_reg, swap_reg, lock_reg, slow_path_unlock);
+ __ lightweight_unlock(obj_reg, swap_reg, thread, lock_reg, slow_path_unlock);
__ dec_held_monitor_count();
}
diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
index cab50e85ec51c..1af7d1caa0455 100644
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
+++ b/src/hotspot/cpu/x86/sharedRuntime_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
@@ -2190,8 +2190,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ jcc(Assembler::notEqual, slow_path_lock);
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- // Load object header
- __ movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
__ lightweight_lock(obj_reg, swap_reg, r15_thread, rscratch1, slow_path_lock);
}
__ bind(count_mon);
@@ -2334,9 +2332,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ dec_held_monitor_count();
} else {
assert(LockingMode == LM_LIGHTWEIGHT, "must be");
- __ movptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes()));
- __ andptr(swap_reg, ~(int32_t)markWord::lock_mask_in_place);
- __ lightweight_unlock(obj_reg, swap_reg, lock_reg, slow_path_unlock);
+ __ lightweight_unlock(obj_reg, swap_reg, r15_thread, lock_reg, slow_path_unlock);
__ dec_held_monitor_count();
}
diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp
index cfc16acabc674..bf5e052e16702 100644
--- a/src/hotspot/cpu/x86/vm_version_x86.hpp
+++ b/src/hotspot/cpu/x86/vm_version_x86.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
@@ -770,6 +770,10 @@ class VM_Version : public Abstract_VM_Version {
return true;
}
+ constexpr static bool supports_recursive_lightweight_locking() {
+ return true;
+ }
+
// For AVX CPUs only. f16c support is disabled if UseAVX == 0.
static bool supports_float16() {
return supports_f16c() || supports_avx512vl();
diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad
index 9aa0051043575..df38fe6b92c54 100644
--- a/src/hotspot/cpu/x86/x86_32.ad
+++ b/src/hotspot/cpu/x86/x86_32.ad
@@ -13776,7 +13776,7 @@ instruct cmpFastLockRTM(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eD
%}
instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP scr, eRegP thread) %{
- predicate(!Compile::current()->use_rtm());
+ predicate(LockingMode != LM_LIGHTWEIGHT && !Compile::current()->use_rtm());
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP scr, USE_KILL box, TEMP thread);
ins_cost(300);
@@ -13790,6 +13790,7 @@ instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP
%}
instruct cmpFastUnlock(eFlagsReg cr, eRegP object, eAXRegP box, eRegP tmp ) %{
+ predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp, USE_KILL box);
ins_cost(300);
@@ -13800,6 +13801,32 @@ instruct cmpFastUnlock(eFlagsReg cr, eRegP object, eAXRegP box, eRegP tmp ) %{
ins_pipe(pipe_slow);
%}
+instruct cmpFastLockLightweight(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI eax_reg, eRegP tmp, eRegP thread) %{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set cr (FastLock object box));
+ effect(TEMP eax_reg, TEMP tmp, USE_KILL box, TEMP thread);
+ ins_cost(300);
+ format %{ "FASTLOCK $object,$box\t! kills $box,$eax_reg,$tmp" %}
+ ins_encode %{
+ __ get_thread($thread$$Register);
+ __ fast_lock_lightweight($object$$Register, $box$$Register, $eax_reg$$Register, $tmp$$Register, $thread$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct cmpFastUnlockLightweight(eFlagsReg cr, eRegP object, eAXRegP eax_reg, eRegP tmp, eRegP thread) %{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set cr (FastUnlock object eax_reg));
+ effect(TEMP tmp, USE_KILL eax_reg, TEMP thread);
+ ins_cost(300);
+ format %{ "FASTUNLOCK $object,$eax_reg\t! kills $eax_reg,$tmp" %}
+ ins_encode %{
+ __ get_thread($thread$$Register);
+ __ fast_unlock_lightweight($object$$Register, $eax_reg$$Register, $tmp$$Register, $thread$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
instruct mask_all_evexL_LT32(kReg dst, eRegL src) %{
predicate(Matcher::vector_length(n) <= 32);
match(Set dst (MaskAll src));
diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad
index a248daaa1917b..2cb2cc1becb66 100644
--- a/src/hotspot/cpu/x86/x86_64.ad
+++ b/src/hotspot/cpu/x86/x86_64.ad
@@ -12404,7 +12404,7 @@ instruct cmpFastLockRTM(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp,
%}
instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRegP scr) %{
- predicate(!Compile::current()->use_rtm());
+ predicate(LockingMode != LM_LIGHTWEIGHT && !Compile::current()->use_rtm());
match(Set cr (FastLock object box));
effect(TEMP tmp, TEMP scr, USE_KILL box);
ins_cost(300);
@@ -12417,6 +12417,7 @@ instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRe
%}
instruct cmpFastUnlock(rFlagsReg cr, rRegP object, rax_RegP box, rRegP tmp) %{
+ predicate(LockingMode != LM_LIGHTWEIGHT);
match(Set cr (FastUnlock object box));
effect(TEMP tmp, USE_KILL box);
ins_cost(300);
@@ -12427,6 +12428,30 @@ instruct cmpFastUnlock(rFlagsReg cr, rRegP object, rax_RegP box, rRegP tmp) %{
ins_pipe(pipe_slow);
%}
+instruct cmpFastLockLightweight(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI rax_reg, rRegP tmp) %{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set cr (FastLock object box));
+ effect(TEMP rax_reg, TEMP tmp, USE_KILL box);
+ ins_cost(300);
+ format %{ "fastlock $object,$box\t! kills $box,$rax_reg,$tmp" %}
+ ins_encode %{
+ __ fast_lock_lightweight($object$$Register, $box$$Register, $rax_reg$$Register, $tmp$$Register, r15_thread);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct cmpFastUnlockLightweight(rFlagsReg cr, rRegP object, rax_RegP rax_reg, rRegP tmp) %{
+ predicate(LockingMode == LM_LIGHTWEIGHT);
+ match(Set cr (FastUnlock object rax_reg));
+ effect(TEMP tmp, USE_KILL rax_reg);
+ ins_cost(300);
+ format %{ "fastunlock $object,$rax_reg\t! kills $rax_reg,$tmp" %}
+ ins_encode %{
+ __ fast_unlock_lightweight($object$$Register, $rax_reg$$Register, $tmp$$Register, r15_thread);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
// ============================================================================
// Safepoint Instructions
diff --git a/src/hotspot/share/opto/c2_CodeStubs.hpp b/src/hotspot/share/opto/c2_CodeStubs.hpp
index 3df1e4b726d07..83d170810703d 100644
--- a/src/hotspot/share/opto/c2_CodeStubs.hpp
+++ b/src/hotspot/share/opto/c2_CodeStubs.hpp
@@ -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
@@ -97,6 +97,26 @@ class C2EntryBarrierStub: public C2CodeStub {
void emit(C2_MacroAssembler& masm);
};
+class C2FastUnlockLightweightStub : public C2CodeStub {
+private:
+ Register _obj;
+ Register _mark;
+ Register _t;
+ Register _thread;
+ Label _push_and_slow_path;
+ Label _check_successor;
+ Label _unlocked_continuation;
+public:
+ C2FastUnlockLightweightStub(Register obj, Register mark, Register t, Register thread) : C2CodeStub(),
+ _obj(obj), _mark(mark), _t(t), _thread(thread) {}
+ int max_size() const;
+ void emit(C2_MacroAssembler& masm);
+ Label& push_and_slow_path() { return _push_and_slow_path; }
+ Label& check_successor() { return _check_successor; }
+ Label& unlocked_continuation() { return _unlocked_continuation; }
+ Label& slow_path_continuation() { return continuation(); }
+};
+
#ifdef _LP64
class C2HandleAnonOMOwnerStub : public C2CodeStub {
private:
From ea98de63f7aa4b9d7f95bea267a43619c5ce449e Mon Sep 17 00:00:00 2001
From: Tobias Hartmann
Date: Wed, 14 Feb 2024 07:34:28 +0000
Subject: [PATCH 24/36] 8325449: [BACKOUT] use "dmb.ishst+dmb.ishld" for
release barrier
Reviewed-by: chagedorn
---
src/hotspot/cpu/aarch64/aarch64.ad | 7 +-
src/hotspot/cpu/aarch64/globals_aarch64.hpp | 2 -
.../cpu/aarch64/macroAssembler_aarch64.cpp | 21 ++---
.../cpu/aarch64/vm_version_aarch64.cpp | 3 -
.../vm/compiler/FinalFieldInitialize.java | 85 -------------------
5 files changed, 10 insertions(+), 108 deletions(-)
delete mode 100644 test/micro/org/openjdk/bench/vm/compiler/FinalFieldInitialize.java
diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad
index f22af58f40ab5..9c015bd16da91 100644
--- a/src/hotspot/cpu/aarch64/aarch64.ad
+++ b/src/hotspot/cpu/aarch64/aarch64.ad
@@ -8289,7 +8289,7 @@ instruct membar_acquire() %{
ins_cost(VOLATILE_REF_COST);
format %{ "membar_acquire\n\t"
- "dmb ishld" %}
+ "dmb ish" %}
ins_encode %{
__ block_comment("membar_acquire");
@@ -8343,12 +8343,11 @@ instruct membar_release() %{
ins_cost(VOLATILE_REF_COST);
format %{ "membar_release\n\t"
- "dmb ishst\n\tdmb ishld" %}
+ "dmb ish" %}
ins_encode %{
__ block_comment("membar_release");
- __ membar(Assembler::StoreStore);
- __ membar(Assembler::LoadStore);
+ __ membar(Assembler::LoadStore|Assembler::StoreStore);
%}
ins_pipe(pipe_serial);
%}
diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp
index 13f2e4b61b9a4..293cc6eb0d0c6 100644
--- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp
@@ -127,8 +127,6 @@ define_pd_global(intx, InlineSmallCode, 1000);
range(1, 99) \
product(ccstr, UseBranchProtection, "none", \
"Branch Protection to use: none, standard, pac-ret") \
- product(bool, AlwaysMergeDMB, false, DIAGNOSTIC, \
- "Always merge DMB instructions in code emission") \
// end of ARCH_FLAGS
diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
index 124af3bafbe3a..60de130bc334f 100644
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
@@ -2066,21 +2066,14 @@ void MacroAssembler::membar(Membar_mask_bits order_constraint) {
address last = code()->last_insn();
if (last != nullptr && nativeInstruction_at(last)->is_Membar() && prev == last) {
NativeMembar *bar = NativeMembar_at(prev);
- // Don't promote DMB ST|DMB LD to DMB (a full barrier) because
- // doing so would introduce a StoreLoad which the caller did not
- // intend
- if (AlwaysMergeDMB || bar->get_kind() == order_constraint
- || bar->get_kind() == AnyAny
- || order_constraint == AnyAny) {
- // We are merging two memory barrier instructions. On AArch64 we
- // can do this simply by ORing them together.
- bar->set_kind(bar->get_kind() | order_constraint);
- BLOCK_COMMENT("merged membar");
- return;
- }
+ // We are merging two memory barrier instructions. On AArch64 we
+ // can do this simply by ORing them together.
+ bar->set_kind(bar->get_kind() | order_constraint);
+ BLOCK_COMMENT("merged membar");
+ } else {
+ code()->set_last_insn(pc());
+ dmb(Assembler::barrier(order_constraint));
}
- code()->set_last_insn(pc());
- dmb(Assembler::barrier(order_constraint));
}
bool MacroAssembler::try_merge_ldst(Register rt, const Address &adr, size_t size_in_bytes, bool is_store) {
diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
index b53e427649781..18f310c746cd4 100644
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
@@ -191,9 +191,6 @@ void VM_Version::initialize() {
if (FLAG_IS_DEFAULT(UseSIMDForMemoryOps)) {
FLAG_SET_DEFAULT(UseSIMDForMemoryOps, true);
}
- if (FLAG_IS_DEFAULT(AlwaysMergeDMB)) {
- FLAG_SET_DEFAULT(AlwaysMergeDMB, true);
- }
}
// Cortex A53
diff --git a/test/micro/org/openjdk/bench/vm/compiler/FinalFieldInitialize.java b/test/micro/org/openjdk/bench/vm/compiler/FinalFieldInitialize.java
deleted file mode 100644
index ee0779faecf2a..0000000000000
--- a/test/micro/org/openjdk/bench/vm/compiler/FinalFieldInitialize.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2024, Alibaba Group Co., Ltd. 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 org.openjdk.bench.vm.compiler;
-
-import org.openjdk.jmh.annotations.Benchmark;
-import org.openjdk.jmh.annotations.*;
-
-import java.util.concurrent.TimeUnit;
-import org.openjdk.jmh.infra.Blackhole;
-
-/* test allocation speed of object with final field */
-@BenchmarkMode(Mode.Throughput)
-@OutputTimeUnit(TimeUnit.SECONDS)
-@State(Scope.Benchmark)
-@Warmup(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS)
-@Measurement(iterations = 3, time = 3, timeUnit = TimeUnit.SECONDS)
-@Fork(value = 3)
-public class FinalFieldInitialize {
- final static int LEN = 100_000;
- Object arr[] = null;
- @Setup
- public void setup(){
- arr = new Object[LEN];
- }
-
- @Benchmark
- public void testAlloc(Blackhole bh) {
- for (int i=0; i
Date: Wed, 14 Feb 2024 08:31:35 +0000
Subject: [PATCH 25/36] 8325743:
test/jdk/java/nio/channels/unixdomain/SocketOptions.java enhance user name
output in error case
Reviewed-by: dfuchs, alanb
---
test/jdk/java/nio/channels/unixdomain/SocketOptions.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/test/jdk/java/nio/channels/unixdomain/SocketOptions.java b/test/jdk/java/nio/channels/unixdomain/SocketOptions.java
index f275b519394ba..95188ebcef1e4 100644
--- a/test/jdk/java/nio/channels/unixdomain/SocketOptions.java
+++ b/test/jdk/java/nio/channels/unixdomain/SocketOptions.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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,7 +72,8 @@ static void testPeerCred() throws Exception {
// Check returned user name
if (!s1.equals(s2)) {
- throw new RuntimeException("wrong username");
+ throw new RuntimeException("wrong username, actual " + s1 +
+ " but expected value from property user.name is " + s2);
}
// Try setting the option: Read only
From 0c2def0e3eaa4925746158294f798d37d42c50f3 Mon Sep 17 00:00:00 2001
From: Aggelos Biboudis
Date: Wed, 14 Feb 2024 09:19:18 +0000
Subject: [PATCH 26/36] 8325653: Erroneous exhaustivity analysis for primitive
patterns
Reviewed-by: vromero
---
.../com/sun/tools/javac/comp/Flow.java | 24 +++++------------
.../PrimitivePatternsSwitchErrors.java | 26 ++++++++++++++++++-
.../PrimitivePatternsSwitchErrors.out | 5 +++-
3 files changed, 35 insertions(+), 20 deletions(-)
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
index 9de7a6292db67..83bcf999da5d2 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
@@ -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
@@ -1297,24 +1297,12 @@ public void analyzeTree(Env env, JCTree tree, TreeMaker make) {
private boolean isBpCovered(Type componentType, PatternDescription newNested) {
if (newNested instanceof BindingPattern bp) {
- var seltype = types.erasure(componentType);
+ Type seltype = types.erasure(componentType);
+ Type pattype = types.erasure(bp.type);
- if (seltype.isPrimitive()) {
- if (types.isSameType(bp.type, types.boxedClass(seltype).type)) {
- return true;
- }
-
- // if the target is unconditionally exact to the pattern, target is covered
- if (types.isUnconditionallyExact(seltype, bp.type)) {
- return true;
- }
- } else if (seltype.isReference() && bp.type.isPrimitive() && types.isCastable(seltype, bp.type)) {
- return true;
- } else {
- if (types.isSubtype(seltype, types.erasure(bp.type))) {
- return true;
- }
- }
+ return seltype.isPrimitive() ?
+ types.isUnconditionallyExact(seltype, pattype) :
+ (bp.type.isPrimitive() && types.isUnconditionallyExact(types.unboxedType(seltype), bp.type)) || types.isSubtype(seltype, pattype);
}
return false;
}
diff --git a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java
index 71e6193275ba9..e0e153eb0f5fe 100644
--- a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java
+++ b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java
@@ -1,6 +1,6 @@
/*
* @test /nodynamiccopyright/
- * @bug 8304487
+ * @bug 8304487 8325653
* @summary Compiler Implementation for Primitive types in patterns, instanceof, and switch (Preview)
* @enablePreview
* @compile/fail/ref=PrimitivePatternsSwitchErrors.out -XDrawDiagnostics -XDshould-stop.at=FLOW PrimitivePatternsSwitchErrors.java
@@ -217,4 +217,28 @@ void nullAndPrimitive() {
default -> System.out.println("any other integral value");
}
}
+
+ public static int nonExhaustive4() {
+ Number n = Byte.valueOf((byte) 42);
+ return switch (n) { // Error - not exhaustive
+ case byte b when b == 42 -> 1;
+ case byte b -> -1 ;
+ };
+ }
+
+ public static int nonExhaustive5() {
+ Object n = 42;
+ return switch (n) { // Error - not exhaustive
+ case int b when b == 42 -> 1;
+ case int b -> -1 ;
+ };
+ }
+
+ public static int nonExhaustive6() {
+ Object n = 42;
+ return switch (n) { // Error - not exhaustive
+ case byte b -> -1 ;
+ case int b -> -2 ;
+ };
+ }
}
diff --git a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out
index 2026afe58c2de..97b0d67cec733 100644
--- a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out
+++ b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out
@@ -32,6 +32,9 @@ PrimitivePatternsSwitchErrors.java:44:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:52:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:201:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:207:9: compiler.err.not.exhaustive.statement
+PrimitivePatternsSwitchErrors.java:223:16: compiler.err.not.exhaustive
+PrimitivePatternsSwitchErrors.java:231:16: compiler.err.not.exhaustive
+PrimitivePatternsSwitchErrors.java:239:16: compiler.err.not.exhaustive
- compiler.note.preview.filename: PrimitivePatternsSwitchErrors.java, DEFAULT
- compiler.note.preview.recompile
-34 errors
\ No newline at end of file
+37 errors
\ No newline at end of file
From 84965ea1a86703818410f11c8d284e4b824817dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Erik=20=C3=96sterlund?=
Date: Wed, 14 Feb 2024 11:44:30 +0000
Subject: [PATCH 27/36] 8322630: Remove ICStubs and related safepoints
Co-authored-by: Martin Doerr
Co-authored-by: Aleksey Shipilev
Co-authored-by: Amit Kumar
Co-authored-by: Robbin Ehn
Co-authored-by: Aleksei Voitylov
Reviewed-by: tschatzl, aboldtch, dlong
---
src/hotspot/cpu/aarch64/aarch64.ad | 23 +-
.../cpu/aarch64/c1_LIRAssembler_aarch64.cpp | 25 +-
.../cpu/aarch64/c1_LIRAssembler_aarch64.hpp | 4 +-
.../cpu/aarch64/c1_MacroAssembler_aarch64.cpp | 11 -
.../cpu/aarch64/c1_Runtime1_aarch64.cpp | 1 -
.../cpu/aarch64/compiledIC_aarch64.cpp | 22 +-
src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp | 82 --
.../cpu/aarch64/macroAssembler_aarch64.cpp | 57 +-
.../cpu/aarch64/macroAssembler_aarch64.hpp | 3 +
.../cpu/aarch64/sharedRuntime_aarch64.cpp | 35 +-
.../cpu/aarch64/vtableStubs_aarch64.cpp | 12 +-
src/hotspot/cpu/arm/arm.ad | 17 +-
src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp | 7 +-
src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp | 10 -
src/hotspot/cpu/arm/c1_Runtime1_arm.cpp | 1 -
src/hotspot/cpu/arm/compiledIC_arm.cpp | 24 +-
src/hotspot/cpu/arm/icBuffer_arm.cpp | 65 --
src/hotspot/cpu/arm/macroAssembler_arm.cpp | 37 +-
src/hotspot/cpu/arm/macroAssembler_arm.hpp | 4 +
src/hotspot/cpu/arm/nativeInst_arm_32.cpp | 1 -
src/hotspot/cpu/arm/nativeInst_arm_32.hpp | 2 +-
src/hotspot/cpu/arm/sharedRuntime_arm.cpp | 23 +-
src/hotspot/cpu/arm/vtableStubs_arm.cpp | 6 +-
src/hotspot/cpu/ppc/assembler_ppc.inline.hpp | 4 +-
src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp | 4 +-
src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp | 23 -
src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp | 1 -
src/hotspot/cpu/ppc/compiledIC_ppc.cpp | 26 +-
src/hotspot/cpu/ppc/icBuffer_ppc.cpp | 69 --
src/hotspot/cpu/ppc/macroAssembler_ppc.cpp | 76 ++
src/hotspot/cpu/ppc/macroAssembler_ppc.hpp | 3 +
src/hotspot/cpu/ppc/ppc.ad | 41 +-
src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp | 72 +-
src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp | 6 +-
.../cpu/riscv/c1_LIRAssembler_riscv.cpp | 24 +-
.../cpu/riscv/c1_LIRAssembler_riscv.hpp | 2 +-
.../cpu/riscv/c1_MacroAssembler_riscv.cpp | 9 -
src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp | 1 -
src/hotspot/cpu/riscv/compiledIC_riscv.cpp | 22 +-
src/hotspot/cpu/riscv/icBuffer_riscv.cpp | 78 --
.../cpu/riscv/macroAssembler_riscv.cpp | 49 +-
.../cpu/riscv/macroAssembler_riscv.hpp | 3 +
src/hotspot/cpu/riscv/riscv.ad | 25 +-
src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 36 +-
src/hotspot/cpu/riscv/vtableStubs_riscv.cpp | 12 +-
src/hotspot/cpu/s390/assembler_s390.hpp | 2 +-
src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp | 5 +-
src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp | 2 +-
.../cpu/s390/c1_MacroAssembler_s390.cpp | 25 -
src/hotspot/cpu/s390/c1_Runtime1_s390.cpp | 1 -
src/hotspot/cpu/s390/compiledIC_s390.cpp | 22 +-
src/hotspot/cpu/s390/icBuffer_s390.cpp | 65 --
src/hotspot/cpu/s390/macroAssembler_s390.cpp | 48 +-
src/hotspot/cpu/s390/macroAssembler_s390.hpp | 4 +
src/hotspot/cpu/s390/s390.ad | 48 +-
src/hotspot/cpu/s390/sharedRuntime_s390.cpp | 40 +-
src/hotspot/cpu/s390/vtableStubs_s390.cpp | 8 +-
src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp | 19 +-
src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp | 25 +-
src/hotspot/cpu/x86/c1_Runtime1_x86.cpp | 1 -
src/hotspot/cpu/x86/compiledIC_x86.cpp | 22 +-
src/hotspot/cpu/x86/icBuffer_x86.cpp | 95 ---
src/hotspot/cpu/x86/macroAssembler_x86.cpp | 37 +-
src/hotspot/cpu/x86/macroAssembler_x86.hpp | 2 +
src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp | 29 +-
src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 34 +-
src/hotspot/cpu/x86/vtableStubs_x86_32.cpp | 12 +-
src/hotspot/cpu/x86/vtableStubs_x86_64.cpp | 12 +-
src/hotspot/cpu/x86/x86_32.ad | 20 +-
src/hotspot/cpu/x86/x86_64.ad | 31 +-
src/hotspot/cpu/zero/compiledIC_zero.cpp | 13 +-
src/hotspot/cpu/zero/icBuffer_zero.cpp | 56 --
src/hotspot/cpu/zero/sharedRuntime_zero.cpp | 2 -
src/hotspot/os/aix/os_aix.cpp | 1 -
src/hotspot/os/bsd/os_bsd.cpp | 1 -
src/hotspot/os/linux/os_linux.cpp | 1 -
src/hotspot/os/windows/os_windows.cpp | 1 -
src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp | 1 -
.../os_cpu/bsd_aarch64/os_bsd_aarch64.cpp | 1 -
src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp | 1 -
src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp | 1 -
.../os_cpu/linux_aarch64/os_linux_aarch64.cpp | 1 -
src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp | 1 -
src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp | 1 -
.../os_cpu/linux_riscv/os_linux_riscv.cpp | 1 -
.../os_cpu/linux_s390/os_linux_s390.cpp | 1 -
src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp | 1 -
.../os_cpu/linux_zero/os_linux_zero.cpp | 1 -
.../windows_aarch64/os_windows_aarch64.cpp | 1 -
.../os_cpu/windows_x86/os_windows_x86.cpp | 1 -
src/hotspot/share/adlc/main.cpp | 1 -
src/hotspot/share/asm/codeBuffer.cpp | 1 +
src/hotspot/share/asm/codeBuffer.inline.hpp | 2 +-
src/hotspot/share/c1/c1_LIRAssembler.cpp | 8 +-
src/hotspot/share/c1/c1_MacroAssembler.hpp | 1 -
src/hotspot/share/code/codeBlob.cpp | 6 -
src/hotspot/share/code/codeCache.cpp | 18 -
src/hotspot/share/code/codeCache.hpp | 1 -
src/hotspot/share/code/compiledIC.cpp | 752 ++++++------------
src/hotspot/share/code/compiledIC.hpp | 376 ++-------
src/hotspot/share/code/compiledMethod.cpp | 139 +---
src/hotspot/share/code/compiledMethod.hpp | 18 +-
src/hotspot/share/code/icBuffer.cpp | 293 -------
src/hotspot/share/code/icBuffer.hpp | 193 -----
src/hotspot/share/code/nmethod.cpp | 190 ++---
src/hotspot/share/code/nmethod.hpp | 10 +-
src/hotspot/share/code/relocInfo.cpp | 33 +-
src/hotspot/share/code/relocInfo.hpp | 10 +-
src/hotspot/share/code/vtableStubs.cpp | 7 -
src/hotspot/share/code/vtableStubs.hpp | 1 -
src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 3 -
src/hotspot/share/gc/serial/genMarkSweep.cpp | 1 -
src/hotspot/share/gc/serial/serialHeap.cpp | 3 -
.../share/gc/shared/parallelCleaning.cpp | 1 -
.../gc/shenandoah/shenandoahCodeRoots.cpp | 46 +-
.../share/gc/shenandoah/shenandoahUnload.cpp | 2 +-
src/hotspot/share/gc/x/xNMethod.cpp | 35 +-
src/hotspot/share/gc/x/xNMethodTable.cpp | 1 -
src/hotspot/share/gc/x/xUnload.cpp | 2 +-
src/hotspot/share/gc/z/zNMethod.cpp | 53 +-
src/hotspot/share/gc/z/zNMethodTable.cpp | 1 -
src/hotspot/share/gc/z/zUnload.cpp | 2 +-
.../share/jvmci/jvmciCodeInstaller.cpp | 6 +-
src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 7 +
src/hotspot/share/oops/compiledICHolder.cpp | 75 --
src/hotspot/share/oops/compiledICHolder.hpp | 92 ---
.../share/oops/compiledICHolder.inline.hpp | 43 -
src/hotspot/share/oops/oopsHierarchy.hpp | 3 -
src/hotspot/share/opto/output.cpp | 10 +-
src/hotspot/share/opto/runtime.cpp | 1 -
src/hotspot/share/runtime/globals.hpp | 9 -
src/hotspot/share/runtime/init.cpp | 3 -
src/hotspot/share/runtime/os.cpp | 1 -
src/hotspot/share/runtime/safepoint.cpp | 13 -
src/hotspot/share/runtime/safepoint.hpp | 1 -
src/hotspot/share/runtime/sharedRuntime.cpp | 468 ++---------
src/hotspot/share/runtime/sharedRuntime.hpp | 3 -
src/hotspot/share/runtime/vmStructs.cpp | 5 +-
src/hotspot/share/utilities/debug.cpp | 1 -
.../jvm/hotspot/oops/CompiledICHolder.java | 70 --
.../runtime/logging/SafepointCleanupTest.java | 1 -
.../event/runtime/TestSafepointEvents.java | 2 +-
142 files changed, 1027 insertions(+), 3752 deletions(-)
delete mode 100644 src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp
delete mode 100644 src/hotspot/cpu/arm/icBuffer_arm.cpp
delete mode 100644 src/hotspot/cpu/ppc/icBuffer_ppc.cpp
delete mode 100644 src/hotspot/cpu/riscv/icBuffer_riscv.cpp
delete mode 100644 src/hotspot/cpu/s390/icBuffer_s390.cpp
delete mode 100644 src/hotspot/cpu/x86/icBuffer_x86.cpp
delete mode 100644 src/hotspot/cpu/zero/icBuffer_zero.cpp
delete mode 100644 src/hotspot/share/code/icBuffer.cpp
delete mode 100644 src/hotspot/share/code/icBuffer.hpp
delete mode 100644 src/hotspot/share/oops/compiledICHolder.cpp
delete mode 100644 src/hotspot/share/oops/compiledICHolder.hpp
delete mode 100644 src/hotspot/share/oops/compiledICHolder.inline.hpp
delete mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/CompiledICHolder.java
diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad
index 9c015bd16da91..d6f3cace0a9b4 100644
--- a/src/hotspot/cpu/aarch64/aarch64.ad
+++ b/src/hotspot/cpu/aarch64/aarch64.ad
@@ -2205,14 +2205,14 @@ void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
{
st->print_cr("# MachUEPNode");
if (UseCompressedClassPointers) {
- st->print_cr("\tldrw rscratch1, j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
- if (CompressedKlassPointers::shift() != 0) {
- st->print_cr("\tdecode_klass_not_null rscratch1, rscratch1");
- }
+ st->print_cr("\tldrw rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tldrw r10, [rscratch2 + CompiledICData::speculated_klass_offset()]\t# compressed klass");
+ st->print_cr("\tcmpw rscratch1, r10");
} else {
- st->print_cr("\tldr rscratch1, j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tldr rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tldr r10, [rscratch2 + CompiledICData::speculated_klass_offset()]\t# compressed klass");
+ st->print_cr("\tcmp rscratch1, r10");
}
- st->print_cr("\tcmp r0, rscratch1\t # Inline cache check");
st->print_cr("\tbne, SharedRuntime::_ic_miss_stub");
}
#endif
@@ -2221,14 +2221,7 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
{
// This is the unverified entry point.
C2_MacroAssembler _masm(&cbuf);
-
- __ cmp_klass(j_rarg0, rscratch2, rscratch1);
- Label skip;
- // TODO
- // can we avoid this skip and still use a reloc?
- __ br(Assembler::EQ, skip);
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
- __ bind(skip);
+ __ ic_check(InteriorEntryAlignment);
}
uint MachUEPNode::size(PhaseRegAlloc* ra_) const
@@ -3715,7 +3708,7 @@ encode %{
cbuf.shared_stub_to_interp_for(_method, call - cbuf.insts_begin());
} else {
// Emit stub for static call
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, call);
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf, call);
if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
index b83d618506298..ba613b62a3e2a 100644
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
@@ -53,7 +53,6 @@
#endif
NEEDS_CLEANUP // remove this definitions ?
-const Register IC_Klass = rscratch2; // where the IC klass is cached
const Register SYNC_header = r0; // synchronization header
const Register SHIFT_count = r0; // where count for shift operations must be
@@ -293,27 +292,7 @@ void LIR_Assembler::osr_entry() {
// inline cache check; done before the frame is built.
int LIR_Assembler::check_icache() {
- Register receiver = FrameMap::receiver_opr->as_register();
- Register ic_klass = IC_Klass;
- int start_offset = __ offset();
- __ inline_cache_check(receiver, ic_klass);
-
- // if icache check fails, then jump to runtime routine
- // Note: RECEIVER must still contain the receiver!
- Label dont;
- __ br(Assembler::EQ, dont);
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- // We align the verified entry point unless the method body
- // (including its inline cache check) will fit in a single 64-byte
- // icache line.
- if (! method()->is_accessor() || __ offset() - start_offset > 4 * 4) {
- // force alignment after the cache check.
- __ align(CodeEntryAlignment);
- }
-
- __ bind(dont);
- return start_offset;
+ return __ ic_check(CodeEntryAlignment);
}
void LIR_Assembler::clinit_barrier(ciMethod* method) {
@@ -2042,7 +2021,7 @@ void LIR_Assembler::emit_static_call_stub() {
__ relocate(static_stub_Relocation::spec(call_pc));
__ emit_static_call_stub();
- assert(__ offset() - start + CompiledStaticCall::to_trampoline_stub_size()
+ assert(__ offset() - start + CompiledDirectCall::to_trampoline_stub_size()
<= call_stub_size(), "stub too big");
__ end_a_stub();
}
diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp
index 43ec189255f9c..ef1b5fe2703e6 100644
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.hpp
@@ -71,8 +71,8 @@ friend class ArrayCopyStub;
void deoptimize_trap(CodeEmitInfo *info);
enum {
- // call stub: CompiledStaticCall::to_interp_stub_size() +
- // CompiledStaticCall::to_trampoline_stub_size()
+ // call stub: CompiledDirectCall::to_interp_stub_size() +
+ // CompiledDirectCall::to_trampoline_stub_size()
_call_stub_size = 13 * NativeInstruction::instruction_size,
_exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175),
_deopt_handler_size = 7 * NativeInstruction::instruction_size
diff --git a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp
index d3a746178f14e..c0d1d1747ab28 100644
--- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp
@@ -308,17 +308,6 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1,
verify_oop(obj);
}
-
-void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
- verify_oop(receiver);
- // explicit null check not needed since load from [klass_offset] causes a trap
- // check against inline cache
- assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check");
-
- cmp_klass(receiver, iCache, rscratch1);
-}
-
-
void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) {
assert(bang_size_in_bytes >= framesize, "stack bang size incorrect");
// Make sure there is enough stack space for this method's activation.
diff --git a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
index d2f4744a04914..63a32e714e365 100644
--- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
@@ -38,7 +38,6 @@
#include "interpreter/interpreter.hpp"
#include "memory/universe.hpp"
#include "nativeInst_aarch64.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "register_aarch64.hpp"
diff --git a/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp b/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp
index c58ff8828bce6..23c08f11d1a8b 100644
--- a/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp
@@ -26,7 +26,6 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
@@ -36,7 +35,7 @@
// ----------------------------------------------------------------------------
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
precond(cbuf.stubs()->start() != badAddress);
precond(cbuf.stubs()->end() != badAddress);
@@ -71,11 +70,11 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
}
#undef __
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
return MacroAssembler::static_call_stub_size();
}
-int CompiledStaticCall::to_trampoline_stub_size() {
+int CompiledDirectCall::to_trampoline_stub_size() {
// Somewhat pessimistically, we count 3 instructions here (although
// there are only two) because we sometimes emit an alignment nop.
// Trampoline stubs are always word aligned.
@@ -83,21 +82,14 @@ int CompiledStaticCall::to_trampoline_stub_size() {
}
// Relocation entries for call stub, compiled java to interpreter.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
return 4; // 3 in emit_to_interp_stub + 1 in emit_call
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
address stub = find_stub();
guarantee(stub != nullptr, "stub not found");
- {
- ResourceMark rm;
- log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
- p2i(instruction_address()),
- callee->name_and_sig_as_C_string());
- }
-
// Creation also verifies the object.
NativeMovConstReg* method_holder
= nativeMovConstReg_at(stub + NativeInstruction::instruction_size);
@@ -115,7 +107,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
set_destination_mt_safe(stub);
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
// Reset stub.
address stub = static_stub->addr();
assert(stub != nullptr, "stub not found");
@@ -132,7 +124,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
// Non-product mode code
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
// Verify call.
_call->verify();
_call->verify_alignment();
diff --git a/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp b/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp
deleted file mode 100644
index bd8cfc42600e2..0000000000000
--- a/src/hotspot/cpu/aarch64/icBuffer_aarch64.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014, Red Hat Inc. 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/macroAssembler.hpp"
-#include "asm/macroAssembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_aarch64.hpp"
-#include "oops/oop.inline.hpp"
-
-int InlineCacheBuffer::ic_stub_code_size() {
- return (MacroAssembler::far_branches() ? 6 : 4) * NativeInstruction::instruction_size;
-}
-
-#define __ masm->
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) {
- ResourceMark rm;
- CodeBuffer code(code_begin, ic_stub_code_size());
- MacroAssembler* masm = new MacroAssembler(&code);
- // note: even though the code contains an embedded value, we do not need reloc info
- // because
- // (1) the value is old (i.e., doesn't matter for scavenges)
- // (2) these ICStubs are removed *before* a GC happens, so the roots disappear
- // assert(cached_value == nullptr || cached_oop->is_perm(), "must be perm oop");
-
- address start = __ pc();
- Label l;
- __ ldr(rscratch2, l);
- int jump_code_size = __ far_jump(ExternalAddress(entry_point));
- // IC stub code size is not expected to vary depending on target address.
- // We use NOPs to make the [ldr + far_jump + nops + int64] stub size equal to ic_stub_code_size.
- for (int size = NativeInstruction::instruction_size + jump_code_size + 8;
- size < ic_stub_code_size(); size += NativeInstruction::instruction_size) {
- __ nop();
- }
- __ bind(l);
- assert((uintptr_t)__ pc() % wordSize == 0, "");
- __ emit_int64((int64_t)cached_value);
- // Only need to invalidate the 1st two instructions - not the whole ic stub
- ICache::invalidate_range(code_begin, InlineCacheBuffer::ic_stub_code_size());
- assert(__ pc() - start == ic_stub_code_size(), "must be");
-}
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object
- NativeJump* jump = nativeJump_at(code_begin + 4);
- return jump->jump_destination();
-}
-
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- // The word containing the cached value is at the end of this IC buffer
- uintptr_t *p = (uintptr_t *)(code_begin + ic_stub_code_size() - wordSize);
- void* o = (void*)*p;
- return o;
-}
diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
index 60de130bc334f..b19587ebe760a 100644
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
@@ -29,6 +29,7 @@
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "ci/ciEnv.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/compileTask.hpp"
#include "compiler/disassembler.hpp"
#include "compiler/oopMap.hpp"
@@ -965,7 +966,7 @@ int MacroAssembler::max_trampoline_stub_size() {
}
void MacroAssembler::emit_static_call_stub() {
- // CompiledDirectStaticCall::set_to_interpreted knows the
+ // CompiledDirectCall::set_to_interpreted knows the
// exact layout of this stub.
isb();
@@ -995,10 +996,51 @@ address MacroAssembler::ic_call(address entry, jint method_index) {
// address const_ptr = long_constant((jlong)Universe::non_oop_word());
// uintptr_t offset;
// ldr_constant(rscratch2, const_ptr);
- movptr(rscratch2, (uintptr_t)Universe::non_oop_word());
+ movptr(rscratch2, (intptr_t)Universe::non_oop_word());
return trampoline_call(Address(entry, rh));
}
+int MacroAssembler::ic_check_size() {
+ if (target_needs_far_branch(CAST_FROM_FN_PTR(address, SharedRuntime::get_ic_miss_stub()))) {
+ return NativeInstruction::instruction_size * 7;
+ } else {
+ return NativeInstruction::instruction_size * 5;
+ }
+}
+
+int MacroAssembler::ic_check(int end_alignment) {
+ Register receiver = j_rarg0;
+ Register data = rscratch2;
+ Register tmp1 = rscratch1;
+ Register tmp2 = r10;
+
+ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align
+ // before the inline cache check here, and not after
+ align(end_alignment, offset() + ic_check_size());
+
+ int uep_offset = offset();
+
+ if (UseCompressedClassPointers) {
+ ldrw(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ ldrw(tmp2, Address(data, CompiledICData::speculated_klass_offset()));
+ cmpw(tmp1, tmp2);
+ } else {
+ ldr(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ ldr(tmp2, Address(data, CompiledICData::speculated_klass_offset()));
+ cmp(tmp1, tmp2);
+ }
+
+ Label dont;
+ br(Assembler::EQ, dont);
+ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
+ bind(dont);
+ assert((offset() % end_alignment) == 0, "Misaligned verified entry point");
+
+ return uep_offset;
+}
+
// Implementation of call_VM versions
void MacroAssembler::call_VM(Register oop_result,
@@ -1100,7 +1142,14 @@ void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thr
}
void MacroAssembler::align(int modulus) {
- while (offset() % modulus != 0) nop();
+ align(modulus, offset());
+}
+
+// Ensure that the code at target bytes offset from the current offset() is aligned
+// according to modulus.
+void MacroAssembler::align(int modulus, int target) {
+ int delta = target - offset();
+ while ((offset() + delta) % modulus != 0) nop();
}
void MacroAssembler::post_call_nop() {
@@ -1197,7 +1246,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
}
// Look up the method for a megamorphic invokeinterface call in a single pass over itable:
-// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICHolder
+// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICData
// - find a holder_klass (class that implements the method) vtable offset and get the method from vtable by index
// The target method is determined by .
// The receiver klass is in recv_klass.
diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
index e92e0ee6aa934..990e725d099eb 100644
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
@@ -720,6 +720,7 @@ class MacroAssembler: public Assembler {
// Alignment
void align(int modulus);
+ void align(int modulus, int target);
// nop
void post_call_nop();
@@ -1247,6 +1248,8 @@ class MacroAssembler: public Assembler {
// Emit the CompiledIC call idiom
address ic_call(address entry, jint method_index = 0);
+ static int ic_check_size();
+ int ic_check(int end_alignment);
public:
diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
index 82da734611693..216c1ff35092a 100644
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
@@ -30,7 +30,6 @@
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/oopMap.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
@@ -39,7 +38,6 @@
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "nativeInst_aarch64.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.inline.hpp"
#include "prims/methodHandles.hpp"
@@ -740,9 +738,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
address c2i_unverified_entry = __ pc();
Label skip_fixup;
- Label ok;
-
- Register holder = rscratch2;
+ Register data = rscratch2;
Register receiver = j_rarg0;
Register tmp = r10; // A call-clobbered register not used for arg passing
@@ -757,17 +753,12 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
{
__ block_comment("c2i_unverified_entry {");
- __ load_klass(rscratch1, receiver);
- __ ldr(tmp, Address(holder, CompiledICHolder::holder_klass_offset()));
- __ cmp(rscratch1, tmp);
- __ ldr(rmethod, Address(holder, CompiledICHolder::holder_metadata_offset()));
- __ br(Assembler::EQ, ok);
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- __ bind(ok);
// Method might have been compiled since the call site was patched to
// interpreted; if that is the case treat it as a miss so we can get
// the call site corrected.
+ __ ic_check(1 /* end_alignment */);
+ __ ldr(rmethod, Address(data, CompiledICData::speculated_method_offset()));
+
__ ldr(rscratch1, Address(rmethod, in_bytes(Method::code_offset())));
__ cbz(rscratch1, skip_fixup);
__ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
@@ -1118,7 +1109,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
__ b(exit);
CodeBuffer* cbuf = masm->code_section()->outer();
- address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call);
+ address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, tr_call);
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1183,7 +1174,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
}
CodeBuffer* cbuf = masm->code_section()->outer();
- address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call);
+ address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, tr_call);
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1539,25 +1530,15 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// restoring them except rfp. rfp is the only callee save register
// as far as the interpreter and the compiler(s) are concerned.
-
- const Register ic_reg = rscratch2;
const Register receiver = j_rarg0;
- Label hit;
Label exception_pending;
- assert_different_registers(ic_reg, receiver, rscratch1);
+ assert_different_registers(receiver, rscratch1);
__ verify_oop(receiver);
- __ cmp_klass(receiver, ic_reg, rscratch1);
- __ br(Assembler::EQ, hit);
-
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
+ __ ic_check(8 /* end_alignment */);
// Verified entry point must be aligned
- __ align(8);
-
- __ bind(hit);
-
int vep_offset = ((intptr_t)__ pc()) - start;
// If we have to make this method not-entrant we'll overwrite its
diff --git a/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp b/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp
index c895ff5cc0ec1..2bb53d16a3c97 100644
--- a/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/vtableStubs_aarch64.cpp
@@ -26,10 +26,10 @@
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_aarch64.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@@ -168,22 +168,22 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0");
// Entry arguments:
- // rscratch2: CompiledICHolder
+ // rscratch2: CompiledICData
// j_rarg0: Receiver
// This stub is called from compiled code which has no callee-saved registers,
// so all registers except arguments are free at this point.
const Register recv_klass_reg = r10;
- const Register holder_klass_reg = r16; // declaring interface klass (DECC)
+ const Register holder_klass_reg = r16; // declaring interface klass (DEFC)
const Register resolved_klass_reg = r17; // resolved interface klass (REFC)
const Register temp_reg = r11;
const Register temp_reg2 = r15;
- const Register icholder_reg = rscratch2;
+ const Register icdata_reg = rscratch2;
Label L_no_such_interface;
- __ ldr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
- __ ldr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
+ __ ldr(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset()));
+ __ ldr(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset()));
start_pc = __ pc();
diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad
index 6b18e76e6d7eb..1a833b08c4cf4 100644
--- a/src/hotspot/cpu/arm/arm.ad
+++ b/src/hotspot/cpu/arm/arm.ad
@@ -869,12 +869,7 @@ uint BoxLockNode::size(PhaseRegAlloc *ra_) const {
#define R_RTEMP "R_R12"
void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
st->print_cr("\nUEP:");
- if (UseCompressedClassPointers) {
- st->print_cr("\tLDR_w " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
- st->print_cr("\tdecode_klass " R_RTEMP);
- } else {
- st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
- }
+ st->print_cr("\tLDR " R_RTEMP ",[R_R0 + oopDesc::klass_offset_in_bytes]\t! Inline cache check");
st->print_cr("\tCMP " R_RTEMP ",R_R8" );
st->print ("\tB.NE SharedRuntime::handle_ic_miss_stub");
}
@@ -882,13 +877,7 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
C2_MacroAssembler _masm(&cbuf);
- Register iCache = reg_to_register_object(Matcher::inline_cache_reg_encode());
- assert(iCache == Ricklass, "should be");
- Register receiver = R0;
-
- __ load_klass(Rtemp, receiver);
- __ cmp(Rtemp, iCache);
- __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, noreg, ne);
+ __ ic_check(InteriorEntryAlignment);
}
uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
@@ -1241,7 +1230,7 @@ encode %{
emit_call_reloc(cbuf, as_MachCall(), $meth, rspec);
// Emit stubs for static call.
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf);
if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp
index 999309c02258d..16aeaa20c04b8 100644
--- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp
+++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp
@@ -161,10 +161,7 @@ void LIR_Assembler::osr_entry() {
int LIR_Assembler::check_icache() {
- Register receiver = LIR_Assembler::receiverOpr()->as_register();
- int offset = __ offset();
- __ inline_cache_check(receiver, Ricklass);
- return offset;
+ return __ ic_check(CodeEntryAlignment);
}
void LIR_Assembler::clinit_barrier(ciMethod* method) {
@@ -1950,7 +1947,7 @@ void LIR_Assembler::emit_static_call_stub() {
__ relocate(static_stub_Relocation::spec(call_pc));
// If not a single instruction, NativeMovConstReg::next_instruction_address()
// must jump over the whole following ldr_literal.
- // (See CompiledStaticCall::set_to_interpreted())
+ // (See CompiledDirectCall::set_to_interpreted())
#ifdef ASSERT
address ldr_site = __ pc();
#endif
diff --git a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp
index c09e54e0e57ad..d9d042bb2e4e7 100644
--- a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp
+++ b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp
@@ -43,16 +43,6 @@
// arm [macro]assembler) and used with care in the other C1 specific
// files.
-void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
- Label verified;
- load_klass(Rtemp, receiver);
- cmp(Rtemp, iCache);
- b(verified, eq); // jump over alignment no-ops
- jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type);
- align(CodeEntryAlignment);
- bind(verified);
-}
-
void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) {
assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect");
assert((frame_size_in_bytes % StackAlignmentInBytes) == 0, "frame size should be aligned");
diff --git a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp
index 62faa6170833b..9862a074a687f 100644
--- a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp
+++ b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp
@@ -37,7 +37,6 @@
#include "interpreter/interpreter.hpp"
#include "memory/universe.hpp"
#include "nativeInst_arm.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "register_arm.hpp"
diff --git a/src/hotspot/cpu/arm/compiledIC_arm.cpp b/src/hotspot/cpu/arm/compiledIC_arm.cpp
index 2d4187b7d6c6a..71389d2353d66 100644
--- a/src/hotspot/cpu/arm/compiledIC_arm.cpp
+++ b/src/hotspot/cpu/arm/compiledIC_arm.cpp
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/nmethod.hpp"
#include "logging/log.hpp"
@@ -37,7 +36,7 @@
#if COMPILER2_OR_JVMCI
#define __ _masm.
// emit call stub, compiled java to interpreter
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
// Stub is fixed up when the corresponding call is converted from calling
// compiled code to calling interpreted code.
// set (empty), R9
@@ -59,7 +58,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
InlinedMetadata object_literal(nullptr);
// single instruction, see NativeMovConstReg::next_instruction_address() in
- // CompiledStaticCall::set_to_interpreted()
+ // CompiledDirectCall::set_to_interpreted()
__ ldr_literal(Rmethod, object_literal);
__ set_inst_mark(); // Who uses this?
@@ -87,32 +86,25 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
#undef __
// Relocation entries for call stub, compiled java to interpreter.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
return 10; // 4 in emit_to_interp_stub + 1 in Java_Static_Call
}
#endif // COMPILER2_OR_JVMCI
-int CompiledStaticCall::to_trampoline_stub_size() {
+int CompiledDirectCall::to_trampoline_stub_size() {
// ARM doesn't use trampolines.
return 0;
}
// size of C2 call stub, compiled java to interpreter
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
return 8 * NativeInstruction::instruction_size;
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
address stub = find_stub();
guarantee(stub != nullptr, "stub not found");
- {
- ResourceMark rm;
- log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
- p2i(instruction_address()),
- callee->name_and_sig_as_C_string());
- }
-
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
@@ -128,7 +120,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
set_destination_mt_safe(stub);
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
// Reset stub.
address stub = static_stub->addr();
assert(stub != nullptr, "stub not found");
@@ -144,7 +136,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
// Non-product mode code
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
// Verify call.
_call->verify();
_call->verify_alignment();
diff --git a/src/hotspot/cpu/arm/icBuffer_arm.cpp b/src/hotspot/cpu/arm/icBuffer_arm.cpp
deleted file mode 100644
index e3a1c148ec6a0..0000000000000
--- a/src/hotspot/cpu/arm/icBuffer_arm.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2008, 2016, 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/assembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_arm.hpp"
-#include "oops/oop.inline.hpp"
-
-#define __ masm->
-
-int InlineCacheBuffer::ic_stub_code_size() {
- return (4 * Assembler::InstructionSize);
-}
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) {
- ResourceMark rm;
- CodeBuffer code(code_begin, ic_stub_code_size());
- MacroAssembler* masm = new MacroAssembler(&code);
-
- InlinedAddress oop_literal((address) cached_value);
- __ ldr_literal(Ricklass, oop_literal);
- // FIXME: OK to remove reloc here?
- __ patchable_jump(entry_point, relocInfo::runtime_call_type, Rtemp);
- __ bind_literal(oop_literal);
- __ flush();
-}
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- address jump_address;
- jump_address = code_begin + NativeInstruction::instruction_size;
- NativeJump* jump = nativeJump_at(jump_address);
- return jump->jump_destination();
-}
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin);
- return (void*)move->data();
-}
-
-#undef __
diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.cpp b/src/hotspot/cpu/arm/macroAssembler_arm.cpp
index b827e69d02233..99d619bddb55a 100644
--- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp
+++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp
@@ -28,6 +28,7 @@
#include "asm/assembler.inline.hpp"
#include "asm/macroAssembler.hpp"
#include "ci/ciEnv.hpp"
+#include "code/compiledIC.hpp"
#include "code/nativeInst.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/barrierSet.hpp"
@@ -297,11 +298,13 @@ Address MacroAssembler::receiver_argument_address(Register params_base, Register
return Address(tmp, -Interpreter::stackElementSize);
}
+void MacroAssembler::align(int modulus, int target) {
+ int delta = target - offset();
+ while ((offset() + delta) % modulus != 0) nop();
+}
void MacroAssembler::align(int modulus) {
- while (offset() % modulus != 0) {
- nop();
- }
+ align(modulus, offset());
}
int MacroAssembler::set_last_Java_frame(Register last_java_sp,
@@ -1860,3 +1863,31 @@ void MacroAssembler::lightweight_unlock(Register obj, Register t1, Register t2,
// Fallthrough: success
}
+
+int MacroAssembler::ic_check_size() {
+ return NativeInstruction::instruction_size * 7;
+}
+
+int MacroAssembler::ic_check(int end_alignment) {
+ Register receiver = j_rarg0;
+ Register tmp1 = R4;
+ Register tmp2 = R5;
+
+ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align
+ // before the inline cache check here, and not after
+ align(end_alignment, offset() + ic_check_size());
+
+ int uep_offset = offset();
+
+ ldr(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ ldr(tmp2, Address(Ricklass, CompiledICData::speculated_klass_offset()));
+ cmp(tmp1, tmp2);
+
+ Label dont;
+ b(dont, eq);
+ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type);
+ bind(dont);
+ return uep_offset;
+}
diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.hpp b/src/hotspot/cpu/arm/macroAssembler_arm.hpp
index d9e49ab986c3a..691c8fa70ee8b 100644
--- a/src/hotspot/cpu/arm/macroAssembler_arm.hpp
+++ b/src/hotspot/cpu/arm/macroAssembler_arm.hpp
@@ -221,6 +221,7 @@ class MacroAssembler: public Assembler {
inline bool ignore_non_patchable_relocations() { return true; }
void align(int modulus);
+ void align(int modulus, int target);
// Support for VM calls
//
@@ -1077,6 +1078,9 @@ class MacroAssembler: public Assembler {
void safepoint_poll(Register tmp1, Label& slow_path);
void get_polling_page(Register dest);
void read_polling_page(Register dest, relocInfo::relocType rtype);
+
+ static int ic_check_size();
+ int ic_check(int end_alignment);
};
diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.cpp b/src/hotspot/cpu/arm/nativeInst_arm_32.cpp
index 23ee01d335264..6a4062f29b3ba 100644
--- a/src/hotspot/cpu/arm/nativeInst_arm_32.cpp
+++ b/src/hotspot/cpu/arm/nativeInst_arm_32.cpp
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "memory/resourceArea.hpp"
#include "nativeInst_arm.hpp"
#include "oops/oop.inline.hpp"
diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp
index 7006d7709813a..15b57188730df 100644
--- a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp
+++ b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp
@@ -385,7 +385,7 @@ class NativeMovConstReg: public NativeInstruction {
}
void set_pc_relative_offset(address addr, address pc);
address next_instruction_address() const {
- // NOTE: CompiledStaticCall::set_to_interpreted() calls this but
+ // NOTE: CompiledDirectCall::set_to_interpreted() calls this but
// are restricted to single-instruction ldr. No need to jump over
// several instructions.
assert(is_ldr_literal(), "Should only use single-instructions load");
diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
index 716c7b7575e9c..3792fab082ba6 100644
--- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
+++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
@@ -24,15 +24,14 @@
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/oopMap.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
#include "interpreter/interpreter.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/jniHandles.hpp"
@@ -626,12 +625,9 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
Label skip_fixup;
const Register receiver = R0;
const Register holder_klass = Rtemp; // XXX should be OK for C2 but not 100% sure
- const Register receiver_klass = R4;
- __ load_klass(receiver_klass, receiver);
- __ ldr(holder_klass, Address(Ricklass, CompiledICHolder::holder_klass_offset()));
- __ ldr(Rmethod, Address(Ricklass, CompiledICHolder::holder_metadata_offset()));
- __ cmp(receiver_klass, holder_klass);
+ __ ic_check(1 /* end_alignment */);
+ __ ldr(Rmethod, Address(Ricklass, CompiledICData::speculated_method_offset()));
__ ldr(Rtemp, Address(Rmethod, Method::code_offset()), eq);
__ cmp(Rtemp, 0, eq);
@@ -819,21 +815,14 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Unverified entry point
address start = __ pc();
- // Inline cache check, same as in C1_MacroAssembler::inline_cache_check()
const Register receiver = R0; // see receiverOpr()
- __ load_klass(Rtemp, receiver);
- __ cmp(Rtemp, Ricklass);
- Label verified;
-
- __ b(verified, eq); // jump over alignment no-ops too
- __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, Rtemp);
- __ align(CodeEntryAlignment);
+ __ verify_oop(receiver);
+ // Inline cache check
+ __ ic_check(CodeEntryAlignment /* end_alignment */);
// Verified entry point
- __ bind(verified);
int vep_offset = __ pc() - start;
-
if ((InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) || (method->intrinsic_id() == vmIntrinsics::_identityHashCode)) {
// Object.hashCode, System.identityHashCode can pull the hashCode from the header word
// instead of doing a full VM transition once it's been computed.
diff --git a/src/hotspot/cpu/arm/vtableStubs_arm.cpp b/src/hotspot/cpu/arm/vtableStubs_arm.cpp
index 539e288f63fb2..1229b5073f506 100644
--- a/src/hotspot/cpu/arm/vtableStubs_arm.cpp
+++ b/src/hotspot/cpu/arm/vtableStubs_arm.cpp
@@ -25,10 +25,10 @@
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_arm.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "oops/klass.inline.hpp"
@@ -160,7 +160,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ load_klass(Rclass, R0);
// Receiver subtype check against REFC.
- __ ldr(Rintf, Address(Ricklass, CompiledICHolder::holder_klass_offset()));
+ __ ldr(Rintf, Address(Ricklass, CompiledICData::itable_refc_klass_offset()));
__ lookup_interface_method(// inputs: rec. class, interface, itable index
Rclass, Rintf, noreg,
// outputs: temp reg1, temp reg2
@@ -171,7 +171,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
start_pc = __ pc();
// Get Method* and entry point for compiler
- __ ldr(Rintf, Address(Ricklass, CompiledICHolder::holder_metadata_offset()));
+ __ ldr(Rintf, Address(Ricklass, CompiledICData::itable_defc_klass_offset()));
__ lookup_interface_method(// inputs: rec. class, interface, itable index
Rclass, Rintf, itable_index,
// outputs: temp reg1, temp reg2, temp reg3
diff --git a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
index 47b681ce26be4..d78dec964cbb0 100644
--- a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
+++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
@@ -451,7 +451,7 @@ inline void Assembler::bcctrl(int boint, int biint, int bhint, relocInfo::relocT
// helper function for b
inline bool Assembler::is_within_range_of_b(address a, address pc) {
- // Guard against illegal branch targets, e.g. -1 (see CompiledStaticCall and ad-file).
+ // Guard against illegal branch targets, e.g. -1 (see CompiledDirectCall and ad-file).
if ((((uint64_t)a) & 0x3) != 0) return false;
const int range = 1 << (29-6); // li field is from bit 6 to bit 29.
@@ -465,7 +465,7 @@ inline bool Assembler::is_within_range_of_b(address a, address pc) {
// helper functions for bcxx.
inline bool Assembler::is_within_range_of_bcxx(address a, address pc) {
- // Guard against illegal branch targets, e.g. -1 (see CompiledStaticCall and ad-file).
+ // Guard against illegal branch targets, e.g. -1 (see CompiledDirectCall and ad-file).
if ((((uint64_t)a) & 0x3) != 0) return false;
const int range = 1 << (29-16); // bd field is from bit 16 to bit 29.
diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp
index d316c2b3db2be..4b29bcf57e4d3 100644
--- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp
@@ -77,9 +77,7 @@ int LIR_Assembler::initial_frame_size_in_bytes() const {
// we fetch the class of the receiver and compare it with the cached class.
// If they do not match we jump to slow case.
int LIR_Assembler::check_icache() {
- int offset = __ offset();
- __ inline_cache_check(R3_ARG1, R19_inline_cache_reg);
- return offset;
+ return __ ic_check(CodeEntryAlignment);
}
void LIR_Assembler::clinit_barrier(ciMethod* method) {
diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp
index 577dcae25f4bc..b379d4141a32b 100644
--- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp
@@ -40,29 +40,6 @@
#include "utilities/macros.hpp"
#include "utilities/powerOfTwo.hpp"
-void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
- const Register temp_reg = R12_scratch2;
- Label Lmiss;
-
- verify_oop(receiver, FILE_AND_LINE);
- load_klass_check_null(temp_reg, receiver, &Lmiss);
-
- if (TrapBasedICMissChecks && TrapBasedNullChecks) {
- trap_ic_miss_check(temp_reg, iCache);
- } else {
- Label Lok;
- cmpd(CCR0, temp_reg, iCache);
- beq(CCR0, Lok);
- bind(Lmiss);
- //load_const_optimized(temp_reg, SharedRuntime::get_ic_miss_stub(), R0);
- calculate_address_from_global_toc(temp_reg, SharedRuntime::get_ic_miss_stub(), true, true, false);
- mtctr(temp_reg);
- bctr();
- align(32, 12);
- bind(Lok);
- }
-}
-
void C1_MacroAssembler::explicit_null_check(Register base) {
Unimplemented();
diff --git a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp
index 2ba6a6bca4e03..63914c5d1cb93 100644
--- a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp
+++ b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp
@@ -34,7 +34,6 @@
#include "gc/shared/cardTableBarrierSet.hpp"
#include "interpreter/interpreter.hpp"
#include "nativeInst_ppc.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "register_ppc.hpp"
diff --git a/src/hotspot/cpu/ppc/compiledIC_ppc.cpp b/src/hotspot/cpu/ppc/compiledIC_ppc.cpp
index 54f9cfa936797..355ac4815d551 100644
--- a/src/hotspot/cpu/ppc/compiledIC_ppc.cpp
+++ b/src/hotspot/cpu/ppc/compiledIC_ppc.cpp
@@ -26,7 +26,6 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/mutexLocker.hpp"
@@ -37,7 +36,7 @@
// ----------------------------------------------------------------------------
-// A PPC CompiledDirectStaticCall looks like this:
+// A PPC CompiledDirectCall looks like this:
//
// >>>> consts
//
@@ -79,7 +78,7 @@
const int IC_pos_in_java_to_interp_stub = 8;
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = nullptr*/) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = nullptr*/) {
#ifdef COMPILER2
if (mark == nullptr) {
// Get the mark within main instrs section which is set to the address of the call.
@@ -91,7 +90,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/*
MacroAssembler _masm(&cbuf);
// Start the stub.
- address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size());
+ address stub = __ start_a_stub(CompiledDirectCall::to_interp_stub_size());
if (stub == nullptr) {
return nullptr; // CodeCache is full
}
@@ -135,7 +134,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/*
// FIXME: Assert that the stub can be identified and patched.
// Java_to_interp_stub_size should be good.
- assert((__ offset() - stub_start_offset) <= CompiledStaticCall::to_interp_stub_size(),
+ assert((__ offset() - stub_start_offset) <= CompiledDirectCall::to_interp_stub_size(),
"should be good size");
assert(!is_NativeCallTrampolineStub_at(__ addr_at(stub_start_offset)),
"must not confuse java_to_interp with trampoline stubs");
@@ -153,27 +152,20 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/*
// Size of java_to_interp stub, this doesn't need to be accurate but it must
// be larger or equal to the real size of the stub.
// Used for optimization in Compile::Shorten_branches.
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
return 12 * BytesPerInstWord;
}
// Relocation entries for call stub, compiled java to interpreter.
// Used for optimization in Compile::Shorten_branches.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
return 5;
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
address stub = find_stub();
guarantee(stub != nullptr, "stub not found");
- {
- ResourceMark rm;
- log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
- p2i(instruction_address()),
- callee->name_and_sig_as_C_string());
- }
-
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + IC_pos_in_java_to_interp_stub);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
@@ -188,7 +180,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
set_destination_mt_safe(stub);
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
// Reset stub.
address stub = static_stub->addr();
assert(stub != nullptr, "stub not found");
@@ -204,7 +196,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
// Non-product mode code
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
// Verify call.
_call->verify();
_call->verify_alignment();
diff --git a/src/hotspot/cpu/ppc/icBuffer_ppc.cpp b/src/hotspot/cpu/ppc/icBuffer_ppc.cpp
deleted file mode 100644
index 4157a5b0fd788..0000000000000
--- a/src/hotspot/cpu/ppc/icBuffer_ppc.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2013 SAP SE. 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/assembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_ppc.hpp"
-#include "oops/oop.inline.hpp"
-
-#define __ masm.
-
-int InlineCacheBuffer::ic_stub_code_size() {
- return MacroAssembler::load_const_size + MacroAssembler::b64_patchable_size;
-}
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) {
- ResourceMark rm;
- CodeBuffer code(code_begin, ic_stub_code_size());
- MacroAssembler masm(&code);
- // Note: even though the code contains an embedded metadata, we do not need reloc info
- // because
- // (1) the metadata is old (i.e., doesn't matter for scavenges)
- // (2) these ICStubs are removed *before* a GC happens, so the roots disappear.
-
- // Load the oop ...
- __ load_const(R19_method, (address) cached_value, R0);
- // ... and jump to entry point.
- __ b64_patchable((address) entry_point, relocInfo::none);
-
- __ flush();
-}
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object
- NativeJump* jump = nativeJump_at(move->next_instruction_address());
- return jump->jump_destination();
-}
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object
- void* o = (void*)move->data();
- return o;
-}
-
diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
index b9d1cdb19ac9d..fe19cf0350020 100644
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "gc/shared/barrierSet.hpp"
@@ -1195,6 +1196,81 @@ void MacroAssembler::post_call_nop() {
assert(is_post_call_nop(*(int*)(pc() - 4)), "post call not not found");
}
+int MacroAssembler::ic_check_size() {
+ bool implicit_null_checks_available = ImplicitNullChecks && os::zero_page_read_protected(),
+ use_fast_receiver_null_check = implicit_null_checks_available || TrapBasedNullChecks,
+ use_trap_based_null_check = !implicit_null_checks_available && TrapBasedNullChecks;
+
+ int num_ins;
+ if (use_fast_receiver_null_check && TrapBasedICMissChecks) {
+ num_ins = 3;
+ if (use_trap_based_null_check) num_ins += 1;
+ } else {
+ num_ins = 7;
+ if (!implicit_null_checks_available) num_ins += 2;
+ }
+ return num_ins * BytesPerInstWord;
+}
+
+int MacroAssembler::ic_check(int end_alignment) {
+ bool implicit_null_checks_available = ImplicitNullChecks && os::zero_page_read_protected(),
+ use_fast_receiver_null_check = implicit_null_checks_available || TrapBasedNullChecks,
+ use_trap_based_null_check = !implicit_null_checks_available && TrapBasedNullChecks;
+
+ Register receiver = R3_ARG1;
+ Register data = R19_inline_cache_reg;
+ Register tmp1 = R11_scratch1;
+ Register tmp2 = R12_scratch2;
+
+ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align
+ // before the inline cache check here, and not after
+ align(end_alignment, end_alignment, end_alignment - ic_check_size());
+
+ int uep_offset = offset();
+
+ if (use_fast_receiver_null_check && TrapBasedICMissChecks) {
+ // Fast version which uses SIGTRAP
+
+ if (use_trap_based_null_check) {
+ trap_null_check(receiver);
+ }
+ if (UseCompressedClassPointers) {
+ lwz(tmp1, oopDesc::klass_offset_in_bytes(), receiver);
+ } else {
+ ld(tmp1, oopDesc::klass_offset_in_bytes(), receiver);
+ }
+ ld(tmp2, in_bytes(CompiledICData::speculated_klass_offset()), data);
+ trap_ic_miss_check(tmp1, tmp2);
+
+ } else {
+ // Slower version which doesn't use SIGTRAP
+
+ // Load stub address using toc (fixed instruction size, unlike load_const_optimized)
+ calculate_address_from_global_toc(tmp1, SharedRuntime::get_ic_miss_stub(),
+ true, true, false); // 2 instructions
+ mtctr(tmp1);
+
+ if (!implicit_null_checks_available) {
+ cmpdi(CCR0, receiver, 0);
+ beqctr(CCR0);
+ }
+ if (UseCompressedClassPointers) {
+ lwz(tmp1, oopDesc::klass_offset_in_bytes(), receiver);
+ } else {
+ ld(tmp1, oopDesc::klass_offset_in_bytes(), receiver);
+ }
+ ld(tmp2, in_bytes(CompiledICData::speculated_klass_offset()), data);
+ cmpd(CCR0, tmp1, tmp2);
+ bnectr(CCR0);
+ }
+
+ assert((offset() % end_alignment) == 0, "Misaligned verified entry point");
+
+ return uep_offset;
+}
+
void MacroAssembler::call_VM_base(Register oop_result,
Register last_java_sp,
address entry_point,
diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
index cddc8b92fa09a..ec370a450ac35 100644
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp
@@ -367,6 +367,9 @@ class MacroAssembler: public Assembler {
Register toc);
#endif
+ static int ic_check_size();
+ int ic_check(int end_alignment);
+
protected:
// It is imperative that all calls into the VM are handled via the
diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad
index 783edf727b3bc..6f5e6dabec5a2 100644
--- a/src/hotspot/cpu/ppc/ppc.ad
+++ b/src/hotspot/cpu/ppc/ppc.ad
@@ -1978,42 +1978,7 @@ void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
// This is the unverified entry point.
C2_MacroAssembler _masm(&cbuf);
- // Inline_cache contains a klass.
- Register ic_klass = as_Register(Matcher::inline_cache_reg_encode());
- Register receiver_klass = R12_scratch2; // tmp
-
- assert_different_registers(ic_klass, receiver_klass, R11_scratch1, R3_ARG1);
- assert(R11_scratch1 == R11, "need prologue scratch register");
-
- // Check for nullptr argument if we don't have implicit null checks.
- if (!ImplicitNullChecks || !os::zero_page_read_protected()) {
- if (TrapBasedNullChecks) {
- __ trap_null_check(R3_ARG1);
- } else {
- Label valid;
- __ cmpdi(CCR0, R3_ARG1, 0);
- __ bne_predict_taken(CCR0, valid);
- // We have a null argument, branch to ic_miss_stub.
- __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(),
- relocInfo::runtime_call_type);
- __ bind(valid);
- }
- }
- // Assume argument is not nullptr, load klass from receiver.
- __ load_klass(receiver_klass, R3_ARG1);
-
- if (TrapBasedICMissChecks) {
- __ trap_ic_miss_check(receiver_klass, ic_klass);
- } else {
- Label valid;
- __ cmpd(CCR0, receiver_klass, ic_klass);
- __ beq_predict_taken(CCR0, valid);
- // We have an unexpected klass, branch to ic_miss_stub.
- __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(),
- relocInfo::runtime_call_type);
- __ bind(valid);
- }
-
+ __ ic_check(CodeEntryAlignment);
// Argument is valid and klass is as expected, continue.
}
@@ -3452,7 +3417,7 @@ encode %{
__ bl(__ pc()); // Emits a relocation.
// The stub for call to interpreter.
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf);
if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
@@ -3507,7 +3472,7 @@ encode %{
// Create the nodes for loading the IC from the TOC.
loadConLNodesTuple loadConLNodes_IC =
- loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong)Universe::non_oop_word()),
+ loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong) Universe::non_oop_word()),
OptoReg::Name(R19_H_num), OptoReg::Name(R19_num));
// Create the call node.
diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
index ebe918785edc0..5a080adc7a9fa 100644
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
+++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
@@ -27,7 +27,6 @@
#include "asm/macroAssembler.inline.hpp"
#include "code/debugInfoRec.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "frame_ppc.hpp"
#include "compiler/oopMap.hpp"
@@ -35,7 +34,6 @@
#include "interpreter/interpreter.hpp"
#include "interpreter/interp_masm.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/continuation.hpp"
@@ -1174,8 +1172,8 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
BLOCK_COMMENT("c2i unverified entry");
c2i_unverified_entry = __ pc();
- // inline_cache contains a compiledICHolder
- const Register ic = R19_method;
+ // inline_cache contains a CompiledICData
+ const Register ic = R19_inline_cache_reg;
const Register ic_klass = R11_scratch1;
const Register receiver_klass = R12_scratch2;
const Register code = R21_tmp1;
@@ -1186,45 +1184,10 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
Label call_interpreter;
- assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()),
- "klass offset should reach into any page");
- // Check for null argument if we don't have implicit null checks.
- if (!ImplicitNullChecks || !os::zero_page_read_protected()) {
- if (TrapBasedNullChecks) {
- __ trap_null_check(R3_ARG1);
- } else {
- Label valid;
- __ cmpdi(CCR0, R3_ARG1, 0);
- __ bne_predict_taken(CCR0, valid);
- // We have a null argument, branch to ic_miss_stub.
- __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(),
- relocInfo::runtime_call_type);
- __ BIND(valid);
- }
- }
- // Assume argument is not null, load klass from receiver.
- __ load_klass(receiver_klass, R3_ARG1);
-
- __ ld(ic_klass, CompiledICHolder::holder_klass_offset(), ic);
-
- if (TrapBasedICMissChecks) {
- __ trap_ic_miss_check(receiver_klass, ic_klass);
- } else {
- Label valid;
- __ cmpd(CCR0, receiver_klass, ic_klass);
- __ beq_predict_taken(CCR0, valid);
- // We have an unexpected klass, branch to ic_miss_stub.
- __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(),
- relocInfo::runtime_call_type);
- __ BIND(valid);
- }
-
+ __ ic_check(4 /* end_alignment */);
+ __ ld(R19_method, CompiledICData::speculated_method_offset(), ic);
// Argument is valid and klass is as expected, continue.
- // Extract method from inline cache, verified entry point needs it.
- __ ld(R19_method, CompiledICHolder::holder_metadata_offset(), ic);
- assert(R19_method == ic, "the inline cache register is dead here");
-
__ ld(code, method_(code));
__ cmpdi(CCR0, code, 0);
__ ld(ientry, method_(interpreter_entry)); // preloaded
@@ -1798,7 +1761,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
// static stub for the call above
CodeBuffer* cbuf = masm->code_section()->outer();
- stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, c2i_call_pc);
+ stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, c2i_call_pc);
guarantee(stub != nullptr, "no space for static stub");
}
@@ -1891,7 +1854,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
// static stub for the call above
CodeBuffer* cbuf = masm->code_section()->outer();
- stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, call_pc);
+ stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, call_pc);
guarantee(stub != nullptr, "no space for static stub");
}
@@ -2188,7 +2151,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
intptr_t frame_done_pc;
intptr_t oopmap_pc;
- Label ic_miss;
Label handle_pending_exception;
Register r_callers_sp = R21;
@@ -2212,19 +2174,9 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// Check ic: object class == cached class?
if (!method_is_static) {
- Register ic = R19_inline_cache_reg;
- Register receiver_klass = r_temp_1;
-
- __ cmpdi(CCR0, R3_ARG1, 0);
- __ beq(CCR0, ic_miss);
- __ verify_oop(R3_ARG1, FILE_AND_LINE);
- __ load_klass(receiver_klass, R3_ARG1);
-
- __ cmpd(CCR0, receiver_klass, ic);
- __ bne(CCR0, ic_miss);
+ __ ic_check(4 /* end_alignment */);
}
-
// Generate the Verified Entry Point (VEP).
// --------------------------------------------------------------------------
vep_start_pc = (intptr_t)__ pc();
@@ -2704,16 +2656,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ b64_patchable((address)StubRoutines::forward_exception_entry(),
relocInfo::runtime_call_type);
- // Handler for a cache miss (out-of-line).
- // --------------------------------------------------------------------------
-
- if (!method_is_static) {
- __ bind(ic_miss);
-
- __ b64_patchable((address)SharedRuntime::get_ic_miss_stub(),
- relocInfo::runtime_call_type);
- }
-
// Done.
// --------------------------------------------------------------------------
diff --git a/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp b/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp
index fe4eb3df8f12f..28ba04d833bed 100644
--- a/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp
+++ b/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp
@@ -25,10 +25,10 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_ppc.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/klassVtable.hpp"
@@ -181,13 +181,13 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ load_klass_check_null(rcvr_klass, R3_ARG1);
// Receiver subtype check against REFC.
- __ ld(interface, CompiledICHolder::holder_klass_offset(), R19_method);
+ __ ld(interface, CompiledICData::itable_refc_klass_offset(), R19_method);
__ lookup_interface_method(rcvr_klass, interface, noreg,
R0, tmp1, tmp2,
L_no_such_interface, /*return_method=*/ false);
// Get Method* and entrypoint for compiler
- __ ld(interface, CompiledICHolder::holder_metadata_offset(), R19_method);
+ __ ld(interface, CompiledICData::itable_defc_klass_offset(), R19_method);
__ lookup_interface_method(rcvr_klass, interface, itable_index,
R19_method, tmp1, tmp2,
L_no_such_interface, /*return_method=*/ true);
diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp
index 0bbf3771a04bc..e3ec023aef260 100644
--- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp
@@ -51,7 +51,6 @@
#endif
NEEDS_CLEANUP // remove this definitions ?
-const Register IC_Klass = t1; // where the IC klass is cached
const Register SYNC_header = x10; // synchronization header
const Register SHIFT_count = x10; // where count for shift operations must be
@@ -265,26 +264,7 @@ void LIR_Assembler::osr_entry() {
// inline cache check; done before the frame is built.
int LIR_Assembler::check_icache() {
- Register receiver = FrameMap::receiver_opr->as_register();
- Register ic_klass = IC_Klass;
- int start_offset = __ offset();
- Label dont;
- __ inline_cache_check(receiver, ic_klass, dont);
-
- // if icache check fails, then jump to runtime routine
- // Note: RECEIVER must still contain the receiver!
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- // We align the verified entry point unless the method body
- // (including its inline cache check) will fit in a single 64-byte
- // icache line.
- if (!method()->is_accessor() || __ offset() - start_offset > 4 * 4) {
- // force alignment after the cache check.
- __ align(CodeEntryAlignment);
- }
-
- __ bind(dont);
- return start_offset;
+ return __ ic_check(CodeEntryAlignment);
}
void LIR_Assembler::jobject2reg(jobject o, Register reg) {
@@ -1398,7 +1378,7 @@ void LIR_Assembler::emit_static_call_stub() {
__ relocate(static_stub_Relocation::spec(call_pc));
__ emit_static_call_stub();
- assert(__ offset() - start + CompiledStaticCall::to_trampoline_stub_size()
+ assert(__ offset() - start + CompiledDirectCall::to_trampoline_stub_size()
<= call_stub_size(), "stub too big");
__ end_a_stub();
}
diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp
index b088498e6fc08..ce23213776c08 100644
--- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp
@@ -68,7 +68,7 @@ friend class ArrayCopyStub;
enum {
// See emit_static_call_stub for detail
- // CompiledStaticCall::to_interp_stub_size() (14) + CompiledStaticCall::to_trampoline_stub_size() (1 + 3 + address)
+ // CompiledDirectCall::to_interp_stub_size() (14) + CompiledDirectCall::to_trampoline_stub_size() (1 + 3 + address)
_call_stub_size = 14 * NativeInstruction::instruction_size +
(NativeInstruction::instruction_size + NativeCallTrampolineStub::instruction_size),
// See emit_exception_handler for detail
diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp
index 6c1dce0de1598..2961b1a91ceab 100644
--- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp
@@ -314,15 +314,6 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register tmp1
verify_oop(obj);
}
-void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache, Label &L) {
- verify_oop(receiver);
- // explicit null check not needed since load from [klass_offset] causes a trap
- // check against inline cache
- assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check");
- assert_different_registers(receiver, iCache, t0, t2);
- cmp_klass(receiver, iCache, t0, t2 /* call-clobbered t2 as a tmp */, L);
-}
-
void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) {
assert(bang_size_in_bytes >= framesize, "stack bang size incorrect");
// Make sure there is enough stack space for this method's activation.
diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp
index b76163a30841d..9fa8939837a85 100644
--- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp
+++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp
@@ -37,7 +37,6 @@
#include "interpreter/interpreter.hpp"
#include "memory/universe.hpp"
#include "nativeInst_riscv.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "register_riscv.hpp"
diff --git a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp
index e29dee56de8d8..fdb2bcb06ff97 100644
--- a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp
+++ b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp
@@ -27,7 +27,6 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
@@ -37,7 +36,7 @@
// ----------------------------------------------------------------------------
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
precond(cbuf.stubs()->start() != badAddress);
precond(cbuf.stubs()->end() != badAddress);
// Stub is fixed up when the corresponding call is converted from
@@ -69,11 +68,11 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
}
#undef __
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
return MacroAssembler::static_call_stub_size();
}
-int CompiledStaticCall::to_trampoline_stub_size() {
+int CompiledDirectCall::to_trampoline_stub_size() {
// Somewhat pessimistically, we count 4 instructions here (although
// there are only 3) because we sometimes emit an alignment nop.
// Trampoline stubs are always word aligned.
@@ -81,21 +80,14 @@ int CompiledStaticCall::to_trampoline_stub_size() {
}
// Relocation entries for call stub, compiled java to interpreter.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
return 4; // 3 in emit_to_interp_stub + 1 in emit_call
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
address stub = find_stub();
guarantee(stub != nullptr, "stub not found");
- {
- ResourceMark rm;
- log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
- p2i(instruction_address()),
- callee->name_and_sig_as_C_string());
- }
-
// Creation also verifies the object.
NativeMovConstReg* method_holder
= nativeMovConstReg_at(stub);
@@ -112,7 +104,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
set_destination_mt_safe(stub);
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
// Reset stub.
address stub = static_stub->addr();
assert(stub != nullptr, "stub not found");
@@ -129,7 +121,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
// Non-product mode code
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
// Verify call.
_call->verify();
_call->verify_alignment();
diff --git a/src/hotspot/cpu/riscv/icBuffer_riscv.cpp b/src/hotspot/cpu/riscv/icBuffer_riscv.cpp
deleted file mode 100644
index ab904817816fc..0000000000000
--- a/src/hotspot/cpu/riscv/icBuffer_riscv.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014, Red Hat Inc. All rights reserved.
- * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/macroAssembler.hpp"
-#include "asm/macroAssembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_riscv.hpp"
-#include "oops/oop.inline.hpp"
-
-int InlineCacheBuffer::ic_stub_code_size() {
- // 6: auipc + ld + auipc + jalr + address(2 * instruction_size)
- return 6 * NativeInstruction::instruction_size;
-}
-
-#define __ masm->
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) {
- assert_cond(code_begin != nullptr && entry_point != nullptr);
- ResourceMark rm;
- CodeBuffer code(code_begin, ic_stub_code_size());
- MacroAssembler* masm = new MacroAssembler(&code);
- // Note: even though the code contains an embedded value, we do not need reloc info
- // because
- // (1) the value is old (i.e., doesn't matter for scavenges)
- // (2) these ICStubs are removed *before* a GC happens, so the roots disappear
-
- address start = __ pc();
- Label l;
- __ ld(t1, l);
- __ far_jump(ExternalAddress(entry_point));
- __ align(wordSize);
- __ bind(l);
- __ emit_int64((intptr_t)cached_value);
- // Only need to invalidate the 1st two instructions - not the whole ic stub
- ICache::invalidate_range(code_begin, InlineCacheBuffer::ic_stub_code_size());
- assert(__ pc() - start == ic_stub_code_size(), "must be");
-}
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object
- NativeJump* jump = nativeJump_at(move->next_instruction_address());
- return jump->jump_destination();
-}
-
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- // The word containing the cached value is at the end of this IC buffer
- uintptr_t *p = (uintptr_t *)(code_begin + ic_stub_code_size() - wordSize);
- void* o = (void*)*p;
- return o;
-}
diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
index ce336c16aa718..96e07319e843f 100644
--- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
@@ -27,6 +27,7 @@
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
@@ -634,8 +635,8 @@ void MacroAssembler::unimplemented(const char* what) {
}
void MacroAssembler::emit_static_call_stub() {
- IncompressibleRegion ir(this); // Fixed length: see CompiledStaticCall::to_interp_stub_size().
- // CompiledDirectStaticCall::set_to_interpreted knows the
+ IncompressibleRegion ir(this); // Fixed length: see CompiledDirectCall::to_interp_stub_size().
+ // CompiledDirectCall::set_to_interpreted knows the
// exact layout of this stub.
mov_metadata(xmethod, (Metadata*)nullptr);
@@ -2542,7 +2543,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
}
// Look up the method for a megamorphic invokeinterface call in a single pass over itable:
-// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICHolder
+// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICData
// - find a holder_klass (class that implements the method) vtable offset and get the method from vtable by index
// The target method is determined by .
// The receiver klass is in recv_klass.
@@ -3542,6 +3543,48 @@ address MacroAssembler::ic_call(address entry, jint method_index) {
return trampoline_call(Address(entry, rh));
}
+int MacroAssembler::ic_check_size() {
+ // No compressed
+ return (NativeInstruction::instruction_size * (2 /* 2 loads */ + 1 /* branch */)) +
+ far_branch_size();
+}
+
+int MacroAssembler::ic_check(int end_alignment) {
+ IncompressibleRegion ir(this);
+ Register receiver = j_rarg0;
+ Register data = t1;
+
+ Register tmp1 = t0; // t0 always scratch
+ // t2 is saved on call, thus should have been saved before this check.
+ // Hence we can clobber it.
+ Register tmp2 = t2;
+
+ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align
+ // before the inline cache check here, and not after
+ align(end_alignment, ic_check_size());
+ int uep_offset = offset();
+
+ if (UseCompressedClassPointers) {
+ lwu(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ lwu(tmp2, Address(data, CompiledICData::speculated_klass_offset()));
+ } else {
+ ld(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ ld(tmp2, Address(data, CompiledICData::speculated_klass_offset()));
+ }
+
+ Label ic_hit;
+ beq(tmp1, tmp2, ic_hit);
+ // Note, far_jump is not fixed size.
+ // Is this ever generates a movptr alignment/size will be off.
+ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
+ bind(ic_hit);
+
+ assert((offset() % end_alignment) == 0, "Misaligned verified entry point.");
+ return uep_offset;
+}
+
// Emit a trampoline stub for a call to a target which is too far away.
//
// code sequences:
diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
index d283654e6e179..63cfb22855180 100644
--- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
@@ -1193,7 +1193,10 @@ class MacroAssembler: public Assembler {
//
// Return: the call PC or null if CodeCache is full.
address trampoline_call(Address entry);
+
address ic_call(address entry, jint method_index = 0);
+ static int ic_check_size();
+ int ic_check(int end_alignment = NativeInstruction::instruction_size);
// Support for memory inc/dec
// n.b. increment/decrement calls with an Address destination will
diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad
index a6f0959942414..10a80cd094024 100644
--- a/src/hotspot/cpu/riscv/riscv.ad
+++ b/src/hotspot/cpu/riscv/riscv.ad
@@ -1808,14 +1808,13 @@ void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
assert_cond(st != nullptr);
st->print_cr("# MachUEPNode");
if (UseCompressedClassPointers) {
- st->print_cr("\tlwu t0, [j_rarg0, oopDesc::klass_offset_in_bytes()]\t# compressed klass");
- if (CompressedKlassPointers::shift() != 0) {
- st->print_cr("\tdecode_klass_not_null t0, t0");
- }
+ st->print_cr("\tlwu t0, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tlwu t2, [t1 + CompiledICData::speculated_klass_offset()]\t# compressed klass");
} else {
- st->print_cr("\tld t0, [j_rarg0, oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tld t0, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tld t2, [t1 + CompiledICData::speculated_klass_offset()]\t# compressed klass");
}
- st->print_cr("\tbeq t0, t1, ic_hit");
+ st->print_cr("\tbeq t0, t2, ic_hit");
st->print_cr("\tj, SharedRuntime::_ic_miss_stub\t # Inline cache check");
st->print_cr("\tic_hit:");
}
@@ -1825,15 +1824,11 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
{
// This is the unverified entry point.
C2_MacroAssembler _masm(&cbuf);
+ __ ic_check(CodeEntryAlignment);
- Label skip;
- __ cmp_klass(j_rarg0, t1, t0, t2 /* call-clobbered t2 as a tmp */, skip);
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
- __ bind(skip);
-
- // These NOPs are critical so that verified entry point is properly
- // 4 bytes aligned for patching by NativeJump::patch_verified_entry()
- __ align(NativeInstruction::instruction_size);
+ // Verified entry point must be properly 4 bytes aligned for patching by NativeJump::patch_verified_entry().
+ // ic_check() aligns to CodeEntryAlignment >= InteriorEntryAlignment(min 16) > NativeInstruction::instruction_size(4).
+ assert(((__ offset()) % CodeEntryAlignment) == 0, "Misaligned verified entry point");
}
uint MachUEPNode::size(PhaseRegAlloc* ra_) const
@@ -2402,7 +2397,7 @@ encode %{
cbuf.shared_stub_to_interp_for(_method, call - cbuf.insts_begin());
} else {
// Emit stub for static call
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, call);
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf, call);
if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
index 9f04e20ea3b73..7435b552d15de 100644
--- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
@@ -29,7 +29,6 @@
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/oopMap.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
@@ -38,7 +37,6 @@
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "nativeInst_riscv.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.inline.hpp"
#include "prims/methodHandles.hpp"
@@ -622,10 +620,8 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
address c2i_unverified_entry = __ pc();
Label skip_fixup;
- Label ok;
-
- const Register holder = t1;
const Register receiver = j_rarg0;
+ const Register data = t1;
const Register tmp = t2; // A call-clobbered register not used for arg passing
// -------------------------------------------------------------------------
@@ -639,16 +635,10 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
{
__ block_comment("c2i_unverified_entry {");
- __ load_klass(t0, receiver, tmp);
- __ ld(tmp, Address(holder, CompiledICHolder::holder_klass_offset()));
- __ ld(xmethod, Address(holder, CompiledICHolder::holder_metadata_offset()));
- __ beq(t0, tmp, ok);
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
- __ bind(ok);
- // Method might have been compiled since the call site was patched to
- // interpreted; if that is the case treat it as a miss so we can get
- // the call site corrected.
+ __ ic_check();
+ __ ld(xmethod, Address(data, CompiledICData::speculated_method_offset()));
+
__ ld(t0, Address(xmethod, in_bytes(Method::code_offset())));
__ beqz(t0, skip_fixup);
__ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
@@ -985,7 +975,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
__ j(exit);
CodeBuffer* cbuf = masm->code_section()->outer();
- address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call);
+ address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, tr_call);
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1051,7 +1041,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
}
CodeBuffer* cbuf = masm->code_section()->outer();
- address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, tr_call);
+ address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, tr_call);
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1425,19 +1415,10 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
const Register ic_reg = t1;
const Register receiver = j_rarg0;
- Label hit;
- Label exception_pending;
-
__ verify_oop(receiver);
- assert_different_registers(ic_reg, receiver, t0, t2);
- __ cmp_klass(receiver, ic_reg, t0, t2 /* call-clobbered t2 as a tmp */, hit);
-
- __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
+ assert_different_registers(receiver, t0, t1);
- // Verified entry point must be aligned
- __ align(8);
-
- __ bind(hit);
+ __ ic_check();
int vep_offset = ((intptr_t)__ pc()) - start;
@@ -1872,6 +1853,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ leave();
// Any exception pending?
+ Label exception_pending;
__ ld(t0, Address(xthread, in_bytes(Thread::pending_exception_offset())));
__ bnez(t0, exception_pending);
diff --git a/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp
index 9d08796681f3f..5d945dbc32309 100644
--- a/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp
+++ b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp
@@ -27,10 +27,10 @@
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_riscv.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@@ -171,22 +171,22 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0");
// Entry arguments:
- // t1: CompiledICHolder
+ // t1: CompiledICData
// j_rarg0: Receiver
// This stub is called from compiled code which has no callee-saved registers,
// so all registers except arguments are free at this point.
const Register recv_klass_reg = x18;
- const Register holder_klass_reg = x19; // declaring interface klass (DECC)
+ const Register holder_klass_reg = x19; // declaring interface klass (DEFC)
const Register resolved_klass_reg = x30; // resolved interface klass (REFC)
const Register temp_reg = x28;
const Register temp_reg2 = x29;
- const Register icholder_reg = t1;
+ const Register icdata_reg = t1;
Label L_no_such_interface;
- __ ld(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
- __ ld(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
+ __ ld(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset()));
+ __ ld(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset()));
start_pc = __ pc();
diff --git a/src/hotspot/cpu/s390/assembler_s390.hpp b/src/hotspot/cpu/s390/assembler_s390.hpp
index 9bb143001b944..91cc7e611bfd1 100644
--- a/src/hotspot/cpu/s390/assembler_s390.hpp
+++ b/src/hotspot/cpu/s390/assembler_s390.hpp
@@ -107,7 +107,7 @@ class RelAddr {
static bool is_in_range_of_RelAddr(address target, address pc, bool shortForm) {
// Guard against illegal branch targets, e.g. -1. Occurrences in
- // CompiledStaticCall and ad-file. Do not assert (it's a test
+ // CompiledDirectCall and ad-file. Do not assert (it's a test
// function!). Just return false in case of illegal operands.
if ((((uint64_t)target) & 0x0001L) != 0) return false;
if ((((uint64_t)pc) & 0x0001L) != 0) return false;
diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp
index 355c66047c1b2..13c45bb9fe708 100644
--- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp
+++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp
@@ -76,10 +76,7 @@ int LIR_Assembler::initial_frame_size_in_bytes() const {
// We fetch the class of the receiver and compare it with the cached class.
// If they do not match we jump to the slow case.
int LIR_Assembler::check_icache() {
- Register receiver = receiverOpr()->as_register();
- int offset = __ offset();
- __ inline_cache_check(receiver, Z_inline_cache);
- return offset;
+ return __ ic_check(CodeEntryAlignment);
}
void LIR_Assembler::clinit_barrier(ciMethod* method) {
diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp
index 229216ef20d44..c8815f3a729a4 100644
--- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp
+++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.hpp
@@ -45,7 +45,7 @@
}
enum {
- _call_stub_size = 512, // See Compile::MAX_stubs_size and CompiledStaticCall::emit_to_interp_stub.
+ _call_stub_size = 512, // See Compile::MAX_stubs_size and CompiledDirectCall::emit_to_interp_stub.
_exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(128),
_deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(64)
};
diff --git a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp
index 40edca6559aa4..5dddc7a756f4c 100644
--- a/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp
+++ b/src/hotspot/cpu/s390/c1_MacroAssembler_s390.cpp
@@ -40,31 +40,6 @@
#include "runtime/stubRoutines.hpp"
#include "utilities/macros.hpp"
-void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
- Label ic_miss, ic_hit;
- verify_oop(receiver, FILE_AND_LINE);
- int klass_offset = oopDesc::klass_offset_in_bytes();
-
- if (!ImplicitNullChecks || MacroAssembler::needs_explicit_null_check(klass_offset)) {
- if (VM_Version::has_CompareBranch()) {
- z_cgij(receiver, 0, Assembler::bcondEqual, ic_miss);
- } else {
- z_ltgr(receiver, receiver);
- z_bre(ic_miss);
- }
- }
-
- compare_klass_ptr(iCache, klass_offset, receiver, false);
- z_bre(ic_hit);
-
- // If icache check fails, then jump to runtime routine.
- // Note: RECEIVER must still contain the receiver!
- load_const_optimized(Z_R1_scratch, AddressLiteral(SharedRuntime::get_ic_miss_stub()));
- z_br(Z_R1_scratch);
- align(CodeEntryAlignment);
- bind(ic_hit);
-}
-
void C1_MacroAssembler::explicit_null_check(Register base) {
ShouldNotCallThis(); // unused
}
diff --git a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp
index 257148827be4e..decb3a1cafc31 100644
--- a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp
+++ b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp
@@ -35,7 +35,6 @@
#include "interpreter/interpreter.hpp"
#include "memory/universe.hpp"
#include "nativeInst_s390.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "register_s390.hpp"
diff --git a/src/hotspot/cpu/s390/compiledIC_s390.cpp b/src/hotspot/cpu/s390/compiledIC_s390.cpp
index 7ea90c1de7c69..3adcfbc85f185 100644
--- a/src/hotspot/cpu/s390/compiledIC_s390.cpp
+++ b/src/hotspot/cpu/s390/compiledIC_s390.cpp
@@ -26,7 +26,6 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/mutexLocker.hpp"
@@ -40,7 +39,7 @@
#undef __
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = nullptr*/) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = nullptr*/) {
#ifdef COMPILER2
// Stub is fixed up when the corresponding call is converted from calling
// compiled code to calling interpreted code.
@@ -54,7 +53,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/*
// That's why we must use the macroassembler to generate a stub.
MacroAssembler _masm(&cbuf);
- address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size());
+ address stub = __ start_a_stub(CompiledDirectCall::to_interp_stub_size());
if (stub == nullptr) {
return nullptr; // CodeBuffer::expand failed.
}
@@ -81,27 +80,20 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/*
#undef __
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
return 2 * MacroAssembler::load_const_from_toc_size() +
2; // branch
}
// Relocation entries for call stub, compiled java to interpreter.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
return 5; // 4 in emit_java_to_interp + 1 in Java_Static_Call
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
address stub = find_stub();
guarantee(stub != nullptr, "stub not found");
- {
- ResourceMark rm;
- log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
- p2i(instruction_address()),
- callee->name_and_sig_as_C_string());
- }
-
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + NativeCall::get_IC_pos_in_java_to_interp_stub());
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
@@ -115,7 +107,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
set_destination_mt_safe(stub);
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
// Reset stub.
address stub = static_stub->addr();
assert(stub != nullptr, "stub not found");
@@ -131,7 +123,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
// Verify call.
_call->verify();
_call->verify_alignment();
diff --git a/src/hotspot/cpu/s390/icBuffer_s390.cpp b/src/hotspot/cpu/s390/icBuffer_s390.cpp
deleted file mode 100644
index 0dc936d6fad0c..0000000000000
--- a/src/hotspot/cpu/s390/icBuffer_s390.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016 SAP SE. 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "asm/macroAssembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_s390.hpp"
-#include "oops/oop.inline.hpp"
-
-#define __ masm.
-
-int InlineCacheBuffer::ic_stub_code_size() {
- return MacroAssembler::load_const_size() + Assembler::z_brul_size();
-}
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_oop, address entry_point) {
- ResourceMark rm;
- CodeBuffer code(code_begin, ic_stub_code_size());
- MacroAssembler masm(&code);
- // Note: even though the code contains an embedded oop, we do not need reloc info
- // because
- // (1) the oop is old (i.e., doesn't matter for scavenges)
- // (2) these ICStubs are removed *before* a GC happens, so the roots disappear.
-
- // Load the oop,
- __ load_const(Z_method, (address) cached_oop); // inline cache reg = Z_method
- // and do a tail-call (pc-relative).
- __ z_brul((address) entry_point);
- __ flush();
-}
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // Creation also verifies the object.
- return MacroAssembler::get_target_addr_pcrel(move->next_instruction_address());
-}
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // Creation also verifies the object.
- return (void*)move->data();
-}
diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp
index 14fc07ec00794..0226d494c8958 100644
--- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp
@@ -26,6 +26,7 @@
#include "precompiled.hpp"
#include "asm/codeBuffer.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/disassembler.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
@@ -1097,7 +1098,13 @@ void MacroAssembler::clear_mem(const Address& addr, unsigned int size) {
}
void MacroAssembler::align(int modulus) {
- while (offset() % modulus != 0) z_nop();
+ align(modulus, offset());
+}
+
+void MacroAssembler::align(int modulus, int target) {
+ assert(((modulus % 2 == 0) && (target % 2 == 0)), "needs to be even");
+ int delta = target - offset();
+ while ((offset() + delta) % modulus != 0) z_nop();
}
// Special version for non-relocateable code if required alignment
@@ -2150,6 +2157,45 @@ void MacroAssembler::call_VM_leaf_base(address entry_point) {
call_VM_leaf_base(entry_point, allow_relocation);
}
+int MacroAssembler::ic_check_size() {
+ return 30 + (ImplicitNullChecks ? 0 : 6);
+}
+
+int MacroAssembler::ic_check(int end_alignment) {
+ Register R2_receiver = Z_ARG1;
+ Register R0_scratch = Z_R0_scratch;
+ Register R1_scratch = Z_R1_scratch;
+ Register R9_data = Z_inline_cache;
+ Label success, failure;
+
+ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align
+ // before the inline cache check here, and not after
+ align(end_alignment, offset() + ic_check_size());
+
+ int uep_offset = offset();
+ if (!ImplicitNullChecks) {
+ z_cgij(R2_receiver, 0, Assembler::bcondEqual, failure);
+ }
+
+ if (UseCompressedClassPointers) {
+ z_llgf(R1_scratch, Address(R2_receiver, oopDesc::klass_offset_in_bytes()));
+ } else {
+ z_lg(R1_scratch, Address(R2_receiver, oopDesc::klass_offset_in_bytes()));
+ }
+ z_cg(R1_scratch, Address(R9_data, in_bytes(CompiledICData::speculated_klass_offset())));
+ z_bre(success);
+
+ bind(failure);
+ load_const(R1_scratch, AddressLiteral(SharedRuntime::get_ic_miss_stub()));
+ z_br(R1_scratch);
+ bind(success);
+
+ assert((offset() % end_alignment) == 0, "Misaligned verified entry point, offset() = %d, end_alignment = %d", offset(), end_alignment);
+ return uep_offset;
+}
+
void MacroAssembler::call_VM_base(Register oop_result,
Register last_java_sp,
address entry_point,
diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.hpp b/src/hotspot/cpu/s390/macroAssembler_s390.hpp
index bf14b42e2d1b3..924583abdf563 100644
--- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp
@@ -257,6 +257,7 @@ class MacroAssembler: public Assembler {
// nop padding
void align(int modulus);
+ void align(int modulus, int target);
void align_address(int modulus);
//
@@ -566,6 +567,9 @@ class MacroAssembler: public Assembler {
// Get the pc where the last call will return to. Returns _last_calls_return_pc.
inline address last_calls_return_pc();
+ static int ic_check_size();
+ int ic_check(int end_alignment);
+
private:
static bool is_call_far_patchable_variant0_at(address instruction_addr); // Dynamic TOC: load target addr from CP and call.
static bool is_call_far_patchable_variant2_at(address instruction_addr); // PC-relative call, prefixed with NOPs.
diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad
index fa53c73269196..5db2db9d32c73 100644
--- a/src/hotspot/cpu/s390/s390.ad
+++ b/src/hotspot/cpu/s390/s390.ad
@@ -1341,51 +1341,9 @@ void MachUEPNode::format(PhaseRegAlloc *ra_, outputStream *os) const {
#endif
void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
+ // This is Unverified Entry Point
C2_MacroAssembler _masm(&cbuf);
- const int ic_miss_offset = 2;
-
- // Inline_cache contains a klass.
- Register ic_klass = as_Register(Matcher::inline_cache_reg_encode());
- // ARG1 is the receiver oop.
- Register R2_receiver = Z_ARG1;
- int klass_offset = oopDesc::klass_offset_in_bytes();
- AddressLiteral icmiss(SharedRuntime::get_ic_miss_stub());
- Register R1_ic_miss_stub_addr = Z_R1_scratch;
-
- // Null check of receiver.
- // This is the null check of the receiver that actually should be
- // done in the caller. It's here because in case of implicit null
- // checks we get it for free.
- assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()),
- "second word in oop should not require explicit null check.");
- if (!ImplicitNullChecks) {
- Label valid;
- if (VM_Version::has_CompareBranch()) {
- __ z_cgij(R2_receiver, 0, Assembler::bcondNotEqual, valid);
- } else {
- __ z_ltgr(R2_receiver, R2_receiver);
- __ z_bre(valid);
- }
- // The ic_miss_stub will handle the null pointer exception.
- __ load_const_optimized(R1_ic_miss_stub_addr, icmiss);
- __ z_br(R1_ic_miss_stub_addr);
- __ bind(valid);
- }
-
- // Check whether this method is the proper implementation for the class of
- // the receiver (ic miss check).
- {
- Label valid;
- // Compare cached class against klass from receiver.
- // This also does an implicit null check!
- __ compare_klass_ptr(ic_klass, klass_offset, R2_receiver, false);
- __ z_bre(valid);
- // The inline cache points to the wrong method. Call the
- // ic_miss_stub to find the proper method.
- __ load_const_optimized(R1_ic_miss_stub_addr, icmiss);
- __ z_br(R1_ic_miss_stub_addr);
- __ bind(valid);
- }
+ __ ic_check(CodeEntryAlignment);
}
uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
@@ -2146,7 +2104,7 @@ encode %{
assert(__ inst_mark() != nullptr, "emit_call_reloc must set_inst_mark()");
if (_method) { // Emit stub for static call.
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf);
if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
index ed1795cfa339f..11e1e617d8e3a 100644
--- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
+++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
@@ -26,8 +26,8 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/oopMap.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
#include "gc/shared/gcLocker.hpp"
@@ -35,7 +35,6 @@
#include "interpreter/interp_masm.hpp"
#include "memory/resourceArea.hpp"
#include "nativeInst_s390.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "prims/methodHandles.hpp"
#include "registerSaver_s390.hpp"
@@ -1500,17 +1499,15 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
unsigned int wrapper_FrameDone;
unsigned int wrapper_CRegsSet;
Label handle_pending_exception;
- Label ic_miss;
//---------------------------------------------------------------------
// Unverified entry point (UEP)
//---------------------------------------------------------------------
- wrapper_UEPStart = __ offset();
// check ic: object class <-> cached class
- if (!method_is_static) __ nmethod_UEP(ic_miss);
- // Fill with nops (alignment of verified entry point).
- __ align(CodeEntryAlignment);
+ if (!method_is_static) {
+ wrapper_UEPStart = __ ic_check(CodeEntryAlignment /* end_alignment */);
+ }
//---------------------------------------------------------------------
// Verified entry point (VEP)
@@ -2026,13 +2023,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ restore_return_pc();
__ z_br(Z_R1_scratch);
- //---------------------------------------------------------------------
- // Handler for a cache miss (out-of-line)
- //---------------------------------------------------------------------
- __ call_ic_miss_handler(ic_miss, 0x77, 0, Z_R1_scratch);
__ flush();
-
-
//////////////////////////////////////////////////////////////////////
// end of code generation
//////////////////////////////////////////////////////////////////////
@@ -2318,9 +2309,6 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
Label skip_fixup;
{
Label ic_miss;
- const int klass_offset = oopDesc::klass_offset_in_bytes();
- const int holder_klass_offset = in_bytes(CompiledICHolder::holder_klass_offset());
- const int holder_metadata_offset = in_bytes(CompiledICHolder::holder_metadata_offset());
// Out-of-line call to ic_miss handler.
__ call_ic_miss_handler(ic_miss, 0x11, 0, Z_R1_scratch);
@@ -2329,27 +2317,11 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
__ align(CodeEntryAlignment);
c2i_unverified_entry = __ pc();
- // Check the pointers.
- if (!ImplicitNullChecks || MacroAssembler::needs_explicit_null_check(klass_offset)) {
- __ z_ltgr(Z_ARG1, Z_ARG1);
- __ z_bre(ic_miss);
- }
- __ verify_oop(Z_ARG1, FILE_AND_LINE);
-
- // Check ic: object class <-> cached class
- // Compress cached class for comparison. That's more efficient.
- if (UseCompressedClassPointers) {
- __ z_lg(Z_R11, holder_klass_offset, Z_method); // Z_R11 is overwritten a few instructions down anyway.
- __ compare_klass_ptr(Z_R11, klass_offset, Z_ARG1, false); // Cached class can't be zero.
- } else {
- __ z_clc(klass_offset, sizeof(void *)-1, Z_ARG1, holder_klass_offset, Z_method);
- }
- __ z_brne(ic_miss); // Cache miss: call runtime to handle this.
-
+ __ ic_check(2);
+ __ z_lg(Z_method, Address(Z_inline_cache, CompiledICData::speculated_method_offset()));
// This def MUST MATCH code in gen_c2i_adapter!
const Register code = Z_R11;
- __ z_lg(Z_method, holder_metadata_offset, Z_method);
__ load_and_test_long(Z_R0, method_(code));
__ z_brne(ic_miss); // Cache miss: call runtime to handle this.
diff --git a/src/hotspot/cpu/s390/vtableStubs_s390.cpp b/src/hotspot/cpu/s390/vtableStubs_s390.cpp
index 5a79369ceab47..573c23d796708 100644
--- a/src/hotspot/cpu/s390/vtableStubs_s390.cpp
+++ b/src/hotspot/cpu/s390/vtableStubs_s390.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2021 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2023 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,10 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_s390.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/klassVtable.hpp"
@@ -197,12 +197,12 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ load_klass(rcvr_klass, Z_ARG1);
// Receiver subtype check against REFC.
- __ z_lg(interface, Address(Z_method, CompiledICHolder::holder_klass_offset()));
+ __ z_lg(interface, Address(Z_method, CompiledICData::itable_refc_klass_offset()));
__ lookup_interface_method(rcvr_klass, interface, noreg,
noreg, Z_R1, no_such_interface, /*return_method=*/ false);
// Get Method* and entrypoint for compiler
- __ z_lg(interface, Address(Z_method, CompiledICHolder::holder_metadata_offset()));
+ __ z_lg(interface, Address(Z_method, CompiledICData::itable_defc_klass_offset()));
__ lookup_interface_method(rcvr_klass, interface, itable_index,
Z_method, Z_R1, no_such_interface, /*return_method=*/ true);
diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp
index ff0726840d30a..3b7a3cec2d815 100644
--- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp
@@ -72,7 +72,6 @@ static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], (jl
NEEDS_CLEANUP // remove this definitions ?
-const Register IC_Klass = rax; // where the IC klass is cached
const Register SYNC_header = rax; // synchronization header
const Register SHIFT_count = rcx; // where count for shift operations must be
@@ -336,23 +335,7 @@ void LIR_Assembler::osr_entry() {
// inline cache check; done before the frame is built.
int LIR_Assembler::check_icache() {
- Register receiver = FrameMap::receiver_opr->as_register();
- Register ic_klass = IC_Klass;
- const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9);
- const bool do_post_padding = VerifyOops || UseCompressedClassPointers;
- if (!do_post_padding) {
- // insert some nops so that the verified entry point is aligned on CodeEntryAlignment
- __ align(CodeEntryAlignment, __ offset() + ic_cmp_size);
- }
- int offset = __ offset();
- __ inline_cache_check(receiver, IC_Klass);
- assert(__ offset() % CodeEntryAlignment == 0 || do_post_padding, "alignment must be correct");
- if (do_post_padding) {
- // force alignment after the cache check.
- // It's been verified to be aligned if !VerifyOops
- __ align(CodeEntryAlignment);
- }
- return offset;
+ return __ ic_check(CodeEntryAlignment);
}
void LIR_Assembler::clinit_barrier(ciMethod* method) {
diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
index 5e98b2d3af4ac..0c4544f5bc49e 100644
--- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "c1/c1_MacroAssembler.hpp"
#include "c1/c1_Runtime1.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/compilerDefinitions.inline.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetAssembler.hpp"
@@ -301,30 +302,6 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1,
verify_oop(obj);
}
-
-
-void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
- verify_oop(receiver);
- // explicit null check not needed since load from [klass_offset] causes a trap
- // check against inline cache
- assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check");
- int start_offset = offset();
-
- if (UseCompressedClassPointers) {
- load_klass(rscratch1, receiver, rscratch2);
- cmpptr(rscratch1, iCache);
- } else {
- cmpptr(iCache, Address(receiver, oopDesc::klass_offset_in_bytes()));
- }
- // if icache check fails, then jump to runtime routine
- // Note: RECEIVER must still contain the receiver!
- jump_cc(Assembler::notEqual,
- RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
- const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9);
- assert(UseCompressedClassPointers || offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry");
-}
-
-
void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) {
assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect");
// Make sure there is enough stack space for this method's activation.
diff --git a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp
index 8b56f464f2739..2c24c0c2cfb17 100644
--- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp
+++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp
@@ -38,7 +38,6 @@
#include "interpreter/interpreter.hpp"
#include "memory/universe.hpp"
#include "nativeInst_x86.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "register_x86.hpp"
diff --git a/src/hotspot/cpu/x86/compiledIC_x86.cpp b/src/hotspot/cpu/x86/compiledIC_x86.cpp
index 8fc001039fbd3..95b41f62b6aab 100644
--- a/src/hotspot/cpu/x86/compiledIC_x86.cpp
+++ b/src/hotspot/cpu/x86/compiledIC_x86.cpp
@@ -26,7 +26,6 @@
#include "asm/macroAssembler.inline.hpp"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
@@ -36,7 +35,7 @@
// ----------------------------------------------------------------------------
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
// Stub is fixed up when the corresponding call is converted from
// calling compiled code to calling interpreted code.
// movq rbx, 0
@@ -66,32 +65,25 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
}
#undef __
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
return NOT_LP64(10) // movl; jmp
LP64_ONLY(15); // movq (1+1+8); jmp (1+4)
}
-int CompiledStaticCall::to_trampoline_stub_size() {
+int CompiledDirectCall::to_trampoline_stub_size() {
// x86 doesn't use trampolines.
return 0;
}
// Relocation entries for call stub, compiled java to interpreter.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
return 4; // 3 in emit_to_interp_stub + 1 in emit_call
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
address stub = find_stub();
guarantee(stub != nullptr, "stub not found");
- {
- ResourceMark rm;
- log_trace(inlinecache)("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s",
- p2i(instruction_address()),
- callee->name_and_sig_as_C_string());
- }
-
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
@@ -105,7 +97,7 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad
set_destination_mt_safe(stub);
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
assert(CompiledICLocker::is_safe(static_stub->addr()), "mt unsafe call");
// Reset stub.
address stub = static_stub->addr();
@@ -122,7 +114,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
// Non-product mode code
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
// Verify call.
_call->verify();
_call->verify_alignment();
diff --git a/src/hotspot/cpu/x86/icBuffer_x86.cpp b/src/hotspot/cpu/x86/icBuffer_x86.cpp
deleted file mode 100644
index af374b5741659..0000000000000
--- a/src/hotspot/cpu/x86/icBuffer_x86.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 "asm/macroAssembler.hpp"
-#include "asm/macroAssembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_x86.hpp"
-#include "oops/oop.inline.hpp"
-
-int InlineCacheBuffer::ic_stub_code_size() {
- // Worst case, if destination is not a near call:
- // lea rax, lit1
- // lea scratch, lit2
- // jmp scratch
-
- // Best case
- // lea rax, lit1
- // jmp lit2
-
- int best = NativeMovConstReg::instruction_size + NativeJump::instruction_size;
- int worst = 2 * NativeMovConstReg::instruction_size + 3;
- return MAX2(best, worst);
-}
-
-
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) {
- ResourceMark rm;
- CodeBuffer code(code_begin, ic_stub_code_size());
- MacroAssembler* masm = new MacroAssembler(&code);
- // note: even though the code contains an embedded value, we do not need reloc info
- // because
- // (1) the value is old (i.e., doesn't matter for scavenges)
- // (2) these ICStubs are removed *before* a GC happens, so the roots disappear
- // assert(cached_value == nullptr || cached_oop->is_perm(), "must be perm oop");
- masm->lea(rax, AddressLiteral((address) cached_value, relocInfo::metadata_type));
- masm->jump(ExternalAddress(entry_point));
-}
-
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin); // creation also verifies the object
- address jmp = move->next_instruction_address();
- NativeInstruction* ni = nativeInstruction_at(jmp);
- if (ni->is_jump()) {
- NativeJump* jump = nativeJump_at(jmp);
- return jump->jump_destination();
- } else {
- assert(ni->is_far_jump(), "unexpected instruction");
- NativeFarJump* jump = nativeFarJump_at(jmp);
- return jump->jump_destination();
- }
-}
-
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- // creation also verifies the object
- NativeMovConstReg* move = nativeMovConstReg_at(code_begin);
- // Verifies the jump
- address jmp = move->next_instruction_address();
- NativeInstruction* ni = nativeInstruction_at(jmp);
- if (ni->is_jump()) {
- NativeJump* jump = nativeJump_at(jmp);
- } else {
- assert(ni->is_far_jump(), "unexpected instruction");
- NativeFarJump* jump = nativeFarJump_at(jmp);
- }
- void* o = (void*)move->data();
- return o;
-}
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
index 63a7c43c7ff9b..7496bddb39a5b 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/compiler_globals.hpp"
#include "compiler/disassembler.hpp"
#include "crc32c.h"
@@ -1341,13 +1342,45 @@ void MacroAssembler::ic_call(address entry, jint method_index) {
RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index);
#ifdef _LP64
// Needs full 64-bit immediate for later patching.
- mov64(rax, (intptr_t)Universe::non_oop_word());
+ mov64(rax, (int64_t)Universe::non_oop_word());
#else
movptr(rax, (intptr_t)Universe::non_oop_word());
#endif
call(AddressLiteral(entry, rh));
}
+int MacroAssembler::ic_check_size() {
+ return LP64_ONLY(14) NOT_LP64(12);
+}
+
+int MacroAssembler::ic_check(int end_alignment) {
+ Register receiver = LP64_ONLY(j_rarg0) NOT_LP64(rcx);
+ Register data = rax;
+ Register temp = LP64_ONLY(rscratch1) NOT_LP64(rbx);
+
+ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align
+ // before the inline cache check here, and not after
+ align(end_alignment, offset() + ic_check_size());
+
+ int uep_offset = offset();
+
+ if (UseCompressedClassPointers) {
+ movl(temp, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ cmpl(temp, Address(data, CompiledICData::speculated_klass_offset()));
+ } else {
+ movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes()));
+ cmpptr(temp, Address(data, CompiledICData::speculated_klass_offset()));
+ }
+
+ // if inline cache check fails, then jump to runtime routine
+ jump_cc(Assembler::notEqual, RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
+ assert((offset() % end_alignment) == 0, "Misaligned verified entry point");
+
+ return uep_offset;
+}
+
void MacroAssembler::emit_static_call_stub() {
// Static stub relocation also tags the Method* in the code-stream.
mov_metadata(rbx, (Metadata*) nullptr); // Method is zapped till fixup time.
@@ -4354,7 +4387,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
}
// Look up the method for a megamorphic invokeinterface call in a single pass over itable:
-// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICHolder
+// - check recv_klass (actual object class) is a subtype of resolved_klass from CompiledICData
// - find a holder_klass (class that implements the method) vtable offset and get the method from vtable by index
// The target method is determined by .
// The receiver klass is in recv_klass.
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
index 971aacb2adc7b..4789b63decc6c 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
@@ -896,6 +896,8 @@ class MacroAssembler: public Assembler {
// Emit the CompiledIC call idiom
void ic_call(address entry, jint method_index = 0);
+ static int ic_check_size();
+ int ic_check(int end_alignment);
void emit_static_call_stub();
diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp
index 4d1078c55cd7d..febc1b2c3b143 100644
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp
@@ -25,8 +25,8 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
+#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/oopMap.hpp"
@@ -36,7 +36,6 @@
#include "interpreter/interpreter.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/jniHandles.hpp"
@@ -944,25 +943,18 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
address c2i_unverified_entry = __ pc();
Label skip_fixup;
- Register holder = rax;
+ Register data = rax;
Register receiver = rcx;
Register temp = rbx;
{
-
- Label missed;
- __ movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes()));
- __ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset()));
- __ movptr(rbx, Address(holder, CompiledICHolder::holder_metadata_offset()));
- __ jcc(Assembler::notEqual, missed);
+ __ ic_check(1 /* end_alignment */);
+ __ movptr(rbx, Address(data, CompiledICData::speculated_method_offset()));
// Method might have been compiled since the call site was patched to
// interpreted if that is the case treat it as a miss so we can get
// the call site corrected.
__ cmpptr(Address(rbx, in_bytes(Method::code_offset())), NULL_WORD);
__ jcc(Assembler::equal, skip_fixup);
-
- __ bind(missed);
- __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
}
address c2i_entry = __ pc();
@@ -1449,23 +1441,12 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// as far as the interpreter and the compiler(s) are concerned.
- const Register ic_reg = rax;
const Register receiver = rcx;
- Label hit;
Label exception_pending;
__ verify_oop(receiver);
- __ cmpptr(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes()));
- __ jcc(Assembler::equal, hit);
-
- __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
// verified entry must be aligned for code patching.
- // and the first 5 bytes must be in the same cache line
- // if we align at 8 then we will be sure 5 bytes are in the same line
- __ align(8);
-
- __ bind(hit);
+ __ ic_check(8 /* end_alignment */);
int vep_offset = ((intptr_t)__ pc()) - start;
diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
index 1af7d1caa0455..c666f982d0f52 100644
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
@@ -30,7 +30,6 @@
#include "asm/macroAssembler.inline.hpp"
#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/oopMap.hpp"
@@ -42,7 +41,6 @@
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.inline.hpp"
#include "prims/methodHandles.hpp"
@@ -1000,20 +998,14 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
address c2i_unverified_entry = __ pc();
Label skip_fixup;
- Label ok;
- Register holder = rax;
+ Register data = rax;
Register receiver = j_rarg0;
Register temp = rbx;
{
- __ load_klass(temp, receiver, rscratch1);
- __ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset()));
- __ movptr(rbx, Address(holder, CompiledICHolder::holder_metadata_offset()));
- __ jcc(Assembler::equal, ok);
- __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- __ bind(ok);
+ __ ic_check(1 /* end_alignment */);
+ __ movptr(rbx, Address(data, CompiledICData::speculated_method_offset()));
// Method might have been compiled since the call site was patched to
// interpreted if that is the case treat it as a miss so we can get
// the call site corrected.
@@ -1450,7 +1442,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
__ align(BytesPerWord, __ offset() + NativeCall::displacement_offset);
// Emit stub for static call
CodeBuffer* cbuf = masm->code_section()->outer();
- address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, __ pc());
+ address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, __ pc());
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1487,7 +1479,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
// Emit stub for static call
CodeBuffer* cbuf = masm->code_section()->outer();
- address stub = CompiledStaticCall::emit_to_interp_stub(*cbuf, __ pc());
+ address stub = CompiledDirectCall::emit_to_interp_stub(*cbuf, __ pc());
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1883,25 +1875,13 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// restoring them except rbp. rbp is the only callee save register
// as far as the interpreter and the compiler(s) are concerned.
-
- const Register ic_reg = rax;
const Register receiver = j_rarg0;
- Label hit;
Label exception_pending;
- assert_different_registers(ic_reg, receiver, rscratch1, rscratch2);
+ assert_different_registers(receiver, rscratch1, rscratch2);
__ verify_oop(receiver);
- __ load_klass(rscratch1, receiver, rscratch2);
- __ cmpq(ic_reg, rscratch1);
- __ jcc(Assembler::equal, hit);
-
- __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- // Verified entry point must be aligned
- __ align(8);
-
- __ bind(hit);
+ __ ic_check(8 /* end_alignment */);
int vep_offset = ((intptr_t)__ pc()) - start;
diff --git a/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp b/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp
index 0e78e0274d7f2..398f2e37eb5cc 100644
--- a/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp
+++ b/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp
@@ -24,10 +24,10 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_x86.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@@ -176,21 +176,21 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
#endif /* PRODUCT */
// Entry arguments:
- // rax: CompiledICHolder
+ // rax: CompiledICData
// rcx: Receiver
// Most registers are in use; we'll use rax, rbx, rcx, rdx, rsi, rdi
// (If we need to make rsi, rdi callee-save, do a push/pop here.)
const Register recv_klass_reg = rsi;
- const Register holder_klass_reg = rax; // declaring interface klass (DECC)
+ const Register holder_klass_reg = rax; // declaring interface klass (DEFC)
const Register resolved_klass_reg = rdi; // resolved interface klass (REFC)
const Register temp_reg = rdx;
const Register method = rbx;
- const Register icholder_reg = rax;
+ const Register icdata_reg = rax;
const Register receiver = rcx;
- __ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
- __ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
+ __ movptr(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset()));
+ __ movptr(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset()));
Label L_no_such_interface;
diff --git a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp
index f162a651183f9..158d6f9c6922b 100644
--- a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp
+++ b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp
@@ -24,10 +24,10 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
+#include "code/compiledIC.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_x86.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@@ -168,21 +168,21 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
#endif // PRODUCT
// Entry arguments:
- // rax: CompiledICHolder
+ // rax: CompiledICData
// j_rarg0: Receiver
// Most registers are in use; we'll use rax, rbx, r10, r11
// (various calling sequences use r[cd]x, r[sd]i, r[89]; stay away from them)
const Register recv_klass_reg = r10;
- const Register holder_klass_reg = rax; // declaring interface klass (DECC)
+ const Register holder_klass_reg = rax; // declaring interface klass (DEFC)
const Register resolved_klass_reg = r14; // resolved interface klass (REFC)
const Register temp_reg = r11;
const Register temp_reg2 = r13;
const Register method = rbx;
- const Register icholder_reg = rax;
+ const Register icdata_reg = rax;
- __ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
- __ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
+ __ movptr(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset()));
+ __ movptr(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset()));
Label L_no_such_interface;
diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad
index df38fe6b92c54..cad53ca6d5a45 100644
--- a/src/hotspot/cpu/x86/x86_32.ad
+++ b/src/hotspot/cpu/x86/x86_32.ad
@@ -1383,24 +1383,12 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream* st ) const {
void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
MacroAssembler masm(&cbuf);
-#ifdef ASSERT
- uint insts_size = cbuf.insts_size();
-#endif
- masm.cmpptr(rax, Address(rcx, oopDesc::klass_offset_in_bytes()));
- masm.jump_cc(Assembler::notEqual,
- RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
- /* WARNING these NOPs are critical so that verified entry point is properly
- aligned for patching by NativeJump::patch_verified_entry() */
- int nops_cnt = 2;
- if( !OptoBreakpoint ) // Leave space for int3
- nops_cnt += 1;
- masm.nop(nops_cnt);
-
- assert(cbuf.insts_size() - insts_size == size(ra_), "checking code size of inline cache node");
+ masm.ic_check(CodeEntryAlignment);
}
uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
- return OptoBreakpoint ? 11 : 12;
+ return MachNode::size(ra_); // too many variables; just compute it
+ // the hard way
}
@@ -1842,7 +1830,7 @@ encode %{
cbuf.shared_stub_to_interp_for(_method, cbuf.insts()->mark_off());
} else {
// Emit stubs for static call.
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, mark);
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf, mark);
if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad
index 2cb2cc1becb66..d1a19e452c6b7 100644
--- a/src/hotspot/cpu/x86/x86_64.ad
+++ b/src/hotspot/cpu/x86/x86_64.ad
@@ -1472,40 +1472,19 @@ void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
{
if (UseCompressedClassPointers) {
st->print_cr("movl rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
- st->print_cr("\tdecode_klass_not_null rscratch1, rscratch1");
- st->print_cr("\tcmpq rax, rscratch1\t # Inline cache check");
+ st->print_cr("\tcmpl rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check");
} else {
- st->print_cr("\tcmpq rax, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t"
- "# Inline cache check");
+ st->print_cr("movq rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
+ st->print_cr("\tcmpq rscratch1, [rax + CompiledICData::speculated_klass_offset()]\t # Inline cache check");
}
st->print_cr("\tjne SharedRuntime::_ic_miss_stub");
- st->print_cr("\tnop\t# nops to align entry point");
}
#endif
void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
{
MacroAssembler masm(&cbuf);
- uint insts_size = cbuf.insts_size();
- if (UseCompressedClassPointers) {
- masm.load_klass(rscratch1, j_rarg0, rscratch2);
- masm.cmpptr(rax, rscratch1);
- } else {
- masm.cmpptr(rax, Address(j_rarg0, oopDesc::klass_offset_in_bytes()));
- }
-
- masm.jump_cc(Assembler::notEqual, RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
-
- /* WARNING these NOPs are critical so that verified entry point is properly
- 4 bytes aligned for patching by NativeJump::patch_verified_entry() */
- int nops_cnt = 4 - ((cbuf.insts_size() - insts_size) & 0x3);
- if (OptoBreakpoint) {
- // Leave space for int3
- nops_cnt -= 1;
- }
- nops_cnt &= 0x3; // Do not add nops if code is aligned.
- if (nops_cnt > 0)
- masm.nop(nops_cnt);
+ masm.ic_check(InteriorEntryAlignment);
}
uint MachUEPNode::size(PhaseRegAlloc* ra_) const
@@ -1840,7 +1819,7 @@ encode %{
cbuf.shared_stub_to_interp_for(_method, call_offset);
} else {
// Emit stubs for static call.
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, mark);
+ address stub = CompiledDirectCall::emit_to_interp_stub(cbuf, mark);
if (stub == nullptr) {
ciEnv::current()->record_failure("CodeCache is full");
return;
diff --git a/src/hotspot/cpu/zero/compiledIC_zero.cpp b/src/hotspot/cpu/zero/compiledIC_zero.cpp
index b0564643af080..24153aeacc5e1 100644
--- a/src/hotspot/cpu/zero/compiledIC_zero.cpp
+++ b/src/hotspot/cpu/zero/compiledIC_zero.cpp
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
@@ -43,27 +42,27 @@
// ----------------------------------------------------------------------------
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
+address CompiledDirectCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
ShouldNotReachHere(); // Only needed for COMPILER2.
return nullptr;
}
-int CompiledStaticCall::to_interp_stub_size() {
+int CompiledDirectCall::to_interp_stub_size() {
ShouldNotReachHere(); // Only needed for COMPILER2.
return 0;
}
// Relocation entries for call stub, compiled java to interpreter.
-int CompiledStaticCall::reloc_to_interp_stub() {
+int CompiledDirectCall::reloc_to_interp_stub() {
ShouldNotReachHere(); // Only needed for COMPILER2.
return 0;
}
-void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) {
+void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) {
ShouldNotReachHere(); // Only needed for COMPILER2.
}
-void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
+void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) {
ShouldNotReachHere(); // Only needed for COMPILER2.
}
@@ -71,7 +70,7 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_
// Non-product mode code.
#ifndef PRODUCT
-void CompiledDirectStaticCall::verify() {
+void CompiledDirectCall::verify() {
ShouldNotReachHere(); // Only needed for COMPILER2.
}
diff --git a/src/hotspot/cpu/zero/icBuffer_zero.cpp b/src/hotspot/cpu/zero/icBuffer_zero.cpp
deleted file mode 100644
index adde916a4c4ad..0000000000000
--- a/src/hotspot/cpu/zero/icBuffer_zero.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2007 Red Hat, Inc.
- * 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 "asm/assembler.inline.hpp"
-#include "code/icBuffer.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/resourceArea.hpp"
-#include "nativeInst_zero.hpp"
-#include "oops/oop.inline.hpp"
-
-int InlineCacheBuffer::ic_stub_code_size() {
- // NB set this once the functions below are implemented
- return 4;
-}
-
-void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin,
- void* cached_oop,
- address entry_point) {
- // NB ic_stub_code_size() must return the size of the code we generate
- ShouldNotCallThis();
-}
-
-address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
- // NB ic_stub_code_size() must return the size of the code we generate
- ShouldNotCallThis();
- return nullptr;
-}
-
-void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
- ShouldNotCallThis();
- return nullptr;
-}
diff --git a/src/hotspot/cpu/zero/sharedRuntime_zero.cpp b/src/hotspot/cpu/zero/sharedRuntime_zero.cpp
index 4244b5817db98..986cee685123b 100644
--- a/src/hotspot/cpu/zero/sharedRuntime_zero.cpp
+++ b/src/hotspot/cpu/zero/sharedRuntime_zero.cpp
@@ -26,10 +26,8 @@
#include "precompiled.hpp"
#include "asm/assembler.inline.hpp"
#include "code/debugInfoRec.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
-#include "oops/compiledICHolder.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/vframeArray.hpp"
diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp
index e701e0aef6082..5d5ea364b6652 100644
--- a/src/hotspot/os/aix/os_aix.cpp
+++ b/src/hotspot/os/aix/os_aix.cpp
@@ -29,7 +29,6 @@
// no precompiled headers
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
#include "interpreter/interpreter.hpp"
diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp
index 42a0b9c083239..ddceab14ffbc2 100644
--- a/src/hotspot/os/bsd/os_bsd.cpp
+++ b/src/hotspot/os/bsd/os_bsd.cpp
@@ -24,7 +24,6 @@
// no precompiled headers
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/disassembler.hpp"
diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp
index f02ca95be5593..d912f9f44a916 100644
--- a/src/hotspot/os/linux/os_linux.cpp
+++ b/src/hotspot/os/linux/os_linux.cpp
@@ -25,7 +25,6 @@
// no precompiled headers
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/disassembler.hpp"
diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp
index 3613edfc7d9e6..f9c3f23f0a67b 100644
--- a/src/hotspot/os/windows/os_windows.cpp
+++ b/src/hotspot/os/windows/os_windows.cpp
@@ -27,7 +27,6 @@
// no precompiled headers
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
index 5e0086521aad9..242042d4247aa 100644
--- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
+++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
@@ -28,7 +28,6 @@
#include "asm/assembler.inline.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp
index fbd7c4eccd403..4750ed8805644 100644
--- a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp
+++ b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp
@@ -29,7 +29,6 @@
#include "classfile/classLoader.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp
index 37b92bc7ffd48..2074f6319c9f0 100644
--- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp
+++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp
@@ -26,7 +26,6 @@
#include "asm/macroAssembler.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
index 012f85ac0ff4a..0fc9484ce23ef 100644
--- a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
+++ b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
@@ -27,7 +27,6 @@
#include "asm/assembler.inline.hpp"
#include "atomic_bsd_zero.hpp"
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
index 4835eb9405a1b..3698896abb78a 100644
--- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
+++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
@@ -27,7 +27,6 @@
#include "asm/macroAssembler.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "code/nativeInst.hpp"
#include "interpreter/interpreter.hpp"
diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
index 86e8ed25618c1..551270588438e 100644
--- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
+++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
@@ -25,7 +25,6 @@
// no precompiled headers
#include "asm/assembler.inline.hpp"
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
index b570e3b6d7f12..0b666f29c312b 100644
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
+++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
@@ -28,7 +28,6 @@
#include "asm/assembler.inline.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp
index 282467bc9e096..3d923c03094ab 100644
--- a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp
+++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp
@@ -27,7 +27,6 @@
#include "asm/macroAssembler.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
diff --git a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp
index 033ea14ead6a4..5aa65e705d9ed 100644
--- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp
+++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp
@@ -28,7 +28,6 @@
// no precompiled headers
#include "asm/assembler.inline.hpp"
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/disassembler.hpp"
diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
index b211330409d59..219f8d828a420 100644
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
@@ -26,7 +26,6 @@
#include "asm/macroAssembler.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
index 1ce73588524c1..d593c46d15d91 100644
--- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
+++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
@@ -27,7 +27,6 @@
#include "asm/assembler.inline.hpp"
#include "atomic_linux_zero.hpp"
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp
index 46f718a9cd0f5..78e98609b6bdc 100644
--- a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp
+++ b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp
@@ -27,7 +27,6 @@
#include "asm/macroAssembler.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "code/nativeInst.hpp"
#include "interpreter/interpreter.hpp"
diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp
index 4e18334315a37..7e0814c014bec 100644
--- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp
+++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp
@@ -25,7 +25,6 @@
// no precompiled headers
#include "asm/macroAssembler.hpp"
#include "classfile/vmSymbols.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
diff --git a/src/hotspot/share/adlc/main.cpp b/src/hotspot/share/adlc/main.cpp
index 6d921cf5e7bee..4d1c5491044a7 100644
--- a/src/hotspot/share/adlc/main.cpp
+++ b/src/hotspot/share/adlc/main.cpp
@@ -216,7 +216,6 @@ int main(int argc, char *argv[])
AD.addInclude(AD._CPP_file, "code/nativeInst.hpp");
AD.addInclude(AD._CPP_file, "code/vmreg.inline.hpp");
AD.addInclude(AD._CPP_file, "gc/shared/collectedHeap.inline.hpp");
- AD.addInclude(AD._CPP_file, "oops/compiledICHolder.hpp");
AD.addInclude(AD._CPP_file, "oops/compressedOops.hpp");
AD.addInclude(AD._CPP_file, "oops/markWord.hpp");
AD.addInclude(AD._CPP_file, "oops/method.hpp");
diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp
index 7a0a31abf597f..5b1e113f15d10 100644
--- a/src/hotspot/share/asm/codeBuffer.cpp
+++ b/src/hotspot/share/asm/codeBuffer.cpp
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "asm/codeBuffer.hpp"
+#include "code/compiledIC.hpp"
#include "code/oopRecorder.inline.hpp"
#include "compiler/disassembler.hpp"
#include "logging/log.hpp"
diff --git a/src/hotspot/share/asm/codeBuffer.inline.hpp b/src/hotspot/share/asm/codeBuffer.inline.hpp
index 838447ad882dc..06ec9174b34bb 100644
--- a/src/hotspot/share/asm/codeBuffer.inline.hpp
+++ b/src/hotspot/share/asm/codeBuffer.inline.hpp
@@ -48,7 +48,7 @@ bool emit_shared_stubs_to_interp(CodeBuffer* cb, SharedStubToInterpRequests* sha
shared_stub_to_interp_requests->sort(by_shared_method);
MacroAssembler masm(cb);
for (int i = 0; i < shared_stub_to_interp_requests->length();) {
- address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size());
+ address stub = __ start_a_stub(CompiledDirectCall::to_interp_stub_size());
if (stub == nullptr) {
return false;
}
diff --git a/src/hotspot/share/c1/c1_LIRAssembler.cpp b/src/hotspot/share/c1/c1_LIRAssembler.cpp
index a601696d8df7e..51fb851d00c0e 100644
--- a/src/hotspot/share/c1/c1_LIRAssembler.cpp
+++ b/src/hotspot/share/c1/c1_LIRAssembler.cpp
@@ -606,13 +606,14 @@ void LIR_Assembler::emit_op0(LIR_Op0* op) {
Unimplemented();
break;
- case lir_std_entry:
+ case lir_std_entry: {
// init offsets
offsets()->set_value(CodeOffsets::OSR_Entry, _masm->offset());
- _masm->align(CodeEntryAlignment);
if (needs_icache(compilation()->method())) {
- check_icache();
+ int offset = check_icache();
+ offsets()->set_value(CodeOffsets::Entry, offset);
}
+ _masm->align(CodeEntryAlignment);
offsets()->set_value(CodeOffsets::Verified_Entry, _masm->offset());
_masm->verified_entry(compilation()->directive()->BreakAtExecuteOption);
if (needs_clinit_barrier_on_entry(compilation()->method())) {
@@ -621,6 +622,7 @@ void LIR_Assembler::emit_op0(LIR_Op0* op) {
build_frame();
offsets()->set_value(CodeOffsets::Frame_Complete, _masm->offset());
break;
+ }
case lir_osr_entry:
offsets()->set_value(CodeOffsets::OSR_Entry, _masm->offset());
diff --git a/src/hotspot/share/c1/c1_MacroAssembler.hpp b/src/hotspot/share/c1/c1_MacroAssembler.hpp
index 6a8304bd405fa..1e193ce086961 100644
--- a/src/hotspot/share/c1/c1_MacroAssembler.hpp
+++ b/src/hotspot/share/c1/c1_MacroAssembler.hpp
@@ -38,7 +38,6 @@ class C1_MacroAssembler: public MacroAssembler {
//----------------------------------------------------
void explicit_null_check(Register base);
- void inline_cache_check(Register receiver, Register iCache);
void build_frame(int frame_size_in_bytes, int bang_size_in_bytes);
void remove_frame(int frame_size_in_bytes);
diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp
index b30a88e90cb48..d24e29c288d5c 100644
--- a/src/hotspot/share/code/codeBlob.cpp
+++ b/src/hotspot/share/code/codeBlob.cpp
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "code/codeBlob.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/relocInfo.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/disassembler.hpp"
@@ -649,11 +648,6 @@ void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const
st->print_cr(INTPTR_FORMAT " is pointing to an (unnamed) stub routine", p2i(addr));
return;
}
- // the InlineCacheBuffer is using stubs generated into a buffer blob
- if (InlineCacheBuffer::contains(addr)) {
- st->print_cr(INTPTR_FORMAT " is pointing into InlineCacheBuffer", p2i(addr));
- return;
- }
VtableStub* v = VtableStubs::stub_containing(addr);
if (v != nullptr) {
st->print_cr(INTPTR_FORMAT " is at entry_point+%d in a vtable stub", p2i(addr), (int)(addr - v->entry_point()));
diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp
index bf8c1d84e71a0..cdc9f3f50dc15 100644
--- a/src/hotspot/share/code/codeCache.cpp
+++ b/src/hotspot/share/code/codeCache.cpp
@@ -29,7 +29,6 @@
#include "code/compiledIC.hpp"
#include "code/dependencies.hpp"
#include "code/dependencyContext.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "code/pcDesc.hpp"
#include "compiler/compilationPolicy.hpp"
@@ -913,23 +912,6 @@ void CodeCache::verify_clean_inline_caches() {
#endif
}
-void CodeCache::verify_icholder_relocations() {
-#ifdef ASSERT
- // make sure that we aren't leaking icholders
- int count = 0;
- FOR_ALL_HEAPS(heap) {
- FOR_ALL_BLOBS(cb, *heap) {
- CompiledMethod *nm = cb->as_compiled_method_or_null();
- if (nm != nullptr) {
- count += nm->verify_icholder_relocations();
- }
- }
- }
- assert(count + InlineCacheBuffer::pending_icholder_count() + CompiledICHolder::live_not_claimed_count() ==
- CompiledICHolder::live_count(), "must agree");
-#endif
-}
-
// Defer freeing of concurrently cleaned ExceptionCache entries until
// after a global handshake operation.
void CodeCache::release_exception_cache(ExceptionCache* entry) {
diff --git a/src/hotspot/share/code/codeCache.hpp b/src/hotspot/share/code/codeCache.hpp
index 103268c8ffcd1..d1c91727bf124 100644
--- a/src/hotspot/share/code/codeCache.hpp
+++ b/src/hotspot/share/code/codeCache.hpp
@@ -294,7 +294,6 @@ class CodeCache : AllStatic {
}
static void verify_clean_inline_caches();
- static void verify_icholder_relocations();
// Deoptimization
private:
diff --git a/src/hotspot/share/code/compiledIC.cpp b/src/hotspot/share/code/compiledIC.cpp
index c5063560ee570..250ef063a2a33 100644
--- a/src/hotspot/share/code/compiledIC.cpp
+++ b/src/hotspot/share/code/compiledIC.cpp
@@ -26,27 +26,19 @@
#include "code/codeBehaviours.hpp"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "code/vtableStubs.hpp"
-#include "interpreter/interpreter.hpp"
-#include "interpreter/linkResolver.hpp"
-#include "memory/metadataFactory.hpp"
-#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
+#include "oops/compressedKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.inline.hpp"
-#include "oops/oop.inline.hpp"
-#include "oops/symbol.hpp"
+#include "runtime/atomic.hpp"
#include "runtime/continuationEntry.hpp"
#include "runtime/handles.inline.hpp"
-#include "runtime/icache.hpp"
-#include "runtime/safepoint.hpp"
+#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/sharedRuntime.hpp"
-#include "runtime/stubRoutines.hpp"
#include "sanitizers/leak.hpp"
-#include "utilities/events.hpp"
// Every time a compiled IC is changed or its type is being accessed,
@@ -75,191 +67,175 @@ bool CompiledICLocker::is_safe(address code) {
return CompiledICProtectionBehaviour::current()->is_safe(cm);
}
-//-----------------------------------------------------------------------------
-// Low-level access to an inline cache. Private, since they might not be
-// MT-safe to use.
+CompiledICData::CompiledICData()
+ : _speculated_method(),
+ _speculated_klass(),
+ _itable_defc_klass(),
+ _itable_refc_klass(),
+ _is_initialized() {}
-void* CompiledIC::cached_value() const {
- assert(CompiledICLocker::is_safe(_method), "mt unsafe call");
- assert (!is_optimized(), "an optimized virtual call does not have a cached metadata");
-
- if (!is_in_transition_state()) {
- void* data = get_data();
- // If we let the metadata value here be initialized to zero...
- assert(data != nullptr || Universe::non_oop_word() == nullptr,
- "no raw nulls in CompiledIC metadatas, because of patching races");
- return (data == (void*)Universe::non_oop_word()) ? nullptr : data;
+// Inline cache callsite info is initialized once the first time it is resolved
+void CompiledICData::initialize(CallInfo* call_info, Klass* receiver_klass) {
+ _speculated_method = call_info->selected_method();
+ if (UseCompressedClassPointers) {
+ _speculated_klass = (uintptr_t)CompressedKlassPointers::encode_not_null(receiver_klass);
} else {
- return InlineCacheBuffer::cached_value_for((CompiledIC *)this);
+ _speculated_klass = (uintptr_t)receiver_klass;
}
+ if (call_info->call_kind() == CallInfo::itable_call) {
+ _itable_defc_klass = call_info->resolved_method()->method_holder();
+ _itable_refc_klass = call_info->resolved_klass();
+ }
+ _is_initialized = true;
}
+bool CompiledICData::is_speculated_klass_unloaded() const {
+ return is_initialized() && _speculated_klass == 0;
+}
-void CompiledIC::internal_set_ic_destination(address entry_point, bool is_icstub, void* cache, bool is_icholder) {
- assert(entry_point != nullptr, "must set legal entry point");
- assert(CompiledICLocker::is_safe(_method), "mt unsafe call");
- assert (!is_optimized() || cache == nullptr, "an optimized virtual call does not have a cached metadata");
- assert (cache == nullptr || cache != (Metadata*)badOopVal, "invalid metadata");
-
- assert(!is_icholder || is_icholder_entry(entry_point), "must be");
-
- // Don't use ic_destination for this test since that forwards
- // through ICBuffer instead of returning the actual current state of
- // the CompiledIC.
- if (is_icholder_entry(_call->destination())) {
- // When patching for the ICStub case the cached value isn't
- // overwritten until the ICStub copied into the CompiledIC during
- // the next safepoint. Make sure that the CompiledICHolder* is
- // marked for release at this point since it won't be identifiable
- // once the entry point is overwritten.
- InlineCacheBuffer::queue_for_release((CompiledICHolder*)get_data());
+void CompiledICData::clean_metadata() {
+ if (!is_initialized() || is_speculated_klass_unloaded()) {
+ return;
}
- if (TraceCompiledIC) {
- tty->print(" ");
- print_compiled_ic();
- tty->print(" changing destination to " INTPTR_FORMAT, p2i(entry_point));
- if (!is_optimized()) {
- tty->print(" changing cached %s to " INTPTR_FORMAT, is_icholder ? "icholder" : "metadata", p2i((address)cache));
- }
- if (is_icstub) {
- tty->print(" (icstub)");
- }
- tty->cr();
+ // GC cleaning doesn't need to change the state of the inline cache,
+ // only nuke stale speculated metadata if it gets unloaded. If the
+ // inline cache is monomorphic, the unverified entries will miss, and
+ // subsequent miss handlers will upgrade the callsite to megamorphic,
+ // which makes sense as it obviously is megamorphic then.
+ if (!speculated_klass()->is_loader_alive()) {
+ Atomic::store(&_speculated_klass, (uintptr_t)0);
+ Atomic::store(&_speculated_method, (Method*)nullptr);
}
-#ifdef ASSERT
- {
- CodeBlob* cb = CodeCache::find_blob(_call->instruction_address());
- assert(cb != nullptr && cb->is_compiled(), "must be compiled");
- }
-#endif
- _call->set_destination_mt_safe(entry_point);
+ assert(_speculated_method == nullptr || _speculated_method->method_holder()->is_loader_alive(),
+ "Speculated method is not unloaded despite class being unloaded");
+}
- if (is_optimized() || is_icstub) {
- // Optimized call sites don't have a cache value and ICStub call
- // sites only change the entry point. Changing the value in that
- // case could lead to MT safety issues.
- assert(cache == nullptr, "must be null");
+void CompiledICData::metadata_do(MetadataClosure* cl) {
+ if (!is_initialized()) {
return;
}
- if (cache == nullptr) cache = Universe::non_oop_word();
-
- set_data((intptr_t)cache);
-}
-
-
-void CompiledIC::set_ic_destination(ICStub* stub) {
- internal_set_ic_destination(stub->code_begin(), true, nullptr, false);
+ if (!is_speculated_klass_unloaded()) {
+ cl->do_metadata(_speculated_method);
+ cl->do_metadata(speculated_klass());
+ }
+ if (_itable_refc_klass != nullptr) {
+ cl->do_metadata(_itable_refc_klass);
+ }
+ if (_itable_defc_klass != nullptr) {
+ cl->do_metadata(_itable_defc_klass);
+ }
}
+Klass* CompiledICData::speculated_klass() const {
+ if (is_speculated_klass_unloaded()) {
+ return nullptr;
+ }
-
-address CompiledIC::ic_destination() const {
- assert(CompiledICLocker::is_safe(_method), "mt unsafe call");
- if (!is_in_transition_state()) {
- return _call->destination();
+ if (UseCompressedClassPointers) {
+ return CompressedKlassPointers::decode_not_null((narrowKlass)_speculated_klass);
} else {
- return InlineCacheBuffer::ic_destination_for((CompiledIC *)this);
+ return (Klass*)_speculated_klass;
}
}
+//-----------------------------------------------------------------------------
+// High-level access to an inline cache. Guaranteed to be MT-safe.
-bool CompiledIC::is_in_transition_state() const {
- assert(CompiledICLocker::is_safe(_method), "mt unsafe call");
- return InlineCacheBuffer::contains(_call->destination());;
+CompiledICData* CompiledIC::data() const {
+ return _data;
}
+CompiledICData* data_from_reloc_iter(RelocIterator* iter) {
+ assert(iter->type() == relocInfo::virtual_call_type, "wrong reloc. info");
+
+ virtual_call_Relocation* r = iter->virtual_call_reloc();
+ NativeMovConstReg* value = nativeMovConstReg_at(r->cached_value());
+
+ return (CompiledICData*)value->data();
+}
-bool CompiledIC::is_icholder_call() const {
+CompiledIC::CompiledIC(RelocIterator* iter)
+ : _method(iter->code()),
+ _data(data_from_reloc_iter(iter)),
+ _call(nativeCall_at(iter->addr()))
+{
+ assert(_method != nullptr, "must pass compiled method");
+ assert(_method->contains(iter->addr()), "must be in compiled method");
assert(CompiledICLocker::is_safe(_method), "mt unsafe call");
- return !_is_optimized && is_icholder_entry(ic_destination());
}
-// Returns native address of 'call' instruction in inline-cache. Used by
-// the InlineCacheBuffer when it needs to find the stub.
-address CompiledIC::stub_address() const {
- assert(is_in_transition_state(), "should only be called when we are in a transition state");
- return _call->destination();
+CompiledIC* CompiledIC_before(CompiledMethod* nm, address return_addr) {
+ address call_site = nativeCall_before(return_addr)->instruction_address();
+ return CompiledIC_at(nm, call_site);
}
-// Clears the IC stub if the compiled IC is in transition state
-void CompiledIC::clear_ic_stub() {
- if (is_in_transition_state()) {
- ICStub* stub = ICStub::from_destination_address(stub_address());
- stub->clear();
- }
+CompiledIC* CompiledIC_at(CompiledMethod* nm, address call_site) {
+ RelocIterator iter(nm, call_site, call_site + 1);
+ iter.next();
+ return CompiledIC_at(&iter);
}
-//-----------------------------------------------------------------------------
-// High-level access to an inline cache. Guaranteed to be MT-safe.
+CompiledIC* CompiledIC_at(Relocation* call_reloc) {
+ address call_site = call_reloc->addr();
+ CompiledMethod* cm = CodeCache::find_blob(call_reloc->addr())->as_compiled_method();
+ return CompiledIC_at(cm, call_site);
+}
-void CompiledIC::initialize_from_iter(RelocIterator* iter) {
- assert(iter->addr() == _call->instruction_address(), "must find ic_call");
+CompiledIC* CompiledIC_at(RelocIterator* reloc_iter) {
+ CompiledIC* c_ic = new CompiledIC(reloc_iter);
+ c_ic->verify();
+ return c_ic;
+}
- if (iter->type() == relocInfo::virtual_call_type) {
- virtual_call_Relocation* r = iter->virtual_call_reloc();
- _is_optimized = false;
- _value = _call->get_load_instruction(r);
- } else {
- assert(iter->type() == relocInfo::opt_virtual_call_type, "must be a virtual call");
- _is_optimized = true;
- _value = nullptr;
+void CompiledIC::ensure_initialized(CallInfo* call_info, Klass* receiver_klass) {
+ if (!_data->is_initialized()) {
+ _data->initialize(call_info, receiver_klass);
}
}
-CompiledIC::CompiledIC(CompiledMethod* cm, NativeCall* call)
- : _method(cm)
-{
- _call = _method->call_wrapper_at((address) call);
- address ic_call = _call->instruction_address();
-
- assert(ic_call != nullptr, "ic_call address must be set");
- assert(cm != nullptr, "must pass compiled method");
- assert(cm->contains(ic_call), "must be in compiled method");
-
- // Search for the ic_call at the given address.
- RelocIterator iter(cm, ic_call, ic_call+1);
- bool ret = iter.next();
- assert(ret == true, "relocInfo must exist at this address");
- assert(iter.addr() == ic_call, "must find ic_call");
-
- initialize_from_iter(&iter);
+void CompiledIC::set_to_clean() {
+ log_debug(inlinecache)("IC@" INTPTR_FORMAT ": set to clean", p2i(_call->instruction_address()));
+ _call->set_destination_mt_safe(SharedRuntime::get_resolve_virtual_call_stub());
}
-CompiledIC::CompiledIC(RelocIterator* iter)
- : _method(iter->code())
-{
- _call = _method->call_wrapper_at(iter->addr());
- address ic_call = _call->instruction_address();
+void CompiledIC::set_to_monomorphic() {
+ assert(data()->is_initialized(), "must be initialized");
+ Method* method = data()->speculated_method();
+ CompiledMethod* code = method->code();
+ address entry;
+ bool to_compiled = code != nullptr && code->is_in_use() && !code->is_unloading();
+
+ if (to_compiled) {
+ entry = code->entry_point();
+ } else {
+ entry = method->get_c2i_unverified_entry();
+ }
- CompiledMethod* nm = iter->code();
- assert(ic_call != nullptr, "ic_call address must be set");
- assert(nm != nullptr, "must pass compiled method");
- assert(nm->contains(ic_call), "must be in compiled method");
+ log_trace(inlinecache)("IC@" INTPTR_FORMAT ": monomorphic to %s: %s",
+ p2i(_call->instruction_address()),
+ to_compiled ? "compiled" : "interpreter",
+ method->print_value_string());
- initialize_from_iter(iter);
+ _call->set_destination_mt_safe(entry);
}
-// This function may fail for two reasons: either due to running out of vtable
-// stubs, or due to running out of IC stubs in an attempted transition to a
-// transitional state. The needs_ic_stub_refill value will be set if the failure
-// was due to running out of IC stubs, in which case the caller will refill IC
-// stubs and retry.
-bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode,
- bool& needs_ic_stub_refill, TRAPS) {
- assert(CompiledICLocker::is_safe(_method), "mt unsafe call");
- assert(!is_optimized(), "cannot set an optimized virtual call to megamorphic");
- assert(is_call_to_compiled() || is_call_to_interpreted(), "going directly to megamorphic?");
+void CompiledIC::set_to_megamorphic(CallInfo* call_info) {
+ assert(data()->is_initialized(), "must be initialized");
address entry;
- if (call_info->call_kind() == CallInfo::itable_call) {
- assert(bytecode == Bytecodes::_invokeinterface, "");
+ if (call_info->call_kind() == CallInfo::direct_call) {
+ // C1 sometimes compiles a callsite before the target method is loaded, resulting in
+ // dynamically bound callsites that should really be statically bound. However, the
+ // target method might not have a vtable or itable. We just wait for better code to arrive
+ return;
+ } else if (call_info->call_kind() == CallInfo::itable_call) {
int itable_index = call_info->itable_index();
entry = VtableStubs::find_itable_stub(itable_index);
if (entry == nullptr) {
- return false;
+ return;
}
#ifdef ASSERT
int index = call_info->resolved_method()->itable_index();
@@ -267,401 +243,151 @@ bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecod
InstanceKlass* k = call_info->resolved_method()->method_holder();
assert(k->verify_itable_index(itable_index), "sanity check");
#endif //ASSERT
- CompiledICHolder* holder = new CompiledICHolder(call_info->resolved_method()->method_holder(),
- call_info->resolved_klass(), false);
- holder->claim();
- if (!InlineCacheBuffer::create_transition_stub(this, holder, entry)) {
- delete holder;
- needs_ic_stub_refill = true;
- return false;
- }
- // LSan appears unable to follow malloc-based memory consistently when embedded as an immediate
- // in generated machine code. So we have to ignore it.
- LSAN_IGNORE_OBJECT(holder);
} else {
- assert(call_info->call_kind() == CallInfo::vtable_call, "either itable or vtable");
+ assert(call_info->call_kind() == CallInfo::vtable_call, "what else?");
// Can be different than selected_method->vtable_index(), due to package-private etc.
int vtable_index = call_info->vtable_index();
assert(call_info->resolved_klass()->verify_vtable_index(vtable_index), "sanity check");
entry = VtableStubs::find_vtable_stub(vtable_index);
if (entry == nullptr) {
- return false;
+ return;
}
- if (!InlineCacheBuffer::create_transition_stub(this, nullptr, entry)) {
- needs_ic_stub_refill = true;
- return false;
- }
- }
-
- {
- ResourceMark rm;
- assert(call_info->selected_method() != nullptr, "Unexpected null selected method");
- log_trace(inlinecache)("IC@" INTPTR_FORMAT ": to megamorphic %s entry: " INTPTR_FORMAT,
- p2i(instruction_address()), call_info->selected_method()->print_value_string(), p2i(entry));
}
- // We can't check this anymore. With lazy deopt we could have already
- // cleaned this IC entry before we even return. This is possible if
- // we ran out of space in the inline cache buffer trying to do the
- // set_next and we safepointed to free up space. This is a benign
- // race because the IC entry was complete when we safepointed so
- // cleaning it immediately is harmless.
- // assert(is_megamorphic(), "sanity check");
- return true;
-}
-
+ 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));
-// true if destination is megamorphic stub
-bool CompiledIC::is_megamorphic() const {
- assert(CompiledICLocker::is_safe(_method), "mt unsafe call");
- assert(!is_optimized(), "an optimized call cannot be megamorphic");
-
- // Cannot rely on cached_value. It is either an interface or a method.
- return VtableStubs::entry_point(ic_destination()) != nullptr;
+ _call->set_destination_mt_safe(entry);
+ assert(is_megamorphic(), "sanity check");
}
-bool CompiledIC::is_call_to_compiled() const {
- assert(CompiledICLocker::is_safe(_method), "mt unsafe call");
-
- CodeBlob* cb = CodeCache::find_blob(ic_destination());
- bool is_monomorphic = (cb != nullptr && cb->is_compiled());
- // Check that the cached_value is a klass for non-optimized monomorphic calls
- // This assertion is invalid for compiler1: a call that does not look optimized (no static stub) can be used
- // for calling directly to vep without using the inline cache (i.e., cached_value == nullptr).
- // For JVMCI this occurs because CHA is only used to improve inlining so call sites which could be optimized
- // virtuals because there are no currently loaded subclasses of a type are left as virtual call sites.
-#ifdef ASSERT
- CodeBlob* caller = CodeCache::find_blob(instruction_address());
- bool is_c1_or_jvmci_method = caller->is_compiled_by_c1() || caller->is_compiled_by_jvmci();
- assert( is_c1_or_jvmci_method ||
- !is_monomorphic ||
- is_optimized() ||
- (cached_metadata() != nullptr && cached_metadata()->is_klass()), "sanity check");
-#endif // ASSERT
- return is_monomorphic;
-}
+void CompiledIC::update(CallInfo* call_info, Klass* receiver_klass) {
+ // If this is the first time we fix the inline cache, we ensure it's initialized
+ ensure_initialized(call_info, receiver_klass);
+ if (is_megamorphic()) {
+ // Terminal state for the inline cache
+ return;
+ }
-bool CompiledIC::is_call_to_interpreted() const {
- assert(CompiledICLocker::is_safe(_method), "mt unsafe call");
- // Call to interpreter if destination is either calling to a stub (if it
- // is optimized), or calling to an I2C blob
- bool is_call_to_interpreted = false;
- if (!is_optimized()) {
- CodeBlob* cb = CodeCache::find_blob(ic_destination());
- is_call_to_interpreted = (cb != nullptr && cb->is_adapter_blob());
- assert(!is_call_to_interpreted || (is_icholder_call() && cached_icholder() != nullptr), "sanity check");
+ if (is_speculated_klass(receiver_klass)) {
+ // If the speculated class matches the receiver klass, we can speculate that will
+ // continue to be the case with a monomorphic inline cache
+ set_to_monomorphic();
} else {
- // Check if we are calling into our own codeblob (i.e., to a stub)
- address dest = ic_destination();
-#ifdef ASSERT
- {
- _call->verify_resolve_call(dest);
- }
-#endif /* ASSERT */
- is_call_to_interpreted = _call->is_call_to_interpreted(dest);
+ // If the dynamic type speculation fails, we try to transform to a megamorphic state
+ // for the inline cache using stubs to dispatch in tables
+ set_to_megamorphic(call_info);
}
- return is_call_to_interpreted;
}
-bool CompiledIC::set_to_clean(bool in_use) {
- assert(CompiledICLocker::is_safe(_method), "mt unsafe call");
- if (TraceInlineCacheClearing) {
- tty->print_cr("IC@" INTPTR_FORMAT ": set to clean", p2i(instruction_address()));
- print();
- }
- log_trace(inlinecache)("IC@" INTPTR_FORMAT ": set to clean", p2i(instruction_address()));
-
- address entry = _call->get_resolve_call_stub(is_optimized());
-
- bool safe_transition = _call->is_safe_for_patching() || !in_use || is_optimized() || SafepointSynchronize::is_at_safepoint();
+bool CompiledIC::is_clean() const {
+ return destination() == SharedRuntime::get_resolve_virtual_call_stub();
+}
- if (safe_transition) {
- // Kill any leftover stub we might have too
- clear_ic_stub();
- if (is_optimized()) {
- set_ic_destination(entry);
- } else {
- set_ic_destination_and_value(entry, (void*)nullptr);
- }
- } else {
- // Unsafe transition - create stub.
- if (!InlineCacheBuffer::create_transition_stub(this, nullptr, entry)) {
- return false;
- }
- }
- // We can't check this anymore. With lazy deopt we could have already
- // cleaned this IC entry before we even return. This is possible if
- // we ran out of space in the inline cache buffer trying to do the
- // set_next and we safepointed to free up space. This is a benign
- // race because the IC entry was complete when we safepointed so
- // cleaning it immediately is harmless.
- // assert(is_clean(), "sanity check");
- return true;
+bool CompiledIC::is_monomorphic() const {
+ return !is_clean() && !is_megamorphic();
}
-bool CompiledIC::is_clean() const {
- assert(CompiledICLocker::is_safe(_method), "mt unsafe call");
- bool is_clean = false;
- address dest = ic_destination();
- is_clean = dest == _call->get_resolve_call_stub(is_optimized());
- assert(!is_clean || is_optimized() || cached_value() == nullptr, "sanity check");
- return is_clean;
+bool CompiledIC::is_megamorphic() const {
+ return VtableStubs::entry_point(destination()) != nullptr;;
}
-bool CompiledIC::set_to_monomorphic(CompiledICInfo& info) {
- assert(CompiledICLocker::is_safe(_method), "mt unsafe call");
- // Updating a cache to the wrong entry can cause bugs that are very hard
- // to track down - if cache entry gets invalid - we just clean it. In
- // this way it is always the same code path that is responsible for
- // updating and resolving an inline cache
- //
- // The above is no longer true. SharedRuntime::fixup_callers_callsite will change optimized
- // callsites. In addition ic_miss code will update a site to monomorphic if it determines
- // that an monomorphic call to the interpreter can now be monomorphic to compiled code.
- //
- // In both of these cases the only thing being modified is the jump/call target and these
- // transitions are mt_safe
-
- Thread *thread = Thread::current();
- if (info.to_interpreter()) {
- // Call to interpreter
- if (info.is_optimized() && is_optimized()) {
- assert(is_clean(), "unsafe IC path");
- // the call analysis (callee structure) specifies that the call is optimized
- // (either because of CHA or the static target is final)
- // At code generation time, this call has been emitted as static call
- // Call via stub
- assert(info.cached_metadata() != nullptr && info.cached_metadata()->is_method(), "sanity check");
- methodHandle method (thread, (Method*)info.cached_metadata());
- _call->set_to_interpreted(method, info);
-
- {
- ResourceMark rm(thread);
- log_trace(inlinecache)("IC@" INTPTR_FORMAT ": monomorphic to interpreter: %s",
- p2i(instruction_address()),
- method->print_value_string());
- }
- } else {
- // Call via method-klass-holder
- CompiledICHolder* holder = info.claim_cached_icholder();
- if (!InlineCacheBuffer::create_transition_stub(this, holder, info.entry())) {
- delete holder;
- return false;
- }
- // LSan appears unable to follow malloc-based memory consistently when embedded as an
- // immediate in generated machine code. So we have to ignore it.
- LSAN_IGNORE_OBJECT(holder);
- {
- ResourceMark rm(thread);
- log_trace(inlinecache)("IC@" INTPTR_FORMAT ": monomorphic to interpreter via icholder ", p2i(instruction_address()));
- }
- }
- } else {
- // Call to compiled code
- bool static_bound = info.is_optimized() || (info.cached_metadata() == nullptr);
-#ifdef ASSERT
- CodeBlob* cb = CodeCache::find_blob(info.entry());
- assert (cb != nullptr && cb->is_compiled(), "must be compiled!");
-#endif /* ASSERT */
-
- // This is MT safe if we come from a clean-cache and go through a
- // non-verified entry point
- bool safe = SafepointSynchronize::is_at_safepoint() ||
- (!is_in_transition_state() && (info.is_optimized() || static_bound || is_clean()));
-
- if (!safe) {
- if (!InlineCacheBuffer::create_transition_stub(this, info.cached_metadata(), info.entry())) {
- return false;
- }
- } else {
- if (is_optimized()) {
- set_ic_destination(info.entry());
- } else {
- set_ic_destination_and_value(info.entry(), info.cached_metadata());
- }
- }
+bool CompiledIC::is_speculated_klass(Klass* receiver_klass) {
+ return data()->speculated_klass() == receiver_klass;
+}
- {
- ResourceMark rm(thread);
- assert(info.cached_metadata() == nullptr || info.cached_metadata()->is_klass(), "must be");
- log_trace(inlinecache)("IC@" INTPTR_FORMAT ": monomorphic to compiled (rcvr klass = %s) %s",
- p2i(instruction_address()),
- (info.cached_metadata() != nullptr) ? ((Klass*)info.cached_metadata())->print_value_string() : "nullptr",
- (safe) ? "" : " via stub");
- }
- }
- // We can't check this anymore. With lazy deopt we could have already
- // cleaned this IC entry before we even return. This is possible if
- // we ran out of space in the inline cache buffer trying to do the
- // set_next and we safepointed to free up space. This is a benign
- // race because the IC entry was complete when we safepointed so
- // cleaning it immediately is harmless.
- // assert(is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
- return true;
-}
-
-
-// is_optimized: Compiler has generated an optimized call (i.e. fixed, no inline cache)
-// static_bound: The call can be static bound. If it isn't also optimized, the property
-// wasn't provable at time of compilation. An optimized call will have any necessary
-// null check, while a static_bound won't. A static_bound (but not optimized) must
-// therefore use the unverified entry point.
-void CompiledIC::compute_monomorphic_entry(const methodHandle& method,
- Klass* receiver_klass,
- bool is_optimized,
- bool static_bound,
- bool caller_is_nmethod,
- CompiledICInfo& info,
- TRAPS) {
- CompiledMethod* method_code = method->code();
-
- address entry = nullptr;
- if (method_code != nullptr && method_code->is_in_use() && !method_code->is_unloading()) {
- assert(method_code->is_compiled(), "must be compiled");
- // Call to compiled code
- //
- // Note: the following problem exists with Compiler1:
- // - at compile time we may or may not know if the destination is final
- // - if we know that the destination is final (is_optimized), we will emit
- // an optimized virtual call (no inline cache), and need a Method* to make
- // a call to the interpreter
- // - if we don't know if the destination is final, we emit a standard
- // virtual call, and use CompiledICHolder to call interpreted code
- // (no static call stub has been generated)
- // - In the case that we here notice the call is static bound we
- // convert the call into what looks to be an optimized virtual call,
- // but we must use the unverified entry point (since there will be no
- // null check on a call when the target isn't loaded).
- // This causes problems when verifying the IC because
- // it looks vanilla but is optimized. Code in is_call_to_interpreted
- // is aware of this and weakens its asserts.
- if (is_optimized) {
- entry = method_code->verified_entry_point();
- } else {
- entry = method_code->entry_point();
- }
- }
- if (entry != nullptr) {
- // Call to near compiled code.
- info.set_compiled_entry(entry, is_optimized ? nullptr : receiver_klass, is_optimized);
- } else {
- if (is_optimized) {
- // Use stub entry
- info.set_interpreter_entry(method()->get_c2i_entry(), method());
- } else {
- // Use icholder entry
- assert(method_code == nullptr || method_code->is_compiled(), "must be compiled");
- CompiledICHolder* holder = new CompiledICHolder(method(), receiver_klass);
- info.set_icholder_entry(method()->get_c2i_unverified_entry(), holder);
- }
- }
- assert(info.is_optimized() == is_optimized, "must agree");
+// GC support
+void CompiledIC::clean_metadata() {
+ data()->clean_metadata();
}
+void CompiledIC::metadata_do(MetadataClosure* cl) {
+ data()->metadata_do(cl);
+}
-bool CompiledIC::is_icholder_entry(address entry) {
- CodeBlob* cb = CodeCache::find_blob(entry);
- if (cb == nullptr) {
- return false;
- }
- if (cb->is_adapter_blob()) {
- return true;
- } else if (cb->is_vtable_blob()) {
- return VtableStubs::is_icholder_entry(entry);
- }
- return false;
+#ifndef PRODUCT
+void CompiledIC::print() {
+ tty->print("Inline cache at " INTPTR_FORMAT ", calling " INTPTR_FORMAT " cached_value " INTPTR_FORMAT,
+ p2i(instruction_address()), p2i(destination()), p2i(data()));
+ tty->cr();
}
-bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm) {
- // This call site might have become stale so inspect it carefully.
- address dest = cm->call_wrapper_at(call_site->addr())->destination();
- return is_icholder_entry(dest);
+void CompiledIC::verify() {
+ _call->verify();
}
+#endif
// ----------------------------------------------------------------------------
-bool CompiledStaticCall::set_to_clean(bool in_use) {
+void CompiledDirectCall::set_to_clean() {
// in_use is unused but needed to match template function in CompiledMethod
assert(CompiledICLocker::is_safe(instruction_address()), "mt unsafe call");
// Reset call site
- set_destination_mt_safe(resolve_call_stub());
+ RelocIterator iter((nmethod*)nullptr, instruction_address(), instruction_address() + 1);
+ while (iter.next()) {
+ switch(iter.type()) {
+ case relocInfo::static_call_type:
+ _call->set_destination_mt_safe(SharedRuntime::get_resolve_static_call_stub());
+ break;
+ case relocInfo::opt_virtual_call_type:
+ _call->set_destination_mt_safe(SharedRuntime::get_resolve_opt_virtual_call_stub());
+ break;
+ default:
+ ShouldNotReachHere();
+ }
+ }
+ assert(is_clean(), "should be clean after cleaning");
- // Do not reset stub here: It is too expensive to call find_stub.
- // Instead, rely on caller (nmethod::clear_inline_caches) to clear
- // both the call and its stub.
- return true;
+ log_debug(inlinecache)("DC@" INTPTR_FORMAT ": set to clean", p2i(_call->instruction_address()));
}
-bool CompiledStaticCall::is_clean() const {
- return destination() == resolve_call_stub();
-}
+void CompiledDirectCall::set(const methodHandle& callee_method) {
+ CompiledMethod* code = callee_method->code();
+ CompiledMethod* caller = CodeCache::find_compiled(instruction_address());
-bool CompiledStaticCall::is_call_to_compiled() const {
- return CodeCache::contains(destination());
-}
+ bool to_interp_cont_enter = caller->method()->is_continuation_enter_intrinsic() &&
+ ContinuationEntry::is_interpreted_call(instruction_address());
-bool CompiledDirectStaticCall::is_call_to_interpreted() const {
- // It is a call to interpreted, if it calls to a stub. Hence, the destination
- // must be in the stub part of the nmethod that contains the call
- CompiledMethod* cm = CodeCache::find_compiled(instruction_address());
- return cm->stub_contains(destination());
-}
+ bool to_compiled = !to_interp_cont_enter && code != nullptr && code->is_in_use() && !code->is_unloading();
-void CompiledStaticCall::set_to_compiled(address entry) {
- {
- ResourceMark rm;
- log_trace(inlinecache)("%s@" INTPTR_FORMAT ": set_to_compiled " INTPTR_FORMAT,
- name(),
- p2i(instruction_address()),
- p2i(entry));
+ if (to_compiled) {
+ _call->set_destination_mt_safe(code->verified_entry_point());
+ assert(is_call_to_compiled(), "should be compiled after set to compiled");
+ } else {
+ // Patch call site to C2I adapter if code is deoptimized or unloaded.
+ // We also need to patch the static call stub to set the rmethod register
+ // to the callee_method so the c2i adapter knows how to build the frame
+ set_to_interpreted(callee_method, callee_method->get_c2i_entry());
+ assert(is_call_to_interpreted(), "should be interpreted after set to interpreted");
}
- // Call to compiled code
- assert(CodeCache::contains(entry), "wrong entry point");
- set_destination_mt_safe(entry);
+
+ log_trace(inlinecache)("DC@" INTPTR_FORMAT ": set to %s: %s: " INTPTR_FORMAT,
+ p2i(_call->instruction_address()),
+ to_compiled ? "compiled" : "interpreter",
+ callee_method->print_value_string(),
+ p2i(_call->destination()));
}
-void CompiledStaticCall::set(const StaticCallInfo& info) {
- assert(CompiledICLocker::is_safe(instruction_address()), "mt unsafe call");
- // Updating a cache to the wrong entry can cause bugs that are very hard
- // to track down - if cache entry gets invalid - we just clean it. In
- // this way it is always the same code path that is responsible for
- // updating and resolving an inline cache
- assert(is_clean(), "do not update a call entry - use clean");
-
- if (info._to_interpreter) {
- // Call to interpreted code
- set_to_interpreted(info.callee(), info.entry());
- } else {
- set_to_compiled(info.entry());
- }
+bool CompiledDirectCall::is_clean() const {
+ return destination() == SharedRuntime::get_resolve_static_call_stub() ||
+ destination() == SharedRuntime::get_resolve_opt_virtual_call_stub();
}
-// Compute settings for a CompiledStaticCall. Since we might have to set
-// the stub when calling to the interpreter, we need to return arguments.
-void CompiledStaticCall::compute_entry(const methodHandle& m, bool caller_is_nmethod, StaticCallInfo& info) {
- CompiledMethod* m_code = m->code();
- info._callee = m;
- if (m_code != nullptr && m_code->is_in_use() && !m_code->is_unloading()) {
- info._to_interpreter = false;
- info._entry = m_code->verified_entry_point();
- } else {
- // Callee is interpreted code. In any case entering the interpreter
- // puts a converter-frame on the stack to save arguments.
- assert(!m->is_method_handle_intrinsic(), "Compiled code should never call interpreter MH intrinsics");
- info._to_interpreter = true;
- info._entry = m()->get_c2i_entry();
- }
+bool CompiledDirectCall::is_call_to_interpreted() const {
+ // It is a call to interpreted, if it calls to a stub. Hence, the destination
+ // must be in the stub part of the nmethod that contains the call
+ CompiledMethod* cm = CodeCache::find_compiled(instruction_address());
+ return cm->stub_contains(destination());
}
-void CompiledStaticCall::compute_entry_for_continuation_entry(const methodHandle& m, StaticCallInfo& info) {
- if (ContinuationEntry::is_interpreted_call(instruction_address())) {
- info._to_interpreter = true;
- info._entry = m()->get_c2i_entry();
- }
+bool CompiledDirectCall::is_call_to_compiled() const {
+ CompiledMethod* caller = CodeCache::find_compiled(instruction_address());
+ CodeBlob* dest_cb = CodeCache::find_blob(destination());
+ return !caller->stub_contains(destination()) && dest_cb->is_compiled();
}
-address CompiledDirectStaticCall::find_stub_for(address instruction) {
+address CompiledDirectCall::find_stub_for(address instruction) {
// Find reloc. information containing this call-site
RelocIterator iter((nmethod*)nullptr, instruction);
while (iter.next()) {
@@ -673,8 +399,6 @@ address CompiledDirectStaticCall::find_stub_for(address instruction) {
// from the CompiledIC implementation
case relocInfo::opt_virtual_call_type:
return iter.opt_virtual_call_reloc()->static_stub();
- case relocInfo::poll_type:
- case relocInfo::poll_return_type: // A safepoint can't overlap a call.
default:
ShouldNotReachHere();
}
@@ -683,36 +407,13 @@ address CompiledDirectStaticCall::find_stub_for(address instruction) {
return nullptr;
}
-address CompiledDirectStaticCall::find_stub() {
- return CompiledDirectStaticCall::find_stub_for(instruction_address());
+address CompiledDirectCall::find_stub() {
+ return find_stub_for(instruction_address());
}
-address CompiledDirectStaticCall::resolve_call_stub() const {
- return SharedRuntime::get_resolve_static_call_stub();
-}
-
-//-----------------------------------------------------------------------------
-// Non-product mode code
#ifndef PRODUCT
-
-void CompiledIC::verify() {
- _call->verify();
- assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted()
- || is_optimized() || is_megamorphic(), "sanity check");
-}
-
-void CompiledIC::print() {
- print_compiled_ic();
- tty->cr();
-}
-
-void CompiledIC::print_compiled_ic() {
- tty->print("Inline cache at " INTPTR_FORMAT ", calling %s " INTPTR_FORMAT " cached_value " INTPTR_FORMAT,
- p2i(instruction_address()), is_call_to_interpreted() ? "interpreted " : "", p2i(ic_destination()), p2i(is_optimized() ? nullptr : cached_value()));
-}
-
-void CompiledDirectStaticCall::print() {
- tty->print("static call at " INTPTR_FORMAT " -> ", p2i(instruction_address()));
+void CompiledDirectCall::print() {
+ tty->print("direct call at " INTPTR_FORMAT " to " INTPTR_FORMAT " -> ", p2i(instruction_address()), p2i(destination()));
if (is_clean()) {
tty->print("clean");
} else if (is_call_to_compiled()) {
@@ -723,9 +424,10 @@ void CompiledDirectStaticCall::print() {
tty->cr();
}
-void CompiledDirectStaticCall::verify_mt_safe(const methodHandle& callee, address entry,
- NativeMovConstReg* method_holder,
- NativeJump* jump) {
+void CompiledDirectCall::verify_mt_safe(const methodHandle& callee, address entry,
+ NativeMovConstReg* method_holder,
+ NativeJump* jump) {
+ _call->verify();
// A generated lambda form might be deleted from the Lambdaform
// cache in MethodTypeForm. If a jit compiled lambdaform method
// becomes not entrant and the cache access returns null, the new
@@ -743,4 +445,4 @@ void CompiledDirectStaticCall::verify_mt_safe(const methodHandle& callee, addres
|| old_method->is_old(), // may be race patching deoptimized nmethod due to redefinition.
"b) MT-unsafe modification of inline cache");
}
-#endif // !PRODUCT
+#endif
diff --git a/src/hotspot/share/code/compiledIC.hpp b/src/hotspot/share/code/compiledIC.hpp
index 17586fc57a05f..321bf280ed40a 100644
--- a/src/hotspot/share/code/compiledIC.hpp
+++ b/src/hotspot/share/code/compiledIC.hpp
@@ -27,42 +27,19 @@
#include "code/nativeInst.hpp"
#include "interpreter/linkResolver.hpp"
-#include "oops/compiledICHolder.hpp"
#include "runtime/safepointVerifiers.hpp"
//-----------------------------------------------------------------------------
// The CompiledIC represents a compiled inline cache.
//
-// In order to make patching of the inline cache MT-safe, we only allow the following
-// transitions (when not at a safepoint):
-//
-//
-// [1] --<-- Clean -->--- [1]
-// / (null) \
-// / \ /-<-\
-// / [2] \ / \
-// Interpreted ---------> Monomorphic | [3]
-// (CompiledICHolder*) (Klass*) |
-// \ / \ /
-// [4] \ / [4] \->-/
-// \->- Megamorphic -<-/
-// (CompiledICHolder*)
-//
-// The text in parentheses () refers to the value of the inline cache receiver (mov instruction)
-//
-// The numbers in square brackets refer to the kind of transition:
-// [1]: Initial fixup. Receiver it found from debug information
-// [2]: Compilation of a method
-// [3]: Recompilation of a method (note: only entry is changed. The Klass* must stay the same)
-// [4]: Inline cache miss. We go directly to megamorphic call.
-//
-// The class automatically inserts transition stubs (using the InlineCacheBuffer) when an MT-unsafe
-// transition is made to a stub.
+// It's safe to transition from any state to any state. Typically an inline cache starts
+// in the clean state, meaning it will resolve the call when called. Then it typically
+// transitions to monomorphic, assuming the first dynamic receiver will be the only one
+// observed. If that speculation fails, we transition to megamorphic.
//
class CompiledIC;
class CompiledICProtectionBehaviour;
class CompiledMethod;
-class ICStub;
class CompiledICLocker: public StackObj {
CompiledMethod* _method;
@@ -77,237 +54,105 @@ class CompiledICLocker: public StackObj {
static bool is_safe(address code);
};
-class CompiledICInfo : public StackObj {
- private:
- address _entry; // entry point for call
- void* _cached_value; // Value of cached_value (either in stub or inline cache)
- bool _is_icholder; // Is the cached value a CompiledICHolder*
- bool _is_optimized; // it is an optimized virtual call (i.e., can be statically bound)
- bool _to_interpreter; // Call it to interpreter
- bool _release_icholder;
+// A CompiledICData is a helper object for the inline cache implementation.
+// It comprises:
+// (1) The first receiver klass and its selected method
+// (2) Itable call metadata
+
+class CompiledICData : public CHeapObj {
+ friend class VMStructs;
+ friend class JVMCIVMStructs;
+
+ Method* volatile _speculated_method;
+ uintptr_t volatile _speculated_klass;
+ Klass* _itable_defc_klass;
+ Klass* _itable_refc_klass;
+ bool _is_initialized;
+
+ bool is_speculated_klass_unloaded() const;
+
public:
- address entry() const { return _entry; }
- Metadata* cached_metadata() const { assert(!_is_icholder, ""); return (Metadata*)_cached_value; }
- CompiledICHolder* claim_cached_icholder() {
- assert(_is_icholder, "");
- assert(_cached_value != nullptr, "must be non-null");
- _release_icholder = false;
- CompiledICHolder* icholder = (CompiledICHolder*)_cached_value;
- icholder->claim();
- return icholder;
- }
- bool is_optimized() const { return _is_optimized; }
- bool to_interpreter() const { return _to_interpreter; }
-
- void set_compiled_entry(address entry, Klass* klass, bool is_optimized) {
- _entry = entry;
- _cached_value = (void*)klass;
- _to_interpreter = false;
- _is_icholder = false;
- _is_optimized = is_optimized;
- _release_icholder = false;
- }
+ // Constructor
+ CompiledICData();
- void set_interpreter_entry(address entry, Method* method) {
- _entry = entry;
- _cached_value = (void*)method;
- _to_interpreter = true;
- _is_icholder = false;
- _is_optimized = true;
- _release_icholder = false;
- }
+ // accessors
+ Klass* speculated_klass() const;
+ Method* speculated_method() const { return _speculated_method; }
+ Klass* itable_defc_klass() const { return _itable_defc_klass; }
+ Klass* itable_refc_klass() const { return _itable_refc_klass; }
- void set_icholder_entry(address entry, CompiledICHolder* icholder) {
- _entry = entry;
- _cached_value = (void*)icholder;
- _to_interpreter = true;
- _is_icholder = true;
- _is_optimized = false;
- _release_icholder = true;
- }
+ static ByteSize speculated_method_offset() { return byte_offset_of(CompiledICData, _speculated_method); }
+ static ByteSize speculated_klass_offset() { return byte_offset_of(CompiledICData, _speculated_klass); }
- CompiledICInfo(): _entry(nullptr), _cached_value(nullptr), _is_icholder(false),
- _is_optimized(false), _to_interpreter(false), _release_icholder(false) {
- }
- ~CompiledICInfo() {
- // In rare cases the info is computed but not used, so release any
- // CompiledICHolder* that was created
- if (_release_icholder) {
- assert(_is_icholder, "must be");
- CompiledICHolder* icholder = (CompiledICHolder*)_cached_value;
- icholder->claim();
- delete icholder;
- }
- }
-};
+ static ByteSize itable_defc_klass_offset() { return byte_offset_of(CompiledICData, _itable_defc_klass); }
+ static ByteSize itable_refc_klass_offset() { return byte_offset_of(CompiledICData, _itable_refc_klass); }
-class NativeCallWrapper: public ResourceObj {
-public:
- virtual address destination() const = 0;
- virtual address instruction_address() const = 0;
- virtual address next_instruction_address() const = 0;
- virtual address return_address() const = 0;
- virtual address get_resolve_call_stub(bool is_optimized) const = 0;
- virtual void set_destination_mt_safe(address dest) = 0;
- virtual void set_to_interpreted(const methodHandle& method, CompiledICInfo& info) = 0;
- virtual void verify() const = 0;
- virtual void verify_resolve_call(address dest) const = 0;
-
- virtual bool is_call_to_interpreted(address dest) const = 0;
- virtual bool is_safe_for_patching() const = 0;
-
- virtual NativeInstruction* get_load_instruction(virtual_call_Relocation* r) const = 0;
-
- virtual void *get_data(NativeInstruction* instruction) const = 0;
- virtual void set_data(NativeInstruction* instruction, intptr_t data) = 0;
+ void initialize(CallInfo* call_info, Klass* receiver_klass);
+
+ bool is_initialized() const { return _is_initialized; }
+
+ // GC Support
+ void clean_metadata();
+ void metadata_do(MetadataClosure* cl);
};
class CompiledIC: public ResourceObj {
- friend class InlineCacheBuffer;
- friend class ICStub;
-
- private:
- NativeCallWrapper* _call;
- NativeInstruction* _value; // patchable value cell for this IC
- bool _is_optimized; // an optimized virtual call (i.e., no compiled IC)
+private:
CompiledMethod* _method;
+ CompiledICData* _data;
+ NativeCall* _call;
- CompiledIC(CompiledMethod* cm, NativeCall* ic_call);
CompiledIC(RelocIterator* iter);
- void initialize_from_iter(RelocIterator* iter);
+ // CompiledICData wrappers
+ void ensure_initialized(CallInfo* call_info, Klass* receiver_klass);
+ bool is_speculated_klass(Klass* receiver_klass);
- static bool is_icholder_entry(address entry);
+ // Inline cache states
+ void set_to_monomorphic();
+ void set_to_megamorphic(CallInfo* call_info);
- // low-level inline-cache manipulation. Cannot be accessed directly, since it might not be MT-safe
- // to change an inline-cache. These changes the underlying inline-cache directly. They *newer* make
- // changes to a transition stub.
- void internal_set_ic_destination(address entry_point, bool is_icstub, void* cache, bool is_icholder);
- void set_ic_destination(ICStub* stub);
- void set_ic_destination(address entry_point) {
- assert(_is_optimized, "use set_ic_destination_and_value instead");
- internal_set_ic_destination(entry_point, false, nullptr, false);
- }
- // This only for use by ICStubs where the type of the value isn't known
- void set_ic_destination_and_value(address entry_point, void* value) {
- internal_set_ic_destination(entry_point, false, value, is_icholder_entry(entry_point));
- }
- void set_ic_destination_and_value(address entry_point, Metadata* value) {
- internal_set_ic_destination(entry_point, false, value, false);
- }
- void set_ic_destination_and_value(address entry_point, CompiledICHolder* value) {
- internal_set_ic_destination(entry_point, false, value, true);
- }
-
- // Reads the location of the transition stub. This will fail with an assertion, if no transition stub is
- // associated with the inline cache.
- address stub_address() const;
- bool is_in_transition_state() const; // Use InlineCacheBuffer
-
- public:
+public:
// conversion (machine PC to CompiledIC*)
friend CompiledIC* CompiledIC_before(CompiledMethod* nm, address return_addr);
friend CompiledIC* CompiledIC_at(CompiledMethod* nm, address call_site);
friend CompiledIC* CompiledIC_at(Relocation* call_site);
friend CompiledIC* CompiledIC_at(RelocIterator* reloc_iter);
- static bool is_icholder_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm);
-
- // Return the cached_metadata/destination associated with this inline cache. If the cache currently points
- // to a transition stub, it will read the values from the transition stub.
- void* cached_value() const;
- CompiledICHolder* cached_icholder() const {
- assert(is_icholder_call(), "must be");
- return (CompiledICHolder*) cached_value();
- }
- Metadata* cached_metadata() const {
- assert(!is_icholder_call(), "must be");
- return (Metadata*) cached_value();
- }
-
- void* get_data() const {
- return _call->get_data(_value);
- }
-
- void set_data(intptr_t data) {
- _call->set_data(_value, data);
- }
-
- address ic_destination() const;
-
- bool is_optimized() const { return _is_optimized; }
+ CompiledICData* data() const;
// State
- bool is_clean() const;
+ bool is_clean() const;
+ bool is_monomorphic() const;
bool is_megamorphic() const;
- bool is_call_to_compiled() const;
- bool is_call_to_interpreted() const;
-
- bool is_icholder_call() const;
- address end_of_call() const { return _call->return_address(); }
+ address end_of_call() const { return _call->return_address(); }
- // MT-safe patching of inline caches. Note: Only safe to call is_xxx when holding the CompiledIC_ock
+ // MT-safe patching of inline caches. Note: Only safe to call is_xxx when holding the CompiledICLocker
// so you are guaranteed that no patching takes place. The same goes for verify.
- //
- // Note: We do not provide any direct access to the stub code, to prevent parts of the code
- // to manipulate the inline cache in MT-unsafe ways.
- //
- // They all takes a TRAP argument, since they can cause a GC if the inline-cache buffer is full.
- //
- bool set_to_clean(bool in_use = true);
- bool set_to_monomorphic(CompiledICInfo& info);
- void clear_ic_stub();
-
- // Returns true if successful and false otherwise. The call can fail if memory
- // allocation in the code cache fails, or ic stub refill is required.
- bool set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, bool& needs_ic_stub_refill, TRAPS);
-
- static void compute_monomorphic_entry(const methodHandle& method, Klass* receiver_klass,
- bool is_optimized, bool static_bound, bool caller_is_nmethod,
- CompiledICInfo& info, TRAPS);
+ void set_to_clean();
+ void update(CallInfo* call_info, Klass* receiver_klass);
+
+ // GC support
+ void clean_metadata();
+ void metadata_do(MetadataClosure* cl);
// Location
address instruction_address() const { return _call->instruction_address(); }
+ address destination() const { return _call->destination(); }
// Misc
void print() PRODUCT_RETURN;
- void print_compiled_ic() PRODUCT_RETURN;
void verify() PRODUCT_RETURN;
};
-inline CompiledIC* CompiledIC_before(CompiledMethod* nm, address return_addr) {
- CompiledIC* c_ic = new CompiledIC(nm, nativeCall_before(return_addr));
- c_ic->verify();
- return c_ic;
-}
-
-inline CompiledIC* CompiledIC_at(CompiledMethod* nm, address call_site) {
- CompiledIC* c_ic = new CompiledIC(nm, nativeCall_at(call_site));
- c_ic->verify();
- return c_ic;
-}
-
-inline CompiledIC* CompiledIC_at(Relocation* call_site) {
- assert(call_site->type() == relocInfo::virtual_call_type ||
- call_site->type() == relocInfo::opt_virtual_call_type, "wrong reloc. info");
- CompiledIC* c_ic = new CompiledIC(call_site->code(), nativeCall_at(call_site->addr()));
- c_ic->verify();
- return c_ic;
-}
-
-inline CompiledIC* CompiledIC_at(RelocIterator* reloc_iter) {
- assert(reloc_iter->type() == relocInfo::virtual_call_type ||
- reloc_iter->type() == relocInfo::opt_virtual_call_type, "wrong reloc. info");
- CompiledIC* c_ic = new CompiledIC(reloc_iter);
- c_ic->verify();
- return c_ic;
-}
+CompiledIC* CompiledIC_before(CompiledMethod* nm, address return_addr);
+CompiledIC* CompiledIC_at(CompiledMethod* nm, address call_site);
+CompiledIC* CompiledIC_at(Relocation* call_site);
+CompiledIC* CompiledIC_at(RelocIterator* reloc_iter);
//-----------------------------------------------------------------------------
-// The CompiledStaticCall represents a call to a static method in the compiled
-//
-// Transition diagram of a static call site is somewhat simpler than for an inlined cache:
+// The CompiledDirectCall represents a call to a method in the compiled code
//
//
// -----<----- Clean ----->-----
@@ -321,63 +166,7 @@ inline CompiledIC* CompiledIC_at(RelocIterator* reloc_iter) {
//
//
-class StaticCallInfo {
- private:
- address _entry; // Entrypoint
- methodHandle _callee; // Callee (used when calling interpreter)
- bool _to_interpreter; // call to interpreted method (otherwise compiled)
-
- friend class CompiledStaticCall;
- friend class CompiledDirectStaticCall;
- friend class CompiledPltStaticCall;
- public:
- address entry() const { return _entry; }
- methodHandle callee() const { return _callee; }
-};
-
-class CompiledStaticCall : public ResourceObj {
- public:
- // Code
-
- // Returns null if CodeBuffer::expand fails
- static address emit_to_interp_stub(CodeBuffer &cbuf, address mark = nullptr);
- static int to_interp_stub_size();
- static int to_trampoline_stub_size();
- static int reloc_to_interp_stub();
-
- // Compute entry point given a method
- static void compute_entry(const methodHandle& m, bool caller_is_nmethod, StaticCallInfo& info);
- void compute_entry_for_continuation_entry(const methodHandle& m, StaticCallInfo& info);
-
-public:
- // Clean static call (will force resolving on next use)
- virtual address destination() const = 0;
-
- // Clean static call (will force resolving on next use)
- bool set_to_clean(bool in_use = true);
-
- // Set state. The entry must be the same, as computed by compute_entry.
- // Computation and setting is split up, since the actions are separate during
- // a OptoRuntime::resolve_xxx.
- void set(const StaticCallInfo& info);
-
- // State
- bool is_clean() const;
- bool is_call_to_compiled() const;
- virtual bool is_call_to_interpreted() const = 0;
-
- virtual address instruction_address() const = 0;
- virtual address end_of_call() const = 0;
-protected:
- virtual address resolve_call_stub() const = 0;
- virtual void set_destination_mt_safe(address dest) = 0;
- virtual void set_to_interpreted(const methodHandle& callee, address entry) = 0;
- virtual const char* name() const = 0;
-
- void set_to_compiled(address entry);
-};
-
-class CompiledDirectStaticCall : public CompiledStaticCall {
+class CompiledDirectCall : public ResourceObj {
private:
friend class CompiledIC;
friend class DirectNativeCallWrapper;
@@ -392,22 +181,28 @@ class CompiledDirectStaticCall : public CompiledStaticCall {
NativeCall* _call;
- CompiledDirectStaticCall(NativeCall* call) : _call(call) {}
+ CompiledDirectCall(NativeCall* call) : _call(call) {}
public:
- static inline CompiledDirectStaticCall* before(address return_addr) {
- CompiledDirectStaticCall* st = new CompiledDirectStaticCall(nativeCall_before(return_addr));
+ // Returns null if CodeBuffer::expand fails
+ static address emit_to_interp_stub(CodeBuffer &cbuf, address mark = nullptr);
+ static int to_interp_stub_size();
+ static int to_trampoline_stub_size();
+ static int reloc_to_interp_stub();
+
+ static inline CompiledDirectCall* before(address return_addr) {
+ CompiledDirectCall* st = new CompiledDirectCall(nativeCall_before(return_addr));
st->verify();
return st;
}
- static inline CompiledDirectStaticCall* at(address native_call) {
- CompiledDirectStaticCall* st = new CompiledDirectStaticCall(nativeCall_at(native_call));
+ static inline CompiledDirectCall* at(address native_call) {
+ CompiledDirectCall* st = new CompiledDirectCall(nativeCall_at(native_call));
st->verify();
return st;
}
- static inline CompiledDirectStaticCall* at(Relocation* call_site) {
+ static inline CompiledDirectCall* at(Relocation* call_site) {
return at(call_site->addr());
}
@@ -415,8 +210,15 @@ class CompiledDirectStaticCall : public CompiledStaticCall {
address destination() const { return _call->destination(); }
address end_of_call() const { return _call->return_address(); }
+ // Clean static call (will force resolving on next use)
+ void set_to_clean();
+
+ void set(const methodHandle& callee_method);
+
// State
- virtual bool is_call_to_interpreted() const;
+ bool is_clean() const;
+ bool is_call_to_interpreted() const;
+ bool is_call_to_compiled() const;
// Stub support
static address find_stub_for(address instruction);
@@ -426,10 +228,6 @@ class CompiledDirectStaticCall : public CompiledStaticCall {
// Misc.
void print() PRODUCT_RETURN;
void verify() PRODUCT_RETURN;
-
- protected:
- virtual address resolve_call_stub() const;
- virtual const char* name() const { return "CompiledDirectStaticCall"; }
};
#endif // SHARE_CODE_COMPILEDIC_HPP
diff --git a/src/hotspot/share/code/compiledMethod.cpp b/src/hotspot/share/code/compiledMethod.cpp
index a26d4a98aba9c..6553d6f79344f 100644
--- a/src/hotspot/share/code/compiledMethod.cpp
+++ b/src/hotspot/share/code/compiledMethod.cpp
@@ -28,7 +28,6 @@
#include "code/exceptionHandlerTable.hpp"
#include "code/scopeDesc.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetNMethod.hpp"
#include "gc/shared/gcBehaviours.hpp"
@@ -36,7 +35,6 @@
#include "logging/log.hpp"
#include "logging/logTag.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/compiledICHolder.inline.hpp"
#include "oops/klass.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/method.inline.hpp"
@@ -335,28 +333,6 @@ address CompiledMethod::oops_reloc_begin() const {
return low_boundary;
}
-int CompiledMethod::verify_icholder_relocations() {
- ResourceMark rm;
- int count = 0;
-
- RelocIterator iter(this);
- while(iter.next()) {
- if (iter.type() == relocInfo::virtual_call_type) {
- if (CompiledIC::is_icholder_call_site(iter.virtual_call_reloc(), this)) {
- CompiledIC *ic = CompiledIC_at(&iter);
- if (TraceCompiledIC) {
- tty->print("noticed icholder " INTPTR_FORMAT " ", p2i(ic->cached_icholder()));
- ic->print();
- }
- assert(ic->cached_icholder() != nullptr, "must be non-nullptr");
- count++;
- }
- }
- }
-
- return count;
-}
-
// Method that knows how to preserve outgoing arguments at call. This method must be
// called with a frame corresponding to a Java invoke
void CompiledMethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) {
@@ -431,20 +407,6 @@ void CompiledMethod::clear_inline_caches() {
}
}
-// Clear IC callsites, releasing ICStubs of all compiled ICs
-// as well as any associated CompiledICHolders.
-void CompiledMethod::clear_ic_callsites() {
- assert(CompiledICLocker::is_safe(this), "mt unsafe call");
- ResourceMark rm;
- RelocIterator iter(this);
- while(iter.next()) {
- if (iter.type() == relocInfo::virtual_call_type) {
- CompiledIC* ic = CompiledIC_at(&iter);
- ic->set_to_clean(false);
- }
- }
-}
-
#ifdef ASSERT
// Check class_loader is alive for this bit of metadata.
class CheckClass : public MetadataClosure {
@@ -466,70 +428,22 @@ class CheckClass : public MetadataClosure {
#endif // ASSERT
-bool CompiledMethod::clean_ic_if_metadata_is_dead(CompiledIC *ic) {
- if (ic->is_clean()) {
- return true;
- }
- if (ic->is_icholder_call()) {
- // The only exception is compiledICHolder metadata which may
- // yet be marked below. (We check this further below).
- CompiledICHolder* cichk_metdata = ic->cached_icholder();
-
- if (cichk_metdata->is_loader_alive()) {
- return true;
- }
- } else {
- Metadata* ic_metdata = ic->cached_metadata();
- if (ic_metdata != nullptr) {
- if (ic_metdata->is_klass()) {
- if (((Klass*)ic_metdata)->is_loader_alive()) {
- return true;
- }
- } else if (ic_metdata->is_method()) {
- Method* method = (Method*)ic_metdata;
- assert(!method->is_old(), "old method should have been cleaned");
- if (method->method_holder()->is_loader_alive()) {
- return true;
- }
- } else {
- ShouldNotReachHere();
- }
- } else {
- // This inline cache is a megamorphic vtable call. Those ICs never hold
- // any Metadata and should therefore never be cleaned by this function.
- return true;
- }
- }
-
- return ic->set_to_clean();
+static void clean_ic_if_metadata_is_dead(CompiledIC *ic) {
+ ic->clean_metadata();
}
// Clean references to unloaded nmethods at addr from this one, which is not unloaded.
-template
-static bool clean_if_nmethod_is_unloaded(CompiledICorStaticCall *ic, address addr, CompiledMethod* from,
+template
+static void clean_if_nmethod_is_unloaded(CallsiteT* callsite, CompiledMethod* from,
bool clean_all) {
- CodeBlob *cb = CodeCache::find_blob(addr);
- CompiledMethod* nm = (cb != nullptr) ? cb->as_compiled_method_or_null() : nullptr;
- if (nm != nullptr) {
- // Clean inline caches pointing to bad nmethods
- if (clean_all || !nm->is_in_use() || nm->is_unloading() || (nm->method()->code() != nm)) {
- if (!ic->set_to_clean(!from->is_unloading())) {
- return false;
- }
- assert(ic->is_clean(), "nmethod " PTR_FORMAT "not clean %s", p2i(from), from->method()->name_and_sig_as_C_string());
- }
+ CodeBlob* cb = CodeCache::find_blob(callsite->destination());
+ if (!cb->is_compiled()) {
+ return;
+ }
+ CompiledMethod* cm = cb->as_compiled_method();
+ if (clean_all || !cm->is_in_use() || cm->is_unloading() || cm->method()->code() != cm) {
+ callsite->set_to_clean();
}
- return true;
-}
-
-static bool clean_if_nmethod_is_unloaded(CompiledIC *ic, CompiledMethod* from,
- bool clean_all) {
- return clean_if_nmethod_is_unloaded(ic, ic->ic_destination(), from, clean_all);
-}
-
-static bool clean_if_nmethod_is_unloaded(CompiledStaticCall *csc, CompiledMethod* from,
- bool clean_all) {
- return clean_if_nmethod_is_unloaded(csc, csc->destination(), from, clean_all);
}
// Cleans caches in nmethods that point to either classes that are unloaded
@@ -539,7 +453,7 @@ static bool clean_if_nmethod_is_unloaded(CompiledStaticCall *csc, CompiledMethod
// nmethods are unloaded. Return postponed=true in the parallel case for
// inline caches found that point to nmethods that are not yet visited during
// the do_unloading walk.
-bool CompiledMethod::unload_nmethod_caches(bool unloading_occurred) {
+void CompiledMethod::unload_nmethod_caches(bool unloading_occurred) {
ResourceMark rm;
// Exception cache only needs to be called if unloading occurred
@@ -547,16 +461,13 @@ bool CompiledMethod::unload_nmethod_caches(bool unloading_occurred) {
clean_exception_cache();
}
- if (!cleanup_inline_caches_impl(unloading_occurred, false)) {
- return false;
- }
+ cleanup_inline_caches_impl(unloading_occurred, false);
#ifdef ASSERT
// Check that the metadata embedded in the nmethod is alive
CheckClass check_class;
metadata_do(&check_class);
#endif
- return true;
}
void CompiledMethod::run_nmethod_entry_barrier() {
@@ -578,8 +489,7 @@ void CompiledMethod::run_nmethod_entry_barrier() {
void CompiledMethod::cleanup_inline_caches_whitebox() {
assert_locked_or_safepoint(CodeCache_lock);
CompiledICLocker ic_locker(this);
- guarantee(cleanup_inline_caches_impl(false /* unloading_occurred */, true /* clean_all */),
- "Inline cache cleaning in a safepoint can't fail");
+ cleanup_inline_caches_impl(false /* unloading_occurred */, true /* clean_all */);
}
address* CompiledMethod::orig_pc_addr(const frame* fr) {
@@ -587,7 +497,7 @@ address* CompiledMethod::orig_pc_addr(const frame* fr) {
}
// Called to clean up after class unloading for live nmethods
-bool CompiledMethod::cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all) {
+void CompiledMethod::cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all) {
assert(CompiledICLocker::is_safe(this), "mt unsafe call");
ResourceMark rm;
@@ -602,26 +512,15 @@ bool CompiledMethod::cleanup_inline_caches_impl(bool unloading_occurred, bool cl
if (unloading_occurred) {
// If class unloading occurred we first clear ICs where the cached metadata
// is referring to an unloaded klass or method.
- if (!clean_ic_if_metadata_is_dead(CompiledIC_at(&iter))) {
- return false;
- }
+ clean_ic_if_metadata_is_dead(CompiledIC_at(&iter));
}
- if (!clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this, clean_all)) {
- return false;
- }
+ clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this, clean_all);
break;
case relocInfo::opt_virtual_call_type:
- if (!clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this, clean_all)) {
- return false;
- }
- break;
-
case relocInfo::static_call_type:
- if (!clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), this, clean_all)) {
- return false;
- }
+ clean_if_nmethod_is_unloaded(CompiledDirectCall::at(iter.reloc()), this, clean_all);
break;
case relocInfo::static_stub_type: {
@@ -672,8 +571,6 @@ bool CompiledMethod::cleanup_inline_caches_impl(bool unloading_occurred, bool cl
break;
}
}
-
- return true;
}
address CompiledMethod::continuation_for_implicit_exception(address pc, bool for_div0_check) {
diff --git a/src/hotspot/share/code/compiledMethod.hpp b/src/hotspot/share/code/compiledMethod.hpp
index afe0905266259..42d68bda55472 100644
--- a/src/hotspot/share/code/compiledMethod.hpp
+++ b/src/hotspot/share/code/compiledMethod.hpp
@@ -35,7 +35,7 @@ class ExceptionHandlerTable;
class ImplicitExceptionTable;
class AbstractCompiler;
class xmlStream;
-class CompiledStaticCall;
+class CompiledDirectCall;
class NativeCallWrapper;
class ScopeDesc;
class CompiledIC;
@@ -364,7 +364,7 @@ class CompiledMethod : public CodeBlob {
// Inline cache support for class unloading and nmethod unloading
private:
- bool cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all);
+ void cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all);
address continuation_for_implicit_exception(address pc, bool for_div0_check);
@@ -373,13 +373,10 @@ class CompiledMethod : public CodeBlob {
void cleanup_inline_caches_whitebox();
virtual void clear_inline_caches();
- void clear_ic_callsites();
// Execute nmethod barrier code, as if entering through nmethod call.
void run_nmethod_entry_barrier();
- // Verify and count cached icholder relocations.
- int verify_icholder_relocations();
void verify_oop_relocations();
bool has_evol_metadata();
@@ -389,14 +386,8 @@ class CompiledMethod : public CodeBlob {
// corresponds to the given method as well.
virtual bool is_dependent_on_method(Method* dependee) = 0;
- virtual NativeCallWrapper* call_wrapper_at(address call) const = 0;
- virtual NativeCallWrapper* call_wrapper_before(address return_pc) const = 0;
virtual address call_instruction_address(address pc) const = 0;
- virtual CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) const = 0;
- virtual CompiledStaticCall* compiledStaticCall_at(address addr) const = 0;
- virtual CompiledStaticCall* compiledStaticCall_before(address addr) const = 0;
-
Method* attached_method(address call_pc);
Method* attached_method_before_pc(address pc);
@@ -406,16 +397,13 @@ class CompiledMethod : public CodeBlob {
protected:
address oops_reloc_begin() const;
- private:
- bool static clean_ic_if_metadata_is_dead(CompiledIC *ic);
-
public:
// GC unloading support
// Cleans unloaded klasses and unloaded nmethods in inline caches
virtual bool is_unloading() = 0;
- bool unload_nmethod_caches(bool class_unloading_occurred);
+ void unload_nmethod_caches(bool class_unloading_occurred);
virtual void do_unloading(bool unloading_occurred) = 0;
private:
diff --git a/src/hotspot/share/code/icBuffer.cpp b/src/hotspot/share/code/icBuffer.cpp
deleted file mode 100644
index ec489eff9c882..0000000000000
--- a/src/hotspot/share/code/icBuffer.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 "code/codeCache.hpp"
-#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
-#include "code/nmethod.hpp"
-#include "code/scopeDesc.hpp"
-#include "gc/shared/collectedHeap.inline.hpp"
-#include "interpreter/interpreter.hpp"
-#include "interpreter/linkResolver.hpp"
-#include "memory/resourceArea.hpp"
-#include "oops/method.hpp"
-#include "oops/oop.inline.hpp"
-#include "runtime/atomic.hpp"
-#include "runtime/handles.inline.hpp"
-#include "runtime/javaThread.hpp"
-#include "runtime/mutexLocker.hpp"
-#include "runtime/stubRoutines.hpp"
-#include "runtime/vmOperations.hpp"
-
-DEF_STUB_INTERFACE(ICStub);
-
-StubQueue* InlineCacheBuffer::_buffer = nullptr;
-
-CompiledICHolder* volatile InlineCacheBuffer::_pending_released = nullptr;
-volatile int InlineCacheBuffer::_pending_count = 0;
-
-#ifdef ASSERT
-ICRefillVerifier::ICRefillVerifier()
- : _refill_requested(false),
- _refill_remembered(false)
-{
- Thread* thread = Thread::current();
- assert(thread->missed_ic_stub_refill_verifier() == nullptr, "nesting not supported");
- thread->set_missed_ic_stub_refill_verifier(this);
-}
-
-ICRefillVerifier::~ICRefillVerifier() {
- assert(!_refill_requested || _refill_remembered,
- "Forgot to refill IC stubs after failed IC transition");
- Thread::current()->set_missed_ic_stub_refill_verifier(nullptr);
-}
-
-ICRefillVerifierMark::ICRefillVerifierMark(ICRefillVerifier* verifier) {
- Thread* thread = Thread::current();
- assert(thread->missed_ic_stub_refill_verifier() == nullptr, "nesting not supported");
- thread->set_missed_ic_stub_refill_verifier(verifier);
-}
-
-ICRefillVerifierMark::~ICRefillVerifierMark() {
- Thread::current()->set_missed_ic_stub_refill_verifier(nullptr);
-}
-
-static ICRefillVerifier* current_ic_refill_verifier() {
- Thread* current = Thread::current();
- ICRefillVerifier* verifier = current->missed_ic_stub_refill_verifier();
- assert(verifier != nullptr, "need a verifier for safety");
- return verifier;
-}
-#endif
-
-void ICStub::finalize() {
- if (!is_empty()) {
- ResourceMark rm;
- CompiledIC *ic = CompiledIC_at(CodeCache::find_compiled(ic_site()), ic_site());
- assert(CodeCache::find_compiled(ic->instruction_address()) != nullptr, "inline cache in non-compiled?");
-
- assert(this == ICStub::from_destination_address(ic->stub_address()), "wrong owner of ic buffer");
- ic->set_ic_destination_and_value(destination(), cached_value());
- }
-}
-
-
-address ICStub::destination() const {
- return InlineCacheBuffer::ic_buffer_entry_point(code_begin());
-}
-
-void* ICStub::cached_value() const {
- return InlineCacheBuffer::ic_buffer_cached_value(code_begin());
-}
-
-
-void ICStub::set_stub(CompiledIC *ic, void* cached_val, address dest_addr) {
- // We cannot store a pointer to the 'ic' object, since it is resource allocated. Instead we
- // store the location of the inline cache. Then we have enough information recreate the CompiledIC
- // object when we need to remove the stub.
- _ic_site = ic->instruction_address();
-
- // Assemble new stub
- InlineCacheBuffer::assemble_ic_buffer_code(code_begin(), cached_val, dest_addr);
- assert(destination() == dest_addr, "can recover destination");
- assert(cached_value() == cached_val, "can recover destination");
-}
-
-
-void ICStub::clear() {
- if (CompiledIC::is_icholder_entry(destination())) {
- InlineCacheBuffer::queue_for_release((CompiledICHolder*)cached_value());
- }
- _ic_site = nullptr;
-}
-
-
-#ifndef PRODUCT
-// anybody calling to this stub will trap
-
-void ICStub::verify() {
-}
-
-void ICStub::print() {
- tty->print_cr("ICStub: site: " INTPTR_FORMAT, p2i(_ic_site));
-}
-#endif
-
-//-----------------------------------------------------------------------------------------------
-// Implementation of InlineCacheBuffer
-
-
-void InlineCacheBuffer::initialize() {
- if (_buffer != nullptr) return; // already initialized
- _buffer = new StubQueue(new ICStubInterface, checked_cast(InlineCacheBufferSize), InlineCacheBuffer_lock, "InlineCacheBuffer");
- assert (_buffer != nullptr, "cannot allocate InlineCacheBuffer");
-}
-
-
-void InlineCacheBuffer::refill_ic_stubs() {
-#ifdef ASSERT
- ICRefillVerifier* verifier = current_ic_refill_verifier();
- verifier->request_remembered();
-#endif
- // we ran out of inline cache buffer space; must enter safepoint.
- // We do this by forcing a safepoint
- VM_ICBufferFull ibf;
- VMThread::execute(&ibf);
-}
-
-bool InlineCacheBuffer::needs_update_inline_caches() {
- // Stub removal
- if (buffer()->number_of_stubs() > 0) {
- return true;
- }
-
- // Release pending CompiledICHolder
- if (pending_icholder_count() > 0) {
- return true;
- }
-
- return false;
-}
-
-void InlineCacheBuffer::update_inline_caches() {
- if (buffer()->number_of_stubs() > 0) {
- if (TraceICBuffer) {
- tty->print_cr("[updating inline caches with %d stubs]", buffer()->number_of_stubs());
- }
- buffer()->remove_all();
- }
- release_pending_icholders();
-}
-
-
-bool InlineCacheBuffer::contains(address instruction_address) {
- return buffer()->contains(instruction_address);
-}
-
-
-bool InlineCacheBuffer::is_empty() {
- return buffer()->number_of_stubs() == 0;
-}
-
-
-void InlineCacheBuffer_init() {
- InlineCacheBuffer::initialize();
-}
-
-bool InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_value, address entry) {
- assert(!SafepointSynchronize::is_at_safepoint(), "should not be called during a safepoint");
- assert(CompiledICLocker::is_safe(ic->instruction_address()), "mt unsafe call");
- if (TraceICBuffer) {
- tty->print_cr(" create transition stub for " INTPTR_FORMAT " destination " INTPTR_FORMAT " cached value " INTPTR_FORMAT,
- p2i(ic->instruction_address()), p2i(entry), p2i(cached_value));
- }
-
- // allocate and initialize new "out-of-line" inline-cache
- ICStub* ic_stub = (ICStub*) buffer()->request_committed(ic_stub_code_size());
- if (ic_stub == nullptr) {
-#ifdef ASSERT
- ICRefillVerifier* verifier = current_ic_refill_verifier();
- verifier->request_refill();
-#endif
- return false;
- }
-
-#ifdef ASSERT
- {
- ICStub* rev_stub = ICStub::from_destination_address(ic_stub->code_begin());
- assert(ic_stub == rev_stub,
- "ICStub mapping is reversible: stub=" PTR_FORMAT ", code=" PTR_FORMAT ", rev_stub=" PTR_FORMAT,
- p2i(ic_stub), p2i(ic_stub->code_begin()), p2i(rev_stub));
- }
-#endif
-
- // If an transition stub is already associate with the inline cache, then we remove the association.
- if (ic->is_in_transition_state()) {
- ICStub* old_stub = ICStub::from_destination_address(ic->stub_address());
- old_stub->clear();
- }
-
- ic_stub->set_stub(ic, cached_value, entry);
-
- // Update inline cache in nmethod to point to new "out-of-line" allocated inline cache
- ic->set_ic_destination(ic_stub);
- return true;
-}
-
-
-address InlineCacheBuffer::ic_destination_for(CompiledIC *ic) {
- ICStub* stub = ICStub::from_destination_address(ic->stub_address());
- return stub->destination();
-}
-
-
-void* InlineCacheBuffer::cached_value_for(CompiledIC *ic) {
- ICStub* stub = ICStub::from_destination_address(ic->stub_address());
- return stub->cached_value();
-}
-
-
-// Free CompiledICHolder*s that are no longer in use
-void InlineCacheBuffer::release_pending_icholders() {
- assert(SafepointSynchronize::is_at_safepoint(), "should only be called during a safepoint");
- CompiledICHolder* holder = Atomic::load(&_pending_released);
- _pending_released = nullptr;
- int count = 0;
- while (holder != nullptr) {
- CompiledICHolder* next = holder->next();
- delete holder;
- holder = next;
- count++;
- }
- assert(pending_icholder_count() == count, "wrong count");
- Atomic::store(&_pending_count, 0);
-}
-
-// Enqueue this icholder for release during the next safepoint. It's
-// not safe to free them until then since they might be visible to
-// another thread.
-void InlineCacheBuffer::queue_for_release(CompiledICHolder* icholder) {
- assert(icholder->next() == nullptr, "multiple enqueue?");
-
- CompiledICHolder* old = Atomic::load(&_pending_released);
- for (;;) {
- icholder->set_next(old);
- // The only reader runs at a safepoint serially so there is no need for a more strict atomic.
- CompiledICHolder* cur = Atomic::cmpxchg(&_pending_released, old, icholder, memory_order_relaxed);
- if (cur == old) {
- break;
- }
- old = cur;
- }
- Atomic::inc(&_pending_count, memory_order_relaxed);
-
- if (TraceICBuffer) {
- tty->print_cr("enqueueing icholder " INTPTR_FORMAT " to be freed", p2i(icholder));
- }
-}
-
-int InlineCacheBuffer::pending_icholder_count() {
- return Atomic::load(&_pending_count);
-}
diff --git a/src/hotspot/share/code/icBuffer.hpp b/src/hotspot/share/code/icBuffer.hpp
deleted file mode 100644
index f67080e6b5852..0000000000000
--- a/src/hotspot/share/code/icBuffer.hpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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.
- *
- */
-
-#ifndef SHARE_CODE_ICBUFFER_HPP
-#define SHARE_CODE_ICBUFFER_HPP
-
-#include "asm/codeBuffer.hpp"
-#include "code/stubs.hpp"
-#include "interpreter/bytecodes.hpp"
-#include "memory/allocation.hpp"
-#include "runtime/safepointVerifiers.hpp"
-#include "utilities/align.hpp"
-#include "utilities/debug.hpp"
-#include "utilities/macros.hpp"
-
-class CompiledIC;
-class CompiledICHolder;
-
-//
-// For CompiledIC's:
-//
-// In cases where we do not have MT-safe state transformation,
-// we go to a transition state, using ICStubs. At a safepoint,
-// the inline caches are transferred from the transitional code:
-//
-// instruction_address --> 01 set xxx_oop, Ginline_cache_klass
-// 23 jump_to Gtemp, yyyy
-// 4 nop
-
-class ICStub: public Stub {
- private:
- int _size; // total size of the stub incl. code
- address _ic_site; // points at call instruction of owning ic-buffer
- /* stub code follows here */
- protected:
- friend class ICStubInterface;
- // This will be called only by ICStubInterface
- void initialize(int size) { _size = size; _ic_site = nullptr; }
- void finalize(); // called when a method is removed
-
- // General info
- int size() const { return _size; }
-
- // To be cautious, we want to make sure that each ICStub is in a separate instruction
- // cache line. This would allow for piggybacking on instruction cache coherency on
- // some architectures to order the updates to ICStub and setting the destination to
- // the ICStub. Note that cache line size might be larger than CodeEntryAlignment
- // that is normal alignment for CodeBlobs.
- static int alignment() { return DEFAULT_CACHE_LINE_SIZE; }
-
- // Aligning the code section is normally done for performance reasons, which is not
- // required for ICStubs, as these stubs are transitional. Setting code alignment
- // to CodeEntryAlignment would waste a lot of memory in ICBuffer. Aligning to
- // word size should be enough. This also offsets the costs of aligning the entire
- // ICStub to cache line (see above), as smaller code alignment would allow ICStub
- // to fit a _single_ cache line.
- static int code_alignment() { return HeapWordSize; }
-
- public:
- // Creation
- void set_stub(CompiledIC *ic, void* cached_value, address dest_addr);
-
- // Code info
- address code_begin() const { return align_up((address)this + sizeof(ICStub), code_alignment()); }
- address code_end() const { return (address)this + size(); }
-
- // Call site info
- address ic_site() const { return _ic_site; }
- void clear();
- bool is_empty() const { return _ic_site == nullptr; }
-
- // stub info
- address destination() const; // destination of jump instruction
- void* cached_value() const; // cached_value for stub
-
- // Debugging
- void verify() PRODUCT_RETURN;
- void print() PRODUCT_RETURN;
-
- // Creation
- static inline ICStub* from_destination_address(address destination_address) {
- ICStub* stub = (ICStub*) align_down(destination_address - sizeof(ICStub), alignment());
-#ifdef ASSERT
- stub->verify();
-#endif
- return stub;
- }
-};
-
-#ifdef ASSERT
-// The ICRefillVerifier class is a stack allocated RAII object used to
-// detect if a failed IC transition that required IC stub refilling has
-// been accidentally missed. It is up to the caller to in that case
-// refill IC stubs.
-class ICRefillVerifier: StackObj {
- bool _refill_requested;
- bool _refill_remembered;
-
- public:
- ICRefillVerifier();
- ~ICRefillVerifier();
-
- void request_refill() { _refill_requested = true; }
- void request_remembered() { _refill_remembered = true; }
-};
-
-// The ICRefillVerifierMark is used to set the thread's current
-// ICRefillVerifier to a provided one. This is useful in particular
-// when transitioning IC stubs in parallel and refilling from the
-// master thread invoking the IC stub transitioning code.
-class ICRefillVerifierMark: StackObj {
- public:
- ICRefillVerifierMark(ICRefillVerifier* verifier);
- ~ICRefillVerifierMark();
-};
-#else
-class ICRefillVerifier: StackObj {
- public:
- ICRefillVerifier() {}
-};
-class ICRefillVerifierMark: StackObj {
- public:
- ICRefillVerifierMark(ICRefillVerifier* verifier) {}
-};
-#endif
-
-class InlineCacheBuffer: public AllStatic {
- private:
- // friends
- friend class ICStub;
-
- static int ic_stub_code_size();
-
- static StubQueue* _buffer;
-
- static CompiledICHolder* volatile _pending_released;
- static volatile int _pending_count;
-
- static StubQueue* buffer() { return _buffer; }
-
- // Machine-dependent implementation of ICBuffer
- static void assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point);
- static address ic_buffer_entry_point (address code_begin);
- static void* ic_buffer_cached_value (address code_begin);
-
- public:
-
- // Initialization; must be called before first usage
- static void initialize();
-
- // Access
- static bool contains(address instruction_address);
-
- // removes the ICStubs after backpatching
- static bool needs_update_inline_caches();
- static void update_inline_caches();
- static void refill_ic_stubs();
-
- // for debugging
- static bool is_empty();
-
- static void release_pending_icholders();
- static void queue_for_release(CompiledICHolder* icholder);
- static int pending_icholder_count();
-
- // New interface
- static bool create_transition_stub(CompiledIC *ic, void* cached_value, address entry);
- static address ic_destination_for(CompiledIC *ic);
- static void* cached_value_for(CompiledIC *ic);
-};
-
-#endif // SHARE_CODE_ICBUFFER_HPP
diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp
index cc2dcf21deebf..2755df3251396 100644
--- a/src/hotspot/share/code/nmethod.cpp
+++ b/src/hotspot/share/code/nmethod.cpp
@@ -640,6 +640,7 @@ nmethod::nmethod(
ByteSize basic_lock_sp_offset,
OopMapSet* oop_maps )
: CompiledMethod(method, "native nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false, true),
+ _compiled_ic_data(nullptr),
_is_unlinked(false),
_native_receiver_sp_offset(basic_lock_owner_sp_offset),
_native_basic_lock_sp_offset(basic_lock_sp_offset),
@@ -697,12 +698,12 @@ nmethod::nmethod(
clear_unloading_state();
+ finalize_relocations();
+
Universe::heap()->register_nmethod(this);
debug_only(Universe::heap()->verify_nmethod(this));
CodeCache::commit(this);
-
- finalize_relocations();
}
if (PrintNativeNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
@@ -784,6 +785,7 @@ nmethod::nmethod(
#endif
)
: CompiledMethod(method, "nmethod", type, nmethod_size, sizeof(nmethod), code_buffer, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps, false, true),
+ _compiled_ic_data(nullptr),
_is_unlinked(false),
_native_receiver_sp_offset(in_ByteSize(-1)),
_native_basic_lock_sp_offset(in_ByteSize(-1)),
@@ -887,13 +889,13 @@ nmethod::nmethod(
}
#endif
+ finalize_relocations();
+
Universe::heap()->register_nmethod(this);
debug_only(Universe::heap()->verify_nmethod(this));
CodeCache::commit(this);
- finalize_relocations();
-
// Copy contents of ExceptionHandlerTable to nmethod
handler_table->copy_to(this);
nul_chk_table->copy_to(this);
@@ -1145,16 +1147,33 @@ static void install_post_call_nop_displacement(nmethod* nm, address pc) {
void nmethod::finalize_relocations() {
NoSafepointVerifier nsv;
+ GrowableArray virtual_call_data;
+
// Make sure that post call nops fill in nmethod offsets eagerly so
// we don't have to race with deoptimization
RelocIterator iter(this);
while (iter.next()) {
- if (iter.type() == relocInfo::post_call_nop_type) {
+ if (iter.type() == relocInfo::virtual_call_type) {
+ virtual_call_Relocation* r = iter.virtual_call_reloc();
+ NativeMovConstReg* value = nativeMovConstReg_at(r->cached_value());
+ virtual_call_data.append(value);
+ } else if (iter.type() == relocInfo::post_call_nop_type) {
post_call_nop_Relocation* const reloc = iter.post_call_nop_reloc();
address pc = reloc->addr();
install_post_call_nop_displacement(this, pc);
}
}
+
+ if (virtual_call_data.length() > 0) {
+ // We allocate a block of CompiledICData per nmethod so the GC can purge this faster.
+ _compiled_ic_data = new CompiledICData[virtual_call_data.length()];
+ CompiledICData* next_data = _compiled_ic_data;
+
+ for (NativeMovConstReg* value : virtual_call_data) {
+ value->set_data((intptr_t)next_data);
+ next_data++;
+ }
+ }
}
void nmethod::make_deoptimized() {
@@ -1180,8 +1199,7 @@ void nmethod::make_deoptimized() {
while (iter.next()) {
switch (iter.type()) {
- case relocInfo::virtual_call_type:
- case relocInfo::opt_virtual_call_type: {
+ case relocInfo::virtual_call_type: {
CompiledIC *ic = CompiledIC_at(&iter);
address pc = ic->end_of_call();
NativePostCallNop* nop = nativePostCallNop_at(pc);
@@ -1191,8 +1209,9 @@ void nmethod::make_deoptimized() {
assert(NativeDeoptInstruction::is_deopt_at(pc), "check");
break;
}
- case relocInfo::static_call_type: {
- CompiledStaticCall *csc = compiledStaticCall_at(iter.reloc());
+ case relocInfo::static_call_type:
+ case relocInfo::opt_virtual_call_type: {
+ CompiledDirectCall *csc = CompiledDirectCall::at(iter.reloc());
address pc = csc->end_of_call();
NativePostCallNop* nop = nativePostCallNop_at(pc);
//tty->print_cr(" - static pc %p", pc);
@@ -1219,29 +1238,29 @@ void nmethod::verify_clean_inline_caches() {
RelocIterator iter(this, oops_reloc_begin());
while(iter.next()) {
switch(iter.type()) {
- case relocInfo::virtual_call_type:
- case relocInfo::opt_virtual_call_type: {
+ case relocInfo::virtual_call_type: {
CompiledIC *ic = CompiledIC_at(&iter);
- CodeBlob *cb = CodeCache::find_blob(ic->ic_destination());
+ CodeBlob *cb = CodeCache::find_blob(ic->destination());
assert(cb != nullptr, "destination not in CodeBlob?");
nmethod* nm = cb->as_nmethod_or_null();
- if( nm != nullptr ) {
+ if (nm != nullptr) {
// Verify that inline caches pointing to bad nmethods are clean
- if (!nm->is_in_use() || (nm->method()->code() != nm)) {
+ if (!nm->is_in_use() || nm->is_unloading()) {
assert(ic->is_clean(), "IC should be clean");
}
}
break;
}
- case relocInfo::static_call_type: {
- CompiledStaticCall *csc = compiledStaticCall_at(iter.reloc());
- CodeBlob *cb = CodeCache::find_blob(csc->destination());
+ case relocInfo::static_call_type:
+ case relocInfo::opt_virtual_call_type: {
+ CompiledDirectCall *cdc = CompiledDirectCall::at(iter.reloc());
+ CodeBlob *cb = CodeCache::find_blob(cdc->destination());
assert(cb != nullptr, "destination not in CodeBlob?");
nmethod* nm = cb->as_nmethod_or_null();
- if( nm != nullptr ) {
+ if (nm != nullptr) {
// Verify that inline caches pointing to bad nmethods are clean
- if (!nm->is_in_use() || (nm->method()->code() != nm)) {
- assert(csc->is_clean(), "IC should be clean");
+ if (!nm->is_in_use() || nm->is_unloading() || nm->method()->code() != nm) {
+ assert(cdc->is_clean(), "IC should be clean");
}
}
break;
@@ -1405,9 +1424,7 @@ bool nmethod::make_not_entrant() {
// For concurrent GCs, there must be a handshake between unlink and flush
void nmethod::unlink() {
if (_is_unlinked) {
- // Already unlinked. It can be invoked twice because concurrent code cache
- // unloading might need to restart when inline cache cleaning fails due to
- // running out of ICStubs, which can only be refilled at safepoints
+ // Already unlinked.
return;
}
@@ -1418,7 +1435,6 @@ void nmethod::unlink() {
// the Method, because it is only concurrently unlinked by
// the entry barrier, which acquires the per nmethod lock.
unlink_from_method();
- clear_ic_callsites();
if (is_osr_method()) {
invalidate_osr_method();
@@ -1463,10 +1479,11 @@ void nmethod::purge(bool free_code_cache_data, bool unregister_nmethod) {
ec = next;
}
+ delete[] _compiled_ic_data;
+
if (unregister_nmethod) {
Universe::heap()->unregister_nmethod(this);
}
-
CodeCache::unregister_old_nmethod(this);
CodeBlob::purge(free_code_cache_data, unregister_nmethod);
@@ -1604,16 +1621,7 @@ void nmethod::metadata_do(MetadataClosure* f) {
// Check compiledIC holders associated with this nmethod
ResourceMark rm;
CompiledIC *ic = CompiledIC_at(&iter);
- if (ic->is_icholder_call()) {
- CompiledICHolder* cichk = ic->cached_icholder();
- f->do_metadata(cichk->holder_metadata());
- f->do_metadata(cichk->holder_klass());
- } else {
- Metadata* ic_oop = ic->cached_metadata();
- if (ic_oop != nullptr) {
- f->do_metadata(ic_oop);
- }
- }
+ ic->metadata_do(f);
}
}
}
@@ -1750,8 +1758,7 @@ void nmethod::do_unloading(bool unloading_occurred) {
if (is_unloading()) {
unlink();
} else {
- guarantee(unload_nmethod_caches(unloading_occurred),
- "Should not need transition stubs");
+ unload_nmethod_caches(unloading_occurred);
BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
if (bs_nm != nullptr) {
bs_nm->disarm(this);
@@ -2284,15 +2291,23 @@ void nmethod::verify() {
}
-void nmethod::verify_interrupt_point(address call_site) {
+void nmethod::verify_interrupt_point(address call_site, bool is_inline_cache) {
// Verify IC only when nmethod installation is finished.
if (!is_not_installed()) {
if (CompiledICLocker::is_safe(this)) {
- CompiledIC_at(this, call_site);
+ if (is_inline_cache) {
+ CompiledIC_at(this, call_site);
+ } else {
+ CompiledDirectCall::at(call_site);
+ }
} else {
CompiledICLocker ml_verify(this);
- CompiledIC_at(this, call_site);
+ if (is_inline_cache) {
+ CompiledIC_at(this, call_site);
+ } else {
+ CompiledDirectCall::at(call_site);
+ }
}
}
@@ -2316,15 +2331,15 @@ void nmethod::verify_scopes() {
address stub = nullptr;
switch (iter.type()) {
case relocInfo::virtual_call_type:
- verify_interrupt_point(iter.addr());
+ verify_interrupt_point(iter.addr(), true /* is_inline_cache */);
break;
case relocInfo::opt_virtual_call_type:
stub = iter.opt_virtual_call_reloc()->static_stub();
- verify_interrupt_point(iter.addr());
+ verify_interrupt_point(iter.addr(), false /* is_inline_cache */);
break;
case relocInfo::static_call_type:
stub = iter.static_call_reloc()->static_stub();
- //verify_interrupt_point(iter.addr());
+ verify_interrupt_point(iter.addr(), false /* is_inline_cache */);
break;
case relocInfo::runtime_call_type:
case relocInfo::runtime_call_w_cp_type: {
@@ -3239,75 +3254,6 @@ void nmethod::print_code_comment_on(outputStream* st, int column, address begin,
#endif
-class DirectNativeCallWrapper: public NativeCallWrapper {
-private:
- NativeCall* _call;
-
-public:
- DirectNativeCallWrapper(NativeCall* call) : _call(call) {}
-
- virtual address destination() const { return _call->destination(); }
- virtual address instruction_address() const { return _call->instruction_address(); }
- virtual address next_instruction_address() const { return _call->next_instruction_address(); }
- virtual address return_address() const { return _call->return_address(); }
-
- virtual address get_resolve_call_stub(bool is_optimized) const {
- if (is_optimized) {
- return SharedRuntime::get_resolve_opt_virtual_call_stub();
- }
- return SharedRuntime::get_resolve_virtual_call_stub();
- }
-
- virtual void set_destination_mt_safe(address dest) {
- _call->set_destination_mt_safe(dest);
- }
-
- virtual void set_to_interpreted(const methodHandle& method, CompiledICInfo& info) {
- CompiledDirectStaticCall* csc = CompiledDirectStaticCall::at(instruction_address());
- {
- csc->set_to_interpreted(method, info.entry());
- }
- }
-
- virtual void verify() const {
- // make sure code pattern is actually a call imm32 instruction
- _call->verify();
- _call->verify_alignment();
- }
-
- virtual void verify_resolve_call(address dest) const {
- CodeBlob* db = CodeCache::find_blob(dest);
- assert(db != nullptr && !db->is_adapter_blob(), "must use stub!");
- }
-
- virtual bool is_call_to_interpreted(address dest) const {
- CodeBlob* cb = CodeCache::find_blob(_call->instruction_address());
- return cb->contains(dest);
- }
-
- virtual bool is_safe_for_patching() const { return false; }
-
- virtual NativeInstruction* get_load_instruction(virtual_call_Relocation* r) const {
- return nativeMovConstReg_at(r->cached_value());
- }
-
- virtual void *get_data(NativeInstruction* instruction) const {
- return (void*)((NativeMovConstReg*) instruction)->data();
- }
-
- virtual void set_data(NativeInstruction* instruction, intptr_t data) {
- ((NativeMovConstReg*) instruction)->set_data(data);
- }
-};
-
-NativeCallWrapper* nmethod::call_wrapper_at(address call) const {
- return new DirectNativeCallWrapper((NativeCall*) call);
-}
-
-NativeCallWrapper* nmethod::call_wrapper_before(address return_pc) const {
- return new DirectNativeCallWrapper(nativeCall_before(return_pc));
-}
-
address nmethod::call_instruction_address(address pc) const {
if (NativeCall::is_call_before(pc)) {
NativeCall *ncall = nativeCall_before(pc);
@@ -3316,18 +3262,6 @@ address nmethod::call_instruction_address(address pc) const {
return nullptr;
}
-CompiledStaticCall* nmethod::compiledStaticCall_at(Relocation* call_site) const {
- return CompiledDirectStaticCall::at(call_site);
-}
-
-CompiledStaticCall* nmethod::compiledStaticCall_at(address call_site) const {
- return CompiledDirectStaticCall::at(call_site);
-}
-
-CompiledStaticCall* nmethod::compiledStaticCall_before(address return_addr) const {
- return CompiledDirectStaticCall::before(return_addr);
-}
-
#if defined(SUPPORT_DATA_STRUCTS)
void nmethod::print_value_on(outputStream* st) const {
st->print("nmethod");
@@ -3341,15 +3275,15 @@ void nmethod::print_calls(outputStream* st) {
RelocIterator iter(this);
while (iter.next()) {
switch (iter.type()) {
- case relocInfo::virtual_call_type:
- case relocInfo::opt_virtual_call_type: {
+ case relocInfo::virtual_call_type: {
CompiledICLocker ml_verify(this);
CompiledIC_at(&iter)->print();
break;
}
case relocInfo::static_call_type:
- st->print_cr("Static call at " INTPTR_FORMAT, p2i(iter.reloc()->addr()));
- CompiledDirectStaticCall::at(iter.reloc())->print();
+ case relocInfo::opt_virtual_call_type:
+ st->print_cr("Direct call at " INTPTR_FORMAT, p2i(iter.reloc()->addr()));
+ CompiledDirectCall::at(iter.reloc())->print();
break;
default:
break;
diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp
index 13cd2f799a76b..2993db21305ee 100644
--- a/src/hotspot/share/code/nmethod.hpp
+++ b/src/hotspot/share/code/nmethod.hpp
@@ -27,6 +27,7 @@
#include "code/compiledMethod.hpp"
+class CompiledICData;
class CompileTask;
class DepChange;
class DirectiveSet;
@@ -196,6 +197,7 @@ class nmethod : public CompiledMethod {
address _verified_entry_point; // entry point without class check
address _osr_entry_point; // entry point for on stack replacement
+ CompiledICData* _compiled_ic_data;
bool _is_unlinked;
// Shared fields for all nmethod's
@@ -604,7 +606,7 @@ class nmethod : public CompiledMethod {
// verify operations
void verify();
void verify_scopes();
- void verify_interrupt_point(address interrupt_point);
+ void verify_interrupt_point(address interrupt_point, bool is_inline_cache);
// Disassemble this nmethod with additional debug information, e.g. information about blocks.
void decode2(outputStream* st) const;
@@ -699,14 +701,8 @@ class nmethod : public CompiledMethod {
virtual void metadata_do(MetadataClosure* f);
- NativeCallWrapper* call_wrapper_at(address call) const;
- NativeCallWrapper* call_wrapper_before(address return_pc) const;
address call_instruction_address(address pc) const;
- virtual CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) const;
- virtual CompiledStaticCall* compiledStaticCall_at(address addr) const;
- virtual CompiledStaticCall* compiledStaticCall_before(address addr) const;
-
virtual void make_deoptimized();
void finalize_relocations();
};
diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp
index bfb3db72d7265..ef90875767503 100644
--- a/src/hotspot/share/code/relocInfo.cpp
+++ b/src/hotspot/share/code/relocInfo.cpp
@@ -641,12 +641,10 @@ Method* virtual_call_Relocation::method_value() {
return (Method*)m;
}
-bool virtual_call_Relocation::clear_inline_cache() {
- // No stubs for ICs
- // Clean IC
+void virtual_call_Relocation::clear_inline_cache() {
ResourceMark rm;
CompiledIC* icache = CompiledIC_at(this);
- return icache->set_to_clean();
+ icache->set_to_clean();
}
@@ -669,18 +667,10 @@ Method* opt_virtual_call_Relocation::method_value() {
return (Method*)m;
}
-template
-static bool set_to_clean_no_ic_refill(CompiledICorStaticCall* ic) {
- guarantee(ic->set_to_clean(), "Should not need transition stubs");
- return true;
-}
-
-bool opt_virtual_call_Relocation::clear_inline_cache() {
- // No stubs for ICs
- // Clean IC
+void opt_virtual_call_Relocation::clear_inline_cache() {
ResourceMark rm;
- CompiledIC* icache = CompiledIC_at(this);
- return set_to_clean_no_ic_refill(icache);
+ CompiledDirectCall* callsite = CompiledDirectCall::at(this);
+ callsite->set_to_clean();
}
address opt_virtual_call_Relocation::static_stub() {
@@ -717,10 +707,10 @@ void static_call_Relocation::unpack_data() {
_method_index = unpack_1_int();
}
-bool static_call_Relocation::clear_inline_cache() {
- // Safe call site info
- CompiledStaticCall* handler = this->code()->compiledStaticCall_at(this);
- return set_to_clean_no_ic_refill(handler);
+void static_call_Relocation::clear_inline_cache() {
+ ResourceMark rm;
+ CompiledDirectCall* callsite = CompiledDirectCall::at(this);
+ callsite->set_to_clean();
}
@@ -759,11 +749,10 @@ address trampoline_stub_Relocation::get_trampoline_for(address call, nmethod* co
return nullptr;
}
-bool static_stub_Relocation::clear_inline_cache() {
+void static_stub_Relocation::clear_inline_cache() {
// Call stub is only used when calling the interpreted code.
// It does not really need to be cleared, except that we want to clean out the methodoop.
- CompiledDirectStaticCall::set_stub_to_clean(this);
- return true;
+ CompiledDirectCall::set_stub_to_clean(this);
}
diff --git a/src/hotspot/share/code/relocInfo.hpp b/src/hotspot/share/code/relocInfo.hpp
index 77e24708bb143..5f67f94bdadc5 100644
--- a/src/hotspot/share/code/relocInfo.hpp
+++ b/src/hotspot/share/code/relocInfo.hpp
@@ -862,7 +862,7 @@ class Relocation {
// all relocations are able to reassert their values
virtual void set_value(address x);
- virtual bool clear_inline_cache() { return true; }
+ virtual void clear_inline_cache() {}
// This method assumes that all virtual/static (inline) caches are cleared (since for static_call_type and
// ic_call_type is not always position dependent (depending on the state of the cache)). However, this is
@@ -1141,7 +1141,7 @@ class virtual_call_Relocation : public CallRelocation {
void pack_data_to(CodeSection* dest) override;
void unpack_data() override;
- bool clear_inline_cache() override;
+ void clear_inline_cache() override;
};
@@ -1170,7 +1170,7 @@ class opt_virtual_call_Relocation : public CallRelocation {
void pack_data_to(CodeSection* dest) override;
void unpack_data() override;
- bool clear_inline_cache() override;
+ void clear_inline_cache() override;
// find the matching static_stub
address static_stub();
@@ -1202,7 +1202,7 @@ class static_call_Relocation : public CallRelocation {
void pack_data_to(CodeSection* dest) override;
void unpack_data() override;
- bool clear_inline_cache() override;
+ void clear_inline_cache() override;
// find the matching static_stub
address static_stub();
@@ -1227,7 +1227,7 @@ class static_stub_Relocation : public Relocation {
static_stub_Relocation() : Relocation(relocInfo::static_stub_type) { }
public:
- bool clear_inline_cache() override;
+ void clear_inline_cache() override;
address static_call() { return _static_call; }
diff --git a/src/hotspot/share/code/vtableStubs.cpp b/src/hotspot/share/code/vtableStubs.cpp
index eed3dc8e7876a..5a54426d6a420 100644
--- a/src/hotspot/share/code/vtableStubs.cpp
+++ b/src/hotspot/share/code/vtableStubs.cpp
@@ -283,13 +283,6 @@ VtableStub* VtableStubs::entry_point(address pc) {
return (s == stub) ? s : nullptr;
}
-bool VtableStubs::is_icholder_entry(address pc) {
- assert(contains(pc), "must contain all vtable blobs");
- VtableStub* stub = (VtableStub*)(pc - VtableStub::entry_offset());
- // itable stubs use CompiledICHolder.
- return stub->is_itable_stub();
-}
-
bool VtableStubs::contains(address pc) {
// simple solution for now - we may want to use
// a faster way if this function is called often
diff --git a/src/hotspot/share/code/vtableStubs.hpp b/src/hotspot/share/code/vtableStubs.hpp
index 7076e50f3e3d8..3993e1e72d5cf 100644
--- a/src/hotspot/share/code/vtableStubs.hpp
+++ b/src/hotspot/share/code/vtableStubs.hpp
@@ -107,7 +107,6 @@ class VtableStubs : AllStatic {
static address find_itable_stub(int itable_index) { return find_stub(false, itable_index); }
static VtableStub* entry_point(address pc); // vtable stub entry point for a pc
- static bool is_icholder_entry(address pc); // is the blob containing pc (which must be a vtable blob) an icholder?
static bool contains(address pc); // is pc within any stub?
static VtableStub* stub_containing(address pc); // stub containing pc or nullptr
static void initialize();
diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
index 802049d9b2f05..f4453a7ba0bb4 100644
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
@@ -27,7 +27,6 @@
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "compiler/oopMap.hpp"
#include "gc/g1/g1Allocator.inline.hpp"
#include "gc/g1/g1Arguments.hpp"
@@ -2198,8 +2197,6 @@ void G1CollectedHeap::trace_heap(GCWhen::Type when, const GCTracer* gc_tracer) {
}
void G1CollectedHeap::gc_prologue(bool full) {
- assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer");
-
// Update common counters.
increment_total_collections(full /* full gc */);
if (full || collector_state()->in_concurrent_start_gc()) {
diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp
index 41bd49edaf605..d0594a3a50037 100644
--- a/src/hotspot/share/gc/serial/genMarkSweep.cpp
+++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp
@@ -30,7 +30,6 @@
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "compiler/oopMap.hpp"
#include "gc/serial/cardTableRS.hpp"
#include "gc/serial/defNewGeneration.hpp"
diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp
index 6d5ce55a1c853..ee7684c910711 100644
--- a/src/hotspot/share/gc/serial/serialHeap.cpp
+++ b/src/hotspot/share/gc/serial/serialHeap.cpp
@@ -28,7 +28,6 @@
#include "classfile/symbolTable.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "compiler/oopMap.hpp"
#include "gc/serial/cardTableRS.hpp"
#include "gc/serial/defNewGeneration.inline.hpp"
@@ -1039,8 +1038,6 @@ void SerialHeap::print_heap_change(const PreGenGCValues& pre_gc_values) const {
}
void SerialHeap::gc_prologue(bool full) {
- assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer");
-
// Fill TLAB's and such
ensure_parsability(true); // retire TLABs
diff --git a/src/hotspot/share/gc/shared/parallelCleaning.cpp b/src/hotspot/share/gc/shared/parallelCleaning.cpp
index 396f7e6c31e1f..ef82c8b676ef1 100644
--- a/src/hotspot/share/gc/shared/parallelCleaning.cpp
+++ b/src/hotspot/share/gc/shared/parallelCleaning.cpp
@@ -47,7 +47,6 @@ CodeCacheUnloadingTask::CodeCacheUnloadingTask(uint num_workers, bool unloading_
CodeCacheUnloadingTask::~CodeCacheUnloadingTask() {
CodeCache::verify_clean_inline_caches();
- CodeCache::verify_icholder_relocations();
}
void CodeCacheUnloadingTask::claim_nmethods(CompiledMethod** claimed_nmethods, int *num_claimed_nmethods) {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp
index c5b6d787b95a8..c6352b2749c78 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp
@@ -24,7 +24,6 @@
#include "precompiled.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "gc/shared/classUnloadingContext.hpp"
#include "gc/shenandoah/shenandoahClosures.inline.hpp"
@@ -128,26 +127,17 @@ void ShenandoahCodeRoots::disarm_nmethods() {
class ShenandoahNMethodUnlinkClosure : public NMethodClosure {
private:
bool _unloading_occurred;
- volatile bool _failed;
ShenandoahHeap* const _heap;
BarrierSetNMethod* const _bs;
- void set_failed() {
- Atomic::store(&_failed, true);
- }
-
public:
ShenandoahNMethodUnlinkClosure(bool unloading_occurred) :
_unloading_occurred(unloading_occurred),
- _failed(false),
_heap(ShenandoahHeap::heap()),
_bs(ShenandoahBarrierSet::barrier_set()->barrier_set_nmethod()) {}
virtual void do_nmethod(nmethod* nm) {
assert(_heap->is_concurrent_weak_root_in_progress(), "Only this phase");
- if (failed()) {
- return;
- }
ShenandoahNMethod* nm_data = ShenandoahNMethod::gc_data(nm);
assert(!nm_data->is_unregistered(), "Should not see unregistered entry");
@@ -170,27 +160,19 @@ class ShenandoahNMethodUnlinkClosure : public NMethodClosure {
}
// Clear compiled ICs and exception caches
- if (!nm->unload_nmethod_caches(_unloading_occurred)) {
- set_failed();
- }
- }
-
- bool failed() const {
- return Atomic::load(&_failed);
+ nm->unload_nmethod_caches(_unloading_occurred);
}
};
class ShenandoahUnlinkTask : public WorkerTask {
private:
ShenandoahNMethodUnlinkClosure _cl;
- ICRefillVerifier* _verifier;
ShenandoahConcurrentNMethodIterator _iterator;
public:
- ShenandoahUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
+ ShenandoahUnlinkTask(bool unloading_occurred) :
WorkerTask("Shenandoah Unlink NMethods"),
_cl(unloading_occurred),
- _verifier(verifier),
_iterator(ShenandoahCodeRoots::table()) {
MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
_iterator.nmethods_do_begin();
@@ -202,35 +184,15 @@ class ShenandoahUnlinkTask : public WorkerTask {
}
virtual void work(uint worker_id) {
- ICRefillVerifierMark mark(_verifier);
_iterator.nmethods_do(&_cl);
}
-
- bool success() const {
- return !_cl.failed();
- }
};
void ShenandoahCodeRoots::unlink(WorkerThreads* workers, bool unloading_occurred) {
assert(ShenandoahHeap::heap()->unload_classes(), "Only when running concurrent class unloading");
- for (;;) {
- ICRefillVerifier verifier;
-
- {
- ShenandoahUnlinkTask task(unloading_occurred, &verifier);
- workers->run_task(&task);
- if (task.success()) {
- return;
- }
- }
-
- // Cleaning failed because we ran out of transitional IC stubs,
- // so we have to refill and try again. Refilling requires taking
- // a safepoint, so we temporarily leave the suspendible thread set.
- SuspendibleThreadSetLeaver sts;
- InlineCacheBuffer::refill_ic_stubs();
- }
+ ShenandoahUnlinkTask task(unloading_occurred);
+ workers->run_task(&task);
}
void ShenandoahCodeRoots::purge() {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp
index bb13e9b8e224c..1017210e23e92 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp
@@ -106,7 +106,7 @@ class ShenandoahCompiledICProtectionBehaviour : public CompiledICProtectionBehav
}
virtual bool is_safe(CompiledMethod* method) {
- if (SafepointSynchronize::is_at_safepoint()) {
+ if (SafepointSynchronize::is_at_safepoint() || method->is_unloading()) {
return true;
}
diff --git a/src/hotspot/share/gc/x/xNMethod.cpp b/src/hotspot/share/gc/x/xNMethod.cpp
index 613e190850225..5a368a8483b65 100644
--- a/src/hotspot/share/gc/x/xNMethod.cpp
+++ b/src/hotspot/share/gc/x/xNMethod.cpp
@@ -24,7 +24,6 @@
#include "precompiled.hpp"
#include "code/relocInfo.hpp"
#include "code/nmethod.hpp"
-#include "code/icBuffer.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetNMethod.hpp"
#include "gc/shared/classUnloadingContext.hpp"
@@ -305,9 +304,7 @@ class XNMethodUnlinkClosure : public NMethodClosure {
}
// Clear compiled ICs and exception caches
- if (!nm->unload_nmethod_caches(_unloading_occurred)) {
- set_failed();
- }
+ nm->unload_nmethod_caches(_unloading_occurred);
}
bool failed() const {
@@ -318,13 +315,11 @@ class XNMethodUnlinkClosure : public NMethodClosure {
class XNMethodUnlinkTask : public XTask {
private:
XNMethodUnlinkClosure _cl;
- ICRefillVerifier* _verifier;
public:
- XNMethodUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
+ XNMethodUnlinkTask(bool unloading_occurred) :
XTask("XNMethodUnlinkTask"),
- _cl(unloading_occurred),
- _verifier(verifier) {
+ _cl(unloading_occurred) {
XNMethodTable::nmethods_do_begin();
}
@@ -333,33 +328,13 @@ class XNMethodUnlinkTask : public XTask {
}
virtual void work() {
- ICRefillVerifierMark mark(_verifier);
XNMethodTable::nmethods_do(&_cl);
}
-
- bool success() const {
- return !_cl.failed();
- }
};
void XNMethod::unlink(XWorkers* workers, bool unloading_occurred) {
- for (;;) {
- ICRefillVerifier verifier;
-
- {
- XNMethodUnlinkTask task(unloading_occurred, &verifier);
- workers->run(&task);
- if (task.success()) {
- return;
- }
- }
-
- // Cleaning failed because we ran out of transitional IC stubs,
- // so we have to refill and try again. Refilling requires taking
- // a safepoint, so we temporarily leave the suspendible thread set.
- SuspendibleThreadSetLeaver sts;
- InlineCacheBuffer::refill_ic_stubs();
- }
+ XNMethodUnlinkTask task(unloading_occurred);
+ workers->run(&task);
}
void XNMethod::purge() {
diff --git a/src/hotspot/share/gc/x/xNMethodTable.cpp b/src/hotspot/share/gc/x/xNMethodTable.cpp
index f866c5816846c..52fcba755a70b 100644
--- a/src/hotspot/share/gc/x/xNMethodTable.cpp
+++ b/src/hotspot/share/gc/x/xNMethodTable.cpp
@@ -24,7 +24,6 @@
#include "precompiled.hpp"
#include "code/relocInfo.hpp"
#include "code/nmethod.hpp"
-#include "code/icBuffer.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetNMethod.hpp"
#include "gc/x/xGlobals.hpp"
diff --git a/src/hotspot/share/gc/x/xUnload.cpp b/src/hotspot/share/gc/x/xUnload.cpp
index 27d429d3635df..230dbf613a445 100644
--- a/src/hotspot/share/gc/x/xUnload.cpp
+++ b/src/hotspot/share/gc/x/xUnload.cpp
@@ -101,7 +101,7 @@ class XCompiledICProtectionBehaviour : public CompiledICProtectionBehaviour {
}
virtual bool is_safe(CompiledMethod* method) {
- if (SafepointSynchronize::is_at_safepoint()) {
+ if (SafepointSynchronize::is_at_safepoint() || method->is_unloading()) {
return true;
}
diff --git a/src/hotspot/share/gc/z/zNMethod.cpp b/src/hotspot/share/gc/z/zNMethod.cpp
index 71d514face15a..a7d23124b683f 100644
--- a/src/hotspot/share/gc/z/zNMethod.cpp
+++ b/src/hotspot/share/gc/z/zNMethod.cpp
@@ -25,7 +25,6 @@
#include "code/codeCache.hpp"
#include "code/relocInfo.hpp"
#include "code/nmethod.hpp"
-#include "code/icBuffer.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetNMethod.hpp"
#include "gc/shared/classUnloadingContext.hpp"
@@ -334,23 +333,13 @@ oop ZNMethod::load_oop(oop* p, DecoratorSet decorators) {
class ZNMethodUnlinkClosure : public NMethodClosure {
private:
- bool _unloading_occurred;
- volatile bool _failed;
-
- void set_failed() {
- Atomic::store(&_failed, true);
- }
+ bool _unloading_occurred;
public:
ZNMethodUnlinkClosure(bool unloading_occurred)
- : _unloading_occurred(unloading_occurred),
- _failed(false) {}
+ : _unloading_occurred(unloading_occurred) {}
virtual void do_nmethod(nmethod* nm) {
- if (failed()) {
- return;
- }
-
if (nm->is_unloading()) {
// Unlink from the ZNMethodTable
ZNMethod::unregister_nmethod(nm);
@@ -386,26 +375,18 @@ class ZNMethodUnlinkClosure : public NMethodClosure {
}
// Clear compiled ICs and exception caches
- if (!nm->unload_nmethod_caches(_unloading_occurred)) {
- set_failed();
- }
- }
-
- bool failed() const {
- return Atomic::load(&_failed);
+ nm->unload_nmethod_caches(_unloading_occurred);
}
};
class ZNMethodUnlinkTask : public ZTask {
private:
ZNMethodUnlinkClosure _cl;
- ICRefillVerifier* _verifier;
public:
- ZNMethodUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier)
+ ZNMethodUnlinkTask(bool unloading_occurred)
: ZTask("ZNMethodUnlinkTask"),
- _cl(unloading_occurred),
- _verifier(verifier) {
+ _cl(unloading_occurred) {
ZNMethodTable::nmethods_do_begin(false /* secondary */);
}
@@ -414,33 +395,13 @@ class ZNMethodUnlinkTask : public ZTask {
}
virtual void work() {
- ICRefillVerifierMark mark(_verifier);
ZNMethodTable::nmethods_do(false /* secondary */, &_cl);
}
-
- bool success() const {
- return !_cl.failed();
- }
};
void ZNMethod::unlink(ZWorkers* workers, bool unloading_occurred) {
- for (;;) {
- ICRefillVerifier verifier;
-
- {
- ZNMethodUnlinkTask task(unloading_occurred, &verifier);
- workers->run(&task);
- if (task.success()) {
- return;
- }
- }
-
- // Cleaning failed because we ran out of transitional IC stubs,
- // so we have to refill and try again. Refilling requires taking
- // a safepoint, so we temporarily leave the suspendible thread set.
- SuspendibleThreadSetLeaver sts_leaver;
- InlineCacheBuffer::refill_ic_stubs();
- }
+ ZNMethodUnlinkTask task(unloading_occurred);
+ workers->run(&task);
}
void ZNMethod::purge() {
diff --git a/src/hotspot/share/gc/z/zNMethodTable.cpp b/src/hotspot/share/gc/z/zNMethodTable.cpp
index f75af7af616c7..a4b56292c522b 100644
--- a/src/hotspot/share/gc/z/zNMethodTable.cpp
+++ b/src/hotspot/share/gc/z/zNMethodTable.cpp
@@ -24,7 +24,6 @@
#include "precompiled.hpp"
#include "code/relocInfo.hpp"
#include "code/nmethod.hpp"
-#include "code/icBuffer.hpp"
#include "gc/shared/barrierSet.hpp"
#include "gc/shared/barrierSetNMethod.hpp"
#include "gc/z/zHash.inline.hpp"
diff --git a/src/hotspot/share/gc/z/zUnload.cpp b/src/hotspot/share/gc/z/zUnload.cpp
index 76c275df35599..3ab4cd5b19f22 100644
--- a/src/hotspot/share/gc/z/zUnload.cpp
+++ b/src/hotspot/share/gc/z/zUnload.cpp
@@ -104,7 +104,7 @@ class ZCompiledICProtectionBehaviour : public CompiledICProtectionBehaviour {
}
virtual bool is_safe(CompiledMethod* method) {
- if (SafepointSynchronize::is_at_safepoint()) {
+ if (SafepointSynchronize::is_at_safepoint() || method->is_unloading()) {
return true;
}
diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp
index 51281b0f5564e..a5a20a1310ef9 100644
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp
@@ -896,8 +896,8 @@ int CodeInstaller::estimate_stubs_size(HotSpotCompiledCodeStream* stream, JVMCI_
// Estimate the number of static call stubs that might be emitted.
u2 static_call_stubs = stream->read_u2("numStaticCallStubs");
u2 trampoline_stubs = stream->read_u2("numTrampolineStubs");
- int size = static_call_stubs * CompiledStaticCall::to_interp_stub_size();
- size += trampoline_stubs * CompiledStaticCall::to_trampoline_stub_size();
+ int size = static_call_stubs * CompiledDirectCall::to_interp_stub_size();
+ size += trampoline_stubs * CompiledDirectCall::to_trampoline_stub_size();
return size;
}
@@ -1243,7 +1243,7 @@ void CodeInstaller::site_Call(CodeBuffer& buffer, u1 tag, jint pc_offset, HotSpo
CodeInstaller::pd_relocate_JavaMethod(buffer, method, pc_offset, JVMCI_CHECK);
if (_next_call_type == INVOKESTATIC || _next_call_type == INVOKESPECIAL) {
// Need a static call stub for transitions from compiled to interpreted.
- if (CompiledStaticCall::emit_to_interp_stub(buffer, _instructions->start() + pc_offset) == nullptr) {
+ if (CompiledDirectCall::emit_to_interp_stub(buffer, _instructions->start() + pc_offset) == nullptr) {
JVMCI_ERROR("could not emit to_interp stub - code cache is full");
}
}
diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
index 2ad442db93483..f47c4cdd94033 100644
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "code/codeCache.hpp"
+#include "code/compiledIC.hpp"
#include "compiler/compileBroker.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "jvmci/jvmciCodeInstaller.hpp"
@@ -144,6 +145,11 @@
\
nonstatic_field(CompileTask, _num_inlined_bytecodes, int) \
\
+ volatile_nonstatic_field(CompiledICData, _speculated_method, Method*) \
+ volatile_nonstatic_field(CompiledICData, _speculated_klass, uintptr_t) \
+ nonstatic_field(CompiledICData, _itable_defc_klass, Klass*) \
+ nonstatic_field(CompiledICData, _itable_refc_klass, Klass*) \
+ \
nonstatic_field(ConstantPool, _tags, Array*) \
nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \
nonstatic_field(ConstantPool, _length, int) \
@@ -430,6 +436,7 @@
declare_toplevel_type(oopDesc) \
declare_type(arrayOopDesc, oopDesc) \
\
+ declare_toplevel_type(CompiledICData) \
declare_toplevel_type(MetaspaceObj) \
declare_type(Metadata, MetaspaceObj) \
declare_type(Klass, Metadata) \
diff --git a/src/hotspot/share/oops/compiledICHolder.cpp b/src/hotspot/share/oops/compiledICHolder.cpp
deleted file mode 100644
index 8bfa55bcce7a5..0000000000000
--- a/src/hotspot/share/oops/compiledICHolder.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 1998, 2022, 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "oops/compiledICHolder.hpp"
-#include "runtime/atomic.hpp"
-
-#ifdef ASSERT
-volatile int CompiledICHolder::_live_count;
-volatile int CompiledICHolder::_live_not_claimed_count;
-#endif
-
-CompiledICHolder::CompiledICHolder(Metadata* metadata, Klass* klass, bool is_method)
- : _holder_metadata(metadata), _holder_klass(klass), _next(nullptr), _is_metadata_method(is_method) {
-#ifdef ASSERT
- Atomic::inc(&_live_count);
- Atomic::inc(&_live_not_claimed_count);
-#endif // ASSERT
-}
-
-#ifdef ASSERT
-CompiledICHolder::~CompiledICHolder() {
- assert(_live_count > 0, "underflow");
- Atomic::dec(&_live_count);
-}
-#endif // ASSERT
-
-// Printing
-
-void CompiledICHolder::print_on(outputStream* st) const {
- st->print("%s", internal_name());
- st->print(" - metadata: "); holder_metadata()->print_value_on(st); st->cr();
- st->print(" - klass: "); holder_klass()->print_value_on(st); st->cr();
-}
-
-void CompiledICHolder::print_value_on(outputStream* st) const {
- st->print("%s", internal_name());
-}
-
-
-// Verification
-
-void CompiledICHolder::verify_on(outputStream* st) {
- guarantee(holder_metadata()->is_method() || holder_metadata()->is_klass(), "should be method or klass");
- guarantee(holder_klass()->is_klass(), "should be klass");
-}
-
-#ifdef ASSERT
-
-void CompiledICHolder::claim() {
- Atomic::dec(&_live_not_claimed_count);
-}
-
-#endif // ASSERT
diff --git a/src/hotspot/share/oops/compiledICHolder.hpp b/src/hotspot/share/oops/compiledICHolder.hpp
deleted file mode 100644
index 4509c8f578b77..0000000000000
--- a/src/hotspot/share/oops/compiledICHolder.hpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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.
- *
- */
-
-#ifndef SHARE_OOPS_COMPILEDICHOLDER_HPP
-#define SHARE_OOPS_COMPILEDICHOLDER_HPP
-
-#include "oops/oop.hpp"
-#include "utilities/macros.hpp"
-#include "oops/klass.hpp"
-#include "oops/method.hpp"
-
-// A CompiledICHolder* is a helper object for the inline cache implementation.
-// It holds:
-// (1) (method+klass pair) when converting from compiled to an interpreted call
-// (2) (klass+klass pair) when calling itable stub from megamorphic compiled call
-//
-// These are always allocated in the C heap and are freed during a
-// safepoint by the ICBuffer logic. It's unsafe to free them earlier
-// since they might be in use.
-//
-
-
-class CompiledICHolder : public CHeapObj {
- friend class VMStructs;
- private:
-#ifdef ASSERT
- static volatile int _live_count; // allocated
- static volatile int _live_not_claimed_count; // allocated but not yet in use so not
- // reachable by iterating over nmethods
-#endif
-
- Metadata* _holder_metadata;
- Klass* _holder_klass; // to avoid name conflict with oopDesc::_klass
- CompiledICHolder* _next;
- bool _is_metadata_method;
-
- public:
- // Constructor
- CompiledICHolder(Metadata* metadata, Klass* klass, bool is_method = true);
- ~CompiledICHolder() NOT_DEBUG_RETURN;
-
-#ifdef ASSERT
- static int live_count() { return _live_count; }
- static int live_not_claimed_count() { return _live_not_claimed_count; }
-#endif
-
- // accessors
- Klass* holder_klass() const { return _holder_klass; }
- Metadata* holder_metadata() const { return _holder_metadata; }
-
- static ByteSize holder_metadata_offset() { return byte_offset_of(CompiledICHolder, _holder_metadata); }
- static ByteSize holder_klass_offset() { return byte_offset_of(CompiledICHolder, _holder_klass); }
-
- CompiledICHolder* next() { return _next; }
- void set_next(CompiledICHolder* n) { _next = n; }
-
- inline bool is_loader_alive();
-
- // Verify
- void verify_on(outputStream* st);
-
- // Printing
- void print_on(outputStream* st) const;
- void print_value_on(outputStream* st) const;
-
- const char* internal_name() const { return "{compiledICHolder}"; }
-
- void claim() NOT_DEBUG_RETURN;
-};
-
-#endif // SHARE_OOPS_COMPILEDICHOLDER_HPP
diff --git a/src/hotspot/share/oops/compiledICHolder.inline.hpp b/src/hotspot/share/oops/compiledICHolder.inline.hpp
deleted file mode 100644
index efbfcec064762..0000000000000
--- a/src/hotspot/share/oops/compiledICHolder.inline.hpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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.
- *
- */
-
-#ifndef SHARE_OOPS_COMPILEDICHOLDER_INLINE_HPP
-#define SHARE_OOPS_COMPILEDICHOLDER_INLINE_HPP
-
-#include "oops/compiledICHolder.hpp"
-
-#include "oops/klass.inline.hpp"
-
-inline bool CompiledICHolder::is_loader_alive() {
- Klass* k = _is_metadata_method ? ((Method*)_holder_metadata)->method_holder() : (Klass*)_holder_metadata;
- if (!k->is_loader_alive()) {
- return false;
- }
- if (!_holder_klass->is_loader_alive()) {
- return false;
- }
- return true;
-}
-
-#endif // SHARE_OOPS_COMPILEDICHOLDER_INLINE_HPP
diff --git a/src/hotspot/share/oops/oopsHierarchy.hpp b/src/hotspot/share/oops/oopsHierarchy.hpp
index b01153da46d54..4bc5a7d4c174c 100644
--- a/src/hotspot/share/oops/oopsHierarchy.hpp
+++ b/src/hotspot/share/oops/oopsHierarchy.hpp
@@ -179,9 +179,6 @@ class MethodData;
// class Metadata
class Method;
class ConstantPool;
-// class CHeapObj
-class CompiledICHolder;
-
// The klass hierarchy is separate from the oop hierarchy.
diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp
index 9481b91ce39e9..640a24693dedd 100644
--- a/src/hotspot/share/opto/output.cpp
+++ b/src/hotspot/share/opto/output.cpp
@@ -507,8 +507,8 @@ void PhaseOutput::shorten_branches(uint* blk_starts) {
mcall->method_set((intptr_t)mcall->entry_point());
if (mcall->is_MachCallJava() && mcall->as_MachCallJava()->_method) {
- stub_size += CompiledStaticCall::to_interp_stub_size();
- reloc_size += CompiledStaticCall::reloc_to_interp_stub();
+ stub_size += CompiledDirectCall::to_interp_stub_size();
+ reloc_size += CompiledDirectCall::reloc_to_interp_stub();
}
} else if (mach->is_MachSafePoint()) {
// If call/safepoint are adjacent, account for possible
@@ -3412,6 +3412,12 @@ void PhaseOutput::install_code(ciMethod* target,
_code_offsets.set_value(CodeOffsets::Verified_Entry, 0);
_code_offsets.set_value(CodeOffsets::OSR_Entry, _first_block_size);
} else {
+ if (!target->is_static()) {
+ // The UEP of an nmethod ensures that the VEP is padded. However, the padding of the UEP is placed
+ // before the inline cache check, so we don't have to execute any nop instructions when dispatching
+ // through the UEP, yet we can ensure that the VEP is aligned appropriately.
+ _code_offsets.set_value(CodeOffsets::Entry, _first_block_size - MacroAssembler::ic_check_size());
+ }
_code_offsets.set_value(CodeOffsets::Verified_Entry, _first_block_size);
_code_offsets.set_value(CodeOffsets::OSR_Entry, 0);
}
diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp
index 8f3367ce0003c..c5f22e8ebbb84 100644
--- a/src/hotspot/share/opto/runtime.cpp
+++ b/src/hotspot/share/opto/runtime.cpp
@@ -28,7 +28,6 @@
#include "code/codeCache.hpp"
#include "code/compiledMethod.inline.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "code/pcDesc.hpp"
#include "code/scopeDesc.hpp"
diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp
index 16198aca5370d..57313c01cb7fe 100644
--- a/src/hotspot/share/runtime/globals.hpp
+++ b/src/hotspot/share/runtime/globals.hpp
@@ -880,9 +880,6 @@ const int ObjectAlignmentInBytes = 8;
notproduct(bool, TraceInvocationCounterOverflow, false, \
"Trace method invocation counter overflow") \
\
- develop(bool, TraceInlineCacheClearing, false, \
- "Trace clearing of inline caches in nmethods") \
- \
develop(bool, VerifyDependencies, trueInDebug, \
"Exercise and verify the compilation dependency mechanism") \
\
@@ -901,12 +898,6 @@ const int ObjectAlignmentInBytes = 8;
develop(bool, TraceOopMapRewrites, false, \
"Trace rewriting of methods during oop map generation") \
\
- develop(bool, TraceICBuffer, false, \
- "Trace usage of IC buffer") \
- \
- develop(bool, TraceCompiledIC, false, \
- "Trace changes of compiled IC") \
- \
develop(bool, FLSVerifyDictionary, false, \
"Do lots of (expensive) FLS dictionary verification") \
\
diff --git a/src/hotspot/share/runtime/init.cpp b/src/hotspot/share/runtime/init.cpp
index aabe3afc53b6e..d37ae99b41886 100644
--- a/src/hotspot/share/runtime/init.cpp
+++ b/src/hotspot/share/runtime/init.cpp
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
-#include "code/icBuffer.hpp"
#include "compiler/compiler_globals.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/gcHeapSummary.hpp"
@@ -83,7 +82,6 @@ void jni_handles_init();
void vmStructs_init() NOT_DEBUG_RETURN;
void vtableStubs_init();
-void InlineCacheBuffer_init();
bool compilerOracle_init();
bool compileBroker_init();
void dependencyContext_init();
@@ -163,7 +161,6 @@ jint init_globals2() {
#endif // INCLUDE_VM_STRUCTS
vtableStubs_init();
- InlineCacheBuffer_init();
if (!compilerOracle_init()) {
return JNI_EINVAL;
}
diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp
index 813bb58cb5a0f..88c52e19ab6be 100644
--- a/src/hotspot/share/runtime/os.cpp
+++ b/src/hotspot/share/runtime/os.cpp
@@ -30,7 +30,6 @@
#include "classfile/vmClasses.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/vtableStubs.hpp"
#include "gc/shared/gcVMOperations.hpp"
#include "interpreter/interpreter.hpp"
diff --git a/src/hotspot/share/runtime/safepoint.cpp b/src/hotspot/share/runtime/safepoint.cpp
index 266e6b54aca94..a04f1945a5ef4 100644
--- a/src/hotspot/share/runtime/safepoint.cpp
+++ b/src/hotspot/share/runtime/safepoint.cpp
@@ -27,7 +27,6 @@
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "code/pcDesc.hpp"
#include "code/scopeDesc.hpp"
@@ -513,7 +512,6 @@ void SafepointSynchronize::end() {
bool SafepointSynchronize::is_cleanup_needed() {
// Need a safepoint if some inline cache buffers is non-empty
- if (!InlineCacheBuffer::is_empty()) return true;
if (StringTable::needs_rehashing()) return true;
if (SymbolTable::needs_rehashing()) return true;
return false;
@@ -558,10 +556,6 @@ class ParallelCleanupTask : public WorkerTask {
workers++;
}
- if (InlineCacheBuffer::needs_update_inline_caches()) {
- workers++;
- }
-
if (_do_lazy_roots) {
workers++;
}
@@ -599,11 +593,6 @@ class ParallelCleanupTask : public WorkerTask {
}
}
- if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_UPDATE_INLINE_CACHES)) {
- Tracer t("updating inline caches");
- InlineCacheBuffer::update_inline_caches();
- }
-
if (_subtasks.try_claim_task(SafepointSynchronize::SAFEPOINT_CLEANUP_REQUEST_OOPSTORAGE_CLEANUP)) {
// Don't bother reporting event or time for this very short operation.
// To have any utility we'd also want to report whether needed.
@@ -633,8 +622,6 @@ void SafepointSynchronize::do_cleanup_tasks() {
cleanup.work(0);
}
- assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer");
-
if (log_is_enabled(Debug, monitorinflation)) {
// The VMThread calls do_final_audit_and_print_stats() which calls
// audit_and_print_stats() at the Info level at VM exit time.
diff --git a/src/hotspot/share/runtime/safepoint.hpp b/src/hotspot/share/runtime/safepoint.hpp
index 1f78a1b8e5a16..f6da9881e4c78 100644
--- a/src/hotspot/share/runtime/safepoint.hpp
+++ b/src/hotspot/share/runtime/safepoint.hpp
@@ -71,7 +71,6 @@ class SafepointSynchronize : AllStatic {
// The enums are listed in the order of the tasks when done serially.
enum SafepointCleanupTasks {
SAFEPOINT_CLEANUP_LAZY_ROOT_PROCESSING,
- SAFEPOINT_CLEANUP_UPDATE_INLINE_CACHES,
SAFEPOINT_CLEANUP_SYMBOL_TABLE_REHASH,
SAFEPOINT_CLEANUP_STRING_TABLE_REHASH,
SAFEPOINT_CLEANUP_REQUEST_OOPSTORAGE_CLEANUP,
diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp
index e1d39225b4cd6..cb0073108ae65 100644
--- a/src/hotspot/share/runtime/sharedRuntime.cpp
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp
@@ -29,7 +29,6 @@
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
-#include "code/icBuffer.hpp"
#include "code/compiledMethod.inline.hpp"
#include "code/scopeDesc.hpp"
#include "code/vtableStubs.hpp"
@@ -47,7 +46,6 @@
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "metaprogramming/primitiveConversions.hpp"
-#include "oops/compiledICHolder.inline.hpp"
#include "oops/klass.hpp"
#include "oops/method.inline.hpp"
#include "oops/objArrayKlass.hpp"
@@ -1288,124 +1286,6 @@ methodHandle SharedRuntime::find_callee_method(TRAPS) {
// Resolves a call.
methodHandle SharedRuntime::resolve_helper(bool is_virtual, bool is_optimized, TRAPS) {
- methodHandle callee_method;
- callee_method = resolve_sub_helper(is_virtual, is_optimized, THREAD);
- if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
- int retry_count = 0;
- while (!HAS_PENDING_EXCEPTION && callee_method->is_old() &&
- callee_method->method_holder() != vmClasses::Object_klass()) {
- // If has a pending exception then there is no need to re-try to
- // resolve this method.
- // If the method has been redefined, we need to try again.
- // Hack: we have no way to update the vtables of arrays, so don't
- // require that java.lang.Object has been updated.
-
- // It is very unlikely that method is redefined more than 100 times
- // in the middle of resolve. If it is looping here more than 100 times
- // means then there could be a bug here.
- guarantee((retry_count++ < 100),
- "Could not resolve to latest version of redefined method");
- // method is redefined in the middle of resolve so re-try.
- callee_method = resolve_sub_helper(is_virtual, is_optimized, THREAD);
- }
- }
- return callee_method;
-}
-
-// This fails if resolution required refilling of IC stubs
-bool SharedRuntime::resolve_sub_helper_internal(methodHandle callee_method, const frame& caller_frame,
- CompiledMethod* caller_nm, bool is_virtual, bool is_optimized,
- Handle receiver, CallInfo& call_info, Bytecodes::Code invoke_code, TRAPS) {
- StaticCallInfo static_call_info;
- CompiledICInfo virtual_call_info;
-
- // Make sure the callee nmethod does not get deoptimized and removed before
- // we are done patching the code.
- CompiledMethod* callee = callee_method->code();
-
- if (callee != nullptr) {
- assert(callee->is_compiled(), "must be nmethod for patching");
- }
-
- if (callee != nullptr && !callee->is_in_use()) {
- // Patch call site to C2I adapter if callee nmethod is deoptimized or unloaded.
- callee = nullptr;
- }
-#ifdef ASSERT
- address dest_entry_point = callee == nullptr ? 0 : callee->entry_point(); // used below
-#endif
-
- bool is_nmethod = caller_nm->is_nmethod();
-
- if (is_virtual) {
- assert(receiver.not_null() || invoke_code == Bytecodes::_invokehandle, "sanity check");
- bool static_bound = call_info.resolved_method()->can_be_statically_bound();
- Klass* klass = invoke_code == Bytecodes::_invokehandle ? nullptr : receiver->klass();
- CompiledIC::compute_monomorphic_entry(callee_method, klass,
- is_optimized, static_bound, is_nmethod, virtual_call_info,
- CHECK_false);
- } else {
- // static call
- CompiledStaticCall::compute_entry(callee_method, is_nmethod, static_call_info);
- }
-
- JFR_ONLY(bool patched_caller = false;)
- // grab lock, check for deoptimization and potentially patch caller
- {
- CompiledICLocker ml(caller_nm);
-
- // Lock blocks for safepoint during which both nmethods can change state.
-
- // Now that we are ready to patch if the Method* was redefined then
- // don't update call site and let the caller retry.
- // Don't update call site if callee nmethod was unloaded or deoptimized.
- // Don't update call site if callee nmethod was replaced by an other nmethod
- // which may happen when multiply alive nmethod (tiered compilation)
- // will be supported.
- if (!callee_method->is_old() &&
- (callee == nullptr || (callee->is_in_use() && callee_method->code() == callee))) {
- NoSafepointVerifier nsv;
-#ifdef ASSERT
- // We must not try to patch to jump to an already unloaded method.
- if (dest_entry_point != 0) {
- CodeBlob* cb = CodeCache::find_blob(dest_entry_point);
- assert((cb != nullptr) && cb->is_compiled() && (((CompiledMethod*)cb) == callee),
- "should not call unloaded nmethod");
- }
-#endif
- if (is_virtual) {
- CompiledIC* inline_cache = CompiledIC_before(caller_nm, caller_frame.pc());
- if (inline_cache->is_clean()) {
- if (!inline_cache->set_to_monomorphic(virtual_call_info)) {
- return false;
- }
- JFR_ONLY(patched_caller = true;)
- }
- } else {
- if (VM_Version::supports_fast_class_init_checks() &&
- invoke_code == Bytecodes::_invokestatic &&
- callee_method->needs_clinit_barrier() &&
- callee != nullptr && callee->is_compiled_by_jvmci()) {
- return true; // skip patching for JVMCI
- }
- CompiledStaticCall* ssc = caller_nm->compiledStaticCall_before(caller_frame.pc());
- if (is_nmethod && caller_nm->method()->is_continuation_enter_intrinsic()) {
- ssc->compute_entry_for_continuation_entry(callee_method, static_call_info);
- }
- if (ssc->is_clean()) {
- ssc->set(static_call_info);
- JFR_ONLY(patched_caller = true;)
- }
- }
- }
- } // unlock CompiledICLocker
- JFR_ONLY(if (patched_caller) Jfr::on_backpatching(callee_method(), THREAD);)
- return true;
-}
-
-// Resolves a call. The compilers generate code for calls that go here
-// and are patched with the real destination of the call.
-methodHandle SharedRuntime::resolve_sub_helper(bool is_virtual, bool is_optimized, TRAPS) {
JavaThread* current = THREAD;
ResourceMark rm(current);
RegisterMap cbl_map(current,
@@ -1416,7 +1296,7 @@ methodHandle SharedRuntime::resolve_sub_helper(bool is_virtual, bool is_optimize
CodeBlob* caller_cb = caller_frame.cb();
guarantee(caller_cb != nullptr && caller_cb->is_compiled(), "must be called from compiled method");
- CompiledMethod* caller_nm = caller_cb->as_compiled_method_or_null();
+ CompiledMethod* caller_nm = caller_cb->as_compiled_method();
// determine call info & receiver
// note: a) receiver is null for static calls
@@ -1424,6 +1304,9 @@ methodHandle SharedRuntime::resolve_sub_helper(bool is_virtual, bool is_optimize
CallInfo call_info;
Bytecodes::Code invoke_code = Bytecodes::_illegal;
Handle receiver = find_callee_info(invoke_code, call_info, CHECK_(methodHandle()));
+
+ NoSafepointVerifier nsv;
+
methodHandle callee_method(current, call_info.selected_method());
assert((!is_virtual && invoke_code == Bytecodes::_invokestatic ) ||
@@ -1468,39 +1351,32 @@ methodHandle SharedRuntime::resolve_sub_helper(bool is_virtual, bool is_optimize
}
}
+
// JSR 292 key invariant:
// If the resolved method is a MethodHandle invoke target, the call
// site must be a MethodHandle call site, because the lambda form might tail-call
// leaving the stack in a state unknown to either caller or callee
- // TODO detune for now but we might need it again
-// assert(!callee_method->is_compiled_lambda_form() ||
-// caller_nm->is_method_handle_return(caller_frame.pc()), "must be MH call site");
-
- // Compute entry points. This might require generation of C2I converter
- // frames, so we cannot be holding any locks here. Furthermore, the
- // computation of the entry points is independent of patching the call. We
- // always return the entry-point, but we only patch the stub if the call has
- // not been deoptimized. Return values: For a virtual call this is an
- // (cached_oop, destination address) pair. For a static call/optimized
- // virtual this is just a destination address.
-
- // Patching IC caches may fail if we run out if transition stubs.
- // We refill the ic stubs then and try again.
- for (;;) {
- ICRefillVerifier ic_refill_verifier;
- bool successful = resolve_sub_helper_internal(callee_method, caller_frame, caller_nm,
- is_virtual, is_optimized, receiver,
- call_info, invoke_code, CHECK_(methodHandle()));
- if (successful) {
- return callee_method;
- } else {
- InlineCacheBuffer::refill_ic_stubs();
- }
+
+ // Compute entry points. The computation of the entry points is independent of
+ // patching the call.
+
+ // Make sure the callee nmethod does not get deoptimized and removed before
+ // we are done patching the code.
+
+
+ CompiledICLocker ml(caller_nm);
+ if (is_virtual && !is_optimized) {
+ CompiledIC* inline_cache = CompiledIC_before(caller_nm, caller_frame.pc());
+ inline_cache->update(&call_info, receiver->klass());
+ } else {
+ // Callsite is a direct call - set it to the destination method
+ CompiledDirectCall* callsite = CompiledDirectCall::before(caller_frame.pc());
+ callsite->set(callee_method);
}
+ return callee_method;
}
-
// Inline caches exist only in compiled code
JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method_ic_miss(JavaThread* current))
#ifdef ASSERT
@@ -1678,86 +1554,6 @@ JRT_BLOCK_ENTRY(address, SharedRuntime::resolve_opt_virtual_call_C(JavaThread* c
return callee_method->verified_code_entry();
JRT_END
-// The handle_ic_miss_helper_internal function returns false if it failed due
-// to either running out of vtable stubs or ic stubs due to IC transitions
-// to transitional states. The needs_ic_stub_refill value will be set if
-// the failure was due to running out of IC stubs, in which case handle_ic_miss_helper
-// refills the IC stubs and tries again.
-bool SharedRuntime::handle_ic_miss_helper_internal(Handle receiver, CompiledMethod* caller_nm,
- const frame& caller_frame, methodHandle callee_method,
- Bytecodes::Code bc, CallInfo& call_info,
- bool& needs_ic_stub_refill, TRAPS) {
- CompiledICLocker ml(caller_nm);
- CompiledIC* inline_cache = CompiledIC_before(caller_nm, caller_frame.pc());
- bool should_be_mono = false;
- if (inline_cache->is_optimized()) {
- if (TraceCallFixup) {
- ResourceMark rm(THREAD);
- tty->print("OPTIMIZED IC miss (%s) call to", Bytecodes::name(bc));
- callee_method->print_short_name(tty);
- tty->print_cr(" code: " INTPTR_FORMAT, p2i(callee_method->code()));
- }
- should_be_mono = true;
- } else if (inline_cache->is_icholder_call()) {
- CompiledICHolder* ic_oop = inline_cache->cached_icholder();
- if (ic_oop != nullptr) {
- if (!ic_oop->is_loader_alive()) {
- // Deferred IC cleaning due to concurrent class unloading
- if (!inline_cache->set_to_clean()) {
- needs_ic_stub_refill = true;
- return false;
- }
- } else if (receiver()->klass() == ic_oop->holder_klass()) {
- // This isn't a real miss. We must have seen that compiled code
- // is now available and we want the call site converted to a
- // monomorphic compiled call site.
- // We can't assert for callee_method->code() != nullptr because it
- // could have been deoptimized in the meantime
- if (TraceCallFixup) {
- ResourceMark rm(THREAD);
- tty->print("FALSE IC miss (%s) converting to compiled call to", Bytecodes::name(bc));
- callee_method->print_short_name(tty);
- tty->print_cr(" code: " INTPTR_FORMAT, p2i(callee_method->code()));
- }
- should_be_mono = true;
- }
- }
- }
-
- if (should_be_mono) {
- // We have a path that was monomorphic but was going interpreted
- // and now we have (or had) a compiled entry. We correct the IC
- // by using a new icBuffer.
- CompiledICInfo info;
- Klass* receiver_klass = receiver()->klass();
- inline_cache->compute_monomorphic_entry(callee_method,
- receiver_klass,
- inline_cache->is_optimized(),
- false, caller_nm->is_nmethod(),
- info, CHECK_false);
- if (!inline_cache->set_to_monomorphic(info)) {
- needs_ic_stub_refill = true;
- return false;
- }
- } else if (!inline_cache->is_megamorphic() && !inline_cache->is_clean()) {
- // Potential change to megamorphic
-
- bool successful = inline_cache->set_to_megamorphic(&call_info, bc, needs_ic_stub_refill, CHECK_false);
- if (needs_ic_stub_refill) {
- return false;
- }
- if (!successful) {
- if (!inline_cache->set_to_clean()) {
- needs_ic_stub_refill = true;
- return false;
- }
- }
- } else {
- // Either clean or megamorphic
- }
- return true;
-}
-
methodHandle SharedRuntime::handle_ic_miss_helper(TRAPS) {
JavaThread* current = THREAD;
ResourceMark rm(current);
@@ -1767,32 +1563,6 @@ methodHandle SharedRuntime::handle_ic_miss_helper(TRAPS) {
// receiver is null for static calls. An exception is thrown for null
// receivers for non-static calls
Handle receiver = find_callee_info(bc, call_info, CHECK_(methodHandle()));
- // Compiler1 can produce virtual call sites that can actually be statically bound
- // If we fell thru to below we would think that the site was going megamorphic
- // when in fact the site can never miss. Worse because we'd think it was megamorphic
- // we'd try and do a vtable dispatch however methods that can be statically bound
- // don't have vtable entries (vtable_index < 0) and we'd blow up. So we force a
- // reresolution of the call site (as if we did a handle_wrong_method and not an
- // plain ic_miss) and the site will be converted to an optimized virtual call site
- // never to miss again. I don't believe C2 will produce code like this but if it
- // did this would still be the correct thing to do for it too, hence no ifdef.
- //
- if (call_info.resolved_method()->can_be_statically_bound()) {
- methodHandle callee_method = SharedRuntime::reresolve_call_site(CHECK_(methodHandle()));
- if (TraceCallFixup) {
- RegisterMap reg_map(current,
- RegisterMap::UpdateMap::skip,
- RegisterMap::ProcessFrames::include,
- RegisterMap::WalkContinuation::skip);
- frame caller_frame = current->last_frame().sender(®_map);
- ResourceMark rm(current);
- tty->print("converting IC miss to reresolve (%s) call to", Bytecodes::name(bc));
- callee_method->print_short_name(tty);
- tty->print_cr(" from pc: " INTPTR_FORMAT, p2i(caller_frame.pc()));
- tty->print_cr(" code: " INTPTR_FORMAT, p2i(callee_method->code()));
- }
- return callee_method;
- }
methodHandle callee_method(current, call_info.selected_method());
@@ -1827,9 +1597,6 @@ methodHandle SharedRuntime::handle_ic_miss_helper(TRAPS) {
JvmtiDynamicCodeEventCollector event_collector;
// Update inline cache to megamorphic. Skip update if we are called from interpreted.
- // Transitioning IC caches may require transition stubs. If we run out
- // of transition stubs, we have to drop locks and perform a safepoint
- // that refills them.
RegisterMap reg_map(current,
RegisterMap::UpdateMap::skip,
RegisterMap::ProcessFrames::include,
@@ -1838,34 +1605,11 @@ methodHandle SharedRuntime::handle_ic_miss_helper(TRAPS) {
CodeBlob* cb = caller_frame.cb();
CompiledMethod* caller_nm = cb->as_compiled_method();
- for (;;) {
- ICRefillVerifier ic_refill_verifier;
- bool needs_ic_stub_refill = false;
- bool successful = handle_ic_miss_helper_internal(receiver, caller_nm, caller_frame, callee_method,
- bc, call_info, needs_ic_stub_refill, CHECK_(methodHandle()));
- if (successful || !needs_ic_stub_refill) {
- return callee_method;
- } else {
- InlineCacheBuffer::refill_ic_stubs();
- }
- }
-}
-
-static bool clear_ic_at_addr(CompiledMethod* caller_nm, address call_addr, bool is_static_call) {
CompiledICLocker ml(caller_nm);
- if (is_static_call) {
- CompiledStaticCall* ssc = caller_nm->compiledStaticCall_at(call_addr);
- if (!ssc->is_clean()) {
- return ssc->set_to_clean();
- }
- } else {
- // compiled, dispatched call (which used to call an interpreted method)
- CompiledIC* inline_cache = CompiledIC_at(caller_nm, call_addr);
- if (!inline_cache->is_clean()) {
- return inline_cache->set_to_clean();
- }
- }
- return true;
+ CompiledIC* inline_cache = CompiledIC_before(caller_nm, caller_frame.pc());
+ inline_cache->update(&call_info, receiver()->klass());
+
+ return callee_method;
}
//
@@ -1894,8 +1638,6 @@ methodHandle SharedRuntime::reresolve_call_site(TRAPS) {
address pc = caller.pc();
- // Check for static or virtual call
- bool is_static_call = false;
CompiledMethod* caller_nm = CodeCache::find_compiled(pc);
// Default call_addr is the location of the "basic" call.
@@ -1916,46 +1658,29 @@ methodHandle SharedRuntime::reresolve_call_site(TRAPS) {
// we jump to it the target gets deoptimized. Similar to 1
// we will wind up in the interprter (thru a c2i with c2).
//
- address call_addr = nullptr;
- {
- // Get call instruction under lock because another thread may be
- // busy patching it.
- CompiledICLocker ml(caller_nm);
- // Location of call instruction
- call_addr = caller_nm->call_instruction_address(pc);
- }
+ CompiledICLocker ml(caller_nm);
+ address call_addr = caller_nm->call_instruction_address(pc);
- // Check relocations for the matching call to 1) avoid false positives,
- // and 2) determine the type.
if (call_addr != nullptr) {
// On x86 the logic for finding a call instruction is blindly checking for a call opcode 5
// bytes back in the instruction stream so we must also check for reloc info.
RelocIterator iter(caller_nm, call_addr, call_addr+1);
bool ret = iter.next(); // Get item
if (ret) {
- bool is_static_call = false;
switch (iter.type()) {
case relocInfo::static_call_type:
- is_static_call = true;
-
- case relocInfo::virtual_call_type:
- case relocInfo::opt_virtual_call_type:
- // Cleaning the inline cache will force a new resolve. This is more robust
- // than directly setting it to the new destination, since resolving of calls
- // is always done through the same code path. (experience shows that it
- // leads to very hard to track down bugs, if an inline cache gets updated
- // to a wrong method). It should not be performance critical, since the
- // resolve is only done once.
- guarantee(iter.addr() == call_addr, "must find call");
- for (;;) {
- ICRefillVerifier ic_refill_verifier;
- if (!clear_ic_at_addr(caller_nm, call_addr, is_static_call)) {
- InlineCacheBuffer::refill_ic_stubs();
- } else {
- break;
- }
- }
+ case relocInfo::opt_virtual_call_type: {
+ CompiledDirectCall* cdc = CompiledDirectCall::at(call_addr);
+ cdc->set_to_clean();
+ break;
+ }
+
+ case relocInfo::virtual_call_type: {
+ // compiled, dispatched call (which used to call an interpreted method)
+ CompiledIC* inline_cache = CompiledIC_at(caller_nm, call_addr);
+ inline_cache->set_to_clean();
break;
+ }
default:
break;
}
@@ -2019,37 +1744,6 @@ void SharedRuntime::check_member_name_argument_is_last_argument(const methodHand
}
#endif
-bool SharedRuntime::should_fixup_call_destination(address destination, address entry_point, address caller_pc, Method* moop, CodeBlob* cb) {
- if (destination != entry_point) {
- CodeBlob* callee = CodeCache::find_blob(destination);
- // callee == cb seems weird. It means calling interpreter thru stub.
- if (callee != nullptr && (callee == cb || callee->is_adapter_blob())) {
- // static call or optimized virtual
- if (TraceCallFixup) {
- tty->print("fixup callsite at " INTPTR_FORMAT " to compiled code for", p2i(caller_pc));
- moop->print_short_name(tty);
- tty->print_cr(" to " INTPTR_FORMAT, p2i(entry_point));
- }
- return true;
- } else {
- if (TraceCallFixup) {
- tty->print("failed to fixup callsite at " INTPTR_FORMAT " to compiled code for", p2i(caller_pc));
- moop->print_short_name(tty);
- tty->print_cr(" to " INTPTR_FORMAT, p2i(entry_point));
- }
- // assert is too strong could also be resolve destinations.
- // assert(InlineCacheBuffer::contains(destination) || VtableStubs::contains(destination), "must be");
- }
- } else {
- if (TraceCallFixup) {
- tty->print("already patched callsite at " INTPTR_FORMAT " to compiled code for", p2i(caller_pc));
- moop->print_short_name(tty);
- tty->print_cr(" to " INTPTR_FORMAT, p2i(entry_point));
- }
- }
- return false;
-}
-
// ---------------------------------------------------------------------------
// We are calling the interpreter via a c2i. Normally this would mean that
// we were called by a compiled method. However we could have lost a race
@@ -2057,8 +1751,6 @@ bool SharedRuntime::should_fixup_call_destination(address destination, address e
// interpreted. If the caller is compiled we attempt to patch the caller
// so he no longer calls into the interpreter.
JRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address caller_pc))
- Method* moop(method);
-
AARCH64_PORT_ONLY(assert(pauth_ptr_is_raw(caller_pc), "should be raw"));
// It's possible that deoptimization can occur at a call site which hasn't
@@ -2074,7 +1766,7 @@ JRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address cal
// Result from nmethod::is_unloading is not stable across safepoints.
NoSafepointVerifier nsv;
- CompiledMethod* callee = moop->code();
+ CompiledMethod* callee = method->code();
if (callee == nullptr) {
return;
}
@@ -2083,65 +1775,41 @@ JRT_LEAF(void, SharedRuntime::fixup_callers_callsite(Method* method, address cal
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, JavaThread::current()));
CodeBlob* cb = CodeCache::find_blob(caller_pc);
- if (cb == nullptr || !cb->is_compiled() || callee->is_unloading()) {
+ if (cb == nullptr || !cb->is_compiled() || !callee->is_in_use() || callee->is_unloading()) {
return;
}
// The check above makes sure this is a nmethod.
- CompiledMethod* nm = cb->as_compiled_method_or_null();
- assert(nm, "must be");
+ CompiledMethod* caller = cb->as_compiled_method();
// Get the return PC for the passed caller PC.
address return_pc = caller_pc + frame::pc_return_offset;
- // There is a benign race here. We could be attempting to patch to a compiled
- // entry point at the same time the callee is being deoptimized. If that is
- // the case then entry_point may in fact point to a c2i and we'd patch the
- // call site with the same old data. clear_code will set code() to null
- // at the end of it. If we happen to see that null then we can skip trying
- // to patch. If we hit the window where the callee has a c2i in the
- // from_compiled_entry and the null isn't present yet then we lose the race
- // and patch the code with the same old data. Asi es la vida.
-
- if (moop->code() == nullptr) return;
-
- if (nm->is_in_use()) {
- // Expect to find a native call there (unless it was no-inline cache vtable dispatch)
- CompiledICLocker ic_locker(nm);
- if (NativeCall::is_call_before(return_pc)) {
- ResourceMark mark;
- NativeCallWrapper* call = nm->call_wrapper_before(return_pc);
- //
- // bug 6281185. We might get here after resolving a call site to a vanilla
- // virtual call. Because the resolvee uses the verified entry it may then
- // see compiled code and attempt to patch the site by calling us. This would
- // then incorrectly convert the call site to optimized and its downhill from
- // there. If you're lucky you'll get the assert in the bugid, if not you've
- // just made a call site that could be megamorphic into a monomorphic site
- // for the rest of its life! Just another racing bug in the life of
- // fixup_callers_callsite ...
- //
- RelocIterator iter(nm, call->instruction_address(), call->next_instruction_address());
- iter.next();
- assert(iter.has_current(), "must have a reloc at java call site");
- relocInfo::relocType typ = iter.reloc()->type();
- if (typ != relocInfo::static_call_type &&
- typ != relocInfo::opt_virtual_call_type &&
- typ != relocInfo::static_stub_type) {
- return;
- }
- if (nm->method()->is_continuation_enter_intrinsic()) {
- if (ContinuationEntry::is_interpreted_call(call->instruction_address())) {
- return;
- }
- }
- address destination = call->destination();
- address entry_point = callee->verified_entry_point();
- if (should_fixup_call_destination(destination, entry_point, caller_pc, moop, cb)) {
- call->set_destination_mt_safe(entry_point);
- }
- }
+ if (!caller->is_in_use() || !NativeCall::is_call_before(return_pc)) {
+ return;
+ }
+
+ // Expect to find a native call there (unless it was no-inline cache vtable dispatch)
+ CompiledICLocker ic_locker(caller);
+ ResourceMark rm;
+
+ // If we got here through a static call or opt_virtual call, then we know where the
+ // call address would be; let's peek at it
+ address callsite_addr = (address)nativeCall_before(return_pc);
+ RelocIterator iter(caller, callsite_addr, callsite_addr + 1);
+ if (!iter.next()) {
+ // No reloc entry found; not a static or optimized virtual call
+ return;
}
+
+ relocInfo::relocType type = iter.reloc()->type();
+ if (type != relocInfo::static_call_type &&
+ type != relocInfo::opt_virtual_call_type) {
+ return;
+ }
+
+ CompiledDirectCall* callsite = CompiledDirectCall::before(return_pc);
+ callsite->set_to_clean();
JRT_END
@@ -3407,8 +3075,8 @@ frame SharedRuntime::look_for_reserved_stack_annotated_method(JavaThread* curren
method = sd->method();
if (method != nullptr && method->has_reserved_stack_access()) {
found = true;
- }
- }
+ }
+ }
}
}
if (found) {
diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp
index 663714dc7fcbe..9d259616bd936 100644
--- a/src/hotspot/share/runtime/sharedRuntime.hpp
+++ b/src/hotspot/share/runtime/sharedRuntime.hpp
@@ -46,9 +46,6 @@ class SharedRuntime: AllStatic {
friend class VMStructs;
private:
- static bool resolve_sub_helper_internal(methodHandle callee_method, const frame& caller_frame,
- CompiledMethod* caller_nm, bool is_virtual, bool is_optimized,
- Handle receiver, CallInfo& call_info, Bytecodes::Code invoke_code, TRAPS);
static methodHandle resolve_sub_helper(bool is_virtual, bool is_optimized, TRAPS);
// Shared stub locations
diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp
index 19db6f61e5666..3ddb9619d72ad 100644
--- a/src/hotspot/share/runtime/vmStructs.cpp
+++ b/src/hotspot/share/runtime/vmStructs.cpp
@@ -40,6 +40,7 @@
#include "classfile/vmSymbols.hpp"
#include "code/codeBlob.hpp"
#include "code/codeCache.hpp"
+#include "code/compiledIC.hpp"
#include "code/compressedStream.hpp"
#include "code/location.hpp"
#include "code/nmethod.hpp"
@@ -63,7 +64,6 @@
#include "oops/array.hpp"
#include "oops/arrayKlass.hpp"
#include "oops/arrayOop.hpp"
-#include "oops/compiledICHolder.hpp"
#include "oops/constMethod.hpp"
#include "oops/constantPool.hpp"
#include "oops/cpCache.hpp"
@@ -211,8 +211,6 @@
nonstatic_field(ArrayKlass, _dimension, int) \
volatile_nonstatic_field(ArrayKlass, _higher_dimension, ObjArrayKlass*) \
volatile_nonstatic_field(ArrayKlass, _lower_dimension, ArrayKlass*) \
- nonstatic_field(CompiledICHolder, _holder_metadata, Metadata*) \
- nonstatic_field(CompiledICHolder, _holder_klass, Klass*) \
nonstatic_field(ConstantPool, _tags, Array*) \
nonstatic_field(ConstantPool, _cache, ConstantPoolCache*) \
nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \
@@ -1162,7 +1160,6 @@
/* MetadataOopDesc hierarchy (NOTE: some missing) */ \
/**************************************************/ \
\
- declare_toplevel_type(CompiledICHolder) \
declare_toplevel_type(MetaspaceObj) \
declare_type(Metadata, MetaspaceObj) \
declare_type(Klass, Metadata) \
diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp
index d39335c6307f4..913d1ba4ce4fc 100644
--- a/src/hotspot/share/utilities/debug.cpp
+++ b/src/hotspot/share/utilities/debug.cpp
@@ -26,7 +26,6 @@
#include "classfile/classPrinter.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
-#include "code/icBuffer.hpp"
#include "code/nmethod.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/CompiledICHolder.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/CompiledICHolder.java
deleted file mode 100644
index 1d1a9278abddf..0000000000000
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/CompiledICHolder.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2000, 2022, 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 sun.jvm.hotspot.oops;
-
-import java.io.*;
-import java.util.*;
-import sun.jvm.hotspot.debugger.*;
-import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.types.*;
-import sun.jvm.hotspot.utilities.Observable;
-import sun.jvm.hotspot.utilities.Observer;
-
-public class CompiledICHolder extends VMObject {
- static {
- VM.registerVMInitializedObserver(new Observer() {
- public void update(Observable o, Object data) {
- initialize(VM.getVM().getTypeDataBase());
- }
- });
- }
-
- private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
- Type type = db.lookupType("CompiledICHolder");
- holderMetadata = new MetadataField(type.getAddressField("_holder_metadata"), 0);
- holderKlass = new MetadataField(type.getAddressField("_holder_klass"), 0);
- headerSize = type.getSize();
- }
-
- public CompiledICHolder(Address addr) {
- super(addr);
- }
-
- public boolean isCompiledICHolder() { return true; }
-
- private static long headerSize;
-
- // Fields
- private static MetadataField holderMetadata;
- private static MetadataField holderKlass;
-
- // Accessors for declared fields
- public Metadata getHolderMetadata() { return holderMetadata.getValue(this); }
- public Klass getHolderKlass() { return (Klass) holderKlass.getValue(this); }
-
- public void printValueOn(PrintStream tty) {
- tty.print("CompiledICHolder");
- }
- }
diff --git a/test/hotspot/jtreg/runtime/logging/SafepointCleanupTest.java b/test/hotspot/jtreg/runtime/logging/SafepointCleanupTest.java
index d4ec877f19bb6..0586bf29989d9 100644
--- a/test/hotspot/jtreg/runtime/logging/SafepointCleanupTest.java
+++ b/test/hotspot/jtreg/runtime/logging/SafepointCleanupTest.java
@@ -40,7 +40,6 @@ static void analyzeOutputOn(ProcessBuilder pb) throws Exception {
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("[safepoint,cleanup]");
output.shouldContain("safepoint cleanup tasks");
- output.shouldContain("updating inline caches");
output.shouldHaveExitValue(0);
}
diff --git a/test/jdk/jdk/jfr/event/runtime/TestSafepointEvents.java b/test/jdk/jdk/jfr/event/runtime/TestSafepointEvents.java
index 285592bce1699..6b165375383ea 100644
--- a/test/jdk/jdk/jfr/event/runtime/TestSafepointEvents.java
+++ b/test/jdk/jdk/jfr/event/runtime/TestSafepointEvents.java
@@ -52,8 +52,8 @@ public class TestSafepointEvents {
static final String[] EVENT_NAMES = new String[] {
EventNames.SafepointBegin,
EventNames.SafepointStateSynchronization,
+ // EventNames.SafepointCleanupTask,
EventNames.SafepointCleanup,
- EventNames.SafepointCleanupTask,
EventNames.SafepointEnd
};
From 8dc59763ebe403f46e395043c91a11d8542f58e1 Mon Sep 17 00:00:00 2001
From: Erik Gahlin
Date: Wed, 14 Feb 2024 13:02:13 +0000
Subject: [PATCH 28/36] 8325809: JFR: Remove unnecessary annotation
Reviewed-by: mgronlun
---
.../share/classes/jdk/jfr/events/ActiveRecordingEvent.java | 3 +--
.../share/classes/jdk/jfr/events/ActiveSettingEvent.java | 3 +--
.../share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java | 3 +--
3 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveRecordingEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveRecordingEvent.java
index 985b5c61fb579..352a8b6a07397 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveRecordingEvent.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveRecordingEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -38,7 +38,6 @@
@Name(Type.EVENT_NAME_PREFIX + "ActiveRecording")
@Label("Flight Recording")
@Category("Flight Recorder")
-@StackTrace(false)
@RemoveFields({"duration", "eventThread", "stackTrace"})
public final class ActiveRecordingEvent extends AbstractJDKEvent {
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveSettingEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveSettingEvent.java
index d751580fa3aa1..3658b06eb14a8 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveSettingEvent.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ActiveSettingEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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,7 +35,6 @@
@Name(Type.EVENT_NAME_PREFIX + "ActiveSetting")
@Label("Recording Setting")
@Category("Flight Recorder")
-@StackTrace(false)
@RemoveFields({"duration", "eventThread", "stackTrace"})
public final class ActiveSettingEvent extends AbstractJDKEvent {
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java
index a5d3f485fad20..cdaa6372f68c7 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionStatisticsEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -38,7 +38,6 @@
@Category({ "Java Application", "Statistics" })
@Description("Number of objects derived from java.lang.Throwable that have been created")
@MirrorEvent(className = "jdk.internal.event.ExceptionStatisticsEvent")
-@StackTrace(false)
public final class ExceptionStatisticsEvent extends AbstractPeriodicEvent {
@Label("Exceptions Created")
From 61f249335d4182544954788534db8a5dde27922c Mon Sep 17 00:00:00 2001
From: Albert Mingkun Yang
Date: Wed, 14 Feb 2024 13:17:10 +0000
Subject: [PATCH 29/36] 8325767: Serial: Move transform_stack_chunk out of
TenuredGeneration::promote
Reviewed-by: stefank
---
src/hotspot/share/gc/serial/defNewGeneration.cpp | 3 +++
src/hotspot/share/gc/serial/tenuredGeneration.cpp | 5 -----
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp
index 52858683c0887..3f1cc7c6e4f93 100644
--- a/src/hotspot/share/gc/serial/defNewGeneration.cpp
+++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp
@@ -862,6 +862,9 @@ oop DefNewGeneration::copy_to_survivor_space(oop old) {
handle_promotion_failure(old);
return old;
}
+
+ ContinuationGCSupport::transform_stack_chunk(obj);
+
new_obj_is_tenured = true;
} else {
// Prefetch beyond obj
diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp
index 508ee971c5f7a..fe37d9975498a 100644
--- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp
+++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp
@@ -29,7 +29,6 @@
#include "gc/serial/serialHeap.hpp"
#include "gc/serial/tenuredGeneration.inline.hpp"
#include "gc/shared/collectorCounters.hpp"
-#include "gc/shared/continuationGCSupport.inline.hpp"
#include "gc/shared/gcLocker.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTrace.hpp"
@@ -436,10 +435,6 @@ oop TenuredGeneration::promote(oop obj, size_t obj_size) {
// Copy to new location.
Copy::aligned_disjoint_words(cast_from_oop(obj), result, obj_size);
oop new_obj = cast_to_oop(result);
-
- // Transform object if it is a stack chunk.
- ContinuationGCSupport::transform_stack_chunk(new_obj);
-
return new_obj;
}
From 737b4c515e082239579369d9806307b9f16c4816 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?=
Date: Wed, 14 Feb 2024 14:10:28 +0000
Subject: [PATCH 30/36] 8323883: JFR AssertionError: Missing object ID 15101
Reviewed-by: egahlin
---
src/hotspot/share/jfr/jni/jfrJniMethod.cpp | 6 +-
.../checkpoint/objectSampleCheckpoint.cpp | 12 +++-
.../leakprofiler/sampling/objectSample.cpp | 6 +-
.../recorder/checkpoint/types/jfrTypeSet.cpp | 71 +++++++++----------
.../checkpoint/types/jfrTypeSetUtils.cpp | 17 +----
.../checkpoint/types/jfrTypeSetUtils.hpp | 39 +++++-----
.../checkpoint/types/traceid/jfrTraceId.hpp | 3 +-
.../types/traceid/jfrTraceId.inline.hpp | 6 +-
.../types/traceid/jfrTraceIdLoadBarrier.hpp | 3 +-
.../traceid/jfrTraceIdLoadBarrier.inline.hpp | 11 ++-
.../recorder/service/jfrRecorderService.cpp | 14 +++-
.../recorder/service/jfrRecorderService.hpp | 3 +-
.../share/jfr/support/jfrTraceIdExtension.hpp | 6 +-
.../share/prims/jvmtiRedefineClasses.cpp | 3 +
.../jfr/internal/consumer/ConstantMap.java | 3 +-
15 files changed, 118 insertions(+), 85 deletions(-)
diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp
index db534b6df3c43..eee46cbbdde21 100644
--- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp
+++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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,6 +36,7 @@
#include "jfr/recorder/repository/jfrEmergencyDump.hpp"
#include "jfr/recorder/service/jfrEventThrottler.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp"
+#include "jfr/recorder/service/jfrRecorderService.hpp"
#include "jfr/recorder/stacktrace/jfrStackFilter.hpp"
#include "jfr/recorder/stacktrace/jfrStackFilterRegistry.hpp"
#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
@@ -348,7 +349,8 @@ JVM_ENTRY_NO_ENV(void, jfr_set_force_instrumentation(JNIEnv* env, jclass jvm, jb
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_emit_old_object_samples(JNIEnv* env, jclass jvm, jlong cutoff_ticks, jboolean emit_all, jboolean skip_bfs))
- LeakProfiler::emit_events(cutoff_ticks, emit_all == JNI_TRUE, skip_bfs == JNI_TRUE);
+ JfrRecorderService service;
+ service.emit_leakprofiler_events(cutoff_ticks, emit_all == JNI_TRUE, skip_bfs == JNI_TRUE);
JVM_END
JVM_ENTRY_NO_ENV(void, jfr_exclude_thread(JNIEnv* env, jclass jvm, jobject t))
diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp
index 9f6679c93ebfc..6a1bbfaf83f67 100644
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -205,6 +205,15 @@ static bool stack_trace_precondition(const ObjectSample* sample) {
return sample->has_stack_trace_id() && !sample->is_dead();
}
+static void add_to_leakp_set(const ObjectSample* sample) {
+ assert(sample != nullptr, "invariant");
+ oop object = sample->object();
+ if (object == nullptr) {
+ return;
+ }
+ JfrTraceId::load_leakp(object->klass());
+}
+
class StackTraceBlobInstaller {
private:
BlobCache _cache;
@@ -219,6 +228,7 @@ class StackTraceBlobInstaller {
}
void sample_do(ObjectSample* sample) {
if (stack_trace_precondition(sample)) {
+ add_to_leakp_set(sample);
install(sample);
}
}
diff --git a/src/hotspot/share/jfr/leakprofiler/sampling/objectSample.cpp b/src/hotspot/share/jfr/leakprofiler/sampling/objectSample.cpp
index a732191af3d13..21d3338f51528 100644
--- a/src/hotspot/share/jfr/leakprofiler/sampling/objectSample.cpp
+++ b/src/hotspot/share/jfr/leakprofiler/sampling/objectSample.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
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "jfr/leakprofiler/sampling/objectSample.hpp"
#include "jfr/leakprofiler/sampling/objectSampler.hpp"
+#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
#include "oops/weakHandle.inline.hpp"
#include "runtime/handles.inline.hpp"
@@ -36,7 +37,7 @@ void ObjectSample::reset() {
}
oop ObjectSample::object() const {
- return _object.resolve();
+ return is_dead() ? nullptr :_object.resolve();
}
bool ObjectSample::is_dead() const {
@@ -48,6 +49,7 @@ const oop* ObjectSample::object_addr() const {
}
void ObjectSample::set_object(oop object) {
+ assert(object != nullptr, "invariant");
assert(_object.is_empty(), "should be empty");
Handle h(Thread::current(), object);
_object = WeakHandle(ObjectSampler::oop_storage(), h);
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
index 3a86f204e619d..31a4c3f25e9cb 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -126,7 +126,6 @@ static traceid artifact_tag(const T* ptr, bool leakp) {
SET_LEAKP(ptr);
}
assert(IS_LEAKP(ptr), "invariant");
- return artifact_id(ptr);
}
if (not_used(ptr)) {
SET_TRANSIENT(ptr);
@@ -153,7 +152,7 @@ static inline bool should_do_cld_klass(const Klass* cld_klass, bool leakp) {
static inline bool should_enqueue(const Klass* cld_klass) {
assert(cld_klass != nullptr, "invariant");
- if (previous_epoch()) {
+ if (unloading() || previous_epoch()) {
return false;
}
CldPtr cld = get_cld(cld_klass);
@@ -253,7 +252,11 @@ class ModuleFieldSelector {
static TypePtr select(KlassPtr klass) {
assert(klass != nullptr, "invariant");
PkgPtr pkg = klass->package();
- return pkg != nullptr ? pkg->module() : nullptr;
+ if (pkg == nullptr) {
+ return nullptr;
+ }
+ assert(current_epoch() ? IS_SERIALIZED(pkg) : true, "invariant");
+ return pkg->module();
}
};
@@ -272,7 +275,11 @@ class ModuleCldFieldSelector {
static TypePtr select(KlassPtr klass) {
assert(klass != nullptr, "invariant");
ModPtr mod = ModuleFieldSelector::select(klass);
- return mod != nullptr ? mod->loader_data() : nullptr;
+ if (mod == nullptr) {
+ return nullptr;
+ }
+ assert(current_epoch() ? IS_SERIALIZED(mod) : true, "invariant");
+ return mod->loader_data();
}
};
@@ -283,18 +290,7 @@ class SerializePredicate {
SerializePredicate(bool class_unload) : _class_unload(class_unload) {}
bool operator()(T const& value) {
assert(value != nullptr, "invariant");
- return _class_unload ? _artifacts->should_do_unloading_artifact(value) : IS_NOT_SERIALIZED(value);
- }
-};
-
-template <>
-class SerializePredicate {
- bool _class_unload;
-public:
- SerializePredicate(bool class_unload) : _class_unload(class_unload) {}
- bool operator()(const Klass* klass) {
- assert(klass != nullptr, "invariant");
- return _class_unload ? true : IS_NOT_SERIALIZED(klass);
+ return _class_unload ? true : IS_NOT_SERIALIZED(value);
}
};
@@ -352,13 +348,19 @@ static void do_write_klass(JfrCheckpointWriter* writer, CldPtr cld, KlassPtr kla
writer->write(package_id(klass, leakp));
writer->write(klass->modifier_flags());
writer->write(klass->is_hidden());
- if (!leakp) {
- set_serialized(klass);
+ if (leakp) {
+ assert(IS_LEAKP(klass), "invariant");
+ CLEAR_LEAKP(klass);
+ assert(IS_NOT_LEAKP(klass), "invariant");
+ return;
}
+ assert(used(klass), "invariant");
+ assert(unloading() ? true : IS_NOT_SERIALIZED(klass), "invariant");
+ set_serialized(klass);
}
static inline bool should_write_cld_klass(KlassPtr klass, bool leakp) {
- return klass != nullptr && (leakp || IS_NOT_SERIALIZED(klass));
+ return klass != nullptr && (leakp ? IS_LEAKP(klass) : unloading() ? true : IS_NOT_SERIALIZED(klass));
}
static void write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp, int& elements) {
@@ -373,10 +375,10 @@ static void write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp,
write_klass(writer, cld_klass, leakp, elements);
}
}
- KlassPtr mod_klass = get_module_cld_klass(klass, leakp);
- if (should_write_cld_klass(mod_klass, leakp)) {
+ KlassPtr mod_cld_klass = get_module_cld_klass(klass, leakp);
+ if (should_write_cld_klass(mod_cld_klass, leakp)) {
// Write the klass for the module cld.
- write_klass(writer, mod_klass, leakp, elements);
+ write_klass(writer, mod_cld_klass, leakp, elements);
}
}
@@ -398,7 +400,6 @@ int write__klass(JfrCheckpointWriter* writer, const void* k) {
int write__klass__leakp(JfrCheckpointWriter* writer, const void* k) {
assert(k != nullptr, "invariant");
KlassPtr klass = static_cast(k);
- CLEAR_LEAKP(klass);
int elements = 0;
write_klass(writer, klass, true, elements);
return elements;
@@ -978,15 +979,12 @@ class MethodIteratorHost {
MethodUsedPredicate _method_used_predicate;
MethodFlagPredicate _method_flag_predicate;
public:
- MethodIteratorHost(JfrCheckpointWriter* writer,
- bool current_epoch = false,
- bool class_unload = false,
- bool skip_header = false) :
- _method_cb(writer, class_unload, skip_header),
- _klass_cb(writer, class_unload, skip_header),
- _klass_used_predicate(current_epoch),
- _method_used_predicate(current_epoch),
- _method_flag_predicate(current_epoch) {}
+ MethodIteratorHost(JfrCheckpointWriter* writer) :
+ _method_cb(writer, unloading(), false),
+ _klass_cb(writer, unloading(), false),
+ _klass_used_predicate(current_epoch()),
+ _method_used_predicate(current_epoch()),
+ _method_flag_predicate(current_epoch()) {}
bool operator()(KlassPtr klass) {
if (_method_used_predicate(klass)) {
@@ -1037,14 +1035,13 @@ typedef LeakPredicate LeakMethodPredicate;
typedef JfrPredicatedTypeWriterImplHost LeakMethodWriterImplTarget;
typedef JfrTypeWriterHost LeakMethodWriterImpl;
typedef MethodIteratorHost LeakMethodWriter;
-typedef MethodIteratorHost LeakMethodWriter;
typedef CompositeFunctor CompositeMethodWriter;
static void write_methods_with_leakp(MethodWriter& mw) {
assert(_writer != nullptr, "invariant");
assert(_leakp_writer != nullptr, "invariant");
assert(previous_epoch(), "invariant");
- LeakMethodWriter lpmw(_leakp_writer, current_epoch(), unloading());
+ LeakMethodWriter lpmw(_leakp_writer);
CompositeMethodWriter cmw(&lpmw, &mw);
_artifacts->iterate_klasses(cmw);
_artifacts->tally(mw);
@@ -1052,7 +1049,7 @@ static void write_methods_with_leakp(MethodWriter& mw) {
static void write_methods() {
assert(_writer != nullptr, "invariant");
- MethodWriter mw(_writer, current_epoch(), unloading());
+ MethodWriter mw(_writer);
if (_leakp_writer == nullptr) {
_artifacts->iterate_klasses(mw);
_artifacts->tally(mw);
@@ -1065,7 +1062,7 @@ static void write_methods_on_clear() {
assert(_writer != nullptr, "invariant");
assert(_leakp_writer != nullptr, "invariant");
assert(previous_epoch(), "invariant");
- MethodWriter mw(_writer, current_epoch(), unloading());
+ MethodWriter mw(_writer);
write_methods_with_leakp(mw);
}
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp
index 883821f853c0a..3db940156a800 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -54,10 +54,6 @@ void JfrArtifactSet::initialize(bool class_unload) {
_klass_list = new GrowableArray(initial_klass_list_size);
_klass_loader_set = new GrowableArray(initial_klass_loader_set_size);
_klass_loader_leakp_set = new GrowableArray(initial_klass_loader_set_size);
-
- if (class_unload) {
- _unloading_set = new GrowableArray(initial_klass_list_size);
- }
}
void JfrArtifactSet::clear() {
@@ -117,18 +113,9 @@ bool JfrArtifactSet::should_do_cld_klass(const Klass* k, bool leakp) {
return not_in_set(leakp ? _klass_loader_leakp_set : _klass_loader_set, k);
}
-bool JfrArtifactSet::should_do_unloading_artifact(const void* ptr) {
- assert(ptr != nullptr, "invariant");
- assert(_class_unload, "invariant");
- assert(_unloading_set != nullptr, "invariant");
- // The incoming pointers are of all kinds of different types.
- // However, we are only interested in set membership.
- // Treat them uniformly as const Klass* for simplicity and code reuse.
- return not_in_set(_unloading_set, static_cast(ptr));
-}
-
void JfrArtifactSet::register_klass(const Klass* k) {
assert(k != nullptr, "invariant");
+ assert(IS_SERIALIZED(k), "invariant");
assert(_klass_list != nullptr, "invariant");
_klass_list->append(k);
}
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp
index 24424fdef3aa9..237745b13d93e 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -80,6 +80,7 @@ class KlassToFieldEnvelope {
public:
KlassToFieldEnvelope(Letter* letter) : _letter(letter) {}
bool operator()(const Klass* klass) {
+ assert(IS_SERIALIZED(klass), "invariant");
typename FieldSelector::TypePtr t = FieldSelector::select(klass);
return t != nullptr ? (*_letter)(t) : true;
}
@@ -130,7 +131,7 @@ class SymbolPredicate {
class KlassUsedPredicate {
bool _current_epoch;
-public:
+ public:
KlassUsedPredicate(bool current_epoch) : _current_epoch(current_epoch) {}
bool operator()(const Klass* klass) {
return _current_epoch ? USED_THIS_EPOCH(klass) : USED_PREVIOUS_EPOCH(klass);
@@ -201,7 +202,6 @@ class JfrArtifactSet : public JfrCHeapObj {
GrowableArray* _klass_list;
GrowableArray* _klass_loader_set;
GrowableArray* _klass_loader_leakp_set;
- GrowableArray* _unloading_set;
size_t _total_count;
bool _class_unload;
@@ -229,23 +229,8 @@ class JfrArtifactSet : public JfrCHeapObj {
size_t total_count() const;
void register_klass(const Klass* k);
bool should_do_cld_klass(const Klass* k, bool leakp);
- bool should_do_unloading_artifact(const void* ptr);
void increment_checkpoint_id();
- template
- void iterate_klasses(Functor& functor) const {
- for (int i = 0; i < _klass_list->length(); ++i) {
- if (!functor(_klass_list->at(i))) {
- return;
- }
- }
- for (int i = 0; i < _klass_loader_set->length(); ++i) {
- if (!functor(_klass_loader_set->at(i))) {
- return;
- }
- }
- }
-
template
void iterate_symbols(T& functor) {
_symbol_table->iterate_symbols(functor);
@@ -261,6 +246,24 @@ class JfrArtifactSet : public JfrCHeapObj {
_total_count += writer.count();
}
+ template
+ void iterate_klasses(Functor& functor) const {
+ if (iterate(functor, _klass_list)) {
+ iterate(functor, _klass_loader_set);
+ }
+ }
+
+ private:
+ template
+ bool iterate(Functor& functor, GrowableArray* list) const {
+ assert(list != nullptr, "invariant");
+ for (int i = 0; i < list->length(); ++i) {
+ if (!functor(list->at(i))) {
+ return false;
+ }
+ }
+ return true;
+ }
};
class KlassArtifactRegistrator {
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp
index 36b9d491d30b6..d9211e8cb8c23 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -92,6 +92,7 @@ class JfrTraceId : public AllStatic {
static traceid load(const ModuleEntry* module);
static traceid load(const PackageEntry* package);
static traceid load(const ClassLoaderData* cld);
+ static traceid load_leakp(const Klass* klass); // leak profiler
static traceid load_leakp(const Klass* klass, const Method* method); // leak profiler
static traceid load_leakp_previous_epoch(const Klass* klass, const Method* method); // leak profiler
static traceid load_no_enqueue(const Method* method);
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp
index 4f1ce813ea6f6..aa99a8383eb56 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -68,6 +68,10 @@ inline traceid JfrTraceId::load(const ClassLoaderData* cld) {
return JfrTraceIdLoadBarrier::load(cld);
}
+inline traceid JfrTraceId::load_leakp(const Klass* klass) {
+ return JfrTraceIdLoadBarrier::load_leakp(klass);
+}
+
inline traceid JfrTraceId::load_leakp(const Klass* klass, const Method* method) {
return JfrTraceIdLoadBarrier::load_leakp(klass, method);
}
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp
index 0795c98940e88..ff984d05c19fa 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -87,6 +87,7 @@ class JfrTraceIdLoadBarrier : AllStatic {
static traceid load(const Method* method);
static traceid load(const ModuleEntry* module);
static traceid load(const PackageEntry* package);
+ static traceid load_leakp(const Klass* klass); // leak profiler
static traceid load_leakp(const Klass* klass, const Method* method); // leak profiler
static traceid load_leakp_previuos_epoch(const Klass* klass, const Method* method); // leak profiler
static void do_klasses(void f(Klass*), bool previous_epoch = false);
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp
index 13853e14a1334..ed30233527400 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -82,7 +82,7 @@ inline traceid JfrTraceIdLoadBarrier::load(const Klass* klass) {
if (should_tag(klass)) {
load_barrier(klass);
}
- assert(USED_THIS_EPOCH(klass), "invariant");
+ assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant");
return TRACE_ID(klass);
}
@@ -148,6 +148,13 @@ inline traceid JfrTraceIdLoadBarrier::load(const PackageEntry* package) {
return set_used_and_get(package);
}
+inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass) {
+ assert(klass != nullptr, "invariant");
+ load(klass); // Ensure tagged and enqueued.
+ SET_LEAKP(klass);
+ return TRACE_ID(klass);
+}
+
inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass, const Method* method) {
assert(klass != nullptr, "invariant");
assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant");
diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
index fe674bc961064..a9f0cecb53c11 100644
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -691,3 +691,15 @@ void JfrRecorderService::evaluate_chunk_size_for_rotation() {
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_native(JavaThread::current()));
JfrChunkRotation::evaluate(_chunkwriter);
}
+
+void JfrRecorderService::emit_leakprofiler_events(int64_t cutoff_ticks, bool emit_all, bool skip_bfs) {
+ DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(JavaThread::current()));
+ // Take the rotation lock to exclude flush() during event emits. This is because event emit
+ // also creates a number checkpoint events. Those checkpoint events require a future typeset checkpoint
+ // event for completeness, i.e. to be generated before being flushed to a segment.
+ // The upcoming flush() or rotation() after event emit completes this typeset checkpoint
+ // and serializes all event emit checkpoint events to the same segment.
+ JfrRotationLock lock;
+ LeakProfiler::emit_events(cutoff_ticks, emit_all, skip_bfs);
+}
+
diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp
index 4ba775d8970bd..89c0437dd13bf 100644
--- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp
+++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -70,6 +70,7 @@ class JfrRecorderService : public StackObj {
void flushpoint();
void process_full_buffers();
void evaluate_chunk_size_for_rotation();
+ void emit_leakprofiler_events(int64_t cutoff_ticks, bool emit_all, bool skip_bfs);
static bool is_recording();
};
diff --git a/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp b/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp
index d319e307884f6..353e5c3f07c2b 100644
--- a/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp
+++ b/src/hotspot/share/jfr/support/jfrTraceIdExtension.hpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2012, 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
@@ -95,6 +95,10 @@ class JfrTraceFlag {
} \
uint8_t* trace_meta_addr() const { \
return _trace_flags.meta_addr(); \
+ } \
+ void copy_trace_flags(uint8_t src_flags) const { \
+ uint8_t flags = *_trace_flags.flags_addr(); \
+ _trace_flags.set_flags(flags | src_flags); \
}
#endif // SHARE_JFR_SUPPORT_JFRTRACEIDEXTENSION_HPP
diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
index f6f194fd66f6f..bcfb361c89fa2 100644
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
@@ -48,6 +48,7 @@
#include "oops/fieldStreams.inline.hpp"
#include "oops/klass.inline.hpp"
#include "oops/klassVtable.hpp"
+#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
#include "oops/recordComponent.hpp"
#include "prims/jvmtiImpl.hpp"
@@ -64,6 +65,7 @@
#include "utilities/bitMap.inline.hpp"
#include "utilities/checkedCast.hpp"
#include "utilities/events.hpp"
+#include "utilities/macros.hpp"
Array* VM_RedefineClasses::_old_methods = nullptr;
Array* VM_RedefineClasses::_new_methods = nullptr;
@@ -1171,6 +1173,7 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
}
}
}
+ JFR_ONLY(k_new_method->copy_trace_flags(*k_old_method->trace_flags_addr());)
log_trace(redefine, class, normalize)
("Method matched: new: %s [%d] == old: %s [%d]",
k_new_method->name_and_sig_as_C_string(), ni, k_old_method->name_and_sig_as_C_string(), oi);
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java
index 8ec3a10993da0..3b6859304b86d 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java
@@ -77,8 +77,7 @@ Object get(long id) {
if (id != 0) {
String msg = "Missing object ID " + id + " in pool " + getName() + ". All IDs should reference an object";
Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, msg);
- // Disable assertion until JDK-8323883 is fixed
- // assert false : msg;
+ assert false : msg;
}
return null;
}
From 9c852df6aa019f63d6fae733d7a73521b7151dd0 Mon Sep 17 00:00:00 2001
From: Jorn Vernee
Date: Wed, 14 Feb 2024 14:30:54 +0000
Subject: [PATCH 31/36] 8318966: Some methods make promises about Java array
element alignment that are too strong
Reviewed-by: psandoz, mcimadamore
---
.../java/lang/invoke/MethodHandles.java | 62 +-
.../X-VarHandleByteArrayView.java.template | 512 +-----
.../classes/java/nio/X-Buffer.java.template | 42 +-
.../VarHandleBaseByteArrayTest.java | 5 +-
.../VarHandleTestByteArrayAsChar.java | 276 +---
.../VarHandleTestByteArrayAsDouble.java | 698 +++-----
.../VarHandleTestByteArrayAsFloat.java | 698 +++-----
.../VarHandleTestByteArrayAsInt.java | 944 +++--------
.../VarHandleTestByteArrayAsLong.java | 944 +++--------
.../VarHandleTestByteArrayAsShort.java | 276 +---
...X-VarHandleTestByteArrayView.java.template | 1421 +++++------------
.../jdk/java/nio/Buffer/Basic-X.java.template | 132 +-
test/jdk/java/nio/Buffer/BasicByte.java | 132 +-
test/jdk/java/nio/Buffer/BasicChar.java | 12 -
test/jdk/java/nio/Buffer/BasicDouble.java | 12 -
test/jdk/java/nio/Buffer/BasicFloat.java | 12 -
test/jdk/java/nio/Buffer/BasicInt.java | 12 -
test/jdk/java/nio/Buffer/BasicLong.java | 12 -
test/jdk/java/nio/Buffer/BasicShort.java | 12 -
19 files changed, 1693 insertions(+), 4521 deletions(-)
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 0708ceef3da21..530df86bdd632 100644
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -4513,48 +4513,18 @@ public static VarHandle arrayElementVarHandle(Class> arrayClass) throws Illega
* or greater than the {@code byte[]} array length minus the size (in bytes)
* of {@code T}.
*
- * Access of bytes at an index may be aligned or misaligned for {@code T},
- * with respect to the underlying memory address, {@code A} say, associated
- * with the array and index.
- * If access is misaligned then access for anything other than the
- * {@code get} and {@code set} access modes will result in an
- * {@code IllegalStateException}. In such cases atomic access is only
- * guaranteed with respect to the largest power of two that divides the GCD
- * of {@code A} and the size (in bytes) of {@code T}.
- * If access is aligned then following access modes are supported and are
- * guaranteed to support atomic access:
- *
- * read write access modes for all {@code T}, with the exception of
- * access modes {@code get} and {@code set} for {@code long} and
- * {@code double} on 32-bit platforms.
- * atomic update access modes for {@code int}, {@code long},
- * {@code float} or {@code double}.
- * (Future major platform releases of the JDK may support additional
- * types for certain currently unsupported access modes.)
- * numeric atomic update access modes for {@code int} and {@code long}.
- * (Future major platform releases of the JDK may support additional
- * numeric types for certain currently unsupported access modes.)
- * bitwise atomic update access modes for {@code int} and {@code long}.
- * (Future major platform releases of the JDK may support additional
- * numeric types for certain currently unsupported access modes.)
- *
- *
- * Misaligned access, and therefore atomicity guarantees, may be determined
- * for {@code byte[]} arrays without operating on a specific array. Given
- * an {@code index}, {@code T} and its corresponding boxed type,
- * {@code T_BOX}, misalignment may be determined as follows:
- *
{@code
- * int sizeOfT = T_BOX.BYTES; // size in bytes of T
- * int misalignedAtZeroIndex = ByteBuffer.wrap(new byte[0]).
- * alignmentOffset(0, sizeOfT);
- * int misalignedAtIndex = (misalignedAtZeroIndex + index) % sizeOfT;
- * boolean isMisaligned = misalignedAtIndex != 0;
- * }
- *
- * If the variable type is {@code float} or {@code double} then atomic
- * update access modes compare values using their bitwise representation
- * (see {@link Float#floatToRawIntBits} and
- * {@link Double#doubleToRawLongBits}, respectively).
+ * Only plain {@linkplain VarHandle.AccessMode#GET get} and {@linkplain VarHandle.AccessMode#SET set}
+ * access modes are supported by the returned var handle. For all other access modes, an
+ * {@link UnsupportedOperationException} will be thrown.
+ *
+ * @apiNote if access modes other than plain access are required, clients should
+ * consider using off-heap memory through
+ * {@linkplain java.nio.ByteBuffer#allocateDirect(int) direct byte buffers} or
+ * off-heap {@linkplain java.lang.foreign.MemorySegment memory segments},
+ * or memory segments backed by a
+ * {@linkplain java.lang.foreign.MemorySegment#ofArray(long[]) {@code long[]}},
+ * for which stronger alignment guarantees can be made.
+ *
* @param viewArrayClass the view array class, with a component type of
* type {@code T}
* @param byteOrder the endianness of the view array elements, as
@@ -4600,7 +4570,13 @@ public static VarHandle byteArrayViewVarHandle(Class> viewArrayClass,
* or greater than the {@code ByteBuffer} limit minus the size (in bytes) of
* {@code T}.
*
- * Access of bytes at an index may be aligned or misaligned for {@code T},
+ * For heap byte buffers, access is always unaligned. As a result, only the plain
+ * {@linkplain VarHandle.AccessMode#GET get}
+ * and {@linkplain VarHandle.AccessMode#SET set} access modes are supported by the
+ * returned var handle. For all other access modes, an {@link IllegalStateException}
+ * will be thrown.
+ *
+ * For direct buffers only, access of bytes at an index may be aligned or misaligned for {@code T},
* with respect to the underlying memory address, {@code A} say, associated
* with the {@code ByteBuffer} and index.
* If access is misaligned then access for anything other than the
diff --git a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template
index 08495f2e58d42..995cb38e3ca1e 100644
--- a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template
+++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template
@@ -49,7 +49,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
static final int ALIGN = $BoxType$.BYTES - 1;
-
+
static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
#if[floatingPoint]
@@ -115,14 +115,6 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
return Preconditions.checkIndex(index, ba.length - ALIGN, Preconditions.AIOOBE_FORMATTER);
}
- @ForceInline
- static long address(byte[] ba, int index) {
- long address = ((long) index) + Unsafe.ARRAY_BYTE_BASE_OFFSET;
- if ((address & ALIGN) != 0)
- throw newIllegalStateExceptionForMisalignedAccess(index);
- return address;
- }
-
@ForceInline
static $type$ get(VarHandle ob, Object oba, int index) {
ArrayHandle handle = (ArrayHandle)ob;
@@ -160,419 +152,6 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
#end[floatingPoint]
}
- @ForceInline
- static $type$ getVolatile(VarHandle ob, Object oba, int index) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- return convEndian(handle.be,
- UNSAFE.get$RawType$Volatile(
- ba,
- address(ba, index(ba, index))));
- }
-
- @ForceInline
- static void setVolatile(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- UNSAFE.put$RawType$Volatile(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, value));
- }
-
- @ForceInline
- static $type$ getAcquire(VarHandle ob, Object oba, int index) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- return convEndian(handle.be,
- UNSAFE.get$RawType$Acquire(
- ba,
- address(ba, index(ba, index))));
- }
-
- @ForceInline
- static void setRelease(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- UNSAFE.put$RawType$Release(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, value));
- }
-
- @ForceInline
- static $type$ getOpaque(VarHandle ob, Object oba, int index) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- return convEndian(handle.be,
- UNSAFE.get$RawType$Opaque(
- ba,
- address(ba, index(ba, index))));
- }
-
- @ForceInline
- static void setOpaque(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- UNSAFE.put$RawType$Opaque(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, value));
- }
-#if[CAS]
-
- @ForceInline
- static boolean compareAndSet(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
-#if[Object]
- return UNSAFE.compareAndSetReference(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, expected), convEndian(handle.be, value));
-#else[Object]
- return UNSAFE.compareAndSet$RawType$(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, expected), convEndian(handle.be, value));
-#end[Object]
- }
-
- @ForceInline
- static $type$ compareAndExchange(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- return convEndian(handle.be,
- UNSAFE.compareAndExchange$RawType$(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, expected), convEndian(handle.be, value)));
- }
-
- @ForceInline
- static $type$ compareAndExchangeAcquire(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- return convEndian(handle.be,
- UNSAFE.compareAndExchange$RawType$Acquire(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, expected), convEndian(handle.be, value)));
- }
-
- @ForceInline
- static $type$ compareAndExchangeRelease(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- return convEndian(handle.be,
- UNSAFE.compareAndExchange$RawType$Release(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, expected), convEndian(handle.be, value)));
- }
-
- @ForceInline
- static boolean weakCompareAndSetPlain(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- return UNSAFE.weakCompareAndSet$RawType$Plain(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, expected), convEndian(handle.be, value));
- }
-
- @ForceInline
- static boolean weakCompareAndSet(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- return UNSAFE.weakCompareAndSet$RawType$(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, expected), convEndian(handle.be, value));
- }
-
- @ForceInline
- static boolean weakCompareAndSetAcquire(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- return UNSAFE.weakCompareAndSet$RawType$Acquire(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, expected), convEndian(handle.be, value));
- }
-
- @ForceInline
- static boolean weakCompareAndSetRelease(VarHandle ob, Object oba, int index, $type$ expected, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- return UNSAFE.weakCompareAndSet$RawType$Release(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, expected), convEndian(handle.be, value));
- }
-
- @ForceInline
- static $type$ getAndSet(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
-#if[Object]
- return convEndian(handle.be,
- UNSAFE.getAndSetReference(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, value)));
-#else[Object]
- return convEndian(handle.be,
- UNSAFE.getAndSet$RawType$(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, value)));
-#end[Object]
- }
-
- @ForceInline
- static $type$ getAndSetAcquire(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- return convEndian(handle.be,
- UNSAFE.getAndSet$RawType$Acquire(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, value)));
- }
-
- @ForceInline
- static $type$ getAndSetRelease(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- return convEndian(handle.be,
- UNSAFE.getAndSet$RawType$Release(
- ba,
- address(ba, index(ba, index)),
- convEndian(handle.be, value)));
- }
-#end[CAS]
-#if[AtomicAdd]
-
- @ForceInline
- static $type$ getAndAdd(VarHandle ob, Object oba, int index, $type$ delta) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- if (handle.be == BE) {
- return UNSAFE.getAndAdd$RawType$(
- ba,
- address(ba, index(ba, index)),
- delta);
- } else {
- return getAndAddConvEndianWithCAS(ba, index, delta);
- }
- }
-
- @ForceInline
- static $type$ getAndAddAcquire(VarHandle ob, Object oba, int index, $type$ delta) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- if (handle.be == BE) {
- return UNSAFE.getAndAdd$RawType$Acquire(
- ba,
- address(ba, index(ba, index)),
- delta);
- } else {
- return getAndAddConvEndianWithCAS(ba, index, delta);
- }
- }
-
- @ForceInline
- static $type$ getAndAddRelease(VarHandle ob, Object oba, int index, $type$ delta) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- if (handle.be == BE) {
- return UNSAFE.getAndAdd$RawType$Release(
- ba,
- address(ba, index(ba, index)),
- delta);
- } else {
- return getAndAddConvEndianWithCAS(ba, index, delta);
- }
- }
-
- @ForceInline
- static $type$ getAndAddConvEndianWithCAS(byte[] ba, int index, $type$ delta) {
- $type$ nativeExpectedValue, expectedValue;
- long offset = address(ba, index(ba, index));
- do {
- nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset);
- expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
- } while (!UNSAFE.weakCompareAndSet$RawType$(ba, offset,
- nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta)));
- return expectedValue;
- }
-#end[AtomicAdd]
-#if[Bitwise]
-
- @ForceInline
- static $type$ getAndBitwiseOr(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- if (handle.be == BE) {
- return UNSAFE.getAndBitwiseOr$RawType$(
- ba,
- address(ba, index(ba, index)),
- value);
- } else {
- return getAndBitwiseOrConvEndianWithCAS(ba, index, value);
- }
- }
-
- @ForceInline
- static $type$ getAndBitwiseOrRelease(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- if (handle.be == BE) {
- return UNSAFE.getAndBitwiseOr$RawType$Release(
- ba,
- address(ba, index(ba, index)),
- value);
- } else {
- return getAndBitwiseOrConvEndianWithCAS(ba, index, value);
- }
- }
-
- @ForceInline
- static $type$ getAndBitwiseOrAcquire(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- if (handle.be == BE) {
- return UNSAFE.getAndBitwiseOr$RawType$Acquire(
- ba,
- address(ba, index(ba, index)),
- value);
- } else {
- return getAndBitwiseOrConvEndianWithCAS(ba, index, value);
- }
- }
-
- @ForceInline
- static $type$ getAndBitwiseOrConvEndianWithCAS(byte[] ba, int index, $type$ value) {
- $type$ nativeExpectedValue, expectedValue;
- long offset = address(ba, index(ba, index));
- do {
- nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset);
- expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
- } while (!UNSAFE.weakCompareAndSet$RawType$(ba, offset,
- nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue | value)));
- return expectedValue;
- }
-
- @ForceInline
- static $type$ getAndBitwiseAnd(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- if (handle.be == BE) {
- return UNSAFE.getAndBitwiseAnd$RawType$(
- ba,
- address(ba, index(ba, index)),
- value);
- } else {
- return getAndBitwiseAndConvEndianWithCAS(ba, index, value);
- }
- }
-
- @ForceInline
- static $type$ getAndBitwiseAndRelease(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- if (handle.be == BE) {
- return UNSAFE.getAndBitwiseAnd$RawType$Release(
- ba,
- address(ba, index(ba, index)),
- value);
- } else {
- return getAndBitwiseAndConvEndianWithCAS(ba, index, value);
- }
- }
-
- @ForceInline
- static $type$ getAndBitwiseAndAcquire(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- if (handle.be == BE) {
- return UNSAFE.getAndBitwiseAnd$RawType$Acquire(
- ba,
- address(ba, index(ba, index)),
- value);
- } else {
- return getAndBitwiseAndConvEndianWithCAS(ba, index, value);
- }
- }
-
- @ForceInline
- static $type$ getAndBitwiseAndConvEndianWithCAS(byte[] ba, int index, $type$ value) {
- $type$ nativeExpectedValue, expectedValue;
- long offset = address(ba, index(ba, index));
- do {
- nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset);
- expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
- } while (!UNSAFE.weakCompareAndSet$RawType$(ba, offset,
- nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue & value)));
- return expectedValue;
- }
-
- @ForceInline
- static $type$ getAndBitwiseXor(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- if (handle.be == BE) {
- return UNSAFE.getAndBitwiseXor$RawType$(
- ba,
- address(ba, index(ba, index)),
- value);
- } else {
- return getAndBitwiseXorConvEndianWithCAS(ba, index, value);
- }
- }
-
- @ForceInline
- static $type$ getAndBitwiseXorRelease(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- if (handle.be == BE) {
- return UNSAFE.getAndBitwiseXor$RawType$Release(
- ba,
- address(ba, index(ba, index)),
- value);
- } else {
- return getAndBitwiseXorConvEndianWithCAS(ba, index, value);
- }
- }
-
- @ForceInline
- static $type$ getAndBitwiseXorAcquire(VarHandle ob, Object oba, int index, $type$ value) {
- ArrayHandle handle = (ArrayHandle)ob;
- byte[] ba = (byte[]) oba;
- if (handle.be == BE) {
- return UNSAFE.getAndBitwiseXor$RawType$Acquire(
- ba,
- address(ba, index(ba, index)),
- value);
- } else {
- return getAndBitwiseXorConvEndianWithCAS(ba, index, value);
- }
- }
-
- @ForceInline
- static $type$ getAndBitwiseXorConvEndianWithCAS(byte[] ba, int index, $type$ value) {
- $type$ nativeExpectedValue, expectedValue;
- long offset = address(ba, index(ba, index));
- do {
- nativeExpectedValue = UNSAFE.get$RawType$Volatile(ba, offset);
- expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
- } while (!UNSAFE.weakCompareAndSet$RawType$(ba, offset,
- nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue ^ value)));
- return expectedValue;
- }
-#end[Bitwise]
-
static final VarForm FORM = new VarForm(ArrayHandle.class, byte[].class, $type$.class, int.class);
}
@@ -634,6 +213,14 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
return address;
}
+ @ForceInline
+ static Object checkNullHeapBase(Object hb) {
+ if (hb != null) {
+ throw new IllegalStateException("Atomic access not supported for heap buffer");
+ }
+ return hb;
+ }
+
@ForceInline
static $type$ get(VarHandle ob, Object obb, int index) {
ByteBufferHandle handle = (ByteBufferHandle)ob;
@@ -677,7 +264,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, index(bb, index))));
}
@@ -686,7 +273,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
SCOPED_MEMORY_ACCESS.put$RawType$Volatile(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value));
}
@@ -697,7 +284,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.get$RawType$Acquire(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, index(bb, index))));
}
@@ -706,7 +293,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
SCOPED_MEMORY_ACCESS.put$RawType$Release(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value));
}
@@ -717,7 +304,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.get$RawType$Opaque(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, index(bb, index))));
}
@@ -726,7 +313,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
SCOPED_MEMORY_ACCESS.put$RawType$Opaque(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value));
}
@@ -736,17 +323,10 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
static boolean compareAndSet(VarHandle ob, Object obb, int index, $type$ expected, $type$ value) {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
-#if[Object]
- return SCOPED_MEMORY_ACCESS.compareAndSetReference(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
- address(bb, indexRO(bb, index)),
- convEndian(handle.be, expected), convEndian(handle.be, value));
-#else[Object]
return SCOPED_MEMORY_ACCESS.compareAndSet$RawType$(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
-#end[Object]
}
@ForceInline
@@ -755,7 +335,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@@ -766,7 +346,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Acquire(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@@ -777,7 +357,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Release(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value)));
}
@@ -787,7 +367,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Plain(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@@ -797,7 +377,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@@ -807,7 +387,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Acquire(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@@ -817,7 +397,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Release(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, expected), convEndian(handle.be, value));
}
@@ -826,19 +406,11 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
static $type$ getAndSet(VarHandle ob, Object obb, int index, $type$ value) {
ByteBufferHandle handle = (ByteBufferHandle)ob;
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
-#if[Object]
- return convEndian(handle.be,
- SCOPED_MEMORY_ACCESS.getAndSetReference(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
- address(bb, indexRO(bb, index)),
- convEndian(handle.be, value)));
-#else[Object]
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.getAndSet$RawType$(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value)));
-#end[Object]
}
@ForceInline
@@ -847,7 +419,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.getAndSet$RawType$Acquire(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value)));
}
@@ -858,7 +430,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
return convEndian(handle.be,
SCOPED_MEMORY_ACCESS.getAndSet$RawType$Release(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
convEndian(handle.be, value)));
}
@@ -871,7 +443,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
delta);
} else {
@@ -885,7 +457,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Acquire(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
delta);
} else {
@@ -899,7 +471,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Release(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
delta);
} else {
@@ -910,7 +482,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
@ForceInline
static $type$ getAndAddConvEndianWithCAS(ByteBuffer bb, int index, $type$ delta) {
$type$ nativeExpectedValue, expectedValue;
- Object base = UNSAFE.getReference(bb, BYTE_BUFFER_HB);
+ Object base = checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB));
long offset = address(bb, indexRO(bb, index));
do {
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), base, offset);
@@ -928,7 +500,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@@ -942,7 +514,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Release(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@@ -956,7 +528,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Acquire(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@@ -967,7 +539,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
@ForceInline
static $type$ getAndBitwiseOrConvEndianWithCAS(ByteBuffer bb, int index, $type$ value) {
$type$ nativeExpectedValue, expectedValue;
- Object base = UNSAFE.getReference(bb, BYTE_BUFFER_HB);
+ Object base = checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB));
long offset = address(bb, indexRO(bb, index));
do {
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), base, offset);
@@ -983,7 +555,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@@ -997,7 +569,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Release(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@@ -1011,7 +583,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Acquire(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@@ -1022,7 +594,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
@ForceInline
static $type$ getAndBitwiseAndConvEndianWithCAS(ByteBuffer bb, int index, $type$ value) {
$type$ nativeExpectedValue, expectedValue;
- Object base = UNSAFE.getReference(bb, BYTE_BUFFER_HB);
+ Object base = checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB));
long offset = address(bb, indexRO(bb, index));
do {
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), base, offset);
@@ -1039,7 +611,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@@ -1053,7 +625,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Release(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@@ -1067,7 +639,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
ByteBuffer bb = (ByteBuffer) Objects.requireNonNull(obb);
if (handle.be == BE) {
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Acquire(session(bb),
- UNSAFE.getReference(bb, BYTE_BUFFER_HB),
+ checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB)),
address(bb, indexRO(bb, index)),
value);
} else {
@@ -1078,7 +650,7 @@ final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
@ForceInline
static $type$ getAndBitwiseXorConvEndianWithCAS(ByteBuffer bb, int index, $type$ value) {
$type$ nativeExpectedValue, expectedValue;
- Object base = UNSAFE.getReference(bb, BYTE_BUFFER_HB);
+ Object base = checkNullHeapBase(UNSAFE.getReference(bb, BYTE_BUFFER_HB));
long offset = address(bb, indexRO(bb, index));
do {
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(session(bb), base, offset);
diff --git a/src/java.base/share/classes/java/nio/X-Buffer.java.template b/src/java.base/share/classes/java/nio/X-Buffer.java.template
index 2146c86a577e2..1b378a2ef4a91 100644
--- a/src/java.base/share/classes/java/nio/X-Buffer.java.template
+++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template
@@ -1557,7 +1557,7 @@ public abstract sealed class $Type$Buffer
super.position(newPosition);
return this;
}
-
+
/**
* {@inheritDoc}
* @since 9
@@ -1571,13 +1571,13 @@ public abstract sealed class $Type$Buffer
super.limit(newLimit);
return this;
}
-
+
/**
* {@inheritDoc}
* @since 9
*/
@Override
- public
+ public
#if[!byte]
final
#end[!byte]
@@ -1591,7 +1591,7 @@ public abstract sealed class $Type$Buffer
* @since 9
*/
@Override
- public
+ public
#if[!byte]
final
#end[!byte]
@@ -1605,7 +1605,7 @@ public abstract sealed class $Type$Buffer
* @since 9
*/
@Override
- public
+ public
#if[!byte]
final
#end[!byte]
@@ -1619,7 +1619,7 @@ public abstract sealed class $Type$Buffer
* @since 9
*/
@Override
- public
+ public
#if[!byte]
final
#end[!byte]
@@ -1633,7 +1633,7 @@ public abstract sealed class $Type$Buffer
* @since 9
*/
@Override
- public
+ public
#if[!byte]
final
#end[!byte]
@@ -2208,15 +2208,11 @@ public abstract sealed class $Type$Buffer
* alignmentOffset(index + (unitSize - value), unitSize) == 0
* }
* must hold.
- *
+ *
* @apiNote
* This method may be utilized to determine if unit size bytes from an
* index can be accessed atomically, if supported by the native platform.
*
- * @implNote
- * This implementation throws {@code UnsupportedOperationException} for
- * non-direct buffers when the given unit size is greater then {@code 8}.
- *
* @param index
* The index to query for alignment offset, must be non-negative, no
* upper bounds check is performed
@@ -2231,13 +2227,7 @@ public abstract sealed class $Type$Buffer
* {@code 2}
*
* @throws UnsupportedOperationException
- * If the native platform does not guarantee stable alignment offset
- * values for the given unit size when managing the memory regions
- * of buffers of the same kind as this buffer (direct or
- * non-direct). For example, if garbage collection would result
- * in the moving of a memory region covered by a non-direct buffer
- * from one location to another and both locations have different
- * alignment characteristics.
+ * If the buffer is non-direct, and {@code unitSize > 1}
*
* @see #alignedSlice(int)
* @since 9
@@ -2247,7 +2237,7 @@ public abstract sealed class $Type$Buffer
throw new IllegalArgumentException("Index less than zero: " + index);
if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
- if (unitSize > 8 && !isDirect())
+ if (unitSize > 1 && !isDirect())
throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
return (int) ((address + index) & (unitSize - 1));
@@ -2287,10 +2277,6 @@ public abstract sealed class $Type$Buffer
* from index, that is a multiple of the unit size, may be accessed
* atomically, if supported by the native platform.
*
- * @implNote
- * This implementation throws {@code UnsupportedOperationException} for
- * non-direct buffers when the given unit size is greater then {@code 8}.
- *
* @param unitSize
* The unit size in bytes, must be a power of {@code 2}
*
@@ -2300,13 +2286,7 @@ public abstract sealed class $Type$Buffer
* If the unit size not a power of {@code 2}
*
* @throws UnsupportedOperationException
- * If the native platform does not guarantee stable aligned slices
- * for the given unit size when managing the memory regions
- * of buffers of the same kind as this buffer (direct or
- * non-direct). For example, if garbage collection would result
- * in the moving of a memory region covered by a non-direct buffer
- * from one location to another and both locations have different
- * alignment characteristics.
+ * If the buffer is non-direct, and {@code unitSize > 1}
*
* @see #alignmentOffset(int, int)
* @see #slice()
diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java
index 9d74f2da26e09..f88bb052f5e90 100644
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java
@@ -159,8 +159,11 @@ void fill(byte[] values) {
}
static class VarHandleSource extends Source {
- VarHandleSource(VarHandle vh, MemoryMode... modes) {
+ final boolean supportsAtomicAccess;
+
+ VarHandleSource(VarHandle vh, boolean supportsAtomicAccess, MemoryMode... modes) {
super(vh, modes);
+ this.supportsAtomicAccess = supportsAtomicAccess;
}
boolean matches(ByteArrayViewSource> bav) {
diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java
index ea2aca9b5435d..b18655fcb0353 100644
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java
@@ -72,12 +72,12 @@ public List setupVarHandleSources(boolean same) {
arrayType = int[].class;
}
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(arrayType, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo), false,
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(arrayType, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo), true,
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
@@ -114,38 +114,48 @@ public void testIsAccessModeSupported(VarHandleSource vhs) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
-
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
-
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
-
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ }
+
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
}
@Test(dataProvider = "typesProvider")
@@ -180,9 +190,6 @@ public Object[][] accessTestCaseProvider() throws Exception {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
- false));
}
else {
ByteBufferSource bbs = (ByteBufferSource) bav;
@@ -207,9 +214,11 @@ public Object[][] accessTestCaseProvider() throws Exception {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
- false));
+ if (bbs.s.isDirect()) {
+ cases.add(new VarHandleSourceAccessTestCase(
+ "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+ false));
+ }
}
}
}
@@ -243,33 +252,6 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
checkNPE(() -> {
vh.set(array, ci, VALUE_1);
});
-
- checkNPE(() -> {
- char x = (char) vh.getVolatile(array, ci);
- });
-
- checkNPE(() -> {
- char x = (char) vh.getAcquire(array, ci);
- });
-
- checkNPE(() -> {
- char x = (char) vh.getOpaque(array, ci);
- });
-
- checkNPE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
-
-
}
static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
@@ -423,7 +405,7 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
});
}
- if (readOnly) {
+ if (readOnly && array.isDirect()) {
checkROBE(() -> {
vh.setVolatile(array, ci, VALUE_1);
});
@@ -435,6 +417,11 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkROBE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
+
+
+ }
+
+ if (array.isDirect()) {
checkUOE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -478,7 +465,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkUOE(() -> {
char o = (char) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
checkUOE(() -> {
char o = (char) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -490,7 +476,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkUOE(() -> {
char o = (char) vh.getAndAddRelease(array, ci, VALUE_1);
});
-
checkUOE(() -> {
char o = (char) vh.getAndBitwiseOr(array, ci, VALUE_1);
});
@@ -526,8 +511,18 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkUOE(() -> {
char o = (char) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
- }
- else {
+ } else {
+ checkISE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
checkUOE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -636,33 +631,6 @@ static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) t
checkAIOOBE(() -> {
vh.set(array, ci, VALUE_1);
});
-
- checkAIOOBE(() -> {
- char x = (char) vh.getVolatile(array, ci);
- });
-
- checkAIOOBE(() -> {
- char x = (char) vh.getAcquire(array, ci);
- });
-
- checkAIOOBE(() -> {
- char x = (char) vh.getOpaque(array, ci);
- });
-
- checkAIOOBE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
-
-
}
}
@@ -686,74 +654,35 @@ static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs)
});
}
- checkIOOBE(() -> {
- char x = (char) vh.getVolatile(array, ci);
- });
-
- checkIOOBE(() -> {
- char x = (char) vh.getAcquire(array, ci);
- });
-
- checkIOOBE(() -> {
- char x = (char) vh.getOpaque(array, ci);
- });
-
- if (!readOnly) {
- checkIOOBE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
+ if (array.isDirect()) {
checkIOOBE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
-
-
- }
- }
- }
-
- static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
-
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
- int length = array.length - SIZE + 1;
- for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
- final int ci = i;
-
- if (!iAligned) {
- checkISE(() -> {
char x = (char) vh.getVolatile(array, ci);
});
- checkISE(() -> {
+ checkIOOBE(() -> {
char x = (char) vh.getAcquire(array, ci);
});
- checkISE(() -> {
+ checkIOOBE(() -> {
char x = (char) vh.getOpaque(array, ci);
});
- checkISE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
+ if (!readOnly) {
+ checkIOOBE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
+
+ checkIOOBE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
+ }
}
}
}
@@ -795,9 +724,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs)
checkISE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
-
-
-
}
}
}
@@ -807,45 +733,15 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
byte[] array = bs.s;
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.length - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
-
// Plain
{
vh.set(array, i, VALUE_1);
char x = (char) vh.get(array, i);
assertEquals(x, VALUE_1, "get char value");
}
-
-
- if (iAligned) {
- // Volatile
- {
- vh.setVolatile(array, i, VALUE_2);
- char x = (char) vh.getVolatile(array, i);
- assertEquals(x, VALUE_2, "setVolatile char value");
- }
-
- // Lazy
- {
- vh.setRelease(array, i, VALUE_1);
- char x = (char) vh.getAcquire(array, i);
- assertEquals(x, VALUE_1, "setRelease char value");
- }
-
- // Opaque
- {
- vh.setOpaque(array, i, VALUE_2);
- char x = (char) vh.getOpaque(array, i);
- assertEquals(x, VALUE_2, "setOpaque char value");
- }
-
-
- }
}
}
@@ -854,12 +750,10 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
// Plain
{
@@ -899,15 +793,13 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
ByteBuffer bb = ByteBuffer.allocate(SIZE);
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
bs.fill(bb.putChar(0, VALUE_2).array());
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
char v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
? rotateLeft(VALUE_2, (i % SIZE) << 3)
diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java
index 9dcaf2193236b..808c3ec04cb73 100644
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java
@@ -72,12 +72,12 @@ public List setupVarHandleSources(boolean same) {
arrayType = int[].class;
}
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(arrayType, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo), false,
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(arrayType, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo), true,
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
@@ -114,38 +114,62 @@ public void testIsAccessModeSupported(VarHandleSource vhs) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
-
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
-
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
-
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ }
+
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+ }
+
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
}
@Test(dataProvider = "typesProvider")
@@ -180,9 +204,6 @@ public Object[][] accessTestCaseProvider() throws Exception {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
- false));
}
else {
ByteBufferSource bbs = (ByteBufferSource) bav;
@@ -207,9 +228,11 @@ public Object[][] accessTestCaseProvider() throws Exception {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
- false));
+ if (bbs.s.isDirect()) {
+ cases.add(new VarHandleSourceAccessTestCase(
+ "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+ false));
+ }
}
}
}
@@ -243,6 +266,20 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
checkNPE(() -> {
vh.set(array, ci, VALUE_1);
});
+ }
+
+ static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+ VarHandle vh = vhs.s;
+ ByteBuffer array = null;
+ int ci = 1;
+
+ checkNPE(() -> {
+ double x = (double) vh.get(array, ci);
+ });
+
+ checkNPE(() -> {
+ vh.set(array, ci, VALUE_1);
+ });
checkNPE(() -> {
double x = (double) vh.getVolatile(array, ci);
@@ -315,96 +352,55 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
}
- static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+ static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
- ByteBuffer array = null;
+ byte[] array = bs.s;
int ci = 1;
- checkNPE(() -> {
- double x = (double) vh.get(array, ci);
- });
-
- checkNPE(() -> {
- vh.set(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- double x = (double) vh.getVolatile(array, ci);
- });
-
- checkNPE(() -> {
- double x = (double) vh.getAcquire(array, ci);
- });
-
- checkNPE(() -> {
- double x = (double) vh.getOpaque(array, ci);
- });
-
- checkNPE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
double o = (double) vh.getAndSet(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
- }
-
- static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
- int ci = 1;
-
-
checkUOE(() -> {
double o = (double) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -466,7 +462,7 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
});
}
- if (readOnly) {
+ if (readOnly && array.isDirect()) {
checkROBE(() -> {
vh.setVolatile(array, ci, VALUE_1);
});
@@ -478,7 +474,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkROBE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
-
checkROBE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -524,6 +519,9 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
});
+ }
+
+ if (array.isDirect()) {
checkUOE(() -> {
double o = (double) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -535,7 +533,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkUOE(() -> {
double o = (double) vh.getAndAddRelease(array, ci, VALUE_1);
});
-
checkUOE(() -> {
double o = (double) vh.getAndBitwiseOr(array, ci, VALUE_1);
});
@@ -571,8 +568,61 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkUOE(() -> {
double o = (double) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
- }
- else {
+ } else {
+ checkISE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
+ checkISE(() -> {
+ boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
+ double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+ });
+
+ checkISE(() -> {
+ double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+ });
+
+ checkISE(() -> {
+ double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+ });
+
+ checkISE(() -> {
+ boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
+ boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
+ boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
+ boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
+ double o = (double) vh.getAndSet(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
+ });
checkUOE(() -> {
double o = (double) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -638,77 +688,6 @@ static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) t
checkAIOOBE(() -> {
vh.set(array, ci, VALUE_1);
});
-
- checkAIOOBE(() -> {
- double x = (double) vh.getVolatile(array, ci);
- });
-
- checkAIOOBE(() -> {
- double x = (double) vh.getAcquire(array, ci);
- });
-
- checkAIOOBE(() -> {
- double x = (double) vh.getOpaque(array, ci);
- });
-
- checkAIOOBE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkAIOOBE(() -> {
- double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
-
- checkAIOOBE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkAIOOBE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
-
- checkAIOOBE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
-
- checkAIOOBE(() -> {
- double o = (double) vh.getAndSet(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
- });
-
-
-
}
}
@@ -732,161 +711,78 @@ static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs)
});
}
- checkIOOBE(() -> {
- double x = (double) vh.getVolatile(array, ci);
- });
-
- checkIOOBE(() -> {
- double x = (double) vh.getAcquire(array, ci);
- });
-
- checkIOOBE(() -> {
- double x = (double) vh.getOpaque(array, ci);
- });
-
- if (!readOnly) {
- checkIOOBE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
+ if (array.isDirect()) {
checkIOOBE(() -> {
- vh.setRelease(array, ci, VALUE_1);
+ double x = (double) vh.getVolatile(array, ci);
});
checkIOOBE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
+ double x = (double) vh.getAcquire(array, ci);
});
checkIOOBE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+ double x = (double) vh.getOpaque(array, ci);
});
- checkIOOBE(() -> {
- double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
+ if (!readOnly) {
+ checkIOOBE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- double o = (double) vh.getAndSet(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
- });
-
-
- }
- }
- }
-
- static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
-
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
- int length = array.length - SIZE + 1;
- for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
- final int ci = i;
-
- if (!iAligned) {
- checkISE(() -> {
- double x = (double) vh.getVolatile(array, ci);
- });
-
- checkISE(() -> {
- double x = (double) vh.getAcquire(array, ci);
- });
-
- checkISE(() -> {
- double x = (double) vh.getOpaque(array, ci);
- });
-
- checkISE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- double r = (double) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- double r = (double) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- double r = (double) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+ });
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+ });
- checkISE(() -> {
- double o = (double) vh.getAndSet(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ double o = (double) vh.getAndSet(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ double o = (double) vh.getAndSetAcquire(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
+ });
+ }
}
}
}
@@ -928,7 +824,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs)
checkISE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
-
checkISE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -972,8 +867,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs)
checkISE(() -> {
double o = (double) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
-
}
}
}
@@ -983,204 +876,15 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
byte[] array = bs.s;
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.length - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
-
// Plain
{
vh.set(array, i, VALUE_1);
double x = (double) vh.get(array, i);
assertEquals(x, VALUE_1, "get double value");
}
-
-
- if (iAligned) {
- // Volatile
- {
- vh.setVolatile(array, i, VALUE_2);
- double x = (double) vh.getVolatile(array, i);
- assertEquals(x, VALUE_2, "setVolatile double value");
- }
-
- // Lazy
- {
- vh.setRelease(array, i, VALUE_1);
- double x = (double) vh.getAcquire(array, i);
- assertEquals(x, VALUE_1, "setRelease double value");
- }
-
- // Opaque
- {
- vh.setOpaque(array, i, VALUE_2);
- double x = (double) vh.getOpaque(array, i);
- assertEquals(x, VALUE_2, "setOpaque double value");
- }
-
- vh.set(array, i, VALUE_1);
-
- // Compare
- {
- boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
- assertEquals(r, true, "success compareAndSet double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_2, "success compareAndSet double value");
- }
-
- {
- boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
- assertEquals(r, false, "failing compareAndSet double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing compareAndSet double value");
- }
-
- {
- double r = (double) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
- assertEquals(r, VALUE_2, "success compareAndExchange double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_1, "success compareAndExchange double value");
- }
-
- {
- double r = (double) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
- assertEquals(r, VALUE_1, "failing compareAndExchange double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing compareAndExchange double value");
- }
-
- {
- double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
- assertEquals(r, VALUE_1, "success compareAndExchangeAcquire double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_2, "success compareAndExchangeAcquire double value");
- }
-
- {
- double r = (double) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
- assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire double value");
- }
-
- {
- double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
- assertEquals(r, VALUE_2, "success compareAndExchangeRelease double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_1, "success compareAndExchangeRelease double value");
- }
-
- {
- double r = (double) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
- assertEquals(r, VALUE_1, "failing compareAndExchangeRelease double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing compareAndExchangeRelease double value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetPlain double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_2, "success weakCompareAndSetPlain double value");
- }
-
- {
- boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetPlain double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain double value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetAcquire double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire double");
- }
-
- {
- boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetAcquire double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire double value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetRelease double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_2, "success weakCompareAndSetRelease double");
- }
-
- {
- boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetRelease double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease double value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSet double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_1, "success weakCompareAndSet double");
- }
-
- {
- boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSet double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing weakCompareAndSet double value");
- }
-
- // Compare set and get
- {
- vh.set(array, i, VALUE_1);
-
- double o = (double) vh.getAndSet(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSet double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSet double value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- double o = (double) vh.getAndSetAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSetAcquire double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSetAcquire double value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- double o = (double) vh.getAndSetRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSetRelease double");
- double x = (double) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSetRelease double value");
- }
-
-
- }
}
}
@@ -1189,12 +893,10 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
// Plain
{
@@ -1393,15 +1095,13 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
ByteBuffer bb = ByteBuffer.allocate(SIZE);
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
bs.fill(bb.putDouble(0, VALUE_2).array());
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
double v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
? rotateLeft(VALUE_2, (i % SIZE) << 3)
diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java
index e1c8413142ca1..5c3854b6068db 100644
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java
@@ -72,12 +72,12 @@ public List setupVarHandleSources(boolean same) {
arrayType = int[].class;
}
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(arrayType, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo), false,
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(arrayType, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo), true,
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
@@ -114,38 +114,62 @@ public void testIsAccessModeSupported(VarHandleSource vhs) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
-
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
-
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
-
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ }
+
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+ }
+
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
}
@Test(dataProvider = "typesProvider")
@@ -180,9 +204,6 @@ public Object[][] accessTestCaseProvider() throws Exception {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
- false));
}
else {
ByteBufferSource bbs = (ByteBufferSource) bav;
@@ -207,9 +228,11 @@ public Object[][] accessTestCaseProvider() throws Exception {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
- false));
+ if (bbs.s.isDirect()) {
+ cases.add(new VarHandleSourceAccessTestCase(
+ "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+ false));
+ }
}
}
}
@@ -243,6 +266,20 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
checkNPE(() -> {
vh.set(array, ci, VALUE_1);
});
+ }
+
+ static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+ VarHandle vh = vhs.s;
+ ByteBuffer array = null;
+ int ci = 1;
+
+ checkNPE(() -> {
+ float x = (float) vh.get(array, ci);
+ });
+
+ checkNPE(() -> {
+ vh.set(array, ci, VALUE_1);
+ });
checkNPE(() -> {
float x = (float) vh.getVolatile(array, ci);
@@ -315,96 +352,55 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
}
- static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+ static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
- ByteBuffer array = null;
+ byte[] array = bs.s;
int ci = 1;
- checkNPE(() -> {
- float x = (float) vh.get(array, ci);
- });
-
- checkNPE(() -> {
- vh.set(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- float x = (float) vh.getVolatile(array, ci);
- });
-
- checkNPE(() -> {
- float x = (float) vh.getAcquire(array, ci);
- });
-
- checkNPE(() -> {
- float x = (float) vh.getOpaque(array, ci);
- });
-
- checkNPE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
float o = (float) vh.getAndSet(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
- }
-
- static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
- int ci = 1;
-
-
checkUOE(() -> {
float o = (float) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -466,7 +462,7 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
});
}
- if (readOnly) {
+ if (readOnly && array.isDirect()) {
checkROBE(() -> {
vh.setVolatile(array, ci, VALUE_1);
});
@@ -478,7 +474,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkROBE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
-
checkROBE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -524,6 +519,9 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
});
+ }
+
+ if (array.isDirect()) {
checkUOE(() -> {
float o = (float) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -535,7 +533,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkUOE(() -> {
float o = (float) vh.getAndAddRelease(array, ci, VALUE_1);
});
-
checkUOE(() -> {
float o = (float) vh.getAndBitwiseOr(array, ci, VALUE_1);
});
@@ -571,8 +568,61 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkUOE(() -> {
float o = (float) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
- }
- else {
+ } else {
+ checkISE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
+ checkISE(() -> {
+ boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
+ float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+ });
+
+ checkISE(() -> {
+ float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+ });
+
+ checkISE(() -> {
+ float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+ });
+
+ checkISE(() -> {
+ boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
+ boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
+ boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
+ boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+ });
+
+ checkISE(() -> {
+ float o = (float) vh.getAndSet(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
+ });
checkUOE(() -> {
float o = (float) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -638,77 +688,6 @@ static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) t
checkAIOOBE(() -> {
vh.set(array, ci, VALUE_1);
});
-
- checkAIOOBE(() -> {
- float x = (float) vh.getVolatile(array, ci);
- });
-
- checkAIOOBE(() -> {
- float x = (float) vh.getAcquire(array, ci);
- });
-
- checkAIOOBE(() -> {
- float x = (float) vh.getOpaque(array, ci);
- });
-
- checkAIOOBE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkAIOOBE(() -> {
- float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
-
- checkAIOOBE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkAIOOBE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
-
- checkAIOOBE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
-
- checkAIOOBE(() -> {
- float o = (float) vh.getAndSet(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
- });
-
-
-
}
}
@@ -732,161 +711,78 @@ static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs)
});
}
- checkIOOBE(() -> {
- float x = (float) vh.getVolatile(array, ci);
- });
-
- checkIOOBE(() -> {
- float x = (float) vh.getAcquire(array, ci);
- });
-
- checkIOOBE(() -> {
- float x = (float) vh.getOpaque(array, ci);
- });
-
- if (!readOnly) {
- checkIOOBE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
+ if (array.isDirect()) {
checkIOOBE(() -> {
- vh.setRelease(array, ci, VALUE_1);
+ float x = (float) vh.getVolatile(array, ci);
});
checkIOOBE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
+ float x = (float) vh.getAcquire(array, ci);
});
checkIOOBE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+ float x = (float) vh.getOpaque(array, ci);
});
- checkIOOBE(() -> {
- float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
+ if (!readOnly) {
+ checkIOOBE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- float o = (float) vh.getAndSet(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
- });
-
-
- }
- }
- }
-
- static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
-
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
- int length = array.length - SIZE + 1;
- for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
- final int ci = i;
-
- if (!iAligned) {
- checkISE(() -> {
- float x = (float) vh.getVolatile(array, ci);
- });
-
- checkISE(() -> {
- float x = (float) vh.getAcquire(array, ci);
- });
-
- checkISE(() -> {
- float x = (float) vh.getOpaque(array, ci);
- });
-
- checkISE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- float r = (float) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- float r = (float) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- float r = (float) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+ });
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+ });
- checkISE(() -> {
- float o = (float) vh.getAndSet(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ float o = (float) vh.getAndSet(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ float o = (float) vh.getAndSetAcquire(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
+ });
+ }
}
}
}
@@ -928,7 +824,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs)
checkISE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
-
checkISE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -972,8 +867,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs)
checkISE(() -> {
float o = (float) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
-
}
}
}
@@ -983,204 +876,15 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
byte[] array = bs.s;
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.length - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
-
// Plain
{
vh.set(array, i, VALUE_1);
float x = (float) vh.get(array, i);
assertEquals(x, VALUE_1, "get float value");
}
-
-
- if (iAligned) {
- // Volatile
- {
- vh.setVolatile(array, i, VALUE_2);
- float x = (float) vh.getVolatile(array, i);
- assertEquals(x, VALUE_2, "setVolatile float value");
- }
-
- // Lazy
- {
- vh.setRelease(array, i, VALUE_1);
- float x = (float) vh.getAcquire(array, i);
- assertEquals(x, VALUE_1, "setRelease float value");
- }
-
- // Opaque
- {
- vh.setOpaque(array, i, VALUE_2);
- float x = (float) vh.getOpaque(array, i);
- assertEquals(x, VALUE_2, "setOpaque float value");
- }
-
- vh.set(array, i, VALUE_1);
-
- // Compare
- {
- boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
- assertEquals(r, true, "success compareAndSet float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_2, "success compareAndSet float value");
- }
-
- {
- boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
- assertEquals(r, false, "failing compareAndSet float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing compareAndSet float value");
- }
-
- {
- float r = (float) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
- assertEquals(r, VALUE_2, "success compareAndExchange float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_1, "success compareAndExchange float value");
- }
-
- {
- float r = (float) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
- assertEquals(r, VALUE_1, "failing compareAndExchange float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing compareAndExchange float value");
- }
-
- {
- float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
- assertEquals(r, VALUE_1, "success compareAndExchangeAcquire float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_2, "success compareAndExchangeAcquire float value");
- }
-
- {
- float r = (float) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
- assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire float value");
- }
-
- {
- float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
- assertEquals(r, VALUE_2, "success compareAndExchangeRelease float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_1, "success compareAndExchangeRelease float value");
- }
-
- {
- float r = (float) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
- assertEquals(r, VALUE_1, "failing compareAndExchangeRelease float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing compareAndExchangeRelease float value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetPlain float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_2, "success weakCompareAndSetPlain float value");
- }
-
- {
- boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetPlain float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain float value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetAcquire float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire float");
- }
-
- {
- boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetAcquire float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire float value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetRelease float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_2, "success weakCompareAndSetRelease float");
- }
-
- {
- boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetRelease float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease float value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSet float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_1, "success weakCompareAndSet float");
- }
-
- {
- boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSet float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing weakCompareAndSet float value");
- }
-
- // Compare set and get
- {
- vh.set(array, i, VALUE_1);
-
- float o = (float) vh.getAndSet(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSet float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSet float value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- float o = (float) vh.getAndSetAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSetAcquire float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSetAcquire float value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- float o = (float) vh.getAndSetRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSetRelease float");
- float x = (float) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSetRelease float value");
- }
-
-
- }
}
}
@@ -1189,12 +893,10 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
// Plain
{
@@ -1393,15 +1095,13 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
ByteBuffer bb = ByteBuffer.allocate(SIZE);
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
bs.fill(bb.putFloat(0, VALUE_2).array());
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
float v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
? rotateLeft(VALUE_2, (i % SIZE) << 3)
diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java
index 3f6066c57bb2f..a03a6248a0fd5 100644
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java
@@ -72,12 +72,12 @@ public List setupVarHandleSources(boolean same) {
arrayType = long[].class;
}
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(arrayType, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo), false,
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(arrayType, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo), true,
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
@@ -114,38 +114,80 @@ public void testIsAccessModeSupported(VarHandleSource vhs) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
-
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
-
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
-
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ }
+
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+ }
+
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+ }
+
+
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+ }
}
@Test(dataProvider = "typesProvider")
@@ -180,9 +222,6 @@ public Object[][] accessTestCaseProvider() throws Exception {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
- false));
}
else {
ByteBufferSource bbs = (ByteBufferSource) bav;
@@ -207,9 +246,11 @@ public Object[][] accessTestCaseProvider() throws Exception {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
- false));
+ if (bbs.s.isDirect()) {
+ cases.add(new VarHandleSourceAccessTestCase(
+ "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+ false));
+ }
}
}
}
@@ -243,6 +284,20 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
checkNPE(() -> {
vh.set(array, ci, VALUE_1);
});
+ }
+
+ static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+ VarHandle vh = vhs.s;
+ ByteBuffer array = null;
+ int ci = 1;
+
+ checkNPE(() -> {
+ int x = (int) vh.get(array, ci);
+ });
+
+ checkNPE(() -> {
+ vh.set(array, ci, VALUE_1);
+ });
checkNPE(() -> {
int x = (int) vh.getVolatile(array, ci);
@@ -361,145 +416,104 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
});
}
- static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+ static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
- ByteBuffer array = null;
+ byte[] array = bs.s;
int ci = 1;
- checkNPE(() -> {
- int x = (int) vh.get(array, ci);
- });
-
- checkNPE(() -> {
- vh.set(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- int x = (int) vh.getVolatile(array, ci);
- });
-
- checkNPE(() -> {
- int x = (int) vh.getAcquire(array, ci);
- });
-
- checkNPE(() -> {
- int x = (int) vh.getOpaque(array, ci);
- });
-
- checkNPE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndSet(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndAdd(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
}
- static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
- int ci = 1;
-
-
-
- }
-
static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
@@ -512,7 +526,7 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
});
}
- if (readOnly) {
+ if (readOnly && array.isDirect()) {
checkROBE(() -> {
vh.setVolatile(array, ci, VALUE_1);
});
@@ -524,7 +538,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkROBE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
-
checkROBE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -569,7 +582,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
checkROBE(() -> {
int o = (int) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -618,143 +630,128 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
}
- else {
- }
- }
-
-
- static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
-
- int length = array.length - SIZE + 1;
- for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
- final int ci = i;
-
- checkAIOOBE(() -> {
- int x = (int) vh.get(array, ci);
- });
-
- checkAIOOBE(() -> {
- vh.set(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- int x = (int) vh.getVolatile(array, ci);
- });
-
- checkAIOOBE(() -> {
- int x = (int) vh.getAcquire(array, ci);
- });
- checkAIOOBE(() -> {
- int x = (int) vh.getOpaque(array, ci);
- });
-
- checkAIOOBE(() -> {
+ if (array.isDirect()) {
+ } else {
+ checkISE(() -> {
vh.setVolatile(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
vh.setRelease(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
-
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndSet(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndAdd(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
});
-
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
+ }
+ }
+
+
+ static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+ VarHandle vh = vhs.s;
+ byte[] array = bs.s;
+
+ int length = array.length - SIZE + 1;
+ for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+ final int ci = i;
+
+ checkAIOOBE(() -> {
+ int x = (int) vh.get(array, ci);
+ });
+ checkAIOOBE(() -> {
+ vh.set(array, ci, VALUE_1);
+ });
}
}
@@ -778,253 +775,124 @@ static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs)
});
}
- checkIOOBE(() -> {
- int x = (int) vh.getVolatile(array, ci);
- });
-
- checkIOOBE(() -> {
- int x = (int) vh.getAcquire(array, ci);
- });
-
- checkIOOBE(() -> {
- int x = (int) vh.getOpaque(array, ci);
- });
-
- if (!readOnly) {
+ if (array.isDirect()) {
checkIOOBE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
+ int x = (int) vh.getVolatile(array, ci);
});
checkIOOBE(() -> {
- vh.setRelease(array, ci, VALUE_1);
+ int x = (int) vh.getAcquire(array, ci);
});
checkIOOBE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
+ int x = (int) vh.getOpaque(array, ci);
});
- checkIOOBE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
+ if (!readOnly) {
+ checkIOOBE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- int o = (int) vh.getAndSet(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- int o = (int) vh.getAndAdd(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndSet(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndAdd(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
- });
- }
- }
- }
-
- static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
-
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
- int length = array.length - SIZE + 1;
- for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
- final int ci = i;
-
- if (!iAligned) {
- checkISE(() -> {
- int x = (int) vh.getVolatile(array, ci);
- });
-
- checkISE(() -> {
- int x = (int) vh.getAcquire(array, ci);
- });
-
- checkISE(() -> {
- int x = (int) vh.getOpaque(array, ci);
- });
-
- checkISE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- int r = (int) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- int r = (int) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- int r = (int) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- int o = (int) vh.getAndSet(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- int o = (int) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- int o = (int) vh.getAndAdd(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- int o = (int) vh.getAndAddAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndBitwiseXor(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ int o = (int) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+ });
+ }
}
}
}
@@ -1066,7 +934,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs)
checkISE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
-
checkISE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -1110,7 +977,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs)
checkISE(() -> {
int o = (int) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
checkISE(() -> {
int o = (int) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -1122,7 +988,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs)
checkISE(() -> {
int o = (int) vh.getAndAddRelease(array, ci, VALUE_1);
});
-
checkISE(() -> {
int o = (int) vh.getAndBitwiseOr(array, ci, VALUE_1);
});
@@ -1167,314 +1032,15 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
byte[] array = bs.s;
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.length - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
-
// Plain
{
vh.set(array, i, VALUE_1);
int x = (int) vh.get(array, i);
assertEquals(x, VALUE_1, "get int value");
}
-
-
- if (iAligned) {
- // Volatile
- {
- vh.setVolatile(array, i, VALUE_2);
- int x = (int) vh.getVolatile(array, i);
- assertEquals(x, VALUE_2, "setVolatile int value");
- }
-
- // Lazy
- {
- vh.setRelease(array, i, VALUE_1);
- int x = (int) vh.getAcquire(array, i);
- assertEquals(x, VALUE_1, "setRelease int value");
- }
-
- // Opaque
- {
- vh.setOpaque(array, i, VALUE_2);
- int x = (int) vh.getOpaque(array, i);
- assertEquals(x, VALUE_2, "setOpaque int value");
- }
-
- vh.set(array, i, VALUE_1);
-
- // Compare
- {
- boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
- assertEquals(r, true, "success compareAndSet int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_2, "success compareAndSet int value");
- }
-
- {
- boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
- assertEquals(r, false, "failing compareAndSet int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing compareAndSet int value");
- }
-
- {
- int r = (int) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
- assertEquals(r, VALUE_2, "success compareAndExchange int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1, "success compareAndExchange int value");
- }
-
- {
- int r = (int) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
- assertEquals(r, VALUE_1, "failing compareAndExchange int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing compareAndExchange int value");
- }
-
- {
- int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
- assertEquals(r, VALUE_1, "success compareAndExchangeAcquire int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_2, "success compareAndExchangeAcquire int value");
- }
-
- {
- int r = (int) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
- assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire int value");
- }
-
- {
- int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
- assertEquals(r, VALUE_2, "success compareAndExchangeRelease int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1, "success compareAndExchangeRelease int value");
- }
-
- {
- int r = (int) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
- assertEquals(r, VALUE_1, "failing compareAndExchangeRelease int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing compareAndExchangeRelease int value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetPlain int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_2, "success weakCompareAndSetPlain int value");
- }
-
- {
- boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetPlain int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain int value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetAcquire int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire int");
- }
-
- {
- boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetAcquire int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire int value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetRelease int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_2, "success weakCompareAndSetRelease int");
- }
-
- {
- boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetRelease int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease int value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSet int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1, "success weakCompareAndSet int");
- }
-
- {
- boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSet int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing weakCompareAndSet int value");
- }
-
- // Compare set and get
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndSet(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSet int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSet int value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndSetAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSetAcquire int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSetAcquire int value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndSetRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSetRelease int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSetRelease int value");
- }
-
- // get and add, add and get
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndAdd(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndAdd int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1 + VALUE_2, "getAndAdd int value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndAddAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndAddAcquire int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1 + VALUE_2, "getAndAddAcquire int value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndAddRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndAddRelease int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1 + VALUE_2, "getAndAddRelease int value");
- }
-
- // get and bitwise or
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndBitwiseOr(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseOr int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOr int value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndBitwiseOrAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseOrAcquire int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrAcquire int value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndBitwiseOrRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseOrRelease int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrRelease int value");
- }
-
- // get and bitwise and
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndBitwiseAnd(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseAnd int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAnd int value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndBitwiseAndAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseAndAcquire int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndAcquire int value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndBitwiseAndRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseAndRelease int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndRelease int value");
- }
-
- // get and bitwise xor
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndBitwiseXor(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseXor int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXor int value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndBitwiseXorAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseXorAcquire int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorAcquire int value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- int o = (int) vh.getAndBitwiseXorRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseXorRelease int");
- int x = (int) vh.get(array, i);
- assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorRelease int value");
- }
- }
}
}
@@ -1483,12 +1049,10 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
// Plain
{
@@ -1797,15 +1361,13 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
ByteBuffer bb = ByteBuffer.allocate(SIZE);
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
bs.fill(bb.putInt(0, VALUE_2).array());
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
int v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
? rotateLeft(VALUE_2, (i % SIZE) << 3)
diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java
index d13bb1c03df26..8324a48803505 100644
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java
@@ -72,12 +72,12 @@ public List setupVarHandleSources(boolean same) {
arrayType = int[].class;
}
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(arrayType, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo), false,
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(arrayType, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo), true,
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
@@ -114,38 +114,80 @@ public void testIsAccessModeSupported(VarHandleSource vhs) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
-
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
-
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
-
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ }
+
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+ }
+
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+ }
+
+
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+ }
}
@Test(dataProvider = "typesProvider")
@@ -180,9 +222,6 @@ public Object[][] accessTestCaseProvider() throws Exception {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
- false));
}
else {
ByteBufferSource bbs = (ByteBufferSource) bav;
@@ -207,9 +246,11 @@ public Object[][] accessTestCaseProvider() throws Exception {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
- false));
+ if (bbs.s.isDirect()) {
+ cases.add(new VarHandleSourceAccessTestCase(
+ "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+ false));
+ }
}
}
}
@@ -243,6 +284,20 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
checkNPE(() -> {
vh.set(array, ci, VALUE_1);
});
+ }
+
+ static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+ VarHandle vh = vhs.s;
+ ByteBuffer array = null;
+ int ci = 1;
+
+ checkNPE(() -> {
+ long x = (long) vh.get(array, ci);
+ });
+
+ checkNPE(() -> {
+ vh.set(array, ci, VALUE_1);
+ });
checkNPE(() -> {
long x = (long) vh.getVolatile(array, ci);
@@ -361,145 +416,104 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
});
}
- static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
+ static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
- ByteBuffer array = null;
+ byte[] array = bs.s;
int ci = 1;
- checkNPE(() -> {
- long x = (long) vh.get(array, ci);
- });
-
- checkNPE(() -> {
- vh.set(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- long x = (long) vh.getVolatile(array, ci);
- });
-
- checkNPE(() -> {
- long x = (long) vh.getAcquire(array, ci);
- });
-
- checkNPE(() -> {
- long x = (long) vh.getOpaque(array, ci);
- });
-
- checkNPE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndSet(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndAdd(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
});
- checkNPE(() -> {
+ checkUOE(() -> {
long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
}
- static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
- int ci = 1;
-
-
-
- }
-
static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
@@ -512,7 +526,7 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
});
}
- if (readOnly) {
+ if (readOnly && array.isDirect()) {
checkROBE(() -> {
vh.setVolatile(array, ci, VALUE_1);
});
@@ -524,7 +538,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkROBE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
-
checkROBE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -569,7 +582,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
checkROBE(() -> {
long o = (long) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -618,143 +630,128 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
}
- else {
- }
- }
-
-
- static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
-
- int length = array.length - SIZE + 1;
- for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
- final int ci = i;
-
- checkAIOOBE(() -> {
- long x = (long) vh.get(array, ci);
- });
-
- checkAIOOBE(() -> {
- vh.set(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- long x = (long) vh.getVolatile(array, ci);
- });
-
- checkAIOOBE(() -> {
- long x = (long) vh.getAcquire(array, ci);
- });
- checkAIOOBE(() -> {
- long x = (long) vh.getOpaque(array, ci);
- });
-
- checkAIOOBE(() -> {
+ if (array.isDirect()) {
+ } else {
+ checkISE(() -> {
vh.setVolatile(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
vh.setRelease(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
-
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndSet(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndAdd(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
});
-
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
+ }
+ }
+
+
+ static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+ VarHandle vh = vhs.s;
+ byte[] array = bs.s;
+
+ int length = array.length - SIZE + 1;
+ for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+ final int ci = i;
+
+ checkAIOOBE(() -> {
+ long x = (long) vh.get(array, ci);
+ });
+ checkAIOOBE(() -> {
+ vh.set(array, ci, VALUE_1);
+ });
}
}
@@ -778,253 +775,124 @@ static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs)
});
}
- checkIOOBE(() -> {
- long x = (long) vh.getVolatile(array, ci);
- });
-
- checkIOOBE(() -> {
- long x = (long) vh.getAcquire(array, ci);
- });
-
- checkIOOBE(() -> {
- long x = (long) vh.getOpaque(array, ci);
- });
-
- if (!readOnly) {
+ if (array.isDirect()) {
checkIOOBE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
+ long x = (long) vh.getVolatile(array, ci);
});
checkIOOBE(() -> {
- vh.setRelease(array, ci, VALUE_1);
+ long x = (long) vh.getAcquire(array, ci);
});
checkIOOBE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
+ long x = (long) vh.getOpaque(array, ci);
});
- checkIOOBE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
+ if (!readOnly) {
+ checkIOOBE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- long o = (long) vh.getAndSet(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- long o = (long) vh.getAndAdd(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndSet(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndAdd(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
- });
- }
- }
- }
-
- static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
-
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
- int length = array.length - SIZE + 1;
- for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
- final int ci = i;
-
- if (!iAligned) {
- checkISE(() -> {
- long x = (long) vh.getVolatile(array, ci);
- });
-
- checkISE(() -> {
- long x = (long) vh.getAcquire(array, ci);
- });
-
- checkISE(() -> {
- long x = (long) vh.getOpaque(array, ci);
- });
-
- checkISE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- long r = (long) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- long r = (long) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- long r = (long) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- long o = (long) vh.getAndSet(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- long o = (long) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- long o = (long) vh.getAndAdd(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- long o = (long) vh.getAndAddAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndBitwiseXor(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ long o = (long) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+ });
+ }
}
}
}
@@ -1066,7 +934,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs)
checkISE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
-
checkISE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -1110,7 +977,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs)
checkISE(() -> {
long o = (long) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
checkISE(() -> {
long o = (long) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -1122,7 +988,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs)
checkISE(() -> {
long o = (long) vh.getAndAddRelease(array, ci, VALUE_1);
});
-
checkISE(() -> {
long o = (long) vh.getAndBitwiseOr(array, ci, VALUE_1);
});
@@ -1167,314 +1032,15 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
byte[] array = bs.s;
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.length - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
-
// Plain
{
vh.set(array, i, VALUE_1);
long x = (long) vh.get(array, i);
assertEquals(x, VALUE_1, "get long value");
}
-
-
- if (iAligned) {
- // Volatile
- {
- vh.setVolatile(array, i, VALUE_2);
- long x = (long) vh.getVolatile(array, i);
- assertEquals(x, VALUE_2, "setVolatile long value");
- }
-
- // Lazy
- {
- vh.setRelease(array, i, VALUE_1);
- long x = (long) vh.getAcquire(array, i);
- assertEquals(x, VALUE_1, "setRelease long value");
- }
-
- // Opaque
- {
- vh.setOpaque(array, i, VALUE_2);
- long x = (long) vh.getOpaque(array, i);
- assertEquals(x, VALUE_2, "setOpaque long value");
- }
-
- vh.set(array, i, VALUE_1);
-
- // Compare
- {
- boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
- assertEquals(r, true, "success compareAndSet long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_2, "success compareAndSet long value");
- }
-
- {
- boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
- assertEquals(r, false, "failing compareAndSet long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing compareAndSet long value");
- }
-
- {
- long r = (long) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
- assertEquals(r, VALUE_2, "success compareAndExchange long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1, "success compareAndExchange long value");
- }
-
- {
- long r = (long) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
- assertEquals(r, VALUE_1, "failing compareAndExchange long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing compareAndExchange long value");
- }
-
- {
- long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
- assertEquals(r, VALUE_1, "success compareAndExchangeAcquire long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_2, "success compareAndExchangeAcquire long value");
- }
-
- {
- long r = (long) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
- assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire long value");
- }
-
- {
- long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
- assertEquals(r, VALUE_2, "success compareAndExchangeRelease long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1, "success compareAndExchangeRelease long value");
- }
-
- {
- long r = (long) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
- assertEquals(r, VALUE_1, "failing compareAndExchangeRelease long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing compareAndExchangeRelease long value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetPlain long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_2, "success weakCompareAndSetPlain long value");
- }
-
- {
- boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetPlain long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain long value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetAcquire long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire long");
- }
-
- {
- boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetAcquire long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire long value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetRelease long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_2, "success weakCompareAndSetRelease long");
- }
-
- {
- boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetRelease long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease long value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSet long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1, "success weakCompareAndSet long");
- }
-
- {
- boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSet long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing weakCompareAndSet long value");
- }
-
- // Compare set and get
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndSet(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSet long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSet long value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndSetAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSetAcquire long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSetAcquire long value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndSetRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSetRelease long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSetRelease long value");
- }
-
- // get and add, add and get
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndAdd(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndAdd long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1 + VALUE_2, "getAndAdd long value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndAddAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndAddAcquire long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1 + VALUE_2, "getAndAddAcquire long value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndAddRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndAddRelease long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1 + VALUE_2, "getAndAddRelease long value");
- }
-
- // get and bitwise or
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndBitwiseOr(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseOr long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOr long value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndBitwiseOrAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseOrAcquire long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrAcquire long value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndBitwiseOrRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseOrRelease long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrRelease long value");
- }
-
- // get and bitwise and
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndBitwiseAnd(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseAnd long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAnd long value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndBitwiseAndAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseAndAcquire long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndAcquire long value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndBitwiseAndRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseAndRelease long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndRelease long value");
- }
-
- // get and bitwise xor
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndBitwiseXor(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseXor long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXor long value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndBitwiseXorAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseXorAcquire long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorAcquire long value");
- }
-
- {
- vh.set(array, i, VALUE_1);
-
- long o = (long) vh.getAndBitwiseXorRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseXorRelease long");
- long x = (long) vh.get(array, i);
- assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorRelease long value");
- }
- }
}
}
@@ -1483,12 +1049,10 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
// Plain
{
@@ -1797,15 +1361,13 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
ByteBuffer bb = ByteBuffer.allocate(SIZE);
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
bs.fill(bb.putLong(0, VALUE_2).array());
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
long v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
? rotateLeft(VALUE_2, (i % SIZE) << 3)
diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java
index d25d24cdeabd5..20751c9d76480 100644
--- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java
+++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java
@@ -72,12 +72,12 @@ public List setupVarHandleSources(boolean same) {
arrayType = int[].class;
}
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(arrayType, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo), false,
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(arrayType, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo), true,
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
@@ -114,38 +114,48 @@ public void testIsAccessModeSupported(VarHandleSource vhs) {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
-
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
-
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
-
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ }
+
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+
+
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
}
@Test(dataProvider = "typesProvider")
@@ -180,9 +190,6 @@ public Object[][] accessTestCaseProvider() throws Exception {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
- false));
}
else {
ByteBufferSource bbs = (ByteBufferSource) bav;
@@ -207,9 +214,11 @@ public Object[][] accessTestCaseProvider() throws Exception {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
- false));
+ if (bbs.s.isDirect()) {
+ cases.add(new VarHandleSourceAccessTestCase(
+ "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+ false));
+ }
}
}
}
@@ -243,33 +252,6 @@ static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
checkNPE(() -> {
vh.set(array, ci, VALUE_1);
});
-
- checkNPE(() -> {
- short x = (short) vh.getVolatile(array, ci);
- });
-
- checkNPE(() -> {
- short x = (short) vh.getAcquire(array, ci);
- });
-
- checkNPE(() -> {
- short x = (short) vh.getOpaque(array, ci);
- });
-
- checkNPE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
-
-
}
static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
@@ -423,7 +405,7 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
});
}
- if (readOnly) {
+ if (readOnly && array.isDirect()) {
checkROBE(() -> {
vh.setVolatile(array, ci, VALUE_1);
});
@@ -435,6 +417,11 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkROBE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
+
+
+ }
+
+ if (array.isDirect()) {
checkUOE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -478,7 +465,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkUOE(() -> {
short o = (short) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
checkUOE(() -> {
short o = (short) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -490,7 +476,6 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkUOE(() -> {
short o = (short) vh.getAndAddRelease(array, ci, VALUE_1);
});
-
checkUOE(() -> {
short o = (short) vh.getAndBitwiseOr(array, ci, VALUE_1);
});
@@ -526,8 +511,18 @@ static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
checkUOE(() -> {
short o = (short) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
- }
- else {
+ } else {
+ checkISE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
checkUOE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -636,33 +631,6 @@ static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) t
checkAIOOBE(() -> {
vh.set(array, ci, VALUE_1);
});
-
- checkAIOOBE(() -> {
- short x = (short) vh.getVolatile(array, ci);
- });
-
- checkAIOOBE(() -> {
- short x = (short) vh.getAcquire(array, ci);
- });
-
- checkAIOOBE(() -> {
- short x = (short) vh.getOpaque(array, ci);
- });
-
- checkAIOOBE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkAIOOBE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
-
-
}
}
@@ -686,74 +654,35 @@ static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs)
});
}
- checkIOOBE(() -> {
- short x = (short) vh.getVolatile(array, ci);
- });
-
- checkIOOBE(() -> {
- short x = (short) vh.getAcquire(array, ci);
- });
-
- checkIOOBE(() -> {
- short x = (short) vh.getOpaque(array, ci);
- });
-
- if (!readOnly) {
- checkIOOBE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
+ if (array.isDirect()) {
checkIOOBE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
-
-
- }
- }
- }
-
- static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
-
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
- int length = array.length - SIZE + 1;
- for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
- final int ci = i;
-
- if (!iAligned) {
- checkISE(() -> {
short x = (short) vh.getVolatile(array, ci);
});
- checkISE(() -> {
+ checkIOOBE(() -> {
short x = (short) vh.getAcquire(array, ci);
});
- checkISE(() -> {
+ checkIOOBE(() -> {
short x = (short) vh.getOpaque(array, ci);
});
- checkISE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
+ if (!readOnly) {
+ checkIOOBE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
+
+ checkIOOBE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
- checkISE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
+ }
}
}
}
@@ -795,9 +724,6 @@ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs)
checkISE(() -> {
vh.setOpaque(array, ci, VALUE_1);
});
-
-
-
}
}
}
@@ -807,45 +733,15 @@ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
byte[] array = bs.s;
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.length - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
-
// Plain
{
vh.set(array, i, VALUE_1);
short x = (short) vh.get(array, i);
assertEquals(x, VALUE_1, "get short value");
}
-
-
- if (iAligned) {
- // Volatile
- {
- vh.setVolatile(array, i, VALUE_2);
- short x = (short) vh.getVolatile(array, i);
- assertEquals(x, VALUE_2, "setVolatile short value");
- }
-
- // Lazy
- {
- vh.setRelease(array, i, VALUE_1);
- short x = (short) vh.getAcquire(array, i);
- assertEquals(x, VALUE_1, "setRelease short value");
- }
-
- // Opaque
- {
- vh.setOpaque(array, i, VALUE_2);
- short x = (short) vh.getOpaque(array, i);
- assertEquals(x, VALUE_2, "setOpaque short value");
- }
-
-
- }
}
}
@@ -854,12 +750,10 @@ static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
// Plain
{
@@ -899,15 +793,13 @@ static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
ByteBuffer bb = ByteBuffer.allocate(SIZE);
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
bs.fill(bb.putShort(0, VALUE_2).array());
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
short v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
? rotateLeft(VALUE_2, (i % SIZE) << 3)
diff --git a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template
index 84111ac5eb7c3..a79dbb3547eee 100644
--- a/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template
+++ b/test/jdk/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template
@@ -76,12 +76,12 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
#end[int]
}
VarHandleSource aeh = new VarHandleSource(
- MethodHandles.byteArrayViewVarHandle(arrayType, bo),
+ MethodHandles.byteArrayViewVarHandle(arrayType, bo), false,
endianess, MemoryMode.READ_WRITE);
vhss.add(aeh);
VarHandleSource bbh = new VarHandleSource(
- MethodHandles.byteBufferViewVarHandle(arrayType, bo),
+ MethodHandles.byteBufferViewVarHandle(arrayType, bo), true,
endianess, MemoryMode.READ_WRITE);
vhss.add(bbh);
}
@@ -118,69 +118,91 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ } else {
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
+ }
#if[CAS]
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
-#else[CAS]
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+ } else {
+#end[CAS]
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
+#if[CAS]
+ }
#end[CAS]
#if[AtomicAdd]
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
-#else[AtomicAdd]
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+ } else {
+#end[AtomicAdd]
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
+#if[AtomicAdd]
+ }
#end[AtomicAdd]
+
#if[Bitwise]
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
- assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
-#else[Bitwise]
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
- assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+ if (vhs.supportsAtomicAccess) {
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+ assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+ } else {
+#end[Bitwise]
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
+ assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
+#if[Bitwise]
+ }
#end[Bitwise]
}
@@ -216,9 +238,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
- false));
}
else {
ByteBufferSource bbs = (ByteBufferSource) bav;
@@ -243,9 +262,11 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
cases.add(new VarHandleSourceAccessTestCase(
"index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
false));
- cases.add(new VarHandleSourceAccessTestCase(
- "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
- false));
+ if (bbs.s.isDirect()) {
+ cases.add(new VarHandleSourceAccessTestCase(
+ "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
+ false));
+ }
}
}
}
@@ -279,128 +300,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
checkNPE(() -> {
vh.set(array, ci, VALUE_1);
});
-
- checkNPE(() -> {
- $type$ x = ($type$) vh.getVolatile(array, ci);
- });
-
- checkNPE(() -> {
- $type$ x = ($type$) vh.getAcquire(array, ci);
- });
-
- checkNPE(() -> {
- $type$ x = ($type$) vh.getOpaque(array, ci);
- });
-
- checkNPE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
-#if[CAS]
- checkNPE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkNPE(() -> {
- $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
-
- checkNPE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
-
- checkNPE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkNPE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
-
- checkNPE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
- });
-#end[CAS]
-
-#if[AtomicAdd]
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
- });
-#end[AtomicAdd]
-
-#if[Bitwise]
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
- });
-
- checkNPE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
- });
-#end[Bitwise]
}
static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
@@ -544,7 +443,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
byte[] array = bs.s;
int ci = 1;
-#if[!CAS]
checkUOE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -588,9 +486,7 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
checkUOE(() -> {
$type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
});
-#end[CAS]
-#if[!AtomicAdd]
checkUOE(() -> {
$type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
});
@@ -602,9 +498,7 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
checkUOE(() -> {
$type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
});
-#end[AtomicAdd]
-#if[!Bitwise]
checkUOE(() -> {
$type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
});
@@ -640,7 +534,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
checkUOE(() -> {
$type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
-#end[Bitwise]
}
static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
@@ -655,7 +548,7 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
});
}
- if (readOnly) {
+ if (readOnly && array.isDirect()) {
checkROBE(() -> {
vh.setVolatile(array, ci, VALUE_1);
});
@@ -668,7 +561,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
vh.setOpaque(array, ci, VALUE_1);
});
#if[CAS]
-
checkROBE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
@@ -712,51 +604,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
checkROBE(() -> {
$type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
});
-
-#else[CAS]
- checkUOE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkUOE(() -> {
- $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
-
- checkUOE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
-
- checkUOE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkUOE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
-
- checkUOE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
- });
#end[CAS]
#if[AtomicAdd]
@@ -771,18 +618,6 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
checkROBE(() -> {
$type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
});
-#else[AtomicAdd]
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
- });
#end[AtomicAdd]
#if[Bitwise]
@@ -821,45 +656,10 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
checkROBE(() -> {
$type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
-#else[Bitwise]
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
- });
-
- checkUOE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
- });
#end[Bitwise]
}
- else {
+
+ if (array.isDirect()) {
#if[!CAS]
checkUOE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
@@ -955,148 +755,224 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
$type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
#end[Bitwise]
- }
- }
-
+ } else {
+ checkISE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
- static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
+ checkISE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
- int length = array.length - SIZE + 1;
- for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
- final int ci = i;
+ checkISE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
+#if[!CAS]
+ checkUOE(() -> {
+ boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- checkAIOOBE(() -> {
- $type$ x = ($type$) vh.get(array, ci);
+ checkUOE(() -> {
+ $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
});
- checkAIOOBE(() -> {
- vh.set(array, ci, VALUE_1);
+ checkUOE(() -> {
+ $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
});
- checkAIOOBE(() -> {
- $type$ x = ($type$) vh.getVolatile(array, ci);
+ checkUOE(() -> {
+ $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
});
- checkAIOOBE(() -> {
- $type$ x = ($type$) vh.getAcquire(array, ci);
+ checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
- $type$ x = ($type$) vh.getOpaque(array, ci);
+ checkUOE(() -> {
+ boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
+ checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
- vh.setRelease(array, ci, VALUE_1);
+ checkUOE(() -> {
+ boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
});
-#if[CAS]
- checkAIOOBE(() -> {
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+ });
+
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+ });
+#else[CAS]
+ checkISE(() -> {
boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
});
#end[CAS]
+#if[!AtomicAdd]
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+ });
-#if[AtomicAdd]
- checkAIOOBE(() -> {
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+ });
+
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+ });
+#else[AtomicAdd]
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
});
#end[AtomicAdd]
+#if[!Bitwise]
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+ });
-#if[Bitwise]
- checkAIOOBE(() -> {
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+ });
+
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+ });
+
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+ });
+
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+ });
+
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+ });
+
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+ });
+
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+ });
+
+ checkUOE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+ });
+#else[Bitwise]
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
});
- checkAIOOBE(() -> {
+ checkISE(() -> {
$type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
});
#end[Bitwise]
+ }
+ }
+
+
+ static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
+ VarHandle vh = vhs.s;
+ byte[] array = bs.s;
+
+ int length = array.length - SIZE + 1;
+ for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
+ final int ci = i;
+
+ checkAIOOBE(() -> {
+ $type$ x = ($type$) vh.get(array, ci);
+ });
+ checkAIOOBE(() -> {
+ vh.set(array, ci, VALUE_1);
+ });
}
}
@@ -1120,726 +996,283 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
});
}
- checkIOOBE(() -> {
- $type$ x = ($type$) vh.getVolatile(array, ci);
- });
-
- checkIOOBE(() -> {
- $type$ x = ($type$) vh.getAcquire(array, ci);
- });
-
- checkIOOBE(() -> {
- $type$ x = ($type$) vh.getOpaque(array, ci);
- });
-
- if (!readOnly) {
+ if (array.isDirect()) {
checkIOOBE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
+ $type$ x = ($type$) vh.getVolatile(array, ci);
});
checkIOOBE(() -> {
- vh.setRelease(array, ci, VALUE_1);
+ $type$ x = ($type$) vh.getAcquire(array, ci);
});
checkIOOBE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
+ $type$ x = ($type$) vh.getOpaque(array, ci);
});
+ if (!readOnly) {
+ checkIOOBE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
+
+ checkIOOBE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
+
+ checkIOOBE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
+
#if[CAS]
- checkIOOBE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
+ checkIOOBE(() -> {
+ $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
+ checkIOOBE(() -> {
+ boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+ });
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+ });
#end[CAS]
#if[AtomicAdd]
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+ });
#end[AtomicAdd]
#if[Bitwise]
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
- });
-
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
- });
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+ });
- checkIOOBE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
- });
-#end[Bitwise]
- }
- }
- }
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+ });
- static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+ });
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+ });
- int length = array.length - SIZE + 1;
- for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
- final int ci = i;
-
- if (!iAligned) {
- checkISE(() -> {
- $type$ x = ($type$) vh.getVolatile(array, ci);
- });
-
- checkISE(() -> {
- $type$ x = ($type$) vh.getAcquire(array, ci);
- });
-
- checkISE(() -> {
- $type$ x = ($type$) vh.getOpaque(array, ci);
- });
-
- checkISE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-#if[CAS]
-
- checkISE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
- });
-#end[CAS]
-
-#if[AtomicAdd]
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
- });
-#end[AtomicAdd]
-
-#if[Bitwise]
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
- });
-#end[Bitwise]
- }
- }
- }
-
- static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
- VarHandle vh = vhs.s;
- ByteBuffer array = bs.s;
-
- boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
- int length = array.limit() - SIZE + 1;
- for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
- final int ci = i;
-
- if (!iAligned) {
- checkISE(() -> {
- $type$ x = ($type$) vh.getVolatile(array, ci);
- });
-
- checkISE(() -> {
- $type$ x = ($type$) vh.getAcquire(array, ci);
- });
-
- checkISE(() -> {
- $type$ x = ($type$) vh.getOpaque(array, ci);
- });
-
- if (!readOnly) {
- checkISE(() -> {
- vh.setVolatile(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- vh.setRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- vh.setOpaque(array, ci, VALUE_1);
- });
-
-#if[CAS]
- checkISE(() -> {
- boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
- });
-#end[CAS]
-
-#if[AtomicAdd]
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
- });
-#end[AtomicAdd]
-
-#if[Bitwise]
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
+ checkIOOBE(() -> {
$type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
});
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
- });
-
- checkISE(() -> {
- $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
- });
-#end[Bitwise]
- }
- }
- }
- }
-
- static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
- VarHandle vh = vhs.s;
- byte[] array = bs.s;
-
- int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
-
- bs.fill((byte) 0xff);
- int length = array.length - SIZE + 1;
- for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
-
- // Plain
- {
- vh.set(array, i, VALUE_1);
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1, "get $type$ value");
- }
-
-
- if (iAligned) {
- // Volatile
- {
- vh.setVolatile(array, i, VALUE_2);
- $type$ x = ($type$) vh.getVolatile(array, i);
- assertEquals(x, VALUE_2, "setVolatile $type$ value");
- }
-
- // Lazy
- {
- vh.setRelease(array, i, VALUE_1);
- $type$ x = ($type$) vh.getAcquire(array, i);
- assertEquals(x, VALUE_1, "setRelease $type$ value");
- }
-
- // Opaque
- {
- vh.setOpaque(array, i, VALUE_2);
- $type$ x = ($type$) vh.getOpaque(array, i);
- assertEquals(x, VALUE_2, "setOpaque $type$ value");
- }
-#if[CAS]
-
- vh.set(array, i, VALUE_1);
-
- // Compare
- {
- boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
- assertEquals(r, true, "success compareAndSet $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_2, "success compareAndSet $type$ value");
- }
-
- {
- boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
- assertEquals(r, false, "failing compareAndSet $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing compareAndSet $type$ value");
- }
-
- {
- $type$ r = ($type$) vh.compareAndExchange(array, i, VALUE_2, VALUE_1);
- assertEquals(r, VALUE_2, "success compareAndExchange $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1, "success compareAndExchange $type$ value");
- }
-
- {
- $type$ r = ($type$) vh.compareAndExchange(array, i, VALUE_2, VALUE_3);
- assertEquals(r, VALUE_1, "failing compareAndExchange $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing compareAndExchange $type$ value");
- }
-
- {
- $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
- assertEquals(r, VALUE_1, "success compareAndExchangeAcquire $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_2, "success compareAndExchangeAcquire $type$ value");
- }
-
- {
- $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
- assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire $type$ value");
- }
-
- {
- $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
- assertEquals(r, VALUE_2, "success compareAndExchangeRelease $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1, "success compareAndExchangeRelease $type$ value");
- }
-
- {
- $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
- assertEquals(r, VALUE_1, "failing compareAndExchangeRelease $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing compareAndExchangeRelease $type$ value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_2);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetPlain $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_2, "success weakCompareAndSetPlain $type$ value");
- }
-
- {
- boolean success = vh.weakCompareAndSetPlain(array, i, VALUE_1, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetPlain $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing weakCompareAndSetPlain $type$ value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetAcquire $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1, "success weakCompareAndSetAcquire $type$");
- }
-
- {
- boolean success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetAcquire $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing weakCompareAndSetAcquire $type$ value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSetRelease $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_2, "success weakCompareAndSetRelease $type$");
- }
-
- {
- boolean success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSetRelease $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_2, "failing weakCompareAndSetRelease $type$ value");
- }
-
- {
- boolean success = false;
- for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
- success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_1);
- if (!success) weakDelay();
- }
- assertEquals(success, true, "success weakCompareAndSet $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1, "success weakCompareAndSet $type$");
- }
-
- {
- boolean success = vh.weakCompareAndSet(array, i, VALUE_2, VALUE_3);
- assertEquals(success, false, "failing weakCompareAndSet $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1, "failing weakCompareAndSet $type$ value");
- }
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+ });
- // Compare set and get
- {
- vh.set(array, i, VALUE_1);
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+ });
- $type$ o = ($type$) vh.getAndSet(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSet $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSet $type$ value");
+ checkIOOBE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+ });
+#end[Bitwise]
}
+ }
+ }
+ }
- {
- vh.set(array, i, VALUE_1);
+ static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
+ VarHandle vh = vhs.s;
+ ByteBuffer array = bs.s;
- $type$ o = ($type$) vh.getAndSetAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSetAcquire $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSetAcquire $type$ value");
- }
+ boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
+ int misalignmentAtZero = array.alignmentOffset(0, SIZE);
- {
- vh.set(array, i, VALUE_1);
+ int length = array.limit() - SIZE + 1;
+ for (int i = 0; i < length; i++) {
+ boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ final int ci = i;
- $type$ o = ($type$) vh.getAndSetRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndSetRelease $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_2, "getAndSetRelease $type$ value");
- }
-#end[CAS]
+ if (!iAligned) {
+ checkISE(() -> {
+ $type$ x = ($type$) vh.getVolatile(array, ci);
+ });
-#if[AtomicAdd]
- // get and add, add and get
- {
- vh.set(array, i, VALUE_1);
+ checkISE(() -> {
+ $type$ x = ($type$) vh.getAcquire(array, ci);
+ });
- $type$ o = ($type$) vh.getAndAdd(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndAdd $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1 + VALUE_2, "getAndAdd $type$ value");
- }
+ checkISE(() -> {
+ $type$ x = ($type$) vh.getOpaque(array, ci);
+ });
- {
- vh.set(array, i, VALUE_1);
+ if (!readOnly) {
+ checkISE(() -> {
+ vh.setVolatile(array, ci, VALUE_1);
+ });
- $type$ o = ($type$) vh.getAndAddAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndAddAcquire $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1 + VALUE_2, "getAndAddAcquire $type$ value");
- }
+ checkISE(() -> {
+ vh.setRelease(array, ci, VALUE_1);
+ });
- {
- vh.set(array, i, VALUE_1);
+ checkISE(() -> {
+ vh.setOpaque(array, ci, VALUE_1);
+ });
+#if[CAS]
+ checkISE(() -> {
+ boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- $type$ o = ($type$) vh.getAndAddRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndAddRelease $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1 + VALUE_2, "getAndAddRelease $type$ value");
- }
-#end[AtomicAdd]
+ checkISE(() -> {
+ $type$ r = ($type$) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
+ });
-#if[Bitwise]
- // get and bitwise or
- {
- vh.set(array, i, VALUE_1);
+ checkISE(() -> {
+ $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
+ });
- $type$ o = ($type$) vh.getAndBitwiseOr(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseOr $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOr $type$ value");
- }
+ checkISE(() -> {
+ $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
+ });
- {
- vh.set(array, i, VALUE_1);
+ checkISE(() -> {
+ boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
+ });
- $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseOrAcquire $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrAcquire $type$ value");
- }
+ checkISE(() -> {
+ boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
+ });
- {
- vh.set(array, i, VALUE_1);
+ checkISE(() -> {
+ boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
+ });
- $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseOrRelease $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1 | VALUE_2, "getAndBitwiseOrRelease $type$ value");
- }
+ checkISE(() -> {
+ boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
+ });
- // get and bitwise and
- {
- vh.set(array, i, VALUE_1);
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
+ });
- $type$ o = ($type$) vh.getAndBitwiseAnd(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseAnd $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAnd $type$ value");
- }
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndSetAcquire(array, ci, VALUE_1);
+ });
- {
- vh.set(array, i, VALUE_1);
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndSetRelease(array, ci, VALUE_1);
+ });
+#end[CAS]
+#if[AtomicAdd]
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
+ });
- $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseAndAcquire $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndAcquire $type$ value");
- }
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndAddAcquire(array, ci, VALUE_1);
+ });
- {
- vh.set(array, i, VALUE_1);
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndAddRelease(array, ci, VALUE_1);
+ });
+#end[AtomicAdd]
+#if[Bitwise]
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseOr(array, ci, VALUE_1);
+ });
- $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseAndRelease $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1 & VALUE_2, "getAndBitwiseAndRelease $type$ value");
- }
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
+ });
- // get and bitwise xor
- {
- vh.set(array, i, VALUE_1);
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
+ });
- $type$ o = ($type$) vh.getAndBitwiseXor(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseXor $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXor $type$ value");
- }
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseAnd(array, ci, VALUE_1);
+ });
- {
- vh.set(array, i, VALUE_1);
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
+ });
- $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseXorAcquire $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorAcquire $type$ value");
- }
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
+ });
- {
- vh.set(array, i, VALUE_1);
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseXor(array, ci, VALUE_1);
+ });
- $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, i, VALUE_2);
- assertEquals(o, VALUE_1, "getAndBitwiseXorRelease $type$");
- $type$ x = ($type$) vh.get(array, i);
- assertEquals(x, VALUE_1 ^ VALUE_2, "getAndBitwiseXorRelease $type$ value");
- }
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
+ });
+
+ checkISE(() -> {
+ $type$ o = ($type$) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
+ });
#end[Bitwise]
+ }
+ }
+ }
+ }
+
+ static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
+ VarHandle vh = vhs.s;
+ byte[] array = bs.s;
+
+ bs.fill((byte) 0xff);
+ int length = array.length - SIZE + 1;
+ for (int i = 0; i < length; i++) {
+ // Plain
+ {
+ vh.set(array, i, VALUE_1);
+ $type$ x = ($type$) vh.get(array, i);
+ assertEquals(x, VALUE_1, "get $type$ value");
}
}
}
@@ -1849,12 +1282,10 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
bs.fill((byte) 0xff);
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
// Plain
{
@@ -2169,15 +1600,13 @@ public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
VarHandle vh = vhs.s;
ByteBuffer array = bs.s;
- int misalignmentAtZero = array.alignmentOffset(0, SIZE);
-
ByteBuffer bb = ByteBuffer.allocate(SIZE);
bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
bs.fill(bb.put$Type$(0, VALUE_2).array());
int length = array.limit() - SIZE + 1;
for (int i = 0; i < length; i++) {
- boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
+ boolean iAligned = array.isDirect() ? ((i + array.alignmentOffset(0, SIZE)) & (SIZE - 1)) == 0 : false;
$type$ v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
? rotateLeft(VALUE_2, (i % SIZE) << 3)
diff --git a/test/jdk/java/nio/Buffer/Basic-X.java.template b/test/jdk/java/nio/Buffer/Basic-X.java.template
index d26d3e3e6222b..4cd61ea8043cf 100644
--- a/test/jdk/java/nio/Buffer/Basic-X.java.template
+++ b/test/jdk/java/nio/Buffer/Basic-X.java.template
@@ -384,7 +384,7 @@ public class Basic$Type$
// unit size not a power of two
catchIllegalArgument(b, () -> b.alignmentOffset(0, _us));
} else {
- if (direct || us <= 8) {
+ if (direct || us == 1) {
b.alignmentOffset(0, us);
} else {
// unit size > 8 with non-direct buffer
@@ -394,12 +394,11 @@ public class Basic$Type$
}
}
- // Probe for long misalignment at index zero for a newly created buffer
- ByteBuffer empty =
- direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
- int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
-
if (direct) {
+ // Probe for long misalignment at index zero for a newly created buffer
+ ByteBuffer empty = ByteBuffer.allocateDirect(0);
+ int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
+
// Freshly created direct byte buffers should be aligned at index 0
// for ref and primitive values (see Unsafe.allocateMemory)
if (longMisalignmentAtZero != 0) {
@@ -407,78 +406,67 @@ public class Basic$Type$
+ " for ref and primitive values "
+ longMisalignmentAtZero);
}
- } else {
- // For heap byte buffers misalignment may occur on 32-bit systems
- // where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0
- // Note the GC will preserve alignment of the base address of the
- // array
- if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8
- != longMisalignmentAtZero) {
- fail("Heap byte buffer misaligned at index 0"
- + " for ref and primitive values "
- + longMisalignmentAtZero);
- }
- }
- // Ensure test buffer is correctly aligned at index 0
- if (b.alignmentOffset(0, 8) != longMisalignmentAtZero)
- fail("Test input buffer not correctly aligned at index 0", b);
+ // Ensure test buffer is correctly aligned at index 0
+ if (b.alignmentOffset(0, 8) != longMisalignmentAtZero)
+ fail("Test input buffer not correctly aligned at index 0", b);
- // Test misalignment values
- for (int us : new int[]{1, 2, 4, 8}) {
- for (int i = 0; i < us * 2; i++) {
- int am = b.alignmentOffset(i, us);
- int expectedAm = (longMisalignmentAtZero + i) % us;
+ // Test misalignment values
+ for (int us : new int[]{1, 2, 4, 8}) {
+ for (int i = 0; i < us * 2; i++) {
+ int am = b.alignmentOffset(i, us);
+ int expectedAm = (longMisalignmentAtZero + i) % us;
- if (am != expectedAm) {
- String f = "b.alignmentOffset(%d, %d) == %d incorrect, expected %d";
- fail(String.format(f, i, us, am, expectedAm));
+ if (am != expectedAm) {
+ String f = "b.alignmentOffset(%d, %d) == %d incorrect, expected %d";
+ fail(String.format(f, i, us, am, expectedAm));
+ }
}
}
- }
- // Created aligned slice to test against
- int ap = 8 - longMisalignmentAtZero;
- int al = b.limit() - b.alignmentOffset(b.limit(), 8);
- ByteBuffer ab = b.position(ap).limit(al).
- slice();
- if (ab.limit() == 0) {
- fail("Test input buffer not sufficiently sized to cover" +
- " an aligned region for all values", b);
- }
- if (ab.alignmentOffset(0, 8) != 0)
- fail("Aligned test input buffer not correctly aligned at index 0", ab);
-
- for (int us : new int[]{1, 2, 4, 8}) {
- for (int p = 1; p < 16; p++) {
- int l = ab.limit() - p;
-
- ByteBuffer as = ab.slice().position(p).limit(l).
- alignedSlice(us);
-
- ck(as, 0, as.position());
- ck(as, as.capacity(), as.limit());
- if (b.isDirect() != as.isDirect())
- fail("Lost direction", as);
- if (b.isReadOnly() != as.isReadOnly())
- fail("Lost read-only", as);
-
- if (as.alignmentOffset(0, us) != 0)
- fail("Buffer not correctly aligned at index 0", as);
-
- if (as.alignmentOffset(as.limit(), us) != 0)
- fail("Buffer not correctly aligned at limit", as);
-
- int p_mod = ab.alignmentOffset(p, us);
- int l_mod = ab.alignmentOffset(l, us);
- // Round up position
- p = (p_mod > 0) ? p + (us - p_mod) : p;
- // Round down limit
- l = l - l_mod;
-
- int ec = l - p;
- if (as.limit() != ec) {
- fail("Buffer capacity incorrect, expected: " + ec, as);
+ // Created aligned slice to test against
+ int ap = 8 - longMisalignmentAtZero;
+ int al = b.limit() - b.alignmentOffset(b.limit(), 8);
+ ByteBuffer ab = b.position(ap).limit(al).
+ slice();
+ if (ab.limit() == 0) {
+ fail("Test input buffer not sufficiently sized to cover" +
+ " an aligned region for all values", b);
+ }
+ if (ab.alignmentOffset(0, 8) != 0)
+ fail("Aligned test input buffer not correctly aligned at index 0", ab);
+
+ for (int us : new int[]{1, 2, 4, 8}) {
+ for (int p = 1; p < 16; p++) {
+ int l = ab.limit() - p;
+
+ ByteBuffer as = ab.slice().position(p).limit(l).
+ alignedSlice(us);
+
+ ck(as, 0, as.position());
+ ck(as, as.capacity(), as.limit());
+ if (b.isDirect() != as.isDirect())
+ fail("Lost direction", as);
+ if (b.isReadOnly() != as.isReadOnly())
+ fail("Lost read-only", as);
+
+ if (as.alignmentOffset(0, us) != 0)
+ fail("Buffer not correctly aligned at index 0", as);
+
+ if (as.alignmentOffset(as.limit(), us) != 0)
+ fail("Buffer not correctly aligned at limit", as);
+
+ int p_mod = ab.alignmentOffset(p, us);
+ int l_mod = ab.alignmentOffset(l, us);
+ // Round up position
+ p = (p_mod > 0) ? p + (us - p_mod) : p;
+ // Round down limit
+ l = l - l_mod;
+
+ int ec = l - p;
+ if (as.limit() != ec) {
+ fail("Buffer capacity incorrect, expected: " + ec, as);
+ }
}
}
}
diff --git a/test/jdk/java/nio/Buffer/BasicByte.java b/test/jdk/java/nio/Buffer/BasicByte.java
index b3db0b0c1053b..05bf8e523bbea 100644
--- a/test/jdk/java/nio/Buffer/BasicByte.java
+++ b/test/jdk/java/nio/Buffer/BasicByte.java
@@ -384,7 +384,7 @@ private static void testAlign(final ByteBuffer b, boolean direct) {
// unit size not a power of two
catchIllegalArgument(b, () -> b.alignmentOffset(0, _us));
} else {
- if (direct || us <= 8) {
+ if (direct || us == 1) {
b.alignmentOffset(0, us);
} else {
// unit size > 8 with non-direct buffer
@@ -394,12 +394,11 @@ private static void testAlign(final ByteBuffer b, boolean direct) {
}
}
- // Probe for long misalignment at index zero for a newly created buffer
- ByteBuffer empty =
- direct ? ByteBuffer.allocateDirect(0) : ByteBuffer.allocate(0);
- int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
-
if (direct) {
+ // Probe for long misalignment at index zero for a newly created buffer
+ ByteBuffer empty = ByteBuffer.allocateDirect(0);
+ int longMisalignmentAtZero = empty.alignmentOffset(0, 8);
+
// Freshly created direct byte buffers should be aligned at index 0
// for ref and primitive values (see Unsafe.allocateMemory)
if (longMisalignmentAtZero != 0) {
@@ -407,78 +406,67 @@ private static void testAlign(final ByteBuffer b, boolean direct) {
+ " for ref and primitive values "
+ longMisalignmentAtZero);
}
- } else {
- // For heap byte buffers misalignment may occur on 32-bit systems
- // where Unsafe.ARRAY_BYTE_BASE_OFFSET % 8 == 4 and not 0
- // Note the GC will preserve alignment of the base address of the
- // array
- if (jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET % 8
- != longMisalignmentAtZero) {
- fail("Heap byte buffer misaligned at index 0"
- + " for ref and primitive values "
- + longMisalignmentAtZero);
- }
- }
- // Ensure test buffer is correctly aligned at index 0
- if (b.alignmentOffset(0, 8) != longMisalignmentAtZero)
- fail("Test input buffer not correctly aligned at index 0", b);
+ // Ensure test buffer is correctly aligned at index 0
+ if (b.alignmentOffset(0, 8) != longMisalignmentAtZero)
+ fail("Test input buffer not correctly aligned at index 0", b);
- // Test misalignment values
- for (int us : new int[]{1, 2, 4, 8}) {
- for (int i = 0; i < us * 2; i++) {
- int am = b.alignmentOffset(i, us);
- int expectedAm = (longMisalignmentAtZero + i) % us;
+ // Test misalignment values
+ for (int us : new int[]{1, 2, 4, 8}) {
+ for (int i = 0; i < us * 2; i++) {
+ int am = b.alignmentOffset(i, us);
+ int expectedAm = (longMisalignmentAtZero + i) % us;
- if (am != expectedAm) {
- String f = "b.alignmentOffset(%d, %d) == %d incorrect, expected %d";
- fail(String.format(f, i, us, am, expectedAm));
+ if (am != expectedAm) {
+ String f = "b.alignmentOffset(%d, %d) == %d incorrect, expected %d";
+ fail(String.format(f, i, us, am, expectedAm));
+ }
}
}
- }
- // Created aligned slice to test against
- int ap = 8 - longMisalignmentAtZero;
- int al = b.limit() - b.alignmentOffset(b.limit(), 8);
- ByteBuffer ab = b.position(ap).limit(al).
- slice();
- if (ab.limit() == 0) {
- fail("Test input buffer not sufficiently sized to cover" +
- " an aligned region for all values", b);
- }
- if (ab.alignmentOffset(0, 8) != 0)
- fail("Aligned test input buffer not correctly aligned at index 0", ab);
-
- for (int us : new int[]{1, 2, 4, 8}) {
- for (int p = 1; p < 16; p++) {
- int l = ab.limit() - p;
-
- ByteBuffer as = ab.slice().position(p).limit(l).
- alignedSlice(us);
-
- ck(as, 0, as.position());
- ck(as, as.capacity(), as.limit());
- if (b.isDirect() != as.isDirect())
- fail("Lost direction", as);
- if (b.isReadOnly() != as.isReadOnly())
- fail("Lost read-only", as);
-
- if (as.alignmentOffset(0, us) != 0)
- fail("Buffer not correctly aligned at index 0", as);
-
- if (as.alignmentOffset(as.limit(), us) != 0)
- fail("Buffer not correctly aligned at limit", as);
-
- int p_mod = ab.alignmentOffset(p, us);
- int l_mod = ab.alignmentOffset(l, us);
- // Round up position
- p = (p_mod > 0) ? p + (us - p_mod) : p;
- // Round down limit
- l = l - l_mod;
-
- int ec = l - p;
- if (as.limit() != ec) {
- fail("Buffer capacity incorrect, expected: " + ec, as);
+ // Created aligned slice to test against
+ int ap = 8 - longMisalignmentAtZero;
+ int al = b.limit() - b.alignmentOffset(b.limit(), 8);
+ ByteBuffer ab = b.position(ap).limit(al).
+ slice();
+ if (ab.limit() == 0) {
+ fail("Test input buffer not sufficiently sized to cover" +
+ " an aligned region for all values", b);
+ }
+ if (ab.alignmentOffset(0, 8) != 0)
+ fail("Aligned test input buffer not correctly aligned at index 0", ab);
+
+ for (int us : new int[]{1, 2, 4, 8}) {
+ for (int p = 1; p < 16; p++) {
+ int l = ab.limit() - p;
+
+ ByteBuffer as = ab.slice().position(p).limit(l).
+ alignedSlice(us);
+
+ ck(as, 0, as.position());
+ ck(as, as.capacity(), as.limit());
+ if (b.isDirect() != as.isDirect())
+ fail("Lost direction", as);
+ if (b.isReadOnly() != as.isReadOnly())
+ fail("Lost read-only", as);
+
+ if (as.alignmentOffset(0, us) != 0)
+ fail("Buffer not correctly aligned at index 0", as);
+
+ if (as.alignmentOffset(as.limit(), us) != 0)
+ fail("Buffer not correctly aligned at limit", as);
+
+ int p_mod = ab.alignmentOffset(p, us);
+ int l_mod = ab.alignmentOffset(l, us);
+ // Round up position
+ p = (p_mod > 0) ? p + (us - p_mod) : p;
+ // Round down limit
+ l = l - l_mod;
+
+ int ec = l - p;
+ if (as.limit() != ec) {
+ fail("Buffer capacity incorrect, expected: " + ec, as);
+ }
}
}
}
diff --git a/test/jdk/java/nio/Buffer/BasicChar.java b/test/jdk/java/nio/Buffer/BasicChar.java
index c1358847ad25c..8d6cfd1eecf91 100644
--- a/test/jdk/java/nio/Buffer/BasicChar.java
+++ b/test/jdk/java/nio/Buffer/BasicChar.java
@@ -527,18 +527,6 @@ private static void checkSlice(CharBuffer b, CharBuffer slice) {
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/jdk/java/nio/Buffer/BasicDouble.java b/test/jdk/java/nio/Buffer/BasicDouble.java
index d74fe3db0b7aa..4b1cde85a0843 100644
--- a/test/jdk/java/nio/Buffer/BasicDouble.java
+++ b/test/jdk/java/nio/Buffer/BasicDouble.java
@@ -527,18 +527,6 @@ private static void checkSlice(DoubleBuffer b, DoubleBuffer slice) {
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/jdk/java/nio/Buffer/BasicFloat.java b/test/jdk/java/nio/Buffer/BasicFloat.java
index e60fb7b203c54..654dfe72fbe6d 100644
--- a/test/jdk/java/nio/Buffer/BasicFloat.java
+++ b/test/jdk/java/nio/Buffer/BasicFloat.java
@@ -527,18 +527,6 @@ private static void checkSlice(FloatBuffer b, FloatBuffer slice) {
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/jdk/java/nio/Buffer/BasicInt.java b/test/jdk/java/nio/Buffer/BasicInt.java
index 2d0f591e892aa..4e1b8a237b4d7 100644
--- a/test/jdk/java/nio/Buffer/BasicInt.java
+++ b/test/jdk/java/nio/Buffer/BasicInt.java
@@ -527,18 +527,6 @@ private static void checkSlice(IntBuffer b, IntBuffer slice) {
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/jdk/java/nio/Buffer/BasicLong.java b/test/jdk/java/nio/Buffer/BasicLong.java
index 04807c3461bba..02b30e879b6e7 100644
--- a/test/jdk/java/nio/Buffer/BasicLong.java
+++ b/test/jdk/java/nio/Buffer/BasicLong.java
@@ -527,18 +527,6 @@ private static void checkSlice(LongBuffer b, LongBuffer slice) {
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/jdk/java/nio/Buffer/BasicShort.java b/test/jdk/java/nio/Buffer/BasicShort.java
index bbf1b7a7fa4ea..22c6dd4b59d8a 100644
--- a/test/jdk/java/nio/Buffer/BasicShort.java
+++ b/test/jdk/java/nio/Buffer/BasicShort.java
@@ -527,18 +527,6 @@ private static void checkSlice(ShortBuffer b, ShortBuffer slice) {
-
-
-
-
-
-
-
-
-
-
-
-
From 130f429c6fd1e31fbdbd523419f8d8447e9da0e5 Mon Sep 17 00:00:00 2001
From: Stefan Johansson
Date: Wed, 14 Feb 2024 14:59:34 +0000
Subject: [PATCH 32/36] 8325403: Add SystemGC JMH benchmarks
Reviewed-by: ecaspole, ayang, tschatzl
---
.../openjdk/bench/vm/gc/systemgc/AllDead.java | 62 +++++++++++
.../openjdk/bench/vm/gc/systemgc/AllLive.java | 61 +++++++++++
.../systemgc/DifferentObjectSizesArray.java | 68 ++++++++++++
.../systemgc/DifferentObjectSizesHashMap.java | 70 ++++++++++++
.../systemgc/DifferentObjectSizesTreeMap.java | 69 ++++++++++++
.../vm/gc/systemgc/GarbageGenerator.java | 101 ++++++++++++++++++
.../vm/gc/systemgc/HalfDeadFirstPart.java | 66 ++++++++++++
.../vm/gc/systemgc/HalfDeadInterleaved.java | 69 ++++++++++++
.../systemgc/HalfDeadInterleavedChunks.java | 68 ++++++++++++
.../vm/gc/systemgc/HalfDeadSecondPart.java | 66 ++++++++++++
.../vm/gc/systemgc/HalfHashedHalfDead.java | 73 +++++++++++++
.../bench/vm/gc/systemgc/NoObjects.java | 51 +++++++++
.../bench/vm/gc/systemgc/OneBigObject.java | 61 +++++++++++
13 files changed, 885 insertions(+)
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/AllDead.java
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/AllLive.java
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesArray.java
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesHashMap.java
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesTreeMap.java
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/GarbageGenerator.java
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadFirstPart.java
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleaved.java
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleavedChunks.java
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadSecondPart.java
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/HalfHashedHalfDead.java
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/NoObjects.java
create mode 100644 test/micro/org/openjdk/bench/vm/gc/systemgc/OneBigObject.java
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/AllDead.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/AllDead.java
new file mode 100644
index 0000000000000..12e1ff25454e8
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/AllDead.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.bench.vm.gc.systemgc;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"})
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Benchmark)
+public class AllDead {
+
+ /*
+ * Test the System GC when all allocated objects are dead.
+ *
+ * The jvmArgs are provided to avoid GCs during object creation.
+ */
+
+ static ArrayList holder;
+
+ @Setup(Level.Iteration)
+ public void generateGarbage() {
+ holder = GarbageGenerator.generateObjectArrays();
+ holder = null;
+ }
+
+ @Benchmark
+ public void gc() {
+ System.gc();
+ }
+}
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/AllLive.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/AllLive.java
new file mode 100644
index 0000000000000..ddd9f56cf6022
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/AllLive.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.bench.vm.gc.systemgc;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"})
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Benchmark)
+public class AllLive {
+
+ /*
+ * Test the System GC when all allocated objects are live.
+ *
+ * The jvmArgs are provided to avoid GCs during object creation.
+ */
+
+ static ArrayList holder;
+
+ @Setup(Level.Iteration)
+ public void generateGarbage() {
+ holder = GarbageGenerator.generateObjectArrays();
+ }
+
+ @Benchmark
+ public void gc() {
+ System.gc();
+ }
+}
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesArray.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesArray.java
new file mode 100644
index 0000000000000..a4dcfdaaeb594
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesArray.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.bench.vm.gc.systemgc;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"})
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Benchmark)
+public class DifferentObjectSizesArray {
+
+ /*
+ * Test the System GC when 2/3 of the objects are live
+ * and kept reachable through an object array.
+ *
+ * The jvmArgs are provided to avoid GCs during object creation.
+ */
+
+ static Object[] largeObjArray;
+
+ @Setup(Level.Iteration)
+ public void generateGarbage() {
+ largeObjArray = GarbageGenerator.generateAndFillLargeObjArray(false);
+ // Removing a third of the objects and keeping a good
+ // distribution of sizes.
+ for (int i = 0; i < largeObjArray.length; i++) {
+ if (i%3 == 0) {
+ largeObjArray[i] = null;
+ }
+ }
+ }
+
+ @Benchmark
+ public void gc() {
+ System.gc();
+ }
+}
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesHashMap.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesHashMap.java
new file mode 100644
index 0000000000000..839147251611a
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesHashMap.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.bench.vm.gc.systemgc;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.HashMap;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"})
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Benchmark)
+public class DifferentObjectSizesHashMap {
+
+ /*
+ * Test the System GC when 2/3 of the objects are live
+ * and kept reachable through a HashMap.
+ *
+ * The jvmArgs are provided to avoid GCs during object creation.
+ */
+
+ static HashMap largeMap;
+
+ @Setup(Level.Iteration)
+ public void generateGarbage() {
+ largeMap = GarbageGenerator.generateAndFillHashMap(false);
+ int numberOfObjects = largeMap.size();
+ // Removing a third of the objects and keeping a good
+ // distribution of sizes.
+ for (int i = 0; i < numberOfObjects; i++) {
+ if (i%3 == 0) {
+ largeMap.remove(i);
+ }
+ }
+ }
+
+ @Benchmark
+ public void gc() {
+ System.gc();
+ }
+}
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesTreeMap.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesTreeMap.java
new file mode 100644
index 0000000000000..66aaffff693a2
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/DifferentObjectSizesTreeMap.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.bench.vm.gc.systemgc;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"})
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Benchmark)
+public class DifferentObjectSizesTreeMap {
+
+ /*
+ * Test the System GC when 2/3 of the objects are live
+ * and kept reachable through a TreeMap.
+ *
+ * The jvmArgs are provided to avoid GCs during object creation.
+ */
+ static TreeMap largeMap;
+
+ @Setup(Level.Iteration)
+ public void generateGarbage() {
+ largeMap = GarbageGenerator.generateAndFillTreeMap(false);
+ int numberOfObjects = largeMap.size();
+ // Removing a third of the objects and keeping a good
+ // distribution of sizes.
+ for (int i = 0; i < numberOfObjects; i++) {
+ if (i%3 == 0) {
+ largeMap.remove(i);
+ }
+ }
+ }
+
+ @Benchmark
+ public void gc() {
+ System.gc();
+ }
+}
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/GarbageGenerator.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/GarbageGenerator.java
new file mode 100644
index 0000000000000..12f53ec257f67
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/GarbageGenerator.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.bench.vm.gc.systemgc;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.TreeMap;
+
+public class GarbageGenerator {
+ static final int K = 1024;
+ static final int M = K * K;
+
+ /**
+ * Generates roughly 1GB of objects stored as an arraylist of
+ * 1024 Object[]. Each Objects[] stores 1024 byte[] of size 1024.
+ *
+ * @return ArrayList of 1024 Objects[].
+ */
+ static ArrayList generateObjectArrays() {
+ ArrayList tmp = new ArrayList<>();
+ for (int i = 0; i < GarbageGenerator.K; i++) {
+ Object[] x = new Object[GarbageGenerator.K];
+ for (int j=0; j < GarbageGenerator.K; j++) {
+ x[j] = new byte[GarbageGenerator.K];
+ }
+ tmp.add(x);
+ }
+ return tmp;
+ }
+
+ /**
+ * Allocating an Object[] with elements and filling each slot with
+ * byte[]. If sameSize is true all byte[] are 1024 large, otherwise
+ * there are 8 different sizes from K/8 to 16K.
+ *
+ * @param sameSize all objects are 1K large.
+ * @return
+ */
+ public static Object[] generateAndFillLargeObjArray(boolean sameSize) {
+ // Aiming for ~ 1gb of heap usage. For different sizes
+ // the average size is ~ 4k.
+ Object[] tmp = new Object[sameSize ? M : M / 4];
+ for (int i = 0; i < tmp.length; i++) {
+ if (sameSize) {
+ tmp[i] = new byte[K];
+ } else {
+ int multiplier = 1 << (i % 8); // 1,2,4,8,16,32,64,128
+ tmp[i] = new byte[(K / 8) * multiplier ];
+ }
+ }
+ return tmp;
+ }
+
+ public static HashMap generateAndFillHashMap(boolean sameSize) {
+ HashMap tmp = new HashMap<>();
+ int numberOfObjects = sameSize ? M : M / 4;
+ for (int i = 0; i < numberOfObjects; i++) {
+ if (sameSize) {
+ tmp.put(i, new byte[K]);
+ } else {
+ int multiplier = 1 << (i % 8); // 1,2,4,8,16,32,64,128
+ tmp.put(i, new byte[(K / 8) * multiplier]);
+ }
+ }
+ return tmp;
+ }
+
+ public static TreeMap generateAndFillTreeMap(boolean sameSize) {
+ TreeMap tmp = new TreeMap<>();
+ int numberOfObjects = sameSize ? M : M / 4;
+ for (int i = 0; i < numberOfObjects; i++) {
+ if (sameSize) {
+ tmp.put(i, new byte[K]);
+ } else {
+ int multiplier = 1 << (i % 8); // 1,2,4,8,16,32,64,128
+ tmp.put(i, new byte[(K / 8) * multiplier]);
+ }
+ }
+ return tmp;
+ }
+}
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadFirstPart.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadFirstPart.java
new file mode 100644
index 0000000000000..80cefbfe10f86
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadFirstPart.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.bench.vm.gc.systemgc;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"})
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Benchmark)
+public class HalfDeadFirstPart {
+
+ /*
+ * Test the System GC when half of the objects are dead.
+ * In this test the first half of the objects are cleared.
+ *
+ * The jvmArgs are provided to avoid GCs during object creation.
+ */
+
+ static ArrayList holder;
+
+ @Setup(Level.Iteration)
+ public void generateGarbage() {
+ holder = GarbageGenerator.generateObjectArrays();
+ // Clearing every other object array in the holder
+ for (int i = 0; i < holder.size() / 2; i++) {
+ holder.set(i, null);
+ }
+ }
+
+ @Benchmark
+ public void gc() {
+ System.gc();
+ }
+}
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleaved.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleaved.java
new file mode 100644
index 0000000000000..bda9ccfa2135b
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleaved.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.bench.vm.gc.systemgc;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"})
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Benchmark)
+public class HalfDeadInterleaved {
+
+ /*
+ * Test the System GC when half of the objects are dead.
+ * In this test every other object is cleared.
+ *
+ * The jvmArgs are provided to avoid GCs during object creation.
+ */
+
+ static ArrayList holder;
+
+ @Setup(Level.Iteration)
+ public void generateGarbage() {
+ holder = GarbageGenerator.generateObjectArrays();
+ for (Object[] objArray : holder) {
+ for (int i=0; i < objArray.length; i++) {
+ if ((i & 1) == 1) {
+ objArray[i] = null;
+ }
+ }
+ }
+ }
+
+ @Benchmark
+ public void gc() {
+ System.gc();
+ }
+}
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleavedChunks.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleavedChunks.java
new file mode 100644
index 0000000000000..06955381f5ca9
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadInterleavedChunks.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.bench.vm.gc.systemgc;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"})
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Benchmark)
+public class HalfDeadInterleavedChunks {
+
+ /*
+ * Test the System GC when half of the objects are dead.
+ * In this test every other array of objects is cleared.
+ *
+ * The jvmArgs are provided to avoid GCs during object creation.
+ */
+
+ static ArrayList holder;
+
+ @Setup(Level.Iteration)
+ public void generateGarbage() {
+ holder = GarbageGenerator.generateObjectArrays();
+ // Clearing every other object array in the holder
+ for (int i = 0; i < holder.size(); i++) {
+ if ((i & 1) == 1) {
+ holder.set(i, null);
+ }
+ }
+ }
+
+ @Benchmark
+ public void gc() {
+ System.gc();
+ }
+}
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadSecondPart.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadSecondPart.java
new file mode 100644
index 0000000000000..89606f5a07a99
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfDeadSecondPart.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.bench.vm.gc.systemgc;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"})
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Benchmark)
+public class HalfDeadSecondPart {
+
+ /*
+ * Test the System GC when half of the objects are dead.
+ * In this test the second half of the objects are cleared.
+ *
+ * The jvmArgs are provided to avoid GCs during object creation.
+ */
+
+ static ArrayList holder;
+
+ @Setup(Level.Iteration)
+ public void generateGarbage() {
+ holder = GarbageGenerator.generateObjectArrays();
+ // Clearing every other object array in the holder
+ for (int i = holder.size() / 2; i < holder.size(); i++) {
+ holder.set(i, null);
+ }
+ }
+
+ @Benchmark
+ public void gc() {
+ System.gc();
+ }
+}
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfHashedHalfDead.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfHashedHalfDead.java
new file mode 100644
index 0000000000000..6692e02a13576
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/HalfHashedHalfDead.java
@@ -0,0 +1,73 @@
+/*
+ * 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 org.openjdk.bench.vm.gc.systemgc;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"})
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Benchmark)
+public class HalfHashedHalfDead {
+
+ /*
+ * Test the System GC when there is a big amount of objects
+ * with hash codes calculated.
+ *
+ * The jvmArgs are provided to avoid GCs during object creation.
+ */
+
+ static ArrayList holder;
+
+ @Setup(Level.Iteration)
+ public void generateGarbage() {
+ holder = GarbageGenerator.generateObjectArrays();
+ // Keeping half the objects and calculating the hash code to
+ // force some GCs to preserve marks.
+ for (Object[] objectArray: holder) {
+ for (int i = 0; i < objectArray.length; i++) {
+ if (i % 2 == 0) {
+ objectArray[i].hashCode();
+ } else {
+ objectArray[i] = null;
+ }
+ }
+ }
+ }
+
+ @Benchmark
+ public void gc() {
+ System.gc();
+ }
+}
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/NoObjects.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/NoObjects.java
new file mode 100644
index 0000000000000..a2e35e550611c
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/NoObjects.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.bench.vm.gc.systemgc;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"})
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+public class NoObjects {
+
+ /*
+ * Test the System GC when there are no additionally allocate
+ * objects.
+ *
+ * The heap settings provided are the same as for the other
+ * test for consistency.
+ */
+
+ @Benchmark
+ public void gc() {
+ System.gc();
+ }
+
+}
diff --git a/test/micro/org/openjdk/bench/vm/gc/systemgc/OneBigObject.java b/test/micro/org/openjdk/bench/vm/gc/systemgc/OneBigObject.java
new file mode 100644
index 0000000000000..5601abdcb709e
--- /dev/null
+++ b/test/micro/org/openjdk/bench/vm/gc/systemgc/OneBigObject.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.bench.vm.gc.systemgc;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.SingleShotTime)
+@Fork(value=25, jvmArgsAppend={"-Xmx5g", "-Xms5g", "-Xmn3g", "-XX:+AlwaysPreTouch"})
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Benchmark)
+public class OneBigObject {
+
+ /*
+ * Test the System GC when there is a single large object.
+ *
+ * The heap settings provided are the same as for the other
+ * test for consistency.
+ */
+
+ static Object[] holder;
+
+ @Setup(Level.Iteration)
+ public void generateGarbage() {
+ holder = new Object[1024*1024*128];
+ }
+
+ @Benchmark
+ public void gc() {
+ System.gc();
+ }
+}
From 53878eef137669671aad1899c71481fddd11547c Mon Sep 17 00:00:00 2001
From: Albert Mingkun Yang
Date: Wed, 14 Feb 2024 15:19:40 +0000
Subject: [PATCH 33/36] 8325643: G1: Refactor G1FlushHumongousCandidateRemSets
Reviewed-by: tschatzl, iwalulya, kbarrett
---
src/hotspot/share/gc/g1/g1RemSet.cpp | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp
index ac445850085cd..d26a77837d715 100644
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp
@@ -1174,24 +1174,27 @@ class G1MergeHeapRootsTask : public WorkerTask {
}
HeapRegion* r = g1h->region_at(region_index);
- if (r->rem_set()->is_empty()) {
- return false;
- }
+
+ assert(r->rem_set()->is_complete(), "humongous candidates must have complete remset");
guarantee(r->rem_set()->occupancy_less_or_equal_than(G1EagerReclaimRemSetThreshold),
"Found a not-small remembered set here. This is inconsistent with previous assumptions.");
- _cl.merge_card_set_for_region(r);
+ if (!r->rem_set()->is_empty()) {
+ _cl.merge_card_set_for_region(r);
- // We should only clear the card based remembered set here as we will not
- // implicitly rebuild anything else during eager reclaim. Note that at the moment
- // (and probably never) we do not enter this path if there are other kind of
- // remembered sets for this region.
- // We want to continue collecting remembered set entries for humongous regions
- // that were not reclaimed.
- r->rem_set()->clear(true /* only_cardset */, true /* keep_tracked */);
+ // We should only clear the card based remembered set here as we will not
+ // implicitly rebuild anything else during eager reclaim. Note that at the moment
+ // (and probably never) we do not enter this path if there are other kind of
+ // remembered sets for this region.
+ // We want to continue collecting remembered set entries for humongous regions
+ // that were not reclaimed.
+ r->rem_set()->clear(true /* only_cardset */, true /* keep_tracked */);
+ }
- assert(r->rem_set()->is_empty() && r->rem_set()->is_complete(), "must be for eager reclaim candidates");
+ // Postcondition
+ assert(r->rem_set()->is_empty(), "must be empty after flushing");
+ assert(r->rem_set()->is_complete(), "should still be after flushing");
return false;
}
From f6e285103ad8c840c26e4611e16bb9bf3b2de90c Mon Sep 17 00:00:00 2001
From: Brian Burkhalter
Date: Wed, 14 Feb 2024 15:59:34 +0000
Subject: [PATCH 34/36] 8316340: (bf) Missing {@inheritDoc} for exception in
MappedByteBuffer::compact
Reviewed-by: alanb, iris, lancea
---
src/java.base/share/classes/java/nio/MappedByteBuffer.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/java.base/share/classes/java/nio/MappedByteBuffer.java b/src/java.base/share/classes/java/nio/MappedByteBuffer.java
index 8b51d602f28aa..9740046322db0 100644
--- a/src/java.base/share/classes/java/nio/MappedByteBuffer.java
+++ b/src/java.base/share/classes/java/nio/MappedByteBuffer.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
@@ -422,6 +422,7 @@ public final MappedByteBuffer rewind() {
/**
* {@inheritDoc}
+ * @throws ReadOnlyBufferException {@inheritDoc}
*/
@Override
public abstract MappedByteBuffer compact();
From 09d4936657a0bdc122a4ab80735bd9c8c109839c Mon Sep 17 00:00:00 2001
From: Magnus Ihse Bursie
Date: Wed, 14 Feb 2024 16:29:58 +0000
Subject: [PATCH 35/36] 8252136: Several methods in hotspot are missing
"static"
Reviewed-by: coleenp, stefank, kvn, kbarrett
---
src/hotspot/cpu/aarch64/aarch64.ad | 4 +--
src/hotspot/cpu/aarch64/frame_aarch64.cpp | 4 +--
src/hotspot/cpu/aarch64/immediate_aarch64.cpp | 11 ++++---
src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp | 6 ++--
src/hotspot/cpu/x86/macroAssembler_x86.cpp | 5 ++--
src/hotspot/cpu/x86/peephole_x86_64.cpp | 8 ++---
src/hotspot/cpu/x86/stubRoutines_x86.cpp | 6 ++--
src/hotspot/cpu/x86/x86.ad | 2 +-
src/hotspot/cpu/x86/x86_32.ad | 2 +-
src/hotspot/cpu/x86/x86_64.ad | 12 ++++----
src/hotspot/os/bsd/os_bsd.cpp | 3 +-
src/hotspot/os/posix/signals_posix.cpp | 12 ++++----
src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp | 4 +--
src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp | 4 +--
src/hotspot/share/c1/c1_GraphBuilder.cpp | 2 +-
src/hotspot/share/c1/c1_LinearScan.cpp | 16 +++++-----
src/hotspot/share/c1/c1_Optimizer.cpp | 4 +--
src/hotspot/share/cds/filemap.cpp | 6 ++--
src/hotspot/share/classfile/altHashing.cpp | 4 +--
src/hotspot/share/classfile/classLoader.cpp | 12 ++++----
.../share/classfile/loaderConstraints.cpp | 4 +--
src/hotspot/share/classfile/modules.cpp | 4 +--
src/hotspot/share/classfile/placeholders.cpp | 8 ++---
src/hotspot/share/classfile/stringTable.cpp | 4 +--
.../share/classfile/systemDictionary.cpp | 8 ++---
.../classfile/systemDictionaryShared.cpp | 4 +--
src/hotspot/share/compiler/compileBroker.cpp | 4 +--
src/hotspot/share/compiler/compilerOracle.cpp | 20 ++++++-------
src/hotspot/share/compiler/methodMatcher.cpp | 4 +--
.../share/gc/parallel/psParallelCompact.cpp | 8 ++---
src/hotspot/share/gc/shared/gcId.cpp | 4 +--
src/hotspot/share/gc/shared/weakProcessor.cpp | 4 +--
src/hotspot/share/gc/x/xDirector.cpp | 4 +--
src/hotspot/share/gc/z/zDirector.cpp | 30 +++++++++----------
.../checkpoint/objectSampleWriter.cpp | 16 +++++-----
.../periodic/sampling/jfrThreadSampler.cpp | 4 +--
.../recorder/checkpoint/types/jfrTypeSet.cpp | 8 ++---
src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 10 +++----
.../memory/metaspace/virtualSpaceNode.cpp | 6 ++--
src/hotspot/share/memory/universe.cpp | 14 ++++-----
src/hotspot/share/oops/constMethod.cpp | 4 +--
src/hotspot/share/oops/cpCache.cpp | 4 +--
src/hotspot/share/oops/klassVtable.cpp | 4 +--
src/hotspot/share/opto/addnode.cpp | 6 ++--
src/hotspot/share/opto/doCall.cpp | 8 ++---
src/hotspot/share/opto/intrinsicnode.cpp | 4 +--
src/hotspot/share/opto/loopnode.cpp | 4 +--
src/hotspot/share/opto/node.cpp | 10 +++----
src/hotspot/share/opto/reg_split.cpp | 4 +--
src/hotspot/share/opto/vectorization.cpp | 2 +-
src/hotspot/share/prims/jvmtiExport.cpp | 4 +--
.../share/prims/resolvedMethodTable.cpp | 4 +--
src/hotspot/share/runtime/arguments.cpp | 6 ++--
src/hotspot/share/runtime/deoptimization.cpp | 2 +-
src/hotspot/share/runtime/flags/jvmFlag.cpp | 2 +-
src/hotspot/share/runtime/java.cpp | 22 +++++++-------
src/hotspot/share/runtime/javaThread.cpp | 6 ++--
src/hotspot/share/runtime/os.cpp | 4 +--
.../share/runtime/sharedRuntimeTrans.cpp | 4 +--
src/hotspot/share/runtime/synchronizer.cpp | 2 +-
src/hotspot/share/runtime/threads.cpp | 4 +--
src/hotspot/share/services/attachListener.cpp | 4 +--
src/hotspot/share/services/management.cpp | 4 +--
src/hotspot/share/utilities/exceptions.cpp | 2 +-
.../share/utilities/globalDefinitions.cpp | 4 +--
src/hotspot/share/utilities/json.cpp | 4 +--
src/hotspot/share/utilities/ostream.cpp | 4 +--
.../gtest/classfile/test_symbolTable.cpp | 4 +--
test/hotspot/gtest/oops/test_oop.cpp | 4 +--
.../os/linux/test_cgroupSubsystem_linux.cpp | 10 +++----
test/hotspot/gtest/runtime/test_safefetch.cpp | 2 +-
71 files changed, 227 insertions(+), 220 deletions(-)
diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad
index d6f3cace0a9b4..501d9df08c1c2 100644
--- a/src/hotspot/cpu/aarch64/aarch64.ad
+++ b/src/hotspot/cpu/aarch64/aarch64.ad
@@ -2575,7 +2575,7 @@ Assembler::Condition to_assembler_cond(BoolTest::mask cond) {
}
// Binary src (Replicate con)
-bool is_valid_sve_arith_imm_pattern(Node* n, Node* m) {
+static bool is_valid_sve_arith_imm_pattern(Node* n, Node* m) {
if (n == nullptr || m == nullptr) {
return false;
}
@@ -2616,7 +2616,7 @@ bool is_valid_sve_arith_imm_pattern(Node* n, Node* m) {
// (XorV src (Replicate m1))
// (XorVMask src (MaskAll m1))
-bool is_vector_bitwise_not_pattern(Node* n, Node* m) {
+static bool is_vector_bitwise_not_pattern(Node* n, Node* m) {
if (n != nullptr && m != nullptr) {
return (n->Opcode() == Op_XorV || n->Opcode() == Op_XorVMask) &&
VectorNode::is_all_ones_vector(m);
diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp
index c5b2ff8a4c01c..8d0fa8895d15c 100644
--- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/frame_aarch64.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.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -678,7 +678,7 @@ static void printbc(Method *m, intptr_t bcx) {
printf("%s : %s ==> %s\n", m->name_and_sig_as_C_string(), buf, name);
}
-void internal_pf(uintptr_t sp, uintptr_t fp, uintptr_t pc, uintptr_t bcx) {
+static void internal_pf(uintptr_t sp, uintptr_t fp, uintptr_t pc, uintptr_t bcx) {
if (! fp)
return;
diff --git a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp
index 3d87fde2b5bcd..7caafc19fbd31 100644
--- a/src/hotspot/cpu/aarch64/immediate_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/immediate_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -53,7 +53,7 @@ struct li_pair {
static struct li_pair InverseLITable[LI_TABLE_SIZE];
// comparator to sort entries in the inverse table
-int compare_immediate_pair(const void *i1, const void *i2)
+static int compare_immediate_pair(const void *i1, const void *i2)
{
struct li_pair *li1 = (struct li_pair *)i1;
struct li_pair *li2 = (struct li_pair *)i2;
@@ -142,7 +142,7 @@ static inline uint32_t uimm(uint32_t val, int hi, int lo)
// result
// a bit string containing count copies of input bit string
//
-uint64_t replicate(uint64_t bits, int nbits, int count)
+static uint64_t replicate(uint64_t bits, int nbits, int count)
{
assert(count > 0, "must be");
assert(nbits > 0, "must be");
@@ -231,8 +231,8 @@ uint64_t replicate(uint64_t bits, int nbits, int count)
// For historical reasons the implementation of this function is much
// more convoluted than is really necessary.
-int expandLogicalImmediate(uint32_t immN, uint32_t immr,
- uint32_t imms, uint64_t &bimm)
+static int expandLogicalImmediate(uint32_t immN, uint32_t immr,
+ uint32_t imms, uint64_t &bimm)
{
int len; // ought to be <= 6
uint32_t levels; // 6 bits
@@ -446,4 +446,3 @@ uint32_t encoding_for_fp_immediate(float immediate)
res = (s << 7) | (r << 4) | f;
return res;
}
-
diff --git a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp
index b6a27abf0f37e..7088cf33cf646 100644
--- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp
+++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -1207,9 +1207,10 @@ void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {
__ move(result_reg, result);
}
+#ifndef _LP64
// _i2l, _i2f, _i2d, _l2i, _l2f, _l2d, _f2i, _f2l, _f2d, _d2i, _d2l, _d2f
// _i2b, _i2c, _i2s
-LIR_Opr fixed_register_for(BasicType type) {
+static LIR_Opr fixed_register_for(BasicType type) {
switch (type) {
case T_FLOAT: return FrameMap::fpu0_float_opr;
case T_DOUBLE: return FrameMap::fpu0_double_opr;
@@ -1218,6 +1219,7 @@ LIR_Opr fixed_register_for(BasicType type) {
default: ShouldNotReachHere(); return LIR_OprFact::illegalOpr;
}
}
+#endif
void LIRGenerator::do_Convert(Convert* x) {
#ifdef _LP64
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
index 7496bddb39a5b..f0e7a08dd5f2a 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
@@ -4120,8 +4120,9 @@ static void restore_xmm_register(MacroAssembler* masm, int offset, XMMRegister r
}
}
-int register_section_sizes(RegSet gp_registers, XMMRegSet xmm_registers, bool save_fpu,
- int& gp_area_size, int& fp_area_size, int& xmm_area_size) {
+static int register_section_sizes(RegSet gp_registers, XMMRegSet xmm_registers,
+ bool save_fpu, int& gp_area_size,
+ int& fp_area_size, int& xmm_area_size) {
gp_area_size = align_up(gp_registers.size() * Register::max_slots_per_register * VMRegImpl::stack_slot_size,
StackAlignmentInBytes);
diff --git a/src/hotspot/cpu/x86/peephole_x86_64.cpp b/src/hotspot/cpu/x86/peephole_x86_64.cpp
index 8c956aeb05393..92a29490edaf8 100644
--- a/src/hotspot/cpu/x86/peephole_x86_64.cpp
+++ b/src/hotspot/cpu/x86/peephole_x86_64.cpp
@@ -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
@@ -33,8 +33,8 @@
// lea d, [s1 + s2] and
// mov d, s1; shl d, s2 into
// lea d, [s1 << s2] with s2 = 1, 2, 3
-bool lea_coalesce_helper(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_,
- MachNode* (*new_root)(), uint inst0_rule, bool imm) {
+static bool lea_coalesce_helper(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_,
+ MachNode* (*new_root)(), uint inst0_rule, bool imm) {
MachNode* inst0 = block->get_node(block_index)->as_Mach();
assert(inst0->rule() == inst0_rule, "sanity");
@@ -136,7 +136,7 @@ bool lea_coalesce_helper(Block* block, int block_index, PhaseCFG* cfg_, PhaseReg
// This helper func takes a condition and returns the flags that need to be set for the condition
// It uses the same flags as the test instruction, so if the e.g. the overflow bit is required,
// this func returns clears_overflow, as that is what the test instruction does and what the downstream path expects
-juint map_condition_to_required_test_flags(Assembler::Condition condition) {
+static juint map_condition_to_required_test_flags(Assembler::Condition condition) {
switch (condition) {
case Assembler::Condition::zero: // Same value as equal
case Assembler::Condition::notZero: // Same value as notEqual
diff --git a/src/hotspot/cpu/x86/stubRoutines_x86.cpp b/src/hotspot/cpu/x86/stubRoutines_x86.cpp
index 3be83eed9d22f..bc1cbdbba26b5 100644
--- a/src/hotspot/cpu/x86/stubRoutines_x86.cpp
+++ b/src/hotspot/cpu/x86/stubRoutines_x86.cpp
@@ -279,7 +279,7 @@ uint32_t _crc32c_pow_2k_table[TILL_CYCLE]; // because _crc32c_pow_2k_table[TILL_
// A. Kadatch and B. Jenkins / Everything we know about CRC but afraid to forget September 3, 2010 8
// Listing 1: Multiplication of normalized polynomials
// "a" and "b" occupy D least significant bits.
-uint32_t crc32c_multiply(uint32_t a, uint32_t b) {
+static uint32_t crc32c_multiply(uint32_t a, uint32_t b) {
uint32_t product = 0;
uint32_t b_pow_x_table[D + 1]; // b_pow_x_table[k] = (b * x**k) mod P
b_pow_x_table[0] = b;
@@ -303,7 +303,7 @@ uint32_t crc32c_multiply(uint32_t a, uint32_t b) {
#undef P
// A. Kadatch and B. Jenkins / Everything we know about CRC but afraid to forget September 3, 2010 9
-void crc32c_init_pow_2k(void) {
+static void crc32c_init_pow_2k(void) {
// _crc32c_pow_2k_table(0) =
// x^(2^k) mod P(x) = x mod P(x) = x
// Since we are operating on a reflected values
@@ -318,7 +318,7 @@ void crc32c_init_pow_2k(void) {
}
// x^N mod P(x)
-uint32_t crc32c_f_pow_n(uint32_t n) {
+static uint32_t crc32c_f_pow_n(uint32_t n) {
// result = 1 (polynomial)
uint32_t one, result = 0x80000000, i = 0;
diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad
index a31548eb8c3f9..6df02d280bcef 100644
--- a/src/hotspot/cpu/x86/x86.ad
+++ b/src/hotspot/cpu/x86/x86.ad
@@ -1358,7 +1358,7 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
return offset;
}
-Assembler::Width widthForType(BasicType bt) {
+static Assembler::Width widthForType(BasicType bt) {
if (bt == T_BYTE) {
return Assembler::B;
} else if (bt == T_SHORT) {
diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad
index cad53ca6d5a45..2fe655a576778 100644
--- a/src/hotspot/cpu/x86/x86_32.ad
+++ b/src/hotspot/cpu/x86/x86_32.ad
@@ -504,7 +504,7 @@ void emit_cmpfp_fixup(MacroAssembler& _masm) {
__ bind(exit);
}
-void emit_cmpfp3(MacroAssembler& _masm, Register dst) {
+static void emit_cmpfp3(MacroAssembler& _masm, Register dst) {
Label done;
__ movl(dst, -1);
__ jcc(Assembler::parity, done);
diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad
index d1a19e452c6b7..a8136688cdedd 100644
--- a/src/hotspot/cpu/x86/x86_64.ad
+++ b/src/hotspot/cpu/x86/x86_64.ad
@@ -519,7 +519,7 @@ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
}
// This could be in MacroAssembler but it's fairly C2 specific
-void emit_cmpfp_fixup(MacroAssembler& _masm) {
+static void emit_cmpfp_fixup(MacroAssembler& _masm) {
Label exit;
__ jccb(Assembler::noParity, exit);
__ pushf();
@@ -539,7 +539,7 @@ void emit_cmpfp_fixup(MacroAssembler& _masm) {
__ bind(exit);
}
-void emit_cmpfp3(MacroAssembler& _masm, Register dst) {
+static void emit_cmpfp3(MacroAssembler& _masm, Register dst) {
Label done;
__ movl(dst, -1);
__ jcc(Assembler::parity, done);
@@ -558,10 +558,10 @@ void emit_cmpfp3(MacroAssembler& _masm, Register dst) {
// je #
// |-jz -> a | b # a & b
// | -> a #
-void emit_fp_min_max(MacroAssembler& _masm, XMMRegister dst,
- XMMRegister a, XMMRegister b,
- XMMRegister xmmt, Register rt,
- bool min, bool single) {
+static void emit_fp_min_max(MacroAssembler& _masm, XMMRegister dst,
+ XMMRegister a, XMMRegister b,
+ XMMRegister xmmt, Register rt,
+ bool min, bool single) {
Label nan, zero, below, above, done;
diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp
index ddceab14ffbc2..dbc18794cfec7 100644
--- a/src/hotspot/os/bsd/os_bsd.cpp
+++ b/src/hotspot/os/bsd/os_bsd.cpp
@@ -1268,7 +1268,8 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
}
#endif // !__APPLE__
-int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
+static int _print_dll_info_cb(const char * name, address base_address,
+ address top_address, void * param) {
outputStream * out = (outputStream *) param;
out->print_cr(INTPTR_FORMAT " \t%s", (intptr_t)base_address, name);
return 0;
diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp
index eaadb36731518..6a958f8903b8e 100644
--- a/src/hotspot/os/posix/signals_posix.cpp
+++ b/src/hotspot/os/posix/signals_posix.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -340,7 +340,7 @@ static const struct {
////////////////////////////////////////////////////////////////////////////////
// sun.misc.Signal and BREAK_SIGNAL support
-void jdk_misc_signal_init() {
+static void jdk_misc_signal_init() {
// Initialize signal structures
::memset((void*)pending_signals, 0, sizeof(pending_signals));
@@ -380,7 +380,7 @@ int os::signal_wait() {
////////////////////////////////////////////////////////////////////////////////
// signal chaining support
-struct sigaction* get_chained_signal_action(int sig) {
+static struct sigaction* get_chained_signal_action(int sig) {
struct sigaction *actp = nullptr;
if (libjsig_is_loaded) {
@@ -1245,7 +1245,7 @@ int os::get_signal_number(const char* signal_name) {
return -1;
}
-void set_signal_handler(int sig) {
+static void set_signal_handler(int sig) {
// Check for overwrite.
struct sigaction oldAct;
sigaction(sig, (struct sigaction*)nullptr, &oldAct);
@@ -1292,7 +1292,7 @@ void set_signal_handler(int sig) {
// install signal handlers for signals that HotSpot needs to
// handle in order to support Java-level exception handling.
-void install_signal_handlers() {
+static void install_signal_handlers() {
// signal-chaining
typedef void (*signal_setting_t)();
signal_setting_t begin_signal_setting = nullptr;
@@ -1723,7 +1723,7 @@ static void SR_handler(int sig, siginfo_t* siginfo, void* context) {
errno = old_errno;
}
-int SR_initialize() {
+static int SR_initialize() {
struct sigaction act;
char *s;
// Get signal number to use for suspend/resume
diff --git a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp
index 2074f6319c9f0..c73e83996ff57 100644
--- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp
+++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.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
@@ -350,7 +350,7 @@ frame os::get_sender_for_C_frame(frame* fr) {
return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
}
-intptr_t* _get_previous_fp() {
+static intptr_t* _get_previous_fp() {
#if defined(__clang__) || defined(__llvm__)
intptr_t **ebp;
__asm__("mov %%" SPELL_REG_FP ", %0":"=r"(ebp));
diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
index 219f8d828a420..4dcaedf71da8c 100644
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.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
@@ -164,7 +164,7 @@ frame os::get_sender_for_C_frame(frame* fr) {
return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
}
-intptr_t* _get_previous_fp() {
+static intptr_t* _get_previous_fp() {
#if defined(__clang__)
intptr_t **ebp;
__asm__ __volatile__ ("mov %%" SPELL_REG_FP ", %0":"=r"(ebp):);
diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp
index 6e5fb99242c8c..396c83c6ab976 100644
--- a/src/hotspot/share/c1/c1_GraphBuilder.cpp
+++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp
@@ -523,7 +523,7 @@ inline bool BlockListBuilder::is_successor(BlockBegin* block, BlockBegin* sux) {
#ifndef PRODUCT
-int compare_depth_first(BlockBegin** a, BlockBegin** b) {
+static int compare_depth_first(BlockBegin** a, BlockBegin** b) {
return (*a)->depth_first_number() - (*b)->depth_first_number();
}
diff --git a/src/hotspot/share/c1/c1_LinearScan.cpp b/src/hotspot/share/c1/c1_LinearScan.cpp
index 9e9195a0d60d0..a4d955e52a004 100644
--- a/src/hotspot/share/c1/c1_LinearScan.cpp
+++ b/src/hotspot/share/c1/c1_LinearScan.cpp
@@ -1446,12 +1446,12 @@ int LinearScan::interval_cmp(Interval** a, Interval** b) {
}
}
-#ifndef PRODUCT
-int interval_cmp(Interval* const& l, Interval* const& r) {
+#ifdef ASSERT
+static int interval_cmp(Interval* const& l, Interval* const& r) {
return l->from() - r->from();
}
-bool find_interval(Interval* interval, IntervalArray* intervals) {
+static bool find_interval(Interval* interval, IntervalArray* intervals) {
bool found;
int idx = intervals->find_sorted(interval, found);
@@ -2303,11 +2303,11 @@ void assert_no_register_values(GrowableArray* values) {
}
}
-void assert_equal(Location l1, Location l2) {
+static void assert_equal(Location l1, Location l2) {
assert(l1.where() == l2.where() && l1.type() == l2.type() && l1.offset() == l2.offset(), "");
}
-void assert_equal(ScopeValue* v1, ScopeValue* v2) {
+static void assert_equal(ScopeValue* v1, ScopeValue* v2) {
if (v1->is_location()) {
assert(v2->is_location(), "");
assert_equal(((LocationValue*)v1)->location(), ((LocationValue*)v2)->location());
@@ -2328,12 +2328,12 @@ void assert_equal(ScopeValue* v1, ScopeValue* v2) {
}
}
-void assert_equal(MonitorValue* m1, MonitorValue* m2) {
+static void assert_equal(MonitorValue* m1, MonitorValue* m2) {
assert_equal(m1->owner(), m2->owner());
assert_equal(m1->basic_lock(), m2->basic_lock());
}
-void assert_equal(IRScopeDebugInfo* d1, IRScopeDebugInfo* d2) {
+static void assert_equal(IRScopeDebugInfo* d1, IRScopeDebugInfo* d2) {
assert(d1->scope() == d2->scope(), "not equal");
assert(d1->bci() == d2->bci(), "not equal");
@@ -2375,7 +2375,7 @@ void assert_equal(IRScopeDebugInfo* d1, IRScopeDebugInfo* d2) {
}
}
-void check_stack_depth(CodeEmitInfo* info, int stack_end) {
+static void check_stack_depth(CodeEmitInfo* info, int stack_end) {
if (info->stack()->bci() != SynchronizationEntryBCI && !info->scope()->method()->is_native()) {
Bytecodes::Code code = info->scope()->method()->java_code_at_bci(info->stack()->bci());
switch (code) {
diff --git a/src/hotspot/share/c1/c1_Optimizer.cpp b/src/hotspot/share/c1/c1_Optimizer.cpp
index 6cd282d02ad7e..dd428a5895bc4 100644
--- a/src/hotspot/share/c1/c1_Optimizer.cpp
+++ b/src/hotspot/share/c1/c1_Optimizer.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
@@ -335,7 +335,7 @@ void Optimizer::eliminate_conditional_expressions() {
}
// This removes others' relation to block, but doesn't empty block's lists
-void disconnect_from_graph(BlockBegin* block) {
+static void disconnect_from_graph(BlockBegin* block) {
for (int p = 0; p < block->number_of_preds(); p++) {
BlockBegin* pred = block->pred_at(p);
int idx;
diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp
index 5a0bf2e61b5d0..f6e02594b5c7b 100644
--- a/src/hotspot/share/cds/filemap.cpp
+++ b/src/hotspot/share/cds/filemap.cpp
@@ -1664,9 +1664,9 @@ void FileMapInfo::close() {
/*
* Same as os::map_memory() but also pretouches if AlwaysPreTouch is enabled.
*/
-char* map_memory(int fd, const char* file_name, size_t file_offset,
- char *addr, size_t bytes, bool read_only,
- bool allow_exec, MEMFLAGS flags = mtNone) {
+static char* map_memory(int fd, const char* file_name, size_t file_offset,
+ char *addr, size_t bytes, bool read_only,
+ bool allow_exec, MEMFLAGS flags = mtNone) {
char* mem = os::map_memory(fd, file_name, file_offset, addr, bytes,
AlwaysPreTouch ? false : read_only,
allow_exec, flags);
diff --git a/src/hotspot/share/classfile/altHashing.cpp b/src/hotspot/share/classfile/altHashing.cpp
index 158a8a232a7b4..1d43d6ebf1ed0 100644
--- a/src/hotspot/share/classfile/altHashing.cpp
+++ b/src/hotspot/share/classfile/altHashing.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -120,7 +120,7 @@ static void halfsiphash_init64(uint32_t v[4], uint64_t seed) {
v[1] ^= 0xee;
}
-uint32_t halfsiphash_finish32(uint32_t v[4], int rounds) {
+static uint32_t halfsiphash_finish32(uint32_t v[4], int rounds) {
v[2] ^= 0xff;
halfsiphash_rounds(v, rounds);
return (v[1] ^ v[3]);
diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp
index 43aa82b67f85f..9ce49b71734b1 100644
--- a/src/hotspot/share/classfile/classLoader.cpp
+++ b/src/hotspot/share/classfile/classLoader.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
@@ -134,7 +134,8 @@ ClassPathEntry* ClassLoader::_last_module_path_entry = nullptr;
#endif
// helper routines
-bool string_starts_with(const char* str, const char* str_to_find) {
+#if INCLUDE_CDS
+static bool string_starts_with(const char* str, const char* str_to_find) {
size_t str_len = strlen(str);
size_t str_to_find_len = strlen(str_to_find);
if (str_to_find_len > str_len) {
@@ -142,6 +143,7 @@ bool string_starts_with(const char* str, const char* str_to_find) {
}
return (strncmp(str, str_to_find, str_to_find_len) == 0);
}
+#endif
static const char* get_jimage_version_string() {
static char version_string[10] = "";
@@ -1009,8 +1011,8 @@ const char* ClassLoader::file_name_for_class_name(const char* class_name,
return file_name;
}
-ClassPathEntry* find_first_module_cpe(ModuleEntry* mod_entry,
- const GrowableArray* const module_list) {
+static ClassPathEntry* find_first_module_cpe(ModuleEntry* mod_entry,
+ const GrowableArray* const module_list) {
int num_of_entries = module_list->length();
const Symbol* class_module_name = mod_entry->name();
@@ -1355,7 +1357,7 @@ void ClassLoader::initialize(TRAPS) {
setup_bootstrap_search_path(THREAD);
}
-char* lookup_vm_resource(JImageFile *jimage, const char *jimage_version, const char *path) {
+static char* lookup_vm_resource(JImageFile *jimage, const char *jimage_version, const char *path) {
jlong size;
JImageLocationRef location = (*JImageFindResource)(jimage, "java.base", jimage_version, path, &size);
if (location == 0)
diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp
index e6021e00d3391..99d0c07ed42d4 100644
--- a/src/hotspot/share/classfile/loaderConstraints.cpp
+++ b/src/hotspot/share/classfile/loaderConstraints.cpp
@@ -296,8 +296,8 @@ void LoaderConstraintTable::purge_loader_constraints() {
_loader_constraint_table->unlink(&purge);
}
-void log_ldr_constraint_msg(Symbol* class_name, const char* reason,
- ClassLoaderData* loader1, ClassLoaderData* loader2) {
+static void log_ldr_constraint_msg(Symbol* class_name, const char* reason,
+ ClassLoaderData* loader1, ClassLoaderData* loader2) {
LogTarget(Info, class, loader, constraints) lt;
if (lt.is_enabled()) {
ResourceMark rm;
diff --git a/src/hotspot/share/classfile/modules.cpp b/src/hotspot/share/classfile/modules.cpp
index bd4be93b86877..4664d9565d353 100644
--- a/src/hotspot/share/classfile/modules.cpp
+++ b/src/hotspot/share/classfile/modules.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2016, 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
@@ -259,7 +259,7 @@ static void define_javabase_module(Handle module_handle, jstring version, jstrin
}
// Caller needs ResourceMark.
-void throw_dup_pkg_exception(const char* module_name, PackageEntry* package, TRAPS) {
+static void throw_dup_pkg_exception(const char* module_name, PackageEntry* package, TRAPS) {
const char* package_name = package->name()->as_C_string();
if (package->module()->is_named()) {
THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
diff --git a/src/hotspot/share/classfile/placeholders.cpp b/src/hotspot/share/classfile/placeholders.cpp
index 1bb5f87870417..a6a86473ea794 100644
--- a/src/hotspot/share/classfile/placeholders.cpp
+++ b/src/hotspot/share/classfile/placeholders.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
@@ -198,8 +198,8 @@ void PlaceholderEntry::set_supername(Symbol* supername) {
// All threads examining the placeholder table must hold the
// SystemDictionary_lock, so we don't need special precautions
// on store ordering here.
-PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data,
- Symbol* supername){
+static PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data,
+ Symbol* supername){
assert_locked_or_safepoint(SystemDictionary_lock);
assert(class_name != nullptr, "adding nullptr obj");
@@ -213,7 +213,7 @@ PlaceholderEntry* add_entry(Symbol* class_name, ClassLoaderData* loader_data,
}
// Remove a placeholder object.
-void remove_entry(Symbol* class_name, ClassLoaderData* loader_data) {
+static void remove_entry(Symbol* class_name, ClassLoaderData* loader_data) {
assert_locked_or_safepoint(SystemDictionary_lock);
PlaceholderKey key(class_name, loader_data);
diff --git a/src/hotspot/share/classfile/stringTable.cpp b/src/hotspot/share/classfile/stringTable.cpp
index 9e96340d82b9c..be2971288ef12 100644
--- a/src/hotspot/share/classfile/stringTable.cpp
+++ b/src/hotspot/share/classfile/stringTable.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
@@ -122,7 +122,7 @@ volatile bool _alt_hash = false;
static bool _rehashed = false;
static uint64_t _alt_hash_seed = 0;
-unsigned int hash_string(const jchar* s, int len, bool useAlt) {
+static unsigned int hash_string(const jchar* s, int len, bool useAlt) {
return useAlt ?
AltHashing::halfsiphash_32(_alt_hash_seed, s, len) :
java_lang_String::hash_code(s, len);
diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp
index 82c20a962ce14..f2a88f00e0d9e 100644
--- a/src/hotspot/share/classfile/systemDictionary.cpp
+++ b/src/hotspot/share/classfile/systemDictionary.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
@@ -212,13 +212,13 @@ void SystemDictionary::set_platform_loader(ClassLoaderData *cld) {
// ----------------------------------------------------------------------------
// Parallel class loading check
-bool is_parallelCapable(Handle class_loader) {
+static bool is_parallelCapable(Handle class_loader) {
if (class_loader.is_null()) return true;
return java_lang_ClassLoader::parallelCapable(class_loader());
}
// ----------------------------------------------------------------------------
// ParallelDefineClass flag does not apply to bootclass loader
-bool is_parallelDefine(Handle class_loader) {
+static bool is_parallelDefine(Handle class_loader) {
if (class_loader.is_null()) return false;
if (AllowParallelDefineClass && java_lang_ClassLoader::parallelCapable(class_loader())) {
return true;
@@ -280,7 +280,7 @@ Symbol* SystemDictionary::class_name_symbol(const char* name, Symbol* exception,
#ifdef ASSERT
// Used to verify that class loading succeeded in adding k to the dictionary.
-void verify_dictionary_entry(Symbol* class_name, InstanceKlass* k) {
+static void verify_dictionary_entry(Symbol* class_name, InstanceKlass* k) {
MutexLocker mu(SystemDictionary_lock);
ClassLoaderData* loader_data = k->class_loader_data();
Dictionary* dictionary = loader_data->dictionary();
diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp
index 297483526846c..44d7da5c4a4f1 100644
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -1348,7 +1348,7 @@ void SystemDictionaryShared::update_shared_entry(InstanceKlass* k, int id) {
info->_id = id;
}
-const char* class_loader_name_for_shared(Klass* k) {
+static const char* class_loader_name_for_shared(Klass* k) {
assert(k != nullptr, "Sanity");
assert(k->is_shared(), "Must be");
assert(k->is_instance_klass(), "Must be");
diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp
index 1ade28278aedd..3a25112891484 100644
--- a/src/hotspot/share/compiler/compileBroker.cpp
+++ b/src/hotspot/share/compiler/compileBroker.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
@@ -582,7 +582,7 @@ CompilerCounters::CompilerCounters() {
// c2 uses explicit CompilerPhaseType idToPhase mapping in opto/phasetype.hpp,
// so if c2 is used, it should be always registered first.
// This function is called during vm initialization.
-void register_jfr_phasetype_serializer(CompilerType compiler_type) {
+static void register_jfr_phasetype_serializer(CompilerType compiler_type) {
ResourceMark rm;
static bool first_registration = true;
if (compiler_type == compiler_jvmci) {
diff --git a/src/hotspot/share/compiler/compilerOracle.cpp b/src/hotspot/share/compiler/compilerOracle.cpp
index 089fc5a4d995e..a8eee10fac539 100644
--- a/src/hotspot/share/compiler/compilerOracle.cpp
+++ b/src/hotspot/share/compiler/compilerOracle.cpp
@@ -48,7 +48,7 @@ static const char* optiontype_names[] = {
#undef enum_of_types
};
-const char* optiontype2name(enum OptionType type) {
+static const char* optiontype2name(enum OptionType type) {
return optiontype_names[static_cast(type)];
}
@@ -58,7 +58,7 @@ static enum OptionType option_types[] = {
#undef enum_of_options
};
-enum OptionType option2type(enum CompileCommand option) {
+static enum OptionType option2type(enum CompileCommand option) {
return option_types[static_cast(option)];
}
@@ -68,7 +68,7 @@ static const char* option_names[] = {
#undef enum_of_options
};
-const char* option2name(enum CompileCommand option) {
+static const char* option2name(enum CompileCommand option) {
return option_names[static_cast(option)];
}
@@ -108,7 +108,7 @@ static bool print_final_memstat_report = false;
// A filter for quick lookup if an option is set
static bool option_filter[static_cast(CompileCommand::Unknown) + 1] = { 0 };
-void command_set_in_filter(enum CompileCommand option) {
+static void command_set_in_filter(enum CompileCommand option) {
assert(option != CompileCommand::Unknown, "sanity");
assert(option2type(option) != OptionType::Unknown, "sanity");
@@ -120,7 +120,7 @@ void command_set_in_filter(enum CompileCommand option) {
option_filter[static_cast(option)] = true;
}
-bool has_command(enum CompileCommand option) {
+static bool has_command(enum CompileCommand option) {
return option_filter[static_cast(option)];
}
@@ -547,7 +547,7 @@ enum OptionType CompilerOracle::parse_option_type(const char* type_str) {
return OptionType::Unknown;
}
-void print_tip() { // CMH Update info
+static void print_tip() { // CMH Update info
tty->cr();
tty->print_cr("Usage: '-XX:CompileCommand=,' - to set boolean option to true");
tty->print_cr("Usage: '-XX:CompileCommand=,,'");
@@ -555,13 +555,13 @@ void print_tip() { // CMH Update info
tty->cr();
}
-void print_option(enum CompileCommand option, const char* name, enum OptionType type) {
+static void print_option(enum CompileCommand option, const char* name, enum OptionType type) {
if (type != OptionType::Unknown) {
tty->print_cr(" %s (%s)", name, optiontype2name(type));
}
}
-void print_commands() {
+static void print_commands() {
tty->cr();
tty->print_cr("All available options:");
#define enum_of_options(option, name, ctype) print_option(CompileCommand::option, name, OptionType::ctype);
@@ -621,7 +621,7 @@ static void usage() {
tty->cr();
};
-int skip_whitespace(char* &line) {
+static int skip_whitespace(char* &line) {
// Skip any leading spaces
int whitespace_read = 0;
sscanf(line, "%*[ \t]%n", &whitespace_read);
@@ -629,7 +629,7 @@ int skip_whitespace(char* &line) {
return whitespace_read;
}
-void skip_comma(char* &line) {
+static void skip_comma(char* &line) {
// Skip any leading spaces
if (*line == ',') {
line++;
diff --git a/src/hotspot/share/compiler/methodMatcher.cpp b/src/hotspot/share/compiler/methodMatcher.cpp
index 3e2ee288c80ed..de2e4e82bba3f 100644
--- a/src/hotspot/share/compiler/methodMatcher.cpp
+++ b/src/hotspot/share/compiler/methodMatcher.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -246,7 +246,7 @@ static MethodMatcher::Mode check_mode(char name[], const char*& error_msg) {
}
// Skip any leading spaces
-void skip_leading_spaces(char*& line, int* total_bytes_read ) {
+static void skip_leading_spaces(char*& line, int* total_bytes_read ) {
int bytes_read = 0;
sscanf(line, "%*[ \t]%n", &bytes_read);
if (bytes_read > 0) {
diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp
index e45b60851124f..d7bfe5242a921 100644
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -246,7 +246,7 @@ void PSParallelCompact::print_region_ranges() {
}
}
-void
+static void
print_generic_summary_region(size_t i, const ParallelCompactData::RegionData* c)
{
#define REGION_IDX_FORMAT SIZE_FORMAT_W(7)
@@ -312,7 +312,7 @@ print_generic_summary_data(ParallelCompactData& summary_data,
}
}
-void
+static void
print_initial_summary_data(ParallelCompactData& summary_data,
const MutableSpace* space) {
if (space->top() == space->bottom()) {
@@ -393,7 +393,7 @@ print_initial_summary_data(ParallelCompactData& summary_data,
max_reclaimed_ratio_region, max_dead_to_right, max_live_to_right, max_reclaimed_ratio);
}
-void
+static void
print_initial_summary_data(ParallelCompactData& summary_data,
SpaceInfo* space_info) {
if (!log_develop_is_enabled(Trace, gc, compaction)) {
diff --git a/src/hotspot/share/gc/shared/gcId.cpp b/src/hotspot/share/gc/shared/gcId.cpp
index 646de8339104c..8d123386180cb 100644
--- a/src/hotspot/share/gc/shared/gcId.cpp
+++ b/src/hotspot/share/gc/shared/gcId.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -43,7 +43,7 @@ void GCId::set_printer(GCIdPrinter* printer) {
_printer = printer;
}
-NamedThread* currentNamedthread() {
+static NamedThread* currentNamedthread() {
assert(Thread::current()->is_Named_thread(), "This thread must be NamedThread");
return (NamedThread*)Thread::current();
}
diff --git a/src/hotspot/share/gc/shared/weakProcessor.cpp b/src/hotspot/share/gc/shared/weakProcessor.cpp
index 02ef9bbe88da8..8adf3fab7d5c1 100644
--- a/src/hotspot/share/gc/shared/weakProcessor.cpp
+++ b/src/hotspot/share/gc/shared/weakProcessor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -41,7 +41,7 @@
#include "prims/jvmtiTagMap.hpp"
#endif // INCLUDE_JVMTI
-void notify_jvmti_tagmaps() {
+static void notify_jvmti_tagmaps() {
#if INCLUDE_JVMTI
// Notify JVMTI tagmaps that a STW weak reference processing might be
// clearing entries, so the tagmaps need cleaning. Doing this here allows
diff --git a/src/hotspot/share/gc/x/xDirector.cpp b/src/hotspot/share/gc/x/xDirector.cpp
index 05ef362374192..e1c69bd05b7de 100644
--- a/src/hotspot/share/gc/x/xDirector.cpp
+++ b/src/hotspot/share/gc/x/xDirector.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2021, 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
@@ -168,7 +168,7 @@ static double select_gc_workers(double serial_gc_time, double parallelizable_gc_
return gc_workers;
}
-XDriverRequest rule_allocation_rate_dynamic() {
+static XDriverRequest rule_allocation_rate_dynamic() {
if (!XStatCycle::is_time_trustable()) {
// Rule disabled
return GCCause::_no_gc;
diff --git a/src/hotspot/share/gc/z/zDirector.cpp b/src/hotspot/share/gc/z/zDirector.cpp
index 417ac33a6f86d..47e24063ead75 100644
--- a/src/hotspot/share/gc/z/zDirector.cpp
+++ b/src/hotspot/share/gc/z/zDirector.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
@@ -143,11 +143,11 @@ static double select_young_gc_workers(const ZDirectorStats& stats, double serial
return gc_workers;
}
-ZDriverRequest rule_minor_allocation_rate_dynamic(const ZDirectorStats& stats,
- double serial_gc_time_passed,
- double parallel_gc_time_passed,
- bool conservative_alloc_rate,
- size_t capacity) {
+static ZDriverRequest rule_minor_allocation_rate_dynamic(const ZDirectorStats& stats,
+ double serial_gc_time_passed,
+ double parallel_gc_time_passed,
+ bool conservative_alloc_rate,
+ size_t capacity) {
if (!stats._old_stats._cycle._is_time_trustable) {
// Rule disabled
return ZDriverRequest(GCCause::_no_gc, ZYoungGCThreads, 0);
@@ -214,9 +214,9 @@ ZDriverRequest rule_minor_allocation_rate_dynamic(const ZDirectorStats& stats,
return ZDriverRequest(GCCause::_z_allocation_rate, actual_gc_workers, 0);
}
-ZDriverRequest rule_soft_minor_allocation_rate_dynamic(const ZDirectorStats& stats,
- double serial_gc_time_passed,
- double parallel_gc_time_passed) {
+static ZDriverRequest rule_soft_minor_allocation_rate_dynamic(const ZDirectorStats& stats,
+ double serial_gc_time_passed,
+ double parallel_gc_time_passed) {
return rule_minor_allocation_rate_dynamic(stats,
0.0 /* serial_gc_time_passed */,
0.0 /* parallel_gc_time_passed */,
@@ -224,9 +224,9 @@ ZDriverRequest rule_soft_minor_allocation_rate_dynamic(const ZDirectorStats& sta
stats._heap._soft_max_heap_size /* capacity */);
}
-ZDriverRequest rule_semi_hard_minor_allocation_rate_dynamic(const ZDirectorStats& stats,
- double serial_gc_time_passed,
- double parallel_gc_time_passed) {
+static ZDriverRequest rule_semi_hard_minor_allocation_rate_dynamic(const ZDirectorStats& stats,
+ double serial_gc_time_passed,
+ double parallel_gc_time_passed) {
return rule_minor_allocation_rate_dynamic(stats,
0.0 /* serial_gc_time_passed */,
0.0 /* parallel_gc_time_passed */,
@@ -234,9 +234,9 @@ ZDriverRequest rule_semi_hard_minor_allocation_rate_dynamic(const ZDirectorStats
ZHeap::heap()->max_capacity() /* capacity */);
}
-ZDriverRequest rule_hard_minor_allocation_rate_dynamic(const ZDirectorStats& stats,
- double serial_gc_time_passed,
- double parallel_gc_time_passed) {
+static ZDriverRequest rule_hard_minor_allocation_rate_dynamic(const ZDirectorStats& stats,
+ double serial_gc_time_passed,
+ double parallel_gc_time_passed) {
return rule_minor_allocation_rate_dynamic(stats,
0.0 /* serial_gc_time_passed */,
0.0 /* parallel_gc_time_passed */,
diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.cpp
index 2c2d7fe7b3da6..87851c71cdb75 100644
--- a/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.cpp
+++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/objectSampleWriter.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -199,7 +199,7 @@ static ArrayInfo* array_infos = nullptr;
static FieldTable* field_infos = nullptr;
static RootDescriptionInfo* root_infos = nullptr;
-int __write_sample_info__(JfrCheckpointWriter* writer, const void* si) {
+static int __write_sample_info__(JfrCheckpointWriter* writer, const void* si) {
assert(writer != nullptr, "invariant");
assert(si != nullptr, "invariant");
const OldObjectSampleInfo* const oosi = (const OldObjectSampleInfo*)si;
@@ -224,7 +224,7 @@ static void write_sample_infos(JfrCheckpointWriter& writer) {
}
}
-int __write_reference_info__(JfrCheckpointWriter* writer, const void* ri) {
+static int __write_reference_info__(JfrCheckpointWriter* writer, const void* ri) {
assert(writer != nullptr, "invariant");
assert(ri != nullptr, "invariant");
const ReferenceInfo* const ref_info = (const ReferenceInfo*)ri;
@@ -246,7 +246,7 @@ static void write_reference_infos(JfrCheckpointWriter& writer) {
}
}
-int __write_array_info__(JfrCheckpointWriter* writer, const void* ai) {
+static int __write_array_info__(JfrCheckpointWriter* writer, const void* ai) {
assert(writer != nullptr, "invariant");
assert(ai != nullptr, "invariant");
const ObjectSampleArrayInfo* const osai = (const ObjectSampleArrayInfo*)ai;
@@ -283,7 +283,7 @@ static void write_array_infos(JfrCheckpointWriter& writer) {
}
}
-int __write_field_info__(JfrCheckpointWriter* writer, const void* fi) {
+static int __write_field_info__(JfrCheckpointWriter* writer, const void* fi) {
assert(writer != nullptr, "invariant");
assert(fi != nullptr, "invariant");
const FieldTable::FieldInfoEntry* field_info_entry = (const FieldTable::FieldInfoEntry*)fi;
@@ -340,7 +340,7 @@ static const char* description(const ObjectSampleRootDescriptionInfo* osdi) {
return description.description();
}
-int __write_root_description_info__(JfrCheckpointWriter* writer, const void* di) {
+static int __write_root_description_info__(JfrCheckpointWriter* writer, const void* di) {
assert(writer != nullptr, "invariant");
assert(di != nullptr, "invariant");
const ObjectSampleRootDescriptionInfo* const osdi = (const ObjectSampleRootDescriptionInfo*)di;
@@ -367,11 +367,11 @@ typedef JfrTypeWriterImplHost RootDescriptionWriter;
-int _edge_reference_compare_(uintptr_t lhs, uintptr_t rhs) {
+static int _edge_reference_compare_(uintptr_t lhs, uintptr_t rhs) {
return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0;
}
-int _root_desc_compare_(const ObjectSampleRootDescriptionInfo*const & lhs, const ObjectSampleRootDescriptionInfo* const& rhs) {
+static int _root_desc_compare_(const ObjectSampleRootDescriptionInfo*const & lhs, const ObjectSampleRootDescriptionInfo* const& rhs) {
const uintptr_t lhs_ref = lhs->_data._root_edge->reference().addr();
const uintptr_t rhs_ref = rhs->_data._root_edge->reference().addr();
return _edge_reference_compare_(lhs_ref, rhs_ref);
diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp
index 0ab787a7f3a7d..5cef25c54cb51 100644
--- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -668,7 +668,7 @@ JfrThreadSampling::~JfrThreadSampling() {
}
#ifdef ASSERT
-void assert_periods(const JfrThreadSampler* sampler, int64_t java_period_millis, int64_t native_period_millis) {
+static void assert_periods(const JfrThreadSampler* sampler, int64_t java_period_millis, int64_t native_period_millis) {
assert(sampler != nullptr, "invariant");
assert(sampler->get_java_period() == java_period_millis, "invariant");
assert(sampler->get_native_period() == native_period_millis, "invariant");
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
index 31a4c3f25e9cb..3ef7abd8a4336 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
@@ -1089,14 +1089,14 @@ static int write_symbol(JfrCheckpointWriter* writer, SymbolEntryPtr entry, bool
return 1;
}
-int write__symbol(JfrCheckpointWriter* writer, const void* e) {
+static int write__symbol(JfrCheckpointWriter* writer, const void* e) {
assert(e != nullptr, "invariant");
SymbolEntryPtr entry = static_cast(e);
set_serialized(entry);
return write_symbol(writer, entry, false);
}
-int write__symbol__leakp(JfrCheckpointWriter* writer, const void* e) {
+static int write__symbol__leakp(JfrCheckpointWriter* writer, const void* e) {
assert(e != nullptr, "invariant");
SymbolEntryPtr entry = static_cast(e);
return write_symbol(writer, entry, true);
@@ -1110,14 +1110,14 @@ static int write_string(JfrCheckpointWriter* writer, StringEntryPtr entry, bool
return 1;
}
-int write__string(JfrCheckpointWriter* writer, const void* e) {
+static int write__string(JfrCheckpointWriter* writer, const void* e) {
assert(e != nullptr, "invariant");
StringEntryPtr entry = static_cast(e);
set_serialized(entry);
return write_string(writer, entry, false);
}
-int write__string__leakp(JfrCheckpointWriter* writer, const void* e) {
+static int write__string__leakp(JfrCheckpointWriter* writer, const void* e) {
assert(e != nullptr, "invariant");
StringEntryPtr entry = static_cast(e);
return write_string(writer, entry, true);
diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
index 0999363688f50..ca3750733131a 100644
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
@@ -1380,7 +1380,7 @@ C2V_END
/*
* Used by matches() to convert a ResolvedJavaMethod[] to an array of Method*.
*/
-GrowableArray* init_resolved_methods(jobjectArray methods, JVMCIEnv* JVMCIENV) {
+static GrowableArray* init_resolved_methods(jobjectArray methods, JVMCIEnv* JVMCIENV) {
objArrayOop methods_oop = (objArrayOop) JNIHandles::resolve(methods);
GrowableArray* resolved_methods = new GrowableArray(methods_oop->length());
for (int i = 0; i < methods_oop->length(); i++) {
@@ -1399,7 +1399,7 @@ GrowableArray* init_resolved_methods(jobjectArray methods, JVMCIEnv* JV
* The ResolvedJavaMethod[] array is converted to a Method* array that is then cached in the resolved_methods_ref in/out parameter.
* In case of a match, the matching ResolvedJavaMethod is returned in matched_jvmci_method_ref.
*/
-bool matches(jobjectArray methods, Method* method, GrowableArray** resolved_methods_ref, Handle* matched_jvmci_method_ref, Thread* THREAD, JVMCIEnv* JVMCIENV) {
+static bool matches(jobjectArray methods, Method* method, GrowableArray** resolved_methods_ref, Handle* matched_jvmci_method_ref, Thread* THREAD, JVMCIEnv* JVMCIENV) {
GrowableArray* resolved_methods = *resolved_methods_ref;
if (resolved_methods == nullptr) {
resolved_methods = init_resolved_methods(methods, JVMCIENV);
@@ -1420,7 +1420,7 @@ bool matches(jobjectArray methods, Method* method, GrowableArray** reso
/*
* Resolves an interface call to a concrete method handle.
*/
-methodHandle resolve_interface_call(Klass* spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
+static methodHandle resolve_interface_call(Klass* spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {
CallInfo callinfo;
Handle receiver = args->receiver();
Klass* recvrKlass = receiver.is_null() ? (Klass*)nullptr : receiver->klass();
@@ -1435,7 +1435,7 @@ methodHandle resolve_interface_call(Klass* spec_klass, Symbol* name, Symbol* sig
/*
* Used by c2v_iterateFrames to make a new vframeStream at the given compiled frame id (stack pointer) and vframe id.
*/
-void resync_vframestream_to_compiled_frame(vframeStream& vfst, intptr_t* stack_pointer, int vframe_id, JavaThread* thread, TRAPS) {
+static void resync_vframestream_to_compiled_frame(vframeStream& vfst, intptr_t* stack_pointer, int vframe_id, JavaThread* thread, TRAPS) {
vfst = vframeStream(thread);
while (vfst.frame_id() != stack_pointer && !vfst.at_end()) {
vfst.next();
@@ -1458,7 +1458,7 @@ void resync_vframestream_to_compiled_frame(vframeStream& vfst, intptr_t* stack_p
/*
* Used by c2v_iterateFrames. Returns an array of any unallocated scope objects or null if none.
*/
-GrowableArray* get_unallocated_objects_or_null(GrowableArray* scope_objects) {
+static GrowableArray* get_unallocated_objects_or_null(GrowableArray* scope_objects) {
GrowableArray* unallocated = nullptr;
for (int i = 0; i < scope_objects->length(); i++) {
ObjectValue* sv = (ObjectValue*) scope_objects->at(i);
diff --git a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp
index dc5f7a6cdf110..84f9c9ecc4385 100644
--- a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp
+++ b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -56,12 +56,12 @@ namespace metaspace {
#define LOGFMT_ARGS p2i(this), p2i(_base)
#ifdef ASSERT
-void check_pointer_is_aligned_to_commit_granule(const MetaWord* p) {
+static void check_pointer_is_aligned_to_commit_granule(const MetaWord* p) {
assert(is_aligned(p, Settings::commit_granule_bytes()),
"Pointer not aligned to commit granule size: " PTR_FORMAT ".",
p2i(p));
}
-void check_word_size_is_aligned_to_commit_granule(size_t word_size) {
+static void check_word_size_is_aligned_to_commit_granule(size_t word_size) {
assert(is_aligned(word_size, Settings::commit_granule_words()),
"Not aligned to commit granule size: " SIZE_FORMAT ".", word_size);
}
diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp
index dfeb6b11f6f21..2a3d532725ffb 100644
--- a/src/hotspot/share/memory/universe.cpp
+++ b/src/hotspot/share/memory/universe.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
@@ -298,7 +298,7 @@ void Universe::check_alignment(uintx size, uintx alignment, const char* name) {
}
}
-void initialize_basic_type_klass(Klass* k, TRAPS) {
+static void initialize_basic_type_klass(Klass* k, TRAPS) {
Klass* ok = vmClasses::Object_klass();
#if INCLUDE_CDS
if (UseSharedSpaces) {
@@ -924,11 +924,11 @@ void universe_oopstorage_init() {
Universe::oopstorage_init();
}
-void initialize_known_method(LatestMethodCache* method_cache,
- InstanceKlass* ik,
- const char* method,
- Symbol* signature,
- bool is_static, TRAPS)
+static void initialize_known_method(LatestMethodCache* method_cache,
+ InstanceKlass* ik,
+ const char* method,
+ Symbol* signature,
+ bool is_static, TRAPS)
{
TempNewSymbol name = SymbolTable::new_symbol(method);
Method* m = nullptr;
diff --git a/src/hotspot/share/oops/constMethod.cpp b/src/hotspot/share/oops/constMethod.cpp
index 8b4b509323f3c..a6a93d6f48a94 100644
--- a/src/hotspot/share/oops/constMethod.cpp
+++ b/src/hotspot/share/oops/constMethod.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
@@ -384,7 +384,7 @@ AnnotationArray** ConstMethod::default_annotations_addr() const {
return (AnnotationArray**)constMethod_end() - offset;
}
-Array* copy_annotations(ClassLoaderData* loader_data, AnnotationArray* from, TRAPS) {
+static Array* copy_annotations(ClassLoaderData* loader_data, AnnotationArray* from, TRAPS) {
int length = from->length();
Array* a = MetadataFactory::new_array(loader_data, length, 0, CHECK_NULL);
memcpy((void*)a->adr_at(0), (void*)from->adr_at(0), length);
diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp
index daa094baa7eed..43e30a9ca3c5f 100644
--- a/src/hotspot/share/oops/cpCache.cpp
+++ b/src/hotspot/share/oops/cpCache.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -453,7 +453,7 @@ void ConstantPoolCache::set_archived_references(int root_index) {
#endif
#if INCLUDE_JVMTI
-void log_adjust(const char* entry_type, Method* old_method, Method* new_method, bool* trace_name_printed) {
+static void log_adjust(const char* entry_type, Method* old_method, Method* new_method, bool* trace_name_printed) {
ResourceMark rm;
if (!(*trace_name_printed)) {
diff --git a/src/hotspot/share/oops/klassVtable.cpp b/src/hotspot/share/oops/klassVtable.cpp
index ece1ad3c6de10..cbc379709f1f4 100644
--- a/src/hotspot/share/oops/klassVtable.cpp
+++ b/src/hotspot/share/oops/klassVtable.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
@@ -1442,7 +1442,7 @@ class InterfaceVisiterClosure : public StackObj {
};
// Visit all interfaces with at least one itable method
-void visit_all_interfaces(Array* transitive_intf, InterfaceVisiterClosure *blk) {
+static void visit_all_interfaces(Array* transitive_intf, InterfaceVisiterClosure *blk) {
// Handle array argument
for(int i = 0; i < transitive_intf->length(); i++) {
InstanceKlass* intf = transitive_intf->at(i);
diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp
index 1b92193300449..443086b6737d9 100644
--- a/src/hotspot/share/opto/addnode.cpp
+++ b/src/hotspot/share/opto/addnode.cpp
@@ -764,7 +764,7 @@ Node* OrINode::Identity(PhaseGVN* phase) {
}
// Find shift value for Integer or Long OR.
-Node* rotate_shift(PhaseGVN* phase, Node* lshift, Node* rshift, int mask) {
+static Node* rotate_shift(PhaseGVN* phase, Node* lshift, Node* rshift, int mask) {
// val << norm_con_shift | val >> ({32|64} - norm_con_shift) => rotate_left val, norm_con_shift
const TypeInt* lshift_t = phase->type(lshift)->isa_int();
const TypeInt* rshift_t = phase->type(rshift)->isa_int();
@@ -1080,7 +1080,7 @@ const Type* XorLNode::Value(PhaseGVN* phase) const {
return AddNode::Value(phase);
}
-Node* build_min_max_int(Node* a, Node* b, bool is_max) {
+static Node* build_min_max_int(Node* a, Node* b, bool is_max) {
if (is_max) {
return new MaxINode(a, b);
} else {
@@ -1312,7 +1312,7 @@ const Type *MinINode::add_ring( const Type *t0, const Type *t1 ) const {
//
// Note: we assume that SubL was already replaced by an AddL, and that the stride
// has its sign flipped: SubL(limit, stride) -> AddL(limit, -stride).
-Node* fold_subI_no_underflow_pattern(Node* n, PhaseGVN* phase) {
+static Node* fold_subI_no_underflow_pattern(Node* n, PhaseGVN* phase) {
assert(n->Opcode() == Op_MaxL || n->Opcode() == Op_MinL, "sanity");
// Check that the two clamps have the correct values.
jlong clamp = (n->Opcode() == Op_MaxL) ? min_jint : max_jint;
diff --git a/src/hotspot/share/opto/doCall.cpp b/src/hotspot/share/opto/doCall.cpp
index 122da9b447c5e..0a5e27ed5b13f 100644
--- a/src/hotspot/share/opto/doCall.cpp
+++ b/src/hotspot/share/opto/doCall.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -50,15 +50,15 @@
#include "jfr/jfr.hpp"
#endif
-void print_trace_type_profile(outputStream* out, int depth, ciKlass* prof_klass, int site_count, int receiver_count) {
+static void print_trace_type_profile(outputStream* out, int depth, ciKlass* prof_klass, int site_count, int receiver_count) {
CompileTask::print_inline_indent(depth, out);
out->print(" \\-> TypeProfile (%d/%d counts) = ", receiver_count, site_count);
prof_klass->name()->print_symbol_on(out);
out->cr();
}
-void trace_type_profile(Compile* C, ciMethod* method, int depth, int bci, ciMethod* prof_method,
- ciKlass* prof_klass, int site_count, int receiver_count) {
+static void trace_type_profile(Compile* C, ciMethod* method, int depth, int bci, ciMethod* prof_method,
+ ciKlass* prof_klass, int site_count, int receiver_count) {
if (TraceTypeProfile || C->print_inlining()) {
outputStream* out = tty;
if (!C->print_inlining()) {
diff --git a/src/hotspot/share/opto/intrinsicnode.cpp b/src/hotspot/share/opto/intrinsicnode.cpp
index 7d8894c8bdfa1..010579722bb10 100644
--- a/src/hotspot/share/opto/intrinsicnode.cpp
+++ b/src/hotspot/share/opto/intrinsicnode.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
@@ -174,7 +174,7 @@ Node* CompressBitsNode::Ideal(PhaseGVN* phase, bool can_reshape) {
return nullptr;
}
-Node* compress_expand_identity(PhaseGVN* phase, Node* n) {
+static Node* compress_expand_identity(PhaseGVN* phase, Node* n) {
BasicType bt = n->bottom_type()->basic_type();
// compress(x, 0) == 0, expand(x, 0) == 0
if(phase->type(n->in(2))->higher_equal(TypeInteger::zero(bt))) return n->in(2);
diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp
index 38fc36cec06bf..fdfbab09b8fe8 100644
--- a/src/hotspot/share/opto/loopnode.cpp
+++ b/src/hotspot/share/opto/loopnode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -5071,7 +5071,7 @@ bool PhaseIdealLoop::verify_loop_ctrl(Node* n, const PhaseIdealLoop* phase_verif
}
}
-int compare_tree(IdealLoopTree* const& a, IdealLoopTree* const& b) {
+static int compare_tree(IdealLoopTree* const& a, IdealLoopTree* const& b) {
assert(a != nullptr && b != nullptr, "must be");
return a->_head->_idx - b->_head->_idx;
}
diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp
index 44c37768cdc7d..dee4ce80d35d2 100644
--- a/src/hotspot/share/opto/node.cpp
+++ b/src/hotspot/share/opto/node.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
@@ -1632,7 +1632,7 @@ void visit_nodes(Node* start, Callback callback, bool traverse_output, bool only
}
// BFS traverse from start, return node with idx
-Node* find_node_by_idx(Node* start, uint idx, bool traverse_output, bool only_ctrl) {
+static Node* find_node_by_idx(Node* start, uint idx, bool traverse_output, bool only_ctrl) {
ResourceMark rm;
Node* result = nullptr;
auto callback = [&] (Node* n) {
@@ -1648,11 +1648,11 @@ Node* find_node_by_idx(Node* start, uint idx, bool traverse_output, bool only_ct
return result;
}
-int node_idx_cmp(const Node** n1, const Node** n2) {
+static int node_idx_cmp(const Node** n1, const Node** n2) {
return (*n1)->_idx - (*n2)->_idx;
}
-void find_nodes_by_name(Node* start, const char* name) {
+static void find_nodes_by_name(Node* start, const char* name) {
ResourceMark rm;
GrowableArray ns;
auto callback = [&] (const Node* n) {
@@ -1667,7 +1667,7 @@ void find_nodes_by_name(Node* start, const char* name) {
}
}
-void find_nodes_by_dump(Node* start, const char* pattern) {
+static void find_nodes_by_dump(Node* start, const char* pattern) {
ResourceMark rm;
GrowableArray ns;
auto callback = [&] (const Node* n) {
diff --git a/src/hotspot/share/opto/reg_split.cpp b/src/hotspot/share/opto/reg_split.cpp
index 8e5247e93b681..35b2618c64c40 100644
--- a/src/hotspot/share/opto/reg_split.cpp
+++ b/src/hotspot/share/opto/reg_split.cpp
@@ -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
@@ -289,7 +289,7 @@ int PhaseChaitin::split_USE(MachSpillCopyNode::SpillType spill_type, Node *def,
//------------------------------clone_node----------------------------
// Clone node with anti dependence check.
-Node* clone_node(Node* def, Block *b, Compile* C) {
+static Node* clone_node(Node* def, Block *b, Compile* C) {
if (def->needs_anti_dependence_check()) {
#ifdef ASSERT
if (PrintOpto && WizardMode) {
diff --git a/src/hotspot/share/opto/vectorization.cpp b/src/hotspot/share/opto/vectorization.cpp
index 98b996339fa46..a8374cbcd20db 100644
--- a/src/hotspot/share/opto/vectorization.cpp
+++ b/src/hotspot/share/opto/vectorization.cpp
@@ -1272,7 +1272,7 @@ AlignmentSolution* AlignmentSolver::solve() const {
}
#ifdef ASSERT
-void print_con_or_idx(const Node* n) {
+static void print_con_or_idx(const Node* n) {
if (n == nullptr) {
tty->print("(0)");
} else if (n->is_ConI()) {
diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp
index eee5b2a70fa5d..0a436b2778e5f 100644
--- a/src/hotspot/share/prims/jvmtiExport.cpp
+++ b/src/hotspot/share/prims/jvmtiExport.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
@@ -2437,7 +2437,7 @@ void JvmtiExport::post_native_method_bind(Method* method, address* function_ptr)
}
// Returns a record containing inlining information for the given nmethod
-jvmtiCompiledMethodLoadInlineRecord* create_inline_record(nmethod* nm) {
+static jvmtiCompiledMethodLoadInlineRecord* create_inline_record(nmethod* nm) {
jint numstackframes = 0;
jvmtiCompiledMethodLoadInlineRecord* record = (jvmtiCompiledMethodLoadInlineRecord*)NEW_RESOURCE_OBJ(jvmtiCompiledMethodLoadInlineRecord);
record->header.kind = JVMTI_CMLR_INLINE_INFO;
diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp
index 4ff09c6581b22..0dd96357506f6 100644
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -53,7 +53,7 @@ static const size_t GROW_HINT = 32;
static const size_t ResolvedMethodTableSizeLog = 10;
-unsigned int method_hash(const Method* method) {
+static unsigned int method_hash(const Method* method) {
unsigned int hash = method->method_holder()->class_loader_data()->identity_hash();
hash = (hash * 31) ^ method->klass_name()->identity_hash();
hash = (hash * 31) ^ method->name()->identity_hash();
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
index 8a4b54a22584d..dfd5eec6b4f45 100644
--- a/src/hotspot/share/runtime/arguments.cpp
+++ b/src/hotspot/share/runtime/arguments.cpp
@@ -1364,7 +1364,7 @@ void Arguments::no_shared_spaces(const char* message) {
}
}
-void set_object_alignment() {
+static void set_object_alignment() {
// Object alignment.
assert(is_power_of_2(ObjectAlignmentInBytes), "ObjectAlignmentInBytes must be power of 2");
MinObjAlignmentInBytes = ObjectAlignmentInBytes;
@@ -2009,11 +2009,12 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs *vm_options_args,
return JNI_OK;
}
+#if !INCLUDE_JVMTI
// Checks if name in command-line argument -agent{lib,path}:name[=options]
// represents a valid JDWP agent. is_path==true denotes that we
// are dealing with -agentpath (case where name is a path), otherwise with
// -agentlib
-bool valid_jdwp_agent(char *name, bool is_path) {
+static bool valid_jdwp_agent(char *name, bool is_path) {
char *_name;
const char *_jdwp = "jdwp";
size_t _len_jdwp, _len_prefix;
@@ -2053,6 +2054,7 @@ bool valid_jdwp_agent(char *name, bool is_path) {
return false;
}
+#endif
int Arguments::process_patch_mod_option(const char* patch_mod_tail, bool* patch_mod_javabase) {
// --patch-module==(