mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-26 23:00:38 +00:00
Merge branch 'openjdk:master' into master
This commit is contained in:
commit
5d09ffa9fb
@ -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"
|
||||
|
||||
@ -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), \
|
||||
))
|
||||
|
||||
@ -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 () {
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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()) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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") \
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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++) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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 " \
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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[]);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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) \
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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-----------------------------------------
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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 },
|
||||
|
||||
@ -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() },
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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)
|
||||
);
|
||||
|
||||
@ -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; }
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 */ \
|
||||
/******************/ \
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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, -∞ < alpha < ∞
|
||||
* and tanh(atanh(x)) = x, -1 < x < 1;
|
||||
* It can be written as atanh(x) = 0.5 * log1p(2 * x/(1-x)), -1 < x < 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(±0)=±0 is exact for finite x.
|
||||
* atanh(NaN) is NaN
|
||||
* atanh(±1) is ±∞
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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> +<i>y</i><sup>2</sup>)
|
||||
* without intermediate overflow or underflow.
|
||||
|
||||
@ -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> +<i>y</i><sup>2</sup>)
|
||||
* without intermediate overflow or underflow.
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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"];
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
// ********************************
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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.*;
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user