merge latest changes from master branch

This commit is contained in:
Daniel Fuchs 2025-06-11 13:01:35 +01:00
commit 4cee27b5ec
196 changed files with 2919 additions and 2613 deletions

View File

@ -1192,8 +1192,8 @@ var getJibProfilesDependencies = function (input, common) {
server: "jpg",
product: "jcov",
version: "3.0",
build_number: "1",
file: "bundles/jcov-3.0+1.zip",
build_number: "3",
file: "bundles/jcov-3.0+3.zip",
environment_name: "JCOV_HOME",
},

View File

@ -46,6 +46,8 @@ CLDR_GEN_DONE := $(GENSRC_DIR)/_cldr-gensrc.marker
TZ_DATA_DIR := $(MODULE_SRC)/share/data/tzdata
ZONENAME_TEMPLATE := $(MODULE_SRC)/share/classes/java/time/format/ZoneName.java.template
# The `-utf8` option is used even for US English, as some names
# may contain non-ASCII characters, such as “Türkiye”.
$(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \
$(wildcard $(CLDR_DATA_DIR)/main/en*.xml) \
$(wildcard $(CLDR_DATA_DIR)/supplemental/*.xml) \
@ -61,7 +63,8 @@ $(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \
-basemodule \
-year $(COPYRIGHT_YEAR) \
-zntempfile $(ZONENAME_TEMPLATE) \
-tzdatadir $(TZ_DATA_DIR))
-tzdatadir $(TZ_DATA_DIR) \
-utf8)
$(TOUCH) $@
TARGETS += $(CLDR_GEN_DONE)

View File

@ -45,7 +45,8 @@ $(CLDR_GEN_DONE): $(wildcard $(CLDR_DATA_DIR)/dtd/*.dtd) \
-baselocales "en-US" \
-year $(COPYRIGHT_YEAR) \
-o $(GENSRC_DIR) \
-tzdatadir $(TZ_DATA_DIR))
-tzdatadir $(TZ_DATA_DIR) \
-utf8)
$(TOUCH) $@
TARGETS += $(CLDR_GEN_DONE)

View File

@ -187,22 +187,18 @@ public class HelloWorld {
new Run("none", "Hello from Cupertino")
}),
new Paragraph("title", new Run[] {
new Run("none", "\u53F0\u5317\u554F\u5019\u60A8\u0021")
new Run("none", "台北問候您!")
}),
new Paragraph("title", new Run[] {
new Run("none", "\u0391\u03B8\u03B7\u03BD\u03B1\u03B9\u0020" // Greek
+ "\u03B1\u03C3\u03C0\u03B1\u03B6\u03BF\u03BD"
+ "\u03C4\u03B1\u03B9\u0020\u03C5\u03BC\u03B1"
+ "\u03C2\u0021")
new Run("none", "Αθηναι ασπαζονται υμας!") // Greek
}),
new Paragraph("title", new Run[] {
new Run("none", "\u6771\u4eac\u304b\u3089\u4eca\u65e5\u306f")
new Run("none", "東京から今日は")
}),
new Paragraph("title", new Run[] {
new Run("none", "\u05e9\u05dc\u05d5\u05dd \u05de\u05d9\u05e8\u05d5"
+ "\u05e9\u05dc\u05d9\u05dd")
new Run("none", "שלום מירושלים")
}),
new Paragraph("title", new Run[] {
new Run("none", "\u0633\u0644\u0627\u0645")
new Run("none", "سلام")
}), };
}

View File

@ -3921,6 +3921,10 @@ ins_attrib ins_alignment(4); // Required alignment attribute (must
// compute_padding() function must be
// provided for the instruction
// Whether this node is expanded during code emission into a sequence of
// instructions and the first instruction can perform an implicit null check.
ins_attrib ins_is_late_expanded_null_check_candidate(false);
//----------OPERANDS-----------------------------------------------------------
// Operand definitions must precede instruction definitions for correct parsing
// in the ADLC because operands constitute user defined types which are used in

View File

@ -106,6 +106,13 @@ instruct zLoadP(iRegPNoSp dst, memory8 mem, rFlagsReg cr)
match(Set dst (LoadP mem));
predicate(UseZGC && !needs_acquiring_load(n) && n->as_Load()->barrier_data() != 0);
effect(TEMP dst, KILL cr);
// The main load is a candidate to implement implicit null checks, as long as
// legitimize_address() does not require a preceding lea instruction to
// materialize the memory operand. The absence of a preceding lea instruction
// is guaranteed for immLoffset8 memory operands, because these do not lead to
// out-of-range offsets (see definition of immLoffset8). Fortunately,
// immLoffset8 memory operands are the most common ones in practice.
ins_is_late_expanded_null_check_candidate(opnd_array(1)->opcode() == INDOFFL8);
ins_cost(4 * INSN_COST);
@ -117,7 +124,11 @@ instruct zLoadP(iRegPNoSp dst, memory8 mem, rFlagsReg cr)
// Fix up any out-of-range offsets.
assert_different_registers(rscratch2, as_Register($mem$$base));
assert_different_registers(rscratch2, $dst$$Register);
ref_addr = __ legitimize_address(ref_addr, 8, rscratch2);
int size = 8;
assert(!this->is_late_expanded_null_check_candidate() ||
!MacroAssembler::legitimize_address_requires_lea(ref_addr, size),
"an instruction that can be used for implicit null checking should emit the candidate memory access first");
ref_addr = __ legitimize_address(ref_addr, size, rscratch2);
}
__ ldr($dst$$Register, ref_addr);
z_load_barrier(masm, this, ref_addr, $dst$$Register, rscratch1);

View File

@ -129,16 +129,21 @@ class MacroAssembler: public Assembler {
a.lea(this, r);
}
// Whether materializing the given address for a LDR/STR requires an
// additional lea instruction.
static bool legitimize_address_requires_lea(const Address &a, int size) {
return a.getMode() == Address::base_plus_offset &&
!Address::offset_ok_for_immed(a.offset(), exact_log2(size));
}
/* Sometimes we get misaligned loads and stores, usually from Unsafe
accesses, and these can exceed the offset range. */
Address legitimize_address(const Address &a, int size, Register scratch) {
if (a.getMode() == Address::base_plus_offset) {
if (! Address::offset_ok_for_immed(a.offset(), exact_log2(size))) {
block_comment("legitimize_address {");
lea(scratch, a);
block_comment("} legitimize_address");
return Address(scratch);
}
if (legitimize_address_requires_lea(a, size)) {
block_comment("legitimize_address {");
lea(scratch, a);
block_comment("} legitimize_address");
return Address(scratch);
}
return a;
}

View File

@ -141,6 +141,7 @@ instruct zLoadP(iRegPdst dst, memoryAlg4 mem, flagsRegCR0 cr0)
%{
match(Set dst (LoadP mem));
effect(TEMP_DEF dst, KILL cr0);
ins_is_late_expanded_null_check_candidate(true);
ins_cost(MEMORY_REF_COST);
predicate((UseZGC && n->as_Load()->barrier_data() != 0)
@ -160,6 +161,7 @@ instruct zLoadP_acq(iRegPdst dst, memoryAlg4 mem, flagsRegCR0 cr0)
%{
match(Set dst (LoadP mem));
effect(TEMP_DEF dst, KILL cr0);
ins_is_late_expanded_null_check_candidate(true);
ins_cost(3 * MEMORY_REF_COST);
// Predicate on instruction order is implicitly present due to the predicate of the cheaper zLoadP operation

View File

@ -4036,6 +4036,10 @@ ins_attrib ins_field_cbuf_insts_offset(-1);
ins_attrib ins_field_load_ic_hi_node(0);
ins_attrib ins_field_load_ic_node(0);
// Whether this node is expanded during code emission into a sequence of
// instructions and the first instruction can perform an implicit null check.
ins_attrib ins_is_late_expanded_null_check_candidate(false);
//----------OPERANDS-----------------------------------------------------------
// Operand definitions must precede instruction definitions for correct
// parsing in the ADLC because operands constitute user defined types

View File

@ -96,6 +96,7 @@ instruct zLoadP(iRegPNoSp dst, memory mem, iRegPNoSp tmp, rFlagsReg cr)
match(Set dst (LoadP mem));
predicate(UseZGC && n->as_Load()->barrier_data() != 0);
effect(TEMP dst, TEMP tmp, KILL cr);
ins_is_late_expanded_null_check_candidate(true);
ins_cost(4 * DEFAULT_COST);

View File

@ -2619,6 +2619,10 @@ ins_attrib ins_alignment(4); // Required alignment attribute (must
// compute_padding() function must be
// provided for the instruction
// Whether this node is expanded during code emission into a sequence of
// instructions and the first instruction can perform an implicit null check.
ins_attrib ins_is_late_expanded_null_check_candidate(false);
//----------OPERANDS-----------------------------------------------------------
// Operand definitions must precede instruction definitions for correct parsing
// in the ADLC because operands constitute user defined types which are used in

View File

@ -118,6 +118,10 @@ instruct zLoadP(rRegP dst, memory mem, rFlagsReg cr)
predicate(UseZGC && n->as_Load()->barrier_data() != 0);
match(Set dst (LoadP mem));
effect(TEMP dst, KILL cr);
// The main load is a candidate to implement implicit null checks. The
// barrier's slow path includes an identical reload, which does not need to be
// registered in the exception table because it is dominated by the main one.
ins_is_late_expanded_null_check_candidate(true);
ins_cost(125);

View File

@ -2055,6 +2055,10 @@ ins_attrib ins_alignment(1); // Required alignment attribute (must
// compute_padding() function must be
// provided for the instruction
// Whether this node is expanded during code emission into a sequence of
// instructions and the first instruction can perform an implicit null check.
ins_attrib ins_is_late_expanded_null_check_candidate(false);
//----------OPERANDS-----------------------------------------------------------
// Operand definitions must precede instruction definitions for correct parsing
// in the ADLC because operands constitute user defined types which are used in

View File

@ -1261,69 +1261,6 @@ void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
// Nothing to do beyond of what os::print_cpu_info() does.
}
static char saved_jvm_path[MAXPATHLEN] = {0};
// Find the full path to the current module, libjvm.so.
void os::jvm_path(char *buf, jint buflen) {
// Error checking.
if (buflen < MAXPATHLEN) {
assert(false, "must use a large-enough buffer");
buf[0] = '\0';
return;
}
// Lazy resolve the path to current module.
if (saved_jvm_path[0] != 0) {
strcpy(buf, saved_jvm_path);
return;
}
Dl_info dlinfo;
int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo);
assert(ret != 0, "cannot locate libjvm");
char* rp = os::realpath((char *)dlinfo.dli_fname, buf, buflen);
assert(rp != nullptr, "error in realpath(): maybe the 'path' argument is too long?");
// If executing unit tests we require JAVA_HOME to point to the real JDK.
if (Arguments::executing_unit_tests()) {
// Look for JAVA_HOME in the environment.
char* java_home_var = ::getenv("JAVA_HOME");
if (java_home_var != nullptr && java_home_var[0] != 0) {
// Check the current module name "libjvm.so".
const char* p = strrchr(buf, '/');
if (p == nullptr) {
return;
}
assert(strstr(p, "/libjvm") == p, "invalid library name");
stringStream ss(buf, buflen);
rp = os::realpath(java_home_var, buf, buflen);
if (rp == nullptr) {
return;
}
assert((int)strlen(buf) < buflen, "Ran out of buffer room");
ss.print("%s/lib", buf);
if (0 == access(buf, F_OK)) {
// Use current module name "libjvm.so"
ss.print("/%s/libjvm%s", Abstract_VM_Version::vm_variant(), JNI_LIB_SUFFIX);
assert(strcmp(buf + strlen(buf) - strlen(JNI_LIB_SUFFIX), JNI_LIB_SUFFIX) == 0,
"buf has been truncated");
} else {
// Go back to path of .so
rp = os::realpath((char *)dlinfo.dli_fname, buf, buflen);
if (rp == nullptr) {
return;
}
}
}
}
strncpy(saved_jvm_path, buf, sizeof(saved_jvm_path));
saved_jvm_path[sizeof(saved_jvm_path) - 1] = '\0';
}
////////////////////////////////////////////////////////////////////////////////
// Virtual Memory

View File

@ -1482,83 +1482,6 @@ void os::print_memory_info(outputStream* st) {
st->cr();
}
static char saved_jvm_path[MAXPATHLEN] = {0};
// Find the full path to the current module, libjvm
void os::jvm_path(char *buf, jint buflen) {
// Error checking.
if (buflen < MAXPATHLEN) {
assert(false, "must use a large-enough buffer");
buf[0] = '\0';
return;
}
// Lazy resolve the path to current module.
if (saved_jvm_path[0] != 0) {
strcpy(buf, saved_jvm_path);
return;
}
char dli_fname[MAXPATHLEN];
dli_fname[0] = '\0';
bool ret = dll_address_to_library_name(
CAST_FROM_FN_PTR(address, os::jvm_path),
dli_fname, sizeof(dli_fname), nullptr);
assert(ret, "cannot locate libjvm");
char *rp = nullptr;
if (ret && dli_fname[0] != '\0') {
rp = os::realpath(dli_fname, buf, buflen);
}
if (rp == nullptr) {
return;
}
// If executing unit tests we require JAVA_HOME to point to the real JDK.
if (Arguments::executing_unit_tests()) {
// Look for JAVA_HOME in the environment.
char* java_home_var = ::getenv("JAVA_HOME");
if (java_home_var != nullptr && java_home_var[0] != 0) {
// Check the current module name "libjvm"
const char* p = strrchr(buf, '/');
assert(strstr(p, "/libjvm") == p, "invalid library name");
stringStream ss(buf, buflen);
rp = os::realpath(java_home_var, buf, buflen);
if (rp == nullptr) {
return;
}
assert((int)strlen(buf) < buflen, "Ran out of buffer space");
// Add the appropriate library and JVM variant subdirs
ss.print("%s/lib/%s", buf, Abstract_VM_Version::vm_variant());
if (0 != access(buf, F_OK)) {
ss.reset();
ss.print("%s/lib", buf);
}
// If the path exists within JAVA_HOME, add the JVM library name
// to complete the path to JVM being overridden. Otherwise fallback
// to the path to the current library.
if (0 == access(buf, F_OK)) {
// Use current module name "libjvm"
ss.print("/libjvm%s", JNI_LIB_SUFFIX);
assert(strcmp(buf + strlen(buf) - strlen(JNI_LIB_SUFFIX), JNI_LIB_SUFFIX) == 0,
"buf has been truncated");
} else {
// Fall back to path of current library
rp = os::realpath(dli_fname, buf, buflen);
if (rp == nullptr) {
return;
}
}
}
}
strncpy(saved_jvm_path, buf, MAXPATHLEN);
saved_jvm_path[MAXPATHLEN - 1] = '\0';
}
////////////////////////////////////////////////////////////////////////////////
// Virtual Memory

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,9 +35,6 @@
range, \
constraint) \
\
product(bool, UseOprofile, false, \
"(Deprecated) enable support for Oprofile profiler") \
\
product(bool, UseTransparentHugePages, false, \
"Use MADV_HUGEPAGE for large pages") \
\

View File

@ -2746,118 +2746,9 @@ void os::get_summary_cpu_info(char* cpuinfo, size_t length) {
#endif
}
static char saved_jvm_path[MAXPATHLEN] = {0};
// Find the full path to the current module, libjvm.so
void os::jvm_path(char *buf, jint buflen) {
// Error checking.
if (buflen < MAXPATHLEN) {
assert(false, "must use a large-enough buffer");
buf[0] = '\0';
return;
}
// Lazy resolve the path to current module.
if (saved_jvm_path[0] != 0) {
strcpy(buf, saved_jvm_path);
return;
}
char dli_fname[MAXPATHLEN];
dli_fname[0] = '\0';
bool ret = dll_address_to_library_name(
CAST_FROM_FN_PTR(address, os::jvm_path),
dli_fname, sizeof(dli_fname), nullptr);
assert(ret, "cannot locate libjvm");
char *rp = nullptr;
if (ret && dli_fname[0] != '\0') {
rp = os::realpath(dli_fname, buf, buflen);
}
if (rp == nullptr) {
return;
}
// If executing unit tests we require JAVA_HOME to point to the real JDK.
if (Arguments::executing_unit_tests()) {
// Look for JAVA_HOME in the environment.
char* java_home_var = ::getenv("JAVA_HOME");
if (java_home_var != nullptr && java_home_var[0] != 0) {
// Check the current module name "libjvm.so".
const char* p = strrchr(buf, '/');
if (p == nullptr) {
return;
}
assert(strstr(p, "/libjvm") == p, "invalid library name");
stringStream ss(buf, buflen);
rp = os::realpath(java_home_var, buf, buflen);
if (rp == nullptr) {
return;
}
assert((int)strlen(buf) < buflen, "Ran out of buffer room");
ss.print("%s/lib", buf);
if (0 == access(buf, F_OK)) {
// Use current module name "libjvm.so"
ss.print("/%s/libjvm%s", Abstract_VM_Version::vm_variant(), JNI_LIB_SUFFIX);
assert(strcmp(buf + strlen(buf) - strlen(JNI_LIB_SUFFIX), JNI_LIB_SUFFIX) == 0,
"buf has been truncated");
} else {
// Go back to path of .so
rp = os::realpath(dli_fname, buf, buflen);
if (rp == nullptr) {
return;
}
}
}
}
strncpy(saved_jvm_path, buf, MAXPATHLEN);
saved_jvm_path[MAXPATHLEN - 1] = '\0';
}
////////////////////////////////////////////////////////////////////////////////
// Virtual Memory
// Rationale behind this function:
// current (Mon Apr 25 20:12:18 MSD 2005) oprofile drops samples without executable
// mapping for address (see lookup_dcookie() in the kernel module), thus we cannot get
// samples for JITted code. Here we create private executable mapping over the code cache
// and then we can use standard (well, almost, as mapping can change) way to provide
// info for the reporting script by storing timestamp and location of symbol
void linux_wrap_code(char* base, size_t size) {
static volatile jint cnt = 0;
static_assert(sizeof(off_t) == 8, "Expected Large File Support in this file");
if (!UseOprofile) {
return;
}
char buf[PATH_MAX+1];
int num = Atomic::add(&cnt, 1);
snprintf(buf, sizeof(buf), "%s/hs-vm-%d-%d",
os::get_temp_directory(), os::current_process_id(), num);
unlink(buf);
int fd = ::open(buf, O_CREAT | O_RDWR, S_IRWXU);
if (fd != -1) {
off_t rv = ::lseek(fd, size-2, SEEK_SET);
if (rv != (off_t)-1) {
if (::write(fd, "", 1) == 1) {
mmap(base, size,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE, fd, 0);
}
}
::close(fd);
unlink(buf);
}
}
static bool recoverable_mmap_error(int err) {
// See if the error is one we can let the caller handle. This
// list of errno values comes from JBS-6843484. I can't find a

View File

@ -59,6 +59,7 @@
#ifdef AIX
#include "loadlib_aix.hpp"
#include "os_aix.hpp"
#include "porting_aix.hpp"
#endif
#ifdef LINUX
#include "os_linux.hpp"
@ -1060,6 +1061,95 @@ bool os::same_files(const char* file1, const char* file2) {
return is_same;
}
static char saved_jvm_path[MAXPATHLEN] = {0};
// Find the full path to the current module, libjvm.so
void os::jvm_path(char *buf, jint buflen) {
// Error checking.
if (buflen < MAXPATHLEN) {
assert(false, "must use a large-enough buffer");
buf[0] = '\0';
return;
}
// Lazy resolve the path to current module.
if (saved_jvm_path[0] != 0) {
strcpy(buf, saved_jvm_path);
return;
}
const char* fname;
#ifdef AIX
Dl_info dlinfo;
int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo);
assert(ret != 0, "cannot locate libjvm");
if (ret == 0) {
return;
}
fname = dlinfo.dli_fname;
#else
char dli_fname[MAXPATHLEN];
dli_fname[0] = '\0';
bool ret = dll_address_to_library_name(
CAST_FROM_FN_PTR(address, os::jvm_path),
dli_fname, sizeof(dli_fname), nullptr);
assert(ret, "cannot locate libjvm");
if (!ret) {
return;
}
fname = dli_fname;
#endif // AIX
char* rp = nullptr;
if (fname[0] != '\0') {
rp = os::realpath(fname, buf, buflen);
}
if (rp == nullptr) {
return;
}
// If executing unit tests we require JAVA_HOME to point to the real JDK.
if (Arguments::executing_unit_tests()) {
// Look for JAVA_HOME in the environment.
char* java_home_var = ::getenv("JAVA_HOME");
if (java_home_var != nullptr && java_home_var[0] != 0) {
// Check the current module name "libjvm.so".
const char* p = strrchr(buf, '/');
if (p == nullptr) {
return;
}
assert(strstr(p, "/libjvm") == p, "invalid library name");
stringStream ss(buf, buflen);
rp = os::realpath(java_home_var, buf, buflen);
if (rp == nullptr) {
return;
}
assert((int)strlen(buf) < buflen, "Ran out of buffer room");
ss.print("%s/lib", buf);
// If the path exists within JAVA_HOME, add the VM variant directory and JVM
// library name to complete the path to JVM being overridden. Otherwise fallback
// to the path to the current library.
if (0 == access(buf, F_OK)) {
// Use current module name "libjvm.so"
ss.print("/%s/libjvm%s", Abstract_VM_Version::vm_variant(), JNI_LIB_SUFFIX);
assert(strcmp(buf + strlen(buf) - strlen(JNI_LIB_SUFFIX), JNI_LIB_SUFFIX) == 0,
"buf has been truncated");
} else {
// Go back to path of .so
rp = os::realpath(fname, buf, buflen);
if (rp == nullptr) {
return;
}
}
}
}
strncpy(saved_jvm_path, buf, MAXPATHLEN);
saved_jvm_path[MAXPATHLEN - 1] = '\0';
}
// Called when creating the thread. The minimum stack sizes have already been calculated
size_t os::Posix::get_initial_stack_size(ThreadType thr_type, size_t req_stack_size) {
size_t stack_size;

View File

@ -481,7 +481,3 @@ int get_legal_text(FileBuff &fbuf, char **legal_text)
*legal_text = legal_start;
return (int) (legal_end - legal_start);
}
void *operator new( size_t size, int, const char *, int ) throw() {
return ::operator new( size );
}

View File

@ -1626,6 +1626,8 @@ void ArchDesc::declareClasses(FILE *fp) {
while (attr != nullptr) {
if (strcmp (attr->_ident, "ins_is_TrapBasedCheckNode") == 0) {
fprintf(fp, " virtual bool is_TrapBasedCheckNode() const { return %s; }\n", attr->_val);
} else if (strcmp (attr->_ident, "ins_is_late_expanded_null_check_candidate") == 0) {
fprintf(fp, " virtual bool is_late_expanded_null_check_candidate() const { return %s; }\n", attr->_val);
} else if (strcmp (attr->_ident, "ins_cost") != 0 &&
strncmp(attr->_ident, "ins_field_", 10) != 0 &&
// Must match function in node.hpp: return type bool, no prefix "ins_".

View File

@ -110,12 +110,24 @@ const char* CDSConfig::default_archive_path() {
// before CDSConfig::ergo_initialize() is called.
assert(_cds_ergo_initialize_started, "sanity");
if (_default_archive_path == nullptr) {
char jvm_path[JVM_MAXPATHLEN];
os::jvm_path(jvm_path, sizeof(jvm_path));
char *end = strrchr(jvm_path, *os::file_separator());
if (end != nullptr) *end = '\0';
stringStream tmp;
tmp.print("%s%sclasses", jvm_path, os::file_separator());
if (is_vm_statically_linked()) {
// It's easier to form the path using JAVA_HOME as os::jvm_path
// gives the path to the launcher executable on static JDK.
const char* subdir = WINDOWS_ONLY("bin") NOT_WINDOWS("lib");
tmp.print("%s%s%s%s%s%sclasses",
Arguments::get_java_home(), os::file_separator(),
subdir, os::file_separator(),
Abstract_VM_Version::vm_variant(), os::file_separator());
} else {
// Assume .jsa is in the same directory where libjvm resides on
// non-static JDK.
char jvm_path[JVM_MAXPATHLEN];
os::jvm_path(jvm_path, sizeof(jvm_path));
char *end = strrchr(jvm_path, *os::file_separator());
if (end != nullptr) *end = '\0';
tmp.print("%s%sclasses", jvm_path, os::file_separator());
}
#ifdef _LP64
if (!UseCompressedOops) {
tmp.print_raw("_nocoops");

View File

@ -98,15 +98,15 @@ void ParallelArguments::initialize() {
FullGCForwarding::initialize_flags(heap_reserved_size_bytes());
}
// The alignment used for boundary between young gen and old gen
static size_t default_gen_alignment() {
// The alignment used for spaces in young gen and old gen
static size_t default_space_alignment() {
return 64 * K * HeapWordSize;
}
void ParallelArguments::initialize_alignments() {
// Initialize card size before initializing alignments
CardTable::initialize_card_size();
SpaceAlignment = GenAlignment = default_gen_alignment();
SpaceAlignment = default_space_alignment();
HeapAlignment = compute_heap_alignment();
}
@ -123,9 +123,8 @@ void ParallelArguments::initialize_heap_flags_and_sizes() {
// Can a page size be something else than a power of two?
assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2");
size_t new_alignment = align_up(page_sz, GenAlignment);
if (new_alignment != GenAlignment) {
GenAlignment = new_alignment;
size_t new_alignment = align_up(page_sz, SpaceAlignment);
if (new_alignment != SpaceAlignment) {
SpaceAlignment = new_alignment;
// Redo everything from the start
initialize_heap_flags_and_sizes_one_pass();

View File

@ -29,10 +29,8 @@
void ParallelInitLogger::print_heap() {
log_info_p(gc, init)("Alignments:"
" Space " EXACTFMT ","
" Generation " EXACTFMT ","
" Heap " EXACTFMT,
EXACTFMTARGS(SpaceAlignment),
EXACTFMTARGS(GenAlignment),
EXACTFMTARGS(HeapAlignment));
GCInitLogger::print_heap();
}

View File

@ -69,8 +69,8 @@ jint ParallelScavengeHeap::initialize() {
initialize_reserved_region(heap_rs);
// Layout the reserved space for the generations.
ReservedSpace old_rs = heap_rs.first_part(MaxOldSize, GenAlignment);
ReservedSpace young_rs = heap_rs.last_part(MaxOldSize, GenAlignment);
ReservedSpace old_rs = heap_rs.first_part(MaxOldSize, SpaceAlignment);
ReservedSpace young_rs = heap_rs.last_part(MaxOldSize, SpaceAlignment);
assert(young_rs.size() == MaxNewSize, "Didn't reserve all of the heap");
PSCardTable* card_table = new PSCardTable(_reserved);
@ -107,7 +107,7 @@ jint ParallelScavengeHeap::initialize() {
new PSAdaptiveSizePolicy(eden_capacity,
initial_promo_size,
young_gen()->to_space()->capacity_in_bytes(),
GenAlignment,
SpaceAlignment,
max_gc_pause_sec,
GCTimeRatio
);

View File

@ -41,7 +41,7 @@ PSOldGen::PSOldGen(ReservedSpace rs, size_t initial_size, size_t min_size,
_min_gen_size(min_size),
_max_gen_size(max_size)
{
initialize(rs, initial_size, GenAlignment);
initialize(rs, initial_size, SpaceAlignment);
}
void PSOldGen::initialize(ReservedSpace rs, size_t initial_size, size_t alignment) {

View File

@ -47,7 +47,7 @@ PSYoungGen::PSYoungGen(ReservedSpace rs, size_t initial_size, size_t min_size, s
_from_counters(nullptr),
_to_counters(nullptr)
{
initialize(rs, initial_size, GenAlignment);
initialize(rs, initial_size, SpaceAlignment);
}
void PSYoungGen::initialize_virtual_space(ReservedSpace rs,
@ -746,7 +746,7 @@ size_t PSYoungGen::available_to_live() {
}
size_t delta_in_bytes = unused_committed + delta_in_survivor;
delta_in_bytes = align_down(delta_in_bytes, GenAlignment);
delta_in_bytes = align_down(delta_in_bytes, SpaceAlignment);
return delta_in_bytes;
}

View File

@ -188,8 +188,8 @@ jint SerialHeap::initialize() {
initialize_reserved_region(heap_rs);
ReservedSpace young_rs = heap_rs.first_part(MaxNewSize, GenAlignment);
ReservedSpace old_rs = heap_rs.last_part(MaxNewSize, GenAlignment);
ReservedSpace young_rs = heap_rs.first_part(MaxNewSize, SpaceAlignment);
ReservedSpace old_rs = heap_rs.last_part(MaxNewSize, SpaceAlignment);
_rem_set = new CardTableRS(_reserved);
_rem_set->initialize(young_rs.base(), old_rs.base());

View File

@ -35,7 +35,7 @@ extern size_t SpaceAlignment;
class GCArguments {
protected:
// Initialize HeapAlignment, SpaceAlignment, and extra alignments (E.g. GenAlignment)
// Initialize HeapAlignment, SpaceAlignment
virtual void initialize_alignments() = 0;
virtual void initialize_heap_flags_and_sizes();
virtual void initialize_size_info();

View File

@ -42,17 +42,15 @@ size_t MaxOldSize = 0;
// See more in JDK-8346005
size_t OldSize = ScaleForWordSize(4*M);
size_t GenAlignment = 0;
size_t GenArguments::conservative_max_heap_alignment() { return (size_t)Generation::GenGrain; }
static size_t young_gen_size_lower_bound() {
// The young generation must be aligned and have room for eden + two survivors
return align_up(3 * SpaceAlignment, GenAlignment);
return 3 * SpaceAlignment;
}
static size_t old_gen_size_lower_bound() {
return align_up(SpaceAlignment, GenAlignment);
return SpaceAlignment;
}
size_t GenArguments::scale_by_NewRatio_aligned(size_t base_size, size_t alignment) {
@ -69,23 +67,20 @@ static size_t bound_minus_alignment(size_t desired_size,
void GenArguments::initialize_alignments() {
// Initialize card size before initializing alignments
CardTable::initialize_card_size();
SpaceAlignment = GenAlignment = (size_t)Generation::GenGrain;
SpaceAlignment = (size_t)Generation::GenGrain;
HeapAlignment = compute_heap_alignment();
}
void GenArguments::initialize_heap_flags_and_sizes() {
GCArguments::initialize_heap_flags_and_sizes();
assert(GenAlignment != 0, "Generation alignment not set up properly");
assert(HeapAlignment >= GenAlignment,
"HeapAlignment: %zu less than GenAlignment: %zu",
HeapAlignment, GenAlignment);
assert(GenAlignment % SpaceAlignment == 0,
"GenAlignment: %zu not aligned by SpaceAlignment: %zu",
GenAlignment, SpaceAlignment);
assert(HeapAlignment % GenAlignment == 0,
"HeapAlignment: %zu not aligned by GenAlignment: %zu",
HeapAlignment, GenAlignment);
assert(SpaceAlignment != 0, "Generation alignment not set up properly");
assert(HeapAlignment >= SpaceAlignment,
"HeapAlignment: %zu less than SpaceAlignment: %zu",
HeapAlignment, SpaceAlignment);
assert(HeapAlignment % SpaceAlignment == 0,
"HeapAlignment: %zu not aligned by SpaceAlignment: %zu",
HeapAlignment, SpaceAlignment);
// All generational heaps have a young gen; handle those flags here
@ -106,7 +101,7 @@ void GenArguments::initialize_heap_flags_and_sizes() {
// Make sure NewSize allows an old generation to fit even if set on the command line
if (FLAG_IS_CMDLINE(NewSize) && NewSize >= InitialHeapSize) {
size_t revised_new_size = bound_minus_alignment(NewSize, InitialHeapSize, GenAlignment);
size_t revised_new_size = bound_minus_alignment(NewSize, InitialHeapSize, SpaceAlignment);
log_warning(gc, ergo)("NewSize (%zuk) is equal to or greater than initial heap size (%zuk). A new "
"NewSize of %zuk will be used to accomodate an old generation.",
NewSize/K, InitialHeapSize/K, revised_new_size/K);
@ -115,8 +110,8 @@ void GenArguments::initialize_heap_flags_and_sizes() {
// Now take the actual NewSize into account. We will silently increase NewSize
// if the user specified a smaller or unaligned value.
size_t bounded_new_size = bound_minus_alignment(NewSize, MaxHeapSize, GenAlignment);
bounded_new_size = MAX2(smallest_new_size, align_down(bounded_new_size, GenAlignment));
size_t bounded_new_size = bound_minus_alignment(NewSize, MaxHeapSize, SpaceAlignment);
bounded_new_size = MAX2(smallest_new_size, align_down(bounded_new_size, SpaceAlignment));
if (bounded_new_size != NewSize) {
FLAG_SET_ERGO(NewSize, bounded_new_size);
}
@ -125,7 +120,7 @@ void GenArguments::initialize_heap_flags_and_sizes() {
if (!FLAG_IS_DEFAULT(MaxNewSize)) {
if (MaxNewSize >= MaxHeapSize) {
// Make sure there is room for an old generation
size_t smaller_max_new_size = MaxHeapSize - GenAlignment;
size_t smaller_max_new_size = MaxHeapSize - SpaceAlignment;
if (FLAG_IS_CMDLINE(MaxNewSize)) {
log_warning(gc, ergo)("MaxNewSize (%zuk) is equal to or greater than the entire "
"heap (%zuk). A new max generation size of %zuk will be used.",
@ -137,8 +132,8 @@ void GenArguments::initialize_heap_flags_and_sizes() {
}
} else if (MaxNewSize < NewSize) {
FLAG_SET_ERGO(MaxNewSize, NewSize);
} else if (!is_aligned(MaxNewSize, GenAlignment)) {
FLAG_SET_ERGO(MaxNewSize, align_down(MaxNewSize, GenAlignment));
} else if (!is_aligned(MaxNewSize, SpaceAlignment)) {
FLAG_SET_ERGO(MaxNewSize, align_down(MaxNewSize, SpaceAlignment));
}
}
@ -166,13 +161,13 @@ void GenArguments::initialize_heap_flags_and_sizes() {
// exceed it. Adjust New/OldSize as necessary.
size_t calculated_size = NewSize + OldSize;
double shrink_factor = (double) MaxHeapSize / calculated_size;
size_t smaller_new_size = align_down((size_t)(NewSize * shrink_factor), GenAlignment);
size_t smaller_new_size = align_down((size_t)(NewSize * shrink_factor), SpaceAlignment);
FLAG_SET_ERGO(NewSize, MAX2(young_gen_size_lower_bound(), smaller_new_size));
// OldSize is already aligned because above we aligned MaxHeapSize to
// HeapAlignment, and we just made sure that NewSize is aligned to
// GenAlignment. In initialize_flags() we verified that HeapAlignment
// is a multiple of GenAlignment.
// SpaceAlignment. In initialize_flags() we verified that HeapAlignment
// is a multiple of SpaceAlignment.
OldSize = MaxHeapSize - NewSize;
} else {
FLAG_SET_ERGO(MaxHeapSize, align_up(NewSize + OldSize, HeapAlignment));
@ -200,7 +195,7 @@ void GenArguments::initialize_size_info() {
// Determine maximum size of the young generation.
if (FLAG_IS_DEFAULT(MaxNewSize)) {
max_young_size = scale_by_NewRatio_aligned(MaxHeapSize, GenAlignment);
max_young_size = scale_by_NewRatio_aligned(MaxHeapSize, SpaceAlignment);
// Bound the maximum size by NewSize below (since it historically
// would have been NewSize and because the NewRatio calculation could
// yield a size that is too small) and bound it by MaxNewSize above.
@ -229,18 +224,18 @@ void GenArguments::initialize_size_info() {
// If NewSize is set on the command line, we should use it as
// the initial size, but make sure it is within the heap bounds.
initial_young_size =
MIN2(max_young_size, bound_minus_alignment(NewSize, InitialHeapSize, GenAlignment));
MinNewSize = bound_minus_alignment(initial_young_size, MinHeapSize, GenAlignment);
MIN2(max_young_size, bound_minus_alignment(NewSize, InitialHeapSize, SpaceAlignment));
MinNewSize = bound_minus_alignment(initial_young_size, MinHeapSize, SpaceAlignment);
} else {
// For the case where NewSize is not set on the command line, use
// NewRatio to size the initial generation size. Use the current
// NewSize as the floor, because if NewRatio is overly large, the resulting
// size can be too small.
initial_young_size =
clamp(scale_by_NewRatio_aligned(InitialHeapSize, GenAlignment), NewSize, max_young_size);
clamp(scale_by_NewRatio_aligned(InitialHeapSize, SpaceAlignment), NewSize, max_young_size);
// Derive MinNewSize from MinHeapSize
MinNewSize = MIN2(scale_by_NewRatio_aligned(MinHeapSize, GenAlignment), initial_young_size);
MinNewSize = MIN2(scale_by_NewRatio_aligned(MinHeapSize, SpaceAlignment), initial_young_size);
}
}
@ -252,7 +247,7 @@ void GenArguments::initialize_size_info() {
// The maximum old size can be determined from the maximum young
// and maximum heap size since no explicit flags exist
// for setting the old generation maximum.
MaxOldSize = MAX2(MaxHeapSize - max_young_size, GenAlignment);
MaxOldSize = MAX2(MaxHeapSize - max_young_size, SpaceAlignment);
MinOldSize = MIN3(MaxOldSize,
InitialHeapSize - initial_young_size,
MinHeapSize - MinNewSize);
@ -315,10 +310,10 @@ void GenArguments::assert_flags() {
assert(NewSize >= MinNewSize, "Ergonomics decided on a too small young gen size");
assert(NewSize <= MaxNewSize, "Ergonomics decided on incompatible initial and maximum young gen sizes");
assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young gen and heap sizes");
assert(NewSize % GenAlignment == 0, "NewSize alignment");
assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize % GenAlignment == 0, "MaxNewSize alignment");
assert(NewSize % SpaceAlignment == 0, "NewSize alignment");
assert(FLAG_IS_DEFAULT(MaxNewSize) || MaxNewSize % SpaceAlignment == 0, "MaxNewSize alignment");
assert(OldSize + NewSize <= MaxHeapSize, "Ergonomics decided on incompatible generation and heap sizes");
assert(OldSize % GenAlignment == 0, "OldSize alignment");
assert(OldSize % SpaceAlignment == 0, "OldSize alignment");
}
void GenArguments::assert_size_info() {
@ -327,19 +322,19 @@ void GenArguments::assert_size_info() {
assert(MaxNewSize < MaxHeapSize, "Ergonomics decided on incompatible maximum young and heap sizes");
assert(MinNewSize <= NewSize, "Ergonomics decided on incompatible minimum and initial young gen sizes");
assert(NewSize <= MaxNewSize, "Ergonomics decided on incompatible initial and maximum young gen sizes");
assert(MinNewSize % GenAlignment == 0, "_min_young_size alignment");
assert(NewSize % GenAlignment == 0, "_initial_young_size alignment");
assert(MaxNewSize % GenAlignment == 0, "MaxNewSize alignment");
assert(MinNewSize <= bound_minus_alignment(MinNewSize, MinHeapSize, GenAlignment),
assert(MinNewSize % SpaceAlignment == 0, "_min_young_size alignment");
assert(NewSize % SpaceAlignment == 0, "_initial_young_size alignment");
assert(MaxNewSize % SpaceAlignment == 0, "MaxNewSize alignment");
assert(MinNewSize <= bound_minus_alignment(MinNewSize, MinHeapSize, SpaceAlignment),
"Ergonomics made minimum young generation larger than minimum heap");
assert(NewSize <= bound_minus_alignment(NewSize, InitialHeapSize, GenAlignment),
assert(NewSize <= bound_minus_alignment(NewSize, InitialHeapSize, SpaceAlignment),
"Ergonomics made initial young generation larger than initial heap");
assert(MaxNewSize <= bound_minus_alignment(MaxNewSize, MaxHeapSize, GenAlignment),
assert(MaxNewSize <= bound_minus_alignment(MaxNewSize, MaxHeapSize, SpaceAlignment),
"Ergonomics made maximum young generation lager than maximum heap");
assert(MinOldSize <= OldSize, "Ergonomics decided on incompatible minimum and initial old gen sizes");
assert(OldSize <= MaxOldSize, "Ergonomics decided on incompatible initial and maximum old gen sizes");
assert(MaxOldSize % GenAlignment == 0, "MaxOldSize alignment");
assert(OldSize % GenAlignment == 0, "OldSize alignment");
assert(MaxOldSize % SpaceAlignment == 0, "MaxOldSize alignment");
assert(OldSize % SpaceAlignment == 0, "OldSize alignment");
assert(MaxHeapSize <= (MaxNewSize + MaxOldSize), "Total maximum heap sizes must be sum of generation maximum sizes");
assert(MinNewSize + MinOldSize <= MinHeapSize, "Minimum generation sizes exceed minimum heap size");
assert(NewSize + OldSize == InitialHeapSize, "Initial generation sizes should match initial heap size");

View File

@ -35,8 +35,6 @@ extern size_t MaxOldSize;
extern size_t OldSize;
extern size_t GenAlignment;
class GenArguments : public GCArguments {
friend class TestGenCollectorPolicy; // Testing
private:

View File

@ -23,6 +23,7 @@
#include "gc/z/zAllocator.hpp"
#include "gc/z/zObjectAllocator.hpp"
#include "gc/z/zPageAge.inline.hpp"
ZAllocatorEden* ZAllocator::_eden;
ZAllocatorForRelocation* ZAllocator::_relocation[ZAllocator::_relocation_allocators];
@ -47,7 +48,7 @@ ZPageAge ZAllocatorForRelocation::install() {
for (uint i = 0; i < ZAllocator::_relocation_allocators; ++i) {
if (_relocation[i] == nullptr) {
_relocation[i] = this;
return static_cast<ZPageAge>(i + 1);
return to_zpageage(i + 1);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,7 +35,7 @@ class ZPage;
class ZAllocator {
public:
static constexpr uint _relocation_allocators = static_cast<uint>(ZPageAge::old);
static constexpr uint _relocation_allocators = ZPageAgeCount - 1;
protected:
ZObjectAllocator _object_allocator;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,13 +28,14 @@
#include "gc/z/zAddress.inline.hpp"
#include "gc/z/zHeap.hpp"
#include "gc/z/zPageAge.inline.hpp"
inline ZAllocatorEden* ZAllocator::eden() {
return _eden;
}
inline ZAllocatorForRelocation* ZAllocator::relocation(ZPageAge page_age) {
return _relocation[static_cast<uint>(page_age) - 1];
return _relocation[untype(page_age - 1)];
}
inline ZAllocatorForRelocation* ZAllocator::old() {

View File

@ -41,6 +41,7 @@
#include "gc/z/zHeap.inline.hpp"
#include "gc/z/zJNICritical.hpp"
#include "gc/z/zMark.inline.hpp"
#include "gc/z/zPageAge.inline.hpp"
#include "gc/z/zPageAllocator.hpp"
#include "gc/z/zRelocationSet.inline.hpp"
#include "gc/z/zRelocationSetSelector.inline.hpp"
@ -699,11 +700,10 @@ uint ZGenerationYoung::compute_tenuring_threshold(ZRelocationSetSelectorStats st
uint last_populated_age = 0;
size_t last_populated_live = 0;
for (uint i = 0; i <= ZPageAgeMax; ++i) {
const ZPageAge age = static_cast<ZPageAge>(i);
for (ZPageAge age : ZPageAgeRange()) {
const size_t young_live = stats.small(age).live() + stats.medium(age).live() + stats.large(age).live();
if (young_live > 0) {
last_populated_age = i;
last_populated_age = untype(age);
last_populated_live = young_live;
if (young_live_last > 0) {
young_life_expectancy_sum += double(young_live) / double(young_live_last);
@ -842,8 +842,8 @@ void ZGenerationYoung::mark_start() {
// Retire allocating pages
ZAllocator::eden()->retire_pages();
for (ZPageAge i = ZPageAge::survivor1; i <= ZPageAge::survivor14; i = static_cast<ZPageAge>(static_cast<uint>(i) + 1)) {
ZAllocator::relocation(i)->retire_pages();
for (ZPageAge age : ZPageAgeRangeSurvivor) {
ZAllocator::relocation(age)->retire_pages();
}
// Reset allocated/reclaimed/used statistics

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,7 @@
#ifndef SHARE_GC_Z_ZPAGEAGE_HPP
#define SHARE_GC_Z_ZPAGEAGE_HPP
#include "utilities/enumIterator.hpp"
#include "utilities/globalDefinitions.hpp"
enum class ZPageAge : uint8_t {
@ -45,6 +46,19 @@ enum class ZPageAge : uint8_t {
old
};
constexpr uint ZPageAgeMax = static_cast<uint>(ZPageAge::old);
constexpr uint ZPageAgeCount = static_cast<uint>(ZPageAge::old) + 1;
constexpr ZPageAge ZPageAgeLastPlusOne = static_cast<ZPageAge>(ZPageAgeCount);
ENUMERATOR_RANGE(ZPageAge,
ZPageAge::eden,
ZPageAge::old);
using ZPageAgeRange = EnumRange<ZPageAge>;
constexpr ZPageAgeRange ZPageAgeRangeEden = ZPageAgeRange::create<ZPageAge::eden, ZPageAge::survivor1>();
constexpr ZPageAgeRange ZPageAgeRangeYoung = ZPageAgeRange::create<ZPageAge::eden, ZPageAge::old>();
constexpr ZPageAgeRange ZPageAgeRangeSurvivor = ZPageAgeRange::create<ZPageAge::survivor1, ZPageAge::old>();
constexpr ZPageAgeRange ZPageAgeRangeRelocation = ZPageAgeRange::create<ZPageAge::survivor1, ZPageAgeLastPlusOne>();
constexpr ZPageAgeRange ZPageAgeRangeOld = ZPageAgeRange::create<ZPageAge::old, ZPageAgeLastPlusOne>();
#endif // SHARE_GC_Z_ZPAGEAGE_HPP

View File

@ -1,12 +1,10 @@
/*
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@ -23,14 +21,32 @@
* questions.
*/
package jdk.internal.access;
#ifndef SHARE_GC_Z_ZPAGEAGE_INLINE_HPP
#define SHARE_GC_Z_ZPAGEAGE_INLINE_HPP
public interface JavaAWTAccess {
#include "gc/z/zPageAge.hpp"
// Returns the AppContext used for applet logging isolation, or null if
// no isolation is required.
// If there's no applet, or if the caller is a stand alone application,
// or running in the main app context, returns null.
// Otherwise, returns the AppContext of the calling applet.
public Object getAppletContext();
#include "utilities/checkedCast.hpp"
#include <type_traits>
inline uint untype(ZPageAge age) {
return static_cast<uint>(age);
}
inline ZPageAge to_zpageage(uint age) {
assert(age < ZPageAgeCount, "Invalid age");
return static_cast<ZPageAge>(age);
}
inline ZPageAge operator+(ZPageAge age, size_t size) {
const auto size_value = checked_cast<std::underlying_type_t<ZPageAge>>(size);
return to_zpageage(untype(age) + size_value);
}
inline ZPageAge operator-(ZPageAge age, size_t size) {
const auto size_value = checked_cast<std::underlying_type_t<ZPageAge>>(size);
return to_zpageage(untype(age) - size_value);
}
#endif // SHARE_GC_Z_ZPAGEAGE_INLINE_HPP

View File

@ -488,11 +488,11 @@ public:
}
ZPage* shared(ZPageAge age) {
return _shared[static_cast<uint>(age) - 1];
return _shared[untype(age - 1)];
}
void set_shared(ZPageAge age, ZPage* page) {
_shared[static_cast<uint>(age) - 1] = page;
_shared[untype(age - 1)] = page;
}
ZPage* alloc_and_retire_target_page(ZForwarding* forwarding, ZPage* target) {
@ -570,11 +570,11 @@ private:
ZPage* target(ZPageAge age) {
return _target[static_cast<uint>(age) - 1];
return _target[untype(age - 1)];
}
void set_target(ZPageAge age, ZPage* page) {
_target[static_cast<uint>(age) - 1] = page;
_target[untype(age - 1)] = page;
}
size_t object_alignment() const {
@ -1232,12 +1232,12 @@ ZPageAge ZRelocate::compute_to_age(ZPageAge from_age) {
return ZPageAge::old;
}
const uint age = static_cast<uint>(from_age);
const uint age = untype(from_age);
if (age >= ZGeneration::young()->tenuring_threshold()) {
return ZPageAge::old;
}
return static_cast<ZPageAge>(age + 1);
return to_zpageage(age + 1);
}
class ZFlipAgePagesTask : public ZTask {

View File

@ -25,6 +25,7 @@
#include "gc/z/zArray.inline.hpp"
#include "gc/z/zForwarding.inline.hpp"
#include "gc/z/zPage.inline.hpp"
#include "gc/z/zPageAge.inline.hpp"
#include "gc/z/zRelocationSetSelector.inline.hpp"
#include "jfr/jfrEvents.hpp"
#include "logging/log.hpp"
@ -117,8 +118,8 @@ void ZRelocationSetSelectorGroup::select_inner() {
const int npages = _live_pages.length();
int selected_from = 0;
int selected_to = 0;
size_t npages_selected[ZPageAgeMax + 1] = { 0 };
size_t selected_live_bytes[ZPageAgeMax + 1] = { 0 };
size_t npages_selected[ZPageAgeCount] = { 0 };
size_t selected_live_bytes[ZPageAgeCount] = { 0 };
size_t selected_forwarding_entries = 0;
size_t from_live_bytes = 0;
@ -149,8 +150,8 @@ void ZRelocationSetSelectorGroup::select_inner() {
if (diff_reclaimable > _fragmentation_limit) {
selected_from = from;
selected_to = to;
selected_live_bytes[static_cast<uint>(page->age())] += page_live_bytes;
npages_selected[static_cast<uint>(page->age())] += 1;
selected_live_bytes[untype(page->age())] += page_live_bytes;
npages_selected[untype(page->age())] += 1;
selected_forwarding_entries = from_forwarding_entries;
}
@ -172,7 +173,7 @@ void ZRelocationSetSelectorGroup::select_inner() {
_forwarding_entries = selected_forwarding_entries;
// Update statistics
for (uint i = 0; i <= ZPageAgeMax; ++i) {
for (uint i = 0; i < ZPageAgeCount; ++i) {
_stats[i]._relocate = selected_live_bytes[i];
_stats[i]._npages_selected = npages_selected[i];
}
@ -200,7 +201,7 @@ void ZRelocationSetSelectorGroup::select() {
}
ZRelocationSetSelectorGroupStats s{};
for (uint i = 0; i <= ZPageAgeMax; ++i) {
for (uint i = 0; i < ZPageAgeCount; ++i) {
s._npages_candidates += _stats[i].npages_candidates();
s._total += _stats[i].total();
s._empty += _stats[i].empty();
@ -239,8 +240,8 @@ void ZRelocationSetSelector::select() {
ZRelocationSetSelectorStats ZRelocationSetSelector::stats() const {
ZRelocationSetSelectorStats stats;
for (uint i = 0; i <= ZPageAgeMax; ++i) {
const ZPageAge age = static_cast<ZPageAge>(i);
for (ZPageAge age : ZPageAgeRange()) {
const uint i = untype(age);
stats._small[i] = _small.stats(age);
stats._medium[i] = _medium.stats(age);
stats._large[i] = _large.stats(age);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -62,9 +62,9 @@ class ZRelocationSetSelectorStats {
friend class ZRelocationSetSelector;
private:
ZRelocationSetSelectorGroupStats _small[ZPageAgeMax + 1];
ZRelocationSetSelectorGroupStats _medium[ZPageAgeMax + 1];
ZRelocationSetSelectorGroupStats _large[ZPageAgeMax + 1];
ZRelocationSetSelectorGroupStats _small[ZPageAgeCount];
ZRelocationSetSelectorGroupStats _medium[ZPageAgeCount];
ZRelocationSetSelectorGroupStats _large[ZPageAgeCount];
size_t _has_relocatable_pages;
@ -90,7 +90,7 @@ private:
ZArray<ZPage*> _live_pages;
ZArray<ZPage*> _not_selected_pages;
size_t _forwarding_entries;
ZRelocationSetSelectorGroupStats _stats[ZPageAgeMax + 1];
ZRelocationSetSelectorGroupStats _stats[ZPageAgeCount];
bool is_disabled();
bool is_selectable();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,6 +29,7 @@
#include "gc/z/zArray.inline.hpp"
#include "gc/z/zGlobals.hpp"
#include "gc/z/zPage.inline.hpp"
#include "gc/z/zPageAge.inline.hpp"
#include "utilities/powerOfTwo.hpp"
inline size_t ZRelocationSetSelectorGroupStats::npages_candidates() const {
@ -60,15 +61,15 @@ inline bool ZRelocationSetSelectorStats::has_relocatable_pages() const {
}
inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorStats::small(ZPageAge age) const {
return _small[static_cast<uint>(age)];
return _small[untype(age)];
}
inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorStats::medium(ZPageAge age) const {
return _medium[static_cast<uint>(age)];
return _medium[untype(age)];
}
inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorStats::large(ZPageAge age) const {
return _large[static_cast<uint>(age)];
return _large[untype(age)];
}
inline bool ZRelocationSetSelectorGroup::pre_filter_page(const ZPage* page, size_t live_bytes) const {
@ -113,7 +114,7 @@ inline void ZRelocationSetSelectorGroup::register_live_page(ZPage* page) {
}
const size_t size = page->size();
const uint age = static_cast<uint>(page->age());
const uint age = untype(page->age());
_stats[age]._npages_candidates++;
_stats[age]._total += size;
_stats[age]._live += live;
@ -122,7 +123,7 @@ inline void ZRelocationSetSelectorGroup::register_live_page(ZPage* page) {
inline void ZRelocationSetSelectorGroup::register_empty_page(ZPage* page) {
const size_t size = page->size();
const uint age = static_cast<uint>(page->age());
const uint age = untype(page->age());
_stats[age]._npages_candidates++;
_stats[age]._total += size;
_stats[age]._empty += size;
@ -141,7 +142,7 @@ inline size_t ZRelocationSetSelectorGroup::forwarding_entries() const {
}
inline const ZRelocationSetSelectorGroupStats& ZRelocationSetSelectorGroup::stats(ZPageAge age) const {
return _stats[static_cast<uint>(age)];
return _stats[untype(age)];
}
inline void ZRelocationSetSelector::register_live_page(ZPage* page) {
@ -188,8 +189,7 @@ inline void ZRelocationSetSelector::clear_empty_pages() {
inline size_t ZRelocationSetSelector::total() const {
size_t sum = 0;
for (uint i = 0; i <= ZPageAgeMax; ++i) {
const ZPageAge age = static_cast<ZPageAge>(i);
for (ZPageAge age : ZPageAgeRange()) {
sum += _small.stats(age).total() + _medium.stats(age).total() + _large.stats(age).total();
}
return sum;
@ -197,8 +197,7 @@ inline size_t ZRelocationSetSelector::total() const {
inline size_t ZRelocationSetSelector::empty() const {
size_t sum = 0;
for (uint i = 0; i <= ZPageAgeMax; ++i) {
const ZPageAge age = static_cast<ZPageAge>(i);
for (ZPageAge age : ZPageAgeRange()) {
sum += _small.stats(age).empty() + _medium.stats(age).empty() + _large.stats(age).empty();
}
return sum;
@ -206,8 +205,7 @@ inline size_t ZRelocationSetSelector::empty() const {
inline size_t ZRelocationSetSelector::relocate() const {
size_t sum = 0;
for (uint i = 0; i <= ZPageAgeMax; ++i) {
const ZPageAge age = static_cast<ZPageAge>(i);
for (ZPageAge age : ZPageAgeRange()) {
sum += _small.stats(age).relocate() + _medium.stats(age).relocate() + _large.stats(age).relocate();
}
return sum;

View File

@ -30,6 +30,7 @@
#include "gc/z/zGeneration.inline.hpp"
#include "gc/z/zGlobals.hpp"
#include "gc/z/zNMethodTable.hpp"
#include "gc/z/zPageAge.inline.hpp"
#include "gc/z/zPageAllocator.inline.hpp"
#include "gc/z/zRelocationSetSelector.inline.hpp"
#include "gc/z/zStat.hpp"
@ -1499,9 +1500,7 @@ void ZStatRelocation::print_page_summary() {
summary.relocate += stats.relocate();
};
for (uint i = 0; i <= ZPageAgeMax; ++i) {
const ZPageAge age = static_cast<ZPageAge>(i);
for (ZPageAge age : ZPageAgeRange()) {
account_page_size(small_summary, _selector_stats.small(age));
account_page_size(medium_summary, _selector_stats.medium(age));
account_page_size(large_summary, _selector_stats.large(age));
@ -1557,13 +1556,13 @@ void ZStatRelocation::print_age_table() {
.center("Large")
.end());
size_t live[ZPageAgeMax + 1] = {};
size_t total[ZPageAgeMax + 1] = {};
size_t live[ZPageAgeCount] = {};
size_t total[ZPageAgeCount] = {};
uint oldest_none_empty_age = 0;
for (uint i = 0; i <= ZPageAgeMax; ++i) {
ZPageAge age = static_cast<ZPageAge>(i);
for (ZPageAge age : ZPageAgeRange()) {
uint i = untype(age);
auto summarize_pages = [&](const ZRelocationSetSelectorGroupStats& stats) {
live[i] += stats.live();
total[i] += stats.total();
@ -1579,7 +1578,7 @@ void ZStatRelocation::print_age_table() {
}
for (uint i = 0; i <= oldest_none_empty_age; ++i) {
ZPageAge age = static_cast<ZPageAge>(i);
ZPageAge age = to_zpageage(i);
FormatBuffer<> age_str("");
if (age == ZPageAge::eden) {
@ -1791,8 +1790,7 @@ void ZStatHeap::at_select_relocation_set(const ZRelocationSetSelectorStats& stat
ZLocker<ZLock> locker(&_stat_lock);
size_t live = 0;
for (uint i = 0; i <= ZPageAgeMax; ++i) {
const ZPageAge age = static_cast<ZPageAge>(i);
for (ZPageAge age : ZPageAgeRange()) {
live += stats.small(age).live() + stats.medium(age).live() + stats.large(age).live();
}
_at_mark_end.live = live;

View File

@ -113,7 +113,7 @@
\
product(int, ZTenuringThreshold, -1, DIAGNOSTIC, \
"Young generation tenuring threshold, -1 for dynamic computation")\
range(-1, static_cast<int>(ZPageAgeMax)) \
range(-1, static_cast<int>(ZPageAgeCount) - 1) \
\
develop(bool, ZVerifyOops, false, \
"Verify accessed oops") \

View File

@ -1463,8 +1463,7 @@ JVMCIPrimitiveArray JVMCIEnv::new_byteArray(int length, JVMCI_TRAPS) {
JVMCIObjectArray JVMCIEnv::new_byte_array_array(int length, JVMCI_TRAPS) {
JavaThread* THREAD = JavaThread::current(); // For exception macros.
if (is_hotspot()) {
Klass* byteArrayArrayKlass = TypeArrayKlass::cast(Universe::byteArrayKlass())->array_klass(CHECK_(JVMCIObject()));
objArrayOop result = ObjArrayKlass::cast(byteArrayArrayKlass) ->allocate(length, CHECK_(JVMCIObject()));
objArrayOop result = oopFactory::new_objArray(Universe::byteArrayKlass(), length, CHECK_(JVMCIObject()));
return wrap(result);
} else {
JNIAccessMark jni(this, THREAD);

View File

@ -189,14 +189,6 @@ static size_t align_to_page_size(size_t size) {
}
void CodeHeap::on_code_mapping(char* base, size_t size) {
#ifdef LINUX
extern void linux_wrap_code(char* base, size_t size);
linux_wrap_code(base, size);
#endif
}
bool CodeHeap::reserve(ReservedSpace rs, size_t committed_size, size_t segment_size) {
assert(rs.size() >= committed_size, "reserved < committed");
assert(is_aligned(committed_size, rs.page_size()), "must be page aligned");
@ -213,7 +205,6 @@ bool CodeHeap::reserve(ReservedSpace rs, size_t committed_size, size_t segment_s
return false;
}
on_code_mapping(_memory.low(), _memory.committed_size());
_number_of_committed_segments = size_to_segments(_memory.committed_size());
_number_of_reserved_segments = size_to_segments(_memory.reserved_size());
assert(_number_of_reserved_segments >= _number_of_committed_segments, "just checking");
@ -250,7 +241,6 @@ bool CodeHeap::expand_by(size_t size) {
}
char* base = _memory.low() + _memory.committed_size();
if (!_memory.expand_by(dm)) return false;
on_code_mapping(base, dm);
size_t i = _number_of_committed_segments;
_number_of_committed_segments = size_to_segments(_memory.committed_size());
assert(_number_of_reserved_segments == size_to_segments(_memory.reserved_size()), "number of reserved segments should not change");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -146,9 +146,6 @@ class CodeHeap : public CHeapObj<mtCode> {
void* next_used(HeapBlock* b) const;
HeapBlock* block_start(void* p) const;
// to perform additional actions on creation of executable code
void on_code_mapping(char* base, size_t size);
public:
CodeHeap(const char* name, const CodeBlobType code_blob_type);

View File

@ -40,41 +40,41 @@
#include "utilities/utf8.hpp"
typeArrayOop oopFactory::new_boolArray(int length, TRAPS) {
return Universe::boolArrayKlass()->allocate(length, THREAD);
return Universe::boolArrayKlass()->allocate_instance(length, THREAD);
}
typeArrayOop oopFactory::new_charArray(int length, TRAPS) {
return Universe::charArrayKlass()->allocate(length, THREAD);
return Universe::charArrayKlass()->allocate_instance(length, THREAD);
}
typeArrayOop oopFactory::new_floatArray(int length, TRAPS) {
return Universe::floatArrayKlass()->allocate(length, THREAD);
return Universe::floatArrayKlass()->allocate_instance(length, THREAD);
}
typeArrayOop oopFactory::new_doubleArray(int length, TRAPS) {
return Universe::doubleArrayKlass()->allocate(length, THREAD);
return Universe::doubleArrayKlass()->allocate_instance(length, THREAD);
}
typeArrayOop oopFactory::new_byteArray(int length, TRAPS) {
return Universe::byteArrayKlass()->allocate(length, THREAD);
return Universe::byteArrayKlass()->allocate_instance(length, THREAD);
}
typeArrayOop oopFactory::new_shortArray(int length, TRAPS) {
return Universe::shortArrayKlass()->allocate(length, THREAD);
return Universe::shortArrayKlass()->allocate_instance(length, THREAD);
}
typeArrayOop oopFactory::new_intArray(int length, TRAPS) {
return Universe::intArrayKlass()->allocate(length, THREAD);
return Universe::intArrayKlass()->allocate_instance(length, THREAD);
}
typeArrayOop oopFactory::new_longArray(int length, TRAPS) {
return Universe::longArrayKlass()->allocate(length, THREAD);
return Universe::longArrayKlass()->allocate_instance(length, THREAD);
}
// create java.lang.Object[]
objArrayOop oopFactory::new_objectArray(int length, TRAPS) {
assert(Universe::objectArrayKlass() != nullptr, "Too early?");
return Universe::objectArrayKlass()->allocate(length, THREAD);
return Universe::objectArrayKlass()->allocate_instance(length, THREAD);
}
typeArrayOop oopFactory::new_charArray(const char* utf8_str, TRAPS) {
@ -88,7 +88,7 @@ typeArrayOop oopFactory::new_charArray(const char* utf8_str, TRAPS) {
typeArrayOop oopFactory::new_typeArray(BasicType type, int length, TRAPS) {
TypeArrayKlass* klass = Universe::typeArrayKlass(type);
return klass->allocate(length, THREAD);
return klass->allocate_instance(length, THREAD);
}
// Create a Java array that points to Symbol.

View File

@ -44,7 +44,7 @@
#include "runtime/mutexLocker.hpp"
#include "utilities/macros.hpp"
ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS) {
ObjArrayKlass* ObjArrayKlass::allocate_klass(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS) {
assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(),
"array klasses must be same size as InstanceKlass");
@ -100,7 +100,7 @@ ObjArrayKlass* ObjArrayKlass::allocate_objArray_klass(ClassLoaderData* loader_da
}
// Initialize instance variables
ObjArrayKlass* oak = ObjArrayKlass::allocate(loader_data, n, element_klass, name, CHECK_NULL);
ObjArrayKlass* oak = ObjArrayKlass::allocate_klass(loader_data, n, element_klass, name, CHECK_NULL);
ModuleEntry* module = oak->module();
assert(module != nullptr, "No module entry for array");
@ -149,7 +149,7 @@ size_t ObjArrayKlass::oop_size(oop obj) const {
return objArrayOop(obj)->object_size();
}
objArrayOop ObjArrayKlass::allocate(int length, TRAPS) {
objArrayOop ObjArrayKlass::allocate_instance(int length, TRAPS) {
check_array_allocation_length(length, arrayOopDesc::max_array_length(T_OBJECT), CHECK_NULL);
size_t size = objArrayOopDesc::object_size(length);
return (objArrayOop)Universe::heap()->array_allocate(this, size, length,
@ -160,7 +160,7 @@ oop ObjArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) {
int length = *sizes;
ArrayKlass* ld_klass = lower_dimension();
// If length < 0 allocate will throw an exception.
objArrayOop array = allocate(length, CHECK_NULL);
objArrayOop array = allocate_instance(length, CHECK_NULL);
objArrayHandle h_array (THREAD, array);
if (rank > 1) {
if (length != 0) {

View File

@ -33,8 +33,10 @@ class ClassLoaderData;
// ObjArrayKlass is the klass for objArrays
class ObjArrayKlass : public ArrayKlass {
friend class VMStructs;
friend class Deoptimization;
friend class JVMCIVMStructs;
friend class oopFactory;
friend class VMStructs;
public:
static const KlassKind Kind = ObjArrayKlassKind;
@ -47,7 +49,9 @@ class ObjArrayKlass : public ArrayKlass {
// Constructor
ObjArrayKlass(int n, Klass* element_klass, Symbol* name);
static ObjArrayKlass* allocate(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS);
static ObjArrayKlass* allocate_klass(ClassLoaderData* loader_data, int n, Klass* k, Symbol* name, TRAPS);
objArrayOop allocate_instance(int length, TRAPS);
public:
// For dummy objects
ObjArrayKlass() {}
@ -78,7 +82,6 @@ class ObjArrayKlass : public ArrayKlass {
static ObjArrayKlass* allocate_objArray_klass(ClassLoaderData* loader_data,
int n, Klass* element_klass, TRAPS);
objArrayOop allocate(int length, TRAPS);
oop multi_allocate(int rank, jint* sizes, TRAPS);
// Copying

View File

@ -50,7 +50,7 @@ TypeArrayKlass* TypeArrayKlass::create_klass(BasicType type,
ClassLoaderData* null_loader_data = ClassLoaderData::the_null_class_loader_data();
TypeArrayKlass* ak = TypeArrayKlass::allocate(null_loader_data, type, sym, CHECK_NULL);
TypeArrayKlass* ak = TypeArrayKlass::allocate_klass(null_loader_data, type, sym, CHECK_NULL);
// Call complete_create_array_klass after all instance variables have been initialized.
complete_create_array_klass(ak, ak->super(), ModuleEntryTable::javabase_moduleEntry(), CHECK_NULL);
@ -65,7 +65,7 @@ TypeArrayKlass* TypeArrayKlass::create_klass(BasicType type,
return ak;
}
TypeArrayKlass* TypeArrayKlass::allocate(ClassLoaderData* loader_data, BasicType type, Symbol* name, TRAPS) {
TypeArrayKlass* TypeArrayKlass::allocate_klass(ClassLoaderData* loader_data, BasicType type, Symbol* name, TRAPS) {
assert(TypeArrayKlass::header_size() <= InstanceKlass::header_size(),
"array klasses must be same size as InstanceKlass");
@ -101,7 +101,7 @@ oop TypeArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) {
// For typeArrays this is only called for the last dimension
assert(rank == 1, "just checking");
int length = *last_size;
return allocate(length, THREAD);
return allocate_instance(length, THREAD);
}

View File

@ -33,6 +33,8 @@ class ClassLoaderData;
// It contains the type and size of the elements
class TypeArrayKlass : public ArrayKlass {
friend class Deoptimization;
friend class oopFactory;
friend class VMStructs;
public:
@ -43,7 +45,10 @@ class TypeArrayKlass : public ArrayKlass {
// Constructor
TypeArrayKlass(BasicType type, Symbol* name);
static TypeArrayKlass* allocate(ClassLoaderData* loader_data, BasicType type, Symbol* name, TRAPS);
static TypeArrayKlass* allocate_klass(ClassLoaderData* loader_data, BasicType type, Symbol* name, TRAPS);
typeArrayOop allocate_common(int length, bool do_zero, TRAPS);
typeArrayOop allocate_instance(int length, TRAPS) { return allocate_common(length, true, THREAD); }
public:
TypeArrayKlass() {} // For dummy objects.
@ -66,8 +71,6 @@ class TypeArrayKlass : public ArrayKlass {
size_t oop_size(oop obj) const;
// Allocation
typeArrayOop allocate_common(int length, bool do_zero, TRAPS);
typeArrayOop allocate(int length, TRAPS) { return allocate_common(length, true, THREAD); }
oop multi_allocate(int rank, jint* sizes, TRAPS);
oop protection_domain() const { return nullptr; }

View File

@ -464,6 +464,14 @@ class PhaseCFG : public Phase {
Node* catch_cleanup_find_cloned_def(Block* use_blk, Node* def, Block* def_blk, int n_clone_idx);
void catch_cleanup_inter_block(Node *use, Block *use_blk, Node *def, Block *def_blk, int n_clone_idx);
// Ensure that n happens at b or above, i.e. at a block that dominates b.
// We expect n to be an orphan node without further inputs.
void ensure_node_is_at_block_or_above(Node* n, Block* b);
// Move node n from its current placement into the end of block b.
// Move also outgoing Mach projections.
void move_node_and_its_projections_to_block(Node* n, Block* b);
// Detect implicit-null-check opportunities. Basically, find null checks
// with suitable memory ops nearby. Use the memory op to do the null check.
// I can generate a memory op if there is not one nearby.

View File

@ -155,7 +155,6 @@ void IdealGraphPrinter::init(const char* file_name, bool use_multiple_files, boo
// in the mach where kill projections have no users but should
// appear in the dump.
_traverse_outs = true;
_should_send_method = true;
_output = nullptr;
buffer[0] = 0;
_depth = 0;
@ -300,13 +299,11 @@ void IdealGraphPrinter::print_inline_tree(InlineTree *tree) {
void IdealGraphPrinter::print_inlining() {
// Print inline tree
if (_should_send_method) {
InlineTree *inlineTree = C->ilt();
if (inlineTree != nullptr) {
print_inline_tree(inlineTree);
} else {
// print this method only
}
InlineTree *inlineTree = C->ilt();
if (inlineTree != nullptr) {
print_inline_tree(inlineTree);
} else {
// print this method only
}
}
@ -382,7 +379,6 @@ void IdealGraphPrinter::begin_method() {
tail(PROPERTIES_ELEMENT);
_should_send_method = true;
this->_current_method = method;
_xml->flush();
@ -975,7 +971,7 @@ void IdealGraphPrinter::print_graph(const char* name, const frame* fr) {
// Print current ideal graph
void IdealGraphPrinter::print(const char* name, Node* node, GrowableArray<const Node*>& visible_nodes, const frame* fr) {
if (!_current_method || !_should_send_method || node == nullptr) return;
if (!_current_method || node == nullptr) return;
if (name == nullptr) {
stringStream graph_name;

View File

@ -110,7 +110,6 @@ class IdealGraphPrinter : public CHeapObj<mtCompiler> {
ciMethod *_current_method;
int _depth;
char buffer[2048];
bool _should_send_method;
PhaseChaitin* _chaitin;
bool _traverse_outs;
Compile *C;

View File

@ -76,6 +76,36 @@ static bool needs_explicit_null_check_for_read(Node *val) {
return true;
}
void PhaseCFG::move_node_and_its_projections_to_block(Node* n, Block* b) {
assert(!is_CFG(n), "cannot move CFG node");
Block* old = get_block_for_node(n);
old->find_remove(n);
b->add_inst(n);
map_node_to_block(n, b);
// Check for Mach projections that also need to be moved.
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
Node* out = n->fast_out(i);
if (!out->is_MachProj()) {
continue;
}
assert(!n->is_MachProj(), "nested projections are not allowed");
move_node_and_its_projections_to_block(out, b);
}
}
void PhaseCFG::ensure_node_is_at_block_or_above(Node* n, Block* b) {
assert(!is_CFG(n), "cannot move CFG node");
Block* current = get_block_for_node(n);
if (current->dominates(b)) {
return; // n is already placed above b, do nothing.
}
// We only expect nodes without further inputs, like MachTemp or load Base.
assert(n->req() == 0 || (n->req() == 1 && n->in(0) == (Node*)C->root()),
"need for recursive hoisting not expected");
assert(b->dominates(current), "precondition: can only move n to b if b dominates n");
move_node_and_its_projections_to_block(n, b);
}
//------------------------------implicit_null_check----------------------------
// Detect implicit-null-check opportunities. Basically, find null checks
// with suitable memory ops nearby. Use the memory op to do the null check.
@ -160,12 +190,14 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo
Node *m = val->out(i);
if( !m->is_Mach() ) continue;
MachNode *mach = m->as_Mach();
if (mach->barrier_data() != 0) {
if (mach->barrier_data() != 0 &&
!mach->is_late_expanded_null_check_candidate()) {
// Using memory accesses with barriers to perform implicit null checks is
// not supported. These operations might expand into multiple assembly
// instructions during code emission, including new memory accesses (e.g.
// in G1's pre-barrier), which would invalidate the implicit null
// exception table.
// only supported if these are explicit marked as emitting a candidate
// memory access instruction at their initial address. If not marked as
// such, barrier-tagged operations might expand into one or several memory
// access instructions located at arbitrary offsets from the initial
// address, which would invalidate the implicit null exception table.
continue;
}
was_store = false;
@ -321,6 +353,14 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo
// Ignore DecodeN val which could be hoisted to where needed.
if( is_decoden ) continue;
}
if (mach->in(j)->is_MachTemp()) {
assert(mach->in(j)->outcnt() == 1, "MachTemp nodes should not be shared");
// Ignore MachTemp inputs, they can be safely hoisted with the candidate.
// MachTemp nodes have no inputs themselves and are only used to reserve
// a scratch register for the implementation of the node (e.g. in
// late-expanded GC barriers).
continue;
}
// Block of memory-op input
Block *inb = get_block_for_node(mach->in(j));
Block *b = block; // Start from nul check
@ -388,38 +428,24 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo
// Hoist it up to the end of the test block together with its inputs if they exist.
for (uint i = 2; i < val->req(); i++) {
// DecodeN has 2 regular inputs + optional MachTemp or load Base inputs.
Node *temp = val->in(i);
Block *tempb = get_block_for_node(temp);
if (!tempb->dominates(block)) {
assert(block->dominates(tempb), "sanity check: temp node placement");
// We only expect nodes without further inputs, like MachTemp or load Base.
assert(temp->req() == 0 || (temp->req() == 1 && temp->in(0) == (Node*)C->root()),
"need for recursive hoisting not expected");
tempb->find_remove(temp);
block->add_inst(temp);
map_node_to_block(temp, block);
}
}
valb->find_remove(val);
block->add_inst(val);
map_node_to_block(val, block);
// DecodeN on x86 may kill flags. Check for flag-killing projections
// that also need to be hoisted.
for (DUIterator_Fast jmax, j = val->fast_outs(jmax); j < jmax; j++) {
Node* n = val->fast_out(j);
if( n->is_MachProj() ) {
get_block_for_node(n)->find_remove(n);
block->add_inst(n);
map_node_to_block(n, block);
}
// Inputs of val may already be early enough, but if not move them together with val.
ensure_node_is_at_block_or_above(val->in(i), block);
}
move_node_and_its_projections_to_block(val, block);
}
}
// Move any MachTemp inputs to the end of the test block.
for (uint i = 0; i < best->req(); i++) {
Node* n = best->in(i);
if (n == nullptr || !n->is_MachTemp()) {
continue;
}
ensure_node_is_at_block_or_above(n, block);
}
// Hoist the memory candidate up to the end of the test block.
Block *old_block = get_block_for_node(best);
old_block->find_remove(best);
block->add_inst(best);
map_node_to_block(best, block);
move_node_and_its_projections_to_block(best, block);
// Move the control dependence if it is pinned to not-null block.
// Don't change it in other cases: null or dominating control.
@ -429,17 +455,6 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo
best->set_req(0, proj->in(0)->in(0));
}
// Check for flag-killing projections that also need to be hoisted
// Should be DU safe because no edge updates.
for (DUIterator_Fast jmax, j = best->fast_outs(jmax); j < jmax; j++) {
Node* n = best->fast_out(j);
if( n->is_MachProj() ) {
get_block_for_node(n)->find_remove(n);
block->add_inst(n);
map_node_to_block(n, block);
}
}
// proj==Op_True --> ne test; proj==Op_False --> eq test.
// One of two graph shapes got matched:
// (IfTrue (If (Bool NE (CmpP ptr null))))

View File

@ -1676,6 +1676,10 @@ bool PhaseIdealLoop::safe_for_if_replacement(const Node* dom) const {
// like various versions of induction variable+offset. Clone the
// computation per usage to allow it to sink out of the loop.
void PhaseIdealLoop::try_sink_out_of_loop(Node* n) {
bool is_raw_to_oop_cast = n->is_ConstraintCast() &&
n->in(1)->bottom_type()->isa_rawptr() &&
!n->bottom_type()->isa_rawptr();
if (has_ctrl(n) &&
!n->is_Phi() &&
!n->is_Bool() &&
@ -1685,7 +1689,9 @@ void PhaseIdealLoop::try_sink_out_of_loop(Node* n) {
!n->is_OpaqueNotNull() &&
!n->is_OpaqueInitializedAssertionPredicate() &&
!n->is_OpaqueTemplateAssertionPredicate() &&
!n->is_Type()) {
!is_raw_to_oop_cast && // don't extend live ranges of raw oops
(KillPathsReachableByDeadTypeNode || !n->is_Type())
) {
Node *n_ctrl = get_ctrl(n);
IdealLoopTree *n_loop = get_loop(n_ctrl);

View File

@ -386,6 +386,13 @@ public:
// Returns true if this node is a check that can be implemented with a trap.
virtual bool is_TrapBasedCheckNode() const { return false; }
// Whether this node is expanded during code emission into a sequence of
// instructions and the first instruction can perform an implicit null check.
virtual bool is_late_expanded_null_check_candidate() const {
return false;
}
void set_removed() { add_flag(Flag_is_removed_by_peephole); }
bool get_removed() { return (flags() & Flag_is_removed_by_peephole) != 0; }

View File

@ -2407,7 +2407,6 @@ void PhaseMacroExpand::eliminate_macro_nodes() {
}
}
// Next, attempt to eliminate allocations
_has_locks = false;
progress = true;
while (progress) {
progress = false;
@ -2431,7 +2430,6 @@ void PhaseMacroExpand::eliminate_macro_nodes() {
case Node::Class_Lock:
case Node::Class_Unlock:
assert(!n->as_AbstractLock()->is_eliminated(), "sanity");
_has_locks = true;
break;
case Node::Class_ArrayCopy:
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -83,9 +83,6 @@ private:
// projections extracted from a call node
CallProjections _callprojs;
// Additional data collected during macro expansion
bool _has_locks;
void expand_allocate(AllocateNode *alloc);
void expand_allocate_array(AllocateArrayNode *alloc);
void expand_allocate_common(AllocateNode* alloc,
@ -199,7 +196,7 @@ private:
Node* make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* ctl, Node* mem, BasicType ft, const Type *ftype, AllocateNode *alloc);
public:
PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn), _has_locks(false) {
PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn) {
_igvn.set_delay_transform(true);
}

View File

@ -2015,8 +2015,10 @@ void PhaseOutput::FillExceptionTables(uint cnt, uint *call_returns, uint *inct_s
// Handle implicit null exception table updates
if (n->is_MachNullCheck()) {
assert(n->in(1)->as_Mach()->barrier_data() == 0,
"Implicit null checks on memory accesses with barriers are not yet supported");
MachNode* access = n->in(1)->as_Mach();
assert(access->barrier_data() == 0 ||
access->is_late_expanded_null_check_candidate(),
"Implicit null checks on memory accesses with barriers are only supported on nodes explicitly marked as null-check candidates");
uint block_num = block->non_connector_successor(0)->_pre_order;
_inc_table.append(inct_starts[inct_cnt++], blk_labels[block_num].loc_pos());
continue;

View File

@ -318,8 +318,10 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) {
const TypeInstPtr* elem_klass = gvn().type(argument(3))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(4))->isa_int();
if (opr == nullptr || vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr ||
!opr->is_con() || vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) {
if (opr == nullptr || !opr->is_con() ||
vector_klass == nullptr || vector_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con()) {
log_if_needed(" ** missing constant: opr=%s vclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
NodeClassNames[argument(1)->Opcode()],
@ -587,7 +589,11 @@ bool LibraryCallKit::inline_vector_mask_operation() {
const TypeInt* vlen = gvn().type(argument(3))->isa_int();
Node* mask = argument(4);
if (mask_klass == nullptr || elem_klass == nullptr || mask->is_top() || vlen == nullptr) {
if (mask_klass == nullptr || mask_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con() ||
oper == nullptr || !oper->is_con() ||
mask->is_top()) {
return false; // dead code
}
@ -647,9 +653,11 @@ bool LibraryCallKit::inline_vector_frombits_coerced() {
// MODE_BITS_COERCED_LONG_TO_MASK for VectorMask.fromLong operation.
const TypeInt* mode = gvn().type(argument(5))->isa_int();
if (vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr || mode == nullptr ||
bits_type == nullptr || vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr ||
!vlen->is_con() || !mode->is_con()) {
if (vector_klass == nullptr || vector_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con() ||
bits_type == nullptr ||
mode == nullptr || !mode->is_con()) {
log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s bitwise=%s",
NodeClassNames[argument(0)->Opcode()],
NodeClassNames[argument(1)->Opcode()],
@ -775,8 +783,10 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) {
const TypeInt* vlen = gvn().type(argument(2))->isa_int();
const TypeInt* from_ms = gvn().type(argument(6))->isa_int();
if (vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr || !from_ms->is_con() ||
vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) {
if (vector_klass == nullptr || vector_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con() ||
from_ms == nullptr || !from_ms->is_con()) {
log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s from_ms=%s",
NodeClassNames[argument(0)->Opcode()],
NodeClassNames[argument(1)->Opcode()],
@ -983,9 +993,11 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) {
const TypeInt* vlen = gvn().type(argument(3))->isa_int();
const TypeInt* from_ms = gvn().type(argument(7))->isa_int();
if (vector_klass == nullptr || mask_klass == nullptr || elem_klass == nullptr || vlen == nullptr ||
vector_klass->const_oop() == nullptr || mask_klass->const_oop() == nullptr || from_ms == nullptr ||
elem_klass->const_oop() == nullptr || !vlen->is_con() || !from_ms->is_con()) {
if (vector_klass == nullptr || vector_klass->const_oop() == nullptr ||
mask_klass == nullptr || mask_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con() ||
from_ms == nullptr || !from_ms->is_con()) {
log_if_needed(" ** missing constant: vclass=%s mclass=%s etype=%s vlen=%s from_ms=%s",
NodeClassNames[argument(0)->Opcode()],
NodeClassNames[argument(1)->Opcode()],
@ -1222,8 +1234,10 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) {
const TypeInt* vlen = gvn().type(argument(3))->isa_int();
const TypeInstPtr* vector_idx_klass = gvn().type(argument(4))->isa_instptr();
if (vector_klass == nullptr || elem_klass == nullptr || vector_idx_klass == nullptr || vlen == nullptr ||
vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || vector_idx_klass->const_oop() == nullptr || !vlen->is_con()) {
if (vector_klass == nullptr || vector_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con() ||
vector_idx_klass == nullptr || vector_idx_klass->const_oop() == nullptr) {
log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s viclass=%s",
NodeClassNames[argument(0)->Opcode()],
NodeClassNames[argument(2)->Opcode()],
@ -1409,8 +1423,10 @@ bool LibraryCallKit::inline_vector_reduction() {
const TypeInstPtr* elem_klass = gvn().type(argument(3))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(4))->isa_int();
if (opr == nullptr || vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr ||
!opr->is_con() || vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) {
if (opr == nullptr || !opr->is_con() ||
vector_klass == nullptr || vector_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con()) {
log_if_needed(" ** missing constant: opr=%s vclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
NodeClassNames[argument(1)->Opcode()],
@ -1547,8 +1563,10 @@ bool LibraryCallKit::inline_vector_test() {
const TypeInstPtr* elem_klass = gvn().type(argument(2))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(3))->isa_int();
if (cond == nullptr || vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr ||
!cond->is_con() || vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) {
if (cond == nullptr || !cond->is_con() ||
vector_klass == nullptr || vector_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con()) {
log_if_needed(" ** missing constant: cond=%s vclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
NodeClassNames[argument(1)->Opcode()],
@ -2505,10 +2523,10 @@ bool LibraryCallKit::inline_vector_extract() {
const TypeInt* vlen = gvn().type(argument(2))->isa_int();
const TypeInt* idx = gvn().type(argument(4))->isa_int();
if (vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr || idx == nullptr) {
return false; // dead code
}
if (vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) {
if (vector_klass == nullptr || vector_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con() ||
idx == nullptr || !idx->is_con()) {
log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
NodeClassNames[argument(1)->Opcode()],
@ -2811,9 +2829,11 @@ bool LibraryCallKit::inline_vector_compress_expand() {
const TypeInstPtr* elem_klass = gvn().type(argument(3))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(4))->isa_int();
if (vector_klass == nullptr || elem_klass == nullptr || mask_klass == nullptr || vlen == nullptr ||
vector_klass->const_oop() == nullptr || mask_klass->const_oop() == nullptr ||
elem_klass->const_oop() == nullptr || !vlen->is_con() || !opr->is_con()) {
if (opr == nullptr || !opr->is_con() ||
vector_klass == nullptr || vector_klass->const_oop() == nullptr ||
mask_klass == nullptr || mask_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con()) {
log_if_needed(" ** missing constant: opr=%s vclass=%s mclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
NodeClassNames[argument(1)->Opcode()],
@ -2892,9 +2912,9 @@ bool LibraryCallKit::inline_index_vector() {
const TypeInstPtr* elem_klass = gvn().type(argument(1))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(2))->isa_int();
if (vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr ||
vector_klass->const_oop() == nullptr || !vlen->is_con() ||
elem_klass->const_oop() == nullptr) {
if (vector_klass == nullptr || vector_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con() ) {
log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
NodeClassNames[argument(1)->Opcode()],
@ -3026,8 +3046,9 @@ bool LibraryCallKit::inline_index_partially_in_upper_range() {
const TypeInstPtr* elem_klass = gvn().type(argument(1))->isa_instptr();
const TypeInt* vlen = gvn().type(argument(2))->isa_int();
if (mask_klass == nullptr || elem_klass == nullptr || vlen == nullptr ||
mask_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) {
if (mask_klass == nullptr || mask_klass->const_oop() == nullptr ||
elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
vlen == nullptr || !vlen->is_con()) {
log_if_needed(" ** missing constant: mclass=%s etype=%s vlen=%s",
NodeClassNames[argument(0)->Opcode()],
NodeClassNames[argument(1)->Opcode()],

View File

@ -2285,9 +2285,11 @@ JNI_ENTRY(jobjectArray, jni_NewObjectArray(JNIEnv *env, jsize length, jclass ele
jobjectArray ret = nullptr;
DT_RETURN_MARK(NewObjectArray, jobjectArray, (const jobjectArray&)ret);
Klass* ek = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(elementClass));
Klass* ak = ek->array_klass(CHECK_NULL);
ObjArrayKlass::cast(ak)->initialize(CHECK_NULL);
objArrayOop result = ObjArrayKlass::cast(ak)->allocate(length, CHECK_NULL);
// Make sure bottom_klass is initialized.
ek->initialize(CHECK_NULL);
objArrayOop result = oopFactory::new_objArray(ek, length, CHECK_NULL);
oop initial_value = JNIHandles::resolve(initialElement);
if (initial_value != nullptr) { // array already initialized with null
for (int index = 0; index < length; index++) {

View File

@ -28,6 +28,7 @@
#include "code/location.hpp"
#include "jni.h"
#include "jvm.h"
#include "memory/oopFactory.hpp"
#include "oops/klass.inline.hpp"
#include "oops/typeArrayOop.inline.hpp"
#include "prims/vectorSupport.hpp"
@ -109,9 +110,7 @@ Handle VectorSupport::allocate_vector_payload_helper(InstanceKlass* ik, frame* f
int elem_size = type2aelembytes(elem_bt);
// On-heap vector values are represented as primitive arrays.
TypeArrayKlass* tak = Universe::typeArrayKlass(elem_bt);
typeArrayOop arr = tak->allocate(num_elem, CHECK_NH); // safepoint
typeArrayOop arr = oopFactory::new_typeArray(elem_bt, num_elem, CHECK_NH); // safepoint
if (location.is_register()) {
// Value was in a callee-saved register.

View File

@ -583,28 +583,6 @@ WB_ENTRY(jboolean, WB_G1HasRegionsToUncommit(JNIEnv* env, jobject o))
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1HasRegionsToUncommit: G1 GC is not enabled");
WB_END
#endif // INCLUDE_G1GC
#if INCLUDE_PARALLELGC
WB_ENTRY(jlong, WB_PSVirtualSpaceAlignment(JNIEnv* env, jobject o))
if (UseParallelGC) {
return GenAlignment;
}
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_PSVirtualSpaceAlignment: Parallel GC is not enabled");
WB_END
WB_ENTRY(jlong, WB_PSHeapGenerationAlignment(JNIEnv* env, jobject o))
if (UseParallelGC) {
return GenAlignment;
}
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_PSHeapGenerationAlignment: Parallel GC is not enabled");
WB_END
#endif // INCLUDE_PARALLELGC
#if INCLUDE_G1GC
WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env))
if (UseG1GC) {
ResourceMark rm(THREAD);
@ -2773,10 +2751,6 @@ static JNINativeMethod methods[] = {
{CC"g1MemoryNodeIds", CC"()[I", (void*)&WB_G1MemoryNodeIds },
{CC"g1GetMixedGCInfo", CC"(I)[J", (void*)&WB_G1GetMixedGCInfo },
#endif // INCLUDE_G1GC
#if INCLUDE_PARALLELGC
{CC"psVirtualSpaceAlignment",CC"()J", (void*)&WB_PSVirtualSpaceAlignment},
{CC"psHeapGenerationAlignment",CC"()J", (void*)&WB_PSHeapGenerationAlignment},
#endif
{CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc },
{CC"NMTMallocWithPseudoStack", CC"(JI)J", (void*)&WB_NMTMallocWithPseudoStack},
{CC"NMTMallocWithPseudoStackAndType", CC"(JII)J", (void*)&WB_NMTMallocWithPseudoStackAndType},

View File

@ -528,10 +528,6 @@ static SpecialFlag const special_jvm_flags[] = {
{ "DynamicDumpSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() },
{ "RequireSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() },
{ "UseSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() },
#ifdef LINUX
{ "UseLinuxPosixThreadCPUClocks", JDK_Version::jdk(24), JDK_Version::jdk(25), JDK_Version::jdk(26) },
{ "UseOprofile", JDK_Version::jdk(25), JDK_Version::jdk(26), JDK_Version::jdk(27) },
#endif
{ "LockingMode", JDK_Version::jdk(24), JDK_Version::jdk(26), JDK_Version::jdk(27) },
#ifdef _LP64
{ "UseCompressedClassPointers", JDK_Version::jdk(25), JDK_Version::jdk(26), JDK_Version::undefined() },
@ -541,7 +537,9 @@ static SpecialFlag const special_jvm_flags[] = {
// -------------- Obsolete Flags - sorted by expired_in --------------
{ "PerfDataSamplingInterval", JDK_Version::undefined(), JDK_Version::jdk(25), JDK_Version::jdk(26) },
#ifdef LINUX
{ "UseOprofile", JDK_Version::jdk(25), JDK_Version::jdk(26), JDK_Version::jdk(27) },
#endif
{ "MetaspaceReclaimPolicy", JDK_Version::undefined(), JDK_Version::jdk(21), JDK_Version::undefined() },
{ "ZGenerational", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::undefined() },
{ "ZMarkStackSpaceLimit", JDK_Version::undefined(), JDK_Version::jdk(25), JDK_Version::undefined() },

View File

@ -1274,11 +1274,11 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap*
assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length");
int len = sv->field_size() / type2size[ak->element_type()];
InternalOOMEMark iom(THREAD);
obj = ak->allocate(len, THREAD);
obj = ak->allocate_instance(len, THREAD);
} else if (k->is_objArray_klass()) {
ObjArrayKlass* ak = ObjArrayKlass::cast(k);
InternalOOMEMark iom(THREAD);
obj = ak->allocate(sv->field_size(), THREAD);
obj = ak->allocate_instance(sv->field_size(), THREAD);
}
if (obj == nullptr) {

View File

@ -320,9 +320,16 @@ void Reflection::array_set(jvalue* value, arrayOop a, int index, BasicType value
}
}
// Conversion
static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror) {
assert(java_lang_Class::is_primitive(basic_type_mirror),
"just checking");
return java_lang_Class::primitive_type(basic_type_mirror);
}
static Klass* basic_type_mirror_to_arrayklass(oop basic_type_mirror, TRAPS) {
assert(java_lang_Class::is_primitive(basic_type_mirror), "just checking");
BasicType type = java_lang_Class::primitive_type(basic_type_mirror);
BasicType type = basic_type_mirror_to_basic_type(basic_type_mirror);
if (type == T_VOID) {
THROW_NULL(vmSymbols::java_lang_IllegalArgumentException());
}
@ -339,8 +346,11 @@ arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) {
THROW_MSG_NULL(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length));
}
if (java_lang_Class::is_primitive(element_mirror)) {
Klass* tak = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL);
return TypeArrayKlass::cast(tak)->allocate(length, THREAD);
BasicType type = basic_type_mirror_to_basic_type(element_mirror);
if (type == T_VOID) {
THROW_NULL(vmSymbols::java_lang_IllegalArgumentException());
}
return oopFactory::new_typeArray(type, length, CHECK_NULL);
} else {
Klass* k = java_lang_Class::as_Klass(element_mirror);
if (k->is_array_klass() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) {
@ -907,13 +917,6 @@ static methodHandle resolve_interface_call(InstanceKlass* klass,
return methodHandle(THREAD, info.selected_method());
}
// Conversion
static BasicType basic_type_mirror_to_basic_type(oop basic_type_mirror) {
assert(java_lang_Class::is_primitive(basic_type_mirror),
"just checking");
return java_lang_Class::primitive_type(basic_type_mirror);
}
// Narrowing of basic types. Used to create correct jvalues for
// boolean, byte, char and short return return values from interpreter
// which are returned as ints. Throws IllegalArgumentException.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,13 +25,14 @@
#ifndef SHARE_UTILITIES_ENUMITERATOR_HPP
#define SHARE_UTILITIES_ENUMITERATOR_HPP
#include <type_traits>
#include <limits>
#include "memory/allStatic.hpp"
#include "metaprogramming/enableIf.hpp"
#include "metaprogramming/primitiveConversions.hpp"
#include "utilities/debug.hpp"
#include <limits>
#include <type_traits>
// Iteration support for enums.
//
// E is enum type, U is underlying type of E.
@ -147,6 +148,12 @@ public:
assert(value <= end, "out of range");
}
template <T Value>
static constexpr void assert_in_range() {
static_assert(_start <= static_cast<Underlying>(Value), "out of range");
static_assert(static_cast<Underlying>(Value) <= _end, "out of range");
}
// Convert an enumerator value to the corresponding underlying type.
static constexpr Underlying underlying_value(T value) {
return static_cast<Underlying>(value);
@ -229,6 +236,12 @@ class EnumRange {
assert(size() > 0, "empty range");
}
struct ConstExprConstructTag {};
constexpr EnumRange(T start, T end, ConstExprConstructTag) :
_start(Traits::underlying_value(start)),
_end(Traits::underlying_value(end)) {}
public:
using EnumType = T;
using Iterator = EnumIterator<T>;
@ -252,6 +265,14 @@ public:
assert(start <= end, "invalid range");
}
template <T Start, T End>
static constexpr EnumRange<T> create() {
Traits::template assert_in_range<Start>();
Traits::template assert_in_range<End>();
static_assert(Start <= End, "invalid range");
return EnumRange(Start, End, ConstExprConstructTag{});
}
// Return an iterator for the start of the range.
constexpr Iterator begin() const {
return Iterator(Traits::enumerator(_start));

View File

@ -38,7 +38,7 @@ import java.nio.charset.StandardCharsets;
* <p>
* The {@link #readln()} and {@link #readln(String)} methods decode bytes read from
* {@code System.in} into characters. The charset used for decoding is specified by the
* {@link System#getProperties stdin.encoding} property. If this property is not present,
* {@link System##stdin.encoding stdin.encoding} property. If this property is not present,
* or if the charset it names cannot be loaded, then UTF-8 is used instead. Decoding
* always replaces malformed and unmappable byte sequences with the charset's default
* replacement string.

View File

@ -48,8 +48,8 @@ import java.io.Serializable;
import java.text.NumberFormat;
import java.text.MessageFormat;
import java.text.ParsePosition;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.spi.LocaleNameProvider;
import java.util.stream.Stream;
@ -733,58 +733,24 @@ public final class Locale implements Cloneable, Serializable {
* @see #getISOCountries(Locale.IsoCountryCode)
* @since 9
*/
public static enum IsoCountryCode {
public enum IsoCountryCode {
/**
* PART1_ALPHA2 is used to represent the ISO3166-1 alpha-2 two letter
* country codes.
*/
PART1_ALPHA2 {
@Override
Set<String> createCountryCodeSet() {
return Set.of(Locale.getISOCountries());
}
},
PART1_ALPHA2,
/**
*
* PART1_ALPHA3 is used to represent the ISO3166-1 alpha-3 three letter
* country codes.
*/
PART1_ALPHA3 {
@Override
Set<String> createCountryCodeSet() {
return LocaleISOData.computeISO3166_1Alpha3Countries();
}
},
PART1_ALPHA3,
/**
* PART3 is used to represent the ISO3166-3 four letter country codes.
*/
PART3 {
@Override
Set<String> createCountryCodeSet() {
return Set.of(LocaleISOData.ISO3166_3);
}
};
/**
* Concrete implementation of this method attempts to compute value
* for iso3166CodesMap for each IsoCountryCode type key.
*/
abstract Set<String> createCountryCodeSet();
/**
* Map to hold country codes for each ISO3166 part.
*/
private static final Map<IsoCountryCode, Set<String>> iso3166CodesMap = new ConcurrentHashMap<>();
/**
* This method is called from Locale class to retrieve country code set
* for getISOCountries(type)
*/
static Set<String> retrieveISOCountryCodes(IsoCountryCode type) {
return iso3166CodesMap.computeIfAbsent(type, IsoCountryCode::createCountryCodeSet);
}
PART3
}
/**
@ -1004,30 +970,28 @@ public final class Locale implements Cloneable, Serializable {
return getInstance(baseloc, extensions);
}
static Locale getInstance(BaseLocale baseloc, LocaleExtensions extensions) {
if (extensions == null) {
Locale locale = CONSTANT_LOCALES.get(baseloc);
if (locale != null) {
return locale;
}
return LocaleCache.cache(baseloc);
return LOCALE_CACHE.get().computeIfAbsent(baseloc, LOCALE_CREATOR);
} else {
LocaleKey key = new LocaleKey(baseloc, extensions);
return LocaleCache.cache(key);
return LOCALE_CACHE.get().computeIfAbsent(key, LOCALE_CREATOR);
}
}
private static final class LocaleCache implements Function<Object, Locale> {
private static final ReferencedKeyMap<Object, Locale> LOCALE_CACHE
= ReferencedKeyMap.create(true, ReferencedKeyMap.concurrentHashMapSupplier());
private static final Function<Object, Locale> LOCALE_CREATOR = new LocaleCache();
public static Locale cache(Object key) {
return LOCALE_CACHE.computeIfAbsent(key, LOCALE_CREATOR);
}
private static final Supplier<ReferencedKeyMap<Object, Locale>> LOCALE_CACHE =
StableValue.supplier(new Supplier<>() {
@Override
public ReferencedKeyMap<Object, Locale> get() {
return ReferencedKeyMap.create(true, ReferencedKeyMap.concurrentHashMapSupplier());
}
});
private static final Function<Object, Locale> LOCALE_CREATOR = new Function<>() {
@Override
public Locale apply(Object key) {
if (key instanceof BaseLocale base) {
@ -1036,7 +1000,7 @@ public final class Locale implements Cloneable, Serializable {
LocaleKey lk = (LocaleKey)key;
return new Locale(lk.base, lk.exts);
}
}
};
private static final class LocaleKey {
@ -1301,12 +1265,8 @@ public final class Locale implements Cloneable, Serializable {
* @return An array of ISO 3166 two-letter country codes.
*/
public static String[] getISOCountries() {
if (isoCountries == null) {
isoCountries = getISO2Table(LocaleISOData.isoCountryTable);
}
String[] result = new String[isoCountries.length];
System.arraycopy(isoCountries, 0, result, 0, isoCountries.length);
return result;
String[] countries = LocaleISOData.ISO_3166_1_ALPHA2.get();
return Arrays.copyOf(countries, countries.length);
}
/**
@ -1319,7 +1279,11 @@ public final class Locale implements Cloneable, Serializable {
*/
public static Set<String> getISOCountries(IsoCountryCode type) {
Objects.requireNonNull(type);
return IsoCountryCode.retrieveISOCountryCodes(type);
return switch (type) {
case PART1_ALPHA2 -> Set.of(LocaleISOData.ISO_3166_1_ALPHA2.get());
case PART1_ALPHA3 -> LocaleISOData.ISO_3166_1_ALPHA3.get();
case PART3 -> LocaleISOData.ISO_3166_3.get();
};
}
/**
@ -1339,22 +1303,8 @@ public final class Locale implements Cloneable, Serializable {
* @return An array of ISO 639 two-letter language codes.
*/
public static String[] getISOLanguages() {
String[] languages = Locale.isoLanguages;
if (languages == null) {
Locale.isoLanguages = languages = getISO2Table(LocaleISOData.isoLanguageTable);
}
String[] result = new String[languages.length];
System.arraycopy(languages, 0, result, 0, languages.length);
return result;
}
private static String[] getISO2Table(String table) {
int len = table.length() / 5;
String[] isoTable = new String[len];
for (int i = 0, j = 0; i < len; i++, j += 5) {
isoTable[i] = table.substring(j, j + 2);
}
return isoTable;
String[] languages = LocaleISOData.ISO_639.get();
return Arrays.copyOf(languages, languages.length);
}
/**
@ -1683,61 +1633,54 @@ public final class Locale implements Cloneable, Serializable {
* @since 1.7
*/
public String toLanguageTag() {
String lTag = this.languageTag;
if (lTag != null) {
return lTag;
}
return languageTag.get();
}
private String computeLanguageTag() {
LanguageTag tag = LanguageTag.parseLocale(baseLocale, localeExtensions);
StringBuilder buf = new StringBuilder();
StringBuilder bldr = new StringBuilder();
String subtag = tag.language();
if (!subtag.isEmpty()) {
buf.append(LanguageTag.canonicalizeLanguage(subtag));
bldr.append(LanguageTag.canonicalizeLanguage(subtag));
}
subtag = tag.script();
if (!subtag.isEmpty()) {
buf.append(LanguageTag.SEP);
buf.append(LanguageTag.canonicalizeScript(subtag));
bldr.append(LanguageTag.SEP);
bldr.append(LanguageTag.canonicalizeScript(subtag));
}
subtag = tag.region();
if (!subtag.isEmpty()) {
buf.append(LanguageTag.SEP);
buf.append(LanguageTag.canonicalizeRegion(subtag));
bldr.append(LanguageTag.SEP);
bldr.append(LanguageTag.canonicalizeRegion(subtag));
}
List<String>subtags = tag.variants();
for (String s : subtags) {
buf.append(LanguageTag.SEP);
bldr.append(LanguageTag.SEP);
// preserve casing
buf.append(s);
bldr.append(s);
}
subtags = tag.extensions();
for (String s : subtags) {
buf.append(LanguageTag.SEP);
buf.append(LanguageTag.canonicalizeExtension(s));
bldr.append(LanguageTag.SEP);
bldr.append(LanguageTag.canonicalizeExtension(s));
}
subtag = tag.privateuse();
if (!subtag.isEmpty()) {
if (buf.length() > 0) {
buf.append(LanguageTag.SEP);
if (bldr.length() > 0) {
bldr.append(LanguageTag.SEP);
}
buf.append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP);
bldr.append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP);
// preserve casing
buf.append(subtag);
bldr.append(subtag);
}
String langTag = buf.toString();
synchronized (this) {
if (this.languageTag == null) {
this.languageTag = langTag;
}
}
return langTag;
return bldr.toString();
}
/**
@ -1961,7 +1904,7 @@ public final class Locale implements Cloneable, Serializable {
return lang;
}
String language3 = getISO3Code(lang, LocaleISOData.isoLanguageTable);
String language3 = LocaleISOData.getISO3LangCode(lang);
if (language3 == null) {
throw new MissingResourceException("Couldn't find 3-letter language code for "
+ lang, "FormatData_" + toString(), "ShortLanguage");
@ -1983,7 +1926,7 @@ public final class Locale implements Cloneable, Serializable {
* three-letter country abbreviation is not available for this locale.
*/
public String getISO3Country() throws MissingResourceException {
String country3 = getISO3Code(baseLocale.getRegion(), LocaleISOData.isoCountryTable);
String country3 = LocaleISOData.getISO3CtryCode(baseLocale.getRegion());
if (country3 == null) {
throw new MissingResourceException("Couldn't find 3-letter country code for "
+ baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry");
@ -1991,27 +1934,6 @@ public final class Locale implements Cloneable, Serializable {
return country3;
}
private static String getISO3Code(String iso2Code, String table) {
int codeLength = iso2Code.length();
if (codeLength == 0) {
return "";
}
int tableLength = table.length();
int index = tableLength;
if (codeLength == 2) {
char c1 = iso2Code.charAt(0);
char c2 = iso2Code.charAt(1);
for (index = 0; index < tableLength; index += 5) {
if (table.charAt(index) == c1
&& table.charAt(index + 1) == c2) {
break;
}
}
}
return index < tableLength ? table.substring(index + 2, index + 5) : null;
}
/**
* Returns a name for the locale's language that is appropriate for display to the
* user.
@ -2393,7 +2315,13 @@ public final class Locale implements Cloneable, Serializable {
private static volatile Locale defaultDisplayLocale;
private static volatile Locale defaultFormatLocale;
private transient volatile String languageTag;
private final transient Supplier<String> languageTag =
StableValue.supplier(new Supplier<>() {
@Override
public String get() {
return computeLanguageTag();
}
});
/**
* Return an array of the display names of the variant.
@ -2587,10 +2515,6 @@ public final class Locale implements Cloneable, Serializable {
baseLocale.getRegion(), baseLocale.getVariant(), localeExtensions);
}
private static volatile String[] isoLanguages;
private static volatile String[] isoCountries;
private static String convertOldISOCodes(String language) {
// we accept both the old and the new ISO codes for the languages whose ISO
// codes have changed, but we always store the NEW code, unless the property

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,11 +25,47 @@
package java.util;
import java.util.function.Supplier;
// Methods and suppliers for producing ISO 639/3166 resources used by Locale.
class LocaleISOData {
static final Supplier<String[]> ISO_639 =
StableValue.supplier(new Supplier<>() {
@Override
public String[] get() {
return getISO2Table(isoLanguageTable);
}
});
static final Supplier<String[]> ISO_3166_1_ALPHA2 =
StableValue.supplier(new Supplier<>() {
@Override
public String[] get() {
return getISO2Table(isoCountryTable);
}
});
static final Supplier<Set<String>> ISO_3166_1_ALPHA3 =
StableValue.supplier(new Supplier<>() {
@Override
public Set<String> get() {
return computeISO3166_1Alpha3Countries();
}
});
static final Supplier<Set<String>> ISO_3166_3 =
StableValue.supplier(new Supplier<>() {
@Override
public Set<String> get() {
return Set.of(ISO3166_3);
}
});
/**
* The 2- and 3-letter ISO 639 language codes.
*/
static final String isoLanguageTable =
private static final String isoLanguageTable =
"aa" + "aar" // Afar
+ "ab" + "abk" // Abkhazian
+ "ae" + "ave" // Avestan
@ -223,7 +259,7 @@ class LocaleISOData {
/**
* The 2- and 3-letter ISO 3166 country codes.
*/
static final String isoCountryTable =
private static final String isoCountryTable =
"AD" + "AND" // Andorra, Principality of
+ "AE" + "ARE" // United Arab Emirates
+ "AF" + "AFG" // Afghanistan
@ -480,18 +516,60 @@ class LocaleISOData {
/**
* Array to hold country codes for ISO3166-3.
*/
static final String[] ISO3166_3 = {
private static final String[] ISO3166_3 = {
"AIDJ", "ANHH", "BQAQ", "BUMM", "BYAA", "CSHH", "CSXX", "CTKI", "DDDE",
"DYBJ", "FQHH", "FXFR", "GEHH", "HVBF", "JTUM", "MIUM", "NHVU", "NQAQ",
"NTHH", "PCHH", "PUUM", "PZPA", "RHZW", "SKIN", "SUHH", "TPTL", "VDVN",
"WKUM", "YDYE", "YUCS", "ZRCD"
};
static String getISO3LangCode(String language) {
return getISO3Code(language, isoLanguageTable);
}
static String getISO3CtryCode(String country) {
return getISO3Code(country, isoCountryTable);
}
private static String getISO3Code(String iso2Code, String table) {
int codeLength = iso2Code.length();
if (codeLength == 0) {
return "";
}
int tableLength = table.length();
int index = tableLength;
if (codeLength == 2) {
char c1 = iso2Code.charAt(0);
char c2 = iso2Code.charAt(1);
for (index = 0; index < tableLength; index += 5) {
if (table.charAt(index) == c1
&& table.charAt(index + 1) == c2) {
break;
}
}
}
return index < tableLength ? table.substring(index + 2, index + 5) : null;
}
/**
* This method computes an array of alpha-2 codes from either ISO639 or
* ISO3166.
*/
private static String[] getISO2Table(String table) {
int len = table.length() / 5;
String[] isoTable = new String[len];
for (int i = 0, j = 0; i < len; i++, j += 5) {
isoTable[i] = table.substring(j, j + 2);
}
return isoTable;
}
/**
* This method computes a set of ISO3166-1 alpha-3 country codes from
* existing isoCountryTable.
*/
static Set<String> computeISO3166_1Alpha3Countries() {
private static Set<String> computeISO3166_1Alpha3Countries() {
int tableLength = isoCountryTable.length();
String[] isoTable = new String[tableLength / 5];
for (int i = 0, index = 0; index < tableLength; i++, index += 5) {
@ -500,6 +578,5 @@ class LocaleISOData {
return Set.of(isoTable);
}
private LocaleISOData() {
}
private LocaleISOData() {}
}

View File

@ -54,6 +54,7 @@ import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier;
import java.util.jar.JarEntry;
import java.util.spi.ResourceBundleControlProvider;
import java.util.spi.ResourceBundleProvider;
@ -487,7 +488,20 @@ public abstract class ResourceBundle {
/**
* A Set of the keys contained only in this ResourceBundle.
*/
private volatile Set<String> keySet;
private final Supplier<Set<String>> keySet = StableValue.supplier(
new Supplier<>() { public Set<String> get() { return keySet0(); }});
private Set<String> keySet0() {
final Set<String> keys = new HashSet<>();
final Enumeration<String> enumKeys = getKeys();
while (enumKeys.hasMoreElements()) {
final String key = enumKeys.nextElement();
if (handleGetObject(key) != null) {
keys.add(key);
}
}
return keys;
}
/**
* Sole constructor. (For invocation by subclass constructors, typically
@ -2298,22 +2312,7 @@ public abstract class ResourceBundle {
* @since 1.6
*/
protected Set<String> handleKeySet() {
if (keySet == null) {
synchronized (this) {
if (keySet == null) {
Set<String> keys = new HashSet<>();
Enumeration<String> enumKeys = getKeys();
while (enumKeys.hasMoreElements()) {
String key = enumKeys.nextElement();
if (handleGetObject(key) != null) {
keys.add(key);
}
}
keySet = keys;
}
}
}
return keySet;
return keySet.get();
}

View File

@ -454,19 +454,25 @@ public class Cipher {
String[] parts = tokenizeTransformation(transformation);
String alg = parts[0];
String mode = parts[1];
String pad = parts[2];
String mode = (parts[1].length() == 0 ? null : parts[1]);
String pad = (parts[2].length() == 0 ? null : parts[2]);
if ((mode.length() == 0) && (pad.length() == 0)) {
if ((mode == null) && (pad == null)) {
// Algorithm only
Transform tr = new Transform(alg, "", null, null);
return Collections.singletonList(tr);
} else {
// Algorithm w/ at least mode or padding or both
List<Transform> list = new ArrayList<>(4);
list.add(new Transform(alg, "/" + mode + "/" + pad, null, null));
list.add(new Transform(alg, "/" + mode, null, pad));
list.add(new Transform(alg, "//" + pad, mode, null));
if ((mode != null) && (pad != null)) {
list.add(new Transform(alg, "/" + mode + "/" + pad, null, null));
}
if (mode != null) {
list.add(new Transform(alg, "/" + mode, null, pad));
}
if (pad != null) {
list.add(new Transform(alg, "//" + pad, mode, null));
}
list.add(new Transform(alg, "", mode, pad));
return list;
}

View File

@ -59,7 +59,6 @@ import javax.security.auth.x500.X500Principal;
*/
public class SharedSecrets {
private static JavaAWTAccess javaAWTAccess;
private static JavaAWTFontAccess javaAWTFontAccess;
private static JavaBeansAccess javaBeansAccess;
private static JavaLangAccess javaLangAccess;
@ -321,16 +320,6 @@ public class SharedSecrets {
javaUtilZipFileAccess = access;
}
public static void setJavaAWTAccess(JavaAWTAccess jaa) {
javaAWTAccess = jaa;
}
public static JavaAWTAccess getJavaAWTAccess() {
// this may return null in which case calling code needs to
// provision for.
return javaAWTAccess;
}
public static void setJavaAWTFontAccess(JavaAWTFontAccess jafa) {
javaAWTFontAccess = jafa;
}

View File

@ -232,8 +232,8 @@ public class JavaTimeSupplementary extends OpenListResourceBundle {
"Sha.",
"Ram.",
"Shaw.",
"Dhu\u02bbl-Q.",
"Dhu\u02bbl-H.",
"Dhuʻl-Q.",
"Dhuʻl-H.",
"",
}
},
@ -241,16 +241,16 @@ public class JavaTimeSupplementary extends OpenListResourceBundle {
new String[] {
"Muharram",
"Safar",
"Rabi\u02bb I",
"Rabi\u02bb II",
"Rabiʻ I",
"Rabiʻ II",
"Jumada I",
"Jumada II",
"Rajab",
"Sha\u02bbban",
"Shaʻban",
"Ramadan",
"Shawwal",
"Dhu\u02bbl-Qi\u02bbdah",
"Dhu\u02bbl-Hijjah",
"Dhuʻl-Qiʻdah",
"Dhuʻl-Hijjah",
"",
}
},

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -38,6 +38,7 @@ import jdk.internal.util.StaticProperty;
import jdk.internal.vm.annotation.Stable;
import java.util.StringJoiner;
import java.util.function.Supplier;
public final class BaseLocale {
@ -90,6 +91,15 @@ public final class BaseLocale {
}
}
// Interned BaseLocale cache
private static final Supplier<ReferencedKeySet<BaseLocale>> CACHE =
StableValue.supplier(new Supplier<>() {
@Override
public ReferencedKeySet<BaseLocale> get() {
return ReferencedKeySet.create(true, ReferencedKeySet.concurrentHashMapSupplier());
}
});
public static final String SEP = "_";
private final String language;
@ -164,11 +174,7 @@ public final class BaseLocale {
// Obtain the "interned" BaseLocale from the cache. The returned
// "interned" instance can subsequently be used by the Locale
// instance which guarantees the locale components are properly cased/interned.
class InterningCache { // TODO: StableValue
private static final ReferencedKeySet<BaseLocale> CACHE =
ReferencedKeySet.create(true, ReferencedKeySet.concurrentHashMapSupplier());
}
return InterningCache.CACHE.intern(new BaseLocale(
return CACHE.get().intern(new BaseLocale(
language.intern(), // guaranteed to be lower-case
LocaleUtils.toTitleString(script).intern(),
region.intern(), // guaranteed to be upper-case

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,7 @@ import java.util.Collections;
import java.util.Enumeration;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.function.Supplier;
/**
* BreakIteratorResourceBundle is an abstract class for loading BreakIterator
@ -49,7 +50,15 @@ public abstract class BreakIteratorResourceBundle extends ResourceBundle {
// those keys must be added to NON_DATA_KEYS.
private static final Set<String> NON_DATA_KEYS = Set.of("BreakIteratorClasses");
private volatile Set<String> keys;
private final Supplier<Set<String>> keys = StableValue.supplier(
new Supplier<>() { public Set<String> get() { return keys0(); }});
private Set<String> keys0() {
final ResourceBundle info = getBreakIteratorInfo();
final Set<String> k = info.keySet();
k.removeAll(NON_DATA_KEYS);
return k;
}
/**
* Returns an instance of the corresponding {@code BreakIteratorInfo} (basename).
@ -84,16 +93,6 @@ public abstract class BreakIteratorResourceBundle extends ResourceBundle {
@Override
protected Set<String> handleKeySet() {
if (keys == null) {
ResourceBundle info = getBreakIteratorInfo();
Set<String> k = info.keySet();
k.removeAll(NON_DATA_KEYS);
synchronized (this) {
if (keys == null) {
keys = k;
}
}
}
return keys;
return keys.get();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -44,8 +44,11 @@ import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.function.Supplier;
import sun.util.ResourceBundleEnumeration;
/**
@ -69,12 +72,9 @@ public abstract class OpenListResourceBundle extends ResourceBundle {
// Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification.
@Override
protected Object handleGetObject(String key) {
if (key == null) {
throw new NullPointerException();
}
loadLookupTablesIfNecessary();
return lookup.get(key); // this class ignores locales
Objects.requireNonNull(key);
return lookup.get()
.get(key); // this class ignores locales
}
/**
@ -93,26 +93,13 @@ public abstract class OpenListResourceBundle extends ResourceBundle {
*/
@Override
protected Set<String> handleKeySet() {
loadLookupTablesIfNecessary();
return lookup.keySet();
return lookup.get()
.keySet();
}
@Override
public Set<String> keySet() {
if (keyset != null) {
return keyset;
}
Set<String> ks = createSet();
ks.addAll(handleKeySet());
if (parent != null) {
ks.addAll(parent.keySet());
}
synchronized (this) {
if (keyset == null) {
keyset = ks;
}
}
return keyset;
return keyset.get();
}
/**
@ -120,38 +107,6 @@ public abstract class OpenListResourceBundle extends ResourceBundle {
*/
protected abstract Object[][] getContents();
/**
* Load lookup tables if they haven't been loaded already.
*/
void loadLookupTablesIfNecessary() {
if (lookup == null) {
loadLookup();
}
}
/**
* We lazily load the lookup hashtable. This function does the
* loading.
*/
private void loadLookup() {
Object[][] contents = getContents();
Map<String, Object> temp = createMap(contents.length);
for (int i = 0; i < contents.length; ++i) {
// key must be non-null String, value must be non-null
String key = (String) contents[i][0];
Object value = contents[i][1];
if (key == null || value == null) {
throw new NullPointerException();
}
temp.put(key, value);
}
synchronized (this) {
if (lookup == null) {
lookup = temp;
}
}
}
/**
* Lets subclasses provide specialized Map implementations.
* Default uses HashMap.
@ -164,6 +119,31 @@ public abstract class OpenListResourceBundle extends ResourceBundle {
return new HashSet<>();
}
private volatile Map<String, Object> lookup;
private volatile Set<String> keyset;
private final Supplier<Map<String, Object>> lookup = StableValue.supplier(
new Supplier<>() { public Map<String, Object> get() { return lookup0(); }});
private Map<String, Object> lookup0() {
final Object[][] contents = getContents();
final Map<String, Object> temp = createMap(contents.length);
for (Object[] content : contents) {
// key must be non-null String, value must be non-null
final String key = Objects.requireNonNull((String) content[0]);
final Object value = Objects.requireNonNull(content[1]);
temp.put(key, value);
}
return temp;
}
private final Supplier<Set<String>> keyset = StableValue.supplier(
new Supplier<>() { public Set<String> get() { return keyset0(); }});
private Set<String> keyset0() {
final Set<String> ks = createSet();
ks.addAll(handleKeySet());
if (parent != null) {
ks.addAll(parent.keySet());
}
return ks;
}
}

View File

@ -0,0 +1,21 @@
Owner: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB
Issuer: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB
Serial number: 50249ba2ef8ea6bf6c2c1f1a6385d4c3
Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
Signature algorithm name: SHA384withECDSA
Subject Public Key Algorithm: 384-bit EC (secp384r1) key
Version: 3
-----BEGIN CERTIFICATE-----
MIICKDCCAa+gAwIBAgIQUCSbou+Opr9sLB8aY4XUwzAKBggqhkjOPQQDAzBWMQsw
CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRT
ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBFNDYwHhcNMjEwMzIyMDAw
MDAwWhcNNDYwMzIxMjM1OTU5WjBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2Vj
dGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25p
bmcgUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQIMoEDH487om+BR4zl
e7m6wWmyW0nAKLkUWG8kM85Qm3PZO8FoOZx6Yc5c0iJHRKuAhanllayqrmZYhlan
uIODzLTRDqlR+EtnOX+MubY5aDSPGUq6jiHrQrisVp0J3AejQjBAMB0GA1UdDgQW
BBTPfSygkHqYHd22XoXC4NoVcdLlXjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/
BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjACd++zAerlV83j8HflRwwwlLmgchbs
aGX/4g44dv/oG8KfzCVTRg6sZHMobtK0IqYCMGk5W6+oBFyZMtOebrSwXs8lGjll
/zHz43Zy8DMXO+iiqzSEwWGneZ6KupkGGqfVKw==
-----END CERTIFICATE-----

View File

@ -0,0 +1,39 @@
Owner: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB
Issuer: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB
Serial number: 4b2c3b01018bad2abc8c7b5b3eed9057
Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
Signature algorithm name: SHA384withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
-----BEGIN CERTIFICATE-----
MIIFeDCCA2CgAwIBAgIQSyw7AQGLrSq8jHtbPu2QVzANBgkqhkiG9w0BAQwFADBW
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQD
EyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwHhcNMjEwMzIy
MDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMP
U2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNp
Z25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCN
55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+shJHjUoq14pbe0IdjJImK
/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCDJ9qaDStQ6Utbs7hkNqR+
Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7P2bSlDFp+m2zNKzBenjc
klDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extmeme/G3h+pDHazJyCh1rr9
gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUzT2MuuC3hv2WnBGsY2HH6
zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6qRT5uWl+PoVvLnTCGMOgD
s0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mczmrYI4IAFSEDu9oJkRqj1
c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEcQNYWFyn8XJwYK+pF9e+9
1WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2TOglmmVhcKaO5DKYwODzQ
RjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/AZwQsRb8zG4Y3G9i/qZQ
p7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QIDAQABo0IwQDAdBgNVHQ4E
FgQUMuuSmv81lkgvKEBCcCA2kVwXheYwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB
/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAHZlwuPXIkrXHYle/2lexhQCTXOm
zc0oyrA36r+nySGqql/av/aDbNCA0QpcAKTL88w5D55BcYjVPOiKe4wXI/fKNHSR
bAauUD8AWbImPDwXg1cDPi3RGj3UzwdUskMLUnKoiPXEF/Jv0Vil0WjkPZgIGO42
9EhImvpUcPCI1HAWMEJJ0Nk/dUtFcdiuorthDoiFUFe5uhErNikfjyBynlyeidGC
2kWNapnahHFrM6UQu3nwl/Z0gaA/V8eGjDCMDjiVrgHGHqvcqB9vL9f/dh6uF3Nt
5bl1s2EGqJUzwk5vsjfylb6FVBK5yL1iQnb3Kvz1NzEDJlf+0ebb8BYCcoOMCLOE
rKnkB/ihiMQTWlBHVEKm7dBBNCyYsT6iNKEMXb2s9395p79tDFYyhRtLl7jhrOSk
PHHxo+FOY9b0Rrr1CwjhYzztolkvCtQsayOinqFN7tESzRgzUO1Bbst/PUFgC2ML
ePV170MVtzYLEK/cXBipmNk22R3YhLMGioLjexskp0LO7g8+VlwyfexL3lYrOzu6
+XpY0FG2bNb2WKJSJHpEhqEcYD9J0/z6+YQcBcI0v+Lm8RkqmS9WVzWctfUHw0Yv
3jg9GQ37o/HfE57nqXJYMa+96trX1m13MzOO9Kz9wb9Jh9JwBWd0Bqb2eEAtFgSR
Dx/TFsS4ehcNJMmy
-----END CERTIFICATE-----

View File

@ -0,0 +1,21 @@
Owner: CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB
Issuer: CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB
Serial number: 42f2ccda1b6937445f15fe752810b8f4
Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
Signature algorithm name: SHA384withECDSA
Subject Public Key Algorithm: 384-bit EC (secp384r1) key
Version: 3
-----BEGIN CERTIFICATE-----
MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw
CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T
ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN
MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG
A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT
ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA
IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC
WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+
6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B
Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa
qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q
4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw==
-----END CERTIFICATE-----

View File

@ -0,0 +1,39 @@
Owner: CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB
Issuer: CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB
Serial number: 758dfd8bae7c0700faa925a7e1c7ad14
Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046
Signature algorithm name: SHA384withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
-----BEGIN CERTIFICATE-----
MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD
Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw
HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY
MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp
YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB
AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa
ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz
SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf
iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X
ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3
IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS
VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE
SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu
+Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt
8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L
HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt
zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P
AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c
mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ
YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52
gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA
Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB
JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX
DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui
TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5
dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65
LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp
0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY
QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL
-----END CERTIFICATE-----

View File

@ -2917,71 +2917,12 @@ when they're used.
## Removed Java Options
These `java` options have been removed in JDK @@VERSION_SPECIFICATION@@ and using them results in an error of:
> `Unrecognized VM option` *option-name*
`-XX:RTMAbortRatio=`*abort\_ratio*
: Specifies the RTM abort ratio is specified as a percentage (%) of all
executed RTM transactions. If a number of aborted transactions becomes
greater than this ratio, then the compiled code is deoptimized. This ratio
is used when the `-XX:+UseRTMDeopt` option is enabled. The default value of
this option is 50. This means that the compiled code is deoptimized if 50%
of all transactions are aborted.
`-XX:RTMRetryCount=`*number\_of\_retries*
: Specifies the number of times that the RTM locking code is retried, when it
is aborted or busy, before falling back to the normal locking mechanism.
The default value for this option is 5. The `-XX:UseRTMLocking` option must
be enabled.
`-XX:+UseRTMDeopt`
: Autotunes RTM locking depending on the abort ratio. This ratio is specified
by the `-XX:RTMAbortRatio` option. If the number of aborted transactions
exceeds the abort ratio, then the method containing the lock is deoptimized
and recompiled with all locks as normal locks. This option is disabled by
default. The `-XX:+UseRTMLocking` option must be enabled.
`-XX:+UseRTMLocking`
: Generates Restricted Transactional Memory (RTM) locking code for all
inflated locks, with the normal locking mechanism as the fallback handler.
This option is disabled by default. Options related to RTM are available
only on x86 CPUs that support Transactional Synchronization Extensions (TSX).
RTM is part of Intel's TSX, which is an x86 instruction set extension and
facilitates the creation of multithreaded applications. RTM introduces the
new instructions `XBEGIN`, `XABORT`, `XEND`, and `XTEST`. The `XBEGIN` and
`XEND` instructions enclose a set of instructions to run as a transaction.
If no conflict is found when running the transaction, then the memory and
register modifications are committed together at the `XEND` instruction.
The `XABORT` instruction can be used to explicitly abort a transaction and
the `XTEST` instruction checks if a set of instructions is being run in a
transaction.
A lock on a transaction is inflated when another thread tries to access the
same transaction, thereby blocking the thread that didn't originally
request access to the transaction. RTM requires that a fallback set of
operations be specified in case a transaction aborts or fails. An RTM lock
is a lock that has been delegated to the TSX's system.
RTM improves performance for highly contended locks with low conflict in a
critical region (which is code that must not be accessed by more than one
thread concurrently). RTM also improves the performance of coarse-grain
locking, which typically doesn't perform well in multithreaded
applications. (Coarse-grain locking is the strategy of holding locks for
long periods to minimize the overhead of taking and releasing locks, while
fine-grained locking is the strategy of trying to achieve maximum
parallelism by locking only when necessary and unlocking as soon as
possible.) Also, for lightly contended locks that are used by different
threads, RTM can reduce false cache line sharing, also known as cache line
ping-pong. This occurs when multiple threads from different processors are
accessing different resources, but the resources share the same cache line.
As a result, the processors repeatedly invalidate the cache lines of other
processors, which forces them to read from main memory instead of their
cache.
No documented java options have been removed in JDK @@VERSION_SPECIFICATION@@.
For the lists and descriptions of options removed in previous releases see the *Removed Java Options* section in:
- [The `java` Command, Release 25](https://docs.oracle.com/en/java/javase/25/docs/specs/man/java.html)
- [The `java` Command, Release 24](https://docs.oracle.com/en/java/javase/24/docs/specs/man/java.html)
- [The `java` Command, Release 23](https://docs.oracle.com/en/java/javase/23/docs/specs/man/java.html)

View File

@ -42,8 +42,6 @@ import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
import java.lang.ref.SoftReference;
import jdk.internal.access.JavaAWTAccess;
import jdk.internal.access.SharedSecrets;
import sun.util.logging.PlatformLogger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
@ -746,67 +744,6 @@ public final class AppContext {
return changeSupport.getPropertyChangeListeners(propertyName);
}
// Set up JavaAWTAccess in SharedSecrets
static {
SharedSecrets.setJavaAWTAccess(new JavaAWTAccess() {
private boolean hasRootThreadGroup(final AppContext ecx) {
return ecx.threadGroup.getParent() == null;
}
/**
* Returns the AppContext used for applet logging isolation, or null if
* the default global context can be used.
* If there's no applet, or if the caller is a stand alone application,
* or running in the main app context, returns null.
* Otherwise, returns the AppContext of the calling applet.
* @return null if the global default context can be used,
* an AppContext otherwise.
**/
public Object getAppletContext() {
// There's no AppContext: return null.
// No need to call getAppContext() if numAppContext == 0:
// it means that no AppContext has been created yet, and
// we don't want to trigger the creation of a main app
// context since we don't need it.
if (numAppContexts.get() == 0) return null;
AppContext ecx = null;
// Not sure we really need to re-check numAppContexts here.
// If all applets have gone away then we could have a
// numAppContexts coming back to 0. So we recheck
// it here because we don't want to trigger the
// creation of a main AppContext in that case.
// This is probably not 100% MT-safe but should reduce
// the window of opportunity in which that issue could
// happen.
if (numAppContexts.get() > 0) {
// Defaults to thread group caching.
// This is probably not required as we only really need
// isolation in a deployed applet environment, in which
// case ecx will not be null when we reach here
// However it helps emulate the deployed environment,
// in tests for instance.
ecx = ecx != null ? ecx : getAppContext();
}
// getAppletContext() may be called when initializing the main
// app context - in which case mainAppContext will still be
// null. To work around this issue we simply use
// AppContext.threadGroup.getParent() == null instead, since
// mainAppContext is the only AppContext which should have
// the root TG as its thread group.
// See: JDK-8023258
final boolean isMainAppContext = ecx == null
|| mainAppContext == ecx
|| mainAppContext == null && hasRootThreadGroup(ecx);
return isMainAppContext ? null : ecx;
}
});
}
public static <T> T getSoftReferenceValue(Object key,
Supplier<T> supplier) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -204,8 +204,9 @@ public abstract class SunClipboard extends Clipboard
byte[] data = null;
Transferable localeTransferable = null;
openClipboard(null);
try {
openClipboard(null);
long[] formats = getClipboardFormats();
Long lFormat = DataTransferer.getInstance().
@ -318,12 +319,7 @@ public abstract class SunClipboard extends Clipboard
* @since 1.5
*/
protected long[] getClipboardFormatsOpenClose() {
try {
openClipboard(null);
return getClipboardFormats();
} finally {
closeClipboard();
}
return getClipboardFormats();
}
/**
@ -356,15 +352,7 @@ public abstract class SunClipboard extends Clipboard
flavorListeners.add(listener);
if (numberOfFlavorListeners++ == 0) {
long[] currentFormats = null;
try {
openClipboard(null);
currentFormats = getClipboardFormats();
} catch (final IllegalStateException ignored) {
} finally {
closeClipboard();
}
this.currentFormats = currentFormats;
this.currentFormats = getClipboardFormats();
registerClipboardViewerChecked();
}

View File

@ -1016,6 +1016,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_getRGBPixelsImpl
const gchar *token = jtoken
? (*env)->GetStringUTFChars(env, jtoken, NULL)
: NULL;
JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR);
isGtkMainThread = gtk->g_main_context_is_owner(gtk->g_main_context_default());
DEBUG_SCREENCAST(
@ -1121,7 +1122,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
const gchar *token = jtoken
? (*env)->GetStringUTFChars(env, jtoken, NULL)
: NULL;
JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR);
DEBUG_SCREENCAST("moving mouse to\n\t%d %d\n\twith token |%s|\n", jx, jy, token);
@ -1151,6 +1152,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
const gchar *token = jtoken
? (*env)->GetStringUTFChars(env, jtoken, NULL)
: NULL;
JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR);
gboolean result = initPortal(token, NULL, 0);
DEBUG_SCREENCAST("init result %b, mouse pressing %d\n", result, buttons)
@ -1178,6 +1180,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopMou
const gchar *token = jtoken
? (*env)->GetStringUTFChars(env, jtoken, NULL)
: NULL;
JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR);
gboolean result = initPortal(token, NULL, 0);
DEBUG_SCREENCAST("init result %b, mouse wheel %d\n", result, jWheelAmt)
@ -1206,13 +1209,14 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_remoteDesktopKey
int key = awt_getX11KeySym(jkey);
AWT_UNLOCK();
if (key == NoSymbol) {
if (key == NoSymbol || (*env)->ExceptionCheck(env)) {
return RESULT_ERROR;
}
const gchar *token = jtoken
? (*env)->GetStringUTFChars(env, jtoken, NULL)
: NULL;
JNU_CHECK_EXCEPTION_RETURN(env, RESULT_ERROR);
gboolean result = initPortal(token, NULL, 0);
DEBUG_SCREENCAST("init result %b, key %d -> %d isPress %b\n", result, jkey, key, isPress)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,7 +29,9 @@ import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.lang.System.Logger.Level;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
import sun.awt.datatransfer.DataTransferer;
import sun.awt.datatransfer.SunClipboard;
@ -51,8 +53,12 @@ final class WClipboard extends SunClipboard {
private boolean isClipboardViewerRegistered;
private final ReentrantLock clipboardLocked = new ReentrantLock();
WClipboard() {
super("System");
// Register java side of the clipboard with the native side
registerClipboard();
}
@Override
@ -104,18 +110,42 @@ final class WClipboard extends SunClipboard {
/**
* Call the Win32 OpenClipboard function. If newOwner is non-null,
* we also call EmptyClipboard and take ownership.
* we also call EmptyClipboard and take ownership. If this method call
* succeeds, it must be followed by a call to {@link #closeClipboard()}.
*
* @throws IllegalStateException if the clipboard has not been opened
*/
@Override
public native void openClipboard(SunClipboard newOwner) throws IllegalStateException;
public void openClipboard(SunClipboard newOwner) throws IllegalStateException {
if (!clipboardLocked.tryLock()) {
throw new IllegalStateException("Failed to acquire clipboard lock");
}
try {
openClipboard0(newOwner);
} catch (IllegalStateException ex) {
clipboardLocked.unlock();
throw ex;
}
}
/**
* Call the Win32 CloseClipboard function if we have clipboard ownership,
* does nothing if we have not ownership.
*/
@Override
public native void closeClipboard();
public void closeClipboard() {
if (clipboardLocked.isLocked()) {
try {
closeClipboard0();
} finally {
clipboardLocked.unlock();
}
}
}
private native void openClipboard0(SunClipboard newOwner) throws IllegalStateException;
private native void closeClipboard0();
/**
* Call the Win32 SetClipboardData function.
*/
@ -157,16 +187,12 @@ final class WClipboard extends SunClipboard {
return;
}
long[] formats = null;
try {
openClipboard(null);
formats = getClipboardFormats();
} catch (IllegalStateException exc) {
// do nothing to handle the exception, call checkChange(null)
} finally {
closeClipboard();
long[] formats = getClipboardFormats();
checkChange(formats);
} catch (Throwable ex) {
System.getLogger(WClipboard.class.getName()).log(Level.DEBUG, "Failed to process handleContentsChanged", ex);
}
checkChange(formats);
}
/**
@ -214,4 +240,6 @@ final class WClipboard extends SunClipboard {
}
};
}
private native void registerClipboard();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -69,9 +69,8 @@ void AwtClipboard::RegisterClipboardViewer(JNIEnv *env, jobject jclipboard) {
return;
}
if (theCurrentClipboard == NULL) {
theCurrentClipboard = env->NewGlobalRef(jclipboard);
}
DASSERT(AwtClipboard::theCurrentClipboard != NULL);
DASSERT(env->IsSameObject(AwtClipboard::theCurrentClipboard, jclipboard));
jclass cls = env->GetObjectClass(jclipboard);
AwtClipboard::handleContentsChangedMID =
@ -128,11 +127,13 @@ Java_sun_awt_windows_WClipboard_init(JNIEnv *env, jclass cls)
* Signature: (Lsun/awt/windows/WClipboard;)V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WClipboard_openClipboard(JNIEnv *env, jobject self,
Java_sun_awt_windows_WClipboard_openClipboard0(JNIEnv *env, jobject self,
jobject newOwner)
{
TRY;
DASSERT(AwtClipboard::theCurrentClipboard != NULL);
DASSERT(newOwner == NULL || env->IsSameObject(AwtClipboard::theCurrentClipboard, newOwner));
DASSERT(::GetOpenClipboardWindow() != AwtToolkit::GetInstance().GetHWnd());
if (!::OpenClipboard(AwtToolkit::GetInstance().GetHWnd())) {
@ -142,10 +143,6 @@ Java_sun_awt_windows_WClipboard_openClipboard(JNIEnv *env, jobject self,
}
if (newOwner != NULL) {
AwtClipboard::GetOwnership();
if (AwtClipboard::theCurrentClipboard != NULL) {
env->DeleteGlobalRef(AwtClipboard::theCurrentClipboard);
}
AwtClipboard::theCurrentClipboard = env->NewGlobalRef(newOwner);
}
CATCH_BAD_ALLOC;
@ -157,7 +154,7 @@ Java_sun_awt_windows_WClipboard_openClipboard(JNIEnv *env, jobject self,
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WClipboard_closeClipboard(JNIEnv *env, jobject self)
Java_sun_awt_windows_WClipboard_closeClipboard0(JNIEnv *env, jobject self)
{
TRY;
@ -297,23 +294,25 @@ Java_sun_awt_windows_WClipboard_getClipboardFormats
{
TRY;
DASSERT(::GetOpenClipboardWindow() == AwtToolkit::GetInstance().GetHWnd());
unsigned int cFormats = 128; // Allocate enough space to hold all
unsigned int pcFormatsOut = 0;
unsigned int lpuiFormats[128] = { 0 };
jsize nFormats = ::CountClipboardFormats();
jlongArray formats = env->NewLongArray(nFormats);
VERIFY(::GetUpdatedClipboardFormats(lpuiFormats, 128, &pcFormatsOut));
jlongArray formats = env->NewLongArray(pcFormatsOut);
if (formats == NULL) {
throw std::bad_alloc();
}
if (nFormats == 0) {
if (pcFormatsOut == 0) {
return formats;
}
jboolean isCopy;
jlong *lFormats = env->GetLongArrayElements(formats, &isCopy),
*saveFormats = lFormats;
UINT num = 0;
for (jsize i = 0; i < nFormats; i++, lFormats++) {
*lFormats = num = ::EnumClipboardFormats(num);
for (unsigned int i = 0; i < pcFormatsOut; i++, lFormats++) {
*lFormats = lpuiFormats[i];
}
env->ReleaseLongArrayElements(formats, saveFormats, 0);
@ -478,4 +477,16 @@ Java_sun_awt_windows_WClipboard_getClipboardData
CATCH_BAD_ALLOC_RET(NULL);
}
/*
* Class: sun_awt_windows_WClipboard
* Method: registerClipboard
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_sun_awt_windows_WClipboard_registerClipboard(JNIEnv *env, jobject self)
{
DASSERT(AwtClipboard::theCurrentClipboard == NULL);
AwtClipboard::theCurrentClipboard = env->NewGlobalRef(self);
}
} /* extern "C" */

View File

@ -557,34 +557,15 @@ final class SocketTube implements FlowTube {
implements Flow.Publisher<List<ByteBuffer>> {
private final InternalReadSubscription subscriptionImpl
= new InternalReadSubscription();
ConcurrentLinkedQueue<ReadSubscription> pendingSubscriptions = new ConcurrentLinkedQueue<>();
private final AtomicReference<ReadSubscription> pendingSubscriptions
= new AtomicReference<>();
private volatile ReadSubscription subscription;
@Override
public void subscribe(Flow.Subscriber<? super List<ByteBuffer>> s) {
Objects.requireNonNull(s);
TubeSubscriber sub = FlowTube.asTubeSubscriber(s);
ReadSubscription previous;
while ((previous = pendingSubscriptions.poll()) != null) {
if (debug.on())
debug.log("read publisher: dropping pending subscriber: "
+ previous.subscriber);
previous.errorRef.compareAndSet(null, errorRef.get());
// make sure no data will be routed to the old subscriber.
previous.stopReading();
previous.signalOnSubscribe();
if (subscriptionImpl.completed) {
previous.signalCompletion();
} else {
previous.subscriber.dropSubscription();
}
}
ReadSubscription target = new ReadSubscription(subscriptionImpl, sub);
pendingSubscriptions.offer(target);
if (debug.on()) debug.log("read publisher got new subscriber: " + s);
subscriptionImpl.signalSubscribe();
if (debug.on()) debug.log("Offering new subscriber: %s", s);
subscriptionImpl.offer(FlowTube.asTubeSubscriber(s));
debugState("leaving read.subscribe: ");
}
@ -676,7 +657,6 @@ final class SocketTube implements FlowTube {
*/
synchronized void stopReading() {
stopped = true;
impl.demand.reset();
}
synchronized boolean tryDecrementDemand() {
@ -733,14 +713,7 @@ final class SocketTube implements FlowTube {
assert client.isSelectorThread();
debug.log("subscribe event raised");
if (Log.channel()) Log.logChannel("Start reading from {0}", channelDescr());
readScheduler.runOrSchedule();
if (readScheduler.isStopped() || completed) {
// if already completed or stopped we can handle any
// pending connection directly from here.
if (debug.on())
debug.log("handling pending subscription when completed");
handlePending();
}
handlePending();
}
@ -953,22 +926,46 @@ final class SocketTube implements FlowTube {
}
}
boolean handlePending() {
ReadSubscription pending;
synchronized void offer(TubeSubscriber sub) {
ReadSubscription target = new ReadSubscription(this, sub);
ReadSubscription previous = pendingSubscriptions.getAndSet(target);
if (previous != null) {
if (debug.on())
debug.log("read publisher: dropping pending subscriber: "
+ previous.subscriber);
previous.errorRef.compareAndSet(null, errorRef.get());
// make sure no data will be routed to the old subscriber.
previous.stopReading();
previous.signalOnSubscribe();
if (completed) {
previous.signalCompletion();
} else {
previous.subscriber.dropSubscription();
}
}
if (debug.on()) {
debug.log("read publisher got new subscriber: " + sub);
}
signalSubscribe();
}
synchronized boolean handlePending() {
boolean subscribed = false;
while ((pending = pendingSubscriptions.poll()) != null) {
ReadSubscription current = subscription;
ReadSubscription pending = pendingSubscriptions.getAndSet(null);
if (pending != null) {
subscribed = true;
if (debug.on())
debug.log("handling pending subscription for %s",
pending.subscriber);
ReadSubscription current = subscription;
if (current != null && current != pending && !completed) {
debug.log("dropping pending subscription for current %s",
if (current != null && !completed) {
debug.log("dropping subscription for current %s",
current.subscriber);
current.stopReading();
current.subscriber.dropSubscription();
}
if (debug.on()) debug.log("read demand reset to 0");
subscriptionImpl.demand.reset(); // subscriber will increase demand if it needs to.
demand.reset(); // subscriber will increase demand if it needs to.
pending.errorRef.compareAndSet(null, errorRef.get());
if (!readScheduler.isStopped()) {
subscription = pending;
@ -1335,7 +1332,6 @@ final class SocketTube implements FlowTube {
writePublisher.subscribe(this);
}
@Override
public String toString() {
return dbgString();

View File

@ -87,7 +87,7 @@ public class FormatData_ja extends ParallelListResourceBundle {
return new Object[][] {
{ "japanese.FirstYear",
new String[] { // first year name
"\u5143", // "Gan"-nen
"", // "Gan"-nen
}
},
};

View File

@ -117,7 +117,7 @@ class TestGenCollectorPolicy {
initial_heap_size = InitialHeapSize;
}
size_t expected = scale_by_NewRatio_aligned(initial_heap_size, GenAlignment);
size_t expected = scale_by_NewRatio_aligned(initial_heap_size, SpaceAlignment);
ASSERT_EQ(expected, NewSize);
}
};

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "gc/z/zPageAge.hpp"
#include "unittest.hpp"
TEST(ZPageAgeRangeTest, test) {
ZPageAgeRange rangeEden = ZPageAgeRangeEden;
EXPECT_EQ(rangeEden.first(), ZPageAge::eden);
EXPECT_EQ(rangeEden.last(), ZPageAge::eden);
ZPageAgeRange rangeYoung = ZPageAgeRangeYoung;
EXPECT_EQ(rangeYoung.first(), ZPageAge::eden);
EXPECT_EQ(rangeYoung.last(), ZPageAge::survivor14);
ZPageAgeRange rangeSurvivor = ZPageAgeRangeSurvivor;
EXPECT_EQ(rangeSurvivor.first(), ZPageAge::survivor1);
EXPECT_EQ(rangeSurvivor.last(), ZPageAge::survivor14);
ZPageAgeRange rangeRelocation = ZPageAgeRangeRelocation;
EXPECT_EQ(rangeRelocation.first(), ZPageAge::survivor1);
EXPECT_EQ(rangeRelocation.last(), ZPageAge::old);
ZPageAgeRange rangeOld = ZPageAgeRangeOld;
EXPECT_EQ(rangeOld.first(), ZPageAge::old);
EXPECT_EQ(rangeOld.last(), ZPageAge::old);
}

View File

@ -42,12 +42,3 @@ gtest/MetaspaceGtests.java#no-ccs 8356201 generic-all
gtest/NMTGtests.java#nmt-detail 8356201 generic-all
gtest/NMTGtests.java#nmt-off 8356201 generic-all
gtest/NMTGtests.java#nmt-summary 8356201 generic-all
# Need CDS archive
runtime/cds/NonJVMVariantLocation.java 8357632 generic-all
runtime/cds/TestCDSVMCrash.java 8357632 generic-all
runtime/cds/TestDefaultArchiveLoading.java#coops_coh 8357632 generic-all
runtime/cds/TestDefaultArchiveLoading.java#coops_nocoh 8357632 generic-all
runtime/cds/TestDefaultArchiveLoading.java#nocoops_coh 8357632 generic-all
runtime/cds/TestDefaultArchiveLoading.java#nocoops_nocoh 8357632 generic-all
serviceability/jvmti/RedefineClasses/RedefineSharedClass.java 8357632 generic-all

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,18 @@
* compiler.c2.Test7046096
*/
/*
* @test id=stringConcatInline
* @bug 7046096 8357822
* @summary The same test with an updated compile directive that produces
* StringBuilder-backed string concatenations.
*
* @compile -XDstringConcat=inline Test7046096.java
* @run main/othervm -Xbatch compiler.c2.Test7046096
*/
package compiler.c2;
public class Test7046096 {

View File

@ -1,4 +1,5 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012 Skip Balk. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -32,6 +33,18 @@
* @author Skip Balk
*/
/*
* @test id=stringConcatInline
* @bug 7179138
* @summary The same test with an updated compile directive that produces
* StringBuilder-backed string concatenations.
*
* @compile -XDstringConcat=inline Test7179138_2.java
* @run main/othervm -Xbatch -XX:-TieredCompilation compiler.c2.Test7179138_2
*/
package compiler.c2;
public class Test7179138_2 {

View File

@ -0,0 +1,234 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package compiler.gcbarriers;
import compiler.lib.ir_framework.*;
import java.lang.invoke.VarHandle;
import java.lang.invoke.MethodHandles;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import jdk.test.lib.Asserts;
/**
* @test
* @summary Test that implicit null checks are generated as expected for
different GC memory accesses.
* @library /test/lib /
* @run driver compiler.gcbarriers.TestImplicitNullChecks
*/
public class TestImplicitNullChecks {
static class Outer {
Object f;
}
static class OuterWithVolatileField {
volatile Object f;
}
static final VarHandle fVarHandle;
static {
MethodHandles.Lookup l = MethodHandles.lookup();
try {
fVarHandle = l.findVarHandle(Outer.class, "f", Object.class);
} catch (Exception e) {
throw new Error(e);
}
}
public static void main(String[] args) {
TestFramework.runWithFlags("-XX:CompileCommand=inline,java.lang.ref.*::*",
"-XX:-TieredCompilation");
}
@Test
// On AIX, implicit null checks are limited because the zero page is
// readable (but not writable). See os::zero_page_read_protected().
@IR(applyIfPlatform = {"aix", "false"},
applyIfOr = {"UseZGC", "true", "UseG1GC", "true"},
counts = {IRNode.NULL_CHECK, "1"},
phase = CompilePhase.FINAL_CODE)
static Object testLoad(Outer o) {
return o.f;
}
@Test
// On aarch64, volatile loads always use indirect memory operands, which
// leads to a pattern that cannot be exploited by the current C2 analysis.
// On PPC64, volatile loads are preceded by membar_volatile instructions,
// which also inhibits the current C2 analysis.
@IR(applyIfPlatformAnd = {"aarch64", "false", "ppc", "false"},
applyIfOr = {"UseZGC", "true", "UseG1GC", "true"},
counts = {IRNode.NULL_CHECK, "1"},
phase = CompilePhase.FINAL_CODE)
static Object testLoadVolatile(OuterWithVolatileField o) {
return o.f;
}
@Run(test = {"testLoad",
"testLoadVolatile"},
mode = RunMode.STANDALONE)
static void runLoadTests() {
{
Outer o = new Outer();
// Trigger compilation with implicit null check.
for (int i = 0; i < 10_000; i++) {
testLoad(o);
}
// Trigger null pointer exception.
o = null;
boolean nullPointerException = false;
try {
testLoad(o);
} catch (NullPointerException e) { nullPointerException = true; }
Asserts.assertTrue(nullPointerException);
}
{
OuterWithVolatileField o = new OuterWithVolatileField();
// Trigger compilation with implicit null check.
for (int i = 0; i < 10_000; i++) {
testLoadVolatile(o);
}
// Trigger null pointer exception.
o = null;
boolean nullPointerException = false;
try {
testLoadVolatile(o);
} catch (NullPointerException e) { nullPointerException = true; }
Asserts.assertTrue(nullPointerException);
}
}
@Test
// G1 and ZGC stores cannot be currently used to implement implicit null
// checks, because they expand into multiple memory access instructions that
// are not necessarily located at the initial instruction start address.
@IR(applyIfOr = {"UseZGC", "true", "UseG1GC", "true"},
failOn = IRNode.NULL_CHECK,
phase = CompilePhase.FINAL_CODE)
static void testStore(Outer o, Object o1) {
o.f = o1;
}
@Run(test = {"testStore"})
static void runStoreTests() {
{
Outer o = new Outer();
Object o1 = new Object();
testStore(o, o1);
}
}
@Test
// G1 and ZGC compare-and-exchange operations cannot be currently used to
// implement implicit null checks, because they expand into multiple memory
// access instructions that are not necessarily located at the initial
// instruction start address. The same holds for testCompareAndSwap and
// testGetAndSet below.
@IR(applyIfOr = {"UseZGC", "true", "UseG1GC", "true"},
failOn = IRNode.NULL_CHECK,
phase = CompilePhase.FINAL_CODE)
static Object testCompareAndExchange(Outer o, Object oldVal, Object newVal) {
return fVarHandle.compareAndExchange(o, oldVal, newVal);
}
@Test
@IR(applyIfOr = {"UseZGC", "true", "UseG1GC", "true"},
failOn = IRNode.NULL_CHECK,
phase = CompilePhase.FINAL_CODE)
static boolean testCompareAndSwap(Outer o, Object oldVal, Object newVal) {
return fVarHandle.compareAndSet(o, oldVal, newVal);
}
@Test
@IR(applyIfOr = {"UseZGC", "true", "UseG1GC", "true"},
failOn = IRNode.NULL_CHECK,
phase = CompilePhase.FINAL_CODE)
static Object testGetAndSet(Outer o, Object newVal) {
return fVarHandle.getAndSet(o, newVal);
}
@Run(test = {"testCompareAndExchange",
"testCompareAndSwap",
"testGetAndSet"})
static void runAtomicTests() {
{
Outer o = new Outer();
Object oldVal = new Object();
Object newVal = new Object();
testCompareAndExchange(o, oldVal, newVal);
}
{
Outer o = new Outer();
Object oldVal = new Object();
Object newVal = new Object();
testCompareAndSwap(o, oldVal, newVal);
}
{
Outer o = new Outer();
Object oldVal = new Object();
Object newVal = new Object();
testGetAndSet(o, newVal);
}
}
@Test
// G1 reference loads use indirect memory operands, which leads to a pattern
// that cannot be exploited by the current C2 analysis. The same holds for
// testLoadWeakReference.
@IR(applyIf = {"UseZGC", "true"},
counts = {IRNode.NULL_CHECK, "1"},
phase = CompilePhase.FINAL_CODE)
static Object testLoadSoftReference(SoftReference<Object> ref) {
return ref.get();
}
@Test
@IR(applyIf = {"UseZGC", "true"},
counts = {IRNode.NULL_CHECK, "1"},
phase = CompilePhase.FINAL_CODE)
static Object testLoadWeakReference(WeakReference<Object> ref) {
return ref.get();
}
@Run(test = {"testLoadSoftReference",
"testLoadWeakReference"})
static void runReferenceTests() {
{
Object o1 = new Object();
SoftReference<Object> sref = new SoftReference<Object>(o1);
Object o2 = testLoadSoftReference(sref);
}
{
Object o1 = new Object();
WeakReference<Object> wref = new WeakReference<Object>(o1);
Object o2 = testLoadWeakReference(wref);
}
}
}

View File

@ -1499,6 +1499,11 @@ public class IRNode {
trapNodes(NULL_ASSERT_TRAP, "null_assert");
}
public static final String NULL_CHECK = PREFIX + "NULL_CHECK" + POSTFIX;
static {
machOnlyNameRegex(NULL_CHECK, "NullCheck");
}
public static final String NULL_CHECK_TRAP = PREFIX + "NULL_CHECK_TRAP" + POSTFIX;
static {
trapNodes(NULL_CHECK_TRAP, "null_check");

View File

@ -62,6 +62,7 @@ public class IREncodingPrinter {
// as adding non-existent platforms can lead to skipped tests.
private static final List<String> irTestingPlatforms = new ArrayList<String>(Arrays.asList(
// os.family
"aix",
"linux",
"mac",
"windows",
@ -346,7 +347,9 @@ public class IREncodingPrinter {
}
String os = "";
if (Platform.isLinux()) {
if (Platform.isAix()) {
os = "aix";
} else if (Platform.isLinux()) {
os = "linux";
} else if (Platform.isOSX()) {
os = "mac";

View File

@ -162,12 +162,12 @@ public class TestMinAndInitialSurvivorRatioFlags {
MemoryUsage survivorUsage = HeapRegionUsageTool.getSurvivorUsage();
long alignedNewSize = edenUsage.getMax() + 2 * survivorUsage.getMax();
long generationAlignment = wb.psHeapGenerationAlignment();
long spaceAlignment = wb.getHeapSpaceAlignment();
if (survivorRatio >= 0) {
// -XX:SurvivorRatio was passed to JVM, actual ratio should be SurvivorRatio + 2
long expectedSize = HeapRegionUsageTool.alignDown(alignedNewSize / (survivorRatio + 2),
generationAlignment);
spaceAlignment);
if (survivorUsage.getCommitted() != expectedSize) {
throw new RuntimeException("Expected survivor size is: " + expectedSize
@ -177,7 +177,7 @@ public class TestMinAndInitialSurvivorRatioFlags {
// In case of initial ratio verification or disabled adaptive size policy
// ratio should be equal to InitialSurvivorRatio value
long expectedSize = HeapRegionUsageTool.alignDown(alignedNewSize / initRatio,
generationAlignment);
spaceAlignment);
if (survivorUsage.getCommitted() != expectedSize) {
throw new RuntimeException("Expected survivor size is: " + expectedSize
+ ", but observed size is: " + survivorUsage.getCommitted());
@ -186,9 +186,9 @@ public class TestMinAndInitialSurvivorRatioFlags {
// In any other case actual survivor ratio should not be lower than MinSurvivorRatio
// or is should be equal to InitialSurvivorRatio
long expectedMinSize = HeapRegionUsageTool.alignDown(alignedNewSize / minRatio,
generationAlignment);
spaceAlignment);
long expectedInitSize = HeapRegionUsageTool.alignDown(alignedNewSize / initRatio,
generationAlignment);
spaceAlignment);
if (survivorUsage.getCommitted() != expectedInitSize
&& survivorUsage.getCommitted() < expectedMinSize) {
throw new RuntimeException("Expected survivor size should be " + expectedMinSize

View File

@ -146,10 +146,8 @@ public class TestNewRatioFlag {
long newSize = initEden + 2 * initSurv;
// See GenArguments::scale_by_NewRatio_aligned for calculation in the JVM.
long alignedDownNewSize = HeapRegionUsageTool.alignDown(initHeap / (expectedRatio + 1),
long expectedNewSize = HeapRegionUsageTool.alignDown(initHeap / (expectedRatio + 1),
wb.getHeapSpaceAlignment());
long expectedNewSize = HeapRegionUsageTool.alignUp(alignedDownNewSize,
wb.psVirtualSpaceAlignment());
if (expectedNewSize != newSize) {
throw new RuntimeException("Expected young gen size is: " + expectedNewSize

View File

@ -182,8 +182,6 @@ public class TestNewSizeFlags {
private static final GCTypes.YoungGCType YOUNG_GC_TYPE = GCTypes.YoungGCType.getYoungGCType();
private static final long HEAP_SPACE_ALIGNMENT = WB.getHeapSpaceAlignment();
private static final long HEAP_ALIGNMENT = WB.getHeapAlignment();
private static final long PS_VIRTUAL_SPACE_ALIGNMENT =
(YOUNG_GC_TYPE == GCTypes.YoungGCType.PSNew) ? WB.psVirtualSpaceAlignment() : 0;
public static final int ARRAY_LENGTH = 100;
public static final int CHUNK_SIZE = 1024;
@ -303,9 +301,7 @@ public class TestNewSizeFlags {
case DefNew:
return HeapRegionUsageTool.alignDown(value, HEAP_SPACE_ALIGNMENT);
case PSNew:
return HeapRegionUsageTool.alignUp(HeapRegionUsageTool.alignDown(value,
HEAP_SPACE_ALIGNMENT),
PS_VIRTUAL_SPACE_ALIGNMENT);
return HeapRegionUsageTool.alignDown(value, HEAP_SPACE_ALIGNMENT);
case G1:
return HeapRegionUsageTool.alignUp(value, WB.g1RegionSize());
default:

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