diff --git a/src/hotspot/cpu/x86/stubDeclarations_x86.hpp b/src/hotspot/cpu/x86/stubDeclarations_x86.hpp index 2ca05bc773e..419c0b62e5c 100644 --- a/src/hotspot/cpu/x86/stubDeclarations_x86.hpp +++ b/src/hotspot/cpu/x86/stubDeclarations_x86.hpp @@ -30,7 +30,7 @@ do_arch_blob, \ do_arch_entry, \ do_arch_entry_init) \ - do_arch_blob(initial, 20000 WINDOWS_ONLY(+1000)) \ + do_arch_blob(initial, PRODUCT_ONLY(20000) NOT_PRODUCT(21000) WINDOWS_ONLY(+1000)) \ do_stub(initial, verify_mxcsr) \ do_arch_entry(x86, initial, verify_mxcsr, verify_mxcsr_entry, \ verify_mxcsr_entry) \ diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp deleted file mode 100644 index a4817cbc87d..00000000000 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp" -#include "jfr/recorder/checkpoint/types/jfrThreadGroup.hpp" -#include "jfr/utilities/jfrTypes.hpp" -#include "runtime/handles.inline.hpp" -#include "runtime/jniHandles.inline.hpp" -#include "runtime/safepoint.hpp" -#include "runtime/semaphore.hpp" -#include "utilities/growableArray.hpp" - -static const int initial_array_size = 30; - -class ThreadGroupExclusiveAccess : public StackObj { - private: - static Semaphore _mutex_semaphore; - public: - ThreadGroupExclusiveAccess() { _mutex_semaphore.wait(); } - ~ThreadGroupExclusiveAccess() { _mutex_semaphore.signal(); } -}; - -Semaphore ThreadGroupExclusiveAccess::_mutex_semaphore(1); -JfrThreadGroup* JfrThreadGroup::_instance = nullptr; - -class JfrThreadGroupPointers : public ResourceObj { - private: - const Handle _thread_group_handle; - jweak _thread_group_weak_ref; - public: - JfrThreadGroupPointers(Handle thread_group_handle, jweak thread_group_weak_ref); - Handle thread_group_handle() const; - jweak thread_group_weak_ref() const; - oopDesc* thread_group_oop() const; - jweak transfer_weak_global_handle_ownership(); - void clear_weak_ref(); -}; - -JfrThreadGroupPointers::JfrThreadGroupPointers(Handle thread_group_handle, jweak thread_group_weak_ref) : - _thread_group_handle(thread_group_handle), - _thread_group_weak_ref(thread_group_weak_ref) {} - -Handle JfrThreadGroupPointers::thread_group_handle() const { - return _thread_group_handle; -} - -jweak JfrThreadGroupPointers::thread_group_weak_ref() const { - return _thread_group_weak_ref; -} - -oopDesc* JfrThreadGroupPointers::thread_group_oop() const { - assert(_thread_group_weak_ref == nullptr || - JNIHandles::resolve_non_null(_thread_group_weak_ref) == _thread_group_handle(), "invariant"); - return _thread_group_handle(); -} - -jweak JfrThreadGroupPointers::transfer_weak_global_handle_ownership() { - jweak temp = _thread_group_weak_ref; - _thread_group_weak_ref = nullptr; - return temp; -} - -void JfrThreadGroupPointers::clear_weak_ref() { - if (nullptr != _thread_group_weak_ref) { - JNIHandles::destroy_weak_global(_thread_group_weak_ref); - } -} - -class JfrThreadGroupsHelper : public ResourceObj { - private: - static const int invalid_iterator_pos = -1; - GrowableArray* _thread_group_hierarchy; - int _current_iterator_pos; - - int populate_thread_group_hierarchy(const JavaThread* jt, Thread* current); - JfrThreadGroupPointers& at(int index); - - public: - JfrThreadGroupsHelper(const JavaThread* jt, Thread* current); - ~JfrThreadGroupsHelper(); - JfrThreadGroupPointers& next(); - bool is_valid() const; - bool has_next() const; -}; - -JfrThreadGroupsHelper::JfrThreadGroupsHelper(const JavaThread* jt, Thread* current) { - _thread_group_hierarchy = new GrowableArray(10); - _current_iterator_pos = populate_thread_group_hierarchy(jt, current) - 1; -} - -JfrThreadGroupsHelper::~JfrThreadGroupsHelper() { - assert(_current_iterator_pos == invalid_iterator_pos, "invariant"); - for (int i = 0; i < _thread_group_hierarchy->length(); ++i) { - _thread_group_hierarchy->at(i)->clear_weak_ref(); - } -} - -JfrThreadGroupPointers& JfrThreadGroupsHelper::at(int index) { - assert(_thread_group_hierarchy != nullptr, "invariant"); - assert(index > invalid_iterator_pos && index < _thread_group_hierarchy->length(), "invariant"); - return *(_thread_group_hierarchy->at(index)); -} - -bool JfrThreadGroupsHelper::has_next() const { - return _current_iterator_pos > invalid_iterator_pos; -} - -bool JfrThreadGroupsHelper::is_valid() const { - return (_thread_group_hierarchy != nullptr && _thread_group_hierarchy->length() > 0); -} - -JfrThreadGroupPointers& JfrThreadGroupsHelper::next() { - assert(is_valid(), "invariant"); - return at(_current_iterator_pos--); -} - -/* - * If not at a safepoint, we create global weak references for - * all reachable threadgroups for this thread. - * If we are at a safepoint, the caller is the VMThread during - * JFR checkpointing. It can use naked oops, because nothing - * will move before the list of threadgroups is cleared and - * mutator threads restarted. The threadgroup list is cleared - * later by the VMThread as one of the final steps in JFR checkpointing - * (not here). - */ -int JfrThreadGroupsHelper::populate_thread_group_hierarchy(const JavaThread* jt, Thread* current) { - assert(jt != nullptr && jt->is_Java_thread(), "invariant"); - assert(current != nullptr, "invariant"); - assert(_thread_group_hierarchy != nullptr, "invariant"); - - oop thread_oop = jt->threadObj(); - if (thread_oop == nullptr) { - return 0; - } - // immediate thread group - Handle thread_group_handle(current, java_lang_Thread::threadGroup(thread_oop)); - if (thread_group_handle == nullptr) { - return 0; - } - - const bool use_weak_handles = !SafepointSynchronize::is_at_safepoint(); - jweak thread_group_weak_ref = use_weak_handles ? JNIHandles::make_weak_global(thread_group_handle) : nullptr; - - JfrThreadGroupPointers* thread_group_pointers = new JfrThreadGroupPointers(thread_group_handle, thread_group_weak_ref); - _thread_group_hierarchy->append(thread_group_pointers); - // immediate parent thread group - oop parent_thread_group_obj = java_lang_ThreadGroup::parent(thread_group_handle()); - Handle parent_thread_group_handle(current, parent_thread_group_obj); - - // and check parents parents... - while (parent_thread_group_handle != nullptr) { - const jweak parent_group_weak_ref = use_weak_handles ? JNIHandles::make_weak_global(parent_thread_group_handle) : nullptr; - thread_group_pointers = new JfrThreadGroupPointers(parent_thread_group_handle, parent_group_weak_ref); - _thread_group_hierarchy->append(thread_group_pointers); - parent_thread_group_obj = java_lang_ThreadGroup::parent(parent_thread_group_handle()); - parent_thread_group_handle = Handle(current, parent_thread_group_obj); - } - return _thread_group_hierarchy->length(); -} - -static traceid next_id() { - static traceid _current_threadgroup_id = 1; // 1 is reserved for thread group "VirtualThreads" - return ++_current_threadgroup_id; -} - -class JfrThreadGroup::JfrThreadGroupEntry : public JfrCHeapObj { - friend class JfrThreadGroup; - private: - traceid _thread_group_id; - traceid _parent_group_id; - char* _thread_group_name; // utf8 format - // If an entry is created during a safepoint, the - // _thread_group_oop contains a direct oop to - // the java.lang.ThreadGroup object. - // If an entry is created on javathread exit time (not at safepoint), - // _thread_group_weak_ref contains a JNI weak global handle - // indirection to the java.lang.ThreadGroup object. - // Note: we cannot use a union here since CHECK_UNHANDLED_OOPS makes oop have - // a ctor which isn't allowed in a union by the SunStudio compiler - oop _thread_group_oop; - jweak _thread_group_weak_ref; - - JfrThreadGroupEntry(const char* tgstr, JfrThreadGroupPointers& ptrs); - ~JfrThreadGroupEntry(); - - traceid thread_group_id() const { return _thread_group_id; } - void set_thread_group_id(traceid tgid) { _thread_group_id = tgid; } - - const char* thread_group_name() const { return _thread_group_name; } - void set_thread_group_name(const char* tgname); - - traceid parent_group_id() const { return _parent_group_id; } - void set_parent_group_id(traceid pgid) { _parent_group_id = pgid; } - - void set_thread_group(JfrThreadGroupPointers& ptrs); - bool is_equal(const JfrThreadGroupPointers& ptrs) const; - oop thread_group() const; -}; - -JfrThreadGroup::JfrThreadGroupEntry::JfrThreadGroupEntry(const char* tgname, JfrThreadGroupPointers& ptrs) : - _thread_group_id(0), - _parent_group_id(0), - _thread_group_name(nullptr), - _thread_group_oop(nullptr), - _thread_group_weak_ref(nullptr) { - set_thread_group_name(tgname); - set_thread_group(ptrs); -} - -JfrThreadGroup::JfrThreadGroupEntry::~JfrThreadGroupEntry() { - if (_thread_group_name != nullptr) { - JfrCHeapObj::free(_thread_group_name, strlen(_thread_group_name) + 1); - } - if (_thread_group_weak_ref != nullptr) { - JNIHandles::destroy_weak_global(_thread_group_weak_ref); - } -} - -void JfrThreadGroup::JfrThreadGroupEntry::set_thread_group_name(const char* tgname) { - assert(_thread_group_name == nullptr, "invariant"); - if (tgname != nullptr) { - size_t len = strlen(tgname); - _thread_group_name = JfrCHeapObj::new_array(len + 1); - strncpy(_thread_group_name, tgname, len + 1); - } -} - -oop JfrThreadGroup::JfrThreadGroupEntry::thread_group() const { - return _thread_group_weak_ref != nullptr ? JNIHandles::resolve(_thread_group_weak_ref) : _thread_group_oop; -} - -void JfrThreadGroup::JfrThreadGroupEntry::set_thread_group(JfrThreadGroupPointers& ptrs) { - _thread_group_weak_ref = ptrs.transfer_weak_global_handle_ownership(); - if (_thread_group_weak_ref == nullptr) { - _thread_group_oop = ptrs.thread_group_oop(); - assert(_thread_group_oop != nullptr, "invariant"); - } else { - _thread_group_oop = nullptr; - } -} - -JfrThreadGroup::JfrThreadGroup() : - _list(new (mtTracing) GrowableArray(initial_array_size, mtTracing)) {} - -JfrThreadGroup::~JfrThreadGroup() { - if (_list != nullptr) { - for (int i = 0; i < _list->length(); i++) { - JfrThreadGroupEntry* e = _list->at(i); - delete e; - } - delete _list; - } -} - -JfrThreadGroup* JfrThreadGroup::instance() { - return _instance; -} - -void JfrThreadGroup::set_instance(JfrThreadGroup* new_instance) { - _instance = new_instance; -} - -traceid JfrThreadGroup::thread_group_id(const JavaThread* jt, Thread* current) { - HandleMark hm(current); - JfrThreadGroupsHelper helper(jt, current); - return helper.is_valid() ? thread_group_id_internal(helper) : 0; -} - -traceid JfrThreadGroup::thread_group_id(JavaThread* const jt) { - return thread_group_id(jt, jt); -} - -traceid JfrThreadGroup::thread_group_id_internal(JfrThreadGroupsHelper& helper) { - ThreadGroupExclusiveAccess lock; - JfrThreadGroup* tg_instance = instance(); - if (tg_instance == nullptr) { - tg_instance = new JfrThreadGroup(); - if (tg_instance == nullptr) { - return 0; - } - set_instance(tg_instance); - } - - JfrThreadGroupEntry* tge = nullptr; - traceid parent_thread_group_id = 0; - while (helper.has_next()) { - JfrThreadGroupPointers& ptrs = helper.next(); - tge = tg_instance->find_entry(ptrs); - if (nullptr == tge) { - tge = tg_instance->new_entry(ptrs); - assert(tge != nullptr, "invariant"); - tge->set_parent_group_id(parent_thread_group_id); - } - parent_thread_group_id = tge->thread_group_id(); - } - // the last entry in the hierarchy is the immediate thread group - return tge->thread_group_id(); -} - -bool JfrThreadGroup::JfrThreadGroupEntry::is_equal(const JfrThreadGroupPointers& ptrs) const { - return ptrs.thread_group_oop() == thread_group(); -} - -JfrThreadGroup::JfrThreadGroupEntry* -JfrThreadGroup::find_entry(const JfrThreadGroupPointers& ptrs) const { - for (int index = 0; index < _list->length(); ++index) { - JfrThreadGroupEntry* curtge = _list->at(index); - if (curtge->is_equal(ptrs)) { - return curtge; - } - } - return (JfrThreadGroupEntry*) nullptr; -} - -// Assumes you already searched for the existence -// of a corresponding entry in find_entry(). -JfrThreadGroup::JfrThreadGroupEntry* -JfrThreadGroup::new_entry(JfrThreadGroupPointers& ptrs) { - JfrThreadGroupEntry* const tge = new JfrThreadGroupEntry(java_lang_ThreadGroup::name(ptrs.thread_group_oop()), ptrs); - add_entry(tge); - return tge; -} - -int JfrThreadGroup::add_entry(JfrThreadGroupEntry* tge) { - assert(tge != nullptr, "attempting to add a null entry!"); - assert(0 == tge->thread_group_id(), "id must be unassigned!"); - tge->set_thread_group_id(next_id()); - return _list->append(tge); -} - -void JfrThreadGroup::write_thread_group_entries(JfrCheckpointWriter& writer) const { - assert(_list != nullptr && !_list->is_empty(), "should not need be here!"); - const int number_of_tg_entries = _list->length(); - writer.write_count(number_of_tg_entries + 1); // + VirtualThread group - writer.write_key(1); // 1 is reserved for VirtualThread group - writer.write(0); // parent - const oop vgroup = java_lang_Thread_Constants::get_VTHREAD_GROUP(); - assert(vgroup != (oop)nullptr, "invariant"); - const char* const vgroup_name = java_lang_ThreadGroup::name(vgroup); - assert(vgroup_name != nullptr, "invariant"); - writer.write(vgroup_name); - for (int index = 0; index < number_of_tg_entries; ++index) { - const JfrThreadGroupEntry* const curtge = _list->at(index); - writer.write_key(curtge->thread_group_id()); - writer.write(curtge->parent_group_id()); - writer.write(curtge->thread_group_name()); - } -} - -void JfrThreadGroup::write_selective_thread_group(JfrCheckpointWriter* writer, traceid thread_group_id) const { - assert(writer != nullptr, "invariant"); - assert(_list != nullptr && !_list->is_empty(), "should not need be here!"); - assert(thread_group_id != 1, "should not need be here!"); - const int number_of_tg_entries = _list->length(); - - // save context - const JfrCheckpointContext ctx = writer->context(); - writer->write_type(TYPE_THREADGROUP); - const jlong count_offset = writer->reserve(sizeof(u4)); // Don't know how many yet - int number_of_entries_written = 0; - for (int index = number_of_tg_entries - 1; index >= 0; --index) { - const JfrThreadGroupEntry* const curtge = _list->at(index); - if (thread_group_id == curtge->thread_group_id()) { - writer->write_key(curtge->thread_group_id()); - writer->write(curtge->parent_group_id()); - writer->write(curtge->thread_group_name()); - ++number_of_entries_written; - thread_group_id = curtge->parent_group_id(); - } - } - if (number_of_entries_written == 0) { - // nothing to write, restore context - writer->set_context(ctx); - return; - } - assert(number_of_entries_written > 0, "invariant"); - writer->write_count(number_of_entries_written, count_offset); -} - -// Write out JfrThreadGroup instance and then delete it -void JfrThreadGroup::serialize(JfrCheckpointWriter& writer) { - ThreadGroupExclusiveAccess lock; - JfrThreadGroup* tg_instance = instance(); - assert(tg_instance != nullptr, "invariant"); - tg_instance->write_thread_group_entries(writer); -} - -// for writing a particular thread group -void JfrThreadGroup::serialize(JfrCheckpointWriter* writer, traceid thread_group_id) { - assert(writer != nullptr, "invariant"); - ThreadGroupExclusiveAccess lock; - JfrThreadGroup* const tg_instance = instance(); - assert(tg_instance != nullptr, "invariant"); - tg_instance->write_selective_thread_group(writer, thread_group_id); -} diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroupManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroupManager.cpp new file mode 100644 index 00000000000..55864af4d5c --- /dev/null +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroupManager.cpp @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 "jfr/jni/jfrJavaSupport.hpp" +#include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp" +#include "jfr/recorder/checkpoint/types/jfrThreadGroupManager.hpp" +#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp" +#include "jfr/utilities/jfrAllocation.hpp" +#include "jfr/utilities/jfrLinkedList.inline.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/jniHandles.inline.hpp" +#include "runtime/safepoint.hpp" +#include "runtime/semaphore.hpp" +#include "runtime/thread.inline.hpp" +#include "utilities/growableArray.hpp" + +class ThreadGroupExclusiveAccess : public StackObj { + private: + static Semaphore _mutex_semaphore; + public: + ThreadGroupExclusiveAccess() { _mutex_semaphore.wait(); } + ~ThreadGroupExclusiveAccess() { _mutex_semaphore.signal(); } +}; + +Semaphore ThreadGroupExclusiveAccess::_mutex_semaphore(1); + +static traceid next_id() { + static traceid _tgid = 1; // 1 is reserved for thread group "VirtualThreads" + return ++_tgid; +} + +class JfrThreadGroup : public JfrCHeapObj { + template + friend class JfrLinkedList; + private: + mutable const JfrThreadGroup* _next; + const JfrThreadGroup* _parent; + traceid _tgid; + char* _tg_name; // utf8 format + jweak _tg_handle; + mutable u2 _generation; + + public: + JfrThreadGroup(Handle tg, const JfrThreadGroup* parent) : + _next(nullptr), _parent(parent), _tgid(next_id()), _tg_name(nullptr), + _tg_handle(JNIHandles::make_weak_global(tg)), _generation(0) { + const char* name = java_lang_ThreadGroup::name(tg()); + if (name != nullptr) { + const size_t len = strlen(name); + _tg_name = JfrCHeapObj::new_array(len + 1); + strncpy(_tg_name, name, len + 1); + } + } + + ~JfrThreadGroup() { + JNIHandles::destroy_weak_global(_tg_handle); + if (_tg_name != nullptr) { + JfrCHeapObj::free(_tg_name, strlen(_tg_name) + 1); + } + } + + const JfrThreadGroup* next() const { return _next; } + + traceid id() const { return _tgid; } + + const char* name() const { + return _tg_name; + } + + const JfrThreadGroup* parent() const { return _parent; } + + traceid parent_id() const { + return _parent != nullptr ? _parent->id() : 0; + } + + bool is_dead() const { + return JNIHandles::resolve(_tg_handle) == nullptr; + } + + bool operator==(oop tg) const { + assert(tg != nullptr, "invariant"); + return tg == JNIHandles::resolve(_tg_handle); + } + + bool should_write() const { + return !JfrTraceIdEpoch::is_current_epoch_generation(_generation); + } + + void set_written() const { + assert(should_write(), "invariant"); + _generation = JfrTraceIdEpoch::epoch_generation(); + } +}; + +typedef JfrLinkedList JfrThreadGroupList; + +static JfrThreadGroupList* _list = nullptr; + +static JfrThreadGroupList& list() { + assert(_list != nullptr, "invariant"); + return *_list; +} + +bool JfrThreadGroupManager::create() { + assert(_list == nullptr, "invariant"); + _list = new JfrThreadGroupList(); + return _list != nullptr; +} + +void JfrThreadGroupManager::destroy() { + delete _list; + _list = nullptr; +} + +static int populate(GrowableArray* hierarchy, const JavaThread* jt, Thread* current) { + assert(hierarchy != nullptr, "invariant"); + assert(jt != nullptr, "invariant"); + assert(current == Thread::current(), "invariant"); + + oop thread_oop = jt->threadObj(); + if (thread_oop == nullptr) { + return 0; + } + // Immediate thread group. + const Handle tg_handle(current, java_lang_Thread::threadGroup(thread_oop)); + if (tg_handle.is_null()) { + return 0; + } + hierarchy->append(tg_handle); + + // Thread group parent and then its parents... + Handle parent_tg_handle(current, java_lang_ThreadGroup::parent(tg_handle())); + + while (parent_tg_handle != nullptr) { + hierarchy->append(parent_tg_handle); + parent_tg_handle = Handle(current, java_lang_ThreadGroup::parent(parent_tg_handle())); + } + + return hierarchy->length(); +} + +class JfrThreadGroupLookup : public ResourceObj { + static const int invalid_iterator = -1; + private: + GrowableArray* _hierarchy; + mutable int _iterator; + + public: + JfrThreadGroupLookup(const JavaThread* jt, Thread* current) : + _hierarchy(new GrowableArray(16)), + _iterator(populate(_hierarchy, jt, current) - 1) {} + + bool has_next() const { + return _iterator > invalid_iterator; + } + + const Handle& next() const { + assert(has_next(), "invariant"); + return _hierarchy->at(_iterator--); + } +}; + +static const JfrThreadGroup* find_or_add(const Handle& tg_oop, const JfrThreadGroup* parent) { + assert(parent == nullptr || list().in_list(parent), "invariant"); + const JfrThreadGroup* tg = list().head(); + const JfrThreadGroup* result = nullptr; + while (tg != nullptr) { + if (*tg == tg_oop()) { + assert(tg->parent() == parent, "invariant"); + result = tg; + tg = nullptr; + continue; + } + tg = tg->next(); + } + if (result == nullptr) { + result = new JfrThreadGroup(tg_oop, parent); + list().add(result); + } + return result; +} + +static traceid find_tgid(const JfrThreadGroupLookup& lookup) { + const JfrThreadGroup* tg = nullptr; + const JfrThreadGroup* ptg = nullptr; + while (lookup.has_next()) { + tg = find_or_add(lookup.next(), ptg); + ptg = tg; + } + return tg != nullptr ? tg->id() : 0; +} + +static traceid find(const JfrThreadGroupLookup& lookup) { + ThreadGroupExclusiveAccess lock; + return find_tgid(lookup); +} + +traceid JfrThreadGroupManager::thread_group_id(JavaThread* jt) { + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(jt);) + ResourceMark rm(jt); + HandleMark hm(jt); + const JfrThreadGroupLookup lookup(jt, jt); + return find(lookup); +} + +traceid JfrThreadGroupManager::thread_group_id(const JavaThread* jt, Thread* current) { + assert(jt != nullptr, "invariant"); + assert(current != nullptr, "invariant"); + assert(!current->is_Java_thread() || JavaThread::cast(current)->thread_state() == _thread_in_vm, "invariant"); + ResourceMark rm(current); + HandleMark hm(current); + const JfrThreadGroupLookup lookup(jt, current); + return find(lookup); +} + +static void write_virtual_thread_group(JfrCheckpointWriter& writer) { + writer.write_key(1); // 1 is reserved for VirtualThread group + writer.write(0); // parent + const oop vgroup = java_lang_Thread_Constants::get_VTHREAD_GROUP(); + assert(vgroup != (oop)nullptr, "invariant"); + const char* const vgroup_name = java_lang_ThreadGroup::name(vgroup); + assert(vgroup_name != nullptr, "invariant"); + writer.write(vgroup_name); +} + +static int write_thread_group(JfrCheckpointWriter& writer, const JfrThreadGroup* tg, bool to_blob = false) { + assert(tg != nullptr, "invariant"); + if (tg->should_write() || to_blob) { + writer.write_key(tg->id()); + writer.write(tg->parent_id()); + writer.write(tg->name()); + if (!to_blob) { + tg->set_written(); + } + return 1; + } + return 0; +} + +// For writing all live thread groups while removing and deleting dead thread groups. +void JfrThreadGroupManager::serialize(JfrCheckpointWriter& writer) { + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(JavaThread::current());) + + const uint64_t count_offset = writer.reserve(sizeof(u4)); // Don't know how many yet + + // First write the pre-defined ThreadGroup for virtual threads. + write_virtual_thread_group(writer); + int number_of_groups_written = 1; + + const JfrThreadGroup* next = nullptr; + const JfrThreadGroup* prev = nullptr; + + { + ThreadGroupExclusiveAccess lock; + const JfrThreadGroup* tg = list().head(); + while (tg != nullptr) { + next = tg->next(); + if (tg->is_dead()) { + prev = list().excise(prev, tg); + assert(!list().in_list(tg), "invariant"); + delete tg; + tg = next; + continue; + } + number_of_groups_written += write_thread_group(writer, tg); + prev = tg; + tg = next; + } + } + + assert(number_of_groups_written > 0, "invariant"); + writer.write_count(number_of_groups_written, count_offset); +} + +// For writing a specific thread group and its ancestry. +void JfrThreadGroupManager::serialize(JfrCheckpointWriter& writer, traceid tgid, bool to_blob) { + DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(JavaThread::current());) + // save context + const JfrCheckpointContext ctx = writer.context(); + + writer.write_type(TYPE_THREADGROUP); + const uint64_t count_offset = writer.reserve(sizeof(u4)); // Don't know how many yet + + int number_of_groups_written = 0; + + { + ThreadGroupExclusiveAccess lock; + const JfrThreadGroup* tg = list().head(); + while (tg != nullptr) { + if (tgid == tg->id()) { + while (tg != nullptr) { + number_of_groups_written += write_thread_group(writer, tg, to_blob); + tg = tg->parent(); + } + break; + } + tg = tg->next(); + } + } + + if (number_of_groups_written == 0) { + // nothing to write, restore context + writer.set_context(ctx); + return; + } + + assert(number_of_groups_written > 0, "invariant"); + writer.write_count(number_of_groups_written, count_offset); +} diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroupManager.hpp similarity index 50% rename from src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.hpp rename to src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroupManager.hpp index 8226c6ebef2..22c140c6f8f 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroup.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrThreadGroupManager.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,44 +22,27 @@ * */ -#ifndef SHARE_JFR_RECORDER_CHECKPOINT_TYPES_JFRTHREADGROUP_HPP -#define SHARE_JFR_RECORDER_CHECKPOINT_TYPES_JFRTHREADGROUP_HPP +#ifndef SHARE_JFR_RECORDER_CHECKPOINT_TYPES_JFRTHREADGROUPMANAGER_HPP +#define SHARE_JFR_RECORDER_CHECKPOINT_TYPES_JFRTHREADGROUPMANAGER_HPP -#include "jfr/utilities/jfrAllocation.hpp" #include "jfr/utilities/jfrTypes.hpp" -#include "jni.h" +#include "memory/allStatic.hpp" class JfrCheckpointWriter; -template -class GrowableArray; -class JfrThreadGroupsHelper; -class JfrThreadGroupPointers; -class JfrThreadGroup : public JfrCHeapObj { - friend class JfrCheckpointThreadClosure; - private: - static JfrThreadGroup* _instance; - class JfrThreadGroupEntry; - GrowableArray* _list; - - JfrThreadGroup(); - JfrThreadGroupEntry* find_entry(const JfrThreadGroupPointers& ptrs) const; - JfrThreadGroupEntry* new_entry(JfrThreadGroupPointers& ptrs); - int add_entry(JfrThreadGroupEntry* const tge); - - void write_thread_group_entries(JfrCheckpointWriter& writer) const; - void write_selective_thread_group(JfrCheckpointWriter* writer, traceid thread_group_id) const; +class JfrThreadGroupManager : public AllStatic { + friend class JfrRecorder; - static traceid thread_group_id_internal(JfrThreadGroupsHelper& helper); - static JfrThreadGroup* instance(); - static void set_instance(JfrThreadGroup* new_instance); + private: + static bool create(); + static void destroy(); public: - ~JfrThreadGroup(); static void serialize(JfrCheckpointWriter& w); - static void serialize(JfrCheckpointWriter* w, traceid thread_group_id); + static void serialize(JfrCheckpointWriter& w, traceid tgid, bool is_blob); + static traceid thread_group_id(JavaThread* thread); static traceid thread_group_id(const JavaThread* thread, Thread* current); }; -#endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_JFRTHREADGROUP_HPP +#endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_JFRTHREADGROUPMANAGER_HPP diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp index 9179395a451..17d945af65e 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp @@ -32,7 +32,7 @@ #include "gc/shared/gcWhen.hpp" #include "jfr/leakprofiler/leakProfiler.hpp" #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp" -#include "jfr/recorder/checkpoint/types/jfrThreadGroup.hpp" +#include "jfr/recorder/checkpoint/types/jfrThreadGroupManager.hpp" #include "jfr/recorder/checkpoint/types/jfrThreadState.hpp" #include "jfr/recorder/checkpoint/types/jfrType.hpp" #include "jfr/recorder/jfrRecorder.hpp" @@ -106,7 +106,7 @@ void JfrCheckpointThreadClosure::do_thread(Thread* t) { } else { _writer.write(name); _writer.write(tid); - _writer.write(JfrThreadGroup::thread_group_id(JavaThread::cast(t), _curthread)); + _writer.write(JfrThreadGroupManager::thread_group_id(JavaThread::cast(t), _curthread)); } _writer.write(false); // isVirtual } @@ -115,7 +115,10 @@ void JfrThreadConstantSet::serialize(JfrCheckpointWriter& writer) { JfrCheckpointThreadClosure tc(writer); JfrJavaThreadIterator javathreads; while (javathreads.has_next()) { - tc.do_thread(javathreads.next()); + JavaThread* const jt = javathreads.next(); + if (jt->jfr_thread_local()->should_write()) { + tc.do_thread(jt); + } } JfrNonJavaThreadIterator nonjavathreads; while (nonjavathreads.has_next()) { @@ -124,7 +127,7 @@ void JfrThreadConstantSet::serialize(JfrCheckpointWriter& writer) { } void JfrThreadGroupConstant::serialize(JfrCheckpointWriter& writer) { - JfrThreadGroup::serialize(writer); + JfrThreadGroupManager::serialize(writer); } static const char* flag_value_origin_to_string(JVMFlagOrigin origin) { @@ -303,11 +306,11 @@ void JfrThreadConstant::serialize(JfrCheckpointWriter& writer) { writer.write(JfrThreadId::jfr_id(_thread, _tid)); // java thread group - VirtualThread threadgroup reserved id 1 const traceid thread_group_id = is_vthread ? 1 : - JfrThreadGroup::thread_group_id(JavaThread::cast(_thread), Thread::current()); + JfrThreadGroupManager::thread_group_id(JavaThread::cast(_thread), Thread::current()); writer.write(thread_group_id); writer.write(is_vthread); // isVirtual - if (!is_vthread) { - JfrThreadGroup::serialize(&writer, thread_group_id); + if (thread_group_id > 1) { + JfrThreadGroupManager::serialize(writer, thread_group_id, _to_blob); } // VirtualThread threadgroup already serialized invariant. } diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.hpp index de35ecaf917..9798a6d29c0 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,11 +109,12 @@ class JfrThreadConstant : public JfrSerializer { oop _vthread; const char* _name; int _length; + const bool _to_blob; void write_name(JfrCheckpointWriter& writer); void write_os_name(JfrCheckpointWriter& writer, bool is_vthread); public: - JfrThreadConstant(Thread* t, traceid tid, oop vthread = nullptr) : - _thread(t), _tid(tid), _vthread(vthread), _name(nullptr), _length(-1) {} + JfrThreadConstant(Thread* t, traceid tid, bool to_blob, oop vthread = nullptr) : + _thread(t), _tid(tid), _vthread(vthread), _name(nullptr), _length(-1), _to_blob(to_blob) {} void serialize(JfrCheckpointWriter& writer); }; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp index 493942bade4..58d12f70980 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp @@ -109,7 +109,7 @@ JfrBlobHandle JfrTypeManager::create_thread_blob(JavaThread* jt, traceid tid /* // TYPE_THREAD and count is written unconditionally for blobs, also for vthreads. writer.write_type(TYPE_THREAD); writer.write_count(1); - JfrThreadConstant type_thread(jt, tid, vthread); + JfrThreadConstant type_thread(jt, tid, true, vthread); type_thread.serialize(writer); return writer.move(); } @@ -128,7 +128,7 @@ void JfrTypeManager::write_checkpoint(Thread* t, traceid tid /* 0 */, oop vthrea writer.write_type(TYPE_THREAD); writer.write_count(1); } - JfrThreadConstant type_thread(t, tid, vthread); + JfrThreadConstant type_thread(t, tid, false, vthread); type_thread.serialize(writer); } diff --git a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp index dd75cb2929f..4ef278ab522 100644 --- a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp +++ b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp @@ -33,6 +33,7 @@ #include "jfr/periodic/sampling/jfrThreadSampler.hpp" #include "jfr/recorder/jfrRecorder.hpp" #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp" +#include "jfr/recorder/checkpoint/types/jfrThreadGroupManager.hpp" #include "jfr/recorder/repository/jfrRepository.hpp" #include "jfr/recorder/service/jfrEventThrottler.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" @@ -311,6 +312,9 @@ bool JfrRecorder::create_components() { if (!create_event_throttler()) { return false; } + if (!create_thread_group_manager()) { + return false; + } return true; } @@ -405,6 +409,10 @@ bool JfrRecorder::create_event_throttler() { return JfrEventThrottler::create(); } +bool JfrRecorder::create_thread_group_manager() { + return JfrThreadGroupManager::create(); +} + void JfrRecorder::destroy_components() { JfrJvmtiAgent::destroy(); if (_post_box != nullptr) { @@ -444,6 +452,7 @@ void JfrRecorder::destroy_components() { _cpu_time_thread_sampling = nullptr; } JfrEventThrottler::destroy(); + JfrThreadGroupManager::destroy(); } bool JfrRecorder::create_recorder_thread() { diff --git a/src/hotspot/share/jfr/recorder/jfrRecorder.hpp b/src/hotspot/share/jfr/recorder/jfrRecorder.hpp index 3099c8ad344..34cc8fda949 100644 --- a/src/hotspot/share/jfr/recorder/jfrRecorder.hpp +++ b/src/hotspot/share/jfr/recorder/jfrRecorder.hpp @@ -53,6 +53,7 @@ class JfrRecorder : public JfrCHeapObj { static bool create_stacktrace_repository(); static bool create_storage(); static bool create_stringpool(); + static bool create_thread_group_manager(); static bool create_thread_sampler(); static bool create_cpu_time_thread_sampling(); static bool create_event_throttler(); diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp index e38e0427a05..291169b9aa7 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp @@ -29,6 +29,7 @@ #include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp" #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp" #include "jfr/recorder/checkpoint/types/traceid/jfrOopTraceId.inline.hpp" +#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp" #include "jfr/recorder/jfrRecorder.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp" @@ -75,6 +76,7 @@ JfrThreadLocal::JfrThreadLocal() : _wallclock_time(os::javaTimeNanos()), _non_reentrant_nesting(0), _vthread_epoch(0), + _generation(0), _vthread_excluded(false), _jvm_thread_excluded(false), _enqueued_requests(false), @@ -136,17 +138,33 @@ static void send_java_thread_start_event(JavaThread* jt) { } void JfrThreadLocal::on_start(Thread* t) { - assign_thread_id(t, t->jfr_thread_local()); + JfrThreadLocal* const tl = t->jfr_thread_local(); + assert(tl != nullptr, "invariant"); + assign_thread_id(t, tl); if (JfrRecorder::is_recording()) { - JfrCheckpointManager::write_checkpoint(t); - if (t->is_Java_thread()) { - JavaThread *const jt = JavaThread::cast(t); + if (!t->is_Java_thread()) { + JfrCheckpointManager::write_checkpoint(t); + return; + } + JavaThread* const jt = JavaThread::cast(t); + if (jt->thread_state() == _thread_new) { JfrCPUTimeThreadSampling::on_javathread_create(jt); + } else { + assert(jt->thread_state() == _thread_in_vm, "invariant"); + if (tl->should_write()) { + JfrCheckpointManager::write_checkpoint(t); + } send_java_thread_start_event(jt); + if (tl->has_cached_stack_trace()) { + tl->clear_cached_stack_trace(); + } + return; } } - if (t->jfr_thread_local()->has_cached_stack_trace()) { - t->jfr_thread_local()->clear_cached_stack_trace(); + if (t->is_Java_thread() && JavaThread::cast(t)->thread_state() == _thread_in_vm) { + if (tl->has_cached_stack_trace()) { + tl->clear_cached_stack_trace(); + } } } @@ -229,13 +247,18 @@ void JfrThreadLocal::on_exit(Thread* t) { JfrThreadLocal * const tl = t->jfr_thread_local(); assert(!tl->is_dead(), "invariant"); if (JfrRecorder::is_recording()) { - JfrCheckpointManager::write_checkpoint(t); - } - if (t->is_Java_thread()) { - JavaThread* const jt = JavaThread::cast(t); - send_java_thread_end_event(jt, JfrThreadLocal::jvm_thread_id(jt)); - JfrCPUTimeThreadSampling::on_javathread_terminate(jt); - JfrThreadCPULoadEvent::send_event_for_thread(jt); + if (!t->is_Java_thread()) { + JfrCheckpointManager::write_checkpoint(t); + } else { + JavaThread* const jt = JavaThread::cast(t); + assert(jt->thread_state() == _thread_in_vm, "invariant"); + if (tl->should_write()) { + JfrCheckpointManager::write_checkpoint(t); + } + send_java_thread_end_event(jt, JfrThreadLocal::jvm_thread_id(jt)); + JfrCPUTimeThreadSampling::on_javathread_terminate(jt); + JfrThreadCPULoadEvent::send_event_for_thread(jt); + } } release(tl, Thread::current()); // because it could be that Thread::current() != t } @@ -425,6 +448,15 @@ u2 JfrThreadLocal::vthread_epoch(const JavaThread* jt) { return Atomic::load(&jt->jfr_thread_local()->_vthread_epoch); } +bool JfrThreadLocal::should_write() const { + const u2 current_generation = JfrTraceIdEpoch::epoch_generation(); + if (Atomic::load(&_generation) != current_generation) { + Atomic::store(&_generation, current_generation); + return true; + } + return false; +} + traceid JfrThreadLocal::thread_id(const Thread* t) { assert(t != nullptr, "invariant"); if (is_impersonating(t)) { diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.hpp b/src/hotspot/share/jfr/support/jfrThreadLocal.hpp index 715a2c44f93..8c82dfad8af 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.hpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.hpp @@ -75,6 +75,7 @@ class JfrThreadLocal { jlong _wallclock_time; int32_t _non_reentrant_nesting; u2 _vthread_epoch; + mutable u2 _generation; bool _vthread_excluded; bool _jvm_thread_excluded; volatile bool _enqueued_requests; @@ -348,6 +349,9 @@ class JfrThreadLocal { return _sampling_critical_section; } + // Serialization state. + bool should_write() const; + static int32_t make_non_reentrant(Thread* thread); static void make_reentrant(Thread* thread, int32_t previous_nesting); diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 539f70c31f9..799f13b5e91 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -2074,9 +2074,15 @@ const Type* ReverseLNode::Value(PhaseGVN* phase) const { return bottom_type(); } -Node* InvolutionNode::Identity(PhaseGVN* phase) { - // Op ( Op x ) => x - if (in(1)->Opcode() == Opcode()) { +Node* ReverseINode::Identity(PhaseGVN* phase) { + if (in(1)->Opcode() == Op_ReverseI) { + return in(1)->in(1); + } + return this; +} + +Node* ReverseLNode::Identity(PhaseGVN* phase) { + if (in(1)->Opcode() == Op_ReverseL) { return in(1)->in(1); } return this; diff --git a/src/hotspot/share/opto/subnode.hpp b/src/hotspot/share/opto/subnode.hpp index 9a411f3d20e..57a501ecbc3 100644 --- a/src/hotspot/share/opto/subnode.hpp +++ b/src/hotspot/share/opto/subnode.hpp @@ -439,18 +439,11 @@ class CmpLTMaskNode : public Node { virtual uint ideal_reg() const { return Op_RegI; } }; -//------------------------------InvolutionNode---------------------------------- -// Represents a self-inverse operation, i.e., op(op(x)) = x for any x -class InvolutionNode : public Node { -public: - InvolutionNode(Node* in) : Node(nullptr, in) {} - virtual Node* Identity(PhaseGVN* phase); -}; //------------------------------NegNode---------------------------------------- -class NegNode : public InvolutionNode { +class NegNode : public Node { public: - NegNode(Node* in1) : InvolutionNode(in1) { + NegNode(Node* in1) : Node(nullptr, in1) { init_class_id(Class_Neg); } }; @@ -562,18 +555,16 @@ class SqrtHFNode : public Node { }; -class ReverseBytesNode : public InvolutionNode { +class ReverseBytesNode : public Node { public: - ReverseBytesNode(Node* in) : InvolutionNode(in) {} + ReverseBytesNode(Node* in) : Node(nullptr, in) {} virtual const Type* Value(PhaseGVN* phase) const; }; //-------------------------------ReverseBytesINode-------------------------------- // reverse bytes of an integer class ReverseBytesINode : public ReverseBytesNode { public: - ReverseBytesINode(Node* in) : ReverseBytesNode(in) { - } - + ReverseBytesINode(Node* in) : ReverseBytesNode(in) {} virtual int Opcode() const; const Type* bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } @@ -611,23 +602,25 @@ class ReverseBytesSNode : public ReverseBytesNode { //-------------------------------ReverseINode-------------------------------- // reverse bits of an int -class ReverseINode : public InvolutionNode { +class ReverseINode : public Node { public: - ReverseINode(Node* in) : InvolutionNode(in) {} + ReverseINode(Node* in) : Node(nullptr,in) {} virtual int Opcode() const; const Type* bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } + virtual Node* Identity(PhaseGVN* phase); virtual const Type* Value(PhaseGVN* phase) const; }; //-------------------------------ReverseLNode-------------------------------- // reverse bits of a long -class ReverseLNode : public InvolutionNode { +class ReverseLNode : public Node { public: - ReverseLNode(Node* in) : InvolutionNode(in) {} + ReverseLNode(Node* in) : Node(nullptr, in) {} virtual int Opcode() const; const Type* bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } + virtual Node* Identity(PhaseGVN* phase); virtual const Type* Value(PhaseGVN* phase) const; }; diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 57f93f87d47..ddb682cbc75 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -737,6 +737,8 @@ void JavaThread::run() { assert(JavaThread::current() == this, "sanity check"); assert(!Thread::current()->owns_locks(), "sanity check"); + JFR_ONLY(Jfr::on_thread_start(this);) + DTRACE_THREAD_PROBE(start, this); // This operation might block. We call that after all safepoint checks for a new thread has diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp index 358434938f2..c1c5087137f 100644 --- a/src/hotspot/share/runtime/stubRoutines.cpp +++ b/src/hotspot/share/runtime/stubRoutines.cpp @@ -231,7 +231,9 @@ static BufferBlob* initialize_stubs(StubGenBlobId blob_id, StubGenerator_generate(&buffer, blob_id); // When new stubs added we need to make sure there is some space left // to catch situation when we should increase size again. - assert(code_size == 0 || buffer.insts_remaining() > 200, "increase %s", assert_msg); + assert(code_size == 0 || buffer.insts_remaining() > 200, + "increase %s, code_size: %d, used: %d, free: %d", + assert_msg, code_size, buffer.total_content_size(), buffer.insts_remaining()); LogTarget(Info, stubs) lt; if (lt.is_enabled()) { @@ -240,6 +242,7 @@ static BufferBlob* initialize_stubs(StubGenBlobId blob_id, buffer_name, p2i(stubs_code->content_begin()), p2i(stubs_code->content_end()), buffer.total_content_size(), buffer.insts_remaining()); } + return stubs_code; } diff --git a/src/java.base/share/classes/java/text/DecimalFormat.java b/src/java.base/share/classes/java/text/DecimalFormat.java index 3aa42ed8601..185d0baad4b 100644 --- a/src/java.base/share/classes/java/text/DecimalFormat.java +++ b/src/java.base/share/classes/java/text/DecimalFormat.java @@ -114,12 +114,6 @@ * pattern} or using one of the appropriate {@code DecimalFormat} setter methods, * for example, {@link #setMinimumFractionDigits(int)}. These limits have no impact * on parsing behavior. - * @implSpec - * When formatting a {@code Number} other than {@code BigInteger} and - * {@code BigDecimal}, {@code 309} is used as the upper limit for integer digits, - * and {@code 340} as the upper limit for fraction digits. This occurs, even if - * one of the {@code DecimalFormat} getter methods, for example, {@link #getMinimumFractionDigits()} - * returns a numerically greater value. * *

Special Values

*
    @@ -417,6 +411,13 @@ *
  • Exponential patterns may not contain grouping separators. *
* + * @implSpec + * When formatting a {@code Number} other than {@code BigInteger} and + * {@code BigDecimal}, {@code 309} is used as the upper limit for integer digits, + * and {@code 340} as the upper limit for fraction digits. This occurs, even if + * one of the {@code DecimalFormat} getter methods, for example, {@link #getMinimumFractionDigits()} + * returns a numerically greater value. + * * @spec https://www.unicode.org/reports/tr35 * Unicode Locale Data Markup Language (LDML) * @see Java Tutorial 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 9126efd4674..654a313f6c9 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 @@ -328,4 +328,4 @@ CatalogException=JAXP00090001: CatalogResolver ist mit dem Katalog "{0}" aktiviert, eine CatalogException wird jedoch zurückgegeben. # 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. + 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/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties index 538b5a6c03b..0787c839cb4 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties @@ -1378,14 +1378,17 @@ compiler.warn.incubating.modules=Inkubatormodul(e) verwendet: {0} # 0: symbol, 1: symbol # lint: deprecation +# flags: aggregate compiler.warn.has.been.deprecated={0} in {1} ist veraltet # 0: symbol, 1: symbol # lint: removal +# flags: aggregate compiler.warn.has.been.deprecated.for.removal={0} in {1} ist veraltet und wurde zum Entfernen markiert # 0: symbol # lint: preview +# flags: aggregate compiler.warn.is.preview={0} ist eine Vorschau-API, die in einem zukünftigen Release entfernt werden kann. # 0: symbol @@ -1393,6 +1396,7 @@ compiler.err.is.preview={0} ist eine Vorschau-API, die standardmäßig deaktivie # 0: symbol # lint: preview +# flags: aggregate compiler.warn.is.preview.reflective={0} ist eine reflektive Vorschau-API, die in einem zukünftigen Release entfernt werden kann. # 0: symbol, 1: symbol @@ -1401,13 +1405,16 @@ compiler.warn.restricted.method={0}.{1} ist eine eingeschränkte Methode.\n(Eing # 0: symbol # lint: deprecation +# flags: aggregate compiler.warn.has.been.deprecated.module=Modul {0} ist veraltet # 0: symbol # lint: removal +# flags: aggregate compiler.warn.has.been.deprecated.for.removal.module=Modul {0} ist veraltet und wurde zum Entfernen markiert # 0: symbol +# flags: strict compiler.warn.sun.proprietary={0} ist eine interne proprietäre API, die in einem zukünftigen Release entfernt werden kann compiler.warn.illegal.char.for.encoding=Nicht zuordenbares Zeichen für Codierung {0} @@ -1704,10 +1711,12 @@ compiler.warn.unchecked.assign=Nicht geprüfte Zuweisung: {0} zu {1} # 0: symbol, 1: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.assign.to.var=Nicht geprüfte Zuweisung zu Variable {0} als Mitglied des Raw-Typs {1} # 0: symbol, 1: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.call.mbr.of.raw.type=Nicht geprüfter Aufruf von {0} als Mitglied des Raw-Typs {1} # lint: unchecked @@ -1715,14 +1724,17 @@ compiler.warn.unchecked.cast.to.type=Nicht geprüftes Casting zu Typ {0} # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol # lint: unchecked +# flags: aggregate compiler.warn.unchecked.meth.invocation.applied=Nicht geprüfter Methodenaufruf: {0} {1} in {4} {5} wird auf die angegebenen Typen angewendet\nErforderlich: {2}\nErmittelt: {3} # 0: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.generic.array.creation=Nicht geprüfte Erstellung eines generischen Arrays für varargs-Parameter des Typs {0} # 0: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.varargs.non.reifiable.type=Möglich Heap-Beschädigung aus parametrisiertem vararg-Typ {0} # 0: symbol @@ -2011,6 +2023,7 @@ compiler.misc.prob.found.req=Inkompatible Typen: {0} # 0: message segment, 1: type, 2: type # lint: unchecked +# flags: aggregate compiler.warn.prob.found.req={0}\nErforderlich: {2}\nErmittelt: {1} # 0: type, 1: type @@ -2284,10 +2297,12 @@ compiler.err.override.incompatible.ret={0}\nRückgabetyp {1} ist nicht mit {2} k # 0: message segment, 1: type, 2: type # lint: unchecked +# flags: aggregate compiler.warn.override.unchecked.ret={0}\nRückgabetyp erfordert eine nicht geprüfte Konvertierung von {1} in {2} # 0: message segment, 1: type # lint: unchecked +# flags: aggregate compiler.warn.override.unchecked.thrown={0}\nAußer Kraft gesetzte Methode löst nicht {1} aus # 0: symbol @@ -2336,9 +2351,11 @@ compiler.misc.inapplicable.method={0} {1}.{2} ist nicht anwendbar\n({3}) ######################################## # 0: message segment (feature), 1: string (found version), 2: string (expected version) +# flags: source-level compiler.err.feature.not.supported.in.source={0} wird in -source {1} nicht unterstützt\n(Verwenden Sie -source {2} oder höher, um {0} zu aktivieren) # 0: message segment (feature), 1: string (found version), 2: string (expected version) +# flags: source-level compiler.err.feature.not.supported.in.source.plural={0} werden in -source {1} nicht unterstützt\n(Verwenden Sie -source {2} oder höher, um {0} zu aktivieren) # 0: message segment (feature), 1: string (found version), 2: string (expected version) @@ -2348,9 +2365,11 @@ compiler.misc.feature.not.supported.in.source={0} wird in -source {1} nicht unte compiler.misc.feature.not.supported.in.source.plural={0} werden in -source {1} nicht unterstützt\n(Verwenden Sie -source {2} oder höher, um {0} zu aktivieren) # 0: message segment (feature) +# flags: source-level compiler.err.preview.feature.disabled={0} ist ein Vorschaufeature, das standardmäßig deaktiviert ist.\n(Verwenden Sie --enable-preview, um {0} zu aktivieren) # 0: message segment (feature) +# flags: source-level compiler.err.preview.feature.disabled.plural={0} sind ein Vorschaufeature, das standardmäßig deaktiviert ist.\n(Verwenden Sie --enable-preview, um {0} zu aktivieren) # 0: file object (classfile), 1: string (expected version) @@ -2358,10 +2377,12 @@ compiler.err.preview.feature.disabled.classfile=Klassendatei für {0} verwendet # 0: message segment (feature) # lint: preview +# flags: aggregate compiler.warn.preview.feature.use={0} ist ein Vorschaufeature, das in einem zukünftigen Release entfernt werden kann. # 0: message segment (feature) # lint: preview +# flags: aggregate compiler.warn.preview.feature.use.plural={0} sind ein Vorschaufeature, das in einem zukünftigen Release entfernt werden kann. # 0: file object (classfile), 1: string (expected version) @@ -3039,6 +3060,7 @@ compiler.err.incorrect.number.of.nested.patterns=Falsche Anzahl verschachtelter # 0: kind name, 1: symbol # lint: preview +# flags: aggregate compiler.warn.declared.using.preview={0} {1} ist mit einem Vorschaufeature deklariert, das in einem zukünftigen Release entfernt werden kann. # lint: identity diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties index aa501fd6c11..291d8aeeec5 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties @@ -1378,14 +1378,17 @@ compiler.warn.incubating.modules=実験的なモジュールを使用してい # 0: symbol, 1: symbol # lint: deprecation +# flags: aggregate compiler.warn.has.been.deprecated={1}の{0}は推奨されません # 0: symbol, 1: symbol # lint: removal +# flags: aggregate compiler.warn.has.been.deprecated.for.removal={1}の{0}は推奨されておらず、削除用にマークされています # 0: symbol # lint: preview +# flags: aggregate compiler.warn.is.preview={0}はプレビューAPIであり、今後のリリースで削除される可能性があります。 # 0: symbol @@ -1393,6 +1396,7 @@ compiler.err.is.preview={0}はプレビューAPIであり、デフォルトで # 0: symbol # lint: preview +# flags: aggregate compiler.warn.is.preview.reflective={0}はリフレクティブ・プレビューAPIであり、今後のリリースで削除される可能性があります。 # 0: symbol, 1: symbol @@ -1401,13 +1405,16 @@ compiler.warn.restricted.method={0}.{1}は制限されたメソッドです。\n # 0: symbol # lint: deprecation +# flags: aggregate compiler.warn.has.been.deprecated.module=モジュール{0}は推奨されません # 0: symbol # lint: removal +# flags: aggregate compiler.warn.has.been.deprecated.for.removal.module=モジュール{0}は推奨されておらず、削除用にマークされています # 0: symbol +# flags: strict compiler.warn.sun.proprietary={0}は内部所有のAPIであり、今後のリリースで削除される可能性があります compiler.warn.illegal.char.for.encoding=この文字は、エンコーディング{0}にマップできません @@ -1704,10 +1711,12 @@ compiler.warn.unchecked.assign={0}から{1}への無検査代入です # 0: symbol, 1: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.assign.to.var=raw型{1}のメンバーとして変数{0}への無検査代入です # 0: symbol, 1: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.call.mbr.of.raw.type=raw型{1}のメンバーとしての{0}への無検査呼出しです # lint: unchecked @@ -1715,14 +1724,17 @@ compiler.warn.unchecked.cast.to.type=型{0}への無検査キャストです # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol # lint: unchecked +# flags: aggregate compiler.warn.unchecked.meth.invocation.applied=無検査メソッド呼出し: {4} {5}の{0} {1}は指定された型に適用されます\n期待値: {2}\n検出値: {3} # 0: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.generic.array.creation=型{0}の可変引数パラメータに対する総称型配列の無検査作成です # 0: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.varargs.non.reifiable.type=パラメータ化された可変引数型{0}からのヒープ汚染の可能性があります # 0: symbol @@ -2011,6 +2023,7 @@ compiler.misc.prob.found.req=不適合な型: {0} # 0: message segment, 1: type, 2: type # lint: unchecked +# flags: aggregate compiler.warn.prob.found.req={0}\n期待値: {2}\n検出値: {1} # 0: type, 1: type @@ -2284,10 +2297,12 @@ compiler.err.override.incompatible.ret={0}\n戻り値の型{1}は{2}と互換性 # 0: message segment, 1: type, 2: type # lint: unchecked +# flags: aggregate compiler.warn.override.unchecked.ret={0}\n戻り値の型は{1}から{2}への無検査変換が必要です # 0: message segment, 1: type # lint: unchecked +# flags: aggregate compiler.warn.override.unchecked.thrown={0}\nオーバーライドされたメソッドは{1}をスローしません # 0: symbol @@ -2336,9 +2351,11 @@ compiler.misc.inapplicable.method={0} {1}.{2}は使用できません\n({3}) ######################################## # 0: message segment (feature), 1: string (found version), 2: string (expected version) +# flags: source-level compiler.err.feature.not.supported.in.source={0}は-source {1}でサポートされていません\n({0}を有効にするには-source {2}以上を使用してください) # 0: message segment (feature), 1: string (found version), 2: string (expected version) +# flags: source-level compiler.err.feature.not.supported.in.source.plural={0}は-source {1}でサポートされていません\n({0}を有効にするには-source {2}以上を使用してください) # 0: message segment (feature), 1: string (found version), 2: string (expected version) @@ -2348,9 +2365,11 @@ compiler.misc.feature.not.supported.in.source={0}は-source {1}でサポート compiler.misc.feature.not.supported.in.source.plural={0}は-source {1}でサポートされていません\n({0}を有効にするには-source {2}以上を使用してください) # 0: message segment (feature) +# flags: source-level compiler.err.preview.feature.disabled={0}はプレビュー機能であり、デフォルトで無効になっています。\n({0}を有効にするには--enable-previewを使用します) # 0: message segment (feature) +# flags: source-level compiler.err.preview.feature.disabled.plural={0}はプレビュー機能であり、デフォルトで無効になっています。\n({0}を有効にするには--enable-previewを使用します) # 0: file object (classfile), 1: string (expected version) @@ -2358,10 +2377,12 @@ compiler.err.preview.feature.disabled.classfile={0}のクラス・ファイル # 0: message segment (feature) # lint: preview +# flags: aggregate compiler.warn.preview.feature.use={0}はプレビュー機能であり、今後のリリースで削除される可能性があります。 # 0: message segment (feature) # lint: preview +# flags: aggregate compiler.warn.preview.feature.use.plural={0}はプレビュー機能であり、今後のリリースで削除される可能性があります。 # 0: file object (classfile), 1: string (expected version) @@ -3039,6 +3060,7 @@ compiler.err.incorrect.number.of.nested.patterns=ネスト・パターンの数 # 0: kind name, 1: symbol # lint: preview +# flags: aggregate compiler.warn.declared.using.preview={0} {1}はプレビュー機能を使用して宣言されており、今後のリリースで削除される可能性があります。 # lint: identity diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties index d25110f6532..268ce26bd49 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties @@ -1378,14 +1378,17 @@ compiler.warn.incubating.modules=使用 incubating 模块: {0} # 0: symbol, 1: symbol # lint: deprecation +# flags: aggregate compiler.warn.has.been.deprecated={1}中的{0}已过时 # 0: symbol, 1: symbol # lint: removal +# flags: aggregate compiler.warn.has.been.deprecated.for.removal={1} 中的 {0} 已过时, 且标记为待删除 # 0: symbol # lint: preview +# flags: aggregate compiler.warn.is.preview={0} 是预览 API,可能会在未来发行版中删除。 # 0: symbol @@ -1393,6 +1396,7 @@ compiler.err.is.preview={0} 是预览 API,默认情况下处于禁用状态。 # 0: symbol # lint: preview +# flags: aggregate compiler.warn.is.preview.reflective={0} 是反射预览 API,可能会在未来发行版中删除。 # 0: symbol, 1: symbol @@ -1401,13 +1405,16 @@ compiler.warn.restricted.method={0}.{1} 是受限制的方法。\n(受限制 # 0: symbol # lint: deprecation +# flags: aggregate compiler.warn.has.been.deprecated.module=模块 {0} 已过时 # 0: symbol # lint: removal +# flags: aggregate compiler.warn.has.been.deprecated.for.removal.module=模块 {0} 已过时, 且标记为待删除 # 0: symbol +# flags: strict compiler.warn.sun.proprietary={0}是内部专用 API, 可能会在未来发行版中删除 compiler.warn.illegal.char.for.encoding=编码{0}的不可映射字符 @@ -1704,10 +1711,12 @@ compiler.warn.unchecked.assign=未经检查的分配: 将{0}分配给{1} # 0: symbol, 1: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.assign.to.var=对作为原始类型{1}的成员的变量{0}的分配未经过检查 # 0: symbol, 1: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.call.mbr.of.raw.type=对作为原始类型{1}的成员的{0}的调用未经过检查 # lint: unchecked @@ -1715,14 +1724,17 @@ compiler.warn.unchecked.cast.to.type=向类型{0}的转换未经过检查 # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol # lint: unchecked +# flags: aggregate compiler.warn.unchecked.meth.invocation.applied=方法调用未经过检查: 将{4} {5}中的{0} {1}应用到给定的类型\n需要: {2}\n找到: {3} # 0: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.generic.array.creation=对于类型为{0}的 varargs 参数, 泛型数组创建未经过检查 # 0: type # lint: unchecked +# flags: aggregate compiler.warn.unchecked.varargs.non.reifiable.type=参数化 vararg 类型{0}的堆可能已受污染 # 0: symbol @@ -2011,6 +2023,7 @@ compiler.misc.prob.found.req=不兼容的类型: {0} # 0: message segment, 1: type, 2: type # lint: unchecked +# flags: aggregate compiler.warn.prob.found.req={0}\n需要: {2}\n找到: {1} # 0: type, 1: type @@ -2284,10 +2297,12 @@ compiler.err.override.incompatible.ret={0}\n返回类型{1}与{2}不兼容 # 0: message segment, 1: type, 2: type # lint: unchecked +# flags: aggregate compiler.warn.override.unchecked.ret={0}\n返回类型需要从{1}到{2}的未经检查的转换 # 0: message segment, 1: type # lint: unchecked +# flags: aggregate compiler.warn.override.unchecked.thrown={0}\n被覆盖的方法未抛出{1} # 0: symbol @@ -2336,9 +2351,11 @@ compiler.misc.inapplicable.method={0} {1}.{2}不适用\n({3}) ######################################## # 0: message segment (feature), 1: string (found version), 2: string (expected version) +# flags: source-level compiler.err.feature.not.supported.in.source=-source {1} 中不支持 {0}\n(请使用 -source {2} 或更高版本以启用 {0}) # 0: message segment (feature), 1: string (found version), 2: string (expected version) +# flags: source-level compiler.err.feature.not.supported.in.source.plural=-source {1} 中不支持 {0}\n(请使用 -source {2} 或更高版本以启用 {0}) # 0: message segment (feature), 1: string (found version), 2: string (expected version) @@ -2348,9 +2365,11 @@ compiler.misc.feature.not.supported.in.source=-source {1} 中不支持 {0}\n(请 compiler.misc.feature.not.supported.in.source.plural=-source {1} 中不支持 {0}\n(请使用 -source {2} 或更高版本以启用 {0}) # 0: message segment (feature) +# flags: source-level compiler.err.preview.feature.disabled={0} 是预览功能,默认情况下禁用。\n(请使用 --enable-preview 以启用 {0}) # 0: message segment (feature) +# flags: source-level compiler.err.preview.feature.disabled.plural={0} 是预览功能,默认情况下禁用。\n(请使用 --enable-preview 以启用 {0}) # 0: file object (classfile), 1: string (expected version) @@ -2358,10 +2377,12 @@ compiler.err.preview.feature.disabled.classfile={0} 的类文件使用 Java SE { # 0: message segment (feature) # lint: preview +# flags: aggregate compiler.warn.preview.feature.use={0} 是预览功能,可能会在未来发行版中删除。 # 0: message segment (feature) # lint: preview +# flags: aggregate compiler.warn.preview.feature.use.plural={0} 是预览功能,可能会在未来发行版中删除。 # 0: file object (classfile), 1: string (expected version) @@ -3039,6 +3060,7 @@ compiler.err.incorrect.number.of.nested.patterns=嵌套模式数不正确\n需 # 0: kind name, 1: symbol # lint: preview +# flags: aggregate compiler.warn.declared.using.preview={0} {1} 是使用预览功能声明的,可能会在未来发行版中删除。 # lint: identity diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties index 18a43abe14a..1a00fad1dd0 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties @@ -175,11 +175,8 @@ javac.opt.Xlint.desc.preview=Warnt vor Verwendung von Vorschausprachfeatures. javac.opt.Xlint.desc.restricted=Warnt vor der Verwendung eingeschränkter Methoden. -javac.opt.Xlint.desc.synchronization=\ - Warnt vor Synchronisierungsversuchen mit Instanzen wertbasierter Klassen.\n\ -\ Dieser Schlüssel ist ein veralteter Alias für die Kategorie ''identity'', die dieselben Verwendungen und\n\ -\ Effekte hat. Benutzern wird empfohlen, die Kategorie ''identity'' für alle zukünftigen\n\ -\ und vorhandenen Verwendungen von ''synchronization'' zu verwenden. +# L10N: do not localize: identity synchronization +javac.opt.Xlint.desc.synchronization=Warnt vor Synchronisierungsversuchen mit Instanzen wertbasierter Klassen.\n Dieser Schlüssel ist ein veralteter Alias für die Kategorie "identity", die dieselben Verwendungen und\n Effekte hat. Benutzern wird empfohlen, die Kategorie "identity" für alle zukünftigen\n und vorhandenen Verwendungen von "synchronization" zu verwenden. javac.opt.Xlint.desc.identity=Warnt vor Verwendungen wertbasierter Klassen, wenn eine Identitätsklasse erwartet wird. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties index 66e2e3dce39..3b967d368ae 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties @@ -175,6 +175,7 @@ javac.opt.Xlint.desc.preview=プレビュー言語機能の使用について警 javac.opt.Xlint.desc.restricted=制限されたメソッドの使用について警告します。 +# L10N: do not localize: identity synchronization javac.opt.Xlint.desc.synchronization=値ベース・クラスのインスタンスでの同期の試行について警告します。\n このキーは、''identity''の非推奨のエイリアスであり、同じ使用方法と効果を\n 持ちます。ユーザーには、今後および既存の''synchronization''の使用に対して''identity''カテゴリを\n 使用することをお薦めします。 javac.opt.Xlint.desc.identity=アイデンティティ・クラスが必要な場所での値ベース・クラスの使用について警告します。 diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties index efc6e73494e..a24b5511c9c 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties @@ -175,6 +175,7 @@ javac.opt.Xlint.desc.preview=有关使用预览语言功能的警告。 javac.opt.Xlint.desc.restricted=有关使用受限制方法的警告。 +# L10N: do not localize: identity synchronization javac.opt.Xlint.desc.synchronization=有关尝试在基于值的类的实例上同步的警告。\n 此密钥是 ''identity'' 的已过时别名,具有相同的用法和\n 效果。建议用户在 ''synchronization'' 的所有未来和现有\n 用法中使用 ''identity'' 类别。 javac.opt.Xlint.desc.identity=有关在需要身份类的情况下使用基于值的类的警告。 diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties index 7f12decb225..1edda5da22f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties @@ -100,7 +100,7 @@ launcher.err.main.not.void=Methode "main" ist nicht mit Rückgabetyp "void" dekl launcher.err.cant.find.class=Klasse nicht gefunden: {0} # 0: string -launcher.err.cant.find.main.method=Konnte keine main(String[])- oder main()-Methode in der Klasse: {0} finden. +launcher.err.cant.find.main.method=main(String[])- oder main()-Methode nicht gefunden in Klasse: {0} # 0: string launcher.err.cant.instantiate=Abstrakte Klasse: {0} kann nicht instanziiert werden diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties index 1221ae747de..2426b97c7e2 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties @@ -86,7 +86,6 @@ MSG_BundlerFailed=Fehler: Bundler "{1}" ({0}) konnte kein Package generieren MSG_BundlerConfigException=Bundler {0} aufgrund eines Konfigurationsproblems übersprungen: {1} \nEmpfehlung zur Behebung: {2} MSG_BundlerConfigExceptionNoAdvice=Bundler {0} aufgrund eines Konfigurationsproblems übersprungen: {1} MSG_BundlerRuntimeException=Bundler {0} nicht erfolgreich. Grund: {1} -MSG_BundlerFailed=Fehler: Bundler "{1}" ({0}) konnte kein Package generieren ERR_NoMainClass=Fehler: Hauptanwendungsklasse fehlt ERR_UnsupportedOption=Fehler: Option [{0}] ist auf dieser Plattform ungültig diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties index 5a04af8a7bc..e0faf346973 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties @@ -86,7 +86,6 @@ MSG_BundlerFailed=エラー: バンドラ"{1}" ({0})がパッケージの生成 MSG_BundlerConfigException=構成の問題のため、バンドラ{0}がスキップされました: {1} \n次の修正を行ってください: {2} MSG_BundlerConfigExceptionNoAdvice=構成の問題のため、バンドラ{0}がスキップされました: {1} MSG_BundlerRuntimeException={1}のため、バンドラ{0}が失敗しました -MSG_BundlerFailed=エラー: バンドラ"{1}" ({0})がパッケージの生成に失敗しました ERR_NoMainClass=エラー: メイン・アプリケーション・クラスがありません ERR_UnsupportedOption=エラー: オプション[{0}]は、このプラットフォームでは無効です diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties index 5546abef09f..0236ef34077 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties @@ -86,7 +86,6 @@ MSG_BundlerFailed=错误:打包程序 "{1}" ({0}) 无法生成程序包 MSG_BundlerConfigException=由于配置问题, 跳过了打包程序{0}: {1} \n修复建议: {2} MSG_BundlerConfigExceptionNoAdvice=由于配置问题, 跳过了打包程序{0}: {1} MSG_BundlerRuntimeException=由于{1}, 打包程序{0}失败 -MSG_BundlerFailed=错误:打包程序 "{1}" ({0}) 无法生成程序包 ERR_NoMainClass=错误:缺少主应用程序类 ERR_UnsupportedOption=错误:选项 [{0}] 在此平台上无效 diff --git a/test/hotspot/jtreg/compiler/c2/irTests/InvolutionIdentityTests.java b/test/hotspot/jtreg/compiler/c2/irTests/InvolutionIdentityTests.java deleted file mode 100644 index e1945c8a519..00000000000 --- a/test/hotspot/jtreg/compiler/c2/irTests/InvolutionIdentityTests.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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 compiler.c2.irTests; - -import compiler.lib.generators.Generator; -import compiler.lib.generators.Generators; -import compiler.lib.generators.RestrictableGenerator; -import compiler.lib.ir_framework.DontCompile; -import compiler.lib.ir_framework.IR; -import compiler.lib.ir_framework.IRNode; -import compiler.lib.ir_framework.Run; -import compiler.lib.ir_framework.Test; -import compiler.lib.ir_framework.TestFramework; -import jdk.test.lib.Asserts; - -/* - * @test - * @bug 8350988 - * @summary Test that Identity simplifications of Involution nodes are being performed as expected. - * @library /test/lib / - * @run driver compiler.c2.irTests.InvolutionIdentityTests - */ -public class InvolutionIdentityTests { - - public static final RestrictableGenerator GEN_CHAR = Generators.G.safeRestrict(Generators.G.ints(), Character.MIN_VALUE, Character.MAX_VALUE); - public static final RestrictableGenerator GEN_SHORT = Generators.G.safeRestrict(Generators.G.ints(), Short.MIN_VALUE, Short.MAX_VALUE); - public static final RestrictableGenerator GEN_LONG = Generators.G.longs(); - public static final RestrictableGenerator GEN_INT = Generators.G.ints(); - public static final Generator GEN_FLOAT = Generators.G.floats(); - public static final Generator GEN_DOUBLE = Generators.G.doubles(); - - public static void main(String[] args) { - TestFramework.run(); - } - - @Run(test = { - "testI1", "testI2", - "testL1", "testL2", - "testS1", - "testUS1", - "testF1", - "testD1" - }) - public void runMethod() { - int ai = GEN_INT.next(); - - int mini = Integer.MIN_VALUE; - int maxi = Integer.MAX_VALUE; - - assertResultI(0); - assertResultI(ai); - assertResultI(mini); - assertResultI(maxi); - - long al = GEN_LONG.next(); - - long minl = Long.MIN_VALUE; - long maxl = Long.MAX_VALUE; - - assertResultL(0); - assertResultL(al); - assertResultL(minl); - assertResultL(maxl); - - short as = GEN_SHORT.next().shortValue(); - - short mins = Short.MIN_VALUE; - short maxs = Short.MAX_VALUE; - - assertResultS((short) 0); - assertResultS(as); - assertResultS(mins); - assertResultS(maxs); - - char ac = (char) GEN_CHAR.next().intValue(); - - char minc = Character.MIN_VALUE; - char maxc = Character.MAX_VALUE; - - assertResultUS((char) 0); - assertResultUS(ac); - assertResultUS(minc); - assertResultUS(maxc); - - float af = GEN_FLOAT.next(); - float inf = Float.POSITIVE_INFINITY; - float nanf = Float.NaN; - - assertResultF(0f); - assertResultF(-0f); - assertResultF(af); - assertResultF(inf); - assertResultF(nanf); - - double ad = GEN_DOUBLE.next(); - double ind = Double.POSITIVE_INFINITY; - double nand = Double.NaN; - - assertResultD(0d); - assertResultD(-0d); - assertResultD(ad); - assertResultD(ind); - assertResultD(nand); - - } - - @DontCompile - public void assertResultI(int a) { - Asserts.assertEQ(Integer.reverseBytes(Integer.reverseBytes(a)), testI1(a)); - Asserts.assertEQ(Integer.reverse(Integer.reverse(a)) , testI2(a)); - } - - @DontCompile - public void assertResultL(long a) { - Asserts.assertEQ(Long.reverseBytes(Long.reverseBytes(a)), testL1(a)); - Asserts.assertEQ(Long.reverse(Long.reverse(a)) , testL2(a)); - } - - @DontCompile - public void assertResultS(short a) { - Asserts.assertEQ(Short.reverseBytes(Short.reverseBytes(a)), testS1(a)); - } - - @DontCompile - public void assertResultUS(char a) { - Asserts.assertEQ(Character.reverseBytes(Character.reverseBytes(a)), testUS1(a)); - } - - @DontCompile - public void assertResultF(float a) { - Asserts.assertEQ(Float.floatToRawIntBits(-(-a)), Float.floatToRawIntBits(testF1(a))); - } - - @DontCompile - public void assertResultD(double a) { - Asserts.assertEQ(Double.doubleToRawLongBits(-(-a)), Double.doubleToRawLongBits(testD1(a))); - } - - @Test - @IR(failOn = {IRNode.REVERSE_BYTES_I}) - public int testI1(int x) { - return Integer.reverseBytes(Integer.reverseBytes(x)); - } - - @Test - @IR(failOn = {IRNode.REVERSE_I}) - public int testI2(int x) { - return Integer.reverse(Integer.reverse(x)); - } - - @Test - @IR(failOn = {IRNode.REVERSE_BYTES_L}) - public long testL1(long x) { - return Long.reverseBytes(Long.reverseBytes(x)); - } - - @Test - @IR(failOn = {IRNode.REVERSE_L}) - public long testL2(long x) { - return Long.reverse(Long.reverse(x)); - } - - @Test - @IR(failOn = {IRNode.REVERSE_BYTES_S}) - public short testS1(short x) { - return Short.reverseBytes(Short.reverseBytes(x)); - } - - @Test - @IR(failOn = {IRNode.REVERSE_BYTES_US}) - public char testUS1(char x) { - return Character.reverseBytes(Character.reverseBytes(x)); - } - - @Test - @IR(failOn = {IRNode.NEG_F}) - public float testF1(float x) { - return -(-x); - } - - @Test - @IR(failOn = {IRNode.NEG_D}) - public double testD1(double x) { - return -(-x); - } -} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 96b62a2b12a..f53bb45bd43 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1469,16 +1469,6 @@ public class IRNode { superWordNodes(MAX_REDUCTION_V, "MaxReductionV"); } - public static final String NEG_F = PREFIX + "NEG_F" + POSTFIX; - static { - beforeMatchingNameRegex(NEG_F, "NegF"); - } - - public static final String NEG_D = PREFIX + "NEG_D" + POSTFIX; - static { - beforeMatchingNameRegex(NEG_D, "NegD"); - } - public static final String NEG_VF = VECTOR_PREFIX + "NEG_VF" + POSTFIX; static { vectorNode(NEG_VF, "NegVF", TYPE_FLOAT); diff --git a/test/jdk/sun/security/tools/keytool/i18n.java b/test/jdk/sun/security/tools/keytool/i18n.java index 4ba8c7830b7..6eac0239eee 100644 --- a/test/jdk/sun/security/tools/keytool/i18n.java +++ b/test/jdk/sun/security/tools/keytool/i18n.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4348369 8076069 8294994 + * @bug 4348369 8076069 8294994 8360400 * @summary keytool i18n compliant * @author charlie lai * @modules java.base/sun.security.tools.keytool @@ -33,7 +33,7 @@ /* * @test - * @bug 4348369 8076069 8294994 + * @bug 4348369 8076069 8294994 8360400 * @summary keytool i18n compliant * @author charlie lai * @modules java.base/sun.security.tools.keytool @@ -43,7 +43,7 @@ /* * @test - * @bug 4348369 8076069 8294994 + * @bug 4348369 8076069 8294994 8360400 * @summary keytool i18n compliant * @author charlie lai * @modules java.base/sun.security.tools.keytool @@ -53,7 +53,7 @@ /* * @test - * @bug 4348369 8076069 8294994 + * @bug 4348369 8076069 8294994 8360400 * @summary keytool i18n compliant * @author charlie lai * @modules java.base/sun.security.tools.keytool @@ -95,10 +95,6 @@ public class i18n { + "512-bit DSA key algorithm for CN=Name, OU=Java, " + "O=Oracle, L=City, ST=State C=Country."}, - {"-list -v -storepass a -keystore ./i18n.keystore", - "Output in ${LANG}. Check keytool error:java.io.IOException: " - + "keystore password was incorrect."}, - {"-genkey -keyalg DSA -v -keysize 512 " + "-storepass password " + "-keypass password "