merge latest changes from master branch
This commit is contained in:
commit
4cee27b5ec
@ -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",
|
||||
},
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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", "سلام")
|
||||
}), };
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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") \
|
||||
\
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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_".
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
|
@ -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");
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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") \
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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))))
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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()],
|
||||
|
@ -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++) {
|
||||
|
@ -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.
|
||||
|
@ -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},
|
||||
|
@ -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() },
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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() {}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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",
|
||||
"",
|
||||
}
|
||||
},
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
21
src/java.base/share/data/cacerts/sectigocodesignroote46
Normal file
21
src/java.base/share/data/cacerts/sectigocodesignroote46
Normal 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-----
|
39
src/java.base/share/data/cacerts/sectigocodesignrootr46
Normal file
39
src/java.base/share/data/cacerts/sectigocodesignrootr46
Normal 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-----
|
21
src/java.base/share/data/cacerts/sectigotlsroote46
Normal file
21
src/java.base/share/data/cacerts/sectigotlsroote46
Normal 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-----
|
39
src/java.base/share/data/cacerts/sectigotlsrootr46
Normal file
39
src/java.base/share/data/cacerts/sectigotlsrootr46
Normal 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-----
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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" */
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
47
test/hotspot/gtest/gc/z/test_zPageAge.cpp
Normal file
47
test/hotspot/gtest/gc/z/test_zPageAge.cpp
Normal 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);
|
||||
}
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user