Merge branch 'openjdk:master' into master

This commit is contained in:
Harshit470250 2026-02-24 12:36:11 +05:30 committed by GitHub
commit 5d09ffa9fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
382 changed files with 23702 additions and 24304 deletions

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2026, 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
@ -311,6 +311,12 @@ AC_DEFUN([PLATFORM_EXTRACT_TARGET_AND_BUILD],
else
OPENJDK_BUILD_OS_ENV="$VAR_OS"
fi
# Special handling for MSYS2 that reports a Cygwin triplet as the default host triplet.
case `uname` in
MSYS*)
OPENJDK_BUILD_OS_ENV=windows.msys2
;;
esac
OPENJDK_BUILD_CPU="$VAR_CPU"
OPENJDK_BUILD_CPU_ARCH="$VAR_CPU_ARCH"
OPENJDK_BUILD_CPU_BITS="$VAR_CPU_BITS"

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2014, 2026, 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
@ -172,6 +172,10 @@ ifeq ($(USE_EXTERNAL_LIBZ), true)
LEGAL_EXCLUDES += zlib.md
endif
ifneq ($(TOOLCHAIN_TYPE), gcc)
LEGAL_EXCLUDES += gcc.md
endif
$(eval $(call SetupCopyLegalFiles, COPY_LEGAL, \
EXCLUDES := $(LEGAL_EXCLUDES), \
))

View File

@ -96,10 +96,6 @@ static inline Address aaddress(Register r) {
return iaddress(r);
}
static inline Address at_rsp() {
return Address(esp, 0);
}
// At top of Java expression stack which may be different than esp(). It
// isn't for category 1 objects.
static inline Address at_tos () {

View File

@ -600,19 +600,21 @@ void C2_MacroAssembler::count_positives(Register src, Register cnt, Register res
orr(tmp0, tmp2, tmp0);
and_(tmp0, tmp0, tmp1);
bne(CR0, Lslow); // Found negative byte.
bne(CR0, Lslow); // Found negative byte.
addi(result, result, 16);
bdnz(Lfastloop);
bind(Lslow); // Fallback to slow version.
subf(tmp0, src, result); // Bytes known positive.
subf_(tmp0, tmp0, cnt); // Remaining Bytes.
clrldi(tmp1, cnt, 32); // Clear garbage from upper 32 bits.
subf_(tmp0, tmp0, tmp1); // Remaining Bytes.
beq(CR0, Ldone);
mtctr(tmp0);
bind(Lloop);
lbz(tmp0, 0, result);
andi_(tmp0, tmp0, 0x80);
bne(CR0, Ldone); // Found negative byte.
bne(CR0, Ldone); // Found negative byte.
addi(result, result, 1);
bdnz(Lloop);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2018 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -44,7 +44,7 @@ define_pd_global(intx, CompileThreshold, 10000);
define_pd_global(intx, OnStackReplacePercentage, 140);
define_pd_global(intx, ConditionalMoveLimit, 4);
define_pd_global(intx, FreqInlineSize, 175);
define_pd_global(intx, FreqInlineSize, 325);
define_pd_global(intx, InteriorEntryAlignment, 4);
define_pd_global(size_t, NewSizeThreadIncrease, ScaleForWordSize(4*K));
define_pd_global(intx, RegisterCostAreaRatio, 12000);

View File

@ -26,6 +26,8 @@
#ifndef CPU_ZERO_BYTECODEINTERPRETER_ZERO_INLINE_HPP
#define CPU_ZERO_BYTECODEINTERPRETER_ZERO_INLINE_HPP
#include "sanitizers/ub.hpp"
// Inline interpreter functions for zero
inline jfloat BytecodeInterpreter::VMfloatAdd(jfloat op1, jfloat op2) {
@ -40,6 +42,7 @@ inline jfloat BytecodeInterpreter::VMfloatMul(jfloat op1, jfloat op2) {
return op1 * op2;
}
ATTRIBUTE_NO_UBSAN // IEEE-754 division by zero is well-defined
inline jfloat BytecodeInterpreter::VMfloatDiv(jfloat op1, jfloat op2) {
return op1 / op2;
}
@ -68,7 +71,7 @@ inline void BytecodeInterpreter::VMmemCopy64(uint32_t to[2],
}
inline jlong BytecodeInterpreter::VMlongAdd(jlong op1, jlong op2) {
return op1 + op2;
return java_add(op1, op2);
}
inline jlong BytecodeInterpreter::VMlongAnd(jlong op1, jlong op2) {
@ -82,7 +85,7 @@ inline jlong BytecodeInterpreter::VMlongDiv(jlong op1, jlong op2) {
}
inline jlong BytecodeInterpreter::VMlongMul(jlong op1, jlong op2) {
return op1 * op2;
return java_multiply(op1, op2);
}
inline jlong BytecodeInterpreter::VMlongOr(jlong op1, jlong op2) {
@ -90,7 +93,7 @@ inline jlong BytecodeInterpreter::VMlongOr(jlong op1, jlong op2) {
}
inline jlong BytecodeInterpreter::VMlongSub(jlong op1, jlong op2) {
return op1 - op2;
return java_subtract(op1, op2);
}
inline jlong BytecodeInterpreter::VMlongXor(jlong op1, jlong op2) {
@ -104,19 +107,19 @@ inline jlong BytecodeInterpreter::VMlongRem(jlong op1, jlong op2) {
}
inline jlong BytecodeInterpreter::VMlongUshr(jlong op1, jint op2) {
return ((unsigned long long) op1) >> (op2 & 0x3F);
return java_shift_right_unsigned(op1, op2);
}
inline jlong BytecodeInterpreter::VMlongShr(jlong op1, jint op2) {
return op1 >> (op2 & 0x3F);
return java_shift_right(op1, op2);
}
inline jlong BytecodeInterpreter::VMlongShl(jlong op1, jint op2) {
return op1 << (op2 & 0x3F);
return java_shift_left(op1, op2);
}
inline jlong BytecodeInterpreter::VMlongNeg(jlong op) {
return -op;
return java_negate(op);
}
inline jlong BytecodeInterpreter::VMlongNot(jlong op) {
@ -183,8 +186,8 @@ inline jdouble BytecodeInterpreter::VMdoubleAdd(jdouble op1, jdouble op2) {
return op1 + op2;
}
ATTRIBUTE_NO_UBSAN // IEEE-754 division by zero is well-defined
inline jdouble BytecodeInterpreter::VMdoubleDiv(jdouble op1, jdouble op2) {
// Divide by zero... QQQ
return op1 / op2;
}
@ -228,7 +231,7 @@ inline jdouble BytecodeInterpreter::VMfloat2Double(jfloat op) {
// Integer Arithmetic
inline jint BytecodeInterpreter::VMintAdd(jint op1, jint op2) {
return op1 + op2;
return java_add(op1, op2);
}
inline jint BytecodeInterpreter::VMintAnd(jint op1, jint op2) {
@ -242,11 +245,11 @@ inline jint BytecodeInterpreter::VMintDiv(jint op1, jint op2) {
}
inline jint BytecodeInterpreter::VMintMul(jint op1, jint op2) {
return op1 * op2;
return java_multiply(op1, op2);
}
inline jint BytecodeInterpreter::VMintNeg(jint op) {
return -op;
return java_negate(op);
}
inline jint BytecodeInterpreter::VMintOr(jint op1, jint op2) {
@ -260,19 +263,19 @@ inline jint BytecodeInterpreter::VMintRem(jint op1, jint op2) {
}
inline jint BytecodeInterpreter::VMintShl(jint op1, jint op2) {
return op1 << (op2 & 0x1F);
return java_shift_left(op1, op2);
}
inline jint BytecodeInterpreter::VMintShr(jint op1, jint op2) {
return op1 >> (op2 & 0x1F);
return java_shift_right(op1, op2);
}
inline jint BytecodeInterpreter::VMintSub(jint op1, jint op2) {
return op1 - op2;
return java_subtract(op1, op2);
}
inline juint BytecodeInterpreter::VMintUshr(jint op1, jint op2) {
return ((juint) op1) >> (op2 & 0x1F);
return java_shift_right_unsigned(op1, op2);
}
inline jint BytecodeInterpreter::VMintXor(jint op1, jint op2) {

View File

@ -368,12 +368,15 @@ int ZeroInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) {
goto unlock_unwind_and_return;
void **arguments;
void *mirror; {
// These locals must remain on stack until call completes
void *mirror;
void *env;
{
arguments =
(void **) stack->alloc(handler->argument_count() * sizeof(void **));
void **dst = arguments;
void *env = thread->jni_environment();
env = thread->jni_environment();
*(dst++) = &env;
if (method->is_static()) {

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2024 SAP SE. All rights reserved.
* Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026 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
@ -61,10 +61,6 @@
product(bool, OptimizePollingPageLocation, true, DIAGNOSTIC, \
"Optimize the location of the polling page used for Safepoints") \
\
/* Use 64K pages for virtual memory (shmat). */ \
product(bool, Use64KPages, true, DIAGNOSTIC, \
"Use 64K pages if available.") \
\
/* Normally AIX commits memory on touch, but sometimes it is helpful to have */ \
/* explicit commit behaviour. This flag, if true, causes the VM to touch */ \
/* memory on os::commit_memory() (which normally is a noop). */ \
@ -79,7 +75,6 @@
//
// UseLargePages means nothing, for now, on AIX.
// Use Use64KPages or Use16MPages instead.
define_pd_global(size_t, PreTouchParallelChunkSize, 1 * G);
define_pd_global(bool, UseLargePages, false);
define_pd_global(bool, UseLargePagesIndividualAllocation, false);

View File

@ -2142,46 +2142,12 @@ void os::init(void) {
// 64k no --- AIX 5.2 ? ---
// 64k yes 64k new systems and standard java loader (we set datapsize=64k when linking)
// We explicitly leave no option to change page size, because only upgrading would work,
// not downgrading (if stack page size is 64k you cannot pretend its 4k).
if (g_multipage_support.datapsize == 4*K) {
// datapsize = 4K. Data segment, thread stacks are 4K paged.
if (g_multipage_support.can_use_64K_pages || g_multipage_support.can_use_64K_mmap_pages) {
// .. but we are able to use 64K pages dynamically.
// This would be typical for java launchers which are not linked
// with datapsize=64K (like, any other launcher but our own).
//
// In this case it would be smart to allocate the java heap with 64K
// to get the performance benefit, and to fake 64k pages for the
// data segment (when dealing with thread stacks).
//
// However, leave a possibility to downgrade to 4K, using
// -XX:-Use64KPages.
if (Use64KPages) {
trcVerbose("64K page mode (faked for data segment)");
set_page_size(64*K);
} else {
trcVerbose("4K page mode (Use64KPages=off)");
set_page_size(4*K);
}
} else {
// .. and not able to allocate 64k pages dynamically. Here, just
// fall back to 4K paged mode and use mmap for everything.
trcVerbose("4K page mode");
set_page_size(4*K);
FLAG_SET_ERGO(Use64KPages, false);
}
} else {
// datapsize = 64k. Data segment, thread stacks are 64k paged.
// This normally means that we can allocate 64k pages dynamically.
// (There is one special case where this may be false: EXTSHM=on.
// but we decided to not support that mode).
assert0(g_multipage_support.can_use_64K_pages || g_multipage_support.can_use_64K_mmap_pages);
set_page_size(64*K);
trcVerbose("64K page mode");
FLAG_SET_ERGO(Use64KPages, true);
}
// datapsize = 64k. Data segment, thread stacks are 64k paged.
// This normally means that we can allocate 64k pages dynamically.
// (There is one special case where this may be false: EXTSHM=on.
// but we decided to not support that mode).
assert0(g_multipage_support.can_use_64K_pages || g_multipage_support.can_use_64K_mmap_pages);
set_page_size(64*K);
// For now UseLargePages is just ignored.
FLAG_SET_ERGO(UseLargePages, false);

View File

@ -906,8 +906,25 @@ FILE* os::fdopen(int fd, const char* mode) {
ssize_t os::pd_write(int fd, const void *buf, size_t nBytes) {
ssize_t res;
#ifdef __APPLE__
// macOS fails for individual write operations > 2GB.
// See https://gitlab.haskell.org/ghc/ghc/-/issues/17414
ssize_t total = 0;
while (nBytes > 0) {
size_t bytes_to_write = MIN2(nBytes, (size_t)INT_MAX);
RESTARTABLE(::write(fd, buf, bytes_to_write), res);
if (res == OS_ERR) {
return OS_ERR;
}
buf = (const char*)buf + res;
nBytes -= res;
total += res;
}
return total;
#else
RESTARTABLE(::write(fd, buf, nBytes), res);
return res;
#endif
}
ssize_t os::read_at(int fd, void *buf, unsigned int nBytes, jlong offset) {

View File

@ -494,6 +494,7 @@ static char* get_user_name(uid_t uid) {
return user_name;
}
#ifndef __APPLE__
// return the name of the user that owns the process identified by vmid.
//
// This method uses a slow directory search algorithm to find the backing
@ -657,6 +658,7 @@ static char* get_user_name(int vmid, int *nspid, TRAPS) {
#endif
return result;
}
#endif
// return the file name of the backing store file for the named
// shared memory region for the given user name and vmid.

View File

@ -36,16 +36,17 @@
class AOTCompressedPointers: public AllStatic {
public:
// For space saving, we can encode the location of metadata objects in the "rw" and "ro"
// regions using a 32-bit offset from the bottom of the mapped AOT metaspace.
// Currently we allow only up to 2GB total size in the rw and ro regions (which are
// contiguous to each other).
// regions using a 32-bit offset from the bottom of the mapped AOT metaspace. Since metadata
// objects are 8-byte aligned, we store scaled offset units (offset_bytes >> 3) to address
// up to ~32GB on 64-bit platforms. We currently limit the MaxMetadataOffsetBytes to about
// 3.5 GB to be compatible with +CompactObjectHeaders.
enum class narrowPtr : u4;
static constexpr size_t MaxMetadataOffsetBytes = 0x7FFFFFFF;
static constexpr size_t MetadataOffsetShift = LP64_ONLY(3) NOT_LP64(0);
static constexpr size_t MaxMetadataOffsetBytes = LP64_ONLY(3584ULL * M) NOT_LP64(0x7FFFFFFF);
// In the future, this could return a different numerical value than
// narrowp if the encoding contains shifts.
// Convert the encoded narrowPtr to a byte offset by applying the shift.
inline static size_t get_byte_offset(narrowPtr narrowp) {
return checked_cast<size_t>(narrowp);
return ((size_t)checked_cast<u4>(narrowp)) << MetadataOffsetShift;
}
inline static narrowPtr null() {
@ -122,7 +123,8 @@ private:
static narrowPtr encode_byte_offset(size_t offset) {
assert(offset != 0, "offset 0 is in protection zone");
precond(offset <= MaxMetadataOffsetBytes);
return checked_cast<narrowPtr>(offset);
assert(is_aligned(offset, (size_t)1 << MetadataOffsetShift), "offset not aligned");
return checked_cast<narrowPtr>(offset >> MetadataOffsetShift);
}
};

View File

@ -321,8 +321,10 @@ void ArchiveBuilder::sort_klasses() {
}
address ArchiveBuilder::reserve_buffer() {
// AOTCodeCache::max_aot_code_size() accounts for aot code region.
size_t buffer_size = LP64_ONLY(CompressedClassSpaceSize) NOT_LP64(256 * M) + AOTCodeCache::max_aot_code_size();
// On 64-bit: reserve address space for archives up to the max encoded offset limit.
// On 32-bit: use 256MB + AOT code size due to limited virtual address space.
size_t buffer_size = LP64_ONLY(AOTCompressedPointers::MaxMetadataOffsetBytes)
NOT_LP64(256 * M + AOTCodeCache::max_aot_code_size());
ReservedSpace rs = MemoryReserver::reserve(buffer_size,
AOTMetaspace::core_region_alignment(),
os::vm_page_size(),

View File

@ -312,22 +312,9 @@ void DumpRegion::pack(DumpRegion* next) {
}
void WriteClosure::do_ptr(void** p) {
// Write ptr into the archive; ptr can be:
// (a) null -> written as 0
// (b) a "buffered" address -> written as is
// (c) a "source" address -> convert to "buffered" and write
// The common case is (c). E.g., when writing the vmClasses into the archive.
// We have (b) only when we don't have a corresponding source object. E.g.,
// the archived c++ vtable entries.
address ptr = *(address*)p;
if (ptr != nullptr && !ArchiveBuilder::current()->is_in_buffer_space(ptr)) {
ptr = ArchiveBuilder::current()->get_buffered_addr(ptr);
}
// null pointers do not need to be converted to offsets
if (ptr != nullptr) {
ptr = (address)ArchiveBuilder::current()->buffer_to_offset(ptr);
}
_dump_region->append_intptr_t((intptr_t)ptr, false);
AOTCompressedPointers::narrowPtr narrowp = AOTCompressedPointers::encode(ptr);
_dump_region->append_intptr_t(checked_cast<intptr_t>(narrowp), false);
}
void ReadClosure::do_ptr(void** p) {

View File

@ -140,7 +140,7 @@ void CppVtableCloner<T>::initialize(const char* name, CppVtableInfo* info) {
// We already checked (and, if necessary, adjusted n) when the vtables were allocated, so we are
// safe to do memcpy.
log_debug(aot, vtables)("Copying %3d vtable entries for %s", n, name);
log_debug(aot, vtables)("Copying %3d vtable entries for %s to " INTPTR_FORMAT, n, name, p2i(dstvtable));
memcpy(dstvtable, srcvtable, sizeof(intptr_t) * n);
}

View File

@ -717,8 +717,8 @@ bool FileMapInfo::init_from_file(int fd) {
}
void FileMapInfo::seek_to_position(size_t pos) {
if (os::lseek(_fd, (long)pos, SEEK_SET) < 0) {
aot_log_error(aot)("Unable to seek to position %zu", pos);
if (os::lseek(_fd, (jlong)pos, SEEK_SET) < 0) {
aot_log_error(aot)("Unable to seek to position %zu (errno=%d: %s)", pos, errno, os::strerror(errno));
AOTMetaspace::unrecoverable_loading_error();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, 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
@ -96,14 +96,16 @@ void CompactHashtableWriter::allocate_table() {
"Too many entries.");
}
_compact_buckets = ArchiveBuilder::new_ro_array<u4>(_num_buckets + 1);
_compact_entries = ArchiveBuilder::new_ro_array<u4>(entries_space);
_num_compact_buckets = checked_cast<size_t>(_num_buckets + 1); // extra slot for TABLEEND_BUCKET_TYPE
_num_compact_entries = checked_cast<size_t>(entries_space);
_compact_buckets = (u4*)ArchiveBuilder::ro_region_alloc(_num_compact_buckets * sizeof(u4));
_compact_entries = (u4*)ArchiveBuilder::ro_region_alloc(_num_compact_entries * sizeof(u4));
_stats->bucket_count = _num_buckets;
_stats->bucket_bytes = align_up(_compact_buckets->size() * BytesPerWord,
_stats->bucket_bytes = align_up(checked_cast<int>(_num_compact_buckets * sizeof(u4)),
SharedSpaceObjectAlignment);
_stats->hashentry_count = _num_entries_written;
_stats->hashentry_bytes = align_up(_compact_entries->size() * BytesPerWord,
_stats->hashentry_bytes = align_up(checked_cast<int>(_num_compact_entries * sizeof(u4)),
SharedSpaceObjectAlignment);
}
@ -114,21 +116,21 @@ void CompactHashtableWriter::dump_table(NumberSeq* summary) {
GrowableArray<Entry>* bucket = _buckets[index];
int bucket_size = bucket->length();
if (bucket_size == 1) {
_compact_buckets->at_put(index, BUCKET_INFO(offset, VALUE_ONLY_BUCKET_TYPE));
compact_buckets_set(index, BUCKET_INFO(offset, VALUE_ONLY_BUCKET_TYPE));
Entry ent = bucket->at(0);
// bucket with one entry is value_only and only has the encoded_value
_compact_entries->at_put(offset++, ent.encoded_value());
compact_entries_set(offset++, ent.encoded_value());
_num_value_only_buckets++;
} else {
// regular bucket, it could contain zero or more than one entry,
// each entry is a <hash, encoded_value> pair
_compact_buckets->at_put(index, BUCKET_INFO(offset, REGULAR_BUCKET_TYPE));
compact_buckets_set(index, BUCKET_INFO(offset, REGULAR_BUCKET_TYPE));
for (int i=0; i<bucket_size; i++) {
Entry ent = bucket->at(i);
_compact_entries->at_put(offset++, u4(ent.hash())); // write entry hash
_compact_entries->at_put(offset++, ent.encoded_value()); // write entry encoded_value
compact_entries_set(offset++, u4(ent.hash())); // write entry hash
compact_entries_set(offset++, ent.encoded_value()); // write entry encoded_value
}
if (bucket_size == 0) {
_num_empty_buckets++;
@ -140,10 +142,19 @@ void CompactHashtableWriter::dump_table(NumberSeq* summary) {
}
// Mark the end of the buckets
_compact_buckets->at_put(_num_buckets, BUCKET_INFO(offset, TABLEEND_BUCKET_TYPE));
assert(offset == (u4)_compact_entries->length(), "sanity");
compact_buckets_set(_num_buckets, BUCKET_INFO(offset, TABLEEND_BUCKET_TYPE));
assert(offset == checked_cast<u4>(_num_compact_entries), "sanity");
}
void CompactHashtableWriter::compact_buckets_set(u4 index, u4 value) {
precond(index < _num_compact_buckets);
_compact_buckets[index] = value;
}
void CompactHashtableWriter::compact_entries_set(u4 index, u4 value) {
precond(index < _num_compact_entries);
_compact_entries[index] = value;
}
// Write the compact table
void CompactHashtableWriter::dump(SimpleCompactHashtable *cht, const char* table_name) {
@ -154,7 +165,7 @@ void CompactHashtableWriter::dump(SimpleCompactHashtable *cht, const char* table
int table_bytes = _stats->bucket_bytes + _stats->hashentry_bytes;
address base_address = address(SharedBaseAddress);
cht->init(base_address, _num_entries_written, _num_buckets,
_compact_buckets->data(), _compact_entries->data());
_compact_buckets, _compact_entries);
LogMessage(aot, hashtables) msg;
if (msg.is_info()) {

View File

@ -115,8 +115,13 @@ private:
int _num_other_buckets;
GrowableArray<Entry>** _buckets;
CompactHashtableStats* _stats;
Array<u4>* _compact_buckets;
Array<u4>* _compact_entries;
u4* _compact_buckets;
size_t _num_compact_buckets;
u4* _compact_entries;
size_t _num_compact_entries;
void compact_buckets_set(u4 index, u4 value);
void compact_entries_set(u4 index, u4 value);
public:
// This is called at dump-time only

View File

@ -257,6 +257,7 @@ class methodHandle;
do_intrinsic(_bitCount_i, java_lang_Integer, bitCount_name, int_int_signature, F_S) \
do_intrinsic(_bitCount_l, java_lang_Long, bitCount_name, long_int_signature, F_S) \
do_intrinsic(_compress_i, java_lang_Integer, compress_name, int2_int_signature, F_S) \
do_name( compress_name, "compress") \
do_intrinsic(_compress_l, java_lang_Long, compress_name, long2_long_signature, F_S) \
do_intrinsic(_expand_i, java_lang_Integer, expand_name, int2_int_signature, F_S) \
do_intrinsic(_expand_l, java_lang_Long, expand_name, long2_long_signature, F_S) \
@ -358,11 +359,11 @@ class methodHandle;
do_name( vectorizedHashCode_name, "vectorizedHashCode") \
do_signature(vectorizedHashCode_signature, "(Ljava/lang/Object;IIII)I") \
\
do_intrinsic(_compressStringC, java_lang_StringUTF16, compress_name, encodeISOArray_signature, F_S) \
do_name( compress_name, "compress") \
do_intrinsic(_compressStringB, java_lang_StringUTF16, compress_name, indexOfI_signature, F_S) \
do_intrinsic(_compressStringC, java_lang_StringUTF16, compressString_name, encodeISOArray_signature, F_S) \
do_name( compressString_name, "compress0") \
do_intrinsic(_compressStringB, java_lang_StringUTF16, compressString_name, indexOfI_signature, F_S) \
do_intrinsic(_inflateStringC, java_lang_StringLatin1, inflate_name, inflateC_signature, F_S) \
do_name( inflate_name, "inflate") \
do_name( inflate_name, "inflate0") \
do_signature(inflateC_signature, "([BI[CII)V") \
do_intrinsic(_inflateStringB, java_lang_StringLatin1, inflate_name, inflateB_signature, F_S) \
do_signature(inflateB_signature, "([BI[BII)V") \
@ -381,9 +382,9 @@ class methodHandle;
do_intrinsic(_compareToLU, java_lang_StringLatin1,compareToLU_name, compareTo_indexOf_signature, F_S) \
do_intrinsic(_compareToUL, java_lang_StringUTF16, compareToUL_name, compareTo_indexOf_signature, F_S) \
do_signature(compareTo_indexOf_signature, "([B[B)I") \
do_name( compareTo_name, "compareTo") \
do_name( compareToLU_name, "compareToUTF16") \
do_name( compareToUL_name, "compareToLatin1") \
do_name( compareTo_name, "compareTo0") \
do_name( compareToLU_name, "compareToUTF16_0") \
do_name( compareToUL_name, "compareToLatin1_0") \
do_intrinsic(_indexOfL, java_lang_StringLatin1,indexOf_name, compareTo_indexOf_signature, F_S) \
do_intrinsic(_indexOfU, java_lang_StringUTF16, indexOf_name, compareTo_indexOf_signature, F_S) \
do_intrinsic(_indexOfUL, java_lang_StringUTF16, indexOfUL_name, compareTo_indexOf_signature, F_S) \
@ -392,12 +393,13 @@ class methodHandle;
do_intrinsic(_indexOfIUL, java_lang_StringUTF16, indexOfUL_name, indexOfI_signature, F_S) \
do_intrinsic(_indexOfU_char, java_lang_StringUTF16, indexOfChar_name, indexOfChar_signature, F_S) \
do_intrinsic(_indexOfL_char, java_lang_StringLatin1,indexOfChar_name, indexOfChar_signature, F_S) \
do_name( indexOf_name, "indexOf") \
do_name( indexOfChar_name, "indexOfChar") \
do_name( indexOfUL_name, "indexOfLatin1") \
do_name( indexOf_name, "indexOf0") \
do_name( indexOfChar_name, "indexOfChar0") \
do_name( indexOfUL_name, "indexOfLatin1_0") \
do_signature(indexOfI_signature, "([BI[BII)I") \
do_signature(indexOfChar_signature, "([BIII)I") \
do_intrinsic(_equalsL, java_lang_StringLatin1,equals_name, equalsB_signature, F_S) \
do_intrinsic(_equalsL, java_lang_StringLatin1,equalsString_name, equalsB_signature, F_S) \
do_name( equalsString_name, "equals0") \
\
do_intrinsic(_isDigit, java_lang_CharacterDataLatin1, isDigit_name, int_bool_signature, F_R) \
do_name( isDigit_name, "isDigit") \

View File

@ -404,14 +404,12 @@ void CompilerConfig::set_compilation_policy_flags() {
#endif
if (CompilerConfig::is_tiered() && CompilerConfig::is_c2_enabled()) {
#ifdef COMPILER2
// Some inlining tuning
#if defined(X86) || defined(AARCH64) || defined(RISCV64) || defined(PPC64)
#if defined(COMPILER2) && defined(_LP64)
// LP64 specific inlining tuning for C2
if (FLAG_IS_DEFAULT(InlineSmallCode)) {
FLAG_SET_DEFAULT(InlineSmallCode, 2500);
}
#endif
#endif // COMPILER2
}
}

View File

@ -75,6 +75,10 @@ jint EpsilonHeap::initialize() {
void EpsilonHeap::initialize_serviceability() {
_pool = new EpsilonMemoryPool(this);
_memory_manager.add_pool(_pool);
}
void EpsilonHeap::post_initialize() {
CollectedHeap::post_initialize();
_monitoring_support->mark_ready();
}

View File

@ -69,6 +69,7 @@ public:
jint initialize() override;
void initialize_serviceability() override;
void post_initialize() override;
GrowableArray<GCMemoryManager*> memory_managers() override;
GrowableArray<MemoryPool*> memory_pools() override;

View File

@ -242,10 +242,6 @@ void G1Arguments::initialize() {
FLAG_SET_DEFAULT(GCPauseIntervalMillis, MaxGCPauseMillis + 1);
}
if (FLAG_IS_DEFAULT(ParallelRefProcEnabled) && ParallelGCThreads > 1) {
FLAG_SET_DEFAULT(ParallelRefProcEnabled, true);
}
#ifdef COMPILER2
// Enable loop strip mining to offer better pause time guarantees
if (FLAG_IS_DEFAULT(UseCountedLoopSafepoints)) {

View File

@ -1723,8 +1723,7 @@ void G1CollectedHeap::ref_processing_init() {
// * Reference discovery is MT (see below).
// * Reference discovery requires a barrier (see below).
// * Reference processing may or may not be MT
// (depending on the value of ParallelRefProcEnabled
// and ParallelGCThreads).
// (depending on the value of ParallelGCThreads).
// * A full GC disables reference discovery by the CM
// ref processor and abandons any entries on it's
// discovered lists.

View File

@ -565,11 +565,10 @@ void G1ConcurrentMark::fully_initialize() {
_tasks[i] = new G1CMTask(i, this, task_queue, _region_mark_stats);
}
for (uint i = 0; i < _g1h->max_num_regions(); i++) {
::new (&_region_mark_stats[i]) G1RegionMarkStats{};
::new (&_top_at_mark_starts[i]) Atomic<HeapWord*>{};
::new (&_top_at_rebuild_starts[i]) Atomic<HeapWord*>{};
}
uint max_num_regions = _g1h->max_num_regions();
::new (_region_mark_stats) G1RegionMarkStats[max_num_regions]{};
::new (_top_at_mark_starts) Atomic<HeapWord*>[max_num_regions]{};
::new (_top_at_rebuild_starts) Atomic<HeapWord*>[max_num_regions]{};
reset_at_marking_complete();
}
@ -594,8 +593,8 @@ void G1ConcurrentMark::reset() {
}
uint max_num_regions = _g1h->max_num_regions();
::new (_top_at_rebuild_starts) Atomic<HeapWord*>[max_num_regions]{};
for (uint i = 0; i < max_num_regions; i++) {
_top_at_rebuild_starts[i].store_relaxed(nullptr);
_region_mark_stats[i].clear();
}

View File

@ -26,18 +26,6 @@
#include "runtime/atomicAccess.hpp"
#include "runtime/timer.hpp"
G1ConcurrentRefineStats::G1ConcurrentRefineStats() :
_sweep_duration(0),
_yield_during_sweep_duration(0),
_cards_scanned(0),
_cards_clean(0),
_cards_not_parsable(0),
_cards_already_refer_to_cset(0),
_cards_refer_to_cset(0),
_cards_no_cross_region(0),
_refine_duration(0)
{}
void G1ConcurrentRefineStats::add_atomic(G1ConcurrentRefineStats* other) {
_sweep_duration.add_then_fetch(other->_sweep_duration.load_relaxed(), memory_order_relaxed);
_yield_during_sweep_duration.add_then_fetch(other->yield_during_sweep_duration(), memory_order_relaxed);

View File

@ -47,8 +47,6 @@ class G1ConcurrentRefineStats : public CHeapObj<mtGC> {
Atomic<jlong> _refine_duration; // Time spent during actual refinement.
public:
G1ConcurrentRefineStats();
// Time spent performing sweeping the refinement table (includes actual refinement,
// but not yield time).
inline jlong sweep_duration() const;

View File

@ -23,6 +23,7 @@
*/
#include "classfile/classLoaderDataGraph.hpp"
#include "cppstdlib/new.hpp"
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1FullCollector.inline.hpp"
#include "gc/g1/g1FullGCAdjustTask.hpp"
@ -134,12 +135,13 @@ G1FullCollector::G1FullCollector(G1CollectedHeap* heap,
_compaction_points = NEW_C_HEAP_ARRAY(G1FullGCCompactionPoint*, _num_workers, mtGC);
_live_stats = NEW_C_HEAP_ARRAY(G1RegionMarkStats, _heap->max_num_regions(), mtGC);
_compaction_tops = NEW_C_HEAP_ARRAY(Atomic<HeapWord*>, _heap->max_num_regions(), mtGC);
for (uint j = 0; j < heap->max_num_regions(); j++) {
_live_stats[j].clear();
::new (&_compaction_tops[j]) Atomic<HeapWord*>{};
}
_compaction_tops = NEW_C_HEAP_ARRAY(Atomic<HeapWord*>, _heap->max_num_regions(), mtGC);
::new (_compaction_tops) Atomic<HeapWord*>[heap->max_num_regions()]{};
_partial_array_state_manager = new PartialArrayStateManager(_num_workers);
for (uint i = 0; i < _num_workers; i++) {

View File

@ -44,8 +44,6 @@ struct G1RegionMarkStats {
Atomic<size_t> _live_words;
Atomic<size_t> _incoming_refs;
G1RegionMarkStats() : _live_words(0), _incoming_refs(0) { }
// Clear all members.
void clear() {
_live_words.store_relaxed(0);

View File

@ -24,6 +24,7 @@
#include "compiler/oopMap.hpp"
#include "cppstdlib/new.hpp"
#include "gc/g1/g1CardSetMemory.hpp"
#include "gc/g1/g1CardTableEntryClosure.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
@ -814,9 +815,7 @@ public:
void set_max_workers(uint max_workers) override {
_active_workers = max_workers;
_worker_stats = NEW_C_HEAP_ARRAY(FreeCSetStats, max_workers, mtGC);
for (uint worker = 0; worker < _active_workers; worker++) {
::new (&_worker_stats[worker]) FreeCSetStats();
}
::new (_worker_stats) FreeCSetStats[_active_workers]{};
_claimer.set_n_workers(_active_workers);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2026, 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,6 +22,7 @@
*
*/
#include "cppstdlib/new.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1RegionPinCache.inline.hpp"
#include "gc/g1/g1ThreadLocalData.hpp"
@ -89,10 +90,7 @@ public:
void set_max_workers(uint max_workers) override {
_num_workers = max_workers;
_local_tlab_stats = NEW_C_HEAP_ARRAY(ThreadLocalAllocStats, _num_workers, mtGC);
for (uint i = 0; i < _num_workers; i++) {
::new (&_local_tlab_stats[i]) ThreadLocalAllocStats();
}
::new (_local_tlab_stats) ThreadLocalAllocStats[_num_workers]{};
}
ThreadLocalAllocStats tlab_stats() const {

View File

@ -128,10 +128,6 @@ void ParallelArguments::initialize() {
}
}
if (FLAG_IS_DEFAULT(ParallelRefProcEnabled) && ParallelGCThreads > 1) {
FLAG_SET_DEFAULT(ParallelRefProcEnabled, true);
}
FullGCForwarding::initialize_flags(heap_reserved_size_bytes());
}

View File

@ -598,7 +598,6 @@ void CollectedHeap::initialize_reserved_region(const ReservedHeapSpace& rs) {
void CollectedHeap::post_initialize() {
StringDedup::initialize();
initialize_serviceability();
}
bool CollectedHeap::is_shutting_down() {

View File

@ -241,6 +241,10 @@ protected:
*/
virtual jint initialize() = 0;
// Initialize serviceability support. This should prepare the implementation
// for accepting serviceability-related calls, like memory_managers(), memory_pools().
virtual void initialize_serviceability() = 0;
// In many heaps, there will be a need to perform some initialization activities
// after the Universe is fully formed, but before general heap allocation is allowed.
// This is the correct place to place such initialization methods.
@ -419,8 +423,6 @@ protected:
// Generate any dumps preceding or following a full gc
void full_gc_dump(GCTimer* timer, bool before);
virtual void initialize_serviceability() = 0;
void print_relative_to_gc(GCWhen::Type when) const;
public:

View File

@ -198,13 +198,6 @@
constraint(MarkStackSizeConstraintFunc,AfterErgo) \
range(1, (INT_MAX - 1)) \
\
product(bool, ParallelRefProcEnabled, false, \
"(Deprecated) Enable parallel reference processing " \
"whenever possible") \
\
product(bool, ParallelRefProcBalancingEnabled, true, \
"(Deprecated) Enable balancing of reference processing queues") \
\
product(size_t, ReferencesPerThread, 1000, EXPERIMENTAL, \
"Ergonomically start one thread for this amount of " \
"references for reference processing if " \

View File

@ -122,7 +122,7 @@ void ReferenceProcessor::verify_no_references_recorded() {
#endif
bool ReferenceProcessor::processing_is_mt() const {
return ParallelRefProcEnabled && _num_queues > 1;
return _num_queues > 1;
}
void ReferenceProcessor::weak_oops_do(OopClosure* f) {
@ -586,33 +586,9 @@ void ReferenceProcessor::set_active_mt_degree(uint v) {
_next_id = 0;
}
bool ReferenceProcessor::need_balance_queues(DiscoveredList refs_lists[]) {
assert(processing_is_mt(), "why balance non-mt processing?");
// _num_queues is the processing degree. Only list entries up to
// _num_queues will be processed, so any non-empty lists beyond
// that must be redistributed to lists in that range. Even if not
// needed for that, balancing may be desirable to eliminate poor
// distribution of references among the lists.
if (ParallelRefProcBalancingEnabled) {
return true; // Configuration says do it.
} else {
// Configuration says don't balance, but if there are non-empty
// lists beyond the processing degree, then must ignore the
// configuration and balance anyway.
for (uint i = _num_queues; i < _max_num_queues; ++i) {
if (!refs_lists[i].is_empty()) {
return true; // Must balance despite configuration.
}
}
return false; // Safe to obey configuration and not balance.
}
}
void ReferenceProcessor::maybe_balance_queues(DiscoveredList refs_lists[]) {
assert(processing_is_mt(), "Should not call this otherwise");
if (need_balance_queues(refs_lists)) {
balance_queues(refs_lists);
}
balance_queues(refs_lists);
}
// Balances reference queues.

View File

@ -366,7 +366,6 @@ private:
// Balances reference queues.
void balance_queues(DiscoveredList refs_lists[]);
bool need_balance_queues(DiscoveredList refs_lists[]);
// If there is need to balance the given queue, do it.
void maybe_balance_queues(DiscoveredList refs_lists[]);

View File

@ -152,7 +152,15 @@ RefProcTotalPhaseTimesTracker::~RefProcTotalPhaseTimesTracker() {
}
ReferenceProcessorPhaseTimes::ReferenceProcessorPhaseTimes(GCTimer* gc_timer, uint max_gc_threads) :
_processing_is_mt(false), _gc_timer(gc_timer) {
_sub_phases_worker_time_sec{},
_balance_queues_time_ms{},
_soft_weak_final_refs_phase_worker_time_sec(nullptr),
_total_time_ms(0.0),
_ref_dropped{},
_ref_discovered{},
_processing_is_mt(false),
_gc_timer(gc_timer) {
assert(gc_timer != nullptr, "pre-condition");
for (uint i = 0; i < ReferenceProcessor::RefSubPhaseMax; i++) {
_sub_phases_worker_time_sec[i] = new WorkerDataArray<double>(nullptr, SubPhasesParWorkTitle[i], max_gc_threads);

View File

@ -76,8 +76,8 @@ void ThreadLocalAllocBuffer::accumulate_and_reset_statistics(ThreadLocalAllocSta
size_t used = Universe::heap()->tlab_used();
_gc_waste += (unsigned)remaining();
size_t total_allocated = (size_t)thread()->allocated_bytes();
size_t allocated_since_last_gc = total_allocated - _allocated_before_last_gc;
uint64_t total_allocated = thread()->allocated_bytes();
uint64_t allocated_since_last_gc = total_allocated - _allocated_before_last_gc;
_allocated_before_last_gc = total_allocated;
print_stats("gc");

View File

@ -54,7 +54,7 @@ private:
size_t _desired_size; // desired size (including alignment_reserve)
size_t _refill_waste_limit; // hold onto tlab if free() is larger than this
size_t _allocated_before_last_gc; // total bytes allocated up until the last gc
uint64_t _allocated_before_last_gc; // total bytes allocated up until the last gc
static size_t _max_size; // maximum size of any TLAB
static int _reserve_for_allocation_prefetch; // Reserve at the end of the TLAB

View File

@ -72,7 +72,6 @@ void WeakProcessor::oops_do(OopClosure* closure) {
}
uint WeakProcessor::ergo_workers(uint max_workers) {
// Ignore ParallelRefProcEnabled; that's for j.l.r.Reference processing.
if (ReferencesPerThread == 0) {
// Configuration says always use all the threads.
return max_workers;

View File

@ -37,22 +37,22 @@ ShenandoahEvacOOMCounter::ShenandoahEvacOOMCounter() :
void ShenandoahEvacOOMCounter::decrement() {
assert(unmasked_count() > 0, "sanity");
// NOTE: It's ok to simply decrement, even with mask set, because unmasked value is positive.
AtomicAccess::dec(&_bits);
_bits.fetch_then_sub(1);
}
void ShenandoahEvacOOMCounter::clear() {
assert(unmasked_count() == 0, "sanity");
AtomicAccess::release_store_fence(&_bits, (jint)0);
_bits.release_store_fence((jint)0);
}
void ShenandoahEvacOOMCounter::set_oom_bit(bool decrement) {
jint threads_in_evac = AtomicAccess::load_acquire(&_bits);
jint threads_in_evac = _bits.load_acquire();
while (true) {
jint newval = decrement
? (threads_in_evac - 1) | OOM_MARKER_MASK
: threads_in_evac | OOM_MARKER_MASK;
jint other = AtomicAccess::cmpxchg(&_bits, threads_in_evac, newval);
jint other = _bits.compare_exchange(threads_in_evac, newval);
if (other == threads_in_evac) {
// Success: wait for other threads to get out of the protocol and return.
break;
@ -65,7 +65,7 @@ void ShenandoahEvacOOMCounter::set_oom_bit(bool decrement) {
bool ShenandoahEvacOOMCounter::try_increment()
{
jint threads_in_evac = AtomicAccess::load_acquire(&_bits);
jint threads_in_evac = _bits.load_acquire();
while (true) {
// Cannot enter evacuation if OOM_MARKER_MASK is set.
@ -73,7 +73,7 @@ bool ShenandoahEvacOOMCounter::try_increment()
return false;
}
jint other = AtomicAccess::cmpxchg(&_bits, threads_in_evac, threads_in_evac + 1);
jint other = _bits.compare_exchange(threads_in_evac, threads_in_evac + 1);
if (other == threads_in_evac) {
// Success: caller may safely enter evacuation
return true;

View File

@ -27,6 +27,7 @@
#include "gc/shenandoah/shenandoahPadding.hpp"
#include "memory/allocation.hpp"
#include "runtime/atomic.hpp"
#include "runtime/javaThread.hpp"
#include "utilities/globalDefinitions.hpp"
@ -36,7 +37,7 @@
class ShenandoahEvacOOMCounter {
private:
// Combination of a 31-bit counter and 1-bit OOM marker.
volatile jint _bits;
Atomic<jint> _bits;
// This class must be at least a cache line in size to prevent false sharing.
shenandoah_padding_minus_size(0, sizeof(jint));

View File

@ -29,14 +29,13 @@
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
#include "gc/shenandoah/shenandoahThreadLocalData.hpp"
#include "runtime/atomicAccess.hpp"
jint ShenandoahEvacOOMCounter::load_acquire() {
return AtomicAccess::load_acquire(&_bits);
return _bits.load_acquire();
}
jint ShenandoahEvacOOMCounter::unmasked_count() {
return AtomicAccess::load_acquire(&_bits) & ~OOM_MARKER_MASK;
return _bits.load_acquire() & ~OOM_MARKER_MASK;
}
void ShenandoahEvacOOMHandler::enter_evacuation(Thread* thr) {

View File

@ -493,7 +493,7 @@ TRACE_REQUEST_FUNC(InitialSystemProperty) {
TRACE_REQUEST_FUNC(ThreadAllocationStatistics) {
ResourceMark rm;
int initial_size = Threads::number_of_threads();
GrowableArray<jlong> allocated(initial_size);
GrowableArray<uint64_t> allocated(initial_size);
GrowableArray<traceid> thread_ids(initial_size);
JfrTicks time_stamp = JfrTicks::now();
JfrJavaThreadIterator iter;

View File

@ -58,29 +58,22 @@ static inline bool in_stack(intptr_t* ptr, JavaThread* jt) {
return jt->is_in_full_stack_checked(reinterpret_cast<address>(ptr));
}
#ifdef ASSERT
static inline bool sp_in_stack(const JfrSampleRequest& request, JavaThread* jt) {
return in_stack(static_cast<intptr_t*>(request._sample_sp), jt);
}
#endif // ASSERT
static inline bool fp_in_stack(const JfrSampleRequest& request, JavaThread* jt) {
return in_stack(static_cast<intptr_t*>(request._sample_bcp), jt);
}
static inline void update_interpreter_frame_sender_pc(JfrSampleRequest& request, intptr_t* fp) {
request._sample_pc = frame::interpreter_return_address(fp);
}
static inline void update_interpreter_frame_pc(JfrSampleRequest& request, JavaThread* jt) {
assert(fp_in_stack(request, jt), "invariant");
assert(is_interpreter(request), "invariant");
request._sample_pc = frame::interpreter_return_address(static_cast<intptr_t*>(request._sample_bcp));
}
static inline address interpreter_frame_return_address(const JfrSampleRequest& request) {
assert(is_interpreter(request), "invariant");
return frame::interpreter_return_address(static_cast<intptr_t*>(request._sample_bcp));
}
static inline intptr_t* frame_sender_sp(const JfrSampleRequest& request, JavaThread* jt) {
assert(fp_in_stack(request, jt), "invariant");
return frame::sender_sp(static_cast<intptr_t*>(request._sample_bcp));
@ -90,29 +83,10 @@ static inline void update_frame_sender_sp(JfrSampleRequest& request, JavaThread*
request._sample_sp = frame_sender_sp(request, jt);
}
static inline void update_frame_sender_sp(JfrSampleRequest& request, intptr_t* fp) {
request._sample_sp = frame::sender_sp(fp);
}
static inline intptr_t* frame_link(const JfrSampleRequest& request) {
return frame::link(static_cast<intptr_t*>(request._sample_bcp));
}
static inline void update_sp(JfrSampleRequest& request, int frame_size) {
assert(frame_size >= 0, "invariant");
request._sample_sp = static_cast<intptr_t*>(request._sample_sp) + frame_size;
}
static inline void update_pc(JfrSampleRequest& request) {
assert(request._sample_sp != nullptr, "invariant");
request._sample_pc = frame::return_address(static_cast<intptr_t*>(request._sample_sp));
}
static inline void update_fp(JfrSampleRequest& request) {
assert(request._sample_sp != nullptr, "invariant");
request._sample_bcp = is_interpreter(request) ? frame::fp(static_cast<intptr_t*>(request._sample_sp)) : nullptr;
}
// Less extensive sanity checks for an interpreter frame.
static bool is_valid_interpreter_frame(const JfrSampleRequest& request, JavaThread* jt) {
assert(sp_in_stack(request, jt), "invariant");

View File

@ -66,10 +66,6 @@ static inline void send_safepoint_latency_event(const JfrSampleRequest& request,
}
}
static inline bool is_interpreter(address pc) {
return Interpreter::contains(pc);
}
static inline bool is_interpreter(const JfrSampleRequest& request) {
return request._sample_bcp != nullptr;
}

View File

@ -176,6 +176,7 @@ static inline bool is_global(ConstBufferPtr buffer) {
return buffer->context() == JFR_GLOBAL;
}
#ifdef ASSERT
static inline bool is_thread_local(ConstBufferPtr buffer) {
assert(buffer != nullptr, "invariant");
return buffer->context() == JFR_THREADLOCAL;
@ -185,6 +186,7 @@ static inline bool is_virtual_thread_local(ConstBufferPtr buffer) {
assert(buffer != nullptr, "invariant");
return buffer->context() == JFR_VIRTUAL_THREADLOCAL;
}
#endif // ASSERT
BufferPtr JfrCheckpointManager::lease_global(Thread* thread, bool previous_epoch /* false */, size_t size /* 0 */) {
JfrCheckpointMspace* const mspace = instance()._global_mspace;

View File

@ -1265,7 +1265,7 @@ static size_t teardown() {
JfrKlassUnloading::clear();
_artifacts->clear();
_initial_type_set = true;
} else {
} else if (is_initial_typeset_for_chunk()) {
_initial_type_set = false;
}
return total_count;

View File

@ -102,6 +102,9 @@ bool JfrRecorder::on_create_vm_1() {
if (!create_checkpoint_manager()) {
return false;
}
if (!JfrSymbolTable::create()) {
return false;
}
}
// fast time initialization
@ -316,10 +319,7 @@ bool JfrRecorder::create_components() {
if (!create_thread_group_manager()) {
return false;
}
if (!create_symbol_table()) {
return false;
}
return true;
return create_symbol_table();
}
// subsystems
@ -418,7 +418,13 @@ bool JfrRecorder::create_thread_group_manager() {
}
bool JfrRecorder::create_symbol_table() {
return JfrSymbolTable::create();
return !is_started_on_commandline() ? JfrSymbolTable::create() : true;
}
void JfrRecorder::destroy_symbol_table() {
if (!is_started_on_commandline()) {
JfrSymbolTable::destroy();
}
}
void JfrRecorder::destroy_components() {
@ -461,7 +467,7 @@ void JfrRecorder::destroy_components() {
}
JfrEventThrottler::destroy();
JfrThreadGroupManager::destroy();
JfrSymbolTable::destroy();
destroy_symbol_table();
}
bool JfrRecorder::create_recorder_thread() {

View File

@ -59,6 +59,7 @@ class JfrRecorder : public JfrCHeapObj {
static bool create_event_throttler();
static bool create_symbol_table();
static bool create_components();
static void destroy_symbol_table();
static void destroy_components();
static void on_recorder_thread_exit();

View File

@ -194,9 +194,11 @@ static inline bool is_not_jdk_module(const ModuleEntry* module, JavaThread* jt)
return !is_jdk_module(module, jt);
}
#ifdef ASSERT
static inline bool jfr_is_started_on_command_line() {
return JfrRecorder::is_started_on_commandline();
}
#endif // ASSERT
static bool should_record(const Method* method, const Method* sender, JavaThread* jt) {
assert(method != nullptr, "invariant");

View File

@ -432,7 +432,7 @@
\
nonstatic_field(Thread, _poll_data, SafepointMechanism::ThreadData) \
nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \
nonstatic_field(Thread, _allocated_bytes, jlong) \
nonstatic_field(Thread, _allocated_bytes, uint64_t) \
JFR_ONLY(nonstatic_field(Thread, _jfr_thread_local, JfrThreadLocal)) \
\
static_field(java_lang_Thread, _tid_offset, int) \

View File

@ -1182,13 +1182,12 @@ bool universe_post_init() {
Universe::heap()->update_capacity_and_used_at_gc();
}
// ("weak") refs processing infrastructure initialization
// Initialize serviceability
MemoryService::initialize(Universe::heap());
// Complete initialization
Universe::heap()->post_initialize();
MemoryService::add_metaspace_memory_pools();
MemoryService::set_universe_heap(Universe::heap());
#if INCLUDE_CDS
AOTMetaspace::post_initialize(CHECK_false);
#endif

View File

@ -1369,72 +1369,37 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
cast_to_ptr_type(ptr)->
with_offset(offset);
}
} else if (ta) {
// For arrays indexed by constant indices, we flatten the alias
// space to include all of the array body. Only the header, klass
// and array length can be accessed un-aliased.
if( offset != Type::OffsetBot ) {
if( ta->const_oop() ) { // MethodData* or Method*
offset = Type::OffsetBot; // Flatten constant access into array body
tj = ta = ta->
remove_speculative()->
cast_to_ptr_type(ptr)->
cast_to_exactness(false)->
with_offset(offset);
} else if( offset == arrayOopDesc::length_offset_in_bytes() ) {
// range is OK as-is.
tj = ta = TypeAryPtr::RANGE;
} else if( offset == oopDesc::klass_offset_in_bytes() ) {
tj = TypeInstPtr::KLASS; // all klass loads look alike
ta = TypeAryPtr::RANGE; // generic ignored junk
ptr = TypePtr::BotPTR;
} else if( offset == oopDesc::mark_offset_in_bytes() ) {
tj = TypeInstPtr::MARK;
ta = TypeAryPtr::RANGE; // generic ignored junk
ptr = TypePtr::BotPTR;
} else { // Random constant offset into array body
offset = Type::OffsetBot; // Flatten constant access into array body
tj = ta = ta->
remove_speculative()->
cast_to_ptr_type(ptr)->
cast_to_exactness(false)->
with_offset(offset);
}
} else if (ta != nullptr) {
// Common slices
if (offset == arrayOopDesc::length_offset_in_bytes()) {
return TypeAryPtr::RANGE;
} else if (offset == oopDesc::klass_offset_in_bytes()) {
return TypeInstPtr::KLASS;
} else if (offset == oopDesc::mark_offset_in_bytes()) {
return TypeInstPtr::MARK;
}
// Arrays of fixed size alias with arrays of unknown size.
if (ta->size() != TypeInt::POS) {
const TypeAry *tary = TypeAry::make(ta->elem(), TypeInt::POS);
tj = ta = ta->
remove_speculative()->
cast_to_ptr_type(ptr)->
with_ary(tary)->
cast_to_exactness(false);
}
// Arrays of known objects become arrays of unknown objects.
if (ta->elem()->isa_narrowoop() && ta->elem() != TypeNarrowOop::BOTTOM) {
const TypeAry *tary = TypeAry::make(TypeNarrowOop::BOTTOM, ta->size());
tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,nullptr,false,offset);
}
if (ta->elem()->isa_oopptr() && ta->elem() != TypeInstPtr::BOTTOM) {
const TypeAry *tary = TypeAry::make(TypeInstPtr::BOTTOM, ta->size());
tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,nullptr,false,offset);
// Remove size and stability
const TypeAry* normalized_ary = TypeAry::make(ta->elem(), TypeInt::POS, false);
// Remove ptr, const_oop, and offset
if (ta->elem() == Type::BOTTOM) {
// Bottom array (meet of int[] and byte[] for example), accesses to it will be done with
// Unsafe. This should alias with all arrays. For now just leave it as it is (this is
// incorrect, see JDK-8331133).
tj = ta = TypeAryPtr::make(TypePtr::BotPTR, nullptr, normalized_ary, nullptr, false, Type::OffsetBot);
} else if (ta->elem()->make_oopptr() != nullptr) {
// Object arrays, all of them share the same slice
const TypeAry* tary = TypeAry::make(TypeInstPtr::BOTTOM, TypeInt::POS, false);
tj = ta = TypeAryPtr::make(TypePtr::BotPTR, nullptr, tary, nullptr, false, Type::OffsetBot);
} else {
// Primitive arrays
tj = ta = TypeAryPtr::make(TypePtr::BotPTR, nullptr, normalized_ary, ta->exact_klass(), true, Type::OffsetBot);
}
// Arrays of bytes and of booleans both use 'bastore' and 'baload' so
// cannot be distinguished by bytecode alone.
if (ta->elem() == TypeInt::BOOL) {
const TypeAry *tary = TypeAry::make(TypeInt::BYTE, ta->size());
ciKlass* aklass = ciTypeArrayKlass::make(T_BYTE);
tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,aklass,false,offset);
}
// During the 2nd round of IterGVN, NotNull castings are removed.
// Make sure the Bottom and NotNull variants alias the same.
// Also, make sure exact and non-exact variants alias the same.
if (ptr == TypePtr::NotNull || ta->klass_is_exact() || ta->speculative() != nullptr) {
tj = ta = ta->
remove_speculative()->
cast_to_ptr_type(TypePtr::BotPTR)->
cast_to_exactness(false)->
with_offset(offset);
tj = ta = TypeAryPtr::BYTES;
}
}

View File

@ -221,6 +221,9 @@ public:
virtual int Opcode() const;
const Type* bottom_type() const { return TypeInt::BOOL; }
virtual uint ideal_reg() const { return Op_RegI; }
private:
virtual bool depends_only_on_test_impl() const { return false; }
};
//------------------------------LowerCaseNode------------------------------------
@ -230,6 +233,9 @@ public:
virtual int Opcode() const;
const Type* bottom_type() const { return TypeInt::BOOL; }
virtual uint ideal_reg() const { return Op_RegI; }
private:
virtual bool depends_only_on_test_impl() const { return false; }
};
//------------------------------UpperCaseNode------------------------------------
@ -239,6 +245,9 @@ public:
virtual int Opcode() const;
const Type* bottom_type() const { return TypeInt::BOOL; }
virtual uint ideal_reg() const { return Op_RegI; }
private:
virtual bool depends_only_on_test_impl() const { return false; }
};
//------------------------------WhitespaceCode-----------------------------------
@ -248,6 +257,9 @@ public:
virtual int Opcode() const;
const Type* bottom_type() const { return TypeInt::BOOL; }
virtual uint ideal_reg() const { return Op_RegI; }
private:
virtual bool depends_only_on_test_impl() const { return false; }
};
//------------------------------CopySign-----------------------------------------

View File

@ -1307,8 +1307,8 @@ bool LibraryCallKit::inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae) {
Node* tgt_start = array_element_address(tgt, intcon(0), T_BYTE);
// Range checks
generate_string_range_check(src, src_offset, src_count, ae != StrIntrinsicNode::LL);
generate_string_range_check(tgt, intcon(0), tgt_count, ae == StrIntrinsicNode::UU);
generate_string_range_check(src, src_offset, src_count, ae != StrIntrinsicNode::LL, true);
generate_string_range_check(tgt, intcon(0), tgt_count, ae == StrIntrinsicNode::UU, true);
if (stopped()) {
return true;
}
@ -1404,7 +1404,7 @@ bool LibraryCallKit::inline_string_indexOfChar(StrIntrinsicNode::ArgEnc ae) {
Node* src_count = _gvn.transform(new SubINode(max, from_index));
// Range checks
generate_string_range_check(src, src_offset, src_count, ae == StrIntrinsicNode::U);
generate_string_range_check(src, src_offset, src_count, ae == StrIntrinsicNode::U, true);
// Check for int_ch >= 0
Node* int_ch_cmp = _gvn.transform(new CmpINode(int_ch, intcon(0)));
@ -1448,11 +1448,11 @@ bool LibraryCallKit::inline_string_indexOfChar(StrIntrinsicNode::ArgEnc ae) {
}
//---------------------------inline_string_copy---------------------
// compressIt == true --> generate a compressed copy operation (compress char[]/byte[] to byte[])
// int StringUTF16.compress(char[] src, int srcOff, byte[] dst, int dstOff, int len)
// int StringUTF16.compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len)
// int StringUTF16.compress0(char[] src, int srcOff, byte[] dst, int dstOff, int len)
// int StringUTF16.compress0(byte[] src, int srcOff, byte[] dst, int dstOff, int len)
// compressIt == false --> generate an inflated copy operation (inflate byte[] to char[]/byte[])
// void StringLatin1.inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len)
// void StringLatin1.inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len)
// void StringLatin1.inflate0(byte[] src, int srcOff, char[] dst, int dstOff, int len)
// void StringLatin1.inflate0(byte[] src, int srcOff, byte[] dst, int dstOff, int len)
bool LibraryCallKit::inline_string_copy(bool compress) {
if (too_many_traps(Deoptimization::Reason_intrinsic)) {
return false;
@ -1495,8 +1495,8 @@ bool LibraryCallKit::inline_string_copy(bool compress) {
}
// Range checks
generate_string_range_check(src, src_offset, length, convert_src);
generate_string_range_check(dst, dst_offset, length, convert_dst);
generate_string_range_check(src, src_offset, length, convert_src, true);
generate_string_range_check(dst, dst_offset, length, convert_dst, true);
if (stopped()) {
return true;
}

View File

@ -44,6 +44,7 @@
#include "opto/mempointer.hpp"
#include "opto/mulnode.hpp"
#include "opto/narrowptrnode.hpp"
#include "opto/opcodes.hpp"
#include "opto/phaseX.hpp"
#include "opto/regalloc.hpp"
#include "opto/regmask.hpp"
@ -552,6 +553,18 @@ Node::DomResult MemNode::maybe_all_controls_dominate(Node* dom, Node* sub) {
bool MemNode::detect_ptr_independence(Node* p1, AllocateNode* a1,
Node* p2, AllocateNode* a2,
PhaseTransform* phase) {
// Trivial case: Non-overlapping values. Be careful, we can cast a raw pointer to an oop (e.g. in
// the allocation pattern) so joining the types only works if both are oops. join may also give
// an incorrect result when both pointers are nullable and the result is supposed to be
// TypePtr::NULL_PTR, so we exclude that case.
const Type* p1_type = p1->bottom_type();
const Type* p2_type = p2->bottom_type();
if (p1_type->isa_oopptr() && p2_type->isa_oopptr() &&
(!p1_type->maybe_null() || !p2_type->maybe_null()) &&
p1_type->join(p2_type)->empty()) {
return true;
}
// Attempt to prove that these two pointers cannot be aliased.
// They may both manifestly be allocations, and they should differ.
// Or, if they are not both allocations, they can be distinct constants.
@ -690,6 +703,20 @@ Node* MemNode::find_previous_store(PhaseValues* phase) {
Node* base = AddPNode::Ideal_base_and_offset(adr, phase, offset);
AllocateNode* alloc = AllocateNode::Ideal_allocation(base);
const TypePtr* adr_type = this->adr_type();
if (adr_type == nullptr) {
// This means the access is dead
return phase->C->top();
} else if (adr_type->base() == TypePtr::AnyPtr) {
assert(adr_type->ptr() == TypePtr::Null, "MemNode should never access a wide memory");
// Give up, this will upset Compile::get_alias_index
return nullptr;
}
int alias_idx = phase->C->get_alias_index(adr_type);
assert(alias_idx != Compile::AliasIdxTop, "must not be a dead node");
assert(alias_idx != Compile::AliasIdxBot || !phase->C->do_aliasing(), "must not be a very wide access");
if (offset == Type::OffsetBot)
return nullptr; // cannot unalias unless there are precise offsets
@ -709,15 +736,32 @@ Node* MemNode::find_previous_store(PhaseValues* phase) {
Node* st_adr = mem->in(MemNode::Address);
intptr_t st_offset = 0;
Node* st_base = AddPNode::Ideal_base_and_offset(st_adr, phase, st_offset);
if (st_base == nullptr)
break; // inscrutable pointer
// For raw accesses it's not enough to prove that constant offsets don't intersect.
// We need the bases to be the equal in order for the offset check to make sense.
if ((adr_maybe_raw || check_if_adr_maybe_raw(st_adr)) && st_base != base) {
if (st_base == nullptr) {
// inscrutable pointer
break;
}
// If the bases are the same and the offsets are the same, it seems that this is the exact
// store we are looking for, the caller will check if the type of the store matches using
// MemNode::can_see_stored_value
if (st_base == base && st_offset == offset) {
return mem; // (b) found the store that this access observes
}
// If it is provable that the memory accessed by mem does not overlap the memory accessed by
// this, we may walk past mem.
// For raw accesses, 2 accesses are independent if they have the same base and the offsets
// say that they do not overlap.
// For heap accesses, 2 accesses are independent if either the bases are provably different
// at runtime or the offsets say that the accesses do not overlap.
if ((adr_maybe_raw || check_if_adr_maybe_raw(st_adr)) && st_base != base) {
// Raw accesses can only be provably independent if they have the same base
break;
}
// If the offsets say that the accesses do not overlap, then it is provable that mem and this
// do not overlap. For example, a LoadI from Object+8 is independent from a StoreL into
// Object+12, no matter what the bases are.
if (st_offset != offset && st_offset != Type::OffsetBot) {
const int MAX_STORE = MAX2(BytesPerLong, (int)MaxVectorSize);
assert(mem->as_Store()->memory_size() <= MAX_STORE, "");
@ -730,25 +774,25 @@ Node* MemNode::find_previous_store(PhaseValues* phase) {
// in the same sequence of RawMem effects. We sometimes initialize
// a whole 'tile' of array elements with a single jint or jlong.)
mem = mem->in(MemNode::Memory);
continue; // (a) advance through independent store memory
continue; // (a) advance through the independent store
}
}
if (st_base != base &&
detect_ptr_independence(base, alloc,
st_base,
AllocateNode::Ideal_allocation(st_base),
phase)) {
// Success: The bases are provably independent.
// Same base and overlapping offsets, it seems provable that the accesses overlap, give up
if (st_base == base) {
break;
}
// Try to prove that 2 different base nodes at compile time are different values at runtime
bool known_independent = false;
if (detect_ptr_independence(base, alloc, st_base, AllocateNode::Ideal_allocation(st_base), phase)) {
known_independent = true;
}
if (known_independent) {
mem = mem->in(MemNode::Memory);
continue; // (a) advance through independent store memory
continue; // (a) advance through the independent store
}
// (b) At this point, if the bases or offsets do not agree, we lose,
// since we have not managed to prove 'this' and 'mem' independent.
if (st_base == base && st_offset == offset) {
return mem; // let caller handle steps (c), (d)
}
} else if (mem->is_Proj() && mem->in(0)->is_Initialize()) {
InitializeNode* st_init = mem->in(0)->as_Initialize();
AllocateNode* st_alloc = st_init->allocation();
@ -769,7 +813,6 @@ Node* MemNode::find_previous_store(PhaseValues* phase) {
// The bases are provably independent: Either they are
// manifestly distinct allocations, or else the control
// of this load dominates the store's allocation.
int alias_idx = phase->C->get_alias_index(adr_type());
if (alias_idx == Compile::AliasIdxRaw) {
mem = st_alloc->in(TypeFunc::Memory);
} else {
@ -792,6 +835,9 @@ Node* MemNode::find_previous_store(PhaseValues* phase) {
}
// Found an arraycopy that may affect that load
return mem;
} else if (mem->is_MergeMem()) {
mem = mem->as_MergeMem()->memory_at(alias_idx);
continue;
} else if (addr_t != nullptr && addr_t->is_known_instance_field()) {
// Can't use optimize_simple_memory_chain() since it needs PhaseGVN.
if (mem->is_Proj() && mem->in(0)->is_Call()) {
@ -817,10 +863,6 @@ Node* MemNode::find_previous_store(PhaseValues* phase) {
// we are looking for.
return mem;
}
} else if (mem->is_MergeMem()) {
int alias_idx = phase->C->get_alias_index(adr_type());
mem = mem->as_MergeMem()->memory_at(alias_idx);
continue; // (a) advance through independent MergeMem memory
}
}
@ -1843,7 +1885,6 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* ctrl = in(MemNode::Control);
Node* address = in(MemNode::Address);
bool progress = false;
bool addr_mark = ((phase->type(address)->isa_oopptr() || phase->type(address)->isa_narrowoop()) &&
phase->type(address)->is_ptr()->offset() == oopDesc::mark_offset_in_bytes());
@ -1856,7 +1897,7 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) {
(depends_only_on_test() || has_unknown_control_dependency())) {
ctrl = ctrl->in(0);
set_req(MemNode::Control,ctrl);
progress = true;
return this;
}
intptr_t ignore = 0;
@ -1870,7 +1911,7 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) {
&& all_controls_dominate(base, phase->C->start())) {
// A method-invariant, non-null address (constant or 'this' argument).
set_req(MemNode::Control, nullptr);
progress = true;
return this;
}
}
@ -1943,6 +1984,10 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// the alias index stuff. So instead, peek through Stores and IFF we can
// fold up, do so.
Node* prev_mem = find_previous_store(phase);
if (prev_mem != nullptr && prev_mem->is_top()) {
// find_previous_store returns top when the access is dead
return prev_mem;
}
if (prev_mem != nullptr) {
Node* value = can_see_arraycopy_value(prev_mem, phase);
if (value != nullptr) {
@ -1961,7 +2006,11 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) {
}
}
return progress ? this : nullptr;
if (!can_reshape) {
phase->record_for_igvn(this);
}
return nullptr;
}
// Helper to recognize certain Klass fields which are invariant across
@ -3565,6 +3614,10 @@ Node* StoreNode::Identity(PhaseGVN* phase) {
Node* prev_mem = find_previous_store(phase);
// Steps (a), (b): Walk past independent stores to find an exact match.
if (prev_mem != nullptr) {
if (prev_mem->is_top()) {
// find_previous_store returns top when the access is dead
return prev_mem;
}
Node* prev_val = can_see_stored_value(prev_mem, phase);
if (prev_val != nullptr && prev_val == val) {
// prev_val and val might differ by a cast; it would be good

View File

@ -31,6 +31,7 @@
#include "opto/callnode.hpp"
#include "opto/castnode.hpp"
#include "opto/cfgnode.hpp"
#include "opto/convertnode.hpp"
#include "opto/idealGraphPrinter.hpp"
#include "opto/loopnode.hpp"
#include "opto/machnode.hpp"
@ -2649,6 +2650,26 @@ void PhaseIterGVN::add_users_of_use_to_worklist(Node* n, Node* use, Unique_Node_
}
}
}
// ConvD2F::Ideal matches ConvD2F(SqrtD(ConvF2D(x))) => SqrtF(x).
// Notify ConvD2F users of SqrtD when any input of the SqrtD changes.
if (use_op == Op_SqrtD) {
for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
Node* u = use->fast_out(i2);
if (u->Opcode() == Op_ConvD2F) {
worklist.push(u);
}
}
}
// ConvF2HF::Ideal matches ConvF2HF(binopF(ConvHF2F(...))) => FP16BinOp(...).
// Notify ConvF2HF users of float binary ops when any input changes.
if (Float16NodeFactory::is_float32_binary_oper(use_op)) {
for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
Node* u = use->fast_out(i2);
if (u->Opcode() == Op_ConvF2HF) {
worklist.push(u);
}
}
}
// If changed AddP inputs:
// - check Stores for loop invariant, and
// - if the changed input is the offset, check constant-offset AddP users for

View File

@ -1077,11 +1077,19 @@ JvmtiEnv::SuspendAllVirtualThreads(jint except_count, const jthread* except_list
JvmtiVTSuspender::register_vthread_resume(thread_oop);
}
}
// Restore resumed state for current thread if it is virtual.
// It must be suspended in the suspend_thread call out of disabler context.
oop cur_oop = self_tobj();
if (cur_oop != nullptr) {
assert(JvmtiVTSuspender::is_vthread_suspended(cur_oop), "sanity check");
JvmtiVTSuspender::register_vthread_resume(cur_oop);
}
}
// Self suspend after all other suspends if necessary.
// Do not use MountUnmountDisabler in context of self suspend to avoid deadlocks.
if (self_tobj() != nullptr) {
suspend_thread(self_tobj(), current, /* single_suspend */ false);
// Register current vthread as suspended with the suspend_thread call.
suspend_thread(self_tobj(), current, /* single_suspend */ true);
}
return JVMTI_ERROR_NONE;
} /* end SuspendAllVirtualThreads */

View File

@ -2215,25 +2215,10 @@ WB_ENTRY(jboolean, WB_CDSMemoryMappingFailed(JNIEnv* env, jobject wb))
return FileMapInfo::memory_mapping_failed();
WB_END
WB_ENTRY(jboolean, WB_IsSharedInternedString(JNIEnv* env, jobject wb, jobject str))
if (!HeapShared::is_loading_mapping_mode()) {
return false;
}
ResourceMark rm(THREAD);
oop str_oop = JNIHandles::resolve(str);
int length;
jchar* chars = java_lang_String::as_unicode_string(str_oop, length, CHECK_(false));
return StringTable::lookup_shared(chars, length) == str_oop;
WB_END
WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
return (jboolean)AOTMetaspace::in_aot_cache(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
WB_END
WB_ENTRY(jboolean, WB_AreSharedStringsMapped(JNIEnv* env))
return AOTMappedHeapLoader::is_mapped();
WB_END
WB_ENTRY(void, WB_LinkClass(JNIEnv* env, jobject wb, jclass clazz))
Klass *k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
if (!k->is_instance_klass()) {
@ -3058,9 +3043,7 @@ static JNINativeMethod methods[] = {
{CC"getCDSGenericHeaderMinVersion", CC"()I", (void*)&WB_GetCDSGenericHeaderMinVersion},
{CC"getCurrentCDSVersion", CC"()I", (void*)&WB_GetCDSCurrentVersion},
{CC"isSharingEnabled", CC"()Z", (void*)&WB_IsSharingEnabled},
{CC"isSharedInternedString", CC"(Ljava/lang/String;)Z", (void*)&WB_IsSharedInternedString },
{CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass },
{CC"areSharedStringsMapped", CC"()Z", (void*)&WB_AreSharedStringsMapped },
{CC"linkClass", CC"(Ljava/lang/Class;)V", (void*)&WB_LinkClass},
{CC"areOpenArchiveHeapObjectsMapped", CC"()Z", (void*)&WB_AreOpenArchiveHeapObjectsMapped},
{CC"isCDSIncluded", CC"()Z", (void*)&WB_IsCDSIncluded },

View File

@ -536,8 +536,6 @@ static SpecialFlag const special_jvm_flags[] = {
#ifdef _LP64
{ "UseCompressedClassPointers", JDK_Version::jdk(25), JDK_Version::jdk(27), JDK_Version::undefined() },
#endif
{ "ParallelRefProcEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) },
{ "ParallelRefProcBalancingEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) },
{ "MaxRAM", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) },
{ "AggressiveHeap", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) },
{ "NeverActAsServerClassMachine", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) },
@ -553,6 +551,8 @@ static SpecialFlag const special_jvm_flags[] = {
#endif
{ "PSChunkLargeArrays", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) },
{ "ParallelRefProcEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) },
{ "ParallelRefProcBalancingEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) },
#ifdef ASSERT
{ "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() },

View File

@ -329,13 +329,18 @@ void ObjectMonitor::set_object_strong() {
void ObjectMonitor::ExitOnSuspend::operator()(JavaThread* current) {
if (current->is_suspended()) {
// There could be an ongoing safepoint/handshake operation.
// Process them, except suspend requests, before exiting the
// monitor, as this may involve touching oops if the successor
// is a virtual thread. Before processing pending operations,
// set the monitor as pending again.
current->set_current_pending_monitor(_om);
SafepointMechanism::process_if_requested(current, false /*allow_suspend*/, false /*check_async_exception*/);
_om->_recursions = 0;
_om->clear_successor();
// Don't need a full fence after clearing successor here because of the call to exit().
_om->exit(current, false /* not_suspended */);
_om_exited = true;
current->set_current_pending_monitor(_om);
}
}
@ -1644,6 +1649,7 @@ void ObjectMonitor::exit_epilog(JavaThread* current, ObjectWaiter* Wakee) {
Trigger = t->_ParkEvent;
set_successor(t);
} else {
assert_not_at_safepoint();
vthread = Wakee->vthread();
assert(vthread != nullptr, "");
Trigger = ObjectMonitor::vthread_unparker_ParkEvent();

View File

@ -485,8 +485,8 @@ void Thread::print_on(outputStream* st, bool print_extended_info) const {
(double)_statistical_info.getElapsedTime() / 1000.0
);
if (is_Java_thread() && (PrintExtendedThreadInfo || print_extended_info)) {
size_t allocated_bytes = checked_cast<size_t>(cooked_allocated_bytes());
st->print("allocated=%zu%s ",
uint64_t allocated_bytes = cooked_allocated_bytes();
st->print("allocated=" UINT64_FORMAT "%s ",
byte_size_in_proper_unit(allocated_bytes),
proper_unit_for_byte_size(allocated_bytes)
);

View File

@ -257,7 +257,7 @@ class Thread: public ThreadShadow {
private:
ThreadLocalAllocBuffer _tlab; // Thread-local eden
jlong _allocated_bytes; // Cumulative number of bytes allocated on
uint64_t _allocated_bytes; // Cumulative number of bytes allocated on
// the Java heap
ThreadHeapSampler _heap_sampler; // For use when sampling the memory.
@ -410,9 +410,9 @@ class Thread: public ThreadShadow {
void retire_tlab(ThreadLocalAllocStats* stats = nullptr);
void fill_tlab(HeapWord* start, size_t pre_reserved, size_t new_size);
jlong allocated_bytes() { return _allocated_bytes; }
void incr_allocated_bytes(jlong size) { _allocated_bytes += size; }
inline jlong cooked_allocated_bytes() const;
uint64_t allocated_bytes() { return _allocated_bytes; }
void incr_allocated_bytes(uint64_t size) { _allocated_bytes += size; }
inline uint64_t cooked_allocated_bytes() const;
ThreadHeapSampler& heap_sampler() { return _heap_sampler; }

View File

@ -36,8 +36,8 @@
#include "runtime/os.hpp"
#endif
inline jlong Thread::cooked_allocated_bytes() const {
jlong allocated_bytes = AtomicAccess::load_acquire(&_allocated_bytes);
inline uint64_t Thread::cooked_allocated_bytes() const {
uint64_t allocated_bytes = AtomicAccess::load_acquire(&_allocated_bytes);
size_t used_bytes = 0;
if (UseTLAB) {
// cooked_used_bytes() does its best to not return implausible values, but

View File

@ -159,7 +159,7 @@
unchecked_nonstatic_field) \
\
/******************************************************************/ \
/* OopDesc and Klass hierarchies (NOTE: MethodData* incomplete) */ \
/* OopDesc and Klass hierarchies */ \
/******************************************************************/ \
\
volatile_nonstatic_field(oopDesc, _mark, markWord) \
@ -233,27 +233,7 @@
nonstatic_field(Klass, _vtable_len, int) \
nonstatic_field(Klass, _class_loader_data, ClassLoaderData*) \
nonstatic_field(vtableEntry, _method, Method*) \
nonstatic_field(MethodData, _size, int) \
nonstatic_field(MethodData, _method, Method*) \
nonstatic_field(MethodData, _data_size, int) \
nonstatic_field(MethodData, _data[0], intptr_t) \
nonstatic_field(MethodData, _parameters_type_data_di, int) \
nonstatic_field(MethodData, _compiler_counters._nof_decompiles, uint) \
nonstatic_field(MethodData, _compiler_counters._nof_overflow_recompiles, uint) \
nonstatic_field(MethodData, _compiler_counters._nof_overflow_traps, uint) \
nonstatic_field(MethodData, _compiler_counters._trap_hist._array[0], u1) \
nonstatic_field(MethodData, _eflags, intx) \
nonstatic_field(MethodData, _arg_local, intx) \
nonstatic_field(MethodData, _arg_stack, intx) \
nonstatic_field(MethodData, _arg_returned, intx) \
nonstatic_field(MethodData, _tenure_traps, uint) \
nonstatic_field(MethodData, _invoke_mask, int) \
nonstatic_field(MethodData, _backedge_mask, int) \
nonstatic_field(DataLayout, _header._struct._tag, u1) \
nonstatic_field(DataLayout, _header._struct._flags, u1) \
nonstatic_field(DataLayout, _header._struct._bci, u2) \
nonstatic_field(DataLayout, _header._struct._traps, u4) \
nonstatic_field(DataLayout, _cells[0], intptr_t) \
nonstatic_field(MethodCounters, _invoke_mask, int) \
nonstatic_field(MethodCounters, _backedge_mask, int) \
COMPILER2_OR_JVMCI_PRESENT(nonstatic_field(MethodCounters, _interpreter_throwout_count, u2)) \
@ -428,6 +408,8 @@
volatile_nonstatic_field(ClassLoaderData, _klasses, Klass*) \
nonstatic_field(ClassLoaderData, _has_class_mirror_holder, bool) \
\
static_field(ClassLoaderData, _the_null_class_loader_data, ClassLoaderData*) \
\
volatile_static_field(ClassLoaderDataGraph, _head, ClassLoaderData*) \
\
/**********/ \
@ -596,7 +578,7 @@
nonstatic_field(ThreadShadow, _exception_file, const char*) \
nonstatic_field(ThreadShadow, _exception_line, int) \
nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \
nonstatic_field(Thread, _allocated_bytes, jlong) \
nonstatic_field(Thread, _allocated_bytes, uint64_t) \
nonstatic_field(JavaThread, _lock_stack, LockStack) \
nonstatic_field(LockStack, _top, uint32_t) \
nonstatic_field(LockStack, _base[0], oop) \
@ -961,8 +943,6 @@
declare_type(ConstMethod, MetaspaceObj) \
declare_type(Annotations, MetaspaceObj) \
\
declare_toplevel_type(MethodData::CompilerCounters) \
\
declare_toplevel_type(narrowKlass) \
\
declare_toplevel_type(vtableEntry) \
@ -971,7 +951,6 @@
declare_toplevel_type(Symbol*) \
declare_toplevel_type(volatile Metadata*) \
\
declare_toplevel_type(DataLayout) \
declare_toplevel_type(BSMAttributeEntries) \
\
/********/ \
@ -1311,6 +1290,12 @@
VM_INT_CONSTANTS_GC(declare_constant, \
declare_constant_with_value) \
\
/*****************/ \
/* CDS constants */ \
/*****************/ \
\
CDS_ONLY(declare_constant(AOTCompressedPointers::MetadataOffsetShift)) \
\
/******************/ \
/* Useful globals */ \
/******************/ \

View File

@ -33,12 +33,9 @@
// Useful if the function or method is known to do something special or even 'dangerous', for
// example causing desired signals/crashes.
#ifdef UNDEFINED_BEHAVIOR_SANITIZER
#if defined(__clang__)
#if defined(__clang__) || defined(__GNUC__)
#define ATTRIBUTE_NO_UBSAN __attribute__((no_sanitize("undefined","float-divide-by-zero")))
#endif
#if defined(__GNUC__) && !defined(__clang__)
#define ATTRIBUTE_NO_UBSAN __attribute__((no_sanitize("undefined")))
#endif
#endif
#ifndef ATTRIBUTE_NO_UBSAN

View File

@ -2124,12 +2124,12 @@ JVM_ENTRY(jlong, jmm_GetTotalThreadAllocatedMemory(JNIEnv *env))
// We keep a high water mark to ensure monotonicity in case threads counted
// on a previous call end up in state (2).
static jlong high_water_result = 0;
static uint64_t high_water_result = 0;
JavaThreadIteratorWithHandle jtiwh;
jlong result = ThreadService::exited_allocated_bytes();
uint64_t result = ThreadService::exited_allocated_bytes();
for (; JavaThread* thread = jtiwh.next();) {
jlong size = thread->cooked_allocated_bytes();
uint64_t size = thread->cooked_allocated_bytes();
result += size;
}
@ -2144,7 +2144,7 @@ JVM_ENTRY(jlong, jmm_GetTotalThreadAllocatedMemory(JNIEnv *env))
high_water_result = result;
}
}
return result;
return checked_cast<jlong>(result);
JVM_END
// Gets the amount of memory allocated on the Java heap for a single thread.
@ -2156,13 +2156,13 @@ JVM_ENTRY(jlong, jmm_GetOneThreadAllocatedMemory(JNIEnv *env, jlong thread_id))
}
if (thread_id == 0) { // current thread
return thread->cooked_allocated_bytes();
return checked_cast<jlong>(thread->cooked_allocated_bytes());
}
ThreadsListHandle tlh;
JavaThread* java_thread = tlh.list()->find_JavaThread_from_java_tid(thread_id);
if (is_platform_thread(java_thread)) {
return java_thread->cooked_allocated_bytes();
return checked_cast<jlong>(java_thread->cooked_allocated_bytes());
}
return -1;
JVM_END

View File

@ -66,7 +66,13 @@ void GcThreadCountClosure::do_thread(Thread* thread) {
_count++;
}
void MemoryService::set_universe_heap(CollectedHeap* heap) {
void MemoryService::initialize(CollectedHeap* heap) {
// Prepare metaspace pools
add_metaspace_memory_pools();
// Ask heap to initialize its memory pools/managers
heap->initialize_serviceability();
ResourceMark rm; // For internal allocations in GrowableArray.
GrowableArray<MemoryPool*> gc_mem_pools = heap->memory_pools();

View File

@ -60,7 +60,7 @@ private:
static MemoryPool* _compressed_class_pool;
public:
static void set_universe_heap(CollectedHeap* heap);
static void initialize(CollectedHeap* heap);
static void add_code_heap_memory_pool(CodeHeap* heap, const char* name);
static void add_metaspace_memory_pools();

View File

@ -74,7 +74,7 @@ PerfVariable* ThreadService::_daemon_threads_count = nullptr;
volatile int ThreadService::_atomic_threads_count = 0;
volatile int ThreadService::_atomic_daemon_threads_count = 0;
volatile jlong ThreadService::_exited_allocated_bytes = 0;
volatile uint64_t ThreadService::_exited_allocated_bytes = 0;
ThreadDumpResult* ThreadService::_threaddump_list = nullptr;

View File

@ -63,7 +63,7 @@ private:
// As could this...
// Number of heap bytes allocated by terminated threads.
static volatile jlong _exited_allocated_bytes;
static volatile uint64_t _exited_allocated_bytes;
// These 2 counters are like the above thread counts, but are
// atomically decremented in ThreadService::current_thread_exiting instead of
@ -106,8 +106,8 @@ public:
static int get_live_thread_count() { return _atomic_threads_count; }
static int get_daemon_thread_count() { return _atomic_daemon_threads_count; }
static jlong exited_allocated_bytes() { return AtomicAccess::load(&_exited_allocated_bytes); }
static void incr_exited_allocated_bytes(jlong size) {
static uint64_t exited_allocated_bytes() { return AtomicAccess::load(&_exited_allocated_bytes); }
static void incr_exited_allocated_bytes(uint64_t size) {
// No need for an atomic add because called under the Threads_lock,
// but because _exited_allocated_bytes is read concurrently, need
// atomic store to avoid readers seeing a partial update.

View File

@ -408,7 +408,9 @@ AbstractRBTree<K, NodeType, COMPARATOR>::cursor(const K& key, const NodeType* hi
template <typename K, typename NodeType, typename COMPARATOR>
inline void AbstractRBTree<K, NodeType, COMPARATOR>::insert_at_cursor(NodeType* node, const Cursor& node_cursor) {
assert(node_cursor.valid() && !node_cursor.found(), "must be");
precond(node != nullptr);
precond(node_cursor.valid());
precond(!node_cursor.found());
_num_nodes++;
*node_cursor._insert_location = node;
@ -622,7 +624,8 @@ inline void AbstractRBTree<K, NodeType, COMPARATOR>::remove_from_tree(IntrusiveR
template <typename K, typename NodeType, typename COMPARATOR>
inline void AbstractRBTree<K, NodeType, COMPARATOR>::remove_at_cursor(const Cursor& node_cursor) {
assert(node_cursor.valid() && node_cursor.found(), "must be");
precond(node_cursor.valid());
precond(node_cursor.found());
_num_nodes--;
IntrusiveRBNode* node = node_cursor.node();
@ -718,7 +721,9 @@ AbstractRBTree<K, NodeType, COMPARATOR>::prev(const Cursor& node_cursor) const {
template <typename K, typename NodeType, typename COMPARATOR>
inline void AbstractRBTree<K, NodeType, COMPARATOR>::replace_at_cursor(NodeType* new_node, const Cursor& node_cursor) {
assert(node_cursor.valid() && node_cursor.found(), "must be");
precond(new_node != nullptr);
precond(node_cursor.valid());
precond(node_cursor.found());
NodeType* old_node = node_cursor.node();
if (old_node == new_node) {
return;
@ -785,12 +790,14 @@ inline NodeType* AbstractRBTree<K, NodeType, COMPARATOR>::find_node(const K& key
template <typename K, typename NodeType, typename COMPARATOR>
inline void AbstractRBTree<K, NodeType, COMPARATOR>::insert(const K& key, NodeType* node, const NodeType* hint_node) {
precond(node != nullptr);
Cursor node_cursor = cursor(key, hint_node);
insert_at_cursor(node, node_cursor);
}
template <typename K, typename NodeType, typename COMPARATOR>
inline void AbstractRBTree<K, NodeType, COMPARATOR>::remove(NodeType* node) {
precond(node != nullptr);
Cursor node_cursor = cursor(node);
remove_at_cursor(node_cursor);
}
@ -1049,9 +1056,9 @@ inline RBTree<K, V, COMPARATOR, ALLOCATOR>::~RBTree() {
template<typename K, typename V, typename COMPARATOR, typename ALLOCATOR>
bool RBTree<K, V, COMPARATOR, ALLOCATOR>::copy_into(RBTree& other) const {
assert(other.size() == 0, "You can only copy into an empty RBTree");
assert(std::is_copy_constructible<K>::value, "Key type must be copy-constructible when copying a RBTree");
assert(std::is_copy_constructible<V>::value, "Value type must be copy-constructible when copying a RBTree");
precond(other.size() == 0);
precond(std::is_copy_constructible<K>::value);
precond(std::is_copy_constructible<V>::value);
enum class Dir { Left, Right };
struct node_pair { const IntrusiveRBNode* current; IntrusiveRBNode* other_parent; Dir dir; };
struct stack {
@ -1098,6 +1105,9 @@ bool RBTree<K, V, COMPARATOR, ALLOCATOR>::copy_into(RBTree& other) const {
template <typename K, typename V, typename COMPARATOR, typename ALLOCATOR>
inline void RBTree<K, V, COMPARATOR, ALLOCATOR>::replace_at_cursor(RBNode<K, V>* new_node, const Cursor& node_cursor) {
precond(new_node != nullptr);
precond(node_cursor.valid());
precond(node_cursor.found());
RBNode<K, V>* old_node = node_cursor.node();
BaseType::replace_at_cursor(new_node, node_cursor);
free_node(old_node);
@ -1123,6 +1133,7 @@ inline RBNode<K, V>* RBTree<K, V, COMPARATOR, ALLOCATOR>::allocate_node(const K&
template <typename K, typename V, typename COMPARATOR, typename ALLOCATOR>
inline void RBTree<K, V, COMPARATOR, ALLOCATOR>::free_node(RBNode<K, V>* node) {
precond(node != nullptr);
node->_value.~V();
_allocator.free(node);
}

View File

@ -3607,4 +3607,52 @@ final class FdLibm {
}
}
}
/**
* Return the Inverse Hyperbolic Tangent of x
* Method :
*
*
* atanh(x) is defined so that atanh(tanh(alpha)) = alpha, -&infin; &lt; alpha &lt; &infin;
* and tanh(atanh(x)) = x, -1 &lt x &lt 1;
* It can be written as atanh(x) = 0.5 * log1p(2 * x/(1-x)), -1 &lt; x &lt; 1;
* 1.
* atanh(x) := 0.5 * log1p(2 * x/(1 - x)), if |x| >= 0.5,
* := 0.5 * log1p(2x + 2x * x/(1 - x)), if |x| < 0.5.
*
*
*
* Special cases:
* only atanh(&plusmn;0)=&plusmn;0 is exact for finite x.
* atanh(NaN) is NaN
* atanh(&plusmn;1) is &plusmn;&infin;
*/
static final class Atanh {
static double compute(double x) {
double t;
int hx,ix;
int lx; // unsigned
hx = __HI(x); // high word
lx = __LO(x); // low word
ix = hx & 0x7fff_ffff;
if ((ix | ((lx | (-lx)) >>> 31)) > 0x3ff0_0000) { // |x| > 1
return (x - x) / (x - x);
}
if (ix == 0x3ff0_0000) {
return x / 0.0;
}
if (ix < 0x3e30_0000 && (HUGE + x) > 0.0) {
return x; // x<2**-28
}
x = __HI(x, ix); // x <- |x|
if (ix < 0x3fe0_0000) { // x < 0.5
t = x + x;
t = 0.5 * Log1p.compute(t + t * x / (1.0 - x));
} else {
t = 0.5 * Log1p.compute((x + x) / (1.0 - x));
}
return hx >= 0 ? t : -t;
}
}
}

View File

@ -109,7 +109,7 @@ import static java.lang.Double.*;
* acos acos}, {@link atan atan}, {@link exp exp}, {@link expm1
* expm1}, {@link log log}, {@link log10 log10}, {@link log1p log1p},
* {@link sinh sinh}, {@link cosh cosh}, {@link tanh tanh}, {@link asinh asinh},
* {@link acosh acosh}, {@link hypot hypot}, and {@link pow pow}.
* {@link acosh acosh}, {@link atanh atanh}, {@link hypot hypot}, and {@link pow pow}.
* (The {@link sqrt sqrt} operation is a required part of IEEE 754
* from a different section of the standard.) The special case behavior
* of the recommended operations generally follows the guidance of the IEEE 754
@ -2814,6 +2814,38 @@ public final class Math {
return StrictMath.acosh(x);
}
/**
* Returns the inverse hyperbolic tangent of a {@code double} value.
* The inverse hyperbolic tangent of <i>x</i> is defined to be the function such that
* atanh({@linkplain Math#tanh tanh(<i>x</i>)}) = <i>x</i> for any <i>x</i>.
* Note that the domain of the exact atanh is (-1; 1), the range is unrestricted.
*
* <p>Special cases:
* <ul>
*
* <li>If the argument is NaN, then the result is NaN.
*
* <li>If the argument is zero, then the result is a zero with the
* same sign as the argument.
*
* <li>If the argument is {@code +1.0}, then the result is
* positive infinity.
*
* <li>If the argument is {@code -1.0}, then the result is
* negative infinity.
*
* <li>If the argument is greater than {@code 1.0} in magnitude, then the result is NaN.
*
* </ul>
* <p> The computed result must be within 2.5 ulps of the exact result.
* @param x The number whose inverse hyperbolic tangent is to be returned.
* @return The inverse hyperbolic tangent of {@code x}.
* @since 27
*/
public static double atanh(double x) {
return StrictMath.atanh(x);
}
/**
* Returns sqrt(<i>x</i><sup>2</sup>&nbsp;+<i>y</i><sup>2</sup>)
* without intermediate overflow or underflow.

View File

@ -76,8 +76,8 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
* {@code exp}, {@code log}, {@code log10},
* {@code cbrt}, {@code atan2}, {@code pow},
* {@code sinh}, {@code cosh}, {@code tanh},
* {@code asinh}, {@code acosh}, {@code hypot},
* {@code expm1}, and {@code log1p}.
* {@code asinh}, {@code acosh},{@code atanh},
* {@code hypot}, {@code expm1}, and {@code log1p}.
*
* <p>
* The platform uses signed two's complement integer arithmetic with
@ -2222,6 +2222,38 @@ public final class StrictMath {
return FdLibm.Acosh.compute(x);
}
/**
* Returns the inverse hyperbolic tangent of a {@code double} value.
* The inverse hyperbolic tangent of <i>x</i> is defined to be the function such that
* atanh({@linkplain Math#tanh tanh(<i>x</i>)}) = <i>x</i> for any <i>x</i>.
* Note that the domain of the exact atanh is (-1; 1), the range is unrestricted.
*
* <p>Special cases:
* <ul>
*
* <li>If the argument is NaN, then the result is NaN.
*
* <li>If the argument is zero, then the result is a zero with the
* same sign as the argument.
*
* <li>If the argument is {@code +1.0}, then the result is
* positive infinity.
*
* <li>If the argument is {@code -1.0}, then the result is
* negative infinity.
*
* <li>If the argument is greater than {@code 1.0} in magnitude, then the result is NaN.
*
* </ul>
*
* @param x The number whose inverse hyperbolic tangent is to be returned.
* @return The inverse hyperbolic tangent of {@code x}.
* @since 27
*/
public static double atanh(double x) {
return FdLibm.Atanh.compute(x);
}
/**
* Returns sqrt(<i>x</i><sup>2</sup>&nbsp;+<i>y</i><sup>2</sup>)
* without intermediate overflow or underflow.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,7 @@ package java.lang;
import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
@ -39,12 +40,22 @@ import jdk.internal.vm.annotation.IntrinsicCandidate;
import static java.lang.String.LATIN1;
import static java.lang.String.UTF16;
import static java.lang.String.checkIndex;
import static java.lang.String.checkOffset;
/**
* Latin-1 string operations.
* <p>
* Unless stated otherwise, all methods assume that
* <ul>
* <li>{@code byte[]} arguments denote a Latin-1 string byte array
* <li>indices, offsets, and lengths (typically of type {@code int}) are in
* number of characters, i.e., the number of {@code byte}s/{@code char}s for
* Latin-1 strings, and the number of <a href="Character.html#unicode">Unicode
* code units</a> for UTF-16 strings
* </ul>
*/
final class StringLatin1 {
static char charAt(byte[] value, int index) {
checkIndex(index, value.length);
String.checkIndex(index, value.length);
return (char)(value[index] & 0xff);
}
@ -84,8 +95,23 @@ final class StringLatin1 {
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
@IntrinsicCandidate
/**
* {@return {@code true} if provided byte arrays contain identical content; {@code false} otherwise}.
*
* @param value a byte array
* @param other a byte array
*
* @throws NullPointerException if {@code value} or {@code other} is null
*/
static boolean equals(byte[] value, byte[] other) {
Objects.requireNonNull(value);
Objects.requireNonNull(other);
return equals0(value, other);
}
// vmIntrinsics::_equalsL
@IntrinsicCandidate
private static boolean equals0(byte[] value, byte[] other) {
if (value.length == other.length) {
for (int i = 0; i < value.length; i++) {
if (value[i] != other[i]) {
@ -97,33 +123,102 @@ final class StringLatin1 {
return false;
}
@IntrinsicCandidate
/**
* Lexicographically compares two Latin-1 strings as specified in
* {@link String#compareTo(String) String::compareTo}.
*
* @param value a Latin-1 string byte array
* @param other a Latin-1 string byte array
*
* @return {@code 0} if {@code value} is equal to {@code other}, a value
* less than {@code 0} if {@code value} is lexicographically less than
* {@code other}; a value greater than {@code 0} otherwise.
*
* @throws NullPointerException if {@code value} or {@code other} is null
*/
static int compareTo(byte[] value, byte[] other) {
int len1 = value.length;
int len2 = other.length;
return compareTo(value, other, len1, len2);
Objects.requireNonNull(value);
Objects.requireNonNull(other);
return compareTo0(value, other);
}
// vmIntrinsics::_compareToL
@IntrinsicCandidate
private static int compareTo0(byte[] value, byte[] other) {
return compareTo(value, other, value.length, other.length);
}
/**
* Lexicographically compares two Latin-1 string prefixes as specified in
* {@link String#compareTo(String) String::compareTo}.
*
* @param value a Latin-1 string byte array
* @param other a Latin-1 string byte array
* @param len1 the number of characters in {@code value} to compare
* @param len2 the number of characters in {@code other} to compare
*
* @return {@code 0} if the {@code value} prefix is equal to the
* {@code other} prefix, a value less than {@code 0} if the {@code value}
* prefix is lexicographically less than the {@code other} prefix; a
* value greater than {@code 0} otherwise.
*
* @throws NullPointerException if {@code value} or {@code other} is null
* @throws StringIndexOutOfBoundsException if the sub-ranges are out of bounds
*/
static int compareTo(byte[] value, byte[] other, int len1, int len2) {
Objects.requireNonNull(value);
Objects.requireNonNull(other);
String.checkOffset(len1, length(value));
String.checkOffset(len2, length(other));
int lim = Math.min(len1, len2);
int k = ArraysSupport.mismatch(value, other, lim);
return (k < 0) ? len1 - len2 : getChar(value, k) - getChar(other, k);
}
@IntrinsicCandidate
/**
* Lexicographically compares a Latin-1 string to a UTF-16 string as
* specified in {@link String#compareTo(String) String::compareTo}.
*
* @param value a Latin-1 string byte array
* @param other a UTF-16 string byte array
*
* @return {@code 0} if the {@code value} is equal to the {@code other}, a
* value less than {@code 0} if the {@code value} is lexicographically less
* than the {@code other}; a value greater than {@code 0} otherwise.
*
* @throws NullPointerException if {@code value} or {@code other} is null
*/
static int compareToUTF16(byte[] value, byte[] other) {
Objects.requireNonNull(value);
Objects.requireNonNull(other);
return compareToUTF16_0(value, other);
}
// vmIntrinsics::_compareToLU
@IntrinsicCandidate
private static int compareToUTF16_0(byte[] value, byte[] other) {
int len1 = length(value);
int len2 = StringUTF16.length(other);
return compareToUTF16Values(value, other, len1, len2);
}
/*
* Checks the boundary and then compares the byte arrays.
/**
* Lexicographically compares a Latin-1 string prefix to a UTF-16 one as
* specified in {@link String#compareTo(String) String::compareTo}.
*
* @param value a Latin-1 string byte array
* @param other a UTF-16 string byte array
* @param len1 the number of characters in {@code value} to compare
* @param len2 the number of characters in {@code other} to compare
*
* @throws NullPointerException if {@code value} or {@code other} is null
* @throws StringIndexOutOfBoundsException if the sub-ranges are out of bounds
*/
static int compareToUTF16(byte[] value, byte[] other, int len1, int len2) {
checkOffset(len1, length(value));
checkOffset(len2, StringUTF16.length(other));
Objects.requireNonNull(value);
Objects.requireNonNull(other);
String.checkOffset(len1, length(value));
String.checkOffset(len2, StringUTF16.length(other));
return compareToUTF16Values(value, other, len1, len2);
}
@ -139,9 +234,12 @@ final class StringLatin1 {
return len1 - len2;
}
/**
* Case-insensitive {@link #compareTo(byte[], byte[]) compareTo}.
*/
static int compareToCI(byte[] value, byte[] other) {
int len1 = value.length;
int len2 = other.length;
int len1 = value.length; // Implicit null check on `value`
int len2 = other.length; // Implicit null check on `other`
int lim = Math.min(len1, len2);
for (int k = 0; k < lim; k++) {
if (value[k] != other[k]) {
@ -159,7 +257,12 @@ final class StringLatin1 {
return len1 - len2;
}
/**
* Case-insensitive {@link #compareToUTF16(byte[], byte[]) compareToUTF16}.
*/
static int compareToCI_UTF16(byte[] value, byte[] other) {
Objects.requireNonNull(value);
Objects.requireNonNull(other);
int len1 = length(value);
int len2 = StringUTF16.length(other);
int lim = Math.min(len1, len2);
@ -307,16 +410,34 @@ final class StringLatin1 {
return ArraysSupport.hashCodeOfUnsigned(value, 0, value.length, 0);
}
// Caller must ensure that from- and toIndex are within bounds
/**
* Finds the index of the first character matching the provided one in the
* given Latin-1 string byte array sub-range. {@code -1} is returned if the
* provided character cannot be encoded in Latin-1, or cannot be found in
* the target string sub-range.
*
* @param value a Latin-1 string byte array to search in
* @param ch a character to search for
* @param fromIndex the index (inclusive) of the first character in the sub-range
* @param toIndex the index (exclusive) of the last character in the sub-range
*
* @return the index of the first character matching the provided one in the
* given target string sub-range; {@code -1} otherwise
*
* @throws NullPointerException if {@code value} is null
* @throws StringIndexOutOfBoundsException if the sub-range is out of bounds
*/
static int indexOf(byte[] value, int ch, int fromIndex, int toIndex) {
String.checkBoundsBeginEnd(fromIndex, toIndex, value.length); // Implicit null check on `value`
if (!canEncode(ch)) {
return -1;
}
return indexOfChar(value, ch, fromIndex, toIndex);
return indexOfChar0(value, ch, fromIndex, toIndex);
}
// vmIntrinsics::_indexOfL_char
@IntrinsicCandidate
private static int indexOfChar(byte[] value, int ch, int fromIndex, int max) {
private static int indexOfChar0(byte[] value, int ch, int fromIndex, int max) {
byte c = (byte)ch;
for (int i = fromIndex; i < max; i++) {
if (value[i] == c) {
@ -326,22 +447,67 @@ final class StringLatin1 {
return -1;
}
@IntrinsicCandidate
/**
* Searches for the first occurrence of {@code str} in {@code value}, and,
* if found, returns the index of the first character of the matching
* {@code value} sub-range; {@code -1} otherwise.
*
* @param value a Latin-1 string byte array to search in
* @param str a Latin-1 string byte array to search for
*
* @return the index of the first character of the matching {@code value}
* sub-range if a match is found; {@code -1} otherwise
*
* @throws NullPointerException if {@code value} or {@code str} is null
*/
static int indexOf(byte[] value, byte[] str) {
if (str.length == 0) {
return 0;
}
if (value.length == 0) {
return -1;
}
return indexOf(value, value.length, str, str.length, 0);
Objects.requireNonNull(value);
Objects.requireNonNull(str);
return indexOf0(value, str);
}
// vmIntrinsics::_indexOfL
@IntrinsicCandidate
static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
private static int indexOf0(byte[] value, byte[] str) {
return indexOf0(value, value.length, str, str.length, 0);
}
/**
* Searches for the first occurrence of the given {@code str} sub-range in
* the given {@code value} sub-range, and, if found, returns the index of
* the first character of the matching {@code value} sub-range; {@code -1}
* otherwise.
*
* @param value a Latin-1 string byte array to search in
* @param valueToIndex the index (exclusive) of the last character in {@code value}
* @param str a Latin-1 string byte array to search for
* @param strToIndex the index (exclusive) of the last character in {@code str}
* @param valueFromIndex the index (inclusive) of the first character in {@code value}
*
* @return the index of the first character of the matching {@code value}
* sub-range if a match is found; {@code -1} otherwise
*
* @throws NullPointerException if {@code value} or {@code str} is null
* @throws StringIndexOutOfBoundsException if the sub-ranges are out of bounds
*/
static int indexOf(byte[] value, int valueToIndex, byte[] str, int strToIndex, int valueFromIndex) {
String.checkBoundsBeginEnd(valueFromIndex, valueToIndex, value.length); // Implicit null check on `value`
String.checkBoundsBeginEnd(0, strToIndex, str.length); // Implicit null check on `str`
return indexOf0(value, valueToIndex, str, strToIndex, valueFromIndex);
}
// vmIntrinsics::_indexOfIL
@IntrinsicCandidate
private static int indexOf0(byte[] value, int valueToIndex, byte[] str, int strToIndex, int valueFromIndex) {
if (strToIndex == 0) {
return 0;
}
if ((valueToIndex - valueFromIndex) < strToIndex) {
return -1;
}
byte first = str[0];
int max = (valueCount - strCount);
for (int i = fromIndex; i <= max; i++) {
int max = (valueToIndex - strToIndex);
for (int i = valueFromIndex; i <= max; i++) {
// Look for first character.
if (value[i] != first) {
while (++i <= max && value[i] != first);
@ -349,7 +515,7 @@ final class StringLatin1 {
// Found first character, now look at the rest of value
if (i <= max) {
int j = i + 1;
int end = j + strCount - 1;
int end = j + strToIndex - 1;
for (int k = 1; j < end && value[j] == str[k]; j++, k++);
if (j == end) {
// Found whole string.
@ -855,18 +1021,65 @@ final class StringLatin1 {
LATIN1);
}
// inflatedCopy byte[] -> char[]
@IntrinsicCandidate
/**
* Copies characters from a Latin-1 string byte array sub-range to the
* given {@code char} array sub-range.
* <p>
* This effectively <em>inflates</em> the content from a 1 byte per
* character representation to a 2 byte one.
*
* @param src the source Latin-1 string byte array
* @param srcOff the index (inclusive) of the first character in {@code src}
* @param dst the target {@code char} array
* @param dstOff the index (inclusive) of the first character in {@code dst}
* @param len the maximum number of characters to copy
*
* @throws NullPointerException if {@code src} or {@code dst} is null
* @throws StringIndexOutOfBoundsException if the sub-ranges are out of bounds
*/
static void inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
String.checkBoundsOffCount(srcOff, len, src.length); // Implicit null check on `src`
String.checkBoundsOffCount(dstOff, len, dst.length); // Implicit null check on `dst`
inflate0(src, srcOff, dst, dstOff, len);
}
// vmIntrinsics::_inflateStringC
@IntrinsicCandidate
private static void inflate0(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
for (int i = 0; i < len; i++) {
dst[dstOff++] = (char)(src[srcOff++] & 0xff);
}
}
// inflatedCopy byte[] -> byte[]
@IntrinsicCandidate
/**
* Copies characters from a Latin-1 string byte array sub-range to a UTF-16
* one.
* <p>
* This effectively <em>inflates</em> the content from a 1 byte per
* character representation to a 2 byte one.
*
* @param src the source Latin-1 string byte array
* @param srcOff the index (inclusive) of the first character in {@code src}
* @param dst the target UTF-16 string byte array
* @param dstOff the index (inclusive) of the first character in {@code dst}
* @param len the maximum number of characters to copy
*
* @throws NullPointerException if {@code src} or {@code dst} is null
* @throws StringIndexOutOfBoundsException if the sub-ranges are out of bounds
*/
static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
StringUTF16.inflate(src, srcOff, dst, dstOff, len);
String.checkBoundsOffCount(srcOff, len, src.length); // Implicit null check on `src`
Objects.requireNonNull(dst);
String.checkBoundsOffCount(dstOff, len, StringUTF16.length(dst));
inflate0(src, srcOff, dst, dstOff, len);
}
// vmIntrinsics::_inflateStringB
@IntrinsicCandidate
private static void inflate0(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
for (int i = 0; i < len; i++) {
StringUTF16.putChar(dst, dstOff++, src[srcOff++] & 0xff);
}
}
static class CharsSpliterator implements Spliterator.OfInt {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -28,6 +28,7 @@ package java.lang;
import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.function.IntConsumer;
@ -49,8 +50,13 @@ import static java.lang.String.UTF16;
/// it has the same endianness as a char, which is the platform endianness.
/// This is ensured in the static initializer of StringUTF16.
///
/// All indices and sizes for byte arrays carrying UTF16 data are in number of
/// chars instead of number of bytes.
/// Unless stated otherwise, all methods assume that
///
/// - `byte[]` arguments denote a UTF-16 string byte array
/// - indices, offsets, and lengths (typically of type `int`) are in number of
/// characters, i.e., the number of
/// [Unicode code units](Character.html#unicode) for UTF-16 strings, and the
/// number of `byte`s/`char`s for Latin-1 strings
final class StringUTF16 {
// Return a new byte array for a UTF16-coded string for len chars
@ -388,9 +394,33 @@ final class StringUTF16 {
return n;
}
// compressedCopy char[] -> byte[]
@IntrinsicCandidate
/**
* Copies the prefix of Latin-1 characters from a {@code char} array
* sub-range to a Latin-1 string byte array sub-range.
* <p>
* This effectively <em>compresses</em> the content from a 2 byte per
* character representation to a 1 byte one.
*
* @param src the source {@code char} array
* @param srcOff the index (inclusive) of the first character in {@code src}
* @param dst the target Latin-1 string byte array
* @param dstOff the index (inclusive) of the first character in {@code dst}
* @param len the maximum number of characters to copy
*
* @return the number of characters copied
*
* @throws NullPointerException if {@code src} or {@code dst} is null
* @throws StringIndexOutOfBoundsException if the sub-ranges are out of bounds
*/
static int compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) {
String.checkBoundsOffCount(srcOff, len, src.length); // Implicit null check on `src`
String.checkBoundsOffCount(dstOff, len, dst.length); // Implicit null check on `dst`
return compress0(src, srcOff, dst, dstOff, len);
}
// vmIntrinsics::_compressStringC
@IntrinsicCandidate
private static int compress0(char[] src, int srcOff, byte[] dst, int dstOff, int len) {
for (int i = 0; i < len; i++) {
char c = src[srcOff];
if (c > 0xff) {
@ -403,11 +433,34 @@ final class StringUTF16 {
return len;
}
// compressedCopy byte[] -> byte[]
@IntrinsicCandidate
/**
* Copies the prefix of Latin-1 characters from a UTF-16 string byte array
* sub-range to a Latin-1 one.
* <p>
* This effectively <em>compresses</em> the content from a 2 byte per
* character representation to a 1 byte one.
*
* @param src the source UTF-16 string byte array
* @param srcOff the index (inclusive) of the first character in {@code src}
* @param dst the target Latin-1 string byte array
* @param dstOff the index (inclusive) of the first character in {@code dst}
* @param len the maximum number of characters to copy
*
* @return the number of characters copied
*
* @throws NullPointerException if {@code src} or {@code dst} is null
* @throws StringIndexOutOfBoundsException if the sub-ranges are out of bounds
*/
static int compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
// We need a range check here because 'getChar' has no checks
checkBoundsOffCount(srcOff, len, src);
Objects.requireNonNull(src);
String.checkBoundsOffCount(srcOff, len, length(src));
String.checkBoundsOffCount(dstOff, len, dst.length); // Implicit null check on `dst`
return compress0(src, srcOff, dst, dstOff, len);
}
// vmIntrinsics::_compressStringB
@IntrinsicCandidate
private static int compress0(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
for (int i = 0; i < len; i++) {
char c = getChar(src, srcOff);
if (c > 0xff) {
@ -446,7 +499,7 @@ final class StringUTF16 {
static void getChars(byte[] value, int srcBegin, int srcEnd, char[] dst, int dstBegin) {
// We need a range check here because 'getChar' has no checks
if (srcBegin < srcEnd) {
checkBoundsOffCount(srcBegin, srcEnd - srcBegin, value);
String.checkBoundsOffCount(srcBegin, srcEnd - srcBegin, length(value));
}
for (int i = srcBegin; i < srcEnd; i++) {
dst[dstBegin++] = getChar(value, i);
@ -462,20 +515,50 @@ final class StringUTF16 {
}
}
@IntrinsicCandidate
/**
* Lexicographically compares two UTF-16 strings as specified in
* {@link String#compareTo(String) String::compareTo}.
*
* @param value a UTF-16 string byte array
* @param other a UTF-16 string byte array
*
* @return {@code 0} if {@code value} is equal to {@code other}, a value
* less than {@code 0} if {@code value} is lexicographically less than
* {@code other}; a value greater than {@code 0} otherwise.
*
* @throws NullPointerException if {@code value} or {@code other} is null
*/
static int compareTo(byte[] value, byte[] other) {
Objects.requireNonNull(value);
Objects.requireNonNull(other);
return compareTo0(value, other);
}
// vmIntrinsics::_compareToU
@IntrinsicCandidate
private static int compareTo0(byte[] value, byte[] other) {
int len1 = length(value);
int len2 = length(other);
return compareValues(value, other, len1, len2);
}
/*
* Checks the boundary and then compares the byte arrays.
/**
* Lexicographically compares two UTF-16 string prefixes as specified in
* {@link String#compareTo(String) String::compareTo}.
*
* @param value a UTF-16 string byte array
* @param other a UTF-16 string byte array
* @param len1 the number of characters in {@code value} to compare
* @param len2 the number of characters in {@code other} to compare
*
* @throws NullPointerException if {@code value} or {@code other} is null
* @throws StringIndexOutOfBoundsException if the sub-ranges are out of bounds
*/
static int compareTo(byte[] value, byte[] other, int len1, int len2) {
Objects.requireNonNull(value);
Objects.requireNonNull(other);
checkOffset(len1, value);
checkOffset(len2, other);
return compareValues(value, other, len1, len2);
}
@ -491,16 +574,58 @@ final class StringUTF16 {
return len1 - len2;
}
@IntrinsicCandidate
/**
* Lexicographically compares a UTF-16 string to a Latin-1 one as specified
* in {@link String#compareTo(String) String::compareTo}.
*
* @param value a UTF-16 string byte array
* @param other a Latin-1 string byte array
*
* @return {@code 0} if {@code value} is equal to {@code other}, a value
* less than {@code 0} if {@code value} is lexicographically less than
* {@code other}; a value greater than {@code 0} otherwise.
*
* @throws NullPointerException if {@code value} or {@code other} is null
*/
static int compareToLatin1(byte[] value, byte[] other) {
Objects.requireNonNull(value);
Objects.requireNonNull(other);
return compareToLatin1_0(value, other);
}
// vmIntrinsics::_compareToUL
@IntrinsicCandidate
private static int compareToLatin1_0(byte[] value, byte[] other) {
return -StringLatin1.compareToUTF16(other, value);
}
/**
* Lexicographically compares a UTF-16 string prefix to a Latin-1 one as
* specified in {@link String#compareTo(String) String::compareTo}.
*
* @param value a UTF-16 string byte array
* @param other a Latin-1 string byte array
* @param len1 the number of characters from {@code value} to compare
* @param len2 the number of characters from {@code other} to compare
*
* @return {@code 0} if the {@code value} prefix is equal to the
* {@code other} prefix, a value less than {@code 0} if the {@code value}
* prefix is lexicographically less than the {@code other} prefix; a
* value greater than {@code 0} otherwise.
*
* @throws NullPointerException if {@code value} or {@code other} is null
* @throws StringIndexOutOfBoundsException if the sub-ranges are out of bounds
*/
static int compareToLatin1(byte[] value, byte[] other, int len1, int len2) {
return -StringLatin1.compareToUTF16(other, value, len2, len1);
}
/**
* Case-insensitive {@link #compareTo(byte[], byte[]) compareTo}.
*/
static int compareToCI(byte[] value, byte[] other) {
Objects.requireNonNull(value);
Objects.requireNonNull(other);
return compareToCIImpl(value, 0, length(value), other, 0, length(other));
}
@ -589,6 +714,9 @@ final class StringUTF16 {
return cp;
}
/**
* Case-insensitive {@link #compareToLatin1(byte[], byte[]) compareToLatin1}.
*/
static int compareToCI_Latin1(byte[] value, byte[] other) {
return -StringLatin1.compareToCI_UTF16(other, value);
}
@ -668,19 +796,52 @@ final class StringUTF16 {
return ArraysSupport.hashCodeOfUTF16(value, 0, value.length >> 1, 0);
}
// Caller must ensure that from- and toIndex are within bounds
/**
* {@return the index of the first character matching the provided one in
* the given UTF-16 string byte array sub-range; {@code -1} otherwise}
*
* @param value a UTF-16 string byte array to search in
* @param ch a character to search for
* @param fromIndex the index (inclusive) of the first character in the sub-range
* @param toIndex the index (exclusive) of the last character in the sub-range
*
* @throws NullPointerException if {@code value} is null
* @throws StringIndexOutOfBoundsException if the sub-range is out of bounds
*/
static int indexOf(byte[] value, int ch, int fromIndex, int toIndex) {
Objects.requireNonNull(value);
checkBoundsBeginEnd(fromIndex, toIndex, value);
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
return indexOfChar(value, ch, fromIndex, toIndex);
return indexOfChar0(value, ch, fromIndex, toIndex);
} else {
return indexOfSupplementary(value, ch, fromIndex, toIndex);
}
}
@IntrinsicCandidate
/**
* Searches for the first occurrence of {@code str} in {@code value}, and,
* if found, returns the index of the first character of the matching
* {@code value} sub-range; {@code -1} otherwise.
*
* @param value a UTF-16 string byte array to search in
* @param str a UTF-16 string byte array to search for
*
* @return the index of the first character of the matching {@code value}
* sub-range if a match is found; {@code -1} otherwise
*
* @throws NullPointerException if {@code value} or {@code str} is null
*/
static int indexOf(byte[] value, byte[] str) {
Objects.requireNonNull(value);
Objects.requireNonNull(str);
return indexOf0(value, str);
}
// vmIntrinsics::_indexOfU
@IntrinsicCandidate
private static int indexOf0(byte[] value, byte[] str) {
if (str.length == 0) {
return 0;
}
@ -690,22 +851,58 @@ final class StringUTF16 {
return indexOfUnsafe(value, length(value), str, length(str), 0);
}
@IntrinsicCandidate
static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
checkBoundsBeginEnd(fromIndex, valueCount, value);
checkBoundsBeginEnd(0, strCount, str);
return indexOfUnsafe(value, valueCount, str, strCount, fromIndex);
/**
* Searches for the first occurrence of the given {@code str} sub-range in
* the given {@code value} sub-range, and, if found, returns the index of
* the first character of the matching {@code value} sub-range; {@code -1}
* otherwise.
*
* @param value a UTF-16 string byte array to search in
* @param valueToIndex the index (exclusive) of the last character in {@code value}
* @param str a UTF-16 string byte array to search for
* @param strToIndex the index (exclusive) of the last character in {@code str}
* @param valueFromIndex the index (inclusive) of the first character in {@code value}
*
* @return the index of the first character of the matching {@code value}
* sub-range if a match is found; {@code -1} otherwise
*
* @throws NullPointerException if {@code value} or {@code str} is null
* @throws StringIndexOutOfBoundsException if the sub-ranges are out of bounds
*/
static int indexOf(byte[] value, int valueToIndex, byte[] str, int strToIndex, int valueFromIndex) {
Objects.requireNonNull(value);
checkBoundsBeginEnd(valueFromIndex, valueToIndex, value);
Objects.requireNonNull(str);
checkBoundsBeginEnd(0, strToIndex, str);
return indexOf0(value, valueToIndex, str, strToIndex, valueFromIndex);
}
// vmIntrinsics::_indexOfIU
@IntrinsicCandidate
private static int indexOf0(byte[] value, int valueToIndex, byte[] str, int strToIndex, int valueFromIndex) {
if (strToIndex == 0) {
return 0;
}
if ((valueToIndex - valueFromIndex) < strToIndex) {
return -1;
}
return indexOfUnsafe(value, valueToIndex, str, strToIndex, valueFromIndex);
}
private static int indexOfUnsafe(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
assert fromIndex >= 0;
assert strCount > 0;
assert strCount <= length(str);
assert valueCount >= strCount;
// This method has the following assumptions on its inputs:
//
// - Arrays are not null
// - Sub-ranges are valid
// - The `str` sub-range is not empty
// - The `value` sub-range length is greater than or equal to the `str` sub-range length
private static int indexOfUnsafe(byte[] value, int valueToIndex, byte[] str, int strToIndex, int valueFromIndex) {
assert valueFromIndex >= 0;
assert strToIndex > 0;
assert strToIndex <= length(str);
assert (valueToIndex - valueFromIndex) >= strToIndex;
char first = getChar(str, 0);
int max = (valueCount - strCount);
for (int i = fromIndex; i <= max; i++) {
int max = (valueToIndex - strToIndex);
for (int i = valueFromIndex; i <= max; i++) {
// Look for first character.
if (getChar(value, i) != first) {
while (++i <= max && getChar(value, i) != first);
@ -713,7 +910,7 @@ final class StringUTF16 {
// Found first character, now look at the rest of value
if (i <= max) {
int j = i + 1;
int end = j + strCount - 1;
int end = j + strToIndex - 1;
for (int k = 1; j < end && getChar(value, j) == getChar(str, k); j++, k++);
if (j == end) {
// Found whole string.
@ -724,12 +921,29 @@ final class StringUTF16 {
return -1;
}
/**
* Handles indexOf Latin1 substring in UTF16 string.
* Searches for the first occurrence of the given Latin-1 string byte array
* {@code str} in the given UTF-16 string byte array {@code value}, and, if
* found, returns the index of the first character of the matching
* {@code value} sub-range; {@code -1} otherwise.
*
* @param value a UTF-16 string byte array to search in
* @param str a Latin-1 string byte array to search for
*
* @return the index of the first character of the matching {@code value}
* sub-range if a match is found; {@code -1} otherwise
*
* @throws NullPointerException if {@code value} or {@code str} is null
*/
@IntrinsicCandidate
static int indexOfLatin1(byte[] value, byte[] str) {
Objects.requireNonNull(value);
Objects.requireNonNull(str);
return indexOfLatin1_0(value, str);
}
// vmIntrinsics::_indexOfUL
@IntrinsicCandidate
private static int indexOfLatin1_0(byte[] value, byte[] str) {
if (str.length == 0) {
return 0;
}
@ -739,18 +953,54 @@ final class StringUTF16 {
return indexOfLatin1Unsafe(value, length(value), str, str.length, 0);
}
@IntrinsicCandidate
static int indexOfLatin1(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
checkBoundsBeginEnd(fromIndex, srcCount, src);
String.checkBoundsBeginEnd(0, tgtCount, tgt.length);
return indexOfLatin1Unsafe(src, srcCount, tgt, tgtCount, fromIndex);
/**
* Searches for the first occurrence of the given Latin-1 string byte array
* {@code tgt} sub-range in the given UTF-16 string byte array {@code src}
* sub-range, and, if found, returns the index of the first character in
* {@code src}; {@code -1} otherwise.
*
* @param src a UTF-16 string byte array to search in
* @param srcToIndex the index (exclusive) of the last character in {@code src}
* @param tgt a Latin-1 string byte array to search for
* @param tgtToIndex the index (exclusive) of the last character in {@code tgt}
* @param tgtFromIndex the index (inclusive) of the first character in {@code src}
*
* @return the index of the first character of the matching {@code src}
* sub-range if a match is found; {@code -1} otherwise
*
* @throws NullPointerException if {@code src} or {@code tgt} is null
* @throws StringIndexOutOfBoundsException if the sub-ranges are out of bounds
*/
static int indexOfLatin1(byte[] src, int srcToIndex, byte[] tgt, int tgtToIndex, int tgtFromIndex) {
Objects.requireNonNull(src);
checkBoundsBeginEnd(tgtFromIndex, srcToIndex, src);
String.checkBoundsBeginEnd(0, tgtToIndex, tgt.length);
return indexOfLatin1_0(src, srcToIndex, tgt, tgtToIndex, tgtFromIndex);
}
static int indexOfLatin1Unsafe(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
// vmIntrinsics::_indexOfIUL
@IntrinsicCandidate
private static int indexOfLatin1_0(byte[] src, int srcToIndex, byte[] tgt, int tgtToIndex, int srcFromIndex) {
if (tgtToIndex == 0) {
return 0;
}
if ((srcToIndex - srcFromIndex) < tgtToIndex) {
return -1;
}
return indexOfLatin1Unsafe(src, srcToIndex, tgt, tgtToIndex, srcFromIndex);
}
// This method has the following assumptions on its inputs:
//
// - Arrays are not null
// - Sub-ranges are valid
// - The `tgt` sub-range is not empty
// - The `src` sub-range length is greater than or equal to the `tgt` sub-range length
private static int indexOfLatin1Unsafe(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
assert fromIndex >= 0;
assert tgtCount > 0;
assert tgtCount <= tgt.length;
assert srcCount >= tgtCount;
assert (srcCount - fromIndex) >= tgtCount;
char first = (char)(tgt[0] & 0xff);
int max = (srcCount - tgtCount);
for (int i = fromIndex; i <= max; i++) {
@ -774,8 +1024,9 @@ final class StringUTF16 {
return -1;
}
// vmIntrinsics::_indexOfU_char
@IntrinsicCandidate
private static int indexOfChar(byte[] value, int ch, int fromIndex, int max) {
private static int indexOfChar0(byte[] value, int ch, int fromIndex, int max) {
for (int i = fromIndex; i < max; i++) {
if (getChar(value, i) == ch) {
return i;
@ -1590,7 +1841,7 @@ final class StringUTF16 {
}
static boolean contentEquals(byte[] v1, byte[] v2, int len) {
checkBoundsOffCount(0, len, v2);
String.checkBoundsOffCount(0, len, length(v2));
for (int i = 0; i < len; i++) {
if ((char)(v1[i] & 0xff) != getChar(v2, i)) {
return false;
@ -1667,15 +1918,6 @@ final class StringUTF16 {
}
}
// inflatedCopy byte[] -> byte[]
static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
// We need a range check here because 'putChar' has no checks
checkBoundsOffCount(dstOff, len, dst);
for (int i = 0; i < len; i++) {
putChar(dst, dstOff++, src[srcOff++] & 0xff);
}
}
// srcCoder == UTF16 && tgtCoder == LATIN1
static int lastIndexOfLatin1(byte[] src, int srcCount,
byte[] tgt, int tgtCount, int fromIndex) {
@ -1742,8 +1984,4 @@ final class StringUTF16 {
String.checkBoundsBeginEnd(begin, end, length(val));
}
static void checkBoundsOffCount(int offset, int count, byte[] val) {
String.checkBoundsOffCount(offset, count, length(val));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,7 +32,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.CharBuffer;
@ -800,7 +800,7 @@ public final class Scanner implements Iterator<String>, Closeable {
* @param source A string to scan
*/
public Scanner(String source) {
this(new StringReader(source), WHITESPACE_PATTERN);
this(Reader.of(source), WHITESPACE_PATTERN);
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, 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
@ -2138,10 +2138,12 @@ public class TreeMap<K,V>
return null;
}
public void forEachRemaining(Consumer<? super K> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
public boolean tryAdvance(Consumer<? super K> action) {
Objects.requireNonNull(action);
if (hasNext()) {
action.accept(next());
return true;
@ -2176,10 +2178,12 @@ public class TreeMap<K,V>
return null;
}
public void forEachRemaining(Consumer<? super K> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
public boolean tryAdvance(Consumer<? super K> action) {
Objects.requireNonNull(action);
if (hasNext()) {
action.accept(next());
return true;

View File

@ -30,10 +30,12 @@ import java.net.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.security.cert.Certificate;
import java.util.*;
import java.util.jar.*;
import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;
import java.security.CodeSigner;
import sun.net.www.ParseUtil;
/* URL jar file is a common JarFile subtype used for JarURLConnection */
@ -163,9 +165,11 @@ public class URLJarFile extends JarFile {
}
private class URLJarFileEntry extends JarEntry {
private final JarEntry je;
URLJarFileEntry(JarEntry je) {
super(je);
this.je = je;
}
@Override
@ -180,6 +184,30 @@ public class URLJarFile extends JarFile {
}
return null;
}
@Override
public Certificate[] getCertificates() {
// super.getCertificates() returns Certificates that were
// captured by reading the "JarEntry.certs" field when
// the super instance was created. Some JarEntry
// implementations (like java.util.jar.JarFile$JarFileEntry)
// compute certificates lazily, so we explicitly
// call getCertificates() on the underlying JarEntry instead of
// super.getCertificates()
return je.getCertificates();
}
@Override
public CodeSigner[] getCodeSigners() {
// super.getCodeSigners() returns CodeSigners that were
// captured by reading the "JarEntry.signers" field when
// the super instance was created. Some JarEntry
// implementations (like java.util.jar.JarFile$JarFileEntry)
// compute codesigners lazily, so we explicitly
// call getCodeSigners() on the underlying JarEntry instead of
// super.getCodeSigners()
return je.getCodeSigners();
}
}
public interface URLJarFileCloseController {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2026, 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,9 +25,7 @@
package sun.nio.fs;
import java.lang.ref.Cleaner.Cleanable;
import jdk.internal.misc.Unsafe;
import jdk.internal.ref.CleanerFactory;
/**
* A light-weight buffer in native memory.
@ -38,27 +36,17 @@ class NativeBuffer implements AutoCloseable {
private final long address;
private final int size;
private final Cleanable cleanable;
// optional "owner" to avoid copying
// (only safe for use by thread-local caches)
private Object owner;
private static class Deallocator implements Runnable {
private final long address;
Deallocator(long address) {
this.address = address;
}
public void run() {
unsafe.freeMemory(address);
}
}
// owner thread ID
private long ownerTid;
NativeBuffer(int size) {
this.address = unsafe.allocateMemory(size);
this.size = size;
this.cleanable = CleanerFactory.cleaner()
.register(this, new Deallocator(address));
}
@Override
@ -79,16 +67,26 @@ class NativeBuffer implements AutoCloseable {
}
void free() {
cleanable.clean();
unsafe.freeMemory(address);
}
// not synchronized; only safe for use by thread-local caches
void setOwner(Object owner) {
Thread thread = Thread.currentThread();
assert !thread.isVirtual();
assert ownerTid == 0 || ownerTid == thread.threadId();
this.owner = owner;
this.ownerTid = (owner != null) ? thread.threadId() : 0;
}
// not synchronized; only safe for use by thread-local caches
Object owner() {
return owner;
long tid = Thread.currentThread().threadId();
assert ownerTid == 0 || ownerTid == tid;
if (ownerTid == tid) {
return owner;
} else {
return null;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2026, 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,7 +92,8 @@ class NativeBuffers {
static NativeBuffer getNativeBuffer(int size) {
NativeBuffer buffer = getNativeBufferFromCache(size);
if (buffer != null) {
buffer.setOwner(null);
if (!Thread.currentThread().isVirtual())
buffer.setOwner(null);
return buffer;
} else {
return allocNativeBuffer(size);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2026, 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
@ -47,7 +47,8 @@ class UnixNativeDispatcher {
return buffer;
}
NativeBuffers.copyCStringToNativeBuffer(cstr, buffer);
buffer.setOwner(path);
if (!Thread.currentThread().isVirtual())
buffer.setOwner(path);
return buffer;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2026, 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
@ -1085,7 +1085,8 @@ class WindowsNativeDispatcher {
unsafe.copyMemory(chars, Unsafe.ARRAY_CHAR_BASE_OFFSET, null,
buffer.address(), (long)stringLengthInBytes);
unsafe.putChar(buffer.address() + stringLengthInBytes, (char)0);
buffer.setOwner(s);
if (!Thread.currentThread().isVirtual())
buffer.setOwner(s);
return buffer;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2026, 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
@ -132,7 +132,7 @@ static jobject sAccessibilityClass = NULL;
[rolesMap setObject:@"ImageAccessibility" forKey:@"icon"];
[rolesMap setObject:@"ImageAccessibility" forKey:@"desktopicon"];
[rolesMap setObject:@"SpinboxAccessibility" forKey:@"spinbox"];
[rolesMap setObject:@"StaticTextAccessibility" forKey:@"hyperlink"];
[rolesMap setObject:@"LinkAccessibility" forKey:@"hyperlink"];
[rolesMap setObject:@"StaticTextAccessibility" forKey:@"label"];
[rolesMap setObject:@"RadiobuttonAccessibility" forKey:@"radiobutton"];
[rolesMap setObject:@"CheckboxAccessibility" forKey:@"checkbox"];

View File

@ -1,10 +1,12 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2026, 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.
* 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
@ -19,21 +21,22 @@
* 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;
#ifndef LINK_ACCESSIBILITY
#define LINK_ACCESSIBILITY
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.*;
#import "CommonTextAccessibility.h"
public interface MethodDataInterface<K, M> {
K getKlassAtAddress(Address addr);
M getMethodAtAddress(Address addr);
void printKlassValueOn(K klass, PrintStream st);
void printMethodValueOn(M klass, PrintStream st);
}
#import <AppKit/NSAccessibility.h>
@interface LinkAccessibility : CommonTextAccessibility<NSAccessibilityStaticText> {
};
- (NSAccessibilityRole _Nonnull)accessibilityRole;
- (NSString * _Nullable)accessibilityAttributedStringForRange:(NSRange)range;
- (NSString * _Nullable)accessibilityValue;
- (NSRange)accessibilityVisibleCharacterRange;
@end
#endif

View File

@ -1,10 +1,12 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2026, 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.
* 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
@ -19,42 +21,40 @@
* 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 "LinkAccessibility.h"
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.*;
@implementation LinkAccessibility
// Type entry used for return from a call. A single cell to record the
// type.
public class ReturnTypeEntry<K,M> extends TypeEntries<K,M> {
static final int cellCount = 1;
ReturnTypeEntry(MethodDataInterface<K,M> methodData, ProfileData pd, int baseOff) {
super(methodData, pd, baseOff);
}
K type() {
return validKlass(baseOff);
}
static int staticCellCount() {
return cellCount;
}
int typeIndex() {
return baseOff;
}
void printDataOn(PrintStream st) {
pd.tab(st);
printKlass(st, baseOff);
st.println();
}
- (NSAccessibilityRole _Nonnull)accessibilityRole
{
return NSAccessibilityLinkRole;
}
- (NSString * _Nullable)accessibilityAttributedStringForRange:(NSRange)range
{
return [self accessibilityStringForRangeAttribute:range];
}
- (NSString * _Nullable)accessibilityValue
{
return [self accessibilityValueAttribute];
}
- (NSRange)accessibilityVisibleCharacterRange
{
return [self accessibilityVisibleCharacterRangeAttribute];
}
- (NSRect)accessibilityFrame
{
return [super accessibilityFrame];
}
- (id)accessibilityParent
{
return [super accessibilityParent];
}
@end

View File

@ -36,8 +36,6 @@ import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicRadioButtonUI;
import sun.awt.AppContext;
/**
* RadioButtonUI implementation for MotifRadioButtonUI
*
@ -45,7 +43,7 @@ import sun.awt.AppContext;
*/
public class MotifRadioButtonUI extends BasicRadioButtonUI {
private static final Object MOTIF_RADIO_BUTTON_UI_KEY = new Object();
private static final ComponentUI UI = new MotifRadioButtonUI();
protected Color focusColor;
@ -55,14 +53,7 @@ public class MotifRadioButtonUI extends BasicRadioButtonUI {
// Create PLAF
// ********************************
public static ComponentUI createUI(JComponent c) {
AppContext appContext = AppContext.getAppContext();
MotifRadioButtonUI motifRadioButtonUI =
(MotifRadioButtonUI) appContext.get(MOTIF_RADIO_BUTTON_UI_KEY);
if (motifRadioButtonUI == null) {
motifRadioButtonUI = new MotifRadioButtonUI();
appContext.put(MOTIF_RADIO_BUTTON_UI_KEY, motifRadioButtonUI);
}
return motifRadioButtonUI;
return UI;
}
// ********************************

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2026, 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
@ -2709,7 +2709,7 @@ public class Font implements java.io.Serializable
int limit,
int flags) {
GlyphLayout gl = GlyphLayout.get(null); // !!! no custom layout engines
GlyphLayout gl = GlyphLayout.get();
StandardGlyphVector gv = gl.layout(this, frc, text,
start, limit-start, flags, null);
GlyphLayout.done(gl);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2026, 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
@ -40,7 +40,6 @@ import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.ComponentFactory;
/**
@ -60,12 +59,6 @@ public abstract class MenuComponent implements java.io.Serializable {
transient volatile MenuComponentPeer peer;
transient volatile MenuContainer parent;
/**
* The {@code AppContext} of the {@code MenuComponent}.
* This is set in the constructor and never changes.
*/
private transient volatile AppContext appContext;
/**
* The menu component's font. This value can be
* {@code null} at which point a default will be used.
@ -116,15 +109,6 @@ public abstract class MenuComponent implements java.io.Serializable {
static {
AWTAccessor.setMenuComponentAccessor(
new AWTAccessor.MenuComponentAccessor() {
@Override
public AppContext getAppContext(MenuComponent menuComp) {
return menuComp.appContext;
}
@Override
public void setAppContext(MenuComponent menuComp,
AppContext appContext) {
menuComp.appContext = appContext;
}
@Override
@SuppressWarnings("unchecked")
public <T extends MenuComponentPeer> T getPeer(MenuComponent menuComp) {
@ -154,7 +138,6 @@ public abstract class MenuComponent implements java.io.Serializable {
*/
public MenuComponent() throws HeadlessException {
GraphicsEnvironment.checkHeadless();
appContext = AppContext.getAppContext();
}
/**
@ -428,8 +411,6 @@ public abstract class MenuComponent implements java.io.Serializable {
GraphicsEnvironment.checkHeadless();
s.defaultReadObject();
appContext = AppContext.getAppContext();
}
/*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2026, 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
@ -459,6 +459,9 @@ public class Robot {
* @return Color of the pixel
*/
public synchronized Color getPixelColor(int x, int y) {
// need to sync the toolkit prior to grabbing the pixels since in some
// cases rendering to the screen may be delayed
Toolkit.getDefaultToolkit().sync();
Point point = peer.useAbsoluteCoordinates() ? toDeviceSpaceAbs(x, y)
: toDeviceSpace(x, y);
return new Color(peer.getRGBPixel(point.x, point.y));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, 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
@ -200,6 +200,7 @@ public class ICC_ColorSpace extends ColorSpace {
* the number of components in this {@code ColorSpace}
* @throws NullPointerException if {@code colorvalue} is {@code null}
*/
@Override
public float[] toRGB(float[] colorvalue) {
if (this2srgb == null) {
synchronized (this) {
@ -249,6 +250,7 @@ public class ICC_ColorSpace extends ColorSpace {
* @throws ArrayIndexOutOfBoundsException if array length is not at least 3
* @throws NullPointerException if {@code rgbvalue} is {@code null}
*/
@Override
public float[] fromRGB(float[] rgbvalue) {
if (srgb2this == null) {
synchronized (this) {
@ -378,6 +380,7 @@ public class ICC_ColorSpace extends ColorSpace {
* the number of components in this {@code ColorSpace}
* @throws NullPointerException if {@code colorvalue} is {@code null}
*/
@Override
public float[] toCIEXYZ(float[] colorvalue) {
if (this2xyz == null) {
synchronized (this) {
@ -510,6 +513,7 @@ public class ICC_ColorSpace extends ColorSpace {
* @throws ArrayIndexOutOfBoundsException if array length is not at least 3
* @throws NullPointerException if {@code colorvalue} is {@code null}
*/
@Override
public float[] fromCIEXYZ(float[] colorvalue) {
if (xyz2this == null) {
synchronized (this) {
@ -560,6 +564,7 @@ public class ICC_ColorSpace extends ColorSpace {
* than {@code numComponents - 1}
* @since 1.4
*/
@Override
public float getMinValue(int component) {
rangeCheck(component);
return minVal[component];
@ -583,6 +588,7 @@ public class ICC_ColorSpace extends ColorSpace {
* than {@code numComponents - 1}
* @since 1.4
*/
@Override
public float getMaxValue(int component) {
rangeCheck(component);
return maxVal[component];

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, 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
@ -100,6 +100,7 @@ public final class ICC_ProfileGray extends ICC_Profile {
* @return an array containing the components of the mediaWhitePointTag in
* the ICC profile
*/
@Override
public float[] getMediaWhitePoint() {
return super.getMediaWhitePoint();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, 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
@ -135,6 +135,7 @@ public final class ICC_ProfileRGB extends ICC_Profile {
* @return a 3-element {@code float} array containing the x, y, and z
* components of the profile's {@code mediaWhitePointTag}
*/
@Override
public float[] getMediaWhitePoint() {
return super.getMediaWhitePoint();
}
@ -186,6 +187,7 @@ public final class ICC_ProfileRGB extends ICC_Profile {
* @throws ProfileDataException if the profile does not specify the
* corresponding TRC as a single gamma value
*/
@Override
public float getGamma(int component) {
return super.getGamma(toTag(component));
}
@ -218,6 +220,7 @@ public final class ICC_ProfileRGB extends ICC_Profile {
* @throws ProfileDataException if the profile does not specify the
* corresponding TRC as a table
*/
@Override
public short[] getTRC(int component) {
return super.getTRC(toTag(component));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,7 +30,6 @@ import java.io.ObjectStreamException;
import java.io.Serial;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
/**
@ -326,21 +325,14 @@ public class FocusEvent extends ComponentEvent {
* FOCUS_GAINED event, this is the Component that lost focus. For a
* FOCUS_LOST event, this is the Component that gained focus. If this
* focus change occurs with a native application, with a Java application
* in a different VM or context, or with no other Component, then null is
* in a different VM, or with no other Component, then null is
* returned.
*
* @return the other Component involved in the focus change, or null
* @since 1.4
*/
public Component getOppositeComponent() {
if (opposite == null) {
return null;
}
return (SunToolkit.targetToAppContext(opposite) ==
AppContext.getAppContext())
? opposite
: null;
return opposite;
}
/**
@ -407,4 +399,4 @@ public class FocusEvent extends ComponentEvent {
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, 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,7 +54,6 @@ import javax.swing.event.InternalFrameListener;
import javax.swing.plaf.DesktopIconUI;
import javax.swing.plaf.InternalFrameUI;
import sun.awt.AppContext;
import sun.swing.SwingUtilities2;
/**
@ -237,17 +236,13 @@ public class JInternalFrame extends JComponent implements
/** Constrained property name indicating that the internal frame is iconified. */
public static final String IS_ICON_PROPERTY = "icon";
private static final Object PROPERTY_CHANGE_LISTENER_KEY =
new StringBuilder("InternalFramePropertyChangeListener");
private static PropertyChangeListener focusListener;
private static void addPropertyChangeListenerIfNecessary() {
if (AppContext.getAppContext().get(PROPERTY_CHANGE_LISTENER_KEY) ==
null) {
PropertyChangeListener focusListener =
new FocusPropertyChangeListener();
AppContext.getAppContext().put(PROPERTY_CHANGE_LISTENER_KEY,
focusListener);
synchronized (JInternalFrame.class) {
if (focusListener == null) {
focusListener = new FocusPropertyChangeListener();
}
KeyboardFocusManager.getCurrentKeyboardFocusManager().
addPropertyChangeListener(focusListener);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,6 @@
package javax.swing.plaf.metal;
import sun.swing.SwingUtilities2;
import sun.awt.AppContext;
import javax.swing.*;
import javax.swing.plaf.*;

View File

@ -451,16 +451,6 @@ public final class AWTAccessor {
* An accessor for the MenuComponent class.
*/
public interface MenuComponentAccessor {
/**
* Returns the appContext of the menu component.
*/
AppContext getAppContext(MenuComponent menuComp);
/**
* Sets the appContext of the menu component.
*/
void setAppContext(MenuComponent menuComp, AppContext appContext);
/**
* Returns the peer of the menu component.
*/

Some files were not shown because too many files have changed in this diff Show More