diff --git a/8143251-Thread-suspend-on-VM_G1IncCollectionPause-do.patch b/8143251-Thread-suspend-on-VM_G1IncCollectionPause-do.patch new file mode 100755 index 0000000000000000000000000000000000000000..32cc52ea101e271ca2a75d45d42f23ac2d8b5a86 --- /dev/null +++ b/8143251-Thread-suspend-on-VM_G1IncCollectionPause-do.patch @@ -0,0 +1,121 @@ +From e10cb7fc2dc99af5f7ccb4947fe828c008843f22 Mon Sep 17 00:00:00 2001 +From: mashoubing +Date: Tue, 14 Sep 2021 20:26:58 +0800 +Subject: [PATCH 21/23] 8143251:Thread suspend on + VM_G1IncCollectionPause::doit_epilogue() + +Summary: gc:call system.gc after remark cause Process suspending +LLT: NA +Patch Type:backport +Bug url:NA +--- + .../gc_implementation/g1/g1CollectedHeap.cpp | 14 +++++++++---- + .../gc_implementation/g1/g1CollectedHeap.hpp | 2 ++ + .../g1/g1CollectorPolicy.cpp | 21 +++++++++++++------ + .../g1/g1CollectorPolicy.hpp | 5 +++++ + 4 files changed, 32 insertions(+), 10 deletions(-) + +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +index 1afc2e331..8ed6207ad 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +@@ -2383,15 +2383,21 @@ size_t G1CollectedHeap::recalculate_used() const { + return blk.result(); + } + ++bool G1CollectedHeap::is_user_requested_concurrent_full_gc(GCCause::Cause cause) { ++ switch (cause) { ++ case GCCause::_java_lang_system_gc: return ExplicitGCInvokesConcurrent; ++ case GCCause::_update_allocation_context_stats_inc: return true; ++ case GCCause::_wb_conc_mark: return true; ++ default : return false; ++ } ++} ++ + bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) { + switch (cause) { + case GCCause::_gc_locker: return GCLockerInvokesConcurrent; +- case GCCause::_java_lang_system_gc: return ExplicitGCInvokesConcurrent; + case GCCause::_g1_humongous_allocation: return true; +- case GCCause::_update_allocation_context_stats_inc: return true; +- case GCCause::_wb_conc_mark: return true; + case GCCause::_g1_periodic_collection: return true; +- default: return false; ++ default: return is_user_requested_concurrent_full_gc(cause); + } + } + +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +index 2858ebfba..d83e6cb65 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +@@ -715,6 +715,8 @@ public: + _in_cset_fast_test.clear(); + } + ++ bool is_user_requested_concurrent_full_gc(GCCause::Cause cause); ++ + // This is called at the start of either a concurrent cycle or a Full + // GC to update the number of old marking cycles started. + void increment_old_marking_cycles_started(); +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +index 6d817883a..099762f2b 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +@@ -1504,6 +1504,11 @@ bool G1CollectorPolicy::force_initial_mark_if_outside_cycle( + } + } + ++void G1CollectorPolicy::initiate_conc_mark() { ++ set_during_initial_mark_pause(); ++ clear_initiate_conc_mark_if_possible(); ++} ++ + void + G1CollectorPolicy::decide_on_conc_mark_initiation() { + // We are about to decide on whether this pause will be an +@@ -1523,15 +1528,19 @@ G1CollectorPolicy::decide_on_conc_mark_initiation() { + if (!about_to_start_mixed_phase() && gcs_are_young()) { + // Initiate a new initial mark only if there is no marking or reclamation going + // on. +- set_during_initial_mark_pause(); +- +- // And we can now clear initiate_conc_mark_if_possible() as +- // we've already acted on it. +- clear_initiate_conc_mark_if_possible(); +- ++ initiate_conc_mark(); + ergo_verbose0(ErgoConcCycles, + "initiate concurrent cycle", + ergo_format_reason("concurrent cycle initiation requested")); ++ } else if (_g1->is_user_requested_concurrent_full_gc(_g1->gc_cause())) { ++ // Initiate a user requested initial mark. An initial mark must be young only ++ // GC, so the collector state must be updated to reflect this. ++ set_gcs_are_young(true); ++ _last_young_gc = false; ++ initiate_conc_mark(); ++ ergo_verbose0(ErgoConcCycles, ++ "initiate concurrent cycle", ++ ergo_format_reason("user requested concurrent cycle")); + } else { + // The concurrent marking thread is still finishing up the + // previous cycle. If we start one right now the two cycles +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +index 6438e5e90..1a0d20d6f 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +@@ -808,6 +808,11 @@ private: + // (should not be called directly). + void add_region_to_incremental_cset_common(HeapRegion* hr); + ++ // Set the state to start a concurrent marking cycle and clear ++ // _initiate_conc_mark_if_possible because it has now been ++ // acted on. ++ void initiate_conc_mark(); ++ + public: + // Add hr to the LHS of the incremental collection set. + void add_region_to_incremental_cset_lhs(HeapRegion* hr); +-- +2.22.0 + diff --git a/8167014-jdeps-failed-with-Missing-message-warn-skippen-entry.patch b/8167014-jdeps-failed-with-Missing-message-warn-skippen-entry.patch new file mode 100755 index 0000000000000000000000000000000000000000..14826470b4e8280cc82458a3eca98f649adc37ed --- /dev/null +++ b/8167014-jdeps-failed-with-Missing-message-warn-skippen-entry.patch @@ -0,0 +1,64 @@ +From 6456acbb0412f0a0f3e7374b27e66a504ece36ff Mon Sep 17 00:00:00 2001 +From: c00229008 +Date: Wed, 4 Aug 2021 09:43:49 +0800 +Subject: [PATCH 01/23] 8167014: jdeps failed with "Missing message: + warn.skipped.entry" + +Summary: : jdeps failed with "Missing message: warn.skipped.entry" +LLT: tomcat-websocket-10.0.8.jar +Patch Type: backport +Bug url: https://bugs.openjdk.java.net/browse/JDK-8167014 +--- + .../share/classes/com/sun/tools/jdeps/ClassFileReader.java | 5 ++++- + .../src/share/classes/com/sun/tools/jdeps/JdepsTask.java | 6 ++++-- + .../classes/com/sun/tools/jdeps/resources/jdeps.properties | 1 + + 3 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/langtools/src/share/classes/com/sun/tools/jdeps/ClassFileReader.java b/langtools/src/share/classes/com/sun/tools/jdeps/ClassFileReader.java +index f41f2d0ba..07da40357 100644 +--- a/langtools/src/share/classes/com/sun/tools/jdeps/ClassFileReader.java ++++ b/langtools/src/share/classes/com/sun/tools/jdeps/ClassFileReader.java +@@ -337,7 +337,10 @@ public class ClassFileReader { + cf = reader.readClassFile(jf, nextEntry); + return true; + } catch (ClassFileError | IOException ex) { +- skippedEntries.add(nextEntry.getName()); ++ skippedEntries.add(String.format("%s: %s (%s)", ++ ex.getMessage(), ++ nextEntry.getName(), ++ jf.getName())); + } + nextEntry = nextEntry(); + } +diff --git a/langtools/src/share/classes/com/sun/tools/jdeps/JdepsTask.java b/langtools/src/share/classes/com/sun/tools/jdeps/JdepsTask.java +index 91002d319..97dba138e 100644 +--- a/langtools/src/share/classes/com/sun/tools/jdeps/JdepsTask.java ++++ b/langtools/src/share/classes/com/sun/tools/jdeps/JdepsTask.java +@@ -559,8 +559,10 @@ class JdepsTask { + a.addClass(d.getOrigin()); + } + } +- for (String name : a.reader().skippedEntries()) { +- warning("warn.skipped.entry", name, a.getPathName()); ++ if (!options.nowarning) { ++ for (String name : a.reader().skippedEntries()) { ++ warning("warn.skipped.entry", name, a.getPathName()); ++ } + } + } + } +diff --git a/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdeps.properties b/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdeps.properties +index 51d11b88a..501c4d6cd 100644 +--- a/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdeps.properties ++++ b/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdeps.properties +@@ -92,6 +92,7 @@ err.option.unsupported={0} not supported: {1} + err.profiles.msg=No profile information + err.invalid.path=invalid path: {0} + warn.invalid.arg=Invalid classname or pathname not exist: {0} ++warn.skipped.entry={0} + warn.split.package=package {0} defined in {1} {2} + warn.replace.useJDKInternals=\ + JDK internal APIs are unsupported and private to JDK implementation that are\n\ +-- +2.22.0 + diff --git a/8197387-Run-the-jcmd-tool-as-the-root-user-to-access.patch b/8197387-Run-the-jcmd-tool-as-the-root-user-to-access.patch new file mode 100755 index 0000000000000000000000000000000000000000..cd6fa3431c0e79e84a013333bd88ff342f38fd17 --- /dev/null +++ b/8197387-Run-the-jcmd-tool-as-the-root-user-to-access.patch @@ -0,0 +1,305 @@ +From a83cfc9dc14746ad816933008e700d6d35dcf5f6 Mon Sep 17 00:00:00 2001 +From: wangkun +Date: Sat, 11 Sep 2021 09:45:39 +0800 +Subject: [PATCH 12/23] 8197387: Run the jcmd tool as the root user to access + the Java process that is not run by the root user. + +Summary: : Run the jcmd tool as the root user to access the Java process that is not run by the root user. +LLT: NA +Patch Type: backport +Bug url: https://bugs.openjdk.java.net/browse/JDK-8197387 +--- + hotspot/src/os/aix/vm/attachListener_aix.cpp | 11 +++++------ + hotspot/src/os/bsd/vm/attachListener_bsd.cpp | 11 +++++------ + hotspot/src/os/linux/vm/attachListener_linux.cpp | 11 +++++------ + hotspot/src/os/posix/vm/os_posix.cpp | 14 ++++++++++++++ + hotspot/src/os/posix/vm/os_posix.hpp | 10 ++++++++++ + .../src/os/solaris/vm/attachListener_solaris.cpp | 12 ++++++------ + .../native/sun/tools/attach/AixVirtualMachine.c | 5 +++-- + .../native/sun/tools/attach/BsdVirtualMachine.c | 6 ++++-- + .../native/sun/tools/attach/LinuxVirtualMachine.c | 6 ++++-- + .../sun/tools/attach/SolarisVirtualMachine.c | 6 ++++-- + 10 files changed, 60 insertions(+), 32 deletions(-) + +diff --git a/hotspot/src/os/aix/vm/attachListener_aix.cpp b/hotspot/src/os/aix/vm/attachListener_aix.cpp +index 5b7cb29f1..d23756ead 100644 +--- a/hotspot/src/os/aix/vm/attachListener_aix.cpp ++++ b/hotspot/src/os/aix/vm/attachListener_aix.cpp +@@ -382,10 +382,9 @@ AixAttachOperation* AixAttachListener::dequeue() { + RESTARTABLE(::close(s), res); + continue; + } +- uid_t euid = geteuid(); +- gid_t egid = getegid(); +- +- if (cred_info.euid != euid || cred_info.egid != egid) { ++ if (!os::Posix::matches_effective_uid_and_gid_or_root(cred_info.euid, cred_info.egid)) { ++ log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", ++ cred_info.euid, cred_info.egid, geteuid(), getegid()); + int res; + RESTARTABLE(::close(s), res); + continue; +@@ -541,8 +540,8 @@ bool AttachListener::is_init_trigger() { + } + if (ret == 0) { + // simple check to avoid starting the attach mechanism when +- // a bogus user creates the file +- if (st.st_uid == geteuid()) { ++ // a bogus non-root user creates the file ++ if (os::Posix::matches_effective_uid_or_root(st.st_uid)) { + init(); + return true; + } +diff --git a/hotspot/src/os/bsd/vm/attachListener_bsd.cpp b/hotspot/src/os/bsd/vm/attachListener_bsd.cpp +index 4a580b486..4dd938954 100644 +--- a/hotspot/src/os/bsd/vm/attachListener_bsd.cpp ++++ b/hotspot/src/os/bsd/vm/attachListener_bsd.cpp +@@ -348,10 +348,9 @@ BsdAttachOperation* BsdAttachListener::dequeue() { + ::close(s); + continue; + } +- uid_t euid = geteuid(); +- gid_t egid = getegid(); +- +- if (puid != euid || pgid != egid) { ++ if (!os::Posix::matches_effective_uid_and_gid_or_root(puid, pgid)) { ++ log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", puid, pgid, ++ geteuid(), getegid()); + ::close(s); + continue; + } +@@ -502,8 +501,8 @@ bool AttachListener::is_init_trigger() { + RESTARTABLE(::stat(path, &st), ret); + if (ret == 0) { + // simple check to avoid starting the attach mechanism when +- // a bogus user creates the file +- if (st.st_uid == geteuid()) { ++ // a bogus non-root user creates the file ++ if (os::Posix::matches_effective_uid_or_root(st.st_uid)) { + init(); + return true; + } +diff --git a/hotspot/src/os/linux/vm/attachListener_linux.cpp b/hotspot/src/os/linux/vm/attachListener_linux.cpp +index 1ca089740..2a87e0d7f 100644 +--- a/hotspot/src/os/linux/vm/attachListener_linux.cpp ++++ b/hotspot/src/os/linux/vm/attachListener_linux.cpp +@@ -343,10 +343,9 @@ LinuxAttachOperation* LinuxAttachListener::dequeue() { + ::close(s); + continue; + } +- uid_t euid = geteuid(); +- gid_t egid = getegid(); +- +- if (cred_info.uid != euid || cred_info.gid != egid) { ++ if (!os::Posix::matches_effective_uid_and_gid_or_root(cred_info.uid, cred_info.gid)) { ++ tty->print_cr("euid/egid check failed (%d/%d vs %d/%d)", ++ cred_info.uid, cred_info.gid, geteuid(), getegid()); + ::close(s); + continue; + } +@@ -512,8 +511,8 @@ bool AttachListener::is_init_trigger() { + } + if (ret == 0) { + // simple check to avoid starting the attach mechanism when +- // a bogus user creates the file +- if (st.st_uid == geteuid()) { ++ // a bogus non-root user creates the file ++ if (os::Posix::matches_effective_uid_or_root(st.st_uid)) { + init(); + return true; + } +diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp +index ac00e85ba..e7f1fddb9 100644 +--- a/hotspot/src/os/posix/vm/os_posix.cpp ++++ b/hotspot/src/os/posix/vm/os_posix.cpp +@@ -44,6 +44,8 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC + #endif + #define IS_VALID_PID(p) (p > 0 && p < MAX_PID) + ++#define ROOT_UID 0 ++ + // Check core dump limit and report possible place where core can be found + void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) { + int n; +@@ -858,6 +860,18 @@ void os::Posix::print_siginfo_brief(outputStream* os, const siginfo_t* si) { + } + } + ++bool os::Posix::is_root(uid_t uid){ ++ return ROOT_UID == uid; ++} ++ ++bool os::Posix::matches_effective_uid_or_root(uid_t uid) { ++ return is_root(uid) || geteuid() == uid; ++} ++ ++bool os::Posix::matches_effective_uid_and_gid_or_root(uid_t uid, gid_t gid) { ++ return is_root(uid) || (geteuid() == uid && getegid() == gid); ++} ++ + Thread* os::ThreadCrashProtection::_protected_thread = NULL; + os::ThreadCrashProtection* os::ThreadCrashProtection::_crash_protection = NULL; + volatile intptr_t os::ThreadCrashProtection::_crash_mux = 0; +diff --git a/hotspot/src/os/posix/vm/os_posix.hpp b/hotspot/src/os/posix/vm/os_posix.hpp +index 5cdbb9ae6..d3e55d020 100644 +--- a/hotspot/src/os/posix/vm/os_posix.hpp ++++ b/hotspot/src/os/posix/vm/os_posix.hpp +@@ -59,6 +59,16 @@ public: + // A POSIX conform, platform-independend siginfo print routine. + static void print_siginfo_brief(outputStream* os, const siginfo_t* si); + ++ // Returns true if given uid is root. ++ static bool is_root(uid_t uid); ++ ++ // Returns true if given uid is effective or root uid. ++ static bool matches_effective_uid_or_root(uid_t uid); ++ ++ // Returns true if either given uid is effective uid and given gid is ++ // effective gid, or if given uid is root. ++ static bool matches_effective_uid_and_gid_or_root(uid_t uid, gid_t gid); ++ + }; + + /* +diff --git a/hotspot/src/os/solaris/vm/attachListener_solaris.cpp b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp +index 37400795e..001f8cbce 100644 +--- a/hotspot/src/os/solaris/vm/attachListener_solaris.cpp ++++ b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp +@@ -205,12 +205,12 @@ static int check_credentials() { + return -1; // unable to get them + } + +- // get our euid/eguid (probably could cache these) +- uid_t euid = geteuid(); +- gid_t egid = getegid(); ++ // get euid/egid from ucred_free ++ uid_t ucred_euid = ucred_geteuid(cred_info); ++ gid_t ucred_egid = ucred_getegid(cred_info); + + // check that the effective uid/gid matches - discuss this with Jeff. +- if (cred_info.dc_euid == euid && cred_info.dc_egid == egid) { ++ if (os::Posix::matches_effective_uid_and_gid_or_root(ucred_euid, ucred_egid)) { + return 0; // okay + } else { + return -1; // denied +@@ -644,8 +644,8 @@ bool AttachListener::is_init_trigger() { + } + if (ret == 0) { + // simple check to avoid starting the attach mechanism when +- // a bogus user creates the file +- if (st.st_uid == geteuid()) { ++ // a bogus non-root user creates the file ++ if (os::Posix::matches_effective_uid_or_root(st.st_uid)) { + init(); + return true; + } +diff --git a/jdk/src/aix/native/sun/tools/attach/AixVirtualMachine.c b/jdk/src/aix/native/sun/tools/attach/AixVirtualMachine.c +index a1e6539e4..b67a0fe5a 100644 +--- a/jdk/src/aix/native/sun/tools/attach/AixVirtualMachine.c ++++ b/jdk/src/aix/native/sun/tools/attach/AixVirtualMachine.c +@@ -54,6 +54,7 @@ + } while((_result == -1) && (errno == EINTR)); \ + } while(0) + ++#define ROOT_UID 0 + + /* + * Class: sun_tools_attach_AixVirtualMachine +@@ -188,11 +189,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_AixVirtualMachine_checkPermissions + if (res == 0) { + char msg[100]; + jboolean isError = JNI_FALSE; +- if (sb.st_uid != uid) { ++ if (sb.st_uid != uid && uid != ROOT_UID) { + jio_snprintf(msg, sizeof(msg)-1, + "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid); + isError = JNI_TRUE; +- } else if (sb.st_gid != gid) { ++ } else if (sb.st_gid != gid && uid != ROOT_UID) { + jio_snprintf(msg, sizeof(msg)-1, + "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid); + isError = JNI_TRUE; +diff --git a/jdk/src/solaris/native/sun/tools/attach/BsdVirtualMachine.c b/jdk/src/solaris/native/sun/tools/attach/BsdVirtualMachine.c +index f5afaab57..daf7b7ed9 100644 +--- a/jdk/src/solaris/native/sun/tools/attach/BsdVirtualMachine.c ++++ b/jdk/src/solaris/native/sun/tools/attach/BsdVirtualMachine.c +@@ -50,6 +50,8 @@ + } while((_result == -1) && (errno == EINTR)); \ + } while(0) + ++#define ROOT_UID 0 ++ + /* + * Class: sun_tools_attach_BsdVirtualMachine + * Method: socket +@@ -153,11 +155,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_BsdVirtualMachine_checkPermissions + if (res == 0) { + char msg[100]; + jboolean isError = JNI_FALSE; +- if (sb.st_uid != uid) { ++ if (sb.st_uid != uid && uid != ROOT_UID) { + jio_snprintf(msg, sizeof(msg)-1, + "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid); + isError = JNI_TRUE; +- } else if (sb.st_gid != gid) { ++ } else if (sb.st_gid != gid && uid != ROOT_UID) { + jio_snprintf(msg, sizeof(msg)-1, + "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid); + isError = JNI_TRUE; +diff --git a/jdk/src/solaris/native/sun/tools/attach/LinuxVirtualMachine.c b/jdk/src/solaris/native/sun/tools/attach/LinuxVirtualMachine.c +index 6017308d0..32b7f8785 100644 +--- a/jdk/src/solaris/native/sun/tools/attach/LinuxVirtualMachine.c ++++ b/jdk/src/solaris/native/sun/tools/attach/LinuxVirtualMachine.c +@@ -49,6 +49,8 @@ + } while((_result == -1) && (errno == EINTR)); \ + } while(0) + ++#define ROOT_UID 0 ++ + /* + * Defines a callback that is invoked for each process + */ +@@ -371,11 +373,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_LinuxVirtualMachine_checkPermission + if (res == 0) { + char msg[100]; + jboolean isError = JNI_FALSE; +- if (sb.st_uid != uid) { ++ if (sb.st_uid != uid && uid != ROOT_UID) { + jio_snprintf(msg, sizeof(msg)-1, + "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid); + isError = JNI_TRUE; +- } else if (sb.st_gid != gid) { ++ } else if (sb.st_gid != gid && uid != ROOT_UID) { + jio_snprintf(msg, sizeof(msg)-1, + "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid); + isError = JNI_TRUE; +diff --git a/jdk/src/solaris/native/sun/tools/attach/SolarisVirtualMachine.c b/jdk/src/solaris/native/sun/tools/attach/SolarisVirtualMachine.c +index d2710aaab..217943988 100644 +--- a/jdk/src/solaris/native/sun/tools/attach/SolarisVirtualMachine.c ++++ b/jdk/src/solaris/native/sun/tools/attach/SolarisVirtualMachine.c +@@ -45,6 +45,8 @@ + } while((_result == -1) && (errno == EINTR)); \ + } while(0) + ++#define ROOT_UID 0 ++ + /* + * Class: sun_tools_attach_SolarisVirtualMachine + * Method: open +@@ -116,11 +118,11 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_SolarisVirtualMachine_checkPermissi + if (res == 0) { + char msg[100]; + jboolean isError = JNI_FALSE; +- if (sb.st_uid != uid) { ++ if (sb.st_uid != uid && uid != ROOT_UID) { + jio_snprintf(msg, sizeof(msg)-1, + "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid); + isError = JNI_TRUE; +- } else if (sb.st_gid != gid) { ++ } else if (sb.st_gid != gid && uid != ROOT_UID) { + jio_snprintf(msg, sizeof(msg)-1, + "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid); + isError = JNI_TRUE; +-- +2.22.0 + diff --git a/8202142-jfr-event-io-TestInstrumentation-is-unstable.patch b/8202142-jfr-event-io-TestInstrumentation-is-unstable.patch new file mode 100755 index 0000000000000000000000000000000000000000..6c10c0a559d0a8d58e98c6330089d1f9e5b8a4f8 --- /dev/null +++ b/8202142-jfr-event-io-TestInstrumentation-is-unstable.patch @@ -0,0 +1,1185 @@ +From baadf220d261a6c610920d749a2b9c19f864ba96 Mon Sep 17 00:00:00 2001 +From: wuyan +Date: Sat, 11 Sep 2021 10:07:53 +0800 +Subject: [PATCH 20/23] 8202142: jfr/event/io/TestInstrumentation is unstable + +Summary: : JDK-8202142: jfr/event/io/TestInstrumentation is unstable +LLT: jdk/test/jdk/jfr/event/io/TestInstrumentation.java +Patch Type: backport +Bug url: https://bugs.openjdk.java.net/browse/JDK-8202142 +--- + jdk/test/jdk/jfr/event/io/IOEvent.java | 9 +- + jdk/test/jdk/jfr/event/io/IOHelper.java | 8 +- + .../jdk/jfr/event/io/TestDisabledEvents.java | 33 +-- + .../jfr/event/io/TestFileChannelEvents.java | 138 +++++------ + .../jdk/jfr/event/io/TestFileReadOnly.java | 77 +++--- + .../jfr/event/io/TestFileStreamEvents.java | 69 +++--- + .../jdk/jfr/event/io/TestInstrumentation.java | 4 +- + .../event/io/TestRandomAccessFileEvents.java | 115 ++++----- + .../event/io/TestRandomAccessFileThread.java | 222 +++++++++--------- + .../jfr/event/io/TestSocketChannelEvents.java | 122 +++++----- + .../jdk/jfr/event/io/TestSocketEvents.java | 104 ++++---- + 11 files changed, 455 insertions(+), 446 deletions(-) + +diff --git a/jdk/test/jdk/jfr/event/io/IOEvent.java b/jdk/test/jdk/jfr/event/io/IOEvent.java +index e3939fbf8..dcf70ccc3 100644 +--- a/jdk/test/jdk/jfr/event/io/IOEvent.java ++++ b/jdk/test/jdk/jfr/event/io/IOEvent.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2020, 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 +@@ -197,14 +197,11 @@ public class IOEvent { + } + return canonical_path; + } else { +- return String.format("%s/%s:%d", +- event.getValue("host"), +- event.getValue("address"), +- event.getValue("port")); ++ return event.getValue("address") + ":" + event.getValue("port"); + } + } + + private static String getAddress(Socket s) { +- return s.getInetAddress().toString() + ":" + s.getPort(); ++ return s.getInetAddress().getHostAddress() + ":" + s.getPort(); + } + } +diff --git a/jdk/test/jdk/jfr/event/io/IOHelper.java b/jdk/test/jdk/jfr/event/io/IOHelper.java +index f1f205529..23e61f59a 100644 +--- a/jdk/test/jdk/jfr/event/io/IOHelper.java ++++ b/jdk/test/jdk/jfr/event/io/IOHelper.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2020, 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,6 +28,8 @@ package jdk.jfr.event.io; + import static jdk.test.lib.Asserts.assertEquals; + import static jdk.test.lib.Asserts.assertTrue; + ++import java.util.Collections; ++import java.util.Comparator; + import java.util.List; + import java.util.stream.Collectors; + +@@ -41,6 +43,7 @@ import jdk.test.lib.jfr.Events; + public class IOHelper { + + public static void verifyEqualsInOrder(List events, List expectedEvents) throws Throwable { ++ Collections.sort(events, Comparator.comparing(RecordedEvent::getStartTime)); + List actualEvents = getTestEvents(events, expectedEvents); + try { + assertEquals(actualEvents.size(), expectedEvents.size(), "Wrong number of events."); +@@ -48,6 +51,9 @@ public class IOHelper { + assertEquals(actualEvents.get(i), expectedEvents.get(i), "Wrong event at pos " + i); + } + } catch (Throwable t) { ++ for (RecordedEvent e: events) { ++ System.out.println(e); ++ } + logEvents(actualEvents, expectedEvents); + throw t; + } +diff --git a/jdk/test/jdk/jfr/event/io/TestDisabledEvents.java b/jdk/test/jdk/jfr/event/io/TestDisabledEvents.java +index aad1b217f..d80304cf0 100644 +--- a/jdk/test/jdk/jfr/event/io/TestDisabledEvents.java ++++ b/jdk/test/jdk/jfr/event/io/TestDisabledEvents.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2020, 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 +@@ -57,21 +57,22 @@ public class TestDisabledEvents { + public static void main(String[] args) throws Throwable { + File tmp = File.createTempFile("TestDisabledEvents", ".tmp", new File(".")); + tmp.deleteOnExit(); +- Recording recording = new Recording(); +- recording.disable(IOEvent.EVENT_FILE_READ); +- recording.disable(IOEvent.EVENT_FILE_WRITE); +- recording.start(); +- +- useRandomAccessFile(tmp); +- useFileStreams(tmp); +- useFileChannel(tmp); +- +- recording.stop(); +- for (RecordedEvent event : Events.fromRecording(recording)) { +- final String eventName = event.getEventType().getName(); +- System.out.println("Got eventName:" + eventName); +- assertNotEquals(eventName, IOEvent.EVENT_FILE_READ, "Got disabled read event"); +- assertNotEquals(eventName, IOEvent.EVENT_FILE_WRITE, "Got disabled write event"); ++ try (Recording recording = new Recording()) { ++ recording.disable(IOEvent.EVENT_FILE_READ); ++ recording.disable(IOEvent.EVENT_FILE_WRITE); ++ recording.start(); ++ ++ useRandomAccessFile(tmp); ++ useFileStreams(tmp); ++ useFileChannel(tmp); ++ ++ recording.stop(); ++ for (RecordedEvent event : Events.fromRecording(recording)) { ++ final String eventName = event.getEventType().getName(); ++ System.out.println("Got eventName:" + eventName); ++ assertNotEquals(eventName, IOEvent.EVENT_FILE_READ, "Got disabled read event"); ++ assertNotEquals(eventName, IOEvent.EVENT_FILE_WRITE, "Got disabled write event"); ++ } + } + } + +diff --git a/jdk/test/jdk/jfr/event/io/TestFileChannelEvents.java b/jdk/test/jdk/jfr/event/io/TestFileChannelEvents.java +index cb90bc54f..632fcaba3 100644 +--- a/jdk/test/jdk/jfr/event/io/TestFileChannelEvents.java ++++ b/jdk/test/jdk/jfr/event/io/TestFileChannelEvents.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2020, 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 +@@ -50,74 +50,74 @@ public class TestFileChannelEvents { + public static void main(String[] args) throws Throwable { + File tmp = File.createTempFile("TestFileChannelEvents", ".tmp", new File(".")); + tmp.deleteOnExit(); +- Recording recording = new Recording(); +- List expectedEvents = new ArrayList<>(); +- +- try (RandomAccessFile rf = new RandomAccessFile(tmp, "rw"); FileChannel ch = rf.getChannel();) { +- recording.enable(IOEvent.EVENT_FILE_FORCE).withThreshold(Duration.ofMillis(0)); +- recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0)); +- recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0)); +- recording.start(); +- +- ByteBuffer bufA = ByteBuffer.allocateDirect(10); +- ByteBuffer bufB = ByteBuffer.allocateDirect(20); +- bufA.put("1234567890".getBytes()); +- bufB.put("1234567890".getBytes()); +- +- // test write(ByteBuffer) +- bufA.flip(); +- long size = ch.write(bufA); +- expectedEvents.add(IOEvent.createFileWriteEvent(size, tmp)); +- +- // test write(ByteBuffer, long) +- bufA.flip(); +- size = ch.write(bufA, bufA.capacity() / 2); +- expectedEvents.add(IOEvent.createFileWriteEvent(size, tmp)); +- +- // test write(ByteBuffer[]) +- bufA.flip(); +- bufA.limit(5); +- bufB.flip(); +- bufB.limit(5); +- size = ch.write(new ByteBuffer[] { bufA, bufB }); +- expectedEvents.add(IOEvent.createFileWriteEvent(size, tmp)); +- +- // test force(boolean) +- ch.force(true); +- expectedEvents.add(IOEvent.createFileForceEvent(tmp)); +- +- // reset file +- ch.position(0); +- +- // test read(ByteBuffer) +- bufA.clear(); +- size = ch.read(bufA); +- expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); +- +- // test read(ByteBuffer, long) +- bufA.clear(); +- size = ch.read(bufA, bufA.capacity() / 2); +- expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); +- +- // test read(ByteBuffer[]) +- bufA.clear(); +- bufA.limit(5); +- bufB.clear(); +- bufB.limit(5); +- size = ch.read(new ByteBuffer[] { bufA, bufB }); +- expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); +- +- // Read at EOF. Should get size -1 in event. +- ch.position(ch.size()); +- bufA.clear(); +- size = ch.read(bufA); +- assertEquals(size, -1L, "Expected size -1 when read at EOF"); +- expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); +- +- ch.close(); +- recording.stop(); +- List events = Events.fromRecording(recording); +- IOHelper.verifyEqualsInOrder(events, expectedEvents); ++ try (Recording recording = new Recording()) { ++ List expectedEvents = new ArrayList<>(); ++ try (RandomAccessFile rf = new RandomAccessFile(tmp, "rw"); FileChannel ch = rf.getChannel();) { ++ recording.enable(IOEvent.EVENT_FILE_FORCE).withThreshold(Duration.ofMillis(0)); ++ recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0)); ++ recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0)); ++ recording.start(); ++ ++ ByteBuffer bufA = ByteBuffer.allocateDirect(10); ++ ByteBuffer bufB = ByteBuffer.allocateDirect(20); ++ bufA.put("1234567890".getBytes()); ++ bufB.put("1234567890".getBytes()); ++ ++ // test write(ByteBuffer) ++ bufA.flip(); ++ long size = ch.write(bufA); ++ expectedEvents.add(IOEvent.createFileWriteEvent(size, tmp)); ++ ++ // test write(ByteBuffer, long) ++ bufA.flip(); ++ size = ch.write(bufA, bufA.capacity() / 2); ++ expectedEvents.add(IOEvent.createFileWriteEvent(size, tmp)); ++ ++ // test write(ByteBuffer[]) ++ bufA.flip(); ++ bufA.limit(5); ++ bufB.flip(); ++ bufB.limit(5); ++ size = ch.write(new ByteBuffer[] { bufA, bufB }); ++ expectedEvents.add(IOEvent.createFileWriteEvent(size, tmp)); ++ ++ // test force(boolean) ++ ch.force(true); ++ expectedEvents.add(IOEvent.createFileForceEvent(tmp)); ++ ++ // reset file ++ ch.position(0); ++ ++ // test read(ByteBuffer) ++ bufA.clear(); ++ size = ch.read(bufA); ++ expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); ++ ++ // test read(ByteBuffer, long) ++ bufA.clear(); ++ size = ch.read(bufA, bufA.capacity() / 2); ++ expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); ++ ++ // test read(ByteBuffer[]) ++ bufA.clear(); ++ bufA.limit(5); ++ bufB.clear(); ++ bufB.limit(5); ++ size = ch.read(new ByteBuffer[] { bufA, bufB }); ++ expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); ++ ++ // Read at EOF. Should get size -1 in event. ++ ch.position(ch.size()); ++ bufA.clear(); ++ size = ch.read(bufA); ++ assertEquals(size, -1L, "Expected size -1 when read at EOF"); ++ expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); ++ ++ ch.close(); ++ recording.stop(); ++ List events = Events.fromRecording(recording); ++ IOHelper.verifyEqualsInOrder(events, expectedEvents); ++ } + } + } + } +diff --git a/jdk/test/jdk/jfr/event/io/TestFileReadOnly.java b/jdk/test/jdk/jfr/event/io/TestFileReadOnly.java +index 065ebadc3..b7e20d0ef 100644 +--- a/jdk/test/jdk/jfr/event/io/TestFileReadOnly.java ++++ b/jdk/test/jdk/jfr/event/io/TestFileReadOnly.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2020, 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 +@@ -52,50 +52,51 @@ public class TestFileReadOnly { + public static void main(String[] args) throws Throwable { + File tmp = File.createTempFile("TestFileReadOnly", ".tmp", new File(".")); + tmp.deleteOnExit(); +- Recording recording = new Recording(); +- List expectedEvents = new ArrayList<>(); ++ try(Recording recording = new Recording()) { ++ List expectedEvents = new ArrayList<>(); + +- recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0)); +- recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0)); +- recording.start(); ++ recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0)); ++ recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0)); ++ recording.start(); + +- final byte[] buf = { 1, 2, 3 }; ++ final byte[] buf = { 1, 2, 3 }; + +- // Create the file. +- try (RandomAccessFile f = new RandomAccessFile(tmp, "rw")) { +- f.write(buf); +- expectedEvents.add(IOEvent.createFileWriteEvent(buf.length, tmp)); +- } +- +- // Reopen the file as ReadOnly and try to write to it. +- // Should generate an event with bytesWritten = -1. +- try (RandomAccessFile f = new RandomAccessFile(tmp, "r")) { +- try { ++ // Create the file. ++ try (RandomAccessFile f = new RandomAccessFile(tmp, "rw")) { + f.write(buf); +- fail("No exception for ReadOnly File"); +- } catch (IOException e) { +- // Expected exception +- expectedEvents.add(IOEvent.createFileWriteEvent(-1, tmp)); ++ expectedEvents.add(IOEvent.createFileWriteEvent(buf.length, tmp)); + } +- } + +- // Try to write to read-only FileChannel. +- try (RandomAccessFile f = new RandomAccessFile(tmp, "r"); FileChannel ch = f.getChannel()) { +- ByteBuffer writeBuf = ByteBuffer.allocateDirect(buf.length); +- writeBuf.put(buf); +- writeBuf.flip(); +- ch.position(0); +- try { +- ch.write(writeBuf); +- fail("No exception for ReadOnly FileChannel"); +- } catch (java.nio.channels.NonWritableChannelException e) { +- // Expected exception +- expectedEvents.add(IOEvent.createFileWriteEvent(-1, tmp)); ++ // Reopen the file as ReadOnly and try to write to it. ++ // Should generate an event with bytesWritten = -1. ++ try (RandomAccessFile f = new RandomAccessFile(tmp, "r")) { ++ try { ++ f.write(buf); ++ fail("No exception for ReadOnly File"); ++ } catch (IOException e) { ++ // Expected exception ++ expectedEvents.add(IOEvent.createFileWriteEvent(-1, tmp)); ++ } + } +- } + +- recording.stop(); +- List events = Events.fromRecording(recording); +- IOHelper.verifyEqualsInOrder(events, expectedEvents); ++ // Try to write to read-only FileChannel. ++ try (RandomAccessFile f = new RandomAccessFile(tmp, "r"); FileChannel ch = f.getChannel()) { ++ ByteBuffer writeBuf = ByteBuffer.allocateDirect(buf.length); ++ writeBuf.put(buf); ++ writeBuf.flip(); ++ ch.position(0); ++ try { ++ ch.write(writeBuf); ++ fail("No exception for ReadOnly FileChannel"); ++ } catch (java.nio.channels.NonWritableChannelException e) { ++ // Expected exception ++ expectedEvents.add(IOEvent.createFileWriteEvent(-1, tmp)); ++ } ++ } ++ ++ recording.stop(); ++ List events = Events.fromRecording(recording); ++ IOHelper.verifyEqualsInOrder(events, expectedEvents); ++ } + } + } +diff --git a/jdk/test/jdk/jfr/event/io/TestFileStreamEvents.java b/jdk/test/jdk/jfr/event/io/TestFileStreamEvents.java +index 46c7b80f3..0bddf5a6c 100644 +--- a/jdk/test/jdk/jfr/event/io/TestFileStreamEvents.java ++++ b/jdk/test/jdk/jfr/event/io/TestFileStreamEvents.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2020, 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 +@@ -50,47 +50,48 @@ public class TestFileStreamEvents { + public static void main(String[] args) throws Throwable { + File tmp = File.createTempFile("TestFileStreamEvents", ".tmp", new File(".")); + tmp.deleteOnExit(); +- Recording recording = new Recording(); +- List expectedEvents = new ArrayList<>(); ++ try (Recording recording = new Recording()) { ++ List expectedEvents = new ArrayList<>(); + +- try(FileOutputStream fos = new FileOutputStream(tmp); FileInputStream fis = new FileInputStream(tmp);) { +- recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0)); +- recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0)); +- recording.start(); ++ try(FileOutputStream fos = new FileOutputStream(tmp); FileInputStream fis = new FileInputStream(tmp);) { ++ recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0)); ++ recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0)); ++ recording.start(); + +- int writeByte = 47; +- byte[] writeBuf = {11, 12, 13, 14}; ++ int writeByte = 47; ++ byte[] writeBuf = {11, 12, 13, 14}; + +- // Write +- fos.write(writeByte); +- expectedEvents.add(IOEvent.createFileWriteEvent(1, tmp)); +- fos.write(writeBuf); +- expectedEvents.add(IOEvent.createFileWriteEvent(writeBuf.length, tmp)); +- fos.write(writeBuf, 0, 2); +- expectedEvents.add(IOEvent.createFileWriteEvent(2, tmp)); ++ // Write ++ fos.write(writeByte); ++ expectedEvents.add(IOEvent.createFileWriteEvent(1, tmp)); ++ fos.write(writeBuf); ++ expectedEvents.add(IOEvent.createFileWriteEvent(writeBuf.length, tmp)); ++ fos.write(writeBuf, 0, 2); ++ expectedEvents.add(IOEvent.createFileWriteEvent(2, tmp)); + +- // Read +- int readByte = fis.read(); +- assertEquals(readByte, writeByte, "Wrong byte read"); +- expectedEvents.add(IOEvent.createFileReadEvent(1, tmp)); ++ // Read ++ int readByte = fis.read(); ++ assertEquals(readByte, writeByte, "Wrong byte read"); ++ expectedEvents.add(IOEvent.createFileReadEvent(1, tmp)); + +- byte[] readBuf = new byte[writeBuf.length]; +- long size = fis.read(readBuf); +- assertEquals(size, (long)writeBuf.length, "Wrong size when reading byte[]"); +- expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); ++ byte[] readBuf = new byte[writeBuf.length]; ++ long size = fis.read(readBuf); ++ assertEquals(size, (long)writeBuf.length, "Wrong size when reading byte[]"); ++ expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); + +- size = fis.read(readBuf, 0, 2); +- assertEquals(size, 2L, "Wrong size when reading 2 bytes"); +- expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); ++ size = fis.read(readBuf, 0, 2); ++ assertEquals(size, 2L, "Wrong size when reading 2 bytes"); ++ expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); + +- // We are at EOF. Read more and verify we get size -1. +- size = fis.read(readBuf); +- assertEquals(size, -1L, "Size should be -1 at EOF"); +- expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); ++ // We are at EOF. Read more and verify we get size -1. ++ size = fis.read(readBuf); ++ assertEquals(size, -1L, "Size should be -1 at EOF"); ++ expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); + +- recording.stop(); +- List events = Events.fromRecording(recording); +- IOHelper.verifyEqualsInOrder(events, expectedEvents); ++ recording.stop(); ++ List events = Events.fromRecording(recording); ++ IOHelper.verifyEqualsInOrder(events, expectedEvents); ++ } + } + } + } +diff --git a/jdk/test/jdk/jfr/event/io/TestInstrumentation.java b/jdk/test/jdk/jfr/event/io/TestInstrumentation.java +index d5430e6c6..19fe5a6da 100644 +--- a/jdk/test/jdk/jfr/event/io/TestInstrumentation.java ++++ b/jdk/test/jdk/jfr/event/io/TestInstrumentation.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2020, 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 +@@ -104,11 +104,9 @@ public class TestInstrumentation implements ClassFileTransformer { + "java/io/FileOutputStream::write::([B)V", + "java/io/FileOutputStream::write::([BII)V", + "java/net/SocketInputStream::read::()I", +- "java/net/SocketInputStream::read::([B)I", + "java/net/SocketInputStream::read::([BII)I", + "java/net/SocketInputStream::close::()V", + "java/net/SocketOutputStream::write::(I)V", +- "java/net/SocketOutputStream::write::([B)V", + "java/net/SocketOutputStream::write::([BII)V", + "java/net/SocketOutputStream::close::()V", + "java/nio/channels/FileChannel::read::([Ljava/nio/ByteBuffer;)J", +diff --git a/jdk/test/jdk/jfr/event/io/TestRandomAccessFileEvents.java b/jdk/test/jdk/jfr/event/io/TestRandomAccessFileEvents.java +index 959ed4d22..9c28231c5 100644 +--- a/jdk/test/jdk/jfr/event/io/TestRandomAccessFileEvents.java ++++ b/jdk/test/jdk/jfr/event/io/TestRandomAccessFileEvents.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2020, 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 +@@ -49,62 +49,63 @@ public class TestRandomAccessFileEvents { + public static void main(String[] args) throws Throwable { + File tmp = File.createTempFile("TestRandomAccessFileEvents", ".tmp", new File(".")); + tmp.deleteOnExit(); +- Recording recording = new Recording(); +- List expectedEvents = new ArrayList<>(); +- +- recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0)); +- recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0)); +- recording.start(); +- +- RandomAccessFile ras = new RandomAccessFile(tmp, "rw"); +- int writeInt = 47; +- byte[] writeBuffer = {10,11,12,13}; +- +- // Write an int and a buffer. +- ras.write(writeInt); +- expectedEvents.add(IOEvent.createFileWriteEvent(1, tmp)); +- ras.write(writeBuffer); +- expectedEvents.add(IOEvent.createFileWriteEvent(writeBuffer.length, tmp)); +- +- ras.seek(0); +- +- // Read int and buffer +- int readInt = ras.read(); +- assertEquals(readInt, writeInt, "wrong int read"); +- expectedEvents.add(IOEvent.createFileReadEvent(1, tmp)); +- byte[] readBuffer = new byte [writeBuffer.length]; +- int size = ras.read(readBuffer); +- verifyBufferEquals(readBuffer, writeBuffer); +- expectedEvents.add(IOEvent.createFileReadEvent(readBuffer.length, tmp)); +- +- // Read beyond EOF +- readInt = ras.read(); +- assertEquals(-1, readInt, "wrong read after EOF"); +- expectedEvents.add(IOEvent.createFileReadEvent(-1, tmp)); +- +- // Seek to beginning and verify we can read after EOF. +- ras.seek(0); +- readInt = ras.read(); +- assertEquals(readInt, writeInt, "wrong int read after seek(0)"); +- expectedEvents.add(IOEvent.createFileReadEvent(1, tmp)); +- +- // seek beyond EOF and verify we get EOF when reading. +- ras.seek(10); +- readInt = ras.read(); +- assertEquals(-1, readInt, "wrong read after seek beyond EOF"); +- expectedEvents.add(IOEvent.createFileReadEvent(-1, tmp)); +- +- // Read partial buffer. +- int partialSize = writeBuffer.length - 2; +- ras.seek(ras.length()-partialSize); +- size = ras.read(readBuffer); +- assertEquals(size, partialSize, "Wrong size partial buffer read"); +- expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); +- +- ras.close(); +- recording.stop(); +- List events = Events.fromRecording(recording); +- IOHelper.verifyEqualsInOrder(events, expectedEvents); ++ try (Recording recording = new Recording()) { ++ List expectedEvents = new ArrayList<>(); ++ ++ recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0)); ++ recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0)); ++ recording.start(); ++ ++ RandomAccessFile ras = new RandomAccessFile(tmp, "rw"); ++ int writeInt = 47; ++ byte[] writeBuffer = {10,11,12,13}; ++ ++ // Write an int and a buffer. ++ ras.write(writeInt); ++ expectedEvents.add(IOEvent.createFileWriteEvent(1, tmp)); ++ ras.write(writeBuffer); ++ expectedEvents.add(IOEvent.createFileWriteEvent(writeBuffer.length, tmp)); ++ ++ ras.seek(0); ++ ++ // Read int and buffer ++ int readInt = ras.read(); ++ assertEquals(readInt, writeInt, "wrong int read"); ++ expectedEvents.add(IOEvent.createFileReadEvent(1, tmp)); ++ byte[] readBuffer = new byte [writeBuffer.length]; ++ int size = ras.read(readBuffer); ++ verifyBufferEquals(readBuffer, writeBuffer); ++ expectedEvents.add(IOEvent.createFileReadEvent(readBuffer.length, tmp)); ++ ++ // Read beyond EOF ++ readInt = ras.read(); ++ assertEquals(-1, readInt, "wrong read after EOF"); ++ expectedEvents.add(IOEvent.createFileReadEvent(-1, tmp)); ++ ++ // Seek to beginning and verify we can read after EOF. ++ ras.seek(0); ++ readInt = ras.read(); ++ assertEquals(readInt, writeInt, "wrong int read after seek(0)"); ++ expectedEvents.add(IOEvent.createFileReadEvent(1, tmp)); ++ ++ // seek beyond EOF and verify we get EOF when reading. ++ ras.seek(10); ++ readInt = ras.read(); ++ assertEquals(-1, readInt, "wrong read after seek beyond EOF"); ++ expectedEvents.add(IOEvent.createFileReadEvent(-1, tmp)); ++ ++ // Read partial buffer. ++ int partialSize = writeBuffer.length - 2; ++ ras.seek(ras.length()-partialSize); ++ size = ras.read(readBuffer); ++ assertEquals(size, partialSize, "Wrong size partial buffer read"); ++ expectedEvents.add(IOEvent.createFileReadEvent(size, tmp)); ++ ++ ras.close(); ++ recording.stop(); ++ List events = Events.fromRecording(recording); ++ IOHelper.verifyEqualsInOrder(events, expectedEvents); ++ } + } + + private static void verifyBufferEquals(byte[] a, byte[] b) { +diff --git a/jdk/test/jdk/jfr/event/io/TestRandomAccessFileThread.java b/jdk/test/jdk/jfr/event/io/TestRandomAccessFileThread.java +index b6200fd66..539759c6f 100644 +--- a/jdk/test/jdk/jfr/event/io/TestRandomAccessFileThread.java ++++ b/jdk/test/jdk/jfr/event/io/TestRandomAccessFileThread.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2020, 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 +@@ -64,43 +64,42 @@ public class TestRandomAccessFileThread { + public static void main(String[] args) throws Throwable { + File tmp = File.createTempFile("TestRandomAccessFileThread", ".tmp", new File(".")); + tmp.deleteOnExit(); +- +- Recording recording = new Recording(); +- recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0)); +- recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0)); +- recording.start(); +- +- TestThread writerThread = new TestThread(new XRun() { +- @Override +- public void xrun() throws IOException { +- final byte[] buf = new byte[OP_COUNT]; +- for (int i = 0; i < buf.length; ++i) { +- buf[i] = (byte)((i + 'a') % 255); +- } +- try (RandomAccessFile raf = new RandomAccessFile(tmp, "rwd")) { +- for(int i = 0; i < OP_COUNT; ++i) { +- raf.write(buf, 0, i + 1); +- writeCount++; ++ try (Recording recording = new Recording()) { ++ recording.enable(IOEvent.EVENT_FILE_READ).withThreshold(Duration.ofMillis(0)); ++ recording.enable(IOEvent.EVENT_FILE_WRITE).withThreshold(Duration.ofMillis(0)); ++ recording.start(); ++ ++ TestThread writerThread = new TestThread(new XRun() { ++ @Override ++ public void xrun() throws IOException { ++ final byte[] buf = new byte[OP_COUNT]; ++ for (int i = 0; i < buf.length; ++i) { ++ buf[i] = (byte)((i + 'a') % 255); + } +- } +- }}, "TestWriterThread"); ++ try (RandomAccessFile raf = new RandomAccessFile(tmp, "rwd")) { ++ for(int i = 0; i < OP_COUNT; ++i) { ++ raf.write(buf, 0, i + 1); ++ writeCount++; ++ } ++ } ++ }}, "TestWriterThread"); + + TestThread readerThread = new TestThread(new XRun() { +- @Override +- public void xrun() throws IOException { +- try (RandomAccessFile raf = new RandomAccessFile(tmp, "r")) { +- byte[] buf = new byte[OP_COUNT]; +- for(int i = 0; i < OP_COUNT; ++i) { +- while (writeCount <= i) { +- // No more data to read. Wait for writer thread. +- Thread.yield(); ++ @Override ++ public void xrun() throws IOException { ++ try (RandomAccessFile raf = new RandomAccessFile(tmp, "r")) { ++ byte[] buf = new byte[OP_COUNT]; ++ for(int i = 0; i < OP_COUNT; ++i) { ++ while (writeCount <= i) { ++ // No more data to read. Wait for writer thread. ++ Thread.yield(); ++ } ++ int expectedSize = i + 1; ++ int actualSize = raf.read(buf, 0, expectedSize); ++ Asserts.assertEquals(actualSize, expectedSize, "Wrong read size. Probably test error."); + } +- int expectedSize = i + 1; +- int actualSize = raf.read(buf, 0, expectedSize); +- Asserts.assertEquals(actualSize, expectedSize, "Wrong read size. Probably test error."); + } +- } +- }}, "TestReaderThread"); ++ }}, "TestReaderThread"); + + readerThread.start(); + writerThread.start(); +@@ -118,7 +117,7 @@ public class TestRandomAccessFileThread { + continue; + } + logEventSummary(event); +- if (Events.isEventType(event,IOEvent.EVENT_FILE_READ)) { ++ if (Events.isEventType(event, IOEvent.EVENT_FILE_READ)) { + readEvents.add(event); + } else { + writeEvents.add(event); +@@ -136,91 +135,92 @@ public class TestRandomAccessFileThread { + Asserts.assertEquals(readEvents.size(), OP_COUNT, "Wrong number of read events"); + Asserts.assertEquals(writeEvents.size(), OP_COUNT, "Wrong number of write events"); + } +- +- private static void logEventSummary(RecordedEvent event) { +- boolean isRead = Events.isEventType(event, IOEvent.EVENT_FILE_READ); +- String name = isRead ? "read " : "write"; +- String bytesField = isRead ? "bytesRead" : "bytesWritten"; +- long bytes = Events.assertField(event, bytesField).getValue(); +- long commit = Events.assertField(event, "startTime").getValue(); +- Instant start = event.getStartTime(); +- Instant end = event.getEndTime(); +- System.out.printf("%s: bytes=%d, commit=%d, start=%s, end=%s%n", name, bytes, commit, start, end); +- } +- +- private static void verifyThread(List events, Thread thread) { +- events.stream().forEach(e -> Events.assertEventThread(e, thread)); +- } +- +- private static void verifyBytes(List events, String fieldName) { +- long expectedBytes = 0; +- for (RecordedEvent event : events) { +- Events.assertField(event, fieldName).equal(++expectedBytes); +- } ++ } ++ ++ private static void logEventSummary(RecordedEvent event) { ++ boolean isRead = Events.isEventType(event, IOEvent.EVENT_FILE_READ); ++ String name = isRead ? "read " : "write"; ++ String bytesField = isRead ? "bytesRead" : "bytesWritten"; ++ long bytes = Events.assertField(event, bytesField).getValue(); ++ long commit = Events.assertField(event, "startTime").getValue(); ++ Instant start = event.getStartTime(); ++ Instant end = event.getEndTime(); ++ System.out.printf("%s: bytes=%d, commit=%d, start=%s, end=%s%n", name, bytes, commit, start, end); ++ } ++ ++ private static void verifyThread(List events, Thread thread) { ++ events.stream().forEach(e -> Events.assertEventThread(e, thread)); ++ } ++ ++ private static void verifyBytes(List events, String fieldName) { ++ long expectedBytes = 0; ++ for (RecordedEvent event : events) { ++ Events.assertField(event, fieldName).equal(++expectedBytes); + } +- +- // Verify that all times are increasing +- private static void verifyTimes(List events) { +- RecordedEvent prev = null; +- for (RecordedEvent curr : events) { +- if (prev != null) { +- try { +- Asserts.assertGreaterThanOrEqual(curr.getStartTime(), prev.getStartTime(), "Wrong startTime"); +- Asserts.assertGreaterThanOrEqual(curr.getEndTime(), prev.getEndTime(), "Wrong endTime"); +- long commitPrev = Events.assertField(prev, "startTime").getValue(); +- long commitCurr = Events.assertField(curr, "startTime").getValue(); +- Asserts.assertGreaterThanOrEqual(commitCurr, commitPrev, "Wrong commitTime"); +- } catch (Exception e) { +- System.out.println("Error: " + e.getMessage()); +- System.out.println("Prev Event: " + prev); +- System.out.println("Curr Event: " + curr); +- throw e; +- } ++ } ++ ++ // Verify that all times are increasing ++ private static void verifyTimes(List events) { ++ RecordedEvent prev = null; ++ for (RecordedEvent curr : events) { ++ if (prev != null) { ++ try { ++ Asserts.assertGreaterThanOrEqual(curr.getStartTime(), prev.getStartTime(), "Wrong startTime"); ++ Asserts.assertGreaterThanOrEqual(curr.getEndTime(), prev.getEndTime(), "Wrong endTime"); ++ long commitPrev = Events.assertField(prev, "startTime").getValue(); ++ long commitCurr = Events.assertField(curr, "startTime").getValue(); ++ Asserts.assertGreaterThanOrEqual(commitCurr, commitPrev, "Wrong commitTime"); ++ } catch (Exception e) { ++ System.out.println("Error: " + e.getMessage()); ++ System.out.println("Prev Event: " + prev); ++ System.out.println("Curr Event: " + curr); ++ throw e; + } +- prev = curr; + } ++ prev = curr; + } +- +- // Verify that all times are increasing +- private static void verifyReadWriteTimes(List readEvents, List writeEvents) { +- List events = new ArrayList<>(); +- events.addAll(readEvents); +- events.addAll(writeEvents); +- events.sort(new EventComparator()); +- +- int countRead = 0; +- int countWrite = 0; +- for (RecordedEvent event : events) { +- if (Events.isEventType(event, IOEvent.EVENT_FILE_READ)) { +- ++countRead; +- } else { +- ++countWrite; +- } +- // We can not read from the file before it has been written. +- // This check verifies that times of different threads are correct. +- // Since the read and write are from different threads, it is possible that the read +- // is committed before the same write. +- // But read operation may only be 1 step ahead of the write operation. +- Asserts.assertLessThanOrEqual(countRead, countWrite + 1, "read must be after write"); ++ } ++ ++ // Verify that all times are increasing ++ private static void verifyReadWriteTimes(List readEvents, List writeEvents) { ++ List events = new ArrayList<>(); ++ events.addAll(readEvents); ++ events.addAll(writeEvents); ++ events.sort(new EventComparator()); ++ ++ int countRead = 0; ++ int countWrite = 0; ++ for (RecordedEvent event : events) { ++ if (Events.isEventType(event, IOEvent.EVENT_FILE_READ)) { ++ ++countRead; ++ } else { ++ ++countWrite; + } ++ // We can not read from the file before it has been written. ++ // This check verifies that times of different threads are correct. ++ // Since the read and write are from different threads, it is possible that the read ++ // is committed before the same write. ++ // But read operation may only be 1 step ahead of the write operation. ++ Asserts.assertLessThanOrEqual(countRead, countWrite + 1, "read must be after write"); + } ++ } + +- private static boolean isOurEvent(RecordedEvent event, File file) { +- if (!Events.isEventType(event, IOEvent.EVENT_FILE_READ) && +- !Events.isEventType(event, IOEvent.EVENT_FILE_WRITE)) { +- return false; +- } +- String path = Events.assertField(event, "path").getValue(); +- return file.getPath().equals(path); ++ private static boolean isOurEvent(RecordedEvent event, File file) { ++ if (!Events.isEventType(event, IOEvent.EVENT_FILE_READ) && ++ !Events.isEventType(event, IOEvent.EVENT_FILE_WRITE)) { ++ return false; + } +- +- private static class EventComparator implements Comparator { +- @Override +- public int compare(RecordedEvent a, RecordedEvent b) { +- long commitA = Events.assertField(a, "startTime").getValue(); +- long commitB = Events.assertField(b, "startTime").getValue(); +- return Long.compare(commitA, commitB); +- } ++ String path = Events.assertField(event, "path").getValue(); ++ return file.getPath().equals(path); ++ } ++ ++ private static class EventComparator implements Comparator { ++ @Override ++ public int compare(RecordedEvent a, RecordedEvent b) { ++ long commitA = Events.assertField(a, "startTime").getValue(); ++ long commitB = Events.assertField(b, "startTime").getValue(); ++ return Long.compare(commitA, commitB); + } ++ } + + } +diff --git a/jdk/test/jdk/jfr/event/io/TestSocketChannelEvents.java b/jdk/test/jdk/jfr/event/io/TestSocketChannelEvents.java +index dbd43adbf..23b692a31 100644 +--- a/jdk/test/jdk/jfr/event/io/TestSocketChannelEvents.java ++++ b/jdk/test/jdk/jfr/event/io/TestSocketChannelEvents.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2020, 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 +@@ -53,6 +53,7 @@ public class TestSocketChannelEvents { + private static final int bufSizeB = 20; + + private List expectedEvents = new ArrayList<>(); ++ + private synchronized void addExpectedEvent(IOEvent event) { + expectedEvents.add(event); + } +@@ -62,69 +63,70 @@ public class TestSocketChannelEvents { + } + + public void test() throws Throwable { +- Recording recording = new Recording(); +- +- try (ServerSocketChannel ss = ServerSocketChannel.open()) { +- recording.enable(IOEvent.EVENT_SOCKET_READ).withThreshold(Duration.ofMillis(0)); +- recording.enable(IOEvent.EVENT_SOCKET_WRITE).withThreshold(Duration.ofMillis(0)); +- recording.start(); +- +- ss.socket().setReuseAddress(true); +- ss.socket().bind(null); +- +- TestThread readerThread = new TestThread(new XRun() { +- @Override +- public void xrun() throws IOException { +- ByteBuffer bufA = ByteBuffer.allocate(bufSizeA); +- ByteBuffer bufB = ByteBuffer.allocate(bufSizeB); +- try (SocketChannel sc = ss.accept()) { +- int readSize = sc.read(bufA); +- assertEquals(readSize, bufSizeA, "Wrong readSize bufA"); +- addExpectedEvent(IOEvent.createSocketReadEvent(bufSizeA, sc.socket())); +- +- bufA.clear(); +- bufA.limit(1); +- readSize = (int)sc.read(new ByteBuffer[] { bufA, bufB }); +- assertEquals(readSize, 1 + bufSizeB, "Wrong readSize 1+bufB"); +- addExpectedEvent(IOEvent.createSocketReadEvent(readSize, sc.socket())); +- +- // We try to read, but client have closed. Should get EOF. +- bufA.clear(); +- bufA.limit(1); +- readSize = sc.read(bufA); +- assertEquals(readSize, -1, "Wrong readSize at EOF"); +- addExpectedEvent(IOEvent.createSocketReadEvent(-1, sc.socket())); ++ try (Recording recording = new Recording()) { ++ try (ServerSocketChannel ss = ServerSocketChannel.open()) { ++ recording.enable(IOEvent.EVENT_SOCKET_READ).withThreshold(Duration.ofMillis(0)); ++ recording.enable(IOEvent.EVENT_SOCKET_WRITE).withThreshold(Duration.ofMillis(0)); ++ recording.start(); ++ ++ ss.socket().setReuseAddress(true); ++ ss.socket().bind(null); ++ ++ TestThread readerThread = new TestThread(new XRun() { ++ @Override ++ public void xrun() throws IOException { ++ ByteBuffer bufA = ByteBuffer.allocate(bufSizeA); ++ ByteBuffer bufB = ByteBuffer.allocate(bufSizeB); ++ try (SocketChannel sc = ss.accept()) { ++ int readSize = sc.read(bufA); ++ assertEquals(readSize, bufSizeA, "Wrong readSize bufA"); ++ addExpectedEvent(IOEvent.createSocketReadEvent(bufSizeA, sc.socket())); ++ ++ bufA.clear(); ++ bufA.limit(1); ++ readSize = (int) sc.read(new ByteBuffer[] { bufA, bufB }); ++ assertEquals(readSize, 1 + bufSizeB, "Wrong readSize 1+bufB"); ++ addExpectedEvent(IOEvent.createSocketReadEvent(readSize, sc.socket())); ++ ++ // We try to read, but client have closed. Should ++ // get EOF. ++ bufA.clear(); ++ bufA.limit(1); ++ readSize = sc.read(bufA); ++ assertEquals(readSize, -1, "Wrong readSize at EOF"); ++ addExpectedEvent(IOEvent.createSocketReadEvent(-1, sc.socket())); ++ } + } +- } +- }); +- readerThread.start(); +- +- try (SocketChannel sc = SocketChannel.open(ss.socket().getLocalSocketAddress())) { +- ByteBuffer bufA = ByteBuffer.allocateDirect(bufSizeA); +- ByteBuffer bufB = ByteBuffer.allocateDirect(bufSizeB); +- for (int i = 0; i < bufSizeA; ++i) { +- bufA.put((byte)('a' + (i % 20))); +- } +- for (int i = 0; i < bufSizeB; ++i) { +- bufB.put((byte)('A' + (i % 20))); +- } +- bufA.flip(); +- bufB.flip(); ++ }); ++ readerThread.start(); ++ ++ try (SocketChannel sc = SocketChannel.open(ss.socket().getLocalSocketAddress())) { ++ ByteBuffer bufA = ByteBuffer.allocateDirect(bufSizeA); ++ ByteBuffer bufB = ByteBuffer.allocateDirect(bufSizeB); ++ for (int i = 0; i < bufSizeA; ++i) { ++ bufA.put((byte) ('a' + (i % 20))); ++ } ++ for (int i = 0; i < bufSizeB; ++i) { ++ bufB.put((byte) ('A' + (i % 20))); ++ } ++ bufA.flip(); ++ bufB.flip(); + +- sc.write(bufA); +- addExpectedEvent(IOEvent.createSocketWriteEvent(bufSizeA, sc.socket())); ++ sc.write(bufA); ++ addExpectedEvent(IOEvent.createSocketWriteEvent(bufSizeA, sc.socket())); + +- bufA.clear(); +- bufA.limit(1); +- int bytesWritten = (int)sc.write(new ByteBuffer[] { bufA, bufB }); +- assertEquals(bytesWritten, 1 + bufSizeB, "Wrong bytesWritten 1+bufB"); +- addExpectedEvent(IOEvent.createSocketWriteEvent(bytesWritten, sc.socket())); +- } ++ bufA.clear(); ++ bufA.limit(1); ++ int bytesWritten = (int) sc.write(new ByteBuffer[] { bufA, bufB }); ++ assertEquals(bytesWritten, 1 + bufSizeB, "Wrong bytesWritten 1+bufB"); ++ addExpectedEvent(IOEvent.createSocketWriteEvent(bytesWritten, sc.socket())); ++ } + +- readerThread.joinAndThrow(); +- recording.stop(); +- List events= Events.fromRecording(recording); +- IOHelper.verifyEquals(events, expectedEvents); ++ readerThread.joinAndThrow(); ++ recording.stop(); ++ List events = Events.fromRecording(recording); ++ IOHelper.verifyEquals(events, expectedEvents); ++ } + } + } + } +diff --git a/jdk/test/jdk/jfr/event/io/TestSocketEvents.java b/jdk/test/jdk/jfr/event/io/TestSocketEvents.java +index c0b64aa7d..5b544cc7e 100644 +--- a/jdk/test/jdk/jfr/event/io/TestSocketEvents.java ++++ b/jdk/test/jdk/jfr/event/io/TestSocketEvents.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2020, 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 +@@ -55,6 +55,7 @@ public class TestSocketEvents { + private static final byte[] writeBuf = { 'B', 'C', 'D', 'E' }; + + private List expectedEvents = new ArrayList<>(); ++ + private synchronized void addExpectedEvent(IOEvent event) { + expectedEvents.add(event); + } +@@ -64,58 +65,59 @@ public class TestSocketEvents { + } + + private void test() throws Throwable { +- Recording recording = new Recording(); +- +- try (ServerSocket ss = new ServerSocket()) { +- recording.enable(IOEvent.EVENT_SOCKET_READ).withThreshold(Duration.ofMillis(0)); +- recording.enable(IOEvent.EVENT_SOCKET_WRITE).withThreshold(Duration.ofMillis(0)); +- recording.start(); +- +- ss.setReuseAddress(true); +- ss.bind(null); +- +- TestThread readerThread = new TestThread(new XRun() { +- @Override +- public void xrun() throws IOException { +- byte[] bs = new byte[4]; +- try (Socket s = ss.accept(); InputStream is = s.getInputStream()) { +- int readInt = is.read(); +- assertEquals(readInt, writeInt, "Wrong readInt"); +- addExpectedEvent(IOEvent.createSocketReadEvent(1, s)); +- +- int bytesRead = is.read(bs, 0, 3); +- assertEquals(bytesRead, 3, "Wrong bytesRead partial buffer"); +- addExpectedEvent(IOEvent.createSocketReadEvent(bytesRead, s)); +- +- bytesRead = is.read(bs); +- assertEquals(bytesRead, writeBuf.length, "Wrong bytesRead full buffer"); +- addExpectedEvent(IOEvent.createSocketReadEvent(bytesRead, s)); +- +- // Try to read more, but writer have closed. Should get EOF. +- readInt = is.read(); +- assertEquals(readInt, -1, "Wrong readInt at EOF"); +- addExpectedEvent(IOEvent.createSocketReadEvent(-1, s)); +- } +- } +- }); +- readerThread.start(); +- +- try (Socket s = new Socket()) { +- s.connect(ss.getLocalSocketAddress()); +- try (OutputStream os = s.getOutputStream()) { +- os.write(writeInt); +- addExpectedEvent(IOEvent.createSocketWriteEvent(1, s)); +- os.write(writeBuf, 0, 3); +- addExpectedEvent(IOEvent.createSocketWriteEvent(3, s)); +- os.write(writeBuf); +- addExpectedEvent(IOEvent.createSocketWriteEvent(writeBuf.length, s)); ++ try (Recording recording = new Recording()) { ++ try (ServerSocket ss = new ServerSocket()) { ++ recording.enable(IOEvent.EVENT_SOCKET_READ).withThreshold(Duration.ofMillis(0)); ++ recording.enable(IOEvent.EVENT_SOCKET_WRITE).withThreshold(Duration.ofMillis(0)); ++ recording.start(); ++ ++ ss.setReuseAddress(true); ++ ss.bind(null); ++ ++ TestThread readerThread = new TestThread(new XRun() { ++ @Override ++ public void xrun() throws IOException { ++ byte[] bs = new byte[4]; ++ try (Socket s = ss.accept(); InputStream is = s.getInputStream()) { ++ int readInt = is.read(); ++ assertEquals(readInt, writeInt, "Wrong readInt"); ++ addExpectedEvent(IOEvent.createSocketReadEvent(1, s)); ++ ++ int bytesRead = is.read(bs, 0, 3); ++ assertEquals(bytesRead, 3, "Wrong bytesRead partial buffer"); ++ addExpectedEvent(IOEvent.createSocketReadEvent(bytesRead, s)); ++ ++ bytesRead = is.read(bs); ++ assertEquals(bytesRead, writeBuf.length, "Wrong bytesRead full buffer"); ++ addExpectedEvent(IOEvent.createSocketReadEvent(bytesRead, s)); ++ ++ // Try to read more, but writer have closed. Should ++ // get EOF. ++ readInt = is.read(); ++ assertEquals(readInt, -1, "Wrong readInt at EOF"); ++ addExpectedEvent(IOEvent.createSocketReadEvent(-1, s)); ++ } ++ } ++ }); ++ readerThread.start(); ++ ++ try (Socket s = new Socket()) { ++ s.connect(ss.getLocalSocketAddress()); ++ try (OutputStream os = s.getOutputStream()) { ++ os.write(writeInt); ++ addExpectedEvent(IOEvent.createSocketWriteEvent(1, s)); ++ os.write(writeBuf, 0, 3); ++ addExpectedEvent(IOEvent.createSocketWriteEvent(3, s)); ++ os.write(writeBuf); ++ addExpectedEvent(IOEvent.createSocketWriteEvent(writeBuf.length, s)); ++ } + } +- } + +- readerThread.joinAndThrow(); +- recording.stop(); +- List events = Events.fromRecording(recording); +- IOHelper.verifyEquals(events, expectedEvents); ++ readerThread.joinAndThrow(); ++ recording.stop(); ++ List events = Events.fromRecording(recording); ++ IOHelper.verifyEquals(events, expectedEvents); ++ } + } + } + } +-- +2.22.0 + diff --git a/8268453-sun-security-pkcs12-EmptyPassword.java-fails.patch b/8268453-sun-security-pkcs12-EmptyPassword.java-fails.patch new file mode 100755 index 0000000000000000000000000000000000000000..c82424f44c766afff8b59350798bd7c7d54f2c50 --- /dev/null +++ b/8268453-sun-security-pkcs12-EmptyPassword.java-fails.patch @@ -0,0 +1,232 @@ +From d58382eb0c18949cd04b76c12c556e6f11036573 Mon Sep 17 00:00:00 2001 +From: miaozhuojun +Date: Sat, 11 Sep 2021 11:35:19 +0800 +Subject: [PATCH 14/23] 8268453: sun/security/pkcs12/EmptyPassword.java fails + with Sequence tag error + +Summary: < JDK> : 8268453: sun/security/pkcs12/EmptyPassword.java fails with Sequence tag error +LLT: ./jdk8u/jdk/test/sun/security/pkcs12/EmptyPassword.java +Patch Type: backport +Bug url: https://bugs.openjdk.java.net/browse/JDK-8268453 +--- + .../sun/security/pkcs12/PKCS12KeyStore.java | 125 +++++++++--------- + 1 file changed, 64 insertions(+), 61 deletions(-) + +diff --git a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +index cdd01d6ab..ea3d61f30 100644 +--- a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java ++++ b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java +@@ -286,6 +286,9 @@ public final class PKCS12KeyStore extends KeyStoreSpi { + } catch (Exception e) { + if (password.length == 0) { + // Retry using an empty password with a NUL terminator. ++ if (debug != null) { ++ debug.println("Retry with a NUL password"); ++ } + return f.tryOnce(new char[1]); + } + throw e; +@@ -366,7 +369,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { + + try { + PBEParameterSpec pbeSpec; +- int ic = 0; ++ int ic; + + if (algParams != null) { + try { +@@ -380,68 +383,72 @@ public final class PKCS12KeyStore extends KeyStoreSpi { + if (ic > MAX_ITERATION_COUNT) { + throw new IOException("PBE iteration count too large"); + } ++ } else { ++ ic = 0; + } + +- byte[] keyInfo = RetryWithZero.run(pass -> { ++ key = RetryWithZero.run(pass -> { + // Use JCE + SecretKey skey = getPBEKey(pass); + Cipher cipher = Cipher.getInstance( + mapPBEParamsToAlgorithm(algOid, algParams)); + cipher.init(Cipher.DECRYPT_MODE, skey, algParams); +- return cipher.doFinal(encryptedKey); +- }, password); +- +- /* +- * Parse the key algorithm and then use a JCA key factory +- * to re-create the key. +- */ +- DerValue val = new DerValue(keyInfo); +- DerInputStream in = val.toDerInputStream(); +- int i = in.getInteger(); +- DerValue[] value = in.getSequence(2); +- if (value.length < 1 || value.length > 2) { +- throw new IOException("Invalid length for AlgorithmIdentifier"); +- } +- AlgorithmId algId = new AlgorithmId(value[0].getOID()); +- String keyAlgo = algId.getName(); +- +- // decode private key +- if (entry instanceof PrivateKeyEntry) { +- KeyFactory kfac = KeyFactory.getInstance(keyAlgo); +- PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(keyInfo); +- key = kfac.generatePrivate(kspec); +- +- if (debug != null) { +- debug.println("Retrieved a protected private key at alias" + +- " '" + alias + "' (" + +- new AlgorithmId(algOid).getName() + +- " iterations: " + ic + ")"); ++ byte[] keyInfo = cipher.doFinal(encryptedKey); ++ /* ++ * Parse the key algorithm and then use a JCA key factory ++ * to re-create the key. ++ */ ++ DerValue val = new DerValue(keyInfo); ++ DerInputStream in = val.toDerInputStream(); ++ int i = in.getInteger(); ++ DerValue[] value = in.getSequence(2); ++ if (value.length < 1 || value.length > 2) { ++ throw new IOException("Invalid length for AlgorithmIdentifier"); + } ++ AlgorithmId algId = new AlgorithmId(value[0].getOID()); ++ String keyAlgo = algId.getName(); + +- // decode secret key +- } else { +- byte[] keyBytes = in.getOctetString(); +- SecretKeySpec secretKeySpec = +- new SecretKeySpec(keyBytes, keyAlgo); +- +- // Special handling required for PBE: needs a PBEKeySpec +- if (keyAlgo.startsWith("PBE")) { +- SecretKeyFactory sKeyFactory = +- SecretKeyFactory.getInstance(keyAlgo); +- KeySpec pbeKeySpec = +- sKeyFactory.getKeySpec(secretKeySpec, PBEKeySpec.class); +- key = sKeyFactory.generateSecret(pbeKeySpec); ++ // decode private key ++ if (entry instanceof PrivateKeyEntry) { ++ KeyFactory kfac = KeyFactory.getInstance(keyAlgo); ++ PKCS8EncodedKeySpec kspec = new PKCS8EncodedKeySpec(keyInfo); ++ Key tmp = kfac.generatePrivate(kspec); ++ ++ if (debug != null) { ++ debug.println("Retrieved a protected private key at alias" + ++ " '" + alias + "' (" + ++ new AlgorithmId(algOid).getName() + ++ " iterations: " + ic + ")"); ++ } ++ return tmp; ++ // decode secret key + } else { +- key = secretKeySpec; +- } ++ byte[] keyBytes = in.getOctetString(); ++ SecretKeySpec secretKeySpec = ++ new SecretKeySpec(keyBytes, keyAlgo); ++ ++ // Special handling required for PBE: needs a PBEKeySpec ++ Key tmp; ++ if (keyAlgo.startsWith("PBE")) { ++ SecretKeyFactory sKeyFactory = ++ SecretKeyFactory.getInstance(keyAlgo); ++ KeySpec pbeKeySpec = ++ sKeyFactory.getKeySpec(secretKeySpec, PBEKeySpec.class); ++ tmp = sKeyFactory.generateSecret(pbeKeySpec); ++ } else { ++ tmp = secretKeySpec; ++ } + +- if (debug != null) { +- debug.println("Retrieved a protected secret key at alias " + +- "'" + alias + "' (" + +- new AlgorithmId(algOid).getName() + +- " iterations: " + ic + ")"); ++ if (debug != null) { ++ debug.println("Retrieved a protected secret key at alias " + ++ "'" + alias + "' (" + ++ new AlgorithmId(algOid).getName() + ++ " iterations: " + ic + ")"); ++ } ++ return tmp; + } +- } ++ }, password); ++ + } catch (Exception e) { + UnrecoverableKeyException uke = + new UnrecoverableKeyException("Get Key failed: " + +@@ -1984,7 +1991,6 @@ public final class PKCS12KeyStore extends KeyStoreSpi { + * Spin over the ContentInfos. + */ + for (int i = 0; i < count; i++) { +- byte[] safeContentsData; + ContentInfo safeContents; + DerInputStream sci; + byte[] eAlgId = null; +@@ -1992,14 +1998,13 @@ public final class PKCS12KeyStore extends KeyStoreSpi { + sci = new DerInputStream(safeContentsArray[i].toByteArray()); + safeContents = new ContentInfo(sci); + contentType = safeContents.getContentType(); +- safeContentsData = null; + if (contentType.equals((Object)ContentInfo.DATA_OID)) { + + if (debug != null) { + debug.println("Loading PKCS#7 data"); + } + +- safeContentsData = safeContents.getData(); ++ loadSafeContents(new DerInputStream(safeContents.getData())); + } else if (contentType.equals((Object)ContentInfo.ENCRYPTED_DATA_OID)) { + if (password == null) { + +@@ -2029,7 +2034,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { + if (seq[2].isConstructed()) + newTag |= 0x20; + seq[2].resetTag(newTag); +- safeContentsData = seq[2].getOctetString(); ++ byte[] rawData = seq[2].getOctetString(); + + // parse Algorithm parameters + DerInputStream in = seq[1].toDerInputStream(); +@@ -2060,14 +2065,14 @@ public final class PKCS12KeyStore extends KeyStoreSpi { + " iterations: " + ic + ")"); + } + +- byte[] rawData = safeContentsData; + try { +- safeContentsData = RetryWithZero.run(pass -> { ++ RetryWithZero.run(pass -> { + // Use JCE + SecretKey skey = getPBEKey(pass); + Cipher cipher = Cipher.getInstance(algOid.toString()); + cipher.init(Cipher.DECRYPT_MODE, skey, algParams); +- return cipher.doFinal(rawData); ++ loadSafeContents(new DerInputStream(cipher.doFinal(rawData))); ++ return null; + }, password); + } catch (Exception e) { + throw new IOException("keystore password was incorrect", +@@ -2078,8 +2083,6 @@ public final class PKCS12KeyStore extends KeyStoreSpi { + throw new IOException("public key protected PKCS12" + + " not supported"); + } +- DerInputStream sc = new DerInputStream(safeContentsData); +- loadSafeContents(sc, password); + } + + // The MacData is optional. +@@ -2204,7 +2207,7 @@ public final class PKCS12KeyStore extends KeyStoreSpi { + else return null; + } + +- private void loadSafeContents(DerInputStream stream, char[] password) ++ private void loadSafeContents(DerInputStream stream) + throws IOException, NoSuchAlgorithmException, CertificateException + { + DerValue[] safeBags = stream.getSequence(2); +-- +2.22.0 + diff --git a/C1-assert-is_virtual-failed-type-check.patch b/C1-assert-is_virtual-failed-type-check.patch new file mode 100755 index 0000000000000000000000000000000000000000..1911a1ebf1ce2751262c813df8f58e519c96fe14 --- /dev/null +++ b/C1-assert-is_virtual-failed-type-check.patch @@ -0,0 +1,110 @@ +From b14ebd1d4a12023d8dac06d44556b3559a10d76d Mon Sep 17 00:00:00 2001 +From: wangkun +Date: Mon, 30 Aug 2021 19:44:38 +0800 +Subject: [PATCH 11/23] 8255058: C1 assert(is_virtual()) failed: type check + +Summary: < C1> : 8255058 C1 assert(is_virtual()) failed: type check +LLT: hotspot/test/compiler/c1/TestPinnedConstantExceptionEdge.java +Patch Type: backport +Bug url: https://bugs.openjdk.java.net/browse/JDK-8255058 +--- + hotspot/src/share/vm/c1/c1_LinearScan.cpp | 4 +- + .../c1/TestPinnedConstantExceptionEdge.java | 71 +++++++++++++++++++ + 2 files changed, 73 insertions(+), 2 deletions(-) + create mode 100644 hotspot/test/compiler/c1/TestPinnedConstantExceptionEdge.java + +diff --git a/hotspot/src/share/vm/c1/c1_LinearScan.cpp b/hotspot/src/share/vm/c1/c1_LinearScan.cpp +index 1f6281bf2..ec4a67eda 100644 +--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp ++++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp +@@ -1915,8 +1915,8 @@ void LinearScan::resolve_exception_edge(XHandler* handler, int throwing_op_id, i + move_resolver.set_multiple_reads_allowed(); + + Constant* con = from_value->as_Constant(); +- if (con != NULL && !con->is_pinned()) { +- // unpinned constants may have no register, so add mapping from constant to interval ++ if (con != NULL && (!con->is_pinned() || con->operand()->is_constant())) { ++ // Need a mapping from constant to interval if unpinned (may have no register) or if the operand is a constant (no register). + move_resolver.add_mapping(LIR_OprFact::value_type(con->type()), to_interval); + } else { + // search split child at the throwing op_id +diff --git a/hotspot/test/compiler/c1/TestPinnedConstantExceptionEdge.java b/hotspot/test/compiler/c1/TestPinnedConstantExceptionEdge.java +new file mode 100644 +index 000000000..18f145eb7 +--- /dev/null ++++ b/hotspot/test/compiler/c1/TestPinnedConstantExceptionEdge.java +@@ -0,0 +1,71 @@ ++/* ++ * Copyright (c) 2020, 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. ++ */ ++ ++/* ++ * @test ++ * @bug 8255058 ++ * @summary Add check in LinearScan::resolve_exception_edge for pinned constant that is not virtual which cannot be used to find an interval which ++ resulted in an assertion error. ++ * @run main/othervm -Xcomp -XX:TieredStopAtLevel=1 -XX:CompileCommand=dontinline,compiler.c1.TestPinnedConstantExceptionEdge::dontInline ++ * -XX:CompileCommand=compileonly,compiler.c1.TestPinnedConstantExceptionEdge::* compiler.c1.TestPinnedConstantExceptionEdge ++ */ ++package compiler.c1; ++ ++public class TestPinnedConstantExceptionEdge { ++ ++ public static long iFld = 0; ++ public static boolean b1; ++ public static boolean b2; ++ ++ public static void test() { ++ int x = 5; ++ int y = 11; ++ for (int i = 1; i < 8; i++) { ++ for (int j = 1; j < 2; ++j) { ++ if (b1) { ++ try { ++ y = (x / x); ++ y = (500 / i); ++ y = (-214 / i); ++ } catch (ArithmeticException a_e) {} ++ // Recursion too deep in UseCountComputer::uses_do and therefore constant 1 is pinned. ++ iFld += (b1 ? 1 : 0) + (b2 ? 1 : 0) + 5 + 7 + 6 + 5 + y ++ + dontInline(7) + dontInline(5) + 8 + 8 + 9 ++ + dontInline(3) + dontInline(3) + dontInline(4) ++ + dontInline(dontInline(5)) + dontInline(2); ++ return; ++ } ++ } ++ } ++ } ++ ++ // Not inlined ++ public static int dontInline(int a) { ++ return 0; ++ } ++ ++ public static void main(String[] strArr) { ++ test(); ++ } ++} ++ +-- +2.22.0 + diff --git a/G1Uncommit-Introduce-G1PeriodGCNotRetry-control-whet.patch b/G1Uncommit-Introduce-G1PeriodGCNotRetry-control-whet.patch new file mode 100755 index 0000000000000000000000000000000000000000..dd1f12b79423a0dc72dc89c4094c05af2b4c0d5e --- /dev/null +++ b/G1Uncommit-Introduce-G1PeriodGCNotRetry-control-whet.patch @@ -0,0 +1,49 @@ +From f061aeed6337ea1a5fdfe9b05c0eee4b26d6b26b Mon Sep 17 00:00:00 2001 +From: mashoubing +Date: Thu, 16 Sep 2021 14:28:41 +0800 +Subject: [PATCH 22/23] G1Uncommit: Introduce G1PeriodGCNotRetry control + whether periodic GC retry again when denied + +Summary:gc:periodic gc spin in retry gc +LLT: NA +Patch Type: huawei +Bug url: +--- + .../src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp | 6 ++++++ + hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp | 3 +++ + 2 files changed, 9 insertions(+) + +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +index 8ed6207ad..4f45bba52 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +@@ -2577,6 +2577,12 @@ void G1CollectedHeap::collect(GCCause::Cause cause) { + } + + if (retry_gc) { ++ if (cause == GCCause::_g1_periodic_collection && G1PeriodGCNotRetry) { ++ gclog_or_tty->date_stamp(PrintGCDateStamps); ++ gclog_or_tty->stamp(PrintGCTimeStamps); ++ gclog_or_tty->print_cr("Periodic GC is denied and not try !"); ++ return; ++ } + if (GC_locker::is_active_and_needs_gc()) { + GC_locker::stall_until_clear(); + } +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +index ee7f14278..edac4d72c 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +@@ -333,6 +333,9 @@ + product(bool, G1Uncommit, false, \ + "Allow G1 to uncommit unused memory.") \ + \ ++ product(bool, G1PeriodGCNotRetry, true, \ ++ "Not allow denied G1 Periodic GC try again.") \ ++ \ + product(bool, G1UncommitLog, false, \ + "Enable G1 uncommit logs.") \ + \ +-- +2.22.0 + diff --git a/JDK-debug-version-crash-when-using-AppCDS.patch b/JDK-debug-version-crash-when-using-AppCDS.patch new file mode 100755 index 0000000000000000000000000000000000000000..32d8511c8b0e9445bafc211f43a56560e1574cbb --- /dev/null +++ b/JDK-debug-version-crash-when-using-AppCDS.patch @@ -0,0 +1,546 @@ +From 63cadc56420c73719e7a08587984bf5d96d3b063 Mon Sep 17 00:00:00 2001 +From: miaozhuojun +Date: Sat, 11 Sep 2021 14:48:00 +0800 +Subject: [PATCH 23/23] JDK debug version crash when using AppCDS + +Summary: : JDK debug version crash when using AppCDS +LLT: ./jdk8u-dev/hotspot/test/runtime/NMT/NMTWithCDS.java +Patch Type: huawei +Bug url: NA +--- + .../vm/interpreterGenerator_aarch64.hpp | 2 - + .../vm/templateInterpreter_aarch64.cpp | 144 +++++++++--------- + .../vm/templateInterpreter_aarch64.hpp | 72 +++++++++ + .../share/vm/interpreter/cppInterpreter.cpp | 13 +- + .../share/vm/interpreter/cppInterpreter.hpp | 3 +- + .../src/share/vm/interpreter/interpreter.cpp | 19 +-- + .../vm/interpreter/templateInterpreter.cpp | 14 +- + .../vm/interpreter/templateInterpreter.hpp | 3 +- + hotspot/src/share/vm/memory/universe.cpp | 8 + + hotspot/src/share/vm/runtime/init.cpp | 6 +- + 10 files changed, 165 insertions(+), 119 deletions(-) + +diff --git a/hotspot/src/cpu/aarch64/vm/interpreterGenerator_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/interpreterGenerator_aarch64.hpp +index a275a6a99..40af38a79 100644 +--- a/hotspot/src/cpu/aarch64/vm/interpreterGenerator_aarch64.hpp ++++ b/hotspot/src/cpu/aarch64/vm/interpreterGenerator_aarch64.hpp +@@ -50,8 +50,6 @@ void generate_transcendental_entry(AbstractInterpreter::MethodKind kind, int fpa + address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind); + void lock_method(void); + void generate_stack_overflow_check(void); +- void load_String_value(Register src, Register dst); +- void load_String_offset(Register src, Register dst); + void emit_array_address(Register src, Register idx, Register dst, BasicType type); + address generate_Dgemm_dgemm_entry(); + address generate_Dgemv_dgemv_entry(); +diff --git a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp +index b5f56fd03..f356fbf81 100644 +--- a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp ++++ b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp +@@ -849,27 +849,6 @@ address InterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpret + return generate_native_entry(false); + } + +-// Access the char-array of String +-void InterpreterGenerator::load_String_value(Register src, Register dst) { +- // Need to cooperate with JDK-8243996 +- int value_offset = java_lang_String::value_offset_in_bytes(); +- +- __ add(src, src, value_offset); +- __ load_heap_oop(dst, Address(src)); +-} +- +-void InterpreterGenerator::load_String_offset(Register src, Register dst) { +- __ mov(dst, 0); +- +- // Get String value offset, because of order of initialization for Interpreter, +- // we have to hardcode the offset for String value. (JDK-8243996) +- if (java_lang_String::has_offset_field()) { +- int offset_offset = java_lang_String::offset_offset_in_bytes(); +- __ add(src, src, offset_offset); +- __ ldrw(dst, Address(src)); +- } +-} +- + void InterpreterGenerator::emit_array_address(Register src, Register idx, + Register dst, BasicType type) { + int offset_in_bytes = arrayOopDesc::base_offset_in_bytes(type); +@@ -900,7 +879,7 @@ void InterpreterGenerator::emit_array_address(Register src, Register idx, + * + */ + address InterpreterGenerator::generate_Dgemm_dgemm_entry() { +- if (!UseF2jBLASIntrinsics || (StubRoutines::dgemmDgemm() == NULL)) return NULL; ++ if (StubRoutines::dgemmDgemm() == NULL) return NULL; + + address entry = __ pc(); + +@@ -917,19 +896,29 @@ address InterpreterGenerator::generate_Dgemm_dgemm_entry() { + const Register lda = c_rarg6; + const Register B = c_rarg7; + const FloatRegister beta = c_farg1; +- const Register tmp1 = rscratch1; +- const Register tmp2 = rscratch2; +- +- // trana +- __ ldr(ta, Address(esp, 17 * wordSize)); +- load_String_value(ta, tmp1); +- load_String_offset(ta, tmp2); +- emit_array_address(tmp1, tmp2, ta, T_CHAR); +- // tranb +- __ ldr(tb, Address(esp, 16 * wordSize)); +- load_String_value(tb, tmp1); +- load_String_offset(tb, tmp2); +- emit_array_address(tmp1, tmp2, tb, T_CHAR); ++ ++ // trana/tranb ++ __ ldr(r0, Address(esp, 17 * wordSize)); ++ __ ldr(r1, Address(esp, 16 * wordSize)); ++ ++ // Get String value offset, because of order of initialization for Interpreter, ++ // we have to hardcode the offset for String value and offset. These instructions ++ // generated there will be patched in interpreter_patch after java.lang.String has ++ // been loaded. ++ // load String offset ++ __ mov(r2, 0); // __ ldrw(r2, Address(r0, java_lang_String::offset_offset_in_bytes())) ++ __ mov(r3, 0); // __ ldrw(r3, Address(r1, java_lang_String::offset_offset_in_bytes())) ++ ++ // load String value ++ __ mov(r4, 0xc); // __ mov(r4, java_lang_String::value_offset_in_bytes()) ++ __ add(r0, r0, r4); ++ __ load_heap_oop(r0, Address(r0)); ++ __ add(r1, r1, r4); ++ __ load_heap_oop(r1, Address(r1)); ++ ++ emit_array_address(r0, r2, ta, T_CHAR); ++ emit_array_address(r1, r3, tb, T_CHAR); ++ + // m, n, k + __ ldrw(m, Address(esp, 15 * wordSize)); + __ ldrw(n, Address(esp, 14 * wordSize)); +@@ -937,16 +926,15 @@ address InterpreterGenerator::generate_Dgemm_dgemm_entry() { + // alpha + __ ldrd(alpha, Address(esp, 11 * wordSize)); + // A +- __ ldr(tmp1, Address(esp, 10 * wordSize)); +- __ mov(tmp2, 0); +- __ ldrw(tmp2, Address(esp, 9 * wordSize)); +- emit_array_address(tmp1, tmp2, A, T_DOUBLE); ++ __ ldr(r5, Address(esp, 10 * wordSize)); ++ __ ldrw(r6, Address(esp, 9 * wordSize)); ++ emit_array_address(r5, r6, A, T_DOUBLE); + // lda + __ ldrw(lda, Address(esp, 8 * wordSize)); + // B +- __ ldr(tmp1, Address(esp, 7 * wordSize)); +- __ ldrw(tmp2, Address(esp, 6 * wordSize)); +- emit_array_address(tmp1, tmp2, B, T_DOUBLE); ++ __ ldr(rscratch1, Address(esp, 7 * wordSize)); ++ __ ldrw(rscratch2, Address(esp, 6 * wordSize)); ++ emit_array_address(rscratch1, rscratch2, B, T_DOUBLE); + // beta + __ ldrd(beta, Address(esp, 3 * wordSize)); + // Start pushing arguments to machine stack. +@@ -960,22 +948,22 @@ address InterpreterGenerator::generate_Dgemm_dgemm_entry() { + __ andr(sp, r13, -16); + __ str(lr, Address(sp, -wordSize)); + // ldc +- __ ldrw(tmp1, Address(esp, 0x0)); +- __ strw(tmp1, Address(sp, 2 * -wordSize)); ++ __ ldrw(rscratch1, Address(esp, 0x0)); ++ __ strw(rscratch1, Address(sp, 2 * -wordSize)); + // C +- __ ldr(tmp1, Address(esp, 2 * wordSize)); +- __ ldrw(tmp2, Address(esp, wordSize)); +- emit_array_address(tmp1, tmp2, tmp1, T_DOUBLE); +- __ str(tmp1, Address(sp, 3 * -wordSize)); ++ __ ldr(rscratch1, Address(esp, 2 * wordSize)); ++ __ ldrw(rscratch2, Address(esp, wordSize)); ++ emit_array_address(rscratch1, rscratch2, rscratch1, T_DOUBLE); ++ __ str(rscratch1, Address(sp, 3 * -wordSize)); + // ldb +- __ ldrw(tmp2, Address(esp, 5 * wordSize)); +- __ strw(tmp2, Address(sp, 4 * -wordSize)); ++ __ ldrw(rscratch2, Address(esp, 5 * wordSize)); ++ __ strw(rscratch2, Address(sp, 4 * -wordSize)); + + // Call function + __ add(sp, sp, 4 * -wordSize); + address fn = CAST_FROM_FN_PTR(address, StubRoutines::dgemmDgemm()); +- __ mov(tmp1, fn); +- __ blr(tmp1); ++ __ mov(rscratch1, fn); ++ __ blr(rscratch1); + + __ ldr(lr, Address(sp, 3 * wordSize)); + // For assert(Rd != sp || imm % 16 == 0) +@@ -1001,9 +989,6 @@ address InterpreterGenerator::generate_Dgemv_dgemv_entry() { + const FloatRegister alpha = v0; // alpha + const FloatRegister beta = v1; // beta + +- const Register tmp1 = rscratch1; +- const Register tmp2 = rscratch2; +- + // esp: expression stack of caller + // dgemv parameter ---> the position in stack ---> move to register + // | char* trans | | esp + 15 | | r0 | +@@ -1032,10 +1017,21 @@ address InterpreterGenerator::generate_Dgemv_dgemv_entry() { + + + // trans +- __ ldr(trans, Address(esp, 15 * wordSize)); +- load_String_value(trans, tmp1); +- load_String_offset(trans, tmp2); +- emit_array_address(tmp1, tmp2, trans, T_CHAR); ++ __ ldr(r0, Address(esp, 15 * wordSize)); ++ ++ // Get String value offset, because of order of initialization for Interpreter, ++ // we have to hardcode the offset for String value and offset. These instructions ++ // generated there will be patched in interpreter_patch after java.lang.String has ++ // been loaded. ++ // load String offset ++ __ mov(r1, 0); // __ ldrw(r1, Address(r0, java_lang_String::offset_offset_in_bytes())) ++ ++ // load String value ++ __ mov(r2, 0xc); // __ mov(r2, java_lang_String::value_offset_in_bytes()) ++ __ add(r0, r0, r2); ++ __ load_heap_oop(r0, Address(r0)); ++ emit_array_address(r0, r1, trans, T_CHAR); ++ + // m, n + __ ldrw(m, Address(esp, 14 * wordSize)); + __ ldrw(n, Address(esp, 13 * wordSize)); +@@ -1044,19 +1040,17 @@ address InterpreterGenerator::generate_Dgemv_dgemv_entry() { + __ ldrd(alpha, Address(esp, 11 * wordSize)); + + // a +- __ ldr(tmp1, Address(esp, 10 * wordSize)); +- __ mov(tmp2, zr); +- __ ldrw(tmp2, Address(esp, 9 * wordSize)); +- emit_array_address(tmp1, tmp2, a, T_DOUBLE); ++ __ ldr(r3, Address(esp, 10 * wordSize)); ++ __ ldrw(r4, Address(esp, 9 * wordSize)); ++ emit_array_address(r3, r4, a, T_DOUBLE); + + // lda + __ ldrw(lda, Address(esp, 8 * wordSize)); + + // x +- __ ldr(tmp1, Address(esp, 7 * wordSize)); +- __ mov(tmp2, zr); +- __ ldrw(tmp2, Address(esp, 6 * wordSize)); +- emit_array_address(tmp1, tmp2, x, T_DOUBLE); ++ __ ldr(r5, Address(esp, 7 * wordSize)); ++ __ ldrw(r6, Address(esp, 6 * wordSize)); ++ emit_array_address(r5, r6, x, T_DOUBLE); + + // incx + __ ldrw(incx, Address(esp, 5 * wordSize)); +@@ -1065,25 +1059,24 @@ address InterpreterGenerator::generate_Dgemv_dgemv_entry() { + __ ldrd(beta, Address(esp, 3 * wordSize)); + + // y +- __ ldr(tmp1, Address(esp, 2 * wordSize)); +- __ mov(tmp2, zr); +- __ ldrw(tmp2, Address(esp, wordSize)); +- emit_array_address(tmp1, tmp2, y, T_DOUBLE); ++ __ ldr(rscratch1, Address(esp, 2 * wordSize)); ++ __ ldrw(rscratch2, Address(esp, wordSize)); ++ emit_array_address(rscratch1, rscratch2, y, T_DOUBLE); + + // resume sp, restore lr + __ andr(sp, r13, -16); + __ str(lr, Address(sp, -wordSize)); + + // incy, push on stack +- __ ldrw(tmp1, Address(esp, 0)); +- __ strw(tmp1, Address(sp, 2 * -wordSize)); ++ __ ldrw(rscratch1, Address(esp, 0)); ++ __ strw(rscratch1, Address(sp, 2 * -wordSize)); + + __ add(sp, sp, -2 * wordSize); + + // call function + address fn = CAST_FROM_FN_PTR(address, StubRoutines::dgemvDgemv()); +- __ mov(tmp1, fn); +- __ blr(tmp1); ++ __ mov(rscratch1, fn); ++ __ blr(rscratch1); + + // resume lr + __ ldr(lr, Address(sp, wordSize)); +@@ -1960,7 +1953,6 @@ void AbstractInterpreter::layout_activation(Method* method, + method->constants()->cache(); + } + +- + //----------------------------------------------------------------------------- + // Exceptions + +diff --git a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.hpp +index 36e1aa89d..3ca17e3c4 100644 +--- a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.hpp ++++ b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.hpp +@@ -28,6 +28,78 @@ + #define CPU_AARCH64_VM_TEMPLATEINTERPRETER_AARCH64_HPP + + ++ public: ++ static void patch_method(AbstractInterpreter::MethodKind kind) { ++ unsigned value_offset = java_lang_String::value_offset_in_bytes(); ++ unsigned offset_offset = 0; ++ address entry = entry_for_kind(kind); ++ ++ if (entry == NULL) { ++ return; ++ } ++ ++ switch (kind) { ++ case AbstractInterpreter::org_netlib_blas_Dgemm_dgemm: ++ if (StubRoutines::_dgemmDgemm == NULL) { ++ break; ++ } ++ // 0 : ldr x0, [x20, #136] ++ // 1 : ldr x1, [x20, #128] ++ // 2 : mov x2, #0x0 ==================> ldr w2, [x0, ] ++ // 3 : mov x3, #0x0 ==================> ldr w3, [x1, ] ++ // 4 : orr x4, xzr, #0xc =============> orr x4, xzr, ++ if (java_lang_String::has_offset_field()) { ++ guarantee(Instruction_aarch64::extract(((unsigned*)entry)[2], 31, 23) == 0b110100101 && ++ Instruction_aarch64::extract(((unsigned*)entry)[3], 31, 23) == 0b110100101, ++ "wrong insns in patch"); ++ offset_offset = java_lang_String::offset_offset_in_bytes(); ++ // ldr w2, [x0, ] ++ address tmp = entry + 4 * 2; ++ Instruction_aarch64::patch(tmp, 31, 22, 0b1011100101); // opc ++ Instruction_aarch64::patch(tmp, 21, 10, offset_offset >> 2); // imm12 ++ Instruction_aarch64::patch(tmp, 9, 5, 0); // Rn ++ Instruction_aarch64::patch(tmp, 4, 0, 2); // Rt ++ // ldr w3, [x1, ] ++ tmp = entry + 4 * 3; ++ Instruction_aarch64::patch(tmp, 31, 22, 0b1011100101); // opc ++ Instruction_aarch64::patch(tmp, 21, 10, offset_offset >> 2); // imm12 ++ Instruction_aarch64::patch(tmp, 9, 5, 1); // Rn ++ Instruction_aarch64::patch(tmp, 4, 0, 3); // Rt ++ } ++ guarantee(Instruction_aarch64::extract(((unsigned*)entry)[4], 31, 23) == 0b101100100 && ++ Instruction_aarch64::extract(((unsigned*)entry)[4], 9, 0) == 0b1111100100, "wrong insns in patch"); ++ Instruction_aarch64::patch(entry + 4 * 4, 22, 10, ++ (uint64_t)encode_logical_immediate(false, (uint64_t)value_offset)); // imm16 ++ ICache::invalidate_range(entry, 4 * 5); ++ break; ++ case AbstractInterpreter::org_netlib_blas_Dgemv_dgemv: ++ if (StubRoutines::_dgemvDgemv == NULL) { ++ break; ++ } ++ // 0 : ldr x0, [x20, #120] ++ // 1 : mov x1, #0x0 ==================> ldr w1, [r0, ] ++ // 2 : orr x2, xzr, #0xc =============> orr x2, xzr, ++ if (java_lang_String::has_offset_field()) { ++ guarantee(Instruction_aarch64::extract(((unsigned*)entry)[1], 31, 23) == 0b110100101, "wrong insns in patch"); ++ offset_offset = java_lang_String::offset_offset_in_bytes(); ++ // ldr w1, [x0, ] ++ address tmp = entry + 4 * 1; ++ Instruction_aarch64::patch(tmp, 31, 22, 0b1011100101); // opc ++ Instruction_aarch64::patch(tmp, 21, 10, offset_offset >> 2); // imm12 ++ Instruction_aarch64::patch(tmp, 9, 5, 0); // Rn ++ Instruction_aarch64::patch(tmp, 4, 0, 1); // Rt ++ } ++ guarantee(Instruction_aarch64::extract(((unsigned*)entry)[2], 31, 23) == 0b101100100 && ++ Instruction_aarch64::extract(((unsigned*)entry)[2], 9, 0) == 0b1111100010, "wrong insns in patch"); ++ Instruction_aarch64::patch(entry + 4 * 2, 22, 10, ++ (uint64_t)encode_logical_immediate(false, (uint64_t)value_offset)); // imm16 ++ ICache::invalidate_range(entry, 4 * 3); ++ break; ++ default: ++ break; ++ } ++ } ++ + protected: + + // Size of interpreter code. Increase if too small. Interpreter will +diff --git a/hotspot/src/share/vm/interpreter/cppInterpreter.cpp b/hotspot/src/share/vm/interpreter/cppInterpreter.cpp +index 9e48a1d94..0007aa8be 100644 +--- a/hotspot/src/share/vm/interpreter/cppInterpreter.cpp ++++ b/hotspot/src/share/vm/interpreter/cppInterpreter.cpp +@@ -31,20 +31,17 @@ + #ifdef CC_INTERP + # define __ _masm-> + +-void CppInterpreter::initialize_stub() { ++void CppInterpreter::initialize() { + if (_code != NULL) return; +- int code_size = InterpreterCodeSize; +- NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space +- _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL, +- "Interpreter"); +-} +- +-void CppInterpreter::initialize_code() { + AbstractInterpreter::initialize(); + + // generate interpreter + { ResourceMark rm; + TraceTime timer("Interpreter generation", TraceStartupTime); ++ int code_size = InterpreterCodeSize; ++ NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space ++ _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL, ++ "Interpreter"); + InterpreterGenerator g(_code); + if (PrintInterpreter) print(); + } +diff --git a/hotspot/src/share/vm/interpreter/cppInterpreter.hpp b/hotspot/src/share/vm/interpreter/cppInterpreter.hpp +index 58efcfaf2..6a6447503 100644 +--- a/hotspot/src/share/vm/interpreter/cppInterpreter.hpp ++++ b/hotspot/src/share/vm/interpreter/cppInterpreter.hpp +@@ -54,8 +54,7 @@ class CppInterpreter: public AbstractInterpreter { + + public: + // Initialization/debugging +- static void initialize_stub(); +- static void initialize_code(); ++ static void initialize(); + // this only returns whether a pc is within generated code for the interpreter. + + // This is a moderately dubious interface for the c++ interpreter. Only +diff --git a/hotspot/src/share/vm/interpreter/interpreter.cpp b/hotspot/src/share/vm/interpreter/interpreter.cpp +index a313f2e63..bfcb1bea2 100644 +--- a/hotspot/src/share/vm/interpreter/interpreter.cpp ++++ b/hotspot/src/share/vm/interpreter/interpreter.cpp +@@ -85,6 +85,7 @@ void InterpreterCodelet::print_on(outputStream* st) const { + // Implementation of platform independent aspects of Interpreter + + void AbstractInterpreter::initialize() { ++ if (_code != NULL) return; + // make sure 'imported' classes are initialized + if (CountBytecodes || TraceBytecodes || StopInterpreterAt) BytecodeCounter::reset(); + if (PrintBytecodeHistogram) BytecodeHistogram::reset(); +@@ -112,22 +113,8 @@ void AbstractInterpreter::print() { + } + + +-// The reason that interpreter initialization is split into two parts is that the first part +-// needs to run before methods are loaded (which with CDS implies linked also), and the other +-// part needs to run after. The reason is that when methods are loaded (with CDS) or linked +-// (without CDS), the i2c adapters are generated that assert we are currently in the interpreter. +-// Asserting that requires knowledge about where the interpreter is in memory. Therefore, +-// establishing the interpreter address must be done before methods are loaded. However, +-// we would like to actually generate the interpreter after methods are loaded. That allows +-// us to remove otherwise hardcoded offsets regarding fields that are needed in the interpreter +-// code. This leads to a split if 1. reserving the memory for the interpreter, 2. loading methods +-// and 3. generating the interpreter. +-void interpreter_init_stub() { +- Interpreter::initialize_stub(); +-} +- +-void interpreter_init_code() { +- Interpreter::initialize_code(); ++void interpreter_init() { ++ Interpreter::initialize(); + #ifndef PRODUCT + if (TraceBytecodes) BytecodeTracer::set_closure(BytecodeTracer::std_closure()); + #endif // PRODUCT +diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp +index f38f05117..09298a7fc 100644 +--- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp ++++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp +@@ -32,20 +32,12 @@ + + # define __ _masm-> + +-void TemplateInterpreter::initialize_stub() { ++void TemplateInterpreter::initialize() { + if (_code != NULL) return; + // assertions + assert((int)Bytecodes::number_of_codes <= (int)DispatchTable::length, + "dispatch table too small"); + +- // allocate interpreter +- int code_size = InterpreterCodeSize; +- NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space +- _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL, +- "Interpreter"); +-} +- +-void TemplateInterpreter::initialize_code() { + AbstractInterpreter::initialize(); + + TemplateTable::initialize(); +@@ -53,6 +45,10 @@ void TemplateInterpreter::initialize_code() { + // generate interpreter + { ResourceMark rm; + TraceTime timer("Interpreter generation", TraceStartupTime); ++ int code_size = InterpreterCodeSize; ++ NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space ++ _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL, ++ "Interpreter"); + InterpreterGenerator g(_code); + if (PrintInterpreter) print(); + } +diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp +index 96da6353c..5f76dca8a 100644 +--- a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp ++++ b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp +@@ -132,8 +132,7 @@ class TemplateInterpreter: public AbstractInterpreter { + + public: + // Initialization/debugging +- static void initialize_stub(); +- static void initialize_code(); ++ static void initialize(); + // this only returns whether a pc is within generated code for the interpreter. + static bool contains(address pc) { return _code != NULL && _code->contains(pc); } + +diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp +index d9e670bee..1d05bcc73 100644 +--- a/hotspot/src/share/vm/memory/universe.cpp ++++ b/hotspot/src/share/vm/memory/universe.cpp +@@ -425,6 +425,14 @@ void Universe::genesis(TRAPS) { + // Initialize dependency array for null class loader + ClassLoaderData::the_null_class_loader_data()->init_dependencies(CHECK); + ++ // Patch the BLAS Interpreter intrinsics with java.lang.String ++ // offset after java.lang.String has been loaded. ++#if defined(TARGET_OS_ARCH_linux_aarch64) && !defined(CC_INTERP) ++ if (UseF2jBLASIntrinsics) { ++ Interpreter::patch_method(Interpreter::org_netlib_blas_Dgemm_dgemm); ++ Interpreter::patch_method(Interpreter::org_netlib_blas_Dgemv_dgemv); ++ } ++#endif + } + + // CDS support for patching vtables in metadata in the shared archive. +diff --git a/hotspot/src/share/vm/runtime/init.cpp b/hotspot/src/share/vm/runtime/init.cpp +index 4c133bd4e..d15e40d44 100644 +--- a/hotspot/src/share/vm/runtime/init.cpp ++++ b/hotspot/src/share/vm/runtime/init.cpp +@@ -54,8 +54,7 @@ void VM_Version_init(); + void os_init_globals(); // depends on VM_Version_init, before universe_init + void stubRoutines_init1(); + jint universe_init(); // depends on codeCache_init and stubRoutines_init +-void interpreter_init_stub(); // before any methods loaded +-void interpreter_init_code(); // after methods loaded, but before they are linked ++void interpreter_init(); // before any methods loaded + void invocationCounter_init(); // before any methods loaded + void marksweep_init(); + void accessFlags_init(); +@@ -107,7 +106,7 @@ jint init_globals() { + if (status != JNI_OK) + return status; + +- interpreter_init_stub(); // before methods get loaded ++ interpreter_init(); // before any methods loaded + invocationCounter_init(); // before any methods loaded + marksweep_init(); + accessFlags_init(); +@@ -115,7 +114,6 @@ jint init_globals() { + InterfaceSupport_init(); + SharedRuntime::generate_stubs(); + universe2_init(); // dependent on codeCache_init and stubRoutines_init1 +- interpreter_init_code(); // after universe2_init and before any method gets linked + referenceProcessor_init(); + jni_handles_init(); + #if INCLUDE_VM_STRUCTS +-- +2.22.0 + diff --git a/PS-introduce-UsePSRelaxedForwardee-to-enable-using-r.patch b/PS-introduce-UsePSRelaxedForwardee-to-enable-using-r.patch new file mode 100755 index 0000000000000000000000000000000000000000..3b0611186886cb1701fff198cee8a8bedcbe807e --- /dev/null +++ b/PS-introduce-UsePSRelaxedForwardee-to-enable-using-r.patch @@ -0,0 +1,96 @@ +From ec7d9d798c17df377dc8d4c00d8f285ea32e590e Mon Sep 17 00:00:00 2001 +From: mashoubing +Date: Mon, 13 Sep 2021 15:22:21 +0800 +Subject: [PATCH 18/23] PS:introduce UsePSRelaxedForwardee to enable using + relaxed CAS in copy_to_survivor_space + +Summary:gc:ps use relaxed CAS for better performance in weak memory model +LLT:NA +Patch Type:huawei +Bug url:NA +--- + .../parallelScavenge/psPromotionManager.inline.hpp | 10 ++++++++-- + .../parallelScavenge/psScavenge.inline.hpp | 2 +- + hotspot/src/share/vm/oops/oop.inline.hpp | 2 +- + hotspot/src/share/vm/runtime/globals.hpp | 4 ++++ + 4 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp +index e517abcee..c58e3d1ef 100644 +--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp ++++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp +@@ -203,15 +203,17 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) { + + assert(new_obj != NULL, "allocation should have succeeded"); + ++ Prefetch::write(new_obj, PrefetchCopyIntervalInBytes); + // Copy obj + Copy::aligned_disjoint_words((HeapWord*)o, (HeapWord*)new_obj, new_obj_size); + + // Now we have to CAS in the header. +-#ifdef AARCH64 ++ + // CAS with memory fence cost a lot within copy_to_survivor_space on aarch64. +- // To minimize the cost, we use a normal CAS to do object forwarding, plus a ++ // To minimize the cost, we can use a normal CAS to do object forwarding, plus a + // memory fence only upon CAS succeeds. To further reduce the fence insertion, + // we can skip the fence insertion for leaf objects (objects don't have reference fields). ++#if defined(AARCH64) && defined(PRODUCT) + if (o->relax_cas_forward_to(new_obj, test_mark)) { + #else + if (o->cas_forward_to(new_obj, test_mark)) { +@@ -271,6 +273,10 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) { + #ifndef PRODUCT + // This code must come after the CAS test, or it will print incorrect + // information. ++ // When UsePSRelaxedForwardee is true or object o is gc leaf, CAS failed threads can't access forwardee's content, ++ // as relaxed CAS cann't gurantee new obj's content visible for these CAS failed threads.The below log output is ++ // dangerous. So we just support UsePSRelaxedForwardee and gc leaf in product. ++ // Everywhere access forwardee's content must be careful. + if (TraceScavenge) { + gclog_or_tty->print_cr("{%s %s " PTR_FORMAT " -> " PTR_FORMAT " (%d)}", + PSScavenge::should_scavenge(&new_obj) ? "copying" : "tenuring", +diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp +index 1a722a7ca..3cfabe486 100644 +--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp ++++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp +@@ -78,7 +78,7 @@ inline void PSScavenge::copy_and_push_safe_barrier(PSPromotionManager* pm, + #ifndef PRODUCT + // This code must come after the CAS test, or it will print incorrect + // information. +- if (TraceScavenge && o->is_forwarded()) { ++ if (TraceScavenge && o->is_forwarded()) { + gclog_or_tty->print_cr("{%s %s " PTR_FORMAT " -> " PTR_FORMAT " (%d)}", + "forwarding", + new_obj->klass()->internal_name(), p2i((void *)o), p2i((void *)new_obj), new_obj->size()); +diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp +index 00fb2374e..ed37d0558 100644 +--- a/hotspot/src/share/vm/oops/oop.inline.hpp ++++ b/hotspot/src/share/vm/oops/oop.inline.hpp +@@ -705,7 +705,7 @@ inline bool oopDesc::relax_cas_forward_to(oop p, markOop compare) { + if (old_markoop == compare) { + // Once the CAS succeeds, leaf object never needs to be visible to other threads (finished + // collection by current thread), so we can save the fence. +- if (!p->klass()->oop_is_gc_leaf()) { ++ if (!(UsePSRelaxedForwardee || p->klass()->oop_is_gc_leaf())) { + OrderAccess::fence(); + } + return true; +diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp +index cef343a0e..9779653ba 100644 +--- a/hotspot/src/share/vm/runtime/globals.hpp ++++ b/hotspot/src/share/vm/runtime/globals.hpp +@@ -1441,6 +1441,10 @@ class CommandLineFlags { + product(bool, UseParallelGC, false, \ + "Use the Parallel Scavenge garbage collector") \ + \ ++ experimental(bool, UsePSRelaxedForwardee, false, \ ++ "Use the UsePSRelaxedForwardee to enable ps use relaxed" \ ++ "during young gc copying object") \ ++ \ + product(bool, UseParallelOldGC, false, \ + "Use the Parallel Old garbage collector") \ + \ +-- +2.22.0 + diff --git a/Parallel-Full-GC-for-G1.patch b/Parallel-Full-GC-for-G1.patch new file mode 100755 index 0000000000000000000000000000000000000000..e7729fef156560d2467b9ba838b8c549127fd722 --- /dev/null +++ b/Parallel-Full-GC-for-G1.patch @@ -0,0 +1,2127 @@ +From abe008c9f30db79afb44f87bd8cab37bd1486e4b Mon Sep 17 00:00:00 2001 +From: wangkun +Date: Mon, 13 Sep 2021 17:34:39 +0800 +Subject: [PATCH 19/23] Parallel Full GC for G1. + +Summary:gc:g1:Parallel Full GC for G1. (prepare/adjust/compact in parallel; uses claimer instead of claim value; code clean) +LLT: N/A +Patch Type:huawei +Bug url: N/A +--- + .../gc_implementation/g1/concurrentMark.cpp | 66 +- + .../g1/g1BlockOffsetTable.inline.hpp | 4 +- + .../gc_implementation/g1/g1CollectedHeap.cpp | 168 +---- + .../gc_implementation/g1/g1CollectedHeap.hpp | 21 +- + .../g1/g1CollectorPolicy.cpp | 16 +- + .../vm/gc_implementation/g1/g1EvacFailure.hpp | 13 +- + .../vm/gc_implementation/g1/g1MarkSweep.cpp | 583 ++++++++++++++++-- + .../vm/gc_implementation/g1/g1MarkSweep.hpp | 45 +- + .../gc_implementation/g1/g1MarkSweep_ext.cpp | 31 - + .../vm/gc_implementation/g1/g1RemSet.cpp | 7 +- + .../vm/gc_implementation/g1/g1RemSet.hpp | 2 +- + .../vm/gc_implementation/g1/g1_globals.hpp | 3 + + .../vm/gc_implementation/g1/heapRegion.cpp | 20 +- + .../vm/gc_implementation/g1/heapRegion.hpp | 44 +- + .../g1/heapRegionManager.cpp | 42 +- + .../g1/heapRegionManager.hpp | 25 +- + hotspot/src/share/vm/memory/space.cpp | 9 +- + hotspot/src/share/vm/memory/space.hpp | 6 +- + hotspot/src/share/vm/memory/space.inline.hpp | 61 ++ + hotspot/src/share/vm/runtime/mutexLocker.cpp | 4 + + hotspot/src/share/vm/runtime/mutexLocker.hpp | 2 + + ...rReclaimHumongousRegionsClearMarkBits.java | 4 +- + ...tEagerReclaimHumongousRegionsWithRefs.java | 4 +- + .../jfr/event/gc/detailed/ExecuteOOMApp.java | 4 +- + .../TestG1ConcurrentModeFailureEvent.java | 36 +- + 25 files changed, 789 insertions(+), 431 deletions(-) + delete mode 100644 hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep_ext.cpp + +diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +index 52bd8cc5e..447bee183 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +@@ -1666,6 +1666,8 @@ protected: + int _failures; + bool _verbose; + ++ HeapRegionClaimer _hrclaimer; ++ + public: + G1ParVerifyFinalCountTask(G1CollectedHeap* g1h, + BitMap* region_bm, BitMap* card_bm, +@@ -1687,6 +1689,7 @@ public: + } else { + _n_workers = 1; + } ++ _hrclaimer.set_workers(_n_workers); + + assert(_expected_card_bm->size() == _actual_card_bm->size(), "sanity"); + assert(_expected_region_bm->size() == _actual_region_bm->size(), "sanity"); +@@ -1706,8 +1709,7 @@ public: + if (G1CollectedHeap::use_parallel_gc_threads()) { + _g1h->heap_region_par_iterate_chunked(&verify_cl, + worker_id, +- _n_workers, +- HeapRegion::VerifyCountClaimValue); ++ &_hrclaimer); + } else { + _g1h->heap_region_iterate(&verify_cl); + } +@@ -1796,6 +1798,7 @@ protected: + BitMap* _actual_card_bm; + + uint _n_workers; ++ HeapRegionClaimer _hrclaimer; + + public: + G1ParFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm) +@@ -1812,6 +1815,7 @@ public: + } else { + _n_workers = 1; + } ++ _hrclaimer.set_workers(_n_workers); + } + + void work(uint worker_id) { +@@ -1824,8 +1828,7 @@ public: + if (G1CollectedHeap::use_parallel_gc_threads()) { + _g1h->heap_region_par_iterate_chunked(&final_update_cl, + worker_id, +- _n_workers, +- HeapRegion::FinalCountClaimValue); ++ &_hrclaimer); + } else { + _g1h->heap_region_iterate(&final_update_cl); + } +@@ -1912,12 +1915,15 @@ protected: + size_t _max_live_bytes; + size_t _freed_bytes; + FreeRegionList* _cleanup_list; ++ HeapRegionClaimer _hrclaimer; + + public: + G1ParNoteEndTask(G1CollectedHeap* g1h, +- FreeRegionList* cleanup_list) : ++ FreeRegionList* cleanup_list, ++ uint n_workers) : + AbstractGangTask("G1 note end"), _g1h(g1h), +- _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list) { } ++ _max_live_bytes(0), _freed_bytes(0), ++ _cleanup_list(cleanup_list), _hrclaimer(n_workers) { } + + void work(uint worker_id) { + double start = os::elapsedTime(); +@@ -1926,9 +1932,7 @@ public: + G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list, + &hrrs_cleanup_task); + if (G1CollectedHeap::use_parallel_gc_threads()) { +- _g1h->heap_region_par_iterate_chunked(&g1_note_end, worker_id, +- _g1h->workers()->active_workers(), +- HeapRegion::NoteEndClaimValue); ++ _g1h->heap_region_par_iterate_chunked(&g1_note_end, worker_id, &_hrclaimer); + } else { + _g1h->heap_region_iterate(&g1_note_end); + } +@@ -1974,16 +1978,16 @@ protected: + G1RemSet* _g1rs; + BitMap* _region_bm; + BitMap* _card_bm; ++ HeapRegionClaimer _hrclaimer; + public: +- G1ParScrubRemSetTask(G1CollectedHeap* g1h, +- BitMap* region_bm, BitMap* card_bm) : ++ G1ParScrubRemSetTask(G1CollectedHeap* g1h, BitMap* region_bm, ++ BitMap* card_bm, uint n_workers) : + AbstractGangTask("G1 ScrubRS"), _g1rs(g1h->g1_rem_set()), +- _region_bm(region_bm), _card_bm(card_bm) { } ++ _region_bm(region_bm), _card_bm(card_bm), _hrclaimer(n_workers) { } + + void work(uint worker_id) { + if (G1CollectedHeap::use_parallel_gc_threads()) { +- _g1rs->scrub_par(_region_bm, _card_bm, worker_id, +- HeapRegion::ScrubRemSetClaimValue); ++ _g1rs->scrub_par(_region_bm, _card_bm, worker_id, &_hrclaimer); + } else { + _g1rs->scrub(_region_bm, _card_bm); + } +@@ -2026,9 +2030,6 @@ void ConcurrentMark::cleanup() { + G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm); + + if (G1CollectedHeap::use_parallel_gc_threads()) { +- assert(g1h->check_heap_region_claim_values(HeapRegion::InitialClaimValue), +- "sanity check"); +- + g1h->set_par_threads(); + n_workers = g1h->n_par_threads(); + assert(g1h->n_par_threads() == n_workers, +@@ -2036,9 +2037,6 @@ void ConcurrentMark::cleanup() { + g1h->workers()->run_task(&g1_par_count_task); + // Done with the parallel phase so reset to 0. + g1h->set_par_threads(0); +- +- assert(g1h->check_heap_region_claim_values(HeapRegion::FinalCountClaimValue), +- "sanity check"); + } else { + n_workers = 1; + g1_par_count_task.work(0); +@@ -2063,9 +2061,6 @@ void ConcurrentMark::cleanup() { + g1h->workers()->run_task(&g1_par_verify_task); + // Done with the parallel phase so reset to 0. + g1h->set_par_threads(0); +- +- assert(g1h->check_heap_region_claim_values(HeapRegion::VerifyCountClaimValue), +- "sanity check"); + } else { + g1_par_verify_task.work(0); + } +@@ -2091,14 +2086,11 @@ void ConcurrentMark::cleanup() { + g1h->reset_gc_time_stamp(); + + // Note end of marking in all heap regions. +- G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list); ++ G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list, n_workers); + if (G1CollectedHeap::use_parallel_gc_threads()) { + g1h->set_par_threads((int)n_workers); + g1h->workers()->run_task(&g1_par_note_end_task); + g1h->set_par_threads(0); +- +- assert(g1h->check_heap_region_claim_values(HeapRegion::NoteEndClaimValue), +- "sanity check"); + } else { + g1_par_note_end_task.work(0); + } +@@ -2115,15 +2107,11 @@ void ConcurrentMark::cleanup() { + // regions. + if (G1ScrubRemSets) { + double rs_scrub_start = os::elapsedTime(); +- G1ParScrubRemSetTask g1_par_scrub_rs_task(g1h, &_region_bm, &_card_bm); ++ G1ParScrubRemSetTask g1_par_scrub_rs_task(g1h, &_region_bm, &_card_bm, n_workers); + if (G1CollectedHeap::use_parallel_gc_threads()) { + g1h->set_par_threads((int)n_workers); + g1h->workers()->run_task(&g1_par_scrub_rs_task); + g1h->set_par_threads(0); +- +- assert(g1h->check_heap_region_claim_values( +- HeapRegion::ScrubRemSetClaimValue), +- "sanity check"); + } else { + g1_par_scrub_rs_task.work(0); + } +@@ -3299,6 +3287,7 @@ protected: + BitMap* _cm_card_bm; + uint _max_worker_id; + int _active_workers; ++ HeapRegionClaimer _hrclaimer; + + public: + G1AggregateCountDataTask(G1CollectedHeap* g1h, +@@ -3309,15 +3298,14 @@ public: + AbstractGangTask("Count Aggregation"), + _g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm), + _max_worker_id(max_worker_id), +- _active_workers(n_workers) { } ++ _active_workers(n_workers), ++ _hrclaimer(_active_workers) { } + + void work(uint worker_id) { + AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id); + + if (G1CollectedHeap::use_parallel_gc_threads()) { +- _g1h->heap_region_par_iterate_chunked(&cl, worker_id, +- _active_workers, +- HeapRegion::AggregateCountClaimValue); ++ _g1h->heap_region_par_iterate_chunked(&cl, worker_id, &_hrclaimer); + } else { + _g1h->heap_region_iterate(&cl); + } +@@ -3334,15 +3322,9 @@ void ConcurrentMark::aggregate_count_data() { + _max_worker_id, n_workers); + + if (G1CollectedHeap::use_parallel_gc_threads()) { +- assert(_g1h->check_heap_region_claim_values(HeapRegion::InitialClaimValue), +- "sanity check"); + _g1h->set_par_threads(n_workers); + _g1h->workers()->run_task(&g1_par_agg_task); + _g1h->set_par_threads(0); +- +- assert(_g1h->check_heap_region_claim_values(HeapRegion::AggregateCountClaimValue), +- "sanity check"); +- _g1h->reset_heap_region_claim_values(); + } else { + g1_par_agg_task.work(0); + } +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp +index b2d3b282b..912acdbe0 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp +@@ -134,7 +134,9 @@ inline HeapWord* + G1BlockOffsetArray::block_at_or_preceding(const void* addr, + bool has_max_index, + size_t max_index) const { +- assert(_array->offset_array(0) == 0, "objects can't cross covered areas"); ++ assert(_array->offset_array(_array->index_for( ++ G1CollectedHeap::heap()->heap_region_containing(addr)->bottom())) == 0, ++ "objects can't cross covered areas"); + size_t index = _array->index_for(addr); + // We must make sure that the offset table entry we use is valid. If + // "addr" is past the end, start at the last known one and go forward. +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +index ce015b85d..1afc2e331 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +@@ -383,7 +383,6 @@ void G1RegionMappingChangedListener::on_commit(uint start_idx, size_t num_region + + void G1CollectedHeap::run_task(AbstractGangTask* task) { + workers()->run_task(task); +- reset_heap_region_claim_values(); + } + + void G1CollectedHeap::push_dirty_cards_region(HeapRegion* hr) +@@ -1215,17 +1214,17 @@ public: + + class ParRebuildRSTask: public AbstractGangTask { + G1CollectedHeap* _g1; ++ HeapRegionClaimer _hrclaimer; ++ + public: + ParRebuildRSTask(G1CollectedHeap* g1) + : AbstractGangTask("ParRebuildRSTask"), +- _g1(g1) ++ _g1(g1), _hrclaimer(g1->workers()->active_workers()) + { } + + void work(uint worker_id) { + RebuildRSOutOfRegionClosure rebuild_rs(_g1, worker_id); +- _g1->heap_region_par_iterate_chunked(&rebuild_rs, worker_id, +- _g1->workers()->active_workers(), +- HeapRegion::RebuildRSClaimValue); ++ _g1->heap_region_par_iterate_chunked(&rebuild_rs, worker_id, &_hrclaimer); + } + }; + +@@ -1454,8 +1453,6 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, + set_par_threads(n_workers); + + ParRebuildRSTask rebuild_rs_task(this); +- assert(check_heap_region_claim_values( +- HeapRegion::InitialClaimValue), "sanity check"); + assert(UseDynamicNumberOfGCThreads || + workers()->active_workers() == workers()->total_workers(), + "Unless dynamic should use total workers"); +@@ -1465,9 +1462,6 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, + set_par_threads(workers()->active_workers()); + workers()->run_task(&rebuild_rs_task); + set_par_threads(0); +- assert(check_heap_region_claim_values( +- HeapRegion::RebuildRSClaimValue), "sanity check"); +- reset_heap_region_claim_values(); + } else { + RebuildRSOutOfRegionClosure rebuild_rs(this); + heap_region_iterate(&rebuild_rs); +@@ -1553,7 +1547,6 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, + gc_timer->register_gc_end(); + gc_tracer->report_gc_end(gc_timer->gc_end(), gc_timer->time_partitions()); + } +- + return true; + } + +@@ -1574,8 +1567,8 @@ G1CollectedHeap:: + resize_if_necessary_after_full_collection(size_t word_size) { + // Include the current allocation, if any, and bytes that will be + // pre-allocated to support collections, as "used". +- const size_t used_after_gc = used(); + const size_t capacity_after_gc = capacity(); ++ const size_t used_after_gc = capacity_after_gc - num_free_regions() * HeapRegion::GrainBytes; + const size_t free_after_gc = capacity_after_gc - used_after_gc; + + // This is enforced in arguments.cpp. +@@ -2678,13 +2671,15 @@ class G1ParallelObjectIterator : public ParallelObjectIterator { + private: + G1CollectedHeap* _heap; + uint _num_threads; ++ HeapRegionClaimer _claimer; + + public: + G1ParallelObjectIterator(uint thread_num) : +- _heap(G1CollectedHeap::heap()),_num_threads(thread_num) {} ++ _heap(G1CollectedHeap::heap()),_num_threads(thread_num), ++ _claimer(thread_num) { } + + virtual void object_iterate(ObjectClosure* cl, uint worker_id) { +- _heap->object_iterate_parallel(cl, worker_id,_num_threads); ++ _heap->object_iterate_parallel(cl, worker_id, &_claimer); + } + }; + +@@ -2692,9 +2687,10 @@ ParallelObjectIterator* G1CollectedHeap::parallel_object_iterator(uint thread_nu + return new G1ParallelObjectIterator(thread_num); + } + +-void G1CollectedHeap::object_iterate_parallel(ObjectClosure* cl, uint worker_id, uint num_workers) { ++void G1CollectedHeap::object_iterate_parallel(ObjectClosure* cl, uint worker_id, ++ HeapRegionClaimer* claimer) { + IterateObjectClosureRegionClosure blk(cl); +- heap_region_par_iterate_chunked(&blk, worker_id, num_workers, HeapRegion::ParInspectClaimValue); ++ heap_region_par_iterate_chunked(&blk, worker_id, claimer); + } + + +@@ -2722,109 +2718,10 @@ void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const { + void + G1CollectedHeap::heap_region_par_iterate_chunked(HeapRegionClosure* cl, + uint worker_id, +- uint num_workers, +- jint claim_value) const { +- _hrm.par_iterate(cl, worker_id, num_workers, claim_value); +-} +- +-class ResetClaimValuesClosure: public HeapRegionClosure { +-public: +- bool doHeapRegion(HeapRegion* r) { +- r->set_claim_value(HeapRegion::InitialClaimValue); +- return false; +- } +-}; +- +-void G1CollectedHeap::reset_heap_region_claim_values() { +- ResetClaimValuesClosure blk; +- heap_region_iterate(&blk); +-} +- +-void G1CollectedHeap::reset_cset_heap_region_claim_values() { +- ResetClaimValuesClosure blk; +- collection_set_iterate(&blk); +-} +- +-#ifdef ASSERT +-// This checks whether all regions in the heap have the correct claim +-// value. I also piggy-backed on this a check to ensure that the +-// humongous_start_region() information on "continues humongous" +-// regions is correct. +- +-class CheckClaimValuesClosure : public HeapRegionClosure { +-private: +- jint _claim_value; +- uint _failures; +- HeapRegion* _sh_region; +- +-public: +- CheckClaimValuesClosure(jint claim_value) : +- _claim_value(claim_value), _failures(0), _sh_region(NULL) { } +- bool doHeapRegion(HeapRegion* r) { +- if (r->claim_value() != _claim_value) { +- gclog_or_tty->print_cr("Region " HR_FORMAT ", " +- "claim value = %d, should be %d", +- HR_FORMAT_PARAMS(r), +- r->claim_value(), _claim_value); +- ++_failures; +- } +- if (!r->isHumongous()) { +- _sh_region = NULL; +- } else if (r->startsHumongous()) { +- _sh_region = r; +- } else if (r->continuesHumongous()) { +- if (r->humongous_start_region() != _sh_region) { +- gclog_or_tty->print_cr("Region " HR_FORMAT ", " +- "HS = " PTR_FORMAT ", should be " PTR_FORMAT, +- HR_FORMAT_PARAMS(r), +- p2i(r->humongous_start_region()), +- p2i(_sh_region)); +- ++_failures; +- } +- } +- return false; +- } +- uint failures() { return _failures; } +-}; +- +-bool G1CollectedHeap::check_heap_region_claim_values(jint claim_value) { +- CheckClaimValuesClosure cl(claim_value); +- heap_region_iterate(&cl); +- return cl.failures() == 0; ++ HeapRegionClaimer *hrclaimer) const { ++ _hrm.par_iterate(cl, worker_id, hrclaimer); + } + +-class CheckClaimValuesInCSetHRClosure: public HeapRegionClosure { +-private: +- jint _claim_value; +- uint _failures; +- +-public: +- CheckClaimValuesInCSetHRClosure(jint claim_value) : +- _claim_value(claim_value), _failures(0) { } +- +- uint failures() { return _failures; } +- +- bool doHeapRegion(HeapRegion* hr) { +- assert(hr->in_collection_set(), "how?"); +- assert(!hr->isHumongous(), "H-region in CSet"); +- if (hr->claim_value() != _claim_value) { +- gclog_or_tty->print_cr("CSet Region " HR_FORMAT ", " +- "claim value = %d, should be %d", +- HR_FORMAT_PARAMS(hr), +- hr->claim_value(), _claim_value); +- _failures += 1; +- } +- return false; +- } +-}; +- +-bool G1CollectedHeap::check_cset_heap_region_claim_values(jint claim_value) { +- CheckClaimValuesInCSetHRClosure cl(claim_value); +- collection_set_iterate(&cl); +- return cl.failures() == 0; +-} +-#endif // ASSERT +- + // Clear the cached CSet starting regions and (more importantly) + // the time stamps. Called when we reset the GC time stamp. + void G1CollectedHeap::clear_cset_start_regions() { +@@ -3348,6 +3245,7 @@ private: + G1CollectedHeap* _g1h; + VerifyOption _vo; + bool _failures; ++ HeapRegionClaimer _hrclaimer; + + public: + // _vo == UsePrevMarking -> use "prev" marking information, +@@ -3357,7 +3255,8 @@ public: + AbstractGangTask("Parallel verify task"), + _g1h(g1h), + _vo(vo), +- _failures(false) { } ++ _failures(false), ++ _hrclaimer(g1h->workers()->active_workers()) { } + + bool failures() { + return _failures; +@@ -3366,9 +3265,7 @@ public: + void work(uint worker_id) { + HandleMark hm; + VerifyRegionClosure blk(true, _vo); +- _g1h->heap_region_par_iterate_chunked(&blk, worker_id, +- _g1h->workers()->active_workers(), +- HeapRegion::ParVerifyClaimValue); ++ _g1h->heap_region_par_iterate_chunked(&blk, worker_id, &_hrclaimer); + if (blk.failures()) { + _failures = true; + } +@@ -3411,9 +3308,6 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) { + + if (!silent) { gclog_or_tty->print("HeapRegions "); } + if (GCParallelVerificationEnabled && ParallelGCThreads > 1) { +- assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), +- "sanity check"); +- + G1ParVerifyTask task(this, vo); + assert(UseDynamicNumberOfGCThreads || + workers()->active_workers() == workers()->total_workers(), +@@ -3425,16 +3319,6 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) { + if (task.failures()) { + failures = true; + } +- +- // Checks that the expected amount of parallel work was done. +- // The implication is that n_workers is > 0. +- assert(check_heap_region_claim_values(HeapRegion::ParVerifyClaimValue), +- "sanity check"); +- +- reset_heap_region_claim_values(); +- +- assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), +- "sanity check"); + } else { + VerifyRegionClosure blk(false, vo); + heap_region_iterate(&blk); +@@ -4164,8 +4048,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { + } + + assert(check_young_list_well_formed(), "young list should be well formed"); +- assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), +- "sanity check"); + + // Don't dynamically change the number of GC threads this early. A value of + // 0 is used to indicate serial work. When parallel work is done, +@@ -4508,8 +4390,6 @@ void G1CollectedHeap::finalize_for_evac_failure() { + } + + void G1CollectedHeap::remove_self_forwarding_pointers() { +- assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity"); +- + double remove_self_forwards_start = os::elapsedTime(); + + G1ParRemoveSelfForwardPtrsTask rsfp_task(this); +@@ -4522,13 +4402,6 @@ void G1CollectedHeap::remove_self_forwarding_pointers() { + rsfp_task.work(0); + } + +- assert(check_cset_heap_region_claim_values(HeapRegion::ParEvacFailureClaimValue), "sanity"); +- +- // Reset the claim values in the regions in the collection set. +- reset_cset_heap_region_claim_values(); +- +- assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity"); +- + // Now restore saved marks, if any. + assert(_objs_with_preserved_marks.size() == + _preserved_marks_of_objs.size(), "Both or none."); +@@ -6000,11 +5873,6 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) { + + purge_code_root_memory(); + +- if (g1_policy()->during_initial_mark_pause()) { +- // Reset the claim values set during marking the strong code roots +- reset_heap_region_claim_values(); +- } +- + finalize_for_evac_failure(); + + if (evacuation_failed()) { +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +index f4ab7c0bd..2858ebfba 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +@@ -216,6 +216,7 @@ class G1CollectedHeap : public SharedHeap { + friend class CountRCClosure; + friend class EvacPopObjClosure; + friend class G1ParCleanupCTTask; ++ friend class HeapRegionClaimer; + + friend class G1FreeHumongousRegionClosure; + friend class FreeRegionList; +@@ -1294,7 +1295,7 @@ public: + void cleanUpCardTable(); + + // Iteration functions. +- void object_iterate_parallel(ObjectClosure* cl, uint worker_id, uint num_workers); ++ void object_iterate_parallel(ObjectClosure* cl, uint worker_id, HeapRegionClaimer* claimer); + + // Iterate over all the ref-containing fields of all objects, calling + // "cl.do_oop" on each. +@@ -1338,23 +1339,7 @@ public: + // i.e., that a closure never attempt to abort a traversal. + void heap_region_par_iterate_chunked(HeapRegionClosure* cl, + uint worker_id, +- uint num_workers, +- jint claim_value) const; +- +- // It resets all the region claim values to the default. +- void reset_heap_region_claim_values(); +- +- // Resets the claim values of regions in the current +- // collection set to the default. +- void reset_cset_heap_region_claim_values(); +- +-#ifdef ASSERT +- bool check_heap_region_claim_values(jint claim_value); +- +- // Same as the routine above but only checks regions in the +- // current collection set. +- bool check_cset_heap_region_claim_values(jint claim_value); +-#endif // ASSERT ++ HeapRegionClaimer *hrclaimer) const; + + // Clear the cached cset start regions and (more importantly) + // the time stamps. Called when we reset the GC time stamp. +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +index 237932465..6d817883a 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +@@ -1606,19 +1606,19 @@ class ParKnownGarbageTask: public AbstractGangTask { + CollectionSetChooser* _hrSorted; + uint _chunk_size; + G1CollectedHeap* _g1; ++ HeapRegionClaimer _hrclaimer; ++ + public: +- ParKnownGarbageTask(CollectionSetChooser* hrSorted, uint chunk_size) : ++ ParKnownGarbageTask(CollectionSetChooser* hrSorted, uint chunk_size, uint n_workers) : + AbstractGangTask("ParKnownGarbageTask"), + _hrSorted(hrSorted), _chunk_size(chunk_size), +- _g1(G1CollectedHeap::heap()) { } ++ _g1(G1CollectedHeap::heap()), _hrclaimer(n_workers) { } + + void work(uint worker_id) { + ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted, _chunk_size); + + // Back to zero for the claim value. +- _g1->heap_region_par_iterate_chunked(&parKnownGarbageCl, worker_id, +- _g1->workers()->active_workers(), +- HeapRegion::InitialClaimValue); ++ _g1->heap_region_par_iterate_chunked(&parKnownGarbageCl, worker_id, &_hrclaimer); + } + }; + +@@ -1650,11 +1650,9 @@ G1CollectorPolicy::record_concurrent_mark_cleanup_end(int no_of_gc_threads) { + _collectionSetChooser->prepare_for_par_region_addition(_g1->num_regions(), + WorkUnit); + ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser, +- (int) WorkUnit); ++ (int) WorkUnit, ++ no_of_gc_threads); + _g1->workers()->run_task(&parKnownGarbageTask); +- +- assert(_g1->check_heap_region_claim_values(HeapRegion::InitialClaimValue), +- "sanity check"); + } else { + KnownGarbageClosure knownGarbagecl(_collectionSetChooser); + _g1->heap_region_iterate(&knownGarbagecl); +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp +index e62834010..f3930a89d 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp +@@ -177,15 +177,16 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure { + G1CollectedHeap* _g1h; + ConcurrentMark* _cm; + uint _worker_id; ++ HeapRegionClaimer* _hrclaimer; + + DirtyCardQueue _dcq; + UpdateRSetDeferred _update_rset_cl; + + public: + RemoveSelfForwardPtrHRClosure(G1CollectedHeap* g1h, +- uint worker_id) : ++ uint worker_id, HeapRegionClaimer* hrclaimer) : + _g1h(g1h), _dcq(&g1h->dirty_card_queue_set()), _update_rset_cl(g1h, &_dcq), +- _worker_id(worker_id), _cm(_g1h->concurrent_mark()) { ++ _worker_id(worker_id), _hrclaimer(hrclaimer), _cm(_g1h->concurrent_mark()) { + } + + bool doHeapRegion(HeapRegion *hr) { +@@ -195,7 +196,7 @@ public: + assert(!hr->isHumongous(), "sanity"); + assert(hr->in_collection_set(), "bad CS"); + +- if (hr->claimHeapRegion(HeapRegion::ParEvacFailureClaimValue)) { ++ if (_hrclaimer->claim_region(hr->hrm_index())) { + if (hr->evacuation_failed()) { + RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, &_update_rset_cl, + during_initial_mark, +@@ -233,14 +234,16 @@ public: + class G1ParRemoveSelfForwardPtrsTask: public AbstractGangTask { + protected: + G1CollectedHeap* _g1h; ++ HeapRegionClaimer _hrclaimer; + + public: + G1ParRemoveSelfForwardPtrsTask(G1CollectedHeap* g1h) : + AbstractGangTask("G1 Remove Self-forwarding Pointers"), +- _g1h(g1h) { } ++ _g1h(g1h), ++ _hrclaimer(G1CollectedHeap::heap()->workers()->active_workers()) { } + + void work(uint worker_id) { +- RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, worker_id); ++ RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, worker_id, &_hrclaimer); + + HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id); + _g1h->collection_set_iterate_from(hr, &rsfp_cl); +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp +index 24115acaf..2a14b967a 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp +@@ -34,6 +34,7 @@ + #include "gc_implementation/g1/g1RootProcessor.hpp" + #include "gc_implementation/g1/g1StringDedup.hpp" + #include "gc_implementation/shared/gcHeapSummary.hpp" ++#include "gc_implementation/shared/liveRange.hpp" + #include "gc_implementation/shared/gcTimer.hpp" + #include "gc_implementation/shared/gcTrace.hpp" + #include "gc_implementation/shared/gcTraceTime.hpp" +@@ -58,9 +59,173 @@ + + class HeapRegion; + ++ ++class G1FullGCCompactionPoint : public CompactPoint { ++ HeapRegion* _current_region; ++ HeapWord* _threshold; ++ HeapWord* _compaction_top; ++ GrowableArray* _compaction_regions; ++ GrowableArrayIterator _compaction_region_iterator; ++ GrowableArray* _marked_huge_regions; ++ ++ virtual HeapRegion* next_compaction_space() { ++ HeapRegion* next = *(++_compaction_region_iterator); ++ assert(next != NULL, "Must return valid region"); ++ return next; ++ } ++ ++public: ++ G1FullGCCompactionPoint() : ++ _current_region(NULL), ++ _threshold(NULL), ++ _compaction_top(NULL), ++ _compaction_regions(new (ResourceObj::C_HEAP, mtGC) ++ GrowableArray(32/* initial size */, true, mtGC)), ++ _compaction_region_iterator(_compaction_regions->begin()), ++ _marked_huge_regions(new (ResourceObj::C_HEAP, mtGC) ++ GrowableArray(32/* initial size */, true, mtGC)) { ++ } ++ virtual ~G1FullGCCompactionPoint() { ++ delete _compaction_regions; ++ delete _marked_huge_regions; ++ } ++ ++ bool is_initialized() { ++ return _current_region != NULL; ++ } ++ ++ void initialize(HeapRegion* hr, bool init_threshold) { ++ _current_region = hr; ++ initialize_values(init_threshold); ++ } ++ ++ void initialize_values(bool init_threshold) { ++ _compaction_top = _current_region->compaction_top(); ++ if (init_threshold) { ++ _threshold = _current_region->initialize_threshold(); ++ } ++ } ++ ++ void update() { ++ if (is_initialized()) { ++ _current_region->set_compaction_top(_compaction_top); ++ } ++ } ++ ++ bool object_will_fit(size_t size) { ++ size_t space_left = pointer_delta(_current_region->end(), _compaction_top); ++ return size <= space_left; ++ } ++ ++ void switch_region() { ++ // Save compaction top in the region. ++ _current_region->set_compaction_top(_compaction_top); ++ // Get the next region and re-initialize the values. ++ _current_region = next_compaction_space(); ++ initialize_values(true); ++ } ++ ++ void forward(oop object, size_t size) { ++ assert(_current_region != NULL, "Must have been initialized"); ++ ++ // Ensure the object fit in the current region. ++ while (!object_will_fit(size)) { ++ switch_region(); ++ } ++ ++ if ((HeapWord*)object != _compaction_top) { ++ object->forward_to(oop(_compaction_top)); ++ } else { ++ object->init_mark(); ++ } ++ ++ // Update compaction values. ++ _compaction_top += size; ++ if (_compaction_top > _threshold) { ++ _threshold = _current_region->cross_threshold(_compaction_top - size, _compaction_top); ++ } ++ } ++ ++ void add(HeapRegion* hr) { ++ _compaction_regions->append(hr); ++ } ++ void add_huge(HeapRegion* hr) { ++ _marked_huge_regions->append(hr); ++ } ++ HeapRegion* current_region() { ++ return *_compaction_region_iterator; ++ } ++ const GrowableArray* regions() const { ++ return _compaction_regions; ++ } ++ const GrowableArray* huge_regions() const { ++ return _marked_huge_regions; ++ } ++ ++ HeapRegion* remove_last() { ++ return _compaction_regions->pop(); ++ } ++ ++ bool has_region() { ++ return !_compaction_regions->is_empty(); ++ } ++}; ++ ++class G1FullGCCompactionPoints : StackObj { ++private: ++ G1FullGCCompactionPoint** _cps; ++ uint _num_workers; ++ G1FullGCCompactionPoint* _serial_compaction_point; ++public: ++ G1FullGCCompactionPoints(uint num_workers) : _num_workers(num_workers) { ++ _cps = NEW_C_HEAP_ARRAY(G1FullGCCompactionPoint*, _num_workers, mtGC); ++ for (uint i = 0; i < _num_workers; i++) { ++ _cps[i] = new G1FullGCCompactionPoint(); ++ } ++ _serial_compaction_point = new G1FullGCCompactionPoint(); ++ } ++ ~G1FullGCCompactionPoints() { ++ for (uint i = 0; i < _num_workers; i++) { ++ delete _cps[i]; ++ } ++ FREE_C_HEAP_ARRAY(G1FullGCCompactionPoint*, _cps, mtGC); ++ delete _serial_compaction_point; ++ } ++ ++ G1FullGCCompactionPoint* cp_at(uint i) { return _cps[i]; } ++ uint num_workers() { return _num_workers; } ++ ++ G1FullGCCompactionPoint* serial_compaction_point() { return _serial_compaction_point; } ++}; ++ ++size_t G1RePrepareClosure::apply(oop obj) { ++ // We only re-prepare objects forwarded within the current region, so ++ // skip objects that are already forwarded to another region. ++ oop forwarded_to = obj->forwardee(); ++ ++ if (forwarded_to != NULL && !_current->is_in(forwarded_to)) { ++ return obj->size(); ++ } ++ ++ // Get size and forward. ++ size_t size = obj->size(); ++ _cp->forward(obj, size); ++ ++ return size; ++} ++ ++bool G1MarkSweep::_parallel_prepare_compact = false; ++bool G1MarkSweep::_parallel_adjust = false; ++ + void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, + bool clear_all_softrefs) { + assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); ++ uint active_workers = G1CollectedHeap::heap()->workers()->active_workers(); ++ ++ if (G1ParallelFullGC) { ++ _parallel_prepare_compact = true; ++ _parallel_adjust = true; ++ } + + SharedHeap* sh = SharedHeap::heap(); + #ifdef ASSERT +@@ -89,16 +254,20 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, + // The marking doesn't preserve the marks of biased objects. + BiasedLocking::preserve_marks(); + +- mark_sweep_phase1(marked_for_unloading, clear_all_softrefs); ++ { ++ G1FullGCCompactionPoints cps(active_workers); ++ ++ mark_sweep_phase1(marked_for_unloading, clear_all_softrefs); + +- mark_sweep_phase2(); ++ mark_sweep_phase2(&cps); + +- // Don't add any more derived pointers during phase3 +- COMPILER2_PRESENT(DerivedPointerTable::set_active(false)); ++ // Don't add any more derived pointers during phase3 ++ COMPILER2_PRESENT(DerivedPointerTable::set_active(false)); + +- mark_sweep_phase3(); ++ mark_sweep_phase3(); + +- mark_sweep_phase4(); ++ mark_sweep_phase4(&cps); ++ } + + GenMarkSweep::restore_marks(); + BiasedLocking::restore_marks(); +@@ -209,7 +378,170 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading, + } + + +-void G1MarkSweep::mark_sweep_phase2() { ++class G1ParallelPrepareCompactClosure : public HeapRegionClosure { ++protected: ++ G1CollectedHeap* _g1h; ++ ModRefBarrierSet* _mrbs; ++ G1FullGCCompactionPoint* _cp; ++ GrowableArray* _start_humongous_regions_to_be_freed; ++ ++protected: ++ virtual void prepare_for_compaction(HeapRegion* hr, HeapWord* end) { ++ if (_cp->space == NULL) { ++ _cp->space = hr; ++ _cp->threshold = hr->initialize_threshold(); ++ } ++ _cp->add(hr); ++ hr->prepare_for_compaction(_cp); ++ // Also clear the part of the card table that will be unused after compaction. ++ _mrbs->clear(MemRegion(hr->compaction_top(), end)); ++ } ++ ++public: ++ G1ParallelPrepareCompactClosure(G1FullGCCompactionPoint* cp) : ++ _g1h(G1CollectedHeap::heap()), ++ _mrbs(_g1h->g1_barrier_set()), ++ _cp(cp), ++ _start_humongous_regions_to_be_freed( ++ new (ResourceObj::C_HEAP, mtGC) GrowableArray(32, true, mtGC)) { ++ } ++ ++ ~G1ParallelPrepareCompactClosure() { ++ delete _start_humongous_regions_to_be_freed; ++ } ++ ++ const GrowableArray* start_humongous_regions_to_be_freed() const { ++ return _start_humongous_regions_to_be_freed; ++ } ++ ++ bool doHeapRegion(HeapRegion* hr) { ++ if (hr->isHumongous()) { ++ if (hr->startsHumongous()) { ++ oop obj = oop(hr->bottom()); ++ if (obj->is_gc_marked()) { ++ obj->forward_to(obj); ++ _cp->add_huge(hr); ++ } else { ++ _start_humongous_regions_to_be_freed->append(hr); ++ } ++ } else { ++ assert(hr->continuesHumongous(), "Invalid humongous."); ++ } ++ } else { ++ prepare_for_compaction(hr, hr->end()); ++ } ++ return false; ++ } ++ ++ bool freed_regions() { ++ if (_start_humongous_regions_to_be_freed->length() != 0) { ++ return true; ++ } ++ ++ if (!_cp->has_region()) { ++ return false; ++ } ++ ++ if (_cp->current_region() != _cp->regions()->top()) { ++ return true; ++ } ++ ++ return false; ++ } ++}; ++ ++class G1FullGCPrepareTask : public AbstractGangTask { ++protected: ++ HeapRegionClaimer _hrclaimer; ++ G1FullGCCompactionPoints* _cps; ++ GrowableArray* _all_start_humongous_regions_to_be_freed; ++ HeapRegionSetCount _humongous_regions_removed; ++ bool _freed_regions; ++ ++protected: ++ void free_humongous_region(HeapRegion* hr) { ++ FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep"); ++ assert(hr->startsHumongous(), ++ "Only the start of a humongous region should be freed."); ++ hr->set_containing_set(NULL); ++ _humongous_regions_removed.increment(1u, hr->capacity()); ++ G1CollectedHeap::heap()->free_humongous_region(hr, &dummy_free_list, false); ++ dummy_free_list.remove_all(); ++ } ++ ++ void update_sets() { ++ // We'll recalculate total used bytes and recreate the free list ++ // at the end of the GC, so no point in updating those values here. ++ HeapRegionSetCount empty_set; ++ G1CollectedHeap::heap()->remove_from_old_sets(empty_set, _humongous_regions_removed); ++ } ++ ++public: ++ G1FullGCPrepareTask(G1FullGCCompactionPoints* cps) : ++ AbstractGangTask("G1 Prepare Task"), ++ _hrclaimer(G1CollectedHeap::heap()->workers()->active_workers()), ++ _cps(cps), ++ _all_start_humongous_regions_to_be_freed( ++ new (ResourceObj::C_HEAP, mtGC) GrowableArray(32, true, mtGC)), ++ _humongous_regions_removed(), ++ _freed_regions(false) { } ++ ++ virtual ~G1FullGCPrepareTask() { ++ delete _all_start_humongous_regions_to_be_freed; ++ } ++ ++ void work(uint worker_id) { ++ Ticks start = Ticks::now(); ++ G1ParallelPrepareCompactClosure closure(_cps->cp_at(worker_id)); ++ G1CollectedHeap::heap()->heap_region_par_iterate_chunked(&closure, worker_id, &_hrclaimer); ++ { ++ MutexLockerEx mu(FreeHumongousRegions_lock, Mutex::_no_safepoint_check_flag); ++ _all_start_humongous_regions_to_be_freed->appendAll(closure.start_humongous_regions_to_be_freed()); ++ if (closure.freed_regions()) { ++ _freed_regions = true; ++ } ++ } ++ } ++ ++ void free_humongous_regions() { ++ for (GrowableArrayIterator it = _all_start_humongous_regions_to_be_freed->begin(); ++ it != _all_start_humongous_regions_to_be_freed->end(); ++ ++it) { ++ free_humongous_region(*it); ++ } ++ update_sets(); ++ } ++ ++ bool freed_regions() { ++ return _freed_regions; ++ } ++ ++ void prepare_serial_compaction() { ++ for (uint i = 0; i < _cps->num_workers(); i++) { ++ G1FullGCCompactionPoint* cp = _cps->cp_at(i); ++ if (cp->has_region()) { ++ _cps->serial_compaction_point()->add(cp->remove_last()); ++ } ++ } ++ ++ G1FullGCCompactionPoint* cp = _cps->serial_compaction_point(); ++ for (GrowableArrayIterator it = cp->regions()->begin(); it != cp->regions()->end(); ++it) { ++ HeapRegion* current = *it; ++ if (!cp->is_initialized()) { ++ // Initialize the compaction point. Nothing more is needed for the first heap region ++ // since it is already prepared for compaction. ++ cp->initialize(current, false); ++ } else { ++ G1RePrepareClosure re_prepare(cp, current); ++ current->set_compaction_top(current->bottom()); ++ current->apply_to_marked_objects(&re_prepare); ++ } ++ } ++ cp->update(); ++ } ++}; ++ ++void G1MarkSweep::mark_sweep_phase2(G1FullGCCompactionPoints* cps) { + // Now all live objects are marked, compute the new object addresses. + + // It is not required that we traverse spaces in the same order in +@@ -219,9 +551,21 @@ void G1MarkSweep::mark_sweep_phase2() { + GCTraceTime tm("phase 2", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id()); + GenMarkSweep::trace("2"); + +- prepare_compaction(); ++ if (!_parallel_prepare_compact) { ++ prepare_compaction(); ++ } else { ++ G1FullGCPrepareTask task(cps); ++ FlexibleWorkGang* flexible = G1CollectedHeap::heap()->workers(); ++ flexible->run_task(&task); ++ task.free_humongous_regions(); ++ ++ if (!task.freed_regions()) { ++ task.prepare_serial_compaction(); ++ } ++ } + } + ++ + class G1AdjustPointersClosure: public HeapRegionClosure { + public: + bool doHeapRegion(HeapRegion* r) { +@@ -240,6 +584,25 @@ class G1AdjustPointersClosure: public HeapRegionClosure { + } + }; + ++class G1FullGCAdjustTask : public AbstractGangTask { ++ HeapRegionClaimer _hrclaimer; ++ G1AdjustPointersClosure _adjust; ++ ++public: ++ G1FullGCAdjustTask() : ++ AbstractGangTask("G1 Adjust Task"), ++ _hrclaimer(G1CollectedHeap::heap()->workers()->active_workers()), ++ _adjust() { ++ } ++ virtual ~G1FullGCAdjustTask() { } ++ ++ void work(uint worker_id) { ++ Ticks start = Ticks::now(); ++ G1AdjustPointersClosure blk; ++ G1CollectedHeap::heap()->heap_region_par_iterate_chunked(&blk, worker_id, &_hrclaimer); ++ } ++}; ++ + void G1MarkSweep::mark_sweep_phase3() { + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + +@@ -250,7 +613,8 @@ void G1MarkSweep::mark_sweep_phase3() { + // Need cleared claim bits for the roots processing + ClassLoaderDataGraph::clear_claimed_marks(); + +- CodeBlobToOopClosure adjust_code_closure(&GenMarkSweep::adjust_pointer_closure, CodeBlobToOopClosure::FixRelocations); ++ CodeBlobToOopClosure adjust_code_closure(&GenMarkSweep::adjust_pointer_closure, ++ CodeBlobToOopClosure::FixRelocations); + { + G1RootProcessor root_processor(g1h); + root_processor.process_all_roots(&GenMarkSweep::adjust_pointer_closure, +@@ -272,13 +636,19 @@ void G1MarkSweep::mark_sweep_phase3() { + + GenMarkSweep::adjust_marks(); + +- G1AdjustPointersClosure blk; +- g1h->heap_region_iterate(&blk); ++ if (!_parallel_adjust) { ++ G1AdjustPointersClosure blk; ++ g1h->heap_region_iterate(&blk); ++ } else { ++ G1FullGCAdjustTask task; ++ FlexibleWorkGang* flexible = G1CollectedHeap::heap()->workers(); ++ flexible->run_task(&task); ++ } + } + ++ + class G1SpaceCompactClosure: public HeapRegionClosure { + public: +- G1SpaceCompactClosure() {} + + bool doHeapRegion(HeapRegion* hr) { + if (hr->isHumongous()) { +@@ -298,7 +668,60 @@ public: + } + }; + +-void G1MarkSweep::mark_sweep_phase4() { ++class G1FullGCCompactTask : public AbstractGangTask { ++ HeapRegionClaimer _hrclaimer; ++ G1FullGCCompactionPoints* _cps; ++ ++ void compact_region(HeapRegion* hr) { ++ hr->compact(); ++ ++ hr->reset_after_compaction(); ++ if (hr->used_region().is_empty()) { ++ hr->reset_bot(); ++ } ++ } ++ ++public: ++ G1FullGCCompactTask(G1FullGCCompactionPoints* cps) : ++ AbstractGangTask("G1 Compact Task"), ++ _hrclaimer(G1CollectedHeap::heap()->workers()->active_workers()), ++ _cps(cps) { ++ } ++ virtual ~G1FullGCCompactTask() { } ++ ++ void work(uint worker_id) { ++ Ticks start = Ticks::now(); ++ const GrowableArray* compaction_queue = _cps->cp_at(worker_id)->regions(); ++ for (GrowableArrayIterator it = compaction_queue->begin(); ++ it != compaction_queue->end(); ++ ++it) { ++ HeapRegion* hr = *it; ++ compact_region(hr); ++ } ++ ++ const GrowableArray* marked_huge_regions = _cps->cp_at(worker_id)->huge_regions(); ++ for (GrowableArrayIterator it = marked_huge_regions->begin(); ++ it != marked_huge_regions->end(); ++ ++it) { ++ HeapRegion* hr = *it; ++ oop obj = oop(hr->bottom()); ++ assert(obj->is_gc_marked(), "Must be"); ++ obj->init_mark(); ++ hr->reset_during_compaction(); ++ } ++ } ++ ++ void serial_compaction() { ++ const GrowableArray* compaction_queue = _cps->serial_compaction_point()->regions(); ++ for (GrowableArrayIterator it = compaction_queue->begin(); ++ it != compaction_queue->end(); ++ ++it) { ++ compact_region(*it); ++ } ++ } ++}; ++ ++void G1MarkSweep::mark_sweep_phase4(G1FullGCCompactionPoints* cps) { + // All pointers are now adjusted, move objects accordingly + + // The ValidateMarkSweep live oops tracking expects us to traverse spaces +@@ -310,72 +733,100 @@ void G1MarkSweep::mark_sweep_phase4() { + GCTraceTime tm("phase 4", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id()); + GenMarkSweep::trace("4"); + +- G1SpaceCompactClosure blk; +- g1h->heap_region_iterate(&blk); ++ if (!_parallel_prepare_compact) { ++ G1SpaceCompactClosure blk; ++ g1h->heap_region_iterate(&blk); ++ } else { ++ G1FullGCCompactTask task(cps); ++ FlexibleWorkGang* flexible = G1CollectedHeap::heap()->workers(); ++ flexible->run_task(&task); + ++ if (cps->serial_compaction_point()->has_region()) { ++ task.serial_compaction(); ++ } ++ } + } + +-void G1MarkSweep::prepare_compaction_work(G1PrepareCompactClosure* blk) { +- G1CollectedHeap* g1h = G1CollectedHeap::heap(); +- g1h->heap_region_iterate(blk); +- blk->update_sets(); +-} ++class G1PrepareCompactClosure : public HeapRegionClosure { ++protected: ++ G1CollectedHeap* _g1h; ++ ModRefBarrierSet* _mrbs; ++ CompactPoint _cp; ++ HeapRegionSetCount _humongous_regions_removed; ++ ++ virtual void prepare_for_compaction(HeapRegion* hr, HeapWord* end) { ++ // If this is the first live region that we came across which we can compact, ++ // initialize the CompactPoint. ++ if (!is_cp_initialized()) { ++ _cp.space = hr; ++ _cp.threshold = hr->initialize_threshold(); ++ } ++ prepare_for_compaction_work(&_cp, hr, end); ++ } + +-void G1PrepareCompactClosure::free_humongous_region(HeapRegion* hr) { +- HeapWord* end = hr->end(); +- FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep"); ++ void prepare_for_compaction_work(CompactPoint* cp, HeapRegion* hr, HeapWord* end) { ++ hr->prepare_for_compaction(cp); ++ // Also clear the part of the card table that will be unused after ++ // compaction. ++ _mrbs->clear(MemRegion(hr->compaction_top(), end)); ++ } + +- assert(hr->startsHumongous(), +- "Only the start of a humongous region should be freed."); ++ void free_humongous_region(HeapRegion* hr) { ++ HeapWord* end = hr->end(); ++ FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep"); + +- hr->set_containing_set(NULL); +- _humongous_regions_removed.increment(1u, hr->capacity()); ++ assert(hr->startsHumongous(), ++ "Only the start of a humongous region should be freed."); + +- _g1h->free_humongous_region(hr, &dummy_free_list, false /* par */); +- prepare_for_compaction(hr, end); +- dummy_free_list.remove_all(); +-} ++ hr->set_containing_set(NULL); ++ _humongous_regions_removed.increment(1u, hr->capacity()); + +-void G1PrepareCompactClosure::prepare_for_compaction(HeapRegion* hr, HeapWord* end) { +- // If this is the first live region that we came across which we can compact, +- // initialize the CompactPoint. +- if (!is_cp_initialized()) { +- _cp.space = hr; +- _cp.threshold = hr->initialize_threshold(); ++ _g1h->free_humongous_region(hr, &dummy_free_list, false /* par */); ++ prepare_for_compaction(hr, end); ++ dummy_free_list.remove_all(); + } +- prepare_for_compaction_work(&_cp, hr, end); +-} +- +-void G1PrepareCompactClosure::prepare_for_compaction_work(CompactPoint* cp, +- HeapRegion* hr, +- HeapWord* end) { +- hr->prepare_for_compaction(cp); +- // Also clear the part of the card table that will be unused after +- // compaction. +- _mrbs->clear(MemRegion(hr->compaction_top(), end)); +-} + +-void G1PrepareCompactClosure::update_sets() { +- // We'll recalculate total used bytes and recreate the free list +- // at the end of the GC, so no point in updating those values here. +- HeapRegionSetCount empty_set; +- _g1h->remove_from_old_sets(empty_set, _humongous_regions_removed); +-} ++ bool is_cp_initialized() const { return _cp.space != NULL; } + +-bool G1PrepareCompactClosure::doHeapRegion(HeapRegion* hr) { +- if (hr->isHumongous()) { +- if (hr->startsHumongous()) { +- oop obj = oop(hr->bottom()); +- if (obj->is_gc_marked()) { +- obj->forward_to(obj); +- } else { +- free_humongous_region(hr); ++public: ++ G1PrepareCompactClosure() : ++ _g1h(G1CollectedHeap::heap()), ++ _mrbs(_g1h->g1_barrier_set()), ++ _humongous_regions_removed() { } ++ ~G1PrepareCompactClosure() { } ++ ++ void update_sets() { ++ // We'll recalculate total used bytes and recreate the free list ++ // at the end of the GC, so no point in updating those values here. ++ HeapRegionSetCount empty_set; ++ _g1h->remove_from_old_sets(empty_set, _humongous_regions_removed); ++ } ++ bool doHeapRegion(HeapRegion* hr) { ++ if (hr->isHumongous()) { ++ if (hr->startsHumongous()) { ++ oop obj = oop(hr->bottom()); ++ if (obj->is_gc_marked()) { ++ obj->forward_to(obj); ++ } else { ++ free_humongous_region(hr); ++ } ++ } else { ++ assert(hr->continuesHumongous(), "Invalid humongous."); + } + } else { +- assert(hr->continuesHumongous(), "Invalid humongous."); ++ prepare_for_compaction(hr, hr->end()); + } +- } else { +- prepare_for_compaction(hr, hr->end()); ++ return false; + } +- return false; ++}; ++ ++void G1MarkSweep::prepare_compaction() { ++ G1PrepareCompactClosure blk; ++ G1MarkSweep::prepare_compaction_work(&blk); ++} ++ ++void G1MarkSweep::prepare_compaction_work(G1PrepareCompactClosure* blk) { ++ G1CollectedHeap* g1h = G1CollectedHeap::heap(); ++ g1h->heap_region_iterate(blk); ++ blk->update_sets(); + } +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp +index cdde980d3..82aa6b63e 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.hpp +@@ -44,6 +44,21 @@ class ReferenceProcessor; + // + // Class unloading will only occur when a full gc is invoked. + class G1PrepareCompactClosure; ++class G1FullGCCompactionPoints; ++class G1FullGCCompactionPoint; ++ ++class G1RePrepareClosure : public StackObj { ++ G1FullGCCompactionPoint* _cp; ++ HeapRegion* _current; ++ ++ public: ++ G1RePrepareClosure(G1FullGCCompactionPoint* hrcp, ++ HeapRegion* hr) : ++ _cp(hrcp), ++ _current(hr) { } ++ ++ size_t apply(oop obj); ++}; + + class G1MarkSweep : AllStatic { + friend class VM_G1MarkSweep; +@@ -57,43 +72,25 @@ class G1MarkSweep : AllStatic { + static STWGCTimer* gc_timer() { return GenMarkSweep::_gc_timer; } + static SerialOldTracer* gc_tracer() { return GenMarkSweep::_gc_tracer; } + ++ private: ++ static bool _parallel_prepare_compact; ++ static bool _parallel_adjust; ++ + private: + + // Mark live objects + static void mark_sweep_phase1(bool& marked_for_deopt, + bool clear_all_softrefs); + // Calculate new addresses +- static void mark_sweep_phase2(); ++ static void mark_sweep_phase2(G1FullGCCompactionPoints* cps); + // Update pointers + static void mark_sweep_phase3(); + // Move objects to new positions +- static void mark_sweep_phase4(); ++ static void mark_sweep_phase4(G1FullGCCompactionPoints* cps); + + static void allocate_stacks(); + static void prepare_compaction(); + static void prepare_compaction_work(G1PrepareCompactClosure* blk); + }; + +-class G1PrepareCompactClosure : public HeapRegionClosure { +- protected: +- G1CollectedHeap* _g1h; +- ModRefBarrierSet* _mrbs; +- CompactPoint _cp; +- HeapRegionSetCount _humongous_regions_removed; +- +- virtual void prepare_for_compaction(HeapRegion* hr, HeapWord* end); +- void prepare_for_compaction_work(CompactPoint* cp, HeapRegion* hr, HeapWord* end); +- void free_humongous_region(HeapRegion* hr); +- bool is_cp_initialized() const { return _cp.space != NULL; } +- +- public: +- G1PrepareCompactClosure() : +- _g1h(G1CollectedHeap::heap()), +- _mrbs(_g1h->g1_barrier_set()), +- _humongous_regions_removed() { } +- +- void update_sets(); +- bool doHeapRegion(HeapRegion* hr); +-}; +- + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1MARKSWEEP_HPP +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep_ext.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep_ext.cpp +deleted file mode 100644 +index 006e787be..000000000 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep_ext.cpp ++++ /dev/null +@@ -1,31 +0,0 @@ +-/* +- * Copyright (c) 2001, 2014, 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 "precompiled.hpp" +-#include "gc_implementation/g1/g1MarkSweep.hpp" +- +-void G1MarkSweep::prepare_compaction() { +- G1PrepareCompactClosure blk; +- G1MarkSweep::prepare_compaction_work(&blk); +-} +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +index 471844444..b214c6b37 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +@@ -410,12 +410,9 @@ void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) { + } + + void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm, +- uint worker_num, int claim_val) { ++ uint worker_num, HeapRegionClaimer *hrclaimer) { + ScrubRSClosure scrub_cl(region_bm, card_bm); +- _g1->heap_region_par_iterate_chunked(&scrub_cl, +- worker_num, +- n_workers(), +- claim_val); ++ _g1->heap_region_par_iterate_chunked(&scrub_cl, worker_num, hrclaimer); + } + + G1TriggerClosure::G1TriggerClosure() : +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp +index 9839e86c5..4a9b286a6 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp +@@ -131,7 +131,7 @@ public: + // parallel thread id of the current thread, and "claim_val" is the + // value that should be used to claim heap regions. + void scrub_par(BitMap* region_bm, BitMap* card_bm, +- uint worker_num, int claim_val); ++ uint worker_num, HeapRegionClaimer *hrclaimer); + + // Refine the card corresponding to "card_ptr". + // If check_for_refs_into_cset is true, a true result is returned +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +index db7ddeced..ee7f14278 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +@@ -359,6 +359,9 @@ + experimental(uintx, G1UncommitDelay, 50, \ + "Starup delay in seconds for periodic uncommit.") \ + \ ++ product(bool, G1ParallelFullGC, false, \ ++ "Enable Parallel Full GC for G1") \ ++ \ + + G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG) + +diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +index 131cdeacd..9b9afa335 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +@@ -28,6 +28,7 @@ + #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" + #include "gc_implementation/g1/g1NUMA.hpp" + #include "gc_implementation/g1/g1OopClosures.inline.hpp" ++#include "gc_implementation/g1/g1MarkSweep.hpp" + #include "gc_implementation/g1/heapRegion.inline.hpp" + #include "gc_implementation/g1/heapRegionBounds.inline.hpp" + #include "gc_implementation/g1/heapRegionRemSet.hpp" +@@ -180,7 +181,6 @@ void HeapRegion::hr_clear(bool par, bool clear_space, bool locked) { + } else { + hrrs->clear(); + } +- _claimed = InitialClaimValue; + } + zero_marked_bytes(); + +@@ -284,17 +284,6 @@ void HeapRegion::clear_humongous() { + _humongous_start_region = NULL; + } + +-bool HeapRegion::claimHeapRegion(jint claimValue) { +- jint current = _claimed; +- if (current != claimValue) { +- jint res = Atomic::cmpxchg(claimValue, &_claimed, current); +- if (res == current) { +- return true; +- } +- } +- return false; +-} +- + HeapRegion::HeapRegion(uint hrm_index, + G1BlockOffsetSharedArray* sharedOffsetArray, + MemRegion mr) : +@@ -304,7 +293,7 @@ HeapRegion::HeapRegion(uint hrm_index, + _humongous_start_region(NULL), + _in_collection_set(false), + _next_in_special_set(NULL), _orig_end(NULL), +- _claimed(InitialClaimValue), _evacuation_failed(false), ++ _evacuation_failed(false), + _prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0), + _next_young_region(NULL), + _next_dirty_cards_region(NULL), _next(NULL), _prev(NULL), +@@ -327,7 +316,6 @@ void HeapRegion::initialize(MemRegion mr, bool clear_space, bool mangle_space) { + _in_collection_set = false; + _next_in_special_set = NULL; + _orig_end = NULL; +- _claimed = InitialClaimValue; + _evacuation_failed = false; + _prev_marked_bytes = 0; + _next_marked_bytes = 0; +@@ -1184,6 +1172,10 @@ void G1OffsetTableContigSpace::object_iterate(ObjectClosure* blk) { + } + } + ++void G1OffsetTableContigSpace::apply_to_marked_objects(G1RePrepareClosure* closure) { ++ SCAN_AND_REPREPARE(closure); ++} ++ + #define block_is_always_obj(q) true + void G1OffsetTableContigSpace::prepare_for_compaction(CompactPoint* cp) { + SCAN_AND_FORWARD(cp, top, block_is_always_obj, block_size); +diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +index bc9527a87..5d2415e84 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +@@ -52,6 +52,7 @@ class HeapRegionRemSetIterator; + class HeapRegion; + class HeapRegionSetBase; + class nmethod; ++class G1RePrepareClosure; + + #define HR_FORMAT "%u:(%s)[" PTR_FORMAT "," PTR_FORMAT "," PTR_FORMAT "]" + #define HR_FORMAT_PARAMS(_hr_) \ +@@ -152,7 +153,7 @@ class G1OffsetTableContigSpace: public CompactibleSpace { + + void object_iterate(ObjectClosure* blk); + void safe_object_iterate(ObjectClosure* blk); +- ++ void apply_to_marked_objects(G1RePrepareClosure* closure); + void set_bottom(HeapWord* value); + void set_end(HeapWord* value); + +@@ -255,9 +256,6 @@ class HeapRegion: public G1OffsetTableContigSpace { + HeapRegionSetBase* _containing_set; + #endif // ASSERT + +- // For parallel heapRegion traversal. +- jint _claimed; +- + // We use concurrent marking to determine the amount of live data + // in each heap region. + size_t _prev_marked_bytes; // Bytes known to be live via last completed marking. +@@ -281,15 +279,6 @@ class HeapRegion: public G1OffsetTableContigSpace { + // If a collection pause is in progress, this is the top at the start + // of that pause. + +- void init_top_at_mark_start() { +- assert(_prev_marked_bytes == 0 && +- _next_marked_bytes == 0, +- "Must be called after zero_marked_bytes."); +- HeapWord* bot = bottom(); +- _prev_top_at_mark_start = bot; +- _next_top_at_mark_start = bot; +- } +- + // Cached attributes used in the collection set policy information + + // The RSet length that was added to the total value +@@ -315,6 +304,15 @@ class HeapRegion: public G1OffsetTableContigSpace { + // there's clearing to be done ourselves. We also always mangle the space. + virtual void initialize(MemRegion mr, bool clear_space = false, bool mangle_space = SpaceDecorator::Mangle); + ++ void init_top_at_mark_start() { ++ assert(_prev_marked_bytes == 0 && ++ _next_marked_bytes == 0, ++ "Must be called after zero_marked_bytes."); ++ HeapWord* bot = bottom(); ++ _prev_top_at_mark_start = bot; ++ _next_top_at_mark_start = bot; ++ } ++ + static int LogOfHRGrainBytes; + static int LogOfHRGrainWords; + +@@ -337,20 +335,6 @@ class HeapRegion: public G1OffsetTableContigSpace { + // up once during initialization time. + static void setup_heap_region_size(size_t initial_heap_size, size_t max_heap_size); + +- enum ClaimValues { +- InitialClaimValue = 0, +- FinalCountClaimValue = 1, +- NoteEndClaimValue = 2, +- ScrubRemSetClaimValue = 3, +- ParVerifyClaimValue = 4, +- RebuildRSClaimValue = 5, +- ParEvacFailureClaimValue = 6, +- AggregateCountClaimValue = 7, +- VerifyCountClaimValue = 8, +- ParMarkRootClaimValue = 9, +- ParInspectClaimValue = 10 +- }; +- + // All allocated blocks are occupied by objects in a HeapRegion + bool block_is_obj(const HeapWord* p) const; + +@@ -697,12 +681,6 @@ class HeapRegion: public G1OffsetTableContigSpace { + return (HeapWord *) obj >= next_top_at_mark_start(); + } + +- // For parallel heapRegion traversal. +- bool claimHeapRegion(int claimValue); +- jint claim_value() { return _claimed; } +- // Use this carefully: only when you're sure no one is claiming... +- void set_claim_value(int claimValue) { _claimed = claimValue; } +- + // Returns the "evacuation_failed" property of the region. + bool evacuation_failed() { return _evacuation_failed; } + +diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp +index 818f66811..56e2d32df 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp +@@ -31,6 +31,36 @@ + #include "gc_implementation/g1/concurrentG1Refine.hpp" + #include "memory/allocation.hpp" + ++HeapRegionClaimer::HeapRegionClaimer(uint n_workers) : ++ _n_workers(n_workers), _n_regions(G1CollectedHeap::heap()->_hrm._allocated_heapregions_length), _claims(NULL) { ++ uint* new_claims = NEW_C_HEAP_ARRAY(uint, _n_regions, mtGC); ++ memset(new_claims, Unclaimed, sizeof(*_claims) * _n_regions); ++ _claims = new_claims; ++} ++ ++HeapRegionClaimer::~HeapRegionClaimer() { ++ if (_claims != NULL) { ++ FREE_C_HEAP_ARRAY(uint, _claims, mtGC); ++ } ++} ++ ++uint HeapRegionClaimer::offset_for_worker(uint worker_id) const { ++ assert(worker_id < _n_workers, "Invalid worker_id."); ++ return _n_regions * worker_id / _n_workers; ++} ++ ++bool HeapRegionClaimer::is_region_claimed(uint region_index) const { ++ assert(region_index < _n_regions, "Invalid index."); ++ return _claims[region_index] == Claimed; ++} ++ ++bool HeapRegionClaimer::claim_region(uint region_index) { ++ assert(region_index < _n_regions, "Invalid index."); ++ uint old_val = Atomic::cmpxchg(Claimed, &_claims[region_index], Unclaimed); ++ return old_val == Unclaimed; ++} ++ ++ + void HeapRegionManager::initialize(G1RegionToSpaceMapper* heap_storage, + G1RegionToSpaceMapper* prev_bitmap, + G1RegionToSpaceMapper* next_bitmap, +@@ -360,8 +390,8 @@ uint HeapRegionManager::start_region_for_worker(uint worker_i, uint num_workers, + return num_regions * worker_i / num_workers; + } + +-void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint num_workers, jint claim_value) const { +- const uint start_index = start_region_for_worker(worker_id, num_workers, _allocated_heapregions_length); ++void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer) const { ++ const uint start_index = hrclaimer->offset_for_worker(worker_id); + + // Every worker will actually look at all regions, skipping over regions that + // are currently not committed. +@@ -378,11 +408,11 @@ void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint + // We'll ignore "continues humongous" regions (we'll process them + // when we come across their corresponding "start humongous" + // region) and regions already claimed. +- if (r->claim_value() == claim_value || r->continuesHumongous()) { ++ if (hrclaimer->is_region_claimed(index) || r->continuesHumongous()) { + continue; + } + // OK, try to claim it +- if (!r->claimHeapRegion(claim_value)) { ++ if (!hrclaimer->claim_region(index)) { + continue; + } + // Success! +@@ -402,10 +432,10 @@ void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint + assert(chr->humongous_start_region() == r, + err_msg("Must work on humongous continuation of the original start region " + PTR_FORMAT ", but is " PTR_FORMAT, p2i(r), p2i(chr))); +- assert(chr->claim_value() != claim_value, ++ assert(!hrclaimer->is_region_claimed(ch_index), + "Must not have been claimed yet because claiming of humongous continuation first claims the start region"); + +- bool claim_result = chr->claimHeapRegion(claim_value); ++ bool claim_result = hrclaimer->claim_region(ch_index); + // We should always be able to claim it; no one else should + // be trying to claim this region. + guarantee(claim_result, "We should always be able to claim the continuesHumongous part of the humongous object"); +diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp +index a06fa4f56..25f3a223f 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp +@@ -39,6 +39,28 @@ class G1HeapRegionTable : public G1BiasedMappedArray { + virtual HeapRegion* default_value() const { return NULL; } + }; + ++class HeapRegionClaimer : public StackObj { ++ uint _n_workers; ++ uint _n_regions; ++ volatile uint* _claims; ++ static const uint Unclaimed = 0; ++ static const uint Claimed = 1; ++public: ++ HeapRegionClaimer(uint n_workers = 0); ++ ~HeapRegionClaimer(); ++ inline void set_workers(uint n_workers) { ++ assert(n_workers > 0, "Need at least one worker."); ++ _n_workers = n_workers; ++ } ++ // Calculate the starting region for given worker so ++ // that they do not all start from the same region. ++ uint offset_for_worker(uint worker_id) const; ++ // Check if region has been claimed with this HRClaimer. ++ bool is_region_claimed(uint region_index) const; ++ // Claim the given region, returns true if successfully claimed. ++ bool claim_region(uint region_index); ++}; ++ + // This class keeps track of the actual heap memory, auxiliary data + // and its metadata (i.e., HeapRegion instances) and the list of free regions. + // +@@ -68,6 +90,7 @@ class G1HeapRegionTable : public G1BiasedMappedArray { + class HeapRegionManager: public CHeapObj { + friend class VMStructs; + friend class FreeRegionList; ++ friend class HeapRegionClaimer; + + G1HeapRegionTable _regions; + +@@ -239,7 +262,7 @@ public: + // terminating the iteration early if doHeapRegion() returns true. + void iterate(HeapRegionClosure* blk) const; + +- void par_iterate(HeapRegionClosure* blk, uint worker_id, uint no_of_par_workers, jint claim_value) const; ++ void par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer) const; + + // Uncommit up to num_regions_to_remove regions that are completely free. + // Return the actual number of uncommitted regions. +diff --git a/hotspot/src/share/vm/memory/space.cpp b/hotspot/src/share/vm/memory/space.cpp +index 317384f23..ff9d1de55 100644 +--- a/hotspot/src/share/vm/memory/space.cpp ++++ b/hotspot/src/share/vm/memory/space.cpp +@@ -386,7 +386,14 @@ HeapWord* CompactibleSpace::forward(oop q, size_t size, + while (size > compaction_max_size) { + // switch to next compaction space + cp->space->set_compaction_top(compact_top); +- cp->space = cp->space->next_compaction_space(); ++ ++ CompactibleSpace* tmp = cp->next_compaction_space(); ++ if (tmp == NULL) { ++ cp->space = cp->space->next_compaction_space(); ++ } else { ++ cp->space = tmp; ++ } ++ + if (cp->space == NULL) { + cp->gen = GenCollectedHeap::heap()->prev_gen(cp->gen); + assert(cp->gen != NULL, "compaction must succeed"); +diff --git a/hotspot/src/share/vm/memory/space.hpp b/hotspot/src/share/vm/memory/space.hpp +index a4c3f9e3d..5b150c46f 100644 +--- a/hotspot/src/share/vm/memory/space.hpp ++++ b/hotspot/src/share/vm/memory/space.hpp +@@ -325,7 +325,7 @@ public: + + // A structure to represent a point at which objects are being copied + // during compaction. +-class CompactPoint : public StackObj { ++class CompactPoint : public CHeapObj { + public: + Generation* gen; + CompactibleSpace* space; +@@ -333,6 +333,8 @@ public: + + CompactPoint(Generation* g = NULL) : + gen(g), space(NULL), threshold(0) {} ++ ++ virtual CompactibleSpace* next_compaction_space() { return NULL; } + }; + + // A space that supports compaction operations. This is usually, but not +@@ -349,7 +351,7 @@ private: + + public: + CompactibleSpace() : +- _compaction_top(NULL), _next_compaction_space(NULL) {} ++ _compaction_top(NULL), _next_compaction_space(NULL), _end_of_live(NULL), _first_dead(NULL) {} + + virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space); + virtual void clear(bool mangle_space); +diff --git a/hotspot/src/share/vm/memory/space.inline.hpp b/hotspot/src/share/vm/memory/space.inline.hpp +index 007cebd16..f07eedcea 100644 +--- a/hotspot/src/share/vm/memory/space.inline.hpp ++++ b/hotspot/src/share/vm/memory/space.inline.hpp +@@ -156,6 +156,67 @@ inline HeapWord* Space::block_start(const void* p) { + cp->space->set_compaction_top(compact_top); \ + } + ++#define SCAN_AND_REPREPARE(re_prepare) { \ ++ HeapWord* q = bottom(); \ ++ HeapWord* t = _end_of_live; /* Established by "prepare_for_compaction". */ \ ++ \ ++ assert(_first_dead <= _end_of_live, "Stands to reason, no?"); \ ++ \ ++ if (q < t && _first_dead > q && \ ++ !oop(q)->is_gc_marked()) { \ ++ /* we have a chunk of the space which hasn't moved and we've \ ++ * reinitialized the mark word during the previous pass, so we can't \ ++ * use is_gc_marked for the traversal. */ \ ++ HeapWord* end = _first_dead; \ ++ \ ++ while (q < end) { \ ++ /* I originally tried to conjoin "block_start(q) == q" to the \ ++ * assertion below, but that doesn't work, because you can't \ ++ * accurately traverse previous objects to get to the current one \ ++ * after their pointers have been \ ++ * updated, until the actual compaction is done. dld, 4/00 */ \ ++ assert(block_is_obj(q), \ ++ "should be at block boundaries, and should be looking at objs"); \ ++ \ ++ /* point all the oops to the new location */ \ ++ size_t size = re_prepare->apply(oop(q)); \ ++ \ ++ q += size; \ ++ } \ ++ \ ++ if (_first_dead == t) { \ ++ q = t; \ ++ } else { \ ++ /* $$$ This is funky. Using this to read the previously written \ ++ * LiveRange. See also use below. */ \ ++ q = (HeapWord*)oop(_first_dead)->mark()->decode_pointer(); \ ++ } \ ++ } \ ++ \ ++ const intx interval = PrefetchScanIntervalInBytes; \ ++ \ ++ debug_only(HeapWord* prev_q = NULL); \ ++ while (q < t) { \ ++ /* prefetch beyond q */ \ ++ Prefetch::write(q, interval); \ ++ if (oop(q)->is_gc_marked()) { \ ++ /* q is alive */ \ ++ /* point all the oops to the new location */ \ ++ size_t size = re_prepare->apply(oop(q)); \ ++ debug_only(prev_q = q); \ ++ q += size; \ ++ } else { \ ++ /* q is not a live object, so its mark should point at the next \ ++ * live object */ \ ++ debug_only(prev_q = q); \ ++ q = (HeapWord*) oop(q)->mark()->decode_pointer(); \ ++ assert(q > prev_q, "we should be moving forward through memory"); \ ++ } \ ++ } \ ++ \ ++ assert(q == t, "just checking"); \ ++} ++ + #define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) { \ + /* adjust all the interior pointers to point at the new locations of objects \ + * Used by MarkSweep::mark_sweep_phase3() */ \ +diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp +index 2dcda097e..a96ae50eb 100644 +--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp ++++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp +@@ -127,6 +127,8 @@ Monitor* Service_lock = NULL; + Monitor* PeriodicTask_lock = NULL; + Monitor* RedefineClasses_lock = NULL; + ++Mutex* FreeHumongousRegions_lock = NULL; ++ + #ifdef INCLUDE_JFR + Mutex* JfrStacktrace_lock = NULL; + Monitor* JfrMsg_lock = NULL; +@@ -286,6 +288,8 @@ void mutex_init() { + def(PeriodicTask_lock , Monitor, nonleaf+5, true); + def(RedefineClasses_lock , Monitor, nonleaf+5, true); + ++ def(FreeHumongousRegions_lock , Mutex , nonleaf, false); ++ + #if INCLUDE_JFR + def(JfrMsg_lock , Monitor, leaf, true); + def(JfrBuffer_lock , Mutex, leaf, true); +diff --git a/hotspot/src/share/vm/runtime/mutexLocker.hpp b/hotspot/src/share/vm/runtime/mutexLocker.hpp +index ec642a24e..428c80181 100644 +--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp ++++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp +@@ -143,6 +143,8 @@ extern Monitor* Service_lock; // a lock used for service thre + extern Monitor* PeriodicTask_lock; // protects the periodic task structure + extern Monitor* RedefineClasses_lock; // locks classes from parallel redefinition + ++extern Mutex* FreeHumongousRegions_lock; // locks humongous regions from freeing in parallel ++ + #if INCLUDE_JFR + extern Mutex* JfrStacktrace_lock; // used to guard access to the JFR stacktrace table + extern Monitor* JfrMsg_lock; // protects JFR messaging +diff --git a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java +index 5b4e69477..d08d9c106 100644 +--- a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java ++++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java +@@ -45,7 +45,7 @@ class ObjectWithSomeRefs { + public ObjectWithSomeRefs other4; + } + +-class ReclaimRegionFast { ++class ReclaimRegionClearMarkBitsFast { + public static final long MAX_MILLIS_FOR_RUN = 50 * 1000; // The maximum runtime for the actual test. + + public static final int M = 1024*1024; +@@ -123,7 +123,7 @@ public class TestEagerReclaimHumongousRegionsClearMarkBits { + "-XX:ConcGCThreads=1", // Want to make marking as slow as possible. + "-XX:+IgnoreUnrecognizedVMOptions", // G1VerifyBitmaps is develop only. + "-XX:+G1VerifyBitmaps", +- ReclaimRegionFast.class.getName()); ++ ReclaimRegionClearMarkBitsFast.class.getName()); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + } +diff --git a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java +index d12e25af7..16d410fdc 100644 +--- a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java ++++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java +@@ -45,7 +45,7 @@ class RefHolder { + Object ref; + } + +-class ReclaimRegionFast { ++class ReclaimRegionWithRefsFast { + + public static final int M = 1024*1024; + +@@ -93,7 +93,7 @@ public class TestEagerReclaimHumongousRegionsWithRefs { + "-Xmx128M", + "-Xmn16M", + "-XX:+PrintGC", +- ReclaimRegionFast.class.getName()); ++ ReclaimRegionWithRefsFast.class.getName()); + + Pattern p = Pattern.compile("Full GC"); + +diff --git a/jdk/test/jdk/jfr/event/gc/detailed/ExecuteOOMApp.java b/jdk/test/jdk/jfr/event/gc/detailed/ExecuteOOMApp.java +index 03158ea00..0b0620028 100644 +--- a/jdk/test/jdk/jfr/event/gc/detailed/ExecuteOOMApp.java ++++ b/jdk/test/jdk/jfr/event/gc/detailed/ExecuteOOMApp.java +@@ -51,12 +51,12 @@ public class ExecuteOOMApp { + OutputAnalyzer out = AppExecutorHelper.executeAndRecord(settings, jfrFilename, additionalVmFlagsList.toArray(new String[0]), + OOMApp.class.getName(), String.valueOf(bytesToAllocate)); + +- if ((out.getExitValue() == 1 && out.getOutput().contains("Exception: java.lang.OutOfMemoryError"))) { ++ if ((out.getExitValue() != 0 && out.getOutput().contains("java.lang.OutOfMemoryError"))) { + return false; + } + +- out.shouldHaveExitValue(0); + System.out.println(out.getOutput()); ++ out.shouldHaveExitValue(0); + + return true; + } +diff --git a/jdk/test/jdk/jfr/event/gc/detailed/TestG1ConcurrentModeFailureEvent.java b/jdk/test/jdk/jfr/event/gc/detailed/TestG1ConcurrentModeFailureEvent.java +index ab7005500..e551facb2 100644 +--- a/jdk/test/jdk/jfr/event/gc/detailed/TestG1ConcurrentModeFailureEvent.java ++++ b/jdk/test/jdk/jfr/event/gc/detailed/TestG1ConcurrentModeFailureEvent.java +@@ -56,23 +56,27 @@ public class TestG1ConcurrentModeFailureEvent { + private final static int BYTES_TO_ALLOCATE = 1024 * 512; + + public static void main(String[] args) throws Exception { +- String[] vmFlags = {"-Xmx512m", "-Xms512m", "-XX:MaxTenuringThreshold=0", "-Xloggc:testG1GC.log", "-verbose:gc", +- "-XX:+UseG1GC", "-XX:+UnlockExperimentalVMOptions", "-XX:-UseFastUnorderedTimeStamps"}; +- +- if (!ExecuteOOMApp.execute(EVENT_SETTINGS_FILE, JFR_FILE, vmFlags, BYTES_TO_ALLOCATE)) { +- System.out.println("OOM happened in the other thread(not test thread). Skip test."); +- // Skip test, process terminates due to the OOME error in the different thread +- return; +- } ++ String[][] vmFlags = { ++ {"-Xmx512m", "-Xms512m", "-XX:MaxTenuringThreshold=0", "-Xloggc:testG1GC.log", "-verbose:gc", ++ "-XX:+UseG1GC", "-XX:+UnlockExperimentalVMOptions", "-XX:-UseFastUnorderedTimeStamps"}, ++ {"-Xmx512m", "-Xms512m", "-XX:MaxTenuringThreshold=0", "-Xloggc:testG1GC.log", "-verbose:gc", ++ "-XX:+UseG1GC", "-XX:+G1ParallelFullGC", "-XX:+UnlockExperimentalVMOptions", "-XX:-UseFastUnorderedTimeStamps"}}; ++ for (int i = 0; i < vmFlags.length; i++) { ++ if (!ExecuteOOMApp.execute(EVENT_SETTINGS_FILE, JFR_FILE, vmFlags[i], BYTES_TO_ALLOCATE)) { ++ System.out.println("OOM happened in the other thread(not test thread). Skip test."); ++ // Skip test, process terminates due to the OOME error in the different thread ++ return; ++ } + +- Optional event = RecordingFile.readAllEvents(Paths.get(JFR_FILE)).stream().findFirst(); +- if (event.isPresent()) { +- Asserts.assertEquals(EVENT_NAME, event.get().getEventType().getName(), "Wrong event type"); +- } else { +- // No event received. Check if test did trigger the event. +- boolean isEventTriggered = fileContainsString("testG1GC.log", "concurrent-mark-abort"); +- System.out.println("isEventTriggered=" +isEventTriggered); +- Asserts.assertFalse(isEventTriggered, "Event found in log, but not in JFR"); ++ Optional event = RecordingFile.readAllEvents(Paths.get(JFR_FILE)).stream().findFirst(); ++ if (event.isPresent()) { ++ Asserts.assertEquals(EVENT_NAME, event.get().getEventType().getName(), "Wrong event type"); ++ } else { ++ // No event received. Check if test did trigger the event. ++ boolean isEventTriggered = fileContainsString("testG1GC.log", "concurrent-mark-abort"); ++ System.out.println("isEventTriggered=" +isEventTriggered); ++ Asserts.assertFalse(isEventTriggered, "Event found in log, but not in JFR"); ++ } + } + } + +-- +2.22.0 + diff --git a/create-jfr-dump-file-with-pid-or-timestamp-if-specif.patch b/create-jfr-dump-file-with-pid-or-timestamp-if-specif.patch new file mode 100755 index 0000000000000000000000000000000000000000..bcb3017a517cc3cc17343d3781a36a00bc20eb26 --- /dev/null +++ b/create-jfr-dump-file-with-pid-or-timestamp-if-specif.patch @@ -0,0 +1,85 @@ +From ef5d7213507f8148ae0b3fd7f82ea4afa5695d72 Mon Sep 17 00:00:00 2001 +From: hubodao +Date: Sat, 11 Sep 2021 09:56:54 +0800 +Subject: [PATCH 13/23] create jfr dump file with pid or timestamp if specified + +Summary: : create jfr dump file with pid or timestamp if specified +LLT: NA +Patch Type: huawei +Bug url: NA +--- + hotspot/src/share/vm/jfr/dcmd/jfrDcmds.cpp | 16 ++++++++++++++-- + .../jdk/jfr/jcmd/TestJcmdDumpWithFileName.java | 16 ++++++++++++++++ + 2 files changed, 30 insertions(+), 2 deletions(-) + +diff --git a/hotspot/src/share/vm/jfr/dcmd/jfrDcmds.cpp b/hotspot/src/share/vm/jfr/dcmd/jfrDcmds.cpp +index 167405e39..9585de28c 100644 +--- a/hotspot/src/share/vm/jfr/dcmd/jfrDcmds.cpp ++++ b/hotspot/src/share/vm/jfr/dcmd/jfrDcmds.cpp +@@ -226,7 +226,13 @@ void JfrDumpFlightRecordingDCmd::execute(DCmdSource source, TRAPS) { + + jstring filepath = NULL; + if (_filename.is_set() && _filename.value() != NULL) { +- filepath = JfrJavaSupport::new_string(_filename.value(), CHECK); ++ const char* extended_path = make_log_name(_filename.value(), NULL); ++ if (extended_path != NULL) { ++ filepath = JfrJavaSupport::new_string(extended_path, CHECK); ++ FREE_C_HEAP_ARRAY(char, extended_path, mtInternal); ++ } else { ++ filepath = JfrJavaSupport::new_string(_filename.value(), CHECK); ++ } + } + + jobject maxage = NULL; +@@ -394,7 +400,13 @@ void JfrStartFlightRecordingDCmd::execute(DCmdSource source, TRAPS) { + + jstring filename = NULL; + if (_filename.is_set() && _filename.value() != NULL) { +- filename = JfrJavaSupport::new_string(_filename.value(), CHECK); ++ const char* dumpPath = make_log_name(_filename.value(), NULL); ++ if (dumpPath != NULL) { ++ filename = JfrJavaSupport::new_string(dumpPath, CHECK); ++ FREE_C_HEAP_ARRAY(char, dumpPath, mtInternal); ++ } else { ++ filename = JfrJavaSupport::new_string(_filename.value(), CHECK); ++ } + } + + jobject maxage = NULL; +diff --git a/jdk/test/jdk/jfr/jcmd/TestJcmdDumpWithFileName.java b/jdk/test/jdk/jfr/jcmd/TestJcmdDumpWithFileName.java +index 40ff35b4d..f0c39564f 100644 +--- a/jdk/test/jdk/jfr/jcmd/TestJcmdDumpWithFileName.java ++++ b/jdk/test/jdk/jfr/jcmd/TestJcmdDumpWithFileName.java +@@ -48,6 +48,7 @@ public class TestJcmdDumpWithFileName { + testDumpAll(); + testDumpNamed(); + testDumpNamedWithFilename(); ++ testDumpNamedWithFilenameExpansion(); + } + + private static void testDumpAll() throws Exception { +@@ -96,6 +97,21 @@ public class TestJcmdDumpWithFileName { + } + cleanup(); + } ++ ++ private static void testDumpNamedWithFilenameExpansion() throws Exception { ++ long pid = ProcessTools.getProcessId(); ++ Path dumpPath = Paths.get("dumpPath-%p-%t.jfr").toAbsolutePath(); ++ try (Recording r = new Recording()) { ++ r.setName("testDumpNamedWithFilenameExpansion"); ++ r.setDestination(dumpPath); ++ r.start(); ++ JcmdHelper.jcmd("JFR.dump", "name=testDumpNamedWithFilenameExpansion", "filename=" + dumpPath.toString()); ++ Stream stream = Files.find(Paths.get("."), 1, (s, a) -> s.toString() ++ .matches("^.*dumpPath-pid" + pid + ".\\d{4}.\\d{2}.\\d{2}.\\d{2}.\\d{2}.\\d{2}" + ".jfr") && (a.size() > 0L)); ++ Asserts.assertTrue(stream.findAny().isPresent()); ++ } ++ cleanup(); ++ } + + private static boolean namedFile(Path dumpFile) throws IOException { + return Files.exists(dumpFile) && (Files.size(dumpFile) > 0); +-- +2.22.0 + diff --git a/enhance-the-TimeZone-s-path-solution-on-Euler.patch b/enhance-the-TimeZone-s-path-solution-on-Euler.patch new file mode 100755 index 0000000000000000000000000000000000000000..b24361f1a2ddb4c4705d452acf83e676ed401576 --- /dev/null +++ b/enhance-the-TimeZone-s-path-solution-on-Euler.patch @@ -0,0 +1,71 @@ +From f8729bde39c847f09fb0af0a43efe474a6e87f56 Mon Sep 17 00:00:00 2001 +From: s00478819 +Date: Sat, 11 Sep 2021 11:46:37 +0800 +Subject: [PATCH 15/23] enhance the TimeZone's path solution on Euler + +Summary: : enhance the TimeZone's path solution on Euler +LLT: NA +Patch Type: huawei +Bug url: NA +--- + .../solaris/native/java/util/TimeZone_md.c | 33 ++++++++++++++++++- + 1 file changed, 32 insertions(+), 1 deletion(-) + +diff --git a/jdk/src/solaris/native/java/util/TimeZone_md.c b/jdk/src/solaris/native/java/util/TimeZone_md.c +index 990e4afb2..c183a723d 100644 +--- a/jdk/src/solaris/native/java/util/TimeZone_md.c ++++ b/jdk/src/solaris/native/java/util/TimeZone_md.c +@@ -61,10 +61,12 @@ static char *isFileIdentical(char* buf, size_t size, char *pathname); + static const char *ETC_TIMEZONE_FILE = "/etc/timezone"; + static const char *ZONEINFO_DIR = "/usr/share/zoneinfo"; + static const char *DEFAULT_ZONEINFO_FILE = "/etc/localtime"; ++static const char *DEFAULT_ZONEINFO_FILE_DIRNAME = "/etc"; + #else + static const char *SYS_INIT_FILE = "/etc/default/init"; + static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo"; + static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime"; ++static const char *DEFAULT_ZONEINFO_FILE_DIRNAME = "/usr/share/lib/zoneinfo"; + #endif /* defined(__linux__) || defined(_ALLBSD_SOURCE) */ + + static const char popularZones[][4] = {"UTC", "GMT"}; +@@ -317,7 +319,36 @@ getPlatformTimeZoneID() + return NULL; + } + linkbuf[len] = '\0'; +- tz = getZoneName(linkbuf); ++ ++ /* linkbuf may be a relative symlink or has more than one characters, like '.' and '/' , ++ * which will cause the function call getZoneName return to an abnormal timeZone name. ++ * For example, linkbuf is "../usr/share/zoneinfo//Asia/Shanghai", then the call of ++ * getZoneName(linkbuf) will get "/Asia/Shanghai", not "Asia/Shanghai". ++ * So we covert it to an absolute path by adding the file's (which is define by macro ++ * DEFAULT_ZONEINFO_FILE) dirname and then call glibc's realpath API to canonicalize ++ * the path. ++ */ ++ char abslinkbuf[2 * (PATH_MAX + 1)]; ++ if (linkbuf[0] != '/') { ++ if (sprintf(abslinkbuf, "%s/%s", DEFAULT_ZONEINFO_FILE_DIRNAME, linkbuf) < 0) { ++ jio_fprintf(stderr, (const char *) "failed to generate absolute path\n"); ++ return NULL; ++ } ++ } else { ++ strncpy(abslinkbuf, linkbuf, len + 1); ++ } ++ ++ /* canonicalize the path */ ++ char resolvedpath[PATH_MAX + 1]; ++ resolvedpath[PATH_MAX] = '\0'; ++ char *path = realpath(abslinkbuf, resolvedpath); ++ if (path == NULL) { ++ jio_fprintf(stderr, (const char *) "failed to get real path, symlink is %s\n", ++ abslinkbuf); ++ return NULL; ++ } ++ ++ tz = getZoneName(resolvedpath); + if (tz != NULL) { + tz = strdup(tz); + return tz; +-- +2.22.0 + diff --git a/fix-appcds-s-option-AppCDSLockFile.patch b/fix-appcds-s-option-AppCDSLockFile.patch new file mode 100755 index 0000000000000000000000000000000000000000..37eae2257c45f2bcc66a120258c935f344c009cd --- /dev/null +++ b/fix-appcds-s-option-AppCDSLockFile.patch @@ -0,0 +1,43 @@ +From 4ea57acdd47696dd1d36c6efb1cc404b03b76aaf Mon Sep 17 00:00:00 2001 +From: zhangyipeng +Date: Mon, 13 Sep 2021 09:31:12 +0800 +Subject: [PATCH 17/23] add 007 0024-fix-appcds-s-option-AppCDSLockFile + +Summary: < JDK> : add 007 0024-fix-appcds-s-option-AppCDSLockFile +LLT: NA +Patch Type: huawei +Bug url: NA +--- + hotspot/src/share/vm/memory/filemap.cpp | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp +index 5858c9355..99b1f58d0 100644 +--- a/hotspot/src/share/vm/memory/filemap.cpp ++++ b/hotspot/src/share/vm/memory/filemap.cpp +@@ -379,16 +379,20 @@ void FileMapInfo::open_for_write() { + if (realpath(filePath, buf) == NULL) { + fail_stop("A risky filePath:%s, buf:%s, length:%d", filePath, buf, length); + } ++ // Appcds lock file's path doesn't support "%p". Check it here. ++ const char* pts = strstr(AppCDSLockFile, "%p"); ++ if (pts != NULL) { ++ fail_stop("Invalid appcds lock file path name, %s.", AppCDSLockFile); ++ } + _appcds_file_lock_path = os::strdup(AppCDSLockFile, mtInternal); + if (_appcds_file_lock_path == NULL) { + fail_stop("Failed to create appcds file lock."); + } + int lock_fd = open(_appcds_file_lock_path, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR); + if (lock_fd < 0) { +- tty->print_cr("The lock path is: %s", _appcds_file_lock_path); + tty->print_cr("Failed to create jsa file !\n Please check: \n 1. The directory exists.\n " + "2. You have the permission.\n 3. Make sure no other process using the same lock file.\n"); +- JVM_Exit(0); ++ fail_stop("Failed to create appcds lock file, the lock path is: %s.", _appcds_file_lock_path); + } + tty->print_cr("You are using file lock %s in concurrent mode", AppCDSLockFile); + } +-- +2.22.0 + diff --git a/fix-wrong-commitID-in-release-file.patch b/fix-wrong-commitID-in-release-file.patch new file mode 100755 index 0000000000000000000000000000000000000000..f4949033a8f5b024d86fcf7f779883546e71d988 --- /dev/null +++ b/fix-wrong-commitID-in-release-file.patch @@ -0,0 +1,32 @@ +From d94e836f5dc230839aacb4585dcc30575c94d785 Mon Sep 17 00:00:00 2001 +From: zhangyipeng +Date: Sat, 11 Sep 2021 15:24:54 +0800 +Subject: [PATCH 16/23] fix wrong commitID in release file + +Summary: : fix wrong commitID in release file +LLT: NA +Patch Type: huawei +Bug url: NA +--- + make/common/MakeBase.gmk | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk +index 9b7ad7024..8179139ec 100644 +--- a/make/common/MakeBase.gmk ++++ b/make/common/MakeBase.gmk +@@ -322,9 +322,10 @@ define GetSourceTips + fi; \ + done >> $@), \ + $(if $(and $(GIT), $(wildcard $(TOPDIR)/.git)), \ ++ $$($(CD) $(SRC_ROOT) ; \ + $(PRINTF) ".:git:%s%s\n" \ + "$$(git log -n1 --format=%H | cut -c1-12)" \ +- "$$(if test -n "$$(git status --porcelain)"; then printf '+'; fi)" >> $@, )) ++ "$$(if test -n "$$(git status --porcelain)"; then printf '+'; fi)" >> $@), )) + $(PRINTF) "\n" >> $@ + endef + +-- +2.22.0 + diff --git a/fix_bug_in_keypairgenerator.patch b/fix_bug_in_keypairgenerator.patch new file mode 100755 index 0000000000000000000000000000000000000000..d3e4406c49742c10a74ba2b63d87c40ab57cd71b --- /dev/null +++ b/fix_bug_in_keypairgenerator.patch @@ -0,0 +1,576 @@ +diff --git a/jdk/make/CopyFiles.gmk b/jdk/make/CopyFiles.gmk +index ad8db6e5..10d37b9e 100644 +--- a/jdk/make/CopyFiles.gmk ++++ b/jdk/make/CopyFiles.gmk +@@ -609,14 +609,16 @@ endif + + ########################################################################################## + +-ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64) ++ifeq ($(ENABLE_KAE), true) ++ ifeq ($(OPENJDK_TARGET_CPU_ARCH), aarch64) + +- KAE_CONF_PATH= $(JDK_OUTPUTDIR)/lib/ext +- $(KAE_CONF_PATH)/kaeprovider.conf: $(JDK_TOPDIR)/src/share/lib/security/kaeprovider.conf ++ KAE_CONF_PATH= $(JDK_OUTPUTDIR)/lib/ext ++ $(KAE_CONF_PATH)/kaeprovider.conf: $(JDK_TOPDIR)/src/share/lib/security/kaeprovider.conf + $(call install-file) + +- COPY_FILES += $(KAE_CONF_PATH)/kaeprovider.conf ++ COPY_FILES += $(KAE_CONF_PATH)/kaeprovider.conf + ++ endif + endif + + ########################################################################################## +diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEECDHKeyAgreement.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEECDHKeyAgreement.java +index ac05e6d5..7a9cc5cc 100644 +--- a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEECDHKeyAgreement.java ++++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEECDHKeyAgreement.java +@@ -97,7 +97,7 @@ public class KAEECDHKeyAgreement extends KeyAgreementSpi { + + curveName = KAEUtils.getCurveBySize(keyLenBits); + if (curveName == null) { +- throw new InvalidParameterException("unknown keyLenBits" + keyLenBits); ++ throw new InvalidParameterException("unknown keyLenBits " + keyLenBits); + } + if (KAEUtils.getCurveByAlias(curveName) != null) { + curveName = KAEUtils.getCurveByAlias(curveName); +diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEProvider.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEProvider.java +index 83ed8649..8ba70200 100644 +--- a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEProvider.java ++++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAEProvider.java +@@ -104,6 +104,8 @@ public class KAEProvider extends Provider { + if (needLog && "true".equalsIgnoreCase(props.getProperty("kae.log"))) { + logStart(excp); + needLog = false; // Log only once ++ } else { ++ KAEProvider.excp = null; // Ignore exception. + } + if (!"false".equalsIgnoreCase(props.getProperty("kae.md5"))) { + putMD5(); +diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_rsa.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_rsa.c +index d1aedf5f..bad16fb7 100644 +--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_rsa.c ++++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_cipher_rsa.c +@@ -47,7 +47,7 @@ static int RSACryptNotOAEPPadding(JNIEnv* env, jlong keyAddress, jint inLen, jby + int resultSize = 0; + + // get RSA +- EVP_PKEY* pkey = (EVP_PKEY*)keyAddress; ++ EVP_PKEY* pkey = (EVP_PKEY*) keyAddress; + + // rsa = pkey->rsa + RSA* rsa = EVP_PKEY_get1_RSA(pkey); +@@ -198,8 +198,8 @@ static int RSACryptOAEPPadding(JNIEnv* env, jlong keyAddress, jint inLen, jbyteA + * set rsa mgf1 md + * set rsa oaep md + */ +- if(!SetRSAPadding(env, pkeyCtx, paddingType) || !SetRSAMgf1Md(env, pkeyCtx, mgf1MdAlgoUTF) || +- !SetRSAOaepMd(env, pkeyCtx, oaepMdAlgoUTF)) { ++ if (!SetRSAPadding(env, pkeyCtx, paddingType) || !SetRSAMgf1Md(env, pkeyCtx, mgf1MdAlgoUTF) || ++ !SetRSAOaepMd(env, pkeyCtx, oaepMdAlgoUTF)) { + goto cleanup; + } + +@@ -213,7 +213,7 @@ static int RSACryptOAEPPadding(JNIEnv* env, jlong keyAddress, jint inLen, jbyteA + goto cleanup; + } + (*env)->GetByteArrayRegion(env, label, 0, labelSize, labelBytes); +- if(!SetRSAOaepLabel(env, pkeyCtx, labelBytes, labelSize)) { ++ if (!SetRSAOaepLabel(env, pkeyCtx, labelBytes, labelSize)) { + free(labelBytes); + goto cleanup; + } +@@ -434,7 +434,7 @@ JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRS + */ + JNIEXPORT jint JNICALL Java_org_openeuler_security_openssl_KAERSACipher_nativeRSAEncryptOAEPPadding(JNIEnv* env, + jclass cls, jlong keyAddress, jint inLen, jbyteArray in, jbyteArray out, +- jint paddingType,jstring oaepMdAlgo, jstring mgf1MdAlgo, jbyteArray label) { ++ jint paddingType, jstring oaepMdAlgo, jstring mgf1MdAlgo, jbyteArray label) { + return RSACryptOAEPPadding(env, keyAddress, inLen, in, out, paddingType, oaepMdAlgo, mgf1MdAlgo, label, + EVP_PKEY_encrypt_init, "EVP_PKEY_encrypt_init", + EVP_PKEY_encrypt, "EVP_PKEY_encrypt"); +diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_exception.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_exception.c +index 1d1736f5..9ccc617c 100644 +--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_exception.c ++++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_exception.c +@@ -23,7 +23,6 @@ + + #include + #include +-#include "kae_util.h" + #include "kae_log.h" + #include "kae_exception.h" + +@@ -58,6 +57,8 @@ void KAE_ThrowEvpException(JNIEnv* env, int reason, const char* msg, void (* def + case EVP_R_BAD_DECRYPT: + case EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH: + case EVP_F_EVP_PKEY_DECRYPT: ++ case EVP_R_PUBLIC_KEY_NOT_RSA: ++ case EVP_R_CTRL_NOT_IMPLEMENTED: + KAE_ThrowByName(env, "javax/crypto/BadPaddingException", msg); + break; + default: +@@ -128,4 +129,4 @@ void KAE_ThrowSignatureException(JNIEnv* env, const char* msg) { + + void KAE_ThrowClassNotFoundException(JNIEnv* env, const char* msg) { + KAE_ThrowByName(env, "java/lang/ClassNotFoundException", msg); +-} +\ No newline at end of file ++} +diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_dh.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_dh.c +index 26ce9a8e..b1c27241 100644 +--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_dh.c ++++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_dh.c +@@ -112,7 +112,7 @@ JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAEDHKeyAgreeme + + BN_bin2bn(secret, computekeyLength, computeKeyRetBn); + +- retByteArray = KAE_GetByteArrayFromBigNum(env, computeKeyRetBn, NULL); ++ retByteArray = KAE_GetByteArrayFromBigNum(env, computeKeyRetBn); + if (retByteArray == NULL) { + KAE_ThrowRuntimeException(env, "GetByteArrayFromBigNum failed in nativeComputeKey."); + goto cleanup; +diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_dh.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_dh.c +index 808a2626..54dc07ed 100644 +--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_dh.c ++++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_dh.c +@@ -97,13 +97,13 @@ JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAEDHKeyPairG + pri_key_bn = DH_get0_priv_key(dh); + pub_key_bn = DH_get0_pub_key(dh); + +- pub_key = KAE_GetByteArrayFromBigNum(env, pub_key_bn, NULL); ++ pub_key = KAE_GetByteArrayFromBigNum(env, pub_key_bn); + if (pub_key == NULL) { + KAE_ThrowOOMException(env, "PublicKey allocate failed in nativeGenerateKeyPair."); + goto cleanup; + } + +- pri_key = KAE_GetByteArrayFromBigNum(env, pri_key_bn, NULL); ++ pri_key = KAE_GetByteArrayFromBigNum(env, pri_key_bn); + if (pri_key == NULL) { + KAE_ThrowRuntimeException(env, "GetByteArrayFromBigNum failed in nativeGenerateKeyPair."); + goto cleanup; +diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_ec.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_ec.c +index 0f32674c..fbd16841 100644 +--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_ec.c ++++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_ec.c +@@ -43,7 +43,12 @@ typedef enum ECDHParamIndex { + ecdhCofactor + } ECDHParamIndex; + +-static const char* ecdhParamNames[] = {"p", "a", "b", "x", "y", "order", "cofactor"}; ++// ECDH Key index. ++typedef enum ECDHKeyIndex { ++ ecdhWX = 0, ++ ecdhWY, ++ ecdhS ++} ECDHKeyIndex; + + static void FreeECDHCurveParam(JNIEnv* env, BIGNUM* p, BIGNUM* a, BIGNUM* b, jbyteArray paramP, + jbyteArray paramA, jbyteArray paramB) +@@ -69,7 +74,7 @@ static void FreeECDHCurveParam(JNIEnv* env, BIGNUM* p, BIGNUM* a, BIGNUM* b, jby + } + + // Set p, a, b in group to params. +-static bool SetECDHCurve(JNIEnv* env, EC_GROUP* group, jobjectArray params, ECDHParamIndex ecdhParamIndex) ++static bool SetECDHCurve(JNIEnv* env, EC_GROUP* group, jobjectArray params) + { + BIGNUM* p = NULL; + BIGNUM* a = NULL; +@@ -86,25 +91,22 @@ static bool SetECDHCurve(JNIEnv* env, EC_GROUP* group, jobjectArray params, ECDH + } + + // Set p. +- const char* ecdhParamName = ecdhParamNames[ecdhParamIndex]; +- if ((paramP = KAE_GetByteArrayFromBigNum(env, p, ecdhParamName)) == NULL) { ++ if ((paramP = KAE_GetByteArrayFromBigNum(env, p)) == NULL) { + goto cleanup; + } +- (*env)->SetObjectArrayElement(env, params, ecdhParamIndex, paramP); ++ (*env)->SetObjectArrayElement(env, params, ecdhP, paramP); + + // Set a. +- ecdhParamName = ecdhParamNames[++ecdhParamIndex]; +- if ((paramA = KAE_GetByteArrayFromBigNum(env, a, ecdhParamName)) == NULL) { ++ if ((paramA = KAE_GetByteArrayFromBigNum(env, a)) == NULL) { + goto cleanup; + } +- (*env)->SetObjectArrayElement(env, params, ecdhParamIndex, paramA); ++ (*env)->SetObjectArrayElement(env, params, ecdhA, paramA); + + // Set b. +- ecdhParamName = ecdhParamNames[++ecdhParamIndex]; +- if ((paramB = KAE_GetByteArrayFromBigNum(env, b, ecdhParamName)) == NULL) { ++ if ((paramB = KAE_GetByteArrayFromBigNum(env, b)) == NULL) { + goto cleanup; + } +- (*env)->SetObjectArrayElement(env, params, ecdhParamIndex, paramB); ++ (*env)->SetObjectArrayElement(env, params, ecdhB, paramB); + FreeECDHCurveParam(env, p, a, b, paramP, paramA, paramB); + return true; + +@@ -114,7 +116,7 @@ cleanup: + } + + // Set generator(x, y) in group to params. +-static bool SetECDHPoint(JNIEnv* env, EC_GROUP* group, jobjectArray params, ECDHParamIndex ecdhParamIndex) ++static bool SetECDHPoint(JNIEnv* env, EC_GROUP* group, jobjectArray params) + { + BIGNUM* x = NULL; + BIGNUM* y = NULL; +@@ -135,18 +137,16 @@ static bool SetECDHPoint(JNIEnv* env, EC_GROUP* group, jobjectArray params, ECDH + } + + // Set x. +- const char* ecdhParamName = ecdhParamNames[ecdhParamIndex]; +- if ((paramX = KAE_GetByteArrayFromBigNum(env, x, ecdhParamName)) == NULL) { ++ if ((paramX = KAE_GetByteArrayFromBigNum(env, x)) == NULL) { + goto cleanup; + } +- (*env)->SetObjectArrayElement(env, params, ecdhParamIndex, paramX); ++ (*env)->SetObjectArrayElement(env, params, ecdhX, paramX); + + // Set y. +- ecdhParamName = ecdhParamNames[++ecdhParamIndex]; +- if ((paramY = KAE_GetByteArrayFromBigNum(env, y, ecdhParamName)) == NULL) { ++ if ((paramY = KAE_GetByteArrayFromBigNum(env, y)) == NULL) { + goto cleanup; + } +- (*env)->SetObjectArrayElement(env, params, ecdhParamIndex, paramY); ++ (*env)->SetObjectArrayElement(env, params, ecdhY, paramY); + BN_free(x); + BN_free(y); + (*env)->DeleteLocalRef(env, paramX); +@@ -170,7 +170,7 @@ cleanup: + } + + // Set order, cofactor in group to params. +-static bool SetECDHOrderAndCofactor(JNIEnv* env, EC_GROUP* group, jobjectArray params, ECDHParamIndex ecdhParamIndex) ++static bool SetECDHOrderAndCofactor(JNIEnv* env, EC_GROUP* group, jobjectArray params) + { + BIGNUM* order = NULL; + BIGNUM* cofactor = NULL; +@@ -184,21 +184,19 @@ static bool SetECDHOrderAndCofactor(JNIEnv* env, EC_GROUP* group, jobjectArray p + } + + // Set order. +- const char* ecdhParamName = ecdhParamNames[ecdhParamIndex]; +- if ((paramOrder = KAE_GetByteArrayFromBigNum(env, order, ecdhParamName)) == NULL) { ++ if ((paramOrder = KAE_GetByteArrayFromBigNum(env, order)) == NULL) { + goto cleanup; + } +- (*env)->SetObjectArrayElement(env, params, ecdhParamIndex, paramOrder); ++ (*env)->SetObjectArrayElement(env, params, ecdhOrder, paramOrder); + if (!EC_GROUP_get_cofactor(group, cofactor, NULL)) { + goto cleanup; + } + + // Set cofactor. +- ecdhParamName = ecdhParamNames[++ecdhParamIndex]; +- if ((paramCofactor = KAE_GetByteArrayFromBigNum(env, cofactor, ecdhParamName)) == NULL) { ++ if ((paramCofactor = KAE_GetByteArrayFromBigNum(env, cofactor)) == NULL) { + goto cleanup; + } +- (*env)->SetObjectArrayElement(env, params, ecdhParamIndex, paramCofactor); ++ (*env)->SetObjectArrayElement(env, params, ecdhCofactor, paramCofactor); + BN_free(order); + BN_free(cofactor); + (*env)->DeleteLocalRef(env, paramOrder); +@@ -222,7 +220,7 @@ cleanup: + } + + static void FreeECDHKeyParam(JNIEnv* env, +- BIGNUM* wX, BIGNUM* wY, jbyteArray paramWX, jbyteArray paramWY, jbyteArray paramS) ++ BIGNUM* wX, BIGNUM* wY, jbyteArray keyWX, jbyteArray keyWY, jbyteArray keyS) + { + if (wX != NULL) { + BN_free(wX); +@@ -230,28 +228,28 @@ static void FreeECDHKeyParam(JNIEnv* env, + if (wY != NULL) { + BN_free(wY); + } +- if (paramWX != NULL) { +- (*env)->DeleteLocalRef(env, paramWX); ++ if (keyWX != NULL) { ++ (*env)->DeleteLocalRef(env, keyWX); + } +- if (paramWY != NULL) { +- (*env)->DeleteLocalRef(env, paramWY); ++ if (keyWY != NULL) { ++ (*env)->DeleteLocalRef(env, keyWY); + } +- if (paramS != NULL) { +- (*env)->DeleteLocalRef(env, paramS); ++ if (keyS != NULL) { ++ (*env)->DeleteLocalRef(env, keyS); + } + } + + // Set publicKey(wX, wY) and privateKey(s) in eckey to params. + static bool SetECDHKey(JNIEnv* env, const EC_GROUP* group, jobjectArray params, +- ECDHParamIndex ecdhKeyIndex, const EC_KEY* eckey) ++ const EC_KEY* eckey) + { + BIGNUM* wX = NULL; + BIGNUM* wY = NULL; + const EC_POINT* pub = NULL; + const BIGNUM* s = NULL; +- jbyteArray paramWX = NULL; +- jbyteArray paramWY = NULL; +- jbyteArray paramS = NULL; ++ jbyteArray keyWX = NULL; ++ jbyteArray keyWY = NULL; ++ jbyteArray keyS = NULL; + if ((wX = BN_new()) == NULL || (wY = BN_new()) == NULL) { + KAE_ThrowOOMException(env, "failed to allocate array"); + goto cleanup; +@@ -266,53 +264,47 @@ static bool SetECDHKey(JNIEnv* env, const EC_GROUP* group, jobjectArray params, + } + + // Set wX. +- const char* ecdhParamName = ecdhParamNames[ecdhKeyIndex]; +- if ((paramWX = KAE_GetByteArrayFromBigNum(env, wX, ecdhParamName)) == NULL) { ++ if ((keyWX = KAE_GetByteArrayFromBigNum(env, wX)) == NULL) { + goto cleanup; + } +- (*env)->SetObjectArrayElement(env, params, ecdhKeyIndex, paramWX); ++ (*env)->SetObjectArrayElement(env, params, ecdhWX, keyWX); + + // Set wY. +- ecdhParamName = ecdhParamNames[++ecdhKeyIndex]; +- if ((paramWY = KAE_GetByteArrayFromBigNum(env, wY, ecdhParamName)) == NULL) { ++ if ((keyWY = KAE_GetByteArrayFromBigNum(env, wY)) == NULL) { + goto cleanup; + } +- (*env)->SetObjectArrayElement(env, params, ecdhKeyIndex, paramWY); ++ (*env)->SetObjectArrayElement(env, params, ecdhWY, keyWY); + + // Set s. +- ecdhParamName = ecdhParamNames[++ecdhKeyIndex]; +- if ((paramS = KAE_GetByteArrayFromBigNum(env, s, ecdhParamName)) == NULL) { ++ if ((keyS = KAE_GetByteArrayFromBigNum(env, s)) == NULL) { + goto cleanup; + } +- (*env)->SetObjectArrayElement(env, params, ecdhKeyIndex, paramS); +- FreeECDHKeyParam(env, wX, wY, paramWX, paramWY, paramS); ++ (*env)->SetObjectArrayElement(env, params, ecdhS, keyS); ++ FreeECDHKeyParam(env, wX, wY, keyWX, keyWY, keyS); + return true; + + cleanup: +- FreeECDHKeyParam(env, wX, wY, paramWX, paramWY, paramS); ++ FreeECDHKeyParam(env, wX, wY, keyWX, keyWY, keyS); + return false; + } + + // Convert EC_GROUP in openssl to byte[][] in java + static jobjectArray NewECDHParam(JNIEnv* env, EC_GROUP* group) + { +- jclass byteArrayClass = NULL; +- jobjectArray params = NULL; +- +- byteArrayClass = (*env)->FindClass(env, "[B"); +- params = (*env)->NewObjectArray(env, KAE_EC_PARAM_NUM_SIZE, byteArrayClass, NULL); ++ jclass byteArrayClass = (*env)->FindClass(env, "[B"); ++ jobjectArray params = (*env)->NewObjectArray(env, KAE_EC_PARAM_NUM_SIZE, byteArrayClass, NULL); + if (params == NULL) { + KAE_ThrowOOMException(env, "failed to allocate array"); + goto cleanup; + } + +- if (!SetECDHCurve(env, group, params, ecdhP)) { ++ if (!SetECDHCurve(env, group, params)) { + goto cleanup; + } +- if (!SetECDHPoint(env, group, params, ecdhX)) { ++ if (!SetECDHPoint(env, group, params)) { + goto cleanup; + } +- if (!SetECDHOrderAndCofactor(env, group, params, ecdhOrder)) { ++ if (!SetECDHOrderAndCofactor(env, group, params)) { + goto cleanup; + } + +@@ -332,16 +324,13 @@ cleanup: + // Convert EC_KEY in openssl to byte[][] in java + static jobjectArray NewECDHKey(JNIEnv* env, const EC_GROUP* group, const EC_KEY* eckey) + { +- jclass byteArrayClass = NULL; +- jobjectArray params = NULL; +- +- byteArrayClass = (*env)->FindClass(env, "[B"); +- params = (*env)->NewObjectArray(env, KAE_EC_KEY_NUM_SIZE, byteArrayClass, NULL); ++ jclass byteArrayClass = (*env)->FindClass(env, "[B"); ++ jobjectArray params = (*env)->NewObjectArray(env, KAE_EC_KEY_NUM_SIZE, byteArrayClass, NULL); + if (params == NULL) { + KAE_ThrowOOMException(env, "failed to allocate array"); + goto cleanup; + } +- if (!SetECDHKey(env, group, params, 0, eckey)) { ++ if (!SetECDHKey(env, group, params, eckey)) { + goto cleanup; + } + +@@ -435,6 +424,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAEECKeyPairG + JNIEnv* env, jclass cls, jstring curveName) + { + EC_GROUP* group = NULL; ++ jobjectArray ecdhParam = NULL; + + const char *curve = (*env)->GetStringUTFChars(env, curveName, 0); + KAE_TRACE("KAEECKeyPairGenerator_nativeGenerateParam(curveName = %s)", curve); +@@ -447,7 +437,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAEECKeyPairG + if ((group = EC_GROUP_new_by_curve_name(nid)) == NULL) { + goto cleanup; + } +- jobjectArray ecdhParam = NewECDHParam(env, group); ++ ecdhParam = NewECDHParam(env, group); + + if (group != NULL) { + EC_GROUP_free(group); +@@ -476,6 +466,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAEECKeyPairG + { + EC_GROUP* group = NULL; + EC_KEY* eckey = NULL; ++ jobjectArray ecdhKey = NULL; + + if ((group = GetGroupByParam(env, pArr, aArr, bArr, xArr, yArr, orderArr, cofactorInt)) == NULL) { + goto cleanup; +@@ -492,7 +483,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAEECKeyPairG + goto cleanup; + } + +- jobjectArray ecdhKey = NewECDHKey(env, group, eckey); ++ ecdhKey = NewECDHKey(env, group, eckey); + + EC_KEY_free(eckey); + EC_GROUP_free(group); +diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c +index de724593..0b23aa7d 100644 +--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c ++++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keypairgenerator_rsa.c +@@ -27,9 +27,6 @@ + #include "kae_exception.h" + #include "org_openeuler_security_openssl_KAERSAKeyPairGenerator.h" + #define KAE_RSA_PARAM_SIZE 8 +-#define SUCCESS 1 +-#define FAILED -1 +- + + // rsa param index + typedef enum RSAParamIndex { +@@ -102,15 +99,11 @@ static void ReleaseRSA(RSA* rsa) { + + /* + * Set rsa key param, follow the steps below +- * step 1. Get rsa param name +- * step 2. Get rsa param value +- * step 3. Convert paramValue (BIGNUM) to jbyteArray +- * step 4. Set the rsa param to the param array ++ * step 1. Get rsa param value ++ * step 2. Convert paramValue (BIGNUM) to jbyteArray ++ * step 3. Set the rsa param to the param array + */ + static bool SetRSAKeyParam(JNIEnv* env, RSA* rsa, jobjectArray params, RSAParamIndex rsaParamIndex) { +- // get rsa param name +- const char* rsaParamName = rsaParamNames[rsaParamIndex]; +- + // get rsa param value + const BIGNUM* rsaParamValue = GetRSAParamFunctionList[rsaParamIndex](rsa); + if (rsaParamValue == NULL) { +@@ -118,7 +111,7 @@ static bool SetRSAKeyParam(JNIEnv* env, RSA* rsa, jobjectArray params, RSAParamI + } + + // Convert paramValue to jbyteArray +- jbyteArray param = KAE_GetByteArrayFromBigNum(env, rsaParamValue, rsaParamName); ++ jbyteArray param = KAE_GetByteArrayFromBigNum(env, rsaParamValue); + if (param == NULL) { + return false; + } +@@ -156,8 +149,8 @@ static jobjectArray NewRSAKeyParams(JNIEnv* env, RSA* rsa) { + * Method: nativeGenerateKeyPair + * Signature: (I[B)[[B + */ +-JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAERSAKeyPairGenerator_nativeGenerateKeyPair +- (JNIEnv* env, jclass cls, jint keySize, jbyteArray publicExponent) { ++JNIEXPORT jobjectArray JNICALL Java_org_openeuler_security_openssl_KAERSAKeyPairGenerator_nativeGenerateKeyPair ( ++ JNIEnv* env, jclass cls, jint keySize, jbyteArray publicExponent) { + if (publicExponent == NULL) { + return NULL; + } +diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_symmetric_cipher.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_symmetric_cipher.c +index 81c7b3ef..71c28bde 100644 +--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_symmetric_cipher.c ++++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_symmetric_cipher.c +@@ -170,7 +170,7 @@ Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeInit(JNIEnv* en + } + + if (!EVP_CipherInit_ex(ctx, cipher, kaeEngine, (const unsigned char*)keyBytes, +- (const unsigned char*)ivBytes, encrypt ? 1 : 0)) { ++ (const unsigned char*)ivBytes, encrypt ? 1 : 0)) { + KAE_ThrowFromOpenssl(env, "EVP_CipherInit_ex failed", KAE_ThrowRuntimeException); + goto cleanup; + } +diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.c +index a92ba406..0e656a83 100644 +--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.c ++++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.c +@@ -77,7 +77,7 @@ void KAE_ReleaseBigNumFromByteArray(BIGNUM* bn) { + } + } + +-jbyteArray KAE_GetByteArrayFromBigNum(JNIEnv* env, const BIGNUM* bn, const char* sourceName) { ++jbyteArray KAE_GetByteArrayFromBigNum(JNIEnv* env, const BIGNUM* bn) { + if (bn == NULL) { + return NULL; + } +@@ -89,12 +89,12 @@ jbyteArray KAE_GetByteArrayFromBigNum(JNIEnv* env, const BIGNUM* bn, const char* + bnSize += 1; + jbyteArray javaBytes = (*env)->NewByteArray(env, bnSize); + if (javaBytes == NULL) { +- KAE_ThrowOOMException(env, "new byte array failed"); ++ KAE_ThrowOOMException(env, "New byte array failed."); + return NULL; + } + jbyte* bytes = (*env)->GetByteArrayElements(env, javaBytes, NULL); + if (bytes == NULL) { +- KAE_ThrowNullPointerException(env,"GetByteArrayElements failed"); ++ KAE_ThrowNullPointerException(env, "GetByteArrayElements failed."); + return NULL; + } + unsigned char* tmp = (unsigned char*) bytes; +diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.h b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.h +index fee81627..13bd5976 100644 +--- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.h ++++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_util.h +@@ -34,7 +34,7 @@ BIGNUM* KAE_GetBigNumFromByteArray(JNIEnv* env, jbyteArray byteArray); + void KAE_ReleaseBigNumFromByteArray(BIGNUM* bn); + + /* BIGNUM convert to jbyteArray */ +-jbyteArray KAE_GetByteArrayFromBigNum(JNIEnv* env, const BIGNUM* bn, const char* sourceName); ++jbyteArray KAE_GetByteArrayFromBigNum(JNIEnv* env, const BIGNUM* bn); + + void SetKaeEngine(ENGINE* engine); + +diff --git a/jdk/test/micro/org/openeuler/bench/security/openssl/DHKeyAgreementBenchMark.java b/jdk/test/micro/org/openeuler/bench/security/openssl/DHKeyAgreementBenchMark.java +index 8a9a2d5d..c204f4ce 100644 +--- a/jdk/test/micro/org/openeuler/bench/security/openssl/DHKeyAgreementBenchMark.java ++++ b/jdk/test/micro/org/openeuler/bench/security/openssl/DHKeyAgreementBenchMark.java +@@ -43,9 +43,13 @@ public class DHKeyAgreementBenchMark extends BenchmarkBase { + @Param({"512", "1024", "2048", "3072", "4096"}) + private int keySize; + +- private KeyPairGenerator aliceKpairGen, bobKpairGen, carolKpairGen; ++ private KeyPairGenerator aliceKpairGen; ++ private KeyPairGenerator bobKpairGen; ++ private KeyPairGenerator carolKpairGen; + +- private KeyPair aliceKpair, bobKpair, carolKpair; ++ private KeyPair aliceKpair; ++ private KeyPair bobKpair; ++ private KeyPair carolKpair; + + private DHParameterSpec dhSkipParamSpec; + diff --git a/openjdk-1.8.0.spec b/openjdk-1.8.0.spec index 53e16ab330600616b296895e5a97d61552bbdc6a..27464eb8caecbecd22c00cb8ccff713eaa0d9c12 100644 --- a/openjdk-1.8.0.spec +++ b/openjdk-1.8.0.spec @@ -916,7 +916,7 @@ Provides: java-%{javaver}-%{origin}-accessibility%{?1} = %{epoch}:%{version}-%{r Name: java-%{javaver}-%{origin} Version: %{javaver}.%{updatever}.%{buildver} -Release: 2 +Release: 3 # java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons # and this change was brought into RHEL-4. java-1.5.0-ibm packages # also included the epoch in their virtual provides. This created a @@ -1103,6 +1103,21 @@ Patch202: Fix-RSACipher-memory-usage.patch Patch203: fix-lock-ordering-issue-when-calling-JVMTI-GetLoaded.patch Patch204: 8069191.patch Patch205: fix_g1uncommit_ygc_expand_crash.patch +Patch206: 8167014-jdeps-failed-with-Missing-message-warn-skippen-entry.patch +Patch207: fix_bug_in_keypairgenerator.patch +Patch208: C1-assert-is_virtual-failed-type-check.patch +Patch209: 8197387-Run-the-jcmd-tool-as-the-root-user-to-access.patch +Patch210: create-jfr-dump-file-with-pid-or-timestamp-if-specif.patch +Patch211: 8268453-sun-security-pkcs12-EmptyPassword.java-fails.patch +Patch212: enhance-the-TimeZone-s-path-solution-on-Euler.patch +Patch213: fix-wrong-commitID-in-release-file.patch +Patch214: fix-appcds-s-option-AppCDSLockFile.patch +Patch215: PS-introduce-UsePSRelaxedForwardee-to-enable-using-r.patch +Patch216: Parallel-Full-GC-for-G1.patch +Patch217: 8202142-jfr-event-io-TestInstrumentation-is-unstable.patch +Patch218: 8143251-Thread-suspend-on-VM_G1IncCollectionPause-do.patch +Patch219: G1Uncommit-Introduce-G1PeriodGCNotRetry-control-whet.patch +Patch220: JDK-debug-version-crash-when-using-AppCDS.patch ############################################# # @@ -1554,6 +1569,21 @@ pushd %{top_level_dir_name} %patch203 -p1 %patch204 -p1 %patch205 -p1 +%patch206 -p1 +%patch207 -p1 +%patch208 -p1 +%patch209 -p1 +%patch210 -p1 +%patch211 -p1 +%patch212 -p1 +%patch213 -p1 +%patch214 -p1 +%patch215 -p1 +%patch216 -p1 +%patch217 -p1 +%patch218 -p1 +%patch219 -p1 +%patch220 -p1 popd # System library fixes @@ -2169,6 +2199,23 @@ require "copy_jdk_configs.lua" %endif %changelog +* Fri Sep 17 2021 kuenking111 - 1:1.8.0.302-b07.3 +- add 8167014-jdeps-failed-with-Missing-message-warn-skippen-entry.patch +- add fix_bug_in_keypairgenerator.patch +- add C1-assert-is_virtual-failed-type-check.patch +- add 8197387-Run-the-jcmd-tool-as-the-root-user-to-access.patch +- add create-jfr-dump-file-with-pid-or-timestamp-if-specif.patch +- add 8268453-sun-security-pkcs12-EmptyPassword.java-fails.patch +- add enhance-the-TimeZone-s-path-solution-on-Euler.patch +- add fix-wrong-commitID-in-release-file.patch +- add fix-appcds-s-option-AppCDSLockFile.patch +- add PS-introduce-UsePSRelaxedForwardee-to-enable-using-r.patch +- add Parallel-Full-GC-for-G1.patch +- add 8202142-jfr-event-io-TestInstrumentation-is-unstable.patch +- add 8143251-Thread-suspend-on-VM_G1IncCollectionPause-do.patch +- add G1Uncommit-Introduce-G1PeriodGCNotRetry-control-whet.patch +- add JDK-debug-version-crash-when-using-AppCDS.patch + * Fri Aug 20 2021 kuenking111 - 1:1.8.0.302-b07.2 - add fix_g1uncommit_ygc_expand_crash.patch