diff --git a/6896810-Pin.java-fails-with-OOME-during-System.out.p.patch b/6896810-Pin.java-fails-with-OOME-during-System.out.p.patch new file mode 100644 index 0000000000000000000000000000000000000000..e3f41f0642c1071839b48ad04cf2f79293befe65 --- /dev/null +++ b/6896810-Pin.java-fails-with-OOME-during-System.out.p.patch @@ -0,0 +1,26 @@ +From 5462717718cd9d3bed0d866ae47fe5ab9fdcf5e6 Mon Sep 17 00:00:00 2001 +Date: Fri, 28 Aug 2020 15:02:16 +0800 +Subject: [PATCH] 6896810: Pin.java fails with OOME during System.out.println + +Summary: : Pin.java fails with OOME during System.out.println +LLT: jdk8u/jdk/test/java/lang/ref/SoftReference/Pin.java +Bug url: https://bugs.openjdk.java.net/browse/JDK-6896810 huaweijdk/jdk8u-dev#2472 +--- + jdk/test/java/lang/ref/SoftReference/Pin.java | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/jdk/test/java/lang/ref/SoftReference/Pin.java b/jdk/test/java/lang/ref/SoftReference/Pin.java +index dbdf9be1b..38cd56da2 100644 +--- a/jdk/test/java/lang/ref/SoftReference/Pin.java ++++ b/jdk/test/java/lang/ref/SoftReference/Pin.java +@@ -76,6 +76,7 @@ public class Pin { + Thread.sleep(100); // yield, for what it's worth + } + } catch (OutOfMemoryError e) { ++ chain = null; // Free memory for further work. + System.err.println("Got OutOfMemoryError, as expected."); + } + +-- +2.12.3 + diff --git a/8048210-8056152-fix-assert-fail-for-an-InnocuousThre.patch b/8048210-8056152-fix-assert-fail-for-an-InnocuousThre.patch new file mode 100644 index 0000000000000000000000000000000000000000..a58ee5d6cb11b5d618d8ad3a2a00adb2ee748c7e --- /dev/null +++ b/8048210-8056152-fix-assert-fail-for-an-InnocuousThre.patch @@ -0,0 +1,39 @@ +From d4fc164f500d86fcec9302d9b71a830c34888680 Mon Sep 17 00:00:00 2001 +Date: Wed, 12 Aug 2020 15:26:59 +0000 +Subject: [PATCH] 8048210 8056152: fix assert fail for an InnocuousThread + +Summary: : fix assert fail for an InnocuousThread +LLT: jdk8u/jdk/test/java/rmi/transport/pinLastArguments/PinLastArguments.java +Bug url: https://bugs.openjdk.java.net/browse/JDK-8048210 https://bugs.openjdk.java.net/browse/JDK-8056152 +--- + jdk/src/share/classes/sun/misc/InnocuousThread.java | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/jdk/src/share/classes/sun/misc/InnocuousThread.java b/jdk/src/share/classes/sun/misc/InnocuousThread.java +index 3acd9424c..e585a9c0b 100644 +--- a/jdk/src/share/classes/sun/misc/InnocuousThread.java ++++ b/jdk/src/share/classes/sun/misc/InnocuousThread.java +@@ -70,6 +70,7 @@ public final class InnocuousThread extends Thread { + public InnocuousThread(Runnable target) { + super(INNOCUOUSTHREADGROUP, target, newName()); + UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC); ++ UNSAFE.putOrderedObject(this, CONTEXTCLASSLOADER, ClassLoader.getSystemClassLoader()); + eraseThreadLocals(); + } + +@@ -81,12 +82,6 @@ public final class InnocuousThread extends Thread { + } + + @Override +- public ClassLoader getContextClassLoader() { +- // always report system class loader +- return ClassLoader.getSystemClassLoader(); +- } +- +- @Override + public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) { + // silently fail + } +-- +2.12.3 + diff --git a/8160425-Vectorization-with-signalling-NaN-returns-wr.patch b/8160425-Vectorization-with-signalling-NaN-returns-wr.patch new file mode 100644 index 0000000000000000000000000000000000000000..45e07389985f2df94206b58f55fde48fdc2845f0 --- /dev/null +++ b/8160425-Vectorization-with-signalling-NaN-returns-wr.patch @@ -0,0 +1,257 @@ +From c10681e2567e34426759a73a7af8fe6809a8db09 Mon Sep 17 00:00:00 2001 +Date: Fri, 28 Aug 2020 09:51:37 +0800 +Subject: [PATCH] 8160425: Vectorization with signalling NaN returns wrong + result + +Summary: : Should not use doubles/floats for vector constants in the C code +LLT: +Bug url: https://bugs.openjdk.java.net/browse/JDK-8160425 +--- + hotspot/src/cpu/sparc/vm/sparc.ad | 10 ++- + hotspot/src/cpu/x86/vm/x86.ad | 10 ++- + hotspot/src/share/vm/asm/assembler.hpp | 9 +++ + hotspot/src/share/vm/opto/compile.cpp | 3 + + hotspot/src/share/vm/opto/compile.hpp | 9 +++ + .../test/compiler/vectorization/TestNaNVector.java | 84 ++++++++++++++++++++++ + 6 files changed, 113 insertions(+), 12 deletions(-) + create mode 100644 hotspot/test/compiler/vectorization/TestNaNVector.java + +diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad +index 20ec462a7..c8763c411 100644 +--- a/hotspot/src/cpu/sparc/vm/sparc.ad ++++ b/hotspot/src/cpu/sparc/vm/sparc.ad +@@ -720,7 +720,7 @@ intptr_t get_offset_from_base_2(const MachNode* n, const TypePtr* atype, int dis + return offset; + } + +-static inline jdouble replicate_immI(int con, int count, int width) { ++static inline jlong replicate_immI(int con, int count, int width) { + // Load a constant replicated "count" times with width "width" + assert(count*width == 8 && width <= 4, "sanity"); + int bit_width = width * 8; +@@ -729,17 +729,15 @@ static inline jdouble replicate_immI(int con, int count, int width) { + for (int i = 0; i < count - 1; i++) { + val |= (val << bit_width); + } +- jdouble dval = *((jdouble*) &val); // coerce to double type +- return dval; ++ return val; + } + +-static inline jdouble replicate_immF(float con) { ++static inline jlong replicate_immF(float con) { + // Replicate float con 2 times and pack into vector. + int val = *((int*)&con); + jlong lval = val; + lval = (lval << 32) | (lval & 0xFFFFFFFFl); +- jdouble dval = *((jdouble*) &lval); // coerce to double type +- return dval; ++ return lval; + } + + // Standard Sparc opcode form2 field breakdown +diff --git a/hotspot/src/cpu/x86/vm/x86.ad b/hotspot/src/cpu/x86/vm/x86.ad +index 36d6d96ae..48a0b95b4 100644 +--- a/hotspot/src/cpu/x86/vm/x86.ad ++++ b/hotspot/src/cpu/x86/vm/x86.ad +@@ -856,7 +856,7 @@ static int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load, + return 5+offset_size; + } + +-static inline jfloat replicate4_imm(int con, int width) { ++static inline jint replicate4_imm(int con, int width) { + // Load a constant of "width" (in bytes) and replicate it to fill 32bit. + assert(width == 1 || width == 2, "only byte or short types here"); + int bit_width = width * 8; +@@ -866,11 +866,10 @@ static inline jfloat replicate4_imm(int con, int width) { + val |= (val << bit_width); + bit_width <<= 1; + } +- jfloat fval = *((jfloat*) &val); // coerce to float type +- return fval; ++ return val; + } + +-static inline jdouble replicate8_imm(int con, int width) { ++static inline jlong replicate8_imm(int con, int width) { + // Load a constant of "width" (in bytes) and replicate it to fill 64bit. + assert(width == 1 || width == 2 || width == 4, "only byte, short or int types here"); + int bit_width = width * 8; +@@ -880,8 +879,7 @@ static inline jdouble replicate8_imm(int con, int width) { + val |= (val << bit_width); + bit_width <<= 1; + } +- jdouble dval = *((jdouble*) &val); // coerce to double type +- return dval; ++ return val; + } + + #ifndef PRODUCT +diff --git a/hotspot/src/share/vm/asm/assembler.hpp b/hotspot/src/share/vm/asm/assembler.hpp +index 889dd361d..ec72bc3a1 100644 +--- a/hotspot/src/share/vm/asm/assembler.hpp ++++ b/hotspot/src/share/vm/asm/assembler.hpp +@@ -368,6 +368,15 @@ class AbstractAssembler : public ResourceObj { + // + // We must remember the code section (insts or stubs) in c1 + // so we can reset to the proper section in end_a_const(). ++ address int_constant(jint c) { ++ CodeSection* c1 = _code_section; ++ address ptr = start_a_const(sizeof(c), sizeof(c)); ++ if (ptr != NULL) { ++ emit_int32(c); ++ end_a_const(c1); ++ } ++ return ptr; ++ } + address long_constant(jlong c) { + CodeSection* c1 = _code_section; + address ptr = start_a_const(sizeof(c), sizeof(c)); +diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp +index 8e14f1d5a..34e97286e 100644 +--- a/hotspot/src/share/vm/opto/compile.cpp ++++ b/hotspot/src/share/vm/opto/compile.cpp +@@ -3739,6 +3739,7 @@ bool Compile::Constant::operator==(const Constant& other) { + if (can_be_reused() != other.can_be_reused()) return false; + // For floating point values we compare the bit pattern. + switch (type()) { ++ case T_INT: + case T_FLOAT: return (_v._value.i == other._v._value.i); + case T_LONG: + case T_DOUBLE: return (_v._value.j == other._v._value.j); +@@ -3753,6 +3754,7 @@ bool Compile::Constant::operator==(const Constant& other) { + + static int type_to_size_in_bytes(BasicType t) { + switch (t) { ++ case T_INT: return sizeof(jint ); + case T_LONG: return sizeof(jlong ); + case T_FLOAT: return sizeof(jfloat ); + case T_DOUBLE: return sizeof(jdouble); +@@ -3821,6 +3823,7 @@ void Compile::ConstantTable::emit(CodeBuffer& cb) { + Constant con = _constants.at(i); + address constant_addr = NULL; + switch (con.type()) { ++ case T_INT: constant_addr = _masm.int_constant( con.get_jint() ); break; + case T_LONG: constant_addr = _masm.long_constant( con.get_jlong() ); break; + case T_FLOAT: constant_addr = _masm.float_constant( con.get_jfloat() ); break; + case T_DOUBLE: constant_addr = _masm.double_constant(con.get_jdouble()); break; +diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp +index e4985acc7..60da8587b 100644 +--- a/hotspot/src/share/vm/opto/compile.hpp ++++ b/hotspot/src/share/vm/opto/compile.hpp +@@ -203,6 +203,7 @@ class Compile : public Phase { + + BasicType type() const { return _type; } + ++ jint get_jint() const { return _v._value.i; } + jlong get_jlong() const { return _v._value.j; } + jfloat get_jfloat() const { return _v._value.f; } + jdouble get_jdouble() const { return _v._value.d; } +@@ -259,6 +260,14 @@ class Compile : public Phase { + Constant add(MachConstantNode* n, BasicType type, jvalue value); + Constant add(Metadata* metadata); + Constant add(MachConstantNode* n, MachOper* oper); ++ Constant add(MachConstantNode* n, jint i) { ++ jvalue value; value.i = i; ++ return add(n, T_INT, value); ++ } ++ Constant add(MachConstantNode* n, jlong j) { ++ jvalue value; value.j = j; ++ return add(n, T_LONG, value); ++ } + Constant add(MachConstantNode* n, jfloat f) { + jvalue value; value.f = f; + return add(n, T_FLOAT, value); +diff --git a/hotspot/test/compiler/vectorization/TestNaNVector.java b/hotspot/test/compiler/vectorization/TestNaNVector.java +new file mode 100644 +index 000000000..302657951 +--- /dev/null ++++ b/hotspot/test/compiler/vectorization/TestNaNVector.java +@@ -0,0 +1,84 @@ ++/* ++ * Copyright (c) 2016, 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 8160425 ++ * @summary Test vectorization with a signalling NaN. ++ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-OptimizeFill TestNaNVector ++ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-OptimizeFill -XX:MaxVectorSize=4 TestNaNVector ++ */ ++public class TestNaNVector { ++ private char[] array; ++ private static final int LEN = 1024; ++ ++ public static void main(String args[]) { ++ TestNaNVector test = new TestNaNVector(); ++ // Check double precision NaN ++ for (int i = 0; i < 10_000; ++i) { ++ test.vectorizeNaNDP(); ++ } ++ System.out.println("Checking double precision Nan"); ++ test.checkResult(0xfff7); ++ ++ // Check single precision NaN ++ for (int i = 0; i < 10_000; ++i) { ++ test.vectorizeNaNSP(); ++ } ++ System.out.println("Checking single precision Nan"); ++ test.checkResult(0xff80); ++ } ++ ++ public TestNaNVector() { ++ array = new char[LEN]; ++ } ++ ++ public void vectorizeNaNDP() { ++ // This loop will be vectorized and the array store will be replaced by ++ // a 64-bit vector store to four subsequent array elements. The vector ++ // should look like this '0xfff7fff7fff7fff7' and is read from the constant ++ // table. However, in floating point arithmetic this is a signalling NaN ++ // which may be converted to a quiet NaN when processed by the x87 FPU. ++ // If the signalling bit is set, the vector ends up in the constant table ++ // as '0xfffffff7fff7fff7' which leads to an incorrect result. ++ for (int i = 0; i < LEN; ++i) { ++ array[i] = 0xfff7; ++ } ++ } ++ ++ public void vectorizeNaNSP() { ++ // Same as above but with single precision ++ for (int i = 0; i < LEN; ++i) { ++ array[i] = 0xff80; ++ } ++ } ++ ++ public void checkResult(int expected) { ++ for (int i = 0; i < LEN; ++i) { ++ if (array[i] != expected) { ++ throw new RuntimeException("Invalid result: array[" + i + "] = " + (int)array[i] + " != " + expected); ++ } ++ } ++ } ++} ++ +-- +2.12.3 + diff --git a/8181503-Can-t-compile-hotspot-with-c-11.patch b/8181503-Can-t-compile-hotspot-with-c-11.patch new file mode 100644 index 0000000000000000000000000000000000000000..74b48a7ea95db64cd0ecbabf5830b742325bb76e --- /dev/null +++ b/8181503-Can-t-compile-hotspot-with-c-11.patch @@ -0,0 +1,69 @@ +From c36e8cdc5f1175a3f2a771194434d76324d8cdbb Mon Sep 17 00:00:00 2001 +Date: Fri, 17 Apr 2020 17:42:09 +0000 +Subject: [PATCH] 8181503: Can't compile hotspot with c++11 + +Summary: : fix c++11 compiler issues +LLT: N/A +Bug url: https://bugs.openjdk.java.net/browse/JDK-8181503 +--- + hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp | 6 +++--- + hotspot/src/share/vm/code/compiledIC.cpp | 2 +- + hotspot/src/share/vm/utilities/vmError.cpp | 2 +- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp +index 018feea1..935a16b5 100644 +--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp ++++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp +@@ -281,11 +281,11 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC + address os::current_stack_pointer() { + #if defined(__clang__) || defined(__llvm__) + register void *esp; +- __asm__("mov %%"SPELL_REG_SP", %0":"=r"(esp)); ++ __asm__("mov %%" SPELL_REG_SP ", %0":"=r"(esp)); + return (address) esp; + #elif defined(SPARC_WORKS) + register void *esp; +- __asm__("mov %%"SPELL_REG_SP", %0":"=r"(esp)); ++ __asm__("mov %%" SPELL_REG_SP ", %0":"=r"(esp)); + return (address) ((char*)esp + sizeof(long)*2); + #else + register void *esp __asm__ (SPELL_REG_SP); +@@ -368,7 +368,7 @@ frame os::get_sender_for_C_frame(frame* fr) { + intptr_t* _get_previous_fp() { + #if defined(SPARC_WORKS) || defined(__clang__) || defined(__llvm__) + register intptr_t **ebp; +- __asm__("mov %%"SPELL_REG_FP", %0":"=r"(ebp)); ++ __asm__("mov %%" SPELL_REG_FP ", %0":"=r"(ebp)); + #else + register intptr_t **ebp __asm__ (SPELL_REG_FP); + #endif +diff --git a/hotspot/src/share/vm/code/compiledIC.cpp b/hotspot/src/share/vm/code/compiledIC.cpp +index 63821c06..06794215 100644 +--- a/hotspot/src/share/vm/code/compiledIC.cpp ++++ b/hotspot/src/share/vm/code/compiledIC.cpp +@@ -222,7 +222,7 @@ bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecod + assert(bytecode == Bytecodes::_invokeinterface, ""); + int itable_index = call_info->itable_index(); + entry = VtableStubs::find_itable_stub(itable_index); +- if (entry == false) { ++ if (entry == NULL) { + return false; + } + #ifdef ASSERT +diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp +index e5aad6ff..23d495d9 100644 +--- a/hotspot/src/share/vm/utilities/vmError.cpp ++++ b/hotspot/src/share/vm/utilities/vmError.cpp +@@ -399,7 +399,7 @@ void VMError::report(outputStream* st) { + + STEP(15, "(printing type of error)") + +- switch(_id) { ++ switch(static_cast(_id)) { + case OOM_MALLOC_ERROR: + case OOM_MMAP_ERROR: + if (_size) { +-- +2.19.0 + diff --git a/8231631-sun-net-ftp-FtpURLConnectionLeak.java-fails-.patch b/8231631-sun-net-ftp-FtpURLConnectionLeak.java-fails-.patch new file mode 100644 index 0000000000000000000000000000000000000000..c6ab18eba802e9684c74556590107401c641ae6b --- /dev/null +++ b/8231631-sun-net-ftp-FtpURLConnectionLeak.java-fails-.patch @@ -0,0 +1,30 @@ +From 0a3958872fd70590976b185e086eec3f461b27c4 Mon Sep 17 00:00:00 2001 +Date: Fri, 28 Aug 2020 09:28:23 +0800 +Subject: [PATCH] 8231631: sun/net/ftp/FtpURLConnectionLeak.java fails + intermittently with NPE + +Summary: : sun/net/www/ftptest/FtpCommandHandler.java is modified to handle EOF properly +LLT: jdk8u/jdk/test/sun/net/ftp/FtpURLConnectionLeak.java +Bug url: https://bugs.openjdk.java.net/browse/JDK-8231631 #2468 +--- + jdk/test/sun/net/www/ftptest/FtpCommandHandler.java | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/jdk/test/sun/net/www/ftptest/FtpCommandHandler.java b/jdk/test/sun/net/www/ftptest/FtpCommandHandler.java +index 151b3df8e..f6c87d5a4 100644 +--- a/jdk/test/sun/net/www/ftptest/FtpCommandHandler.java ++++ b/jdk/test/sun/net/www/ftptest/FtpCommandHandler.java +@@ -458,6 +458,10 @@ public class FtpCommandHandler extends Thread { + try { + str = in.readLine(); + System.out.println("line: " + str); ++ if (str == null) { ++ System.out.println("EOF read from input"); ++ break; ++ } + buf = new StringBuffer(str); + res = parseCmd(buf); + switch (res) { +-- +2.12.3 + diff --git a/8243670-Unexpected-test-result-caused-by-C2-MergeMem.patch b/8243670-Unexpected-test-result-caused-by-C2-MergeMem.patch new file mode 100644 index 0000000000000000000000000000000000000000..6139bd60194e1bac4434d465bb20505e839eebe9 --- /dev/null +++ b/8243670-Unexpected-test-result-caused-by-C2-MergeMem.patch @@ -0,0 +1,193 @@ +From 3276b4d8d066703d3abc81e3a7815d1c03474af2 Mon Sep 17 00:00:00 2001 +Date: Wed, 19 Aug 2020 17:43:46 +0000 +Subject: [PATCH] 8243670:Unexpected test result caused by C2 + MergeMemNode::Ideal + +Summary: : +LLT: hotspot/test/compiler/c2/TestReplaceEquivPhis.java +Bug url: https://bugs.openjdk.java.net/browse/JDK-8243670 +--- + hotspot/src/share/vm/opto/cfgnode.cpp | 24 +++++++ + hotspot/src/share/vm/opto/memnode.cpp | 20 +----- + hotspot/src/share/vm/opto/type.hpp | 7 ++ + hotspot/test/compiler/c2/TestReplaceEquivPhis.java | 77 ++++++++++++++++++++++ + 4 files changed, 109 insertions(+), 19 deletions(-) + create mode 100644 hotspot/test/compiler/c2/TestReplaceEquivPhis.java + +diff --git a/hotspot/src/share/vm/opto/cfgnode.cpp b/hotspot/src/share/vm/opto/cfgnode.cpp +index dd5a5ec41..f3d223fbd 100644 +--- a/hotspot/src/share/vm/opto/cfgnode.cpp ++++ b/hotspot/src/share/vm/opto/cfgnode.cpp +@@ -1156,6 +1156,30 @@ Node *PhiNode::Identity( PhaseTransform *phase ) { + if (id != NULL) return id; + } + ++ // Looking for phis with identical inputs. If we find one that has ++ // type TypePtr::BOTTOM, replace the current phi with the bottom phi. ++ if (phase->is_IterGVN() && type() == Type::MEMORY && adr_type() != ++ TypePtr::BOTTOM && !adr_type()->is_known_instance()) { ++ uint phi_len = req(); ++ Node* phi_reg = region(); ++ for (DUIterator_Fast imax, i = phi_reg->fast_outs(imax); i < imax; i++) { ++ Node* u = phi_reg->fast_out(i); ++ if (u->is_Phi() && u->as_Phi()->type() == Type::MEMORY && ++ u->adr_type() == TypePtr::BOTTOM && u->in(0) == phi_reg && ++ u->req() == phi_len) { ++ for (uint j = 1; j < phi_len; j++) { ++ if (in(j) != u->in(j)) { ++ u = NULL; ++ break; ++ } ++ } ++ if (u != NULL) { ++ return u; ++ } ++ } ++ } ++ } ++ + return this; // No identity + } + +diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp +index 68a13dbd8..f2a2ee6a2 100644 +--- a/hotspot/src/share/vm/opto/memnode.cpp ++++ b/hotspot/src/share/vm/opto/memnode.cpp +@@ -4418,25 +4418,7 @@ Node *MergeMemNode::Ideal(PhaseGVN *phase, bool can_reshape) { + new_mem = old_mmem->memory_at(i); + } + // else preceding memory was not a MergeMem +- +- // replace equivalent phis (unfortunately, they do not GVN together) +- if (new_mem != NULL && new_mem != new_base && +- new_mem->req() == phi_len && new_mem->in(0) == phi_reg) { +- if (new_mem->is_Phi()) { +- PhiNode* phi_mem = new_mem->as_Phi(); +- for (uint i = 1; i < phi_len; i++) { +- if (phi_base->in(i) != phi_mem->in(i)) { +- phi_mem = NULL; +- break; +- } +- } +- if (phi_mem != NULL) { +- // equivalent phi nodes; revert to the def +- new_mem = new_base; +- } +- } +- } +- ++ + // maybe store down a new value + Node* new_in = new_mem; + if (new_in == new_base) new_in = empty_mem; +diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp +index a9352345e..321d79914 100644 +--- a/hotspot/src/share/vm/opto/type.hpp ++++ b/hotspot/src/share/vm/opto/type.hpp +@@ -431,6 +431,8 @@ public: + return exact_kls != NULL; + } + ++ virtual bool is_known_instance() const { return false; } ++ + private: + // support arrays + static const Type* _zero_type[T_CONFLICT+1]; +@@ -1332,6 +1334,11 @@ public: + return _ptrtype; + } + ++ bool is_known_instance() const { ++ return _ptrtype->is_known_instance(); ++ } ++ ++ + #ifndef PRODUCT + virtual void dump2( Dict &d, uint depth, outputStream *st ) const; + #endif +diff --git a/hotspot/test/compiler/c2/TestReplaceEquivPhis.java b/hotspot/test/compiler/c2/TestReplaceEquivPhis.java +new file mode 100644 +index 000000000..d4c93b390 +--- /dev/null ++++ b/hotspot/test/compiler/c2/TestReplaceEquivPhis.java +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (c) 2020, Huawei Technologies Co. Ltd. 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 8243670 ++ * @summary Unexpected test result caused by C2 MergeMemNode::Ideal ++ * ++ * @run main/othervm -Xcomp -XX:-SplitIfBlocks ++ * -XX:CompileOnly=compiler.c2.TestReplaceEquivPhis::test ++ * -XX:-BackgroundCompilation compiler.c2.TestReplaceEquivPhis ++ */ ++ ++package compiler.c2; ++ ++public class TestReplaceEquivPhis { ++ ++ public static final int N = 400; ++ public static volatile int instanceCount = 0; ++ public int iFld = 0; ++ public static int iArrFld[] = new int[N]; ++ ++ public int test() { ++ int v = 0; ++ boolean bArr[] = new boolean[N]; ++ ++ for (int i = 1; i < 344; i++) { ++ iFld = i; ++ for (int j = 2; j <177 ; j++) { ++ v = iFld; ++ iFld = TestReplaceEquivPhis.instanceCount; ++ TestReplaceEquivPhis.iArrFld[i] = 0; ++ iFld += TestReplaceEquivPhis.instanceCount; ++ TestReplaceEquivPhis.iArrFld[i] = 0; ++ bArr[j] = false; ++ TestReplaceEquivPhis.instanceCount = 1; ++ ++ for (int k = 1; k < 3; k++) { ++ // do nothing ++ } ++ } ++ } ++ return v; ++ } ++ ++ public static void main(String[] args) { ++ TestReplaceEquivPhis obj = new TestReplaceEquivPhis(); ++ for (int i = 0; i < 5; i++) { ++ int result = obj.test(); ++ if (result != 2) { ++ throw new RuntimeException("Test failed."); ++ } ++ } ++ System.out.println("Test passed."); ++ } ++ ++} +-- +2.12.3 + diff --git a/Extend-CDS-to-support-app-class-metadata-sharing.patch b/Extend-CDS-to-support-app-class-metadata-sharing.patch new file mode 100644 index 0000000000000000000000000000000000000000..a164e15ea4c6b8915a31fee41c6e48aea94c9c07 --- /dev/null +++ b/Extend-CDS-to-support-app-class-metadata-sharing.patch @@ -0,0 +1,748 @@ +diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp +index 6d62380..58d9116 100644 +--- a/hotspot/src/share/vm/classfile/classFileParser.cpp ++++ b/hotspot/src/share/vm/classfile/classFileParser.cpp +@@ -3939,7 +3939,8 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, + #if INCLUDE_CDS + if (DumpLoadedClassList != NULL && cfs->source() != NULL && classlist_file->is_open()) { + // Only dump the classes that can be stored into CDS archive +- if (SystemDictionaryShared::is_sharing_possible(loader_data)) { ++ // unless AppCDS is enabled ++ if (_host_klass == NULL && SystemDictionaryShared::is_sharing_possible(loader_data)) { + if (name != NULL) { + ResourceMark rm(THREAD); + classlist_file->print_cr("%s", name->as_C_string()); +diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp +index b9f46df..c7c0f53 100644 +--- a/hotspot/src/share/vm/classfile/classLoader.cpp ++++ b/hotspot/src/share/vm/classfile/classLoader.cpp +@@ -1203,8 +1203,8 @@ instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { + + h = context.record_result(classpath_index, e, result, THREAD); + } else { +- if (DumpSharedSpaces) { +- tty->print_cr("Preload Warning: Cannot find %s", class_name); ++ if (!UseAppCDS && DumpSharedSpaces) { ++ tty->print_cr("Preload Warning: Cannot find %s", class_name); // No need for AppCDS + } + } + +diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp +index 5c6b094..61140d3 100644 +--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp ++++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp +@@ -175,6 +175,16 @@ bool SystemDictionary::is_ext_class_loader(Handle class_loader) { + return (class_loader->klass()->name() == vmSymbols::sun_misc_Launcher_ExtClassLoader()); + } + ++/** ++ * Returns true if the passed class loader is the application class loader. ++ */ ++bool SystemDictionary::is_app_class_loader(Handle class_loader) { ++ if (class_loader.is_null()) { ++ return false; ++ } ++ return (class_loader->klass()->name() == vmSymbols::sun_misc_Launcher_AppClassLoader()); ++} ++ + // ---------------------------------------------------------------------------- + // Resolving of classes + +@@ -336,7 +346,8 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name, + // Bugs 4643874, 4715493 + // compute_hash can have a safepoint + +- ClassLoaderData* loader_data = class_loader_data(class_loader); ++ // class loader may be not registered yet, so use register_loader, which will return a valid classloaderData anyway. ++ ClassLoaderData* loader_data = register_loader(class_loader, CHECK_NULL); + unsigned int d_hash = dictionary()->compute_hash(child_name, loader_data); + int d_index = dictionary()->hash_to_index(d_hash); + unsigned int p_hash = placeholders()->compute_hash(child_name, loader_data); +@@ -526,7 +537,8 @@ instanceKlassHandle SystemDictionary::handle_parallel_super_load( + Handle protection_domain, Handle lockObject, TRAPS) { + + instanceKlassHandle nh = instanceKlassHandle(); // null Handle +- ClassLoaderData* loader_data = class_loader_data(class_loader); ++ // class loader may be not registered yet, so use register_loader, which will return a valid classloaderData anyway. ++ ClassLoaderData* loader_data = register_loader(class_loader, CHECK_NULL); + unsigned int d_hash = dictionary()->compute_hash(name, loader_data); + int d_index = dictionary()->hash_to_index(d_hash); + unsigned int p_hash = placeholders()->compute_hash(name, loader_data); +@@ -1072,6 +1084,19 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name, + return k(); + } + ++static char* convert_into_package_name(char* name) { ++ char* index = strrchr(name, '/'); ++ if (index == NULL) { ++ return NULL; ++ } else { ++ *index = '\0'; // chop to just the package name ++ while ((index = strchr(name, '/')) != NULL) { ++ *index = '.'; // replace '/' with '.' in package name ++ } ++ return name; ++ } ++} ++ + // Add a klass to the system from a stream (called by jni_DefineClass and + // JVM_DefineClass). + // Note: class_name can be NULL. In that case we do not know the name of +@@ -1125,12 +1150,10 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, + // JVM_DefineClass or jni_DefineClass unless you're the bootclassloader + ResourceMark rm(THREAD); + char* name = parsed_name->as_C_string(); +- char* index = strrchr(name, '/'); +- assert(index != NULL, "must be"); +- *index = '\0'; // chop to just the package name +- while ((index = strchr(name, '/')) != NULL) { +- *index = '.'; // replace '/' with '.' in package name +- } ++ ++ name = convert_into_package_name(name); ++ assert(name != NULL, "must be"); ++ + const char* fmt = "Prohibited package name: %s"; + size_t len = strlen(fmt) + strlen(name); + char* message = NEW_RESOURCE_ARRAY(char, len); +@@ -1217,12 +1240,62 @@ Klass* SystemDictionary::find_shared_class(Symbol* class_name) { + + instanceKlassHandle SystemDictionary::load_shared_class( + Symbol* class_name, Handle class_loader, TRAPS) { +- instanceKlassHandle ik (THREAD, find_shared_class(class_name)); +- // Make sure we only return the boot class for the NULL classloader. +- if (ik.not_null() && +- SharedClassUtil::is_shared_boot_class(ik()) && class_loader.is_null()) { +- Handle protection_domain; +- return load_shared_class(ik, class_loader, protection_domain, THREAD); ++ if (!(class_loader.is_null() || SystemDictionary::is_app_class_loader(class_loader) || ++ SystemDictionary::is_ext_class_loader(class_loader))) { ++ return instanceKlassHandle(); ++ } ++ ++ instanceKlassHandle ik (THREAD, find_shared_class(class_name)); // InstanceKlass is find with null class loader. ++ if (ik.not_null()) { ++ if (!UseAppCDS) { ++ // CDS logic ++ if (SharedClassUtil::is_shared_boot_class(ik()) && class_loader.is_null()) { ++ // CDS record boot class load index. ++ Handle protection_domain; ++ return load_shared_class(ik, class_loader, protection_domain, THREAD); ++ } ++ } else { ++ // AppCDS logic. Only use null loader only to load classes that ++ // have been dumped by null loader. For non-null class loaders, ++ // either the class loader data is not initialized (but also not ++ // null) or the same class loader is used to load previously ++ // defined class ++ bool bFound = false; ++ if (class_loader.is_null()) { ++ // condition1: Bootstrap class loader loaded ++ bFound = (ik()->class_loader_data() == NULL || ik()->class_loader_data()->is_the_null_class_loader_data()); ++ } else if (ik()->class_loader_data() != NULL) { ++ // condition2: App Class Loader ++ // condition3: ExtClass Loader ++ // Condition4: not fake class Loader, real one ++ bFound = ((ik->has_fake_loader_data_App() && SystemDictionary::is_app_class_loader(class_loader)) || ++ (ik->has_fake_loader_data_Ext() && SystemDictionary::is_ext_class_loader(class_loader)) || ++ (!ik->has_fake_loader_data() && ik()->class_loader() == class_loader())); ++ } ++ if (!bFound) { ++ return instanceKlassHandle(); ++ } ++ ++ // get protection domain for this class if not loaded by null class loader ++ if (class_loader.not_null()) { ++ ResourceMark rm(THREAD); ++ char* name = ik->name()->as_C_string(); ++ Handle klass_name = java_lang_String::create_from_str(name, CHECK_0); ++ JavaValue result(T_OBJECT); ++ ++ // ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader()); ++ JavaCalls::call_virtual(&result, ++ class_loader, ++ KlassHandle(THREAD, SystemDictionary::URLClassLoader_klass()), ++ vmSymbols::getProtectionDomainInternal_name(), ++ vmSymbols::getProtectionDomainInternal_signature(), ++ klass_name, ++ THREAD); ++ return load_shared_class(ik, class_loader, Handle(THREAD, (oop) result.get_jobject()), THREAD); ++ } else { ++ return load_shared_class(ik, class_loader, Handle(), THREAD); ++ } ++ } + } + return instanceKlassHandle(); + } +@@ -1298,6 +1371,7 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, + + if (DumpLoadedClassList != NULL && classlist_file->is_open()) { + // Only dump the classes that can be stored into CDS archive ++ // unless AppCDS is enabled + if (SystemDictionaryShared::is_sharing_possible(loader_data)) { + ResourceMark rm(THREAD); + classlist_file->print_cr("%s", ik->name()->as_C_string()); +@@ -1308,6 +1382,32 @@ instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik, + // notify a class loaded from shared object + ClassLoadingService::notify_class_loaded(InstanceKlass::cast(ik()), + true /* shared class */); ++ ++ // register package for this class, if necessary ++ if (UseAppCDS && class_loader.not_null()) { ++ ++ ResourceMark rm(THREAD); ++ char* name = ik->name()->as_C_string(); ++ name = convert_into_package_name(name); ++ if (name != NULL) { ++ // not a default package ++ Handle package_name = java_lang_String::create_from_str(name, CHECK_0); ++ // The digital 4 is used only once, indicating the parameter number of ++ // the method invoked in JavaCalls::call_virtual ++ JavaCallArguments args(4); ++ args.push_oop(class_loader); ++ args.push_oop(package_name); ++ args.push_oop(Handle()); ++ args.push_oop(Handle()); ++ JavaValue result(T_VOID); ++ JavaCalls::call_virtual(&result, ++ KlassHandle(THREAD, SystemDictionary::URLClassLoader_klass()), ++ vmSymbols::definePackageInternal_name(), ++ vmSymbols::definePackageInternal_signature(), ++ &args, ++ CHECK_0); ++ } ++ } + } + return ik; + } +@@ -2167,7 +2267,6 @@ void SystemDictionary::update_dictionary(int d_index, unsigned int d_hash, + // yet and these will be ignored. + Klass* SystemDictionary::find_constrained_instance_or_array_klass( + Symbol* class_name, Handle class_loader, TRAPS) { +- + // First see if it has been loaded directly. + // Force the protection domain to be null. (This removes protection checks.) + Handle no_protection_domain; +diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp +index 6f0b38a..cab7381 100644 +--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp ++++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp +@@ -649,6 +649,7 @@ public: + Handle class_loader, + TRAPS); + static bool is_ext_class_loader(Handle class_loader); ++ static bool is_app_class_loader(Handle class_loader); + + protected: + static Klass* find_shared_class(Symbol* class_name); +diff --git a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp +index e1adf8b..a8dbda2 100644 +--- a/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp ++++ b/hotspot/src/share/vm/classfile/systemDictionaryShared.hpp +@@ -35,13 +35,25 @@ public: + static instanceKlassHandle find_or_load_shared_class(Symbol* class_name, + Handle class_loader, + TRAPS) { ++ if (UseAppCDS) { ++ instanceKlassHandle ik = load_shared_class(class_name, class_loader, CHECK_NULL); ++ if (!ik.is_null()) { ++ instanceKlassHandle nh = instanceKlassHandle(); // null Handle ++ ik = find_or_define_instance_class(class_name, class_loader, ik, CHECK_(nh)); ++ } ++ return ik; ++ } + return instanceKlassHandle(); + } + static void roots_oops_do(OopClosure* blk) {} + static void oops_do(OopClosure* f) {} ++ + static bool is_sharing_possible(ClassLoaderData* loader_data) { + oop class_loader = loader_data->class_loader(); +- return (class_loader == NULL); ++ return (class_loader == NULL || ++ (UseAppCDS && (SystemDictionary::is_app_class_loader(class_loader) || ++ SystemDictionary::is_ext_class_loader(class_loader))) ++ ); + } + + static size_t dictionary_entry_size() { +diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp +index f72a948..6bd8dbe 100644 +--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp ++++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp +@@ -418,8 +418,8 @@ + template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \ + template(definePackageInternal_name, "definePackageInternal") \ + template(definePackageInternal_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)V") \ +- template(getProtectionDomain_name, "getProtectionDomain") \ +- template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \ ++ template(getProtectionDomainInternal_name, "getProtectionDomainInternal") \ ++ template(getProtectionDomainInternal_signature, "(Ljava/lang/String;)Ljava/security/ProtectionDomain;") \ + template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \ + template(resolved_references_name, "") \ + template(referencequeue_null_name, "NULL") \ +diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp +index 644e3b1..0f3c076 100644 +--- a/hotspot/src/share/vm/memory/filemap.cpp ++++ b/hotspot/src/share/vm/memory/filemap.cpp +@@ -344,12 +344,12 @@ bool FileMapInfo::init_from_file(int fd) { + + // Read the FileMapInfo information from the file. + bool FileMapInfo::open_for_read() { +- _full_path = Arguments::GetSharedArchivePath(); ++ _full_path = make_log_name(Arguments::GetSharedArchivePath(), NULL); + int fd = open(_full_path, O_RDONLY | O_BINARY, 0); + if (fd < 0) { + if (errno == ENOENT) { + // Not locating the shared archive is ok. +- fail_continue("Specified shared archive not found."); ++ fail_continue("Specified shared archive not found. archive file path:%s", _full_path); + } else { + fail_continue("Failed to open shared archive file (%s).", + strerror(errno)); +@@ -366,7 +366,7 @@ bool FileMapInfo::open_for_read() { + // Write the FileMapInfo information to the file. + + void FileMapInfo::open_for_write() { +- _full_path = Arguments::GetSharedArchivePath(); ++ _full_path = make_log_name(Arguments::GetSharedArchivePath(), NULL); + if (PrintSharedSpaces) { + tty->print_cr("Dumping shared data to file: "); + tty->print_cr(" %s", _full_path); +diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp +index d5826d6..f3c3c51 100644 +--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp ++++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp +@@ -677,14 +677,9 @@ void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) { + SystemDictionary::classes_do(check_one_shared_class); + } while (_check_classes_made_progress); + +- if (IgnoreUnverifiableClassesDuringDump) { +- // This is useful when running JCK or SQE tests. You should not +- // enable this when running real apps. +- SystemDictionary::remove_classes_in_error_state(); +- } else { +- tty->print_cr("Please remove the unverifiable classes from your class list and try again"); +- exit(1); +- } ++ // record error message, remove error state, and continue to dump jsa file ++ tty->print_cr("Please remove the unverifiable classes from your class list and try again"); ++ SystemDictionary::remove_classes_in_error_state(); + } + + // Copy the dependencies from C_HEAP-alloced GrowableArrays to RO-alloced +@@ -803,8 +798,12 @@ int MetaspaceShared::preload_and_dump(const char * class_list_path, + // Got a class name - load it. + TempNewSymbol class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD); + guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol."); ++ ++ Handle loader = UseAppCDS ? SystemDictionary::java_system_loader() : Handle(); + Klass* klass = SystemDictionary::resolve_or_null(class_name_symbol, +- THREAD); ++ loader, ++ Handle(), ++ THREAD); + CLEAR_PENDING_EXCEPTION; + if (klass != NULL) { + if (PrintSharedSpaces && Verbose && WizardMode) { +@@ -824,8 +823,8 @@ int MetaspaceShared::preload_and_dump(const char * class_list_path, + guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class"); + + class_count++; +- } else { +- //tty->print_cr("Preload failed: %s", class_name); ++ } else if (UseAppCDS) { ++ tty->print_cr("Preload failed: %s", class_name); + } + } + fclose(file); +diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp +index 2d2e44b..129bce6 100644 +--- a/hotspot/src/share/vm/oops/arrayKlass.cpp ++++ b/hotspot/src/share/vm/oops/arrayKlass.cpp +@@ -195,6 +195,12 @@ void ArrayKlass::remove_unshareable_info() { + Klass::remove_unshareable_info(); + // Clear the java mirror + set_component_mirror(NULL); ++ ++ if (_higher_dimension != NULL) { ++ ArrayKlass *ak = ArrayKlass::cast(higher_dimension()); ++ ak->remove_unshareable_info(); ++ } ++ _higher_dimension = NULL; + } + + void ArrayKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { +diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp +index 98a11fe..4502a01 100644 +--- a/hotspot/src/share/vm/oops/constantPool.cpp ++++ b/hotspot/src/share/vm/oops/constantPool.cpp +@@ -180,6 +180,20 @@ void ConstantPool::restore_unshareable_info(TRAPS) { + } + + void ConstantPool::remove_unshareable_info() { ++ if (UseAppCDS) { ++ if (cache() != NULL) { ++ cache()->reset(); ++ } ++ for (int i = 0; i < _length; i++) { ++ if (tag_at(i).is_klass()) { ++ Klass* resolvedKlass = resolved_klass_at(i); ++ ResourceMark rm; ++ char* name = resolvedKlass->name()->as_C_string(); ++ int len = strlen(name); ++ unresolved_klass_at_put(i, resolvedKlass->name()); ++ } ++ } ++ } + // Resolved references are not in the shared archive. + // Save the length for restoration. It is not necessarily the same length + // as reference_map.length() if invokedynamic is saved. +diff --git a/hotspot/src/share/vm/oops/cpCache.cpp b/hotspot/src/share/vm/oops/cpCache.cpp +index cda9a4e..ebcf3d6 100644 +--- a/hotspot/src/share/vm/oops/cpCache.cpp ++++ b/hotspot/src/share/vm/oops/cpCache.cpp +@@ -673,3 +673,16 @@ void ConstantPoolCache::verify_on(outputStream* st) { + // print constant pool cache entries + for (int i = 0; i < length(); i++) entry_at(i)->verify(st); + } ++ ++void ConstantPoolCache::reset() { ++ for (int i = 0; i < length(); i++) { ++ ConstantPoolCacheEntry* entry = entry_at(i); ++ int cp_index = entry->constant_pool_index(); ++ if (!entry->is_initial_resolved_ref_index()) { ++ // constant pool cache after initialization contains ++ // placeholders fr handling invokedynamic and invokehandle - ++ // these need to be preserved and all other entries reset ++ entry->initialize_entry(cp_index); ++ } ++ } ++} +diff --git a/hotspot/src/share/vm/oops/cpCache.hpp b/hotspot/src/share/vm/oops/cpCache.hpp +index a4a6c3f..48f9bbd 100644 +--- a/hotspot/src/share/vm/oops/cpCache.hpp ++++ b/hotspot/src/share/vm/oops/cpCache.hpp +@@ -360,7 +360,14 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { + bool is_double() const { return flag_state() == dtos; } + TosState flag_state() const { assert((uint)number_of_states <= (uint)tos_state_mask+1, ""); + return (TosState)((_flags >> tos_state_shift) & tos_state_mask); } +- ++ bool is_initial_resolved_ref_index() const { ++ if (_flags == 0 && _f1 == NULL && bytecode_1() == Bytecodes::_nop && bytecode_2() == Bytecodes::_nop) { ++ return true; ++ } else { ++ return false; ++ } ++ } ++ + // Code generation support + static WordSize size() { return in_WordSize(sizeof(ConstantPoolCacheEntry) / HeapWordSize); } + static ByteSize size_in_bytes() { return in_ByteSize(sizeof(ConstantPoolCacheEntry)); } +@@ -480,6 +487,8 @@ class ConstantPoolCache: public MetaspaceObj { + void dump_cache(); + #endif // INCLUDE_JVMTI + ++ void reset(); ++ + // Deallocate - no fields to deallocate + DEBUG_ONLY(bool on_stack() { return false; }) + void deallocate_contents(ClassLoaderData* data) {} +diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp +index 6f881ac..6d67113 100644 +--- a/hotspot/src/share/vm/oops/instanceKlass.cpp ++++ b/hotspot/src/share/vm/oops/instanceKlass.cpp +@@ -2452,6 +2452,22 @@ void InstanceKlass::remove_unshareable_info() { + m->remove_unshareable_info(); + } + ++ if (UseAppCDS) { ++ if (_oop_map_cache != NULL) { ++ delete _oop_map_cache; ++ _oop_map_cache = NULL; ++ } ++ ++ JNIid::deallocate(jni_ids()); ++ set_jni_ids(NULL); ++ ++ jmethodID* jmeths = methods_jmethod_ids_acquire(); ++ if (jmeths != (jmethodID*)NULL) { ++ release_set_methods_jmethod_ids(NULL); ++ FreeHeap(jmeths); ++ } ++ } ++ + // do array classes also. + array_klasses_do(remove_unshareable_in_class); + } +diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp +index ba20471..399290f 100644 +--- a/hotspot/src/share/vm/oops/klass.cpp ++++ b/hotspot/src/share/vm/oops/klass.cpp +@@ -63,6 +63,9 @@ void Klass::set_is_cloneable() { + } + } + ++ClassLoaderData *Klass::_fake_loader_data_App = reinterpret_cast(0xFDFDFDFA); ++ClassLoaderData *Klass::_fake_loader_data_Ext = reinterpret_cast(0xFDFDFDFB); ++ + void Klass::set_name(Symbol* n) { + _name = n; + if (_name != NULL) _name->increment_refcount(); +@@ -536,8 +539,21 @@ void Klass::remove_unshareable_info() { + set_java_mirror(NULL); + set_next_link(NULL); + +- // Null out class_loader_data because we don't share that yet. +- set_class_loader_data(NULL); ++ if (!UseAppCDS) { ++ // CDS logic ++ set_class_loader_data(NULL); ++ } else if (class_loader_data() != NULL) { ++ // AppCDS logic ++ if (class_loader() == NULL) { ++ // Null out class loader data for classes loaded by bootstrap (null) loader ++ set_class_loader_data(NULL); ++ } else if(SystemDictionary::is_ext_class_loader(class_loader())) { ++ // Mark class loaded by system class loader ++ set_class_loader_data(_fake_loader_data_Ext); ++ } else { ++ set_class_loader_data(_fake_loader_data_App); ++ } ++ } + } + + void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { +@@ -545,7 +561,10 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec + // If an exception happened during CDS restore, some of these fields may already be + // set. We leave the class on the CLD list, even if incomplete so that we don't + // modify the CLD list outside a safepoint. +- if (class_loader_data() == NULL) { ++ if (class_loader_data() == NULL || has_fake_loader_data()) { ++ // CDS should not set fake loader data ++ assert(!has_fake_loader_data() || (has_fake_loader_data() && UseAppCDS), ++ "setting fake loader data possible only with AppCDS enabled"); + // Restore class_loader_data + set_class_loader_data(loader_data); + +diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp +index 428df42..cb7640c 100644 +--- a/hotspot/src/share/vm/oops/klass.hpp ++++ b/hotspot/src/share/vm/oops/klass.hpp +@@ -188,6 +188,10 @@ private: + // -1. + jshort _shared_class_path_index; + ++ // This is used only during AppCDS to mark classes that have non-null class loader ++ static ClassLoaderData* _fake_loader_data_App; ++ static ClassLoaderData* _fake_loader_data_Ext; ++ + friend class SharedClassUtil; + protected: + +@@ -202,6 +206,10 @@ protected: + enum StaticLookupMode { find_static, skip_static }; + enum PrivateLookupMode { find_private, skip_private }; + ++ bool has_fake_loader_data_App() { return class_loader_data() == _fake_loader_data_App; } ++ bool has_fake_loader_data_Ext() { return class_loader_data() == _fake_loader_data_Ext; } ++ bool has_fake_loader_data() { return (has_fake_loader_data_App() || has_fake_loader_data_Ext()); } ++ + bool is_klass() const volatile { return true; } + + // super +diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp +index f9b6bd3..a04dcac 100644 +--- a/hotspot/src/share/vm/runtime/arguments.cpp ++++ b/hotspot/src/share/vm/runtime/arguments.cpp +@@ -3020,6 +3020,23 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, + // Remaining part of option string + const char* tail; + ++ // Special handling for UseAppCDS flag - it has to enable ++ // SharedArviveFile flag no matter where it's located in the ++ // argument list (and in order to enable UseAppCDS) ++ for (int index = 0; index < args->nOptions; index++) { ++ const JavaVMOption* option = args->options + index; ++ if (match_option(option, "-XX:+UseAppCDS", &tail)) { ++ if (!process_argument("+UseAppCDS", args->ignoreUnrecognized, origin)) { ++ return JNI_EINVAL; ++ } else { ++ const char* n = "SharedArchiveFile"; ++ Flag* shared_archive_flag = Flag::find_flag(n, strlen(n), true, true); ++ shared_archive_flag->unlock_diagnostic(); ++ FLAG_SET_CMDLINE(bool, UseAppCDS, true); ++ } ++ } ++ } ++ + // iterate over arguments + for (int index = 0; index < args->nOptions; index++) { + bool is_absolute_path = false; // for -agentpath vs -agentlib +diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp +index 46bbfb4..520cc31 100644 +--- a/hotspot/src/share/vm/runtime/globals.hpp ++++ b/hotspot/src/share/vm/runtime/globals.hpp +@@ -4010,6 +4010,9 @@ class CommandLineFlags { + product(ccstr, ExtraSharedClassListFile, NULL, \ + "Extra classlist for building the CDS archive file") \ + \ ++ product(bool, UseAppCDS, false, \ ++ "Enable Application Class Data Sharing (AppCDS)") \ ++ \ + experimental(uintx, ArrayAllocatorMallocLimit, \ + SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx), \ + "Allocation less than this value will be allocated " \ +diff --git a/hotspot/src/share/vm/runtime/javaCalls.cpp b/hotspot/src/share/vm/runtime/javaCalls.cpp +index 12925a9..217b8ff 100644 +--- a/hotspot/src/share/vm/runtime/javaCalls.cpp ++++ b/hotspot/src/share/vm/runtime/javaCalls.cpp +@@ -310,7 +310,7 @@ void JavaCalls::call(JavaValue* result, methodHandle method, JavaCallArguments* + void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) { + // During dumping, Java execution environment is not fully initialized. Also, Java execution + // may cause undesirable side-effects in the class metadata. +- assert(!DumpSharedSpaces, "must not execute Java bytecodes when dumping"); ++ assert(!DumpSharedSpaces || UseAppCDS, "must not execute Java bytecodes when dumping"); + + methodHandle method = *m; + JavaThread* thread = (JavaThread*)THREAD; +diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp +index 03b6aaf..03c1098 100644 +--- a/hotspot/src/share/vm/runtime/thread.cpp ++++ b/hotspot/src/share/vm/runtime/thread.cpp +@@ -3428,6 +3428,14 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { + os::pause(); + } + ++ if (DumpSharedSpaces) { ++ // when dumping shared spaces for AppCDS we must disable bytecode ++ // rewriting as it initializes internal (cached) meta-data that ++ // would be stored in the archive but cannot be carried over to ++ // the next execution ++ RewriteBytecodes = false; ++ } ++ + #ifndef USDT2 + HS_DTRACE_PROBE(hotspot, vm__init__begin); + #else /* USDT2 */ +@@ -3554,8 +3562,8 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { + + // At this point, the Universe is initialized, but we have not executed + // any byte code. Now is a good time (the only time) to dump out the +- // internal state of the JVM for sharing. +- if (DumpSharedSpaces) { ++ // internal state of the JVM for sharing, unless AppCDS is enabled. ++ if (!UseAppCDS && DumpSharedSpaces) { + MetaspaceShared::preload_and_dump(CHECK_0); + ShouldNotReachHere(); + } +@@ -3682,6 +3690,11 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { + vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); + } + ++ if (UseAppCDS && DumpSharedSpaces) { ++ MetaspaceShared::preload_and_dump(CHECK_0); ++ ShouldNotReachHere(); ++ } ++ + #if INCLUDE_ALL_GCS + // Support for ConcurrentMarkSweep. This should be cleaned up + // and better encapsulated. The ugly nested if test would go away +diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp +index fc17aeb..2b458fe 100644 +--- a/hotspot/src/share/vm/utilities/ostream.cpp ++++ b/hotspot/src/share/vm/utilities/ostream.cpp +@@ -495,7 +495,7 @@ static const char* make_log_name_internal(const char* log_name, const char* forc + // -XX:DumpLoadedClassList= + // in log_name, %p => pid1234 and + // %t => YYYY-MM-DD_HH-MM-SS +-static const char* make_log_name(const char* log_name, const char* force_directory) { ++const char* make_log_name(const char* log_name, const char* force_directory) { + char timestr[32]; + get_datetime_string(timestr, sizeof(timestr)); + return make_log_name_internal(log_name, force_directory, os::current_process_id(), +diff --git a/hotspot/src/share/vm/utilities/ostream.hpp b/hotspot/src/share/vm/utilities/ostream.hpp +index fbcb299..530c523 100644 +--- a/hotspot/src/share/vm/utilities/ostream.hpp ++++ b/hotspot/src/share/vm/utilities/ostream.hpp +@@ -332,4 +332,6 @@ class networkStream : public bufferedStream { + + #endif + ++const char* make_log_name(const char* log_name, const char* force_directory); ++ + #endif // SHARE_VM_UTILITIES_OSTREAM_HPP +diff --git a/jdk/src/share/classes/java/lang/ClassLoader.java b/jdk/src/share/classes/java/lang/ClassLoader.java +index 2e98092..f305c1e 100644 +--- a/jdk/src/share/classes/java/lang/ClassLoader.java ++++ b/jdk/src/share/classes/java/lang/ClassLoader.java +@@ -2182,6 +2182,10 @@ public abstract class ClassLoader { + + // Retrieves the assertion directives from the VM. + private static native AssertionStatusDirectives retrieveDirectives(); ++ ++ protected ProtectionDomain getProtectionDomainInternal(String name) { ++ return null; ++ } + } + + +diff --git a/jdk/src/share/classes/java/net/URLClassLoader.java b/jdk/src/share/classes/java/net/URLClassLoader.java +index 416941c..e82cb6d 100644 +--- a/jdk/src/share/classes/java/net/URLClassLoader.java ++++ b/jdk/src/share/classes/java/net/URLClassLoader.java +@@ -38,6 +38,7 @@ import java.security.Permission; + import java.security.PermissionCollection; + import java.security.PrivilegedAction; + import java.security.PrivilegedExceptionAction; ++import java.security.ProtectionDomain; + import java.security.SecureClassLoader; + import java.util.Enumeration; + import java.util.List; +@@ -343,6 +344,25 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { + return ucp.getURLs(); + } + ++ /* ++ * Retrieve protection domain using the specified class name. ++ * Called from the VM to support AppCDS ++ */ ++ protected ProtectionDomain getProtectionDomainInternal(String name) { ++ String path = name.replace('.', '/').concat(".class"); ++ Resource res = ucp.getResource(path, false); ++ ++ if(res == null) ++ { ++ // Should never happen ++ throw new AssertionError("Cannot find resource fpr path " + path); ++ } ++ URL url = res.getCodeSourceURL(); ++ CodeSigner[] signers = res.getCodeSigners(); ++ CodeSource cs = new CodeSource(url, signers); ++ return getProtectionDomain(cs); ++ } ++ + /** + * Finds and loads the class with the specified name from the URL search + * path. Any URLs referring to JAR files are loaded and opened as needed +diff --git a/jdk/src/share/classes/java/security/SecureClassLoader.java b/jdk/src/share/classes/java/security/SecureClassLoader.java +index 145f4fc..cb5f017 100644 +--- a/jdk/src/share/classes/java/security/SecureClassLoader.java ++++ b/jdk/src/share/classes/java/security/SecureClassLoader.java +@@ -195,7 +195,7 @@ public class SecureClassLoader extends ClassLoader { + /* + * Returned cached ProtectionDomain for the specified CodeSource. + */ +- private ProtectionDomain getProtectionDomain(CodeSource cs) { ++ protected ProtectionDomain getProtectionDomain(CodeSource cs) { + if (cs == null) + return null; + +@@ -215,6 +215,7 @@ public class SecureClassLoader extends ClassLoader { + return pd; + } + ++ + /* + * Check to make sure the class loader has been initialized. + */ diff --git a/Fix-LineBuffer-vappend-when-buffer-too-small.patch b/Fix-LineBuffer-vappend-when-buffer-too-small.patch new file mode 100644 index 0000000000000000000000000000000000000000..9c5b18555869c7f898487f93b7748e52c7b02b31 --- /dev/null +++ b/Fix-LineBuffer-vappend-when-buffer-too-small.patch @@ -0,0 +1,27 @@ +From a409bdd4982a6a463b65b529ed3aedb0c3e29144 Mon Sep 17 00:00:00 2001 +Date: Mon, 17 Aug 2020 19:32:33 +0000 +Subject: [PATCH] Fix LineBuffer::vappend when buffer too small + +Summary: : fix LineBuffer::vappend when buffer too small +LLT: NA +Bug url: NA +--- + hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp +index 75a9a5f95..185b7d67e 100644 +--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp ++++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp +@@ -42,7 +42,7 @@ private: + + void vappend(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0) { + int res = os::vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap); +- if (res > BUFFER_LEN) { ++ if (_cur + res > BUFFER_LEN) { + DEBUG_ONLY(warning("buffer too small in LineBuffer");) + _buffer[BUFFER_LEN -1] = 0; + _cur = BUFFER_LEN; // vsnprintf above should not add to _buffer if we are called again +-- +2.12.3 + diff --git a/Remove-unused-GenericTaskQueueSet-T-F-tasks.patch b/Remove-unused-GenericTaskQueueSet-T-F-tasks.patch new file mode 100644 index 0000000000000000000000000000000000000000..b242ff22646cdf9cff85794ad9804b442dfe2610 --- /dev/null +++ b/Remove-unused-GenericTaskQueueSet-T-F-tasks.patch @@ -0,0 +1,51 @@ +From bd4fd0ac21f668f9f91e802e73cad0c120ba9df6 Mon Sep 17 00:00:00 2001 +Date: Thu, 4 Jun 2020 15:45:47 +0800 +Subject: [PATCH] Remove unused GenericTaskQueueSet::tasks() + +Summary: : remove unused GenericTaskQueueSet::tasks() +LLT: NA +Bug url: NA +--- + hotspot/src/share/vm/utilities/taskqueue.hpp | 12 ------------ + 1 file changed, 12 deletions(-) + +diff --git a/hotspot/src/share/vm/utilities/taskqueue.hpp b/hotspot/src/share/vm/utilities/taskqueue.hpp +index 5b03ccfa..9a2e2ee2 100644 +--- a/hotspot/src/share/vm/utilities/taskqueue.hpp ++++ b/hotspot/src/share/vm/utilities/taskqueue.hpp +@@ -541,8 +541,6 @@ class TaskQueueSetSuper { + public: + // Returns "true" if some TaskQueue in the set contains a task. + virtual bool peek() = 0; +- // Tasks in queue +- virtual uint tasks() const = 0; + virtual size_t tasks() = 0; + }; + +@@ -576,7 +574,6 @@ public: + // Returns if stealing succeeds, and sets "t" to the stolen task. + bool steal(uint queue_num, E& t); + bool peek(); +- uint tasks() const; + size_t tasks(); + + uint size() const { return _n; } +@@ -675,15 +672,6 @@ size_t GenericTaskQueueSet::tasks() { + return n; + } + +-template +-uint GenericTaskQueueSet::tasks() const { +- uint n = 0; +- for (uint j = 0; j < _n; j++) { +- n += _queues[j]->size(); +- } +- return n; +-} +- + // When to terminate from the termination protocol. + class TerminatorTerminator: public CHeapObj { + public: +-- +2.19.0 + diff --git a/Support-Git-commit-ID-in-the-SOURCE-field-of-the-release.patch b/Support-Git-commit-ID-in-the-SOURCE-field-of-the-release.patch new file mode 100644 index 0000000000000000000000000000000000000000..de06f705906f991543f9c64263157591ed857cae --- /dev/null +++ b/Support-Git-commit-ID-in-the-SOURCE-field-of-the-release.patch @@ -0,0 +1,68 @@ +From 9945034658585ea943e6326340c06b5932af8d67 Mon Sep 17 00:00:00 2001 +Date: Thu, 5 Dec 2019 10:29:18 +0000 +Subject: [PATCH] Support 'Git commit ID' in the SOURCE field of the release + file. + +Summary: :Support 'Git commit ID' in the SOURCE field of the release file. +LLT: NA +Bug url: NA +--- + common/autoconf/spec.gmk.in | 1 + + make/common/MakeBase.gmk | 29 +++++++++++++++++------------ + 2 files changed, 18 insertions(+), 12 deletions(-) + +diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in +index 88f9f539..506cf617 100644 +--- a/common/autoconf/spec.gmk.in ++++ b/common/autoconf/spec.gmk.in +@@ -578,6 +578,7 @@ READELF:=@READELF@ + EXPR:=@EXPR@ + FILE:=@FILE@ + HG:=@HG@ ++GIT:=@GIT@ + OBJCOPY:=@OBJCOPY@ + SETFILE:=@SETFILE@ + XATTR:=@XATTR@ +diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk +index 9e5e704b..9b7ad702 100644 +--- a/make/common/MakeBase.gmk ++++ b/make/common/MakeBase.gmk +@@ -308,18 +308,23 @@ REPO_LIST = $(patsubst ./%,%,$(patsubst %/,%,$(sort $(dir \ + + # Emit the repo:id pairs to $@ + define GetSourceTips +- $(CD) $(SRC_ROOT) ; \ +- for i in $(REPO_LIST) IGNORE ; do \ +- if [ "$${i}" = "IGNORE" ] ; then \ +- continue; \ +- elif [ -d $${i}/$(HG_DIRECTORY) -a "$(HG_VERSION)" != "" ] ; then \ +- $(PRINTF) " %s:%s" \ +- "$${i}" `$(HG) id -i --repository $${i}` ; \ +- elif [ -f $${i}/$(HGTIP_FILENAME) ] ; then \ +- $(PRINTF) " %s:%s" \ +- "$${i}" `$(CAT) $${i}/$(HGTIP_FILENAME)` ; \ +- fi; \ +- done >> $@ ++ $(if $(and $(HG), $(wildcard $(TOPDIR)/.hg)), \ ++ $$($(CD) $(SRC_ROOT) ; \ ++ for i in $(REPO_LIST) IGNORE ; do \ ++ if [ "$${i}" = "IGNORE" ] ; then \ ++ continue; \ ++ elif [ -d $${i}/$(HG_DIRECTORY) -a "$(HG_VERSION)" != "" ] ; then \ ++ $(PRINTF) " %s:%s" \ ++ "$${i}" `$(HG) id -i --repository $${i}` ; \ ++ elif [ -f $${i}/$(HGTIP_FILENAME) ] ; then \ ++ $(PRINTF) " %s:%s" \ ++ "$${i}" `$(CAT) $${i}/$(HGTIP_FILENAME)` ; \ ++ fi; \ ++ done >> $@), \ ++ $(if $(and $(GIT), $(wildcard $(TOPDIR)/.git)), \ ++ $(PRINTF) ".:git:%s%s\n" \ ++ "$$(git log -n1 --format=%H | cut -c1-12)" \ ++ "$$(if test -n "$$(git status --porcelain)"; then printf '+'; fi)" >> $@, )) + $(PRINTF) "\n" >> $@ + endef + +-- +2.19.0 + diff --git a/Test-SSLSocketSSLEngineTemplate.java-intermittent-fa.patch b/Test-SSLSocketSSLEngineTemplate.java-intermittent-fa.patch new file mode 100644 index 0000000000000000000000000000000000000000..346b37a610214024ea6952b60a510cca9c956fb2 --- /dev/null +++ b/Test-SSLSocketSSLEngineTemplate.java-intermittent-fa.patch @@ -0,0 +1,42 @@ +From 82b702f9680471ba548866aa17756f76d980ee0a Mon Sep 17 00:00:00 2001 +Date: Fri, 28 Aug 2020 09:13:33 +0800 +Subject: [PATCH] Test SSLSocketSSLEngineTemplate.java intermittent failed with + "Data length error" + +Summary: : Test SSLSocketSSLEngineTemplate.java intermittent failed with "Data length error" +LLT: jdk8u/jdk/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java +Bug url: +--- + .../security/ssl/templates/SSLSocketSSLEngineTemplate.java | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/jdk/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java b/jdk/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java +index 661941677..181bbc8fd 100644 +--- a/jdk/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java ++++ b/jdk/test/sun/security/ssl/templates/SSLSocketSSLEngineTemplate.java +@@ -154,6 +154,8 @@ public class SSLSocketSSLEngineTemplate { + SSLSocketSSLEngineTemplate test = + new SSLSocketSSLEngineTemplate(protocol); + test.runTest(true); ++ // invalid session ++ test.invalidSession(); + test.runTest(false); + } + +@@ -488,4 +490,13 @@ public class SSLSocketSSLEngineTemplate { + System.out.println(str); + } + } ++ ++ /* ++ * invalid session ++ */ ++ private void invalidSession() { ++ if (sslSocket != null && sslSocket.getSession() != null) { ++ sslSocket.getSession().invalidate(); ++ } ++ } + } +-- +2.12.3 + diff --git a/Test8167409.sh-fails-to-run-with-32bit-jdk-on-64bit-.patch b/Test8167409.sh-fails-to-run-with-32bit-jdk-on-64bit-.patch new file mode 100644 index 0000000000000000000000000000000000000000..c8d58f5bd312a45efc235332e4aacf5bf300c4f7 --- /dev/null +++ b/Test8167409.sh-fails-to-run-with-32bit-jdk-on-64bit-.patch @@ -0,0 +1,37 @@ +From 0cf95d445b1f6854249987ec55591e26cc21c6a1 Mon Sep 17 00:00:00 2001 +Date: Thu, 14 May 2020 09:59:34 +0800 +Subject: [PATCH] Test8167409.sh fails to run with 32bit jdk on 64bit system + +Summary: : Test8167409.sh fails to run with 32bit jdk on 64bit system +LLT: jdk8u/hotspot/test/compiler/criticalnatives/argumentcorruption/Test8167409.sh +Bug url: +--- + .../criticalnatives/argumentcorruption/Test8167409.sh | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/hotspot/test/compiler/criticalnatives/argumentcorruption/Test8167409.sh b/hotspot/test/compiler/criticalnatives/argumentcorruption/Test8167409.sh +index 81695e75..1108aaf9 100644 +--- a/hotspot/test/compiler/criticalnatives/argumentcorruption/Test8167409.sh ++++ b/hotspot/test/compiler/criticalnatives/argumentcorruption/Test8167409.sh +@@ -61,13 +61,17 @@ case "$OS" in + exit 0; + ;; + esac ++${TESTJAVA}${FS}bin${FS}java -XshowSettings 2>&1 | grep sun.arch.data.model | grep 32 ++if [ 0 -eq $? ] ; then ++ M32="-m32" ++fi + + THIS_DIR=. + + cp ${TESTSRC}${FS}*.java ${THIS_DIR} + ${TESTJAVA}${FS}bin${FS}javac *.java + +-$cc_cmd -fPIC -shared -o libCNCheckLongArgs.so \ ++$cc_cmd ${M32} -fPIC -shared -o libCNCheckLongArgs.so \ + -I${TESTJAVA}${FS}include -I${TESTJAVA}${FS}include${FS}linux \ + ${TESTSRC}${FS}libCNCheckLongArgs.c + +-- +2.19.0 + diff --git a/The-runok-method-retrying-another-port-does-not-take.patch b/The-runok-method-retrying-another-port-does-not-take.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb602ac2fdc4fd1094df8dde0ec9bdc360544c35 --- /dev/null +++ b/The-runok-method-retrying-another-port-does-not-take.patch @@ -0,0 +1,27 @@ +From 952b5418911a0cbe864d83998b1c99904830d463 Mon Sep 17 00:00:00 2001 +Date: Fri, 28 Aug 2020 09:21:14 +0800 +Subject: [PATCH] The runok method retrying another port does not take effect + +Summary: : The runok method retrying another port does not take effect +LLT: jdk8u/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.sh +Bug url: +--- + jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java b/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java +index d9c20c678..60219e68a 100644 +--- a/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java ++++ b/jdk/test/sun/management/jmxremote/bootstrap/RmiBootstrapTest.java +@@ -824,7 +824,7 @@ public class RmiBootstrapTest { + + String errStr = null; + for (int i=0;iklass_or_null_acquire(); +- if (k != NULL) { ++ if (k != NULL && Metaspace::contains(k)) { + assert(k->is_klass(), "Should really be klass oop."); + oop o = (oop)p; + assert(o->is_oop(true /* ignore mark word */), "Should be an oop."); diff --git a/fix-crash-in-JVMTI-debug.patch b/fix-crash-in-JVMTI-debug.patch new file mode 100644 index 0000000000000000000000000000000000000000..34c3a71ebf0812f68e7468e2aaf46ac8664da701 --- /dev/null +++ b/fix-crash-in-JVMTI-debug.patch @@ -0,0 +1,24 @@ +From 82250c7c4978bf7591299e8635fb183f36d3546f Mon Sep 17 00:00:00 2001 +Date: Fri, 19 Apr 2019 16:30:04 +0000 +Subject: [PATCH] fix crash in JVMTI debug + +--- + hotspot/src/share/vm/prims/jvmtiEnvBase.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +index fe2a3811..5db41567 100644 +--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp ++++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp +@@ -1092,7 +1092,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec + // If the monitor has no owner, then a non-suspended contending + // thread could potentially change the state of the monitor by + // entering it. The JVM/TI spec doesn't allow this. +- if (owning_thread == NULL && !at_safepoint & ++ if (owning_thread == NULL && !at_safepoint && + !JvmtiEnv::is_thread_fully_suspended(pending_thread, true, &debug_bits)) { + if (ret.owner != NULL) { + destroy_jni_reference(calling_thread, ret.owner); +-- +2.19.0 + diff --git a/fix-incorrect-klass-field-in-oop-with-weak-memory-model.patch b/fix-incorrect-klass-field-in-oop-with-weak-memory-model.patch new file mode 100644 index 0000000000000000000000000000000000000000..05f99a33fa6e3e8dbe2f13e543d77088f3c5ec0b --- /dev/null +++ b/fix-incorrect-klass-field-in-oop-with-weak-memory-model.patch @@ -0,0 +1,32 @@ +diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +index b7b3da6..1a915aa 100644 +--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp ++++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +@@ -994,6 +994,8 @@ size_t CompactibleFreeListSpace::block_size(const HeapWord* p) const { + return res; + } + } else { ++ OrderAccess::acquire(); ++ + // Ensure klass read before size. + Klass* k = oop(p)->klass_or_null_acquire(); + if (k != NULL) { +@@ -1044,6 +1046,8 @@ const { + return res; + } + } else { ++ OrderAccess::acquire(); ++ + // Ensure klass read before size. + Klass* k = oop(p)->klass_or_null_acquire(); + if (k != NULL) { +@@ -1098,6 +1102,9 @@ bool CompactibleFreeListSpace::block_is_obj(const HeapWord* p) const { + // assert(CollectedHeap::use_parallel_gc_threads() || _bt.block_start(p) == p, + // "Should be a block boundary"); + if (FreeChunk::indicatesFreeChunk(p)) return false; ++ ++ OrderAccess::acquire(); ++ + Klass* k = oop(p)->klass_or_null_acquire(); + if (k != NULL) { + // Ignore mark word because it may have been used to diff --git a/fix-incorrect-offset-for-oop-field-with-weak-memory-.patch b/fix-incorrect-offset-for-oop-field-with-weak-memory-.patch new file mode 100644 index 0000000000000000000000000000000000000000..31c4001badc9caa75a577ac436b592309a42f284 --- /dev/null +++ b/fix-incorrect-offset-for-oop-field-with-weak-memory-.patch @@ -0,0 +1,37 @@ +From 7c73365615f00951272310db44dec2939b91b48e Mon Sep 17 00:00:00 2001 +Date: Wed, 19 Feb 2020 19:09:39 +0000 +Subject: [PATCH] fix incorrect offset for oop field with weak memory model + +Summary: : add loadload membar in fast_storefield and fast_accessfield to avoid loading a incorrect offset +LLT: N/A +Bug url: N/A +--- + hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp +index 5a619566..aa9545ee 100644 +--- a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp ++++ b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp +@@ -2922,6 +2922,8 @@ void TemplateTable::fast_storefield(TosState state) + // access constant pool cache + __ get_cache_and_index_at_bcp(r2, r1, 1); + ++ __ membar(MacroAssembler::LoadLoad); ++ + // test for volatile with r3 + __ ldrw(r3, Address(r2, in_bytes(base + + ConstantPoolCacheEntry::flags_offset()))); +@@ -3013,6 +3015,9 @@ void TemplateTable::fast_accessfield(TosState state) + + // access constant pool cache + __ get_cache_and_index_at_bcp(r2, r1, 1); ++ ++ __ membar(MacroAssembler::LoadLoad); ++ + __ ldr(r1, Address(r2, in_bytes(ConstantPoolCache::base_offset() + + ConstantPoolCacheEntry::f2_offset()))); + __ ldrw(r3, Address(r2, in_bytes(ConstantPoolCache::base_offset() + +-- +2.19.0 + diff --git a/java-1.8.0-openjdk.spec b/java-1.8.0-openjdk.spec index 0e99c0f2d677f1562b5a16322d977479ef7a087e..f0308fb4d9b01d21cf2ffeeb003baab802969898 100644 --- a/java-1.8.0-openjdk.spec +++ b/java-1.8.0-openjdk.spec @@ -915,7 +915,7 @@ Provides: java-%{javaver}-%{origin}-accessibility%{?1} = %{epoch}:%{version}-%{r Name: java-%{javaver}-%{origin} Version: %{javaver}.%{updatever}.%{buildver} -Release: 4 +Release: 5 # 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 @@ -1044,6 +1044,26 @@ Patch103: Ddot-intrinsic-implement.patch Patch104: 8234003-Improve-IndexSet-iteration.patch Patch105: 8220159-Optimize-various-RegMask-operations-by-introducing-watermarks.patch Patch106: fast-serializer-jdk8.patch +Patch107: 6896810-Pin.java-fails-with-OOME-during-System.out.p.patch +Patch108: 8231631-sun-net-ftp-FtpURLConnectionLeak.java-fails-.patch +Patch109: Test8167409.sh-fails-to-run-with-32bit-jdk-on-64bit-.patch +Patch110: Test-SSLSocketSSLEngineTemplate.java-intermittent-fa.patch +Patch111: The-runok-method-retrying-another-port-does-not-take.patch +Patch112: 8048210-8056152-fix-assert-fail-for-an-InnocuousThre.patch +Patch113: 8160425-Vectorization-with-signalling-NaN-returns-wr.patch +Patch114: 8181503-Can-t-compile-hotspot-with-c-11.patch +Patch115: 8243670-Unexpected-test-result-caused-by-C2-MergeMem.patch +Patch116: fix-crash-in-JVMTI-debug.patch +Patch117: fix-incorrect-klass-field-in-oop-with-weak-memory-model.patch +Patch118: Fix-LineBuffer-vappend-when-buffer-too-small.patch +Patch119: make-disable-precompiled-headers-work.patch +Patch120: fix-CompactibleFreeListSpace-block_size-crash.patch +Patch121: Remove-unused-GenericTaskQueueSet-T-F-tasks.patch +Patch122: optimize-jmap-F-dump-xxx.patch +Patch123: recreate-.java_pid-file-when-deleted-for-attach-mechanism.patch +Patch124: Support-Git-commit-ID-in-the-SOURCE-field-of-the-release.patch +Patch125: Extend-CDS-to-support-app-class-metadata-sharing.patch +Patch126: zlib-optimization.patch ############################################# # @@ -1446,7 +1466,26 @@ pushd %{top_level_dir_name} %patch104 -p1 %patch105 -p1 %patch106 -p1 - +%patch107 -p1 +%patch108 -p1 +%patch109 -p1 +%patch110 -p1 +%patch111 -p1 +%patch112 -p1 +%patch113 -p1 +%patch114 -p1 +%patch115 -p1 +%patch116 -p1 +%patch117 -p1 +%patch118 -p1 +%patch119 -p1 +%patch120 -p1 +%patch121 -p1 +%patch122 -p1 +%patch123 -p1 +%patch124 -p1 +%patch125 -p1 +%patch126 -p1 popd @@ -2066,6 +2105,28 @@ require "copy_jdk_configs.lua" %endif %changelog +* Fri Sep 11 2020 noah -:1.8.0.265-b10.5 +- add 6896810-Pin.java-fails-with-OOME-during-System.out.p.patch +- add 8231631-sun-net-ftp-FtpURLConnectionLeak.java-fails-.patch +- add Test8167409.sh-fails-to-run-with-32bit-jdk-on-64bit-.patch +- add Test-SSLSocketSSLEngineTemplate.java-intermittent-fa.patch +- add The-runok-method-retrying-another-port-does-not-take.patch +- add 8048210-8056152-fix-assert-fail-for-an-InnocuousThre.patch +- add 8160425-Vectorization-with-signalling-NaN-returns-wr.patch +- add 8181503-Can-t-compile-hotspot-with-c-11.patch +- add 8243670-Unexpected-test-result-caused-by-C2-MergeMem.patch +- add fix-crash-in-JVMTI-debug.patch +- add fix-incorrect-klass-field-in-oop-with-weak-memory-model.patch +- add Fix-LineBuffer-vappend-when-buffer-too-small.patch +- add make-disable-precompiled-headers-work.patch +- add fix-CompactibleFreeListSpace-block_size-crash.patch +- add Remove-unused-GenericTaskQueueSet-T-F-tasks.patch +- add optimize-jmap-F-dump-xxx.patch +- add recreate-.java_pid-file-when-deleted-for-attach-mechanism.patch +- add Support-Git-commit-ID-in-the-SOURCE-field-of-the-release.patch +- add Extend-CDS-to-support-app-class-metadata-sharing.patch +- add zlib-optimization.patch + * Tue Sep 8 2020 noah - 1:1.8.0.265-b10.4 - add fast-serializer-jdk8.patch diff --git a/make-disable-precompiled-headers-work.patch b/make-disable-precompiled-headers-work.patch new file mode 100644 index 0000000000000000000000000000000000000000..6a1c9f54ded6ba5972ed84ba1d9b42144566bdcb --- /dev/null +++ b/make-disable-precompiled-headers-work.patch @@ -0,0 +1,41 @@ +From 16d2fb7faaaad6ae1d3f508af0c654c5c83bf484 Mon Sep 17 00:00:00 2001 +Date: Tue, 8 Sep 2020 09:13:31 +0800 +Subject: [PATCH] make disable precompiled headers work + +Summary: :make disable precompiled headers work +LLT: N/A +Bug url: +--- + hotspot/src/share/vm/oops/oop.hpp | 2 +- + hotspot/src/share/vm/oops/oop.inline.hpp | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp +index 41a7bce4d..8a33412ec 100644 +--- a/hotspot/src/share/vm/oops/oop.hpp ++++ b/hotspot/src/share/vm/oops/oop.hpp +@@ -91,7 +91,7 @@ class oopDesc { + narrowKlass* compressed_klass_addr(); + + void set_klass(Klass* k); +- inline void release_set_klass(Klass* k); ++ void release_set_klass(Klass* k); + + // For klass field compression + int klass_gap() const; +diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp +index c3abdb128..3e3883cb6 100644 +--- a/hotspot/src/share/vm/oops/oop.inline.hpp ++++ b/hotspot/src/share/vm/oops/oop.inline.hpp +@@ -141,7 +141,7 @@ inline void oopDesc::set_klass(Klass* k) { + } + } + +-void oopDesc::release_set_klass(Klass* k) { ++inline void oopDesc::release_set_klass(Klass* k) { + CHECK_SET_KLASS(k); + if (UseCompressedClassPointers) { + OrderAccess::release_store(compressed_klass_addr(), +-- +2.12.3 + diff --git a/optimize-jmap-F-dump-xxx.patch b/optimize-jmap-F-dump-xxx.patch new file mode 100644 index 0000000000000000000000000000000000000000..79aef4109ddddfd329089b9215f13bee2d42e673 --- /dev/null +++ b/optimize-jmap-F-dump-xxx.patch @@ -0,0 +1,42 @@ +From 12ec07c99ff937953c3adafc12818136d9fb1d2b Mon Sep 17 00:00:00 2001 +Date: Thu, 9 Apr 2020 09:18:13 +0000 +Subject: [PATCH] optimize jmap -F -dump:xxx + +Summary: optimize jmap -F -dump:xxx to speed up the dump process +LLT: N/A +Bug url: N/A +--- + .../share/classes/sun/jvm/hotspot/oops/Metadata.java | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Metadata.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Metadata.java +index 4fc2ed8c..2e56d270 100644 +--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Metadata.java ++++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Metadata.java +@@ -45,6 +45,7 @@ abstract public class Metadata extends VMObject { + } + + private static VirtualBaseConstructor metadataConstructor; ++ private static Map map = new HashMap(); + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + metadataConstructor = new VirtualBaseConstructor(db, db.lookupType("Metadata"), null, null); +@@ -65,7 +66,14 @@ abstract public class Metadata extends VMObject { + } + + public static Metadata instantiateWrapperFor(Address addr) { +- return metadataConstructor.instantiateWrapperFor(addr); ++ Metadata metadata; ++ if (!map.containsKey(addr)) { ++ metadata = metadataConstructor.instantiateWrapperFor(addr); ++ map.put(addr, metadata); ++ } else { ++ metadata = (Metadata)map.get(addr); ++ } ++ return metadata; + } + + public void iterate(MetadataVisitor visitor) { +-- +2.19.0 + diff --git a/recreate-.java_pid-file-when-deleted-for-attach-mechanism.patch b/recreate-.java_pid-file-when-deleted-for-attach-mechanism.patch new file mode 100644 index 0000000000000000000000000000000000000000..534254a66ddcaeb27cd74c5917457f8f17f663ab --- /dev/null +++ b/recreate-.java_pid-file-when-deleted-for-attach-mechanism.patch @@ -0,0 +1,75 @@ +From 9f8ee6d44e254da38605d3ceb527d412a208c862 Mon Sep 17 00:00:00 2001 +Date: Wed, 12 Aug 2020 12:09:15 +0000 +Subject: [PATCH] recreate .java_pid file when deleted for attach mechanism + +Summary: : +LLT: +Bug url: +--- + hotspot/src/os/linux/vm/attachListener_linux.cpp | 20 ++++++++++++++++---- + hotspot/src/share/vm/services/attachListener.cpp | 1 + + hotspot/src/share/vm/services/attachListener.hpp | 2 +- + 3 files changed, 18 insertions(+), 5 deletions(-) + +diff --git a/hotspot/src/os/linux/vm/attachListener_linux.cpp b/hotspot/src/os/linux/vm/attachListener_linux.cpp +index 700a09ff0..1ca089740 100644 +--- a/hotspot/src/os/linux/vm/attachListener_linux.cpp ++++ b/hotspot/src/os/linux/vm/attachListener_linux.cpp +@@ -485,13 +485,25 @@ bool AttachListener::init_at_startup() { + // If the file .attach_pid exists in the working directory + // or /tmp then this is the trigger to start the attach mechanism + bool AttachListener::is_init_trigger() { +- if (init_at_startup() || is_initialized()) { +- return false; // initialized at startup or already initialized ++ if (init_at_startup()) { ++ return false; // initialized at startup + } +- char fn[PATH_MAX+1]; +- sprintf(fn, ".attach_pid%d", os::current_process_id()); ++ ++ char fn[PATH_MAX + 1]; + int ret; + struct stat64 st; ++ ++ // check initialized ++ if (is_initialized()) { ++ // check .java_pid file exists ++ RESTARTABLE(::stat64(LinuxAttachListener::path(), &st), ret); ++ if (ret == -1) { ++ ::shutdown(LinuxAttachListener::listener(), SHUT_RDWR); ++ } ++ return false; ++ } ++ ++ sprintf(fn, ".attach_pid%d", os::current_process_id()); + RESTARTABLE(::stat64(fn, &st), ret); + if (ret == -1) { + snprintf(fn, sizeof(fn), "%s/.attach_pid%d", +diff --git a/hotspot/src/share/vm/services/attachListener.cpp b/hotspot/src/share/vm/services/attachListener.cpp +index 59b2f5483..0f51378dd 100644 +--- a/hotspot/src/share/vm/services/attachListener.cpp ++++ b/hotspot/src/share/vm/services/attachListener.cpp +@@ -425,6 +425,7 @@ static void attach_listener_thread_entry(JavaThread* thread, TRAPS) { + for (;;) { + AttachOperation* op = AttachListener::dequeue(); + if (op == NULL) { ++ AttachListener::set_initialized(false); + return; // dequeue failed or shutdown + } + +diff --git a/hotspot/src/share/vm/services/attachListener.hpp b/hotspot/src/share/vm/services/attachListener.hpp +index 5204c4c62..11ec525c6 100644 +--- a/hotspot/src/share/vm/services/attachListener.hpp ++++ b/hotspot/src/share/vm/services/attachListener.hpp +@@ -71,7 +71,7 @@ class AttachListener: AllStatic { + + public: + static bool is_initialized() { return _initialized; } +- static void set_initialized() { _initialized = true; } ++ static void set_initialized(bool init = true) { _initialized = init; } + + // indicates if this VM supports attach-on-demand + static bool is_attach_supported() { return !DisableAttachMechanism; } +-- +2.12.3 + diff --git a/zlib-optimization.patch b/zlib-optimization.patch new file mode 100644 index 0000000000000000000000000000000000000000..866a553e5d3f44b511e49d503010421f7ef4ba41 --- /dev/null +++ b/zlib-optimization.patch @@ -0,0 +1,882 @@ +diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk +index c8e4815..c36ac39 100644 +--- a/jdk/make/lib/CoreLibraries.gmk ++++ b/jdk/make/lib/CoreLibraries.gmk +@@ -257,6 +257,9 @@ ifeq ($(USE_EXTERNAL_LIBZ), true) + LIBZIP_EXCLUDES += zlib + else + ZLIB_CPPFLAGS := -I$(JDK_TOPDIR)/src/share/native/java/util/zip/zlib ++ ifeq ($(OPENJDK_TARGET_CPU), aarch64) ++ ZLIB_CPPFLAGS += -DCRC32_ARMV8_CRC32 -DHASH_ARMV8_CRC32 -march=armv8-a+crc -DUNALIGNED_OK -DADLER32_SIMD_NEON -DSLIDE_HASH_NEON -DINFLATE_CHUNK_SIMD_NEON -O3 ++ endif + endif + + BUILD_LIBZIP_REORDER := +@@ -274,7 +277,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBZIP, \ + LIBRARY := zip, \ + OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ + LANG := C, \ +- OPTIMIZATION := LOW, \ ++ OPTIMIZATION := HIGHEST, \ + SRC := $(JDK_TOPDIR)/src/share/native/java/util/zip, \ + EXCLUDES := $(LIBZIP_EXCLUDES), \ + CFLAGS := $(CFLAGS_JDKLIB) \ +diff --git a/jdk/src/share/native/java/util/zip/zlib/deflate.c b/jdk/src/share/native/java/util/zip/zlib/deflate.c +index f30f71b..c018064 100644 +--- a/jdk/src/share/native/java/util/zip/zlib/deflate.c ++++ b/jdk/src/share/native/java/util/zip/zlib/deflate.c +@@ -184,8 +184,16 @@ local const config configuration_table[10] = { + * characters, so that a running hash key can be computed from the previous + * key instead of complete recalculation each time. + */ +-#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) ++#if defined(HASH_ARMV8_CRC32) ++#include ++#define UPDATE_HASH_CRC_INTERNAL(s, h, c) \ ++ (h = __crc32w(0, (c) & 0xFFFFFF) & ((deflate_state *)s)->hash_mask) + ++#define UPDATE_HASH(s, h, c) \ ++ UPDATE_HASH_CRC_INTERNAL(s, h, *(unsigned *)((uintptr_t)(&c) - (MIN_MATCH-1))) ++#else ++#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) ++#endif + + /* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head +@@ -222,6 +230,46 @@ local const config configuration_table[10] = { + * bit values at the expense of memory usage). We slide even when level == 0 to + * keep the hash table consistent if we switch back to level > 0 later. + */ ++ ++#if defined(SLIDE_HASH_NEON) ++#include ++static inline void slide_hash_chain(Pos *table, unsigned int entries, uint16_t window_size) { ++ register uint16x8_t v, *p; ++ register size_t n; ++ ++ size_t size = entries * sizeof(table[0]); /* the size of hash table */ ++ Assert((size % (sizeof(uint16x8_t) * 8) == 0), "hash table size err"); /* if it's not 0, size err occurs */ ++ ++ Assert(sizeof(Pos) == 2, "Wrong Pos size"); /* if size of Pos is not 2, release wrong size error */ ++ v = vdupq_n_u16(window_size); ++ ++ p = (uint16x8_t *)table; ++ n = size / (sizeof(uint16x8_t) * 8); ++ do { ++ p[0] = vqsubq_u16(p[0], v); ++ p[1] = vqsubq_u16(p[1], v); ++ p[2] = vqsubq_u16(p[2], v); ++ p[3] = vqsubq_u16(p[3], v); ++ p[4] = vqsubq_u16(p[4], v); ++ p[5] = vqsubq_u16(p[5], v); ++ p[6] = vqsubq_u16(p[6], v); ++ p[7] = vqsubq_u16(p[7], v); ++ p += 8; ++ } while (--n); ++} ++ ++local void slide_hash(s) ++ deflate_state *s; ++{ ++ const size_t size = s->hash_size * sizeof(s->head[0]); ++ Assert(sizeof(Pos) == 2, "Wrong Pos size."); /* if size of Pos is not 2, release wrong size error */ ++ Assert((size % (sizeof(uint16x8_t)*2)) == 0, "Hash table size error."); /* if it's not 0, size err occurs */ ++ slide_hash_chain(s->head, s->hash_size, s->w_size); ++#ifndef FASTEST ++ slide_hash_chain(s->prev, s->w_size, s->w_size); ++#endif ++} ++#else + local void slide_hash(s) + deflate_state *s; + { +@@ -247,6 +295,7 @@ local void slide_hash(s) + } while (--n); + #endif + } ++#endif + + /* ========================================================================= */ + int ZEXPORT deflateInit_(strm, level, version, stream_size) +@@ -1198,14 +1247,15 @@ local unsigned read_buf(strm, buf, size) + strm->avail_in -= len; + + zmemcpy(buf, strm->next_in, len); +- if (strm->state->wrap == 1) { +- strm->adler = adler32(strm->adler, buf, len); +- } + #ifdef GZIP +- else if (strm->state->wrap == 2) { ++ if (strm->state->wrap == 2) { /* use crc32 algo */ + strm->adler = crc32(strm->adler, buf, len); +- } ++ } else + #endif ++ if (strm->state->wrap == 1) { ++ strm->adler = adler32(strm->adler, buf, len); ++ } ++ + strm->next_in += len; + strm->total_in += len; + +diff --git a/jdk/src/share/native/java/util/zip/zlib/inffast.c b/jdk/src/share/native/java/util/zip/zlib/inffast.c +index 4bfc995..2084739 100644 +--- a/jdk/src/share/native/java/util/zip/zlib/inffast.c ++++ b/jdk/src/share/native/java/util/zip/zlib/inffast.c +@@ -81,6 +81,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ ++#if defined(INFLATE_CHUNK_SIMD_NEON) ++ unsigned char FAR *limit; /* safety limit for chunky copies */ ++#endif + #ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ + #endif +@@ -113,7 +116,12 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ + #endif + wsize = state->wsize; + whave = state->whave; ++#if defined(INFLATE_CHUNK_SIMD_NEON) ++ limit = out + strm->avail_out; ++ wnext = (state->wnext == 0 && whave >= wsize) ? wsize : state->wnext; ++#else + wnext = state->wnext; ++#endif + window = state->window; + hold = state->hold; + bits = state->bits; +@@ -221,6 +229,45 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ + #endif + } + from = window; ++#if defined(INFLATE_CHUNK_SIMD_NEON) ++ if (wnext >= op) { /* contiguous in window */ ++ from += wnext - op; ++ } ++ else { /* wrap around window */ ++ op -= wnext; ++ from += wsize - op; ++ if (op < len) { /* some from end of window */ ++ len -= op; ++ out = chunkcopy_safe(out, from, op, limit); ++ from = window; /* more from start of window */ ++ op = wnext; ++ /* This (rare) case can create a situation where ++ the first chunkcopy below must be checked. ++ */ ++ } ++ } ++ if (op < len) { /* still need some from output */ ++ out = chunkcopy_safe(out, from, op, limit); ++ len -= op; ++ /* When dist is small the amount of data that can be ++ copied from the window is also small, and progress ++ towards the dangerous end of the output buffer is ++ also small. This means that for trivial memsets and ++ for chunkunroll_relaxed() a safety check is ++ unnecessary. However, these conditions may not be ++ entered at all, and in that case it's possible that ++ the main copy is near the end. ++ */ ++ out = chunkunroll_relaxed(out, &dist, &len); ++ out = chunkcopy_safe(out, out - dist, len, limit); ++ } ++ else { ++ /* from points to window, so there is no risk of ++ overlapping pointers requiring memset-like behaviour ++ */ ++ out = chunkcopy_safe(out, from, len, limit); ++ } ++#else + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ +@@ -271,8 +318,18 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ + if (len > 1) + *out++ = *from++; + } ++#endif + } +- else { ++ else { ++#if defined(INFLATE_CHUNK_SIMD_NEON) ++ /* Whole reference is in range of current output. No ++ range checks are necessary because we start with room ++ for at least 258 bytes of output, so unroll and roundoff ++ operations can write beyond `out+len` so long as they ++ stay within 258 bytes of `out`. ++ */ ++ out = chunkcopy_lapped_relaxed(out, dist, len); ++#else + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + *out++ = *from++; +@@ -284,7 +341,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ + *out++ = *from++; + if (len > 1) + *out++ = *from++; +- } ++ } ++#endif + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ +diff --git a/jdk/src/share/native/java/util/zip/zlib/inffast.h b/jdk/src/share/native/java/util/zip/zlib/inffast.h +index b8da8bb..0def2e3 100644 +--- a/jdk/src/share/native/java/util/zip/zlib/inffast.h ++++ b/jdk/src/share/native/java/util/zip/zlib/inffast.h +@@ -32,4 +32,374 @@ + subject to change. Applications should only use zlib.h. + */ + ++/* ++ * The chunk-copy code below deals with writing the decoded DEFLATE data to ++ * the output with SIMD methods to increase decode speed. Reading the input ++ * to the DEFLATE decoder with a wide, SIMD method can also increase decode ++ * speed. This option is supported on little endian machines, and reads the ++ * input data in 64-bit (8 byte) chunks. ++ */ ++ + void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); ++ ++#if defined(INFLATE_CHUNK_SIMD_NEON) ++ ++#include ++#include "zutil.h" ++#include ++ ++typedef uint8x16_t z_vec128i_t; ++ ++#define Z_STATIC_ASSERT(name, assert) typedef char name[(assert) ? 1 : -1] ++ ++#if __STDC_VERSION__ >= 199901L ++#define Z_RESTRICT restrict ++#else ++#define Z_RESTRICT ++#endif ++ ++#if defined(__clang__) || defined(__GNUC__) || defined(__llvm__) ++#define Z_BUILTIN_MEMCPY __builtin_memcpy ++#else ++#define Z_BUILTIN_MEMCPY zmemcpy ++#endif ++ ++/* ++ * chunk copy type: the z_vec128i_t type size should be exactly 128-bits ++ * and equal to CHUNKCOPY_CHUNK_SIZE. ++ */ ++#define CHUNKCOPY_CHUNK_SIZE sizeof(z_vec128i_t) ++ ++Z_STATIC_ASSERT(vector_128_bits_wide, ++ CHUNKCOPY_CHUNK_SIZE == sizeof(int8_t) * 16); ++ ++/* ++ * Ask the compiler to perform a wide, unaligned load with a machinevst1q_u8 ++ * instruction appropriate for the z_vec128i_t type. ++ */ ++static inline z_vec128i_t loadchunk( ++ const unsigned char FAR* s) ++{ ++ z_vec128i_t v; ++ Z_BUILTIN_MEMCPY(&v, s, sizeof(v)); ++ return v; ++} ++ ++/* ++ * Ask the compiler to perform a wide, unaligned store with a machine ++ * instruction appropriate for the z_vec128i_t type. ++ */ ++static inline void storechunk( ++ unsigned char FAR* d, ++ const z_vec128i_t v) ++{ ++ Z_BUILTIN_MEMCPY(d, &v, sizeof(v)); ++} ++ ++/* ++ * Perform a memcpy-like operation, assuming that length is non-zero and that ++ * it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if ++ * the length is shorter than this. ++ * ++ * It also guarantees that it will properly unroll the data if the distance ++ * between `out` and `from` is at least CHUNKCOPY_CHUNK_SIZE, which we rely on ++ * in chunkcopy_relaxed(). ++ * ++ * Aside from better memory bus utilisation, this means that short copies ++ * (CHUNKCOPY_CHUNK_SIZE bytes or fewer) will fall straight through the loop ++ * without iteration, which will hopefully make the branch prediction more ++ * reliable. ++ */ ++static inline unsigned char FAR* chunkcopy_core( ++ unsigned char FAR* out, ++ const unsigned char FAR* from, ++ unsigned len) ++{ ++ const int bump = (--len % CHUNKCOPY_CHUNK_SIZE) + 1; ++ storechunk(out, loadchunk(from)); ++ out += bump; ++ from += bump; ++ len /= CHUNKCOPY_CHUNK_SIZE; ++ while (len-- > 0) { ++ storechunk(out, loadchunk(from)); ++ out += CHUNKCOPY_CHUNK_SIZE; ++ from += CHUNKCOPY_CHUNK_SIZE; ++ } ++ return out; ++} ++ ++/* ++ * Like chunkcopy_core(), but avoid writing beyond of legal output. ++ * ++ * Accepts an additional pointer to the end of safe output. A generic safe ++ * copy would use (out + len), but it's normally the case that the end of the ++ * output buffer is beyond the end of the current copy, and this can still be ++ * exploited. ++ */ ++static inline unsigned char FAR* chunkcopy_core_safe( ++ unsigned char FAR* out, ++ const unsigned char FAR* from, ++ unsigned len, ++ unsigned char FAR* limit) ++{ ++ Assert(out + len <= limit, "chunk copy exceeds safety limit"); ++ if ((limit - out) < (ptrdiff_t) CHUNKCOPY_CHUNK_SIZE) { ++ const unsigned char FAR* Z_RESTRICT rfrom = from; ++ if (len & 8) { ++ Z_BUILTIN_MEMCPY(out, rfrom, 8); ++ out += 8; ++ rfrom += 8; ++ } ++ if (len & 4) { ++ Z_BUILTIN_MEMCPY(out, rfrom, 4); ++ out += 4; ++ rfrom += 4; ++ } ++ if (len & 2) { ++ Z_BUILTIN_MEMCPY(out, rfrom, 2); ++ out += 2; ++ rfrom += 2; ++ } ++ if (len & 1) { ++ *out++ = *rfrom++; ++ } ++ return out; ++ } ++ return chunkcopy_core(out, from, len); ++} ++ ++/* ++ * Perform short copies until distance can be rewritten as being at least ++ * CHUNKCOPY_CHUNK_SIZE. ++ * ++ * Assumes it's OK to overwrite at least the first 2*CHUNKCOPY_CHUNK_SIZE ++ * bytes of output even if the copy is shorter than this. This assumption ++ * holds within zlib inflate_fast(), which starts every iteration with at ++ * least 258 bytes of output space available (258 being the maximum length ++ * output from a single token; see inffast.c). ++ */ ++static inline unsigned char FAR* chunkunroll_relaxed( ++ unsigned char FAR* out, ++ unsigned FAR* dist, ++ unsigned FAR* len) ++{ ++ const unsigned char FAR* from = out - *dist; ++ while (*dist < *len && *dist < CHUNKCOPY_CHUNK_SIZE) { ++ storechunk(out, loadchunk(from)); ++ out += *dist; ++ *len -= *dist; ++ *dist += *dist; ++ } ++ return out; ++} ++ ++/* ++ * v_load64_dup(): load *src as an unaligned 64-bit int and duplicate it in ++ * every 64-bit component of the 128-bit result (64-bit int splat). ++ */ ++static inline z_vec128i_t v_load64_dup(const void* src) ++{ ++ return vcombine_u8(vld1_u8(src), vld1_u8(src)); ++} ++ ++/* ++ * v_load32_dup(): load *src as an unaligned 32-bit int and duplicate it in ++ * every 32-bit component of the 128-bit result (32-bit int splat). ++ */ ++static inline z_vec128i_t v_load32_dup(const void* src) ++{ ++ int32_t i32; ++ Z_BUILTIN_MEMCPY(&i32, src, sizeof(i32)); ++ return vreinterpretq_u8_s32(vdupq_n_s32(i32)); ++} ++ ++/* ++ * v_load16_dup(): load *src as an unaligned 16-bit int and duplicate it in ++ * every 16-bit component of the 128-bit result (16-bit int splat). ++ */ ++static inline z_vec128i_t v_load16_dup(const void* src) ++{ ++ int16_t i16; ++ Z_BUILTIN_MEMCPY(&i16, src, sizeof(i16)); ++ return vreinterpretq_u8_s16(vdupq_n_s16(i16)); ++} ++ ++/* ++ * v_load8_dup(): load the 8-bit int *src and duplicate it in every 8-bit ++ * component of the 128-bit result (8-bit int splat). ++ */ ++static inline z_vec128i_t v_load8_dup(const void* src) ++{ ++ return vld1q_dup_u8((const uint8_t*) src); ++} ++ ++/* ++ * v_store_128(): store the 128-bit vec in a memory destination (that might ++ * not be 16-byte aligned) void* out. ++ */ ++static inline void v_store_128(unsigned char* out, const z_vec128i_t vec) ++{ ++ vst1q_u8(out, vec); ++} ++ ++/* ++ * Perform an overlapping copy which behaves as a memset() operation, but ++ * supporting periods other than one, and assume that length is non-zero and ++ * that it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE*3 bytes of output ++ * even if the length is shorter than this. ++ */ ++static inline unsigned char FAR* chunkset_store_result( ++ unsigned len, ++ unsigned char FAR* out, ++ z_vec128i_t v) ++{ ++ do { ++ v_store_128(out, v); ++ out += sizeof(v); ++ len -= sizeof(v); ++ } while (len > 0); ++ return out; ++} ++ ++static inline unsigned char FAR* chunkset_core(unsigned char FAR* out, unsigned period, unsigned len) ++{ ++ z_vec128i_t v; ++ const int bump = ((len - 1) % sizeof(v)) + 1; ++ switch (period) { ++ case 1: ++ v = v_load8_dup(out - 1); ++ v_store_128(out, v); ++ out += bump; ++ len -= bump; ++ while (len > 0) { ++ v_store_128(out, v); ++ out += sizeof(v); ++ len -= sizeof(v); ++ } ++ return out; ++ case 2: ++ v = v_load16_dup(out - 2); ++ v_store_128(out, v); ++ out += bump; ++ len -= bump; ++ if (len > 0) { ++ v = v_load16_dup(out - 2); ++ out = chunkset_store_result(len, out, v); ++ } ++ return out; ++ case 4: ++ v = v_load32_dup(out - 4); ++ v_store_128(out, v); ++ out += bump; ++ len -= bump; ++ if (len > 0) { ++ v = v_load32_dup(out - 4); ++ out = chunkset_store_result(len, out, v); ++ } ++ return out; ++ case 8: ++ v = v_load64_dup(out - 8); ++ v_store_128(out, v); ++ out += bump; ++ len -= bump; ++ if (len > 0) { ++ v = v_load64_dup(out - 8); ++ out = chunkset_store_result(len, out, v); ++ } ++ return out; ++ } ++ out = chunkunroll_relaxed(out, &period, &len); ++ return chunkcopy_core(out, out - period, len); ++} ++ ++/* ++ * Perform a memcpy-like operation, but assume that length is non-zero and that ++ * it's OK to overwrite at least CHUNKCOPY_CHUNK_SIZE bytes of output even if ++ * the length is shorter than this. ++ * ++ * Unlike chunkcopy_core() above, no guarantee is made regarding the behaviour ++ * of overlapping buffers, regardless of the distance between the pointers. ++ * This is reflected in the `restrict`-qualified pointers, allowing the ++ * compiler to re-order loads and stores. ++ */ ++static inline unsigned char FAR* chunkcopy_relaxed( ++ unsigned char FAR* Z_RESTRICT out, ++ const unsigned char FAR* Z_RESTRICT from, ++ unsigned len) ++{ ++ return chunkcopy_core(out, from, len); ++} ++ ++/* ++ * Like chunkcopy_relaxed(), but avoid writing beyond of legal output. ++ * ++ * Unlike chunkcopy_core_safe() above, no guarantee is made regarding the ++ * behaviour of overlapping buffers, regardless of the distance between the ++ * pointers. This is reflected in the `restrict`-qualified pointers, allowing ++ * the compiler to re-order loads and stores. ++ * ++ * Accepts an additional pointer to the end of safe output. A generic safe ++ * copy would use (out + len), but it's normally the case that the end of the ++ * output buffer is beyond the end of the current copy, and this can still be ++ * exploited. ++ */ ++static inline unsigned char FAR* chunkcopy_safe( ++ unsigned char FAR* out, ++ const unsigned char FAR* Z_RESTRICT from, ++ unsigned len, ++ unsigned char FAR* limit) ++{ ++ Assert(out + len <= limit, "chunk copy exceeds safety limit"); ++ return chunkcopy_core_safe(out, from, len, limit); ++} ++ ++/* ++ * Perform chunky copy within the same buffer, where the source and destination ++ * may potentially overlap. ++ * ++ * Assumes that len > 0 on entry, and that it's safe to write at least ++ * CHUNKCOPY_CHUNK_SIZE*3 bytes to the output. ++ */ ++static inline unsigned char FAR* chunkcopy_lapped_relaxed( ++ unsigned char FAR* out, ++ unsigned dist, ++ unsigned len) ++{ ++ if (dist < len && dist < CHUNKCOPY_CHUNK_SIZE) { ++ return chunkset_core(out, dist, len); ++ } ++ return chunkcopy_core(out, out - dist, len); ++} ++ ++/* ++ * Behave like chunkcopy_lapped_relaxed(), but avoid writing beyond of legal ++ * output. ++ * ++ * Accepts an additional pointer to the end of safe output. A generic safe ++ * copy would use (out + len), but it's normally the case that the end of the ++ * output buffer is beyond the end of the current copy, and this can still be ++ * exploited. ++ */ ++static inline unsigned char FAR* chunkcopy_lapped_safe( ++ unsigned char FAR* out, ++ unsigned dist, ++ unsigned len, ++ unsigned char FAR* limit) ++{ ++ Assert(out + len <= limit, "chunk copy exceeds safety limit"); ++ if ((limit - out) < (ptrdiff_t) (3 * CHUNKCOPY_CHUNK_SIZE)) { ++ while (len-- > 0) { ++ *out = *(out - dist); ++ out++; ++ } ++ return out; ++ } ++ return chunkcopy_lapped_relaxed(out, dist, len); ++} ++ ++ ++#undef Z_STATIC_ASSERT ++#undef Z_RESTRICT ++#undef Z_BUILTIN_MEMCPY ++ ++#endif //defined(INFLATE_CHUNK_SIMD_NEON) +diff --git a/jdk/src/share/native/java/util/zip/zlib/inflate.c b/jdk/src/share/native/java/util/zip/zlib/inflate.c +index ca904e7..c78e05b 100644 +--- a/jdk/src/share/native/java/util/zip/zlib/inflate.c ++++ b/jdk/src/share/native/java/util/zip/zlib/inflate.c +@@ -429,9 +429,16 @@ unsigned copy; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { ++#if defined(INFLATE_CHUNK_SIMD_NEON) ++ unsigned wsize = 1U << state->wbits; ++ state->window = (unsigned char FAR *) ++ ZALLOC(strm, CHUNKCOPY_CHUNK_SIZE + wsize, ++ sizeof(unsigned char)); ++#else + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); ++#endif + if (state->window == Z_NULL) return 1; + } + +diff --git a/jdk/src/share/native/java/util/zip/zlib/zadler32.c b/jdk/src/share/native/java/util/zip/zlib/zadler32.c +index e148022..e024a15 100644 +--- a/jdk/src/share/native/java/util/zip/zlib/zadler32.c ++++ b/jdk/src/share/native/java/util/zip/zlib/zadler32.c +@@ -83,7 +83,169 @@ local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); + # define MOD63(a) a %= BASE + #endif + +-/* ========================================================================= */ ++#if defined(ADLER32_SIMD_NEON) ++#include ++/* ++ * Multiply-add bytes by [ 32, 31, 30, ... ] for s2. ++ */ ++uint32x4_t ZLIB_INTERNAL mul_add_bytes( ++ uint32x4_t v_s2, ++ uint16x8_t v_column_sum_1, ++ uint16x8_t v_column_sum_2, ++ uint16x8_t v_column_sum_3, ++ uint16x8_t v_column_sum_4) ++{ ++ v_s2 = vshlq_n_u32(v_s2, 5); ++ ++ v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_1), ++ (uint16x4_t) { 32, 31, 30, 29 }); ++ v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_1), ++ (uint16x4_t) { 28, 27, 26, 25 }); ++ v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_2), ++ (uint16x4_t) { 24, 23, 22, 21 }); ++ v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_2), ++ (uint16x4_t) { 20, 19, 18, 17 }); ++ v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_3), ++ (uint16x4_t) { 16, 15, 14, 13 }); ++ v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_3), ++ (uint16x4_t) { 12, 11, 10, 9 }); ++ v_s2 = vmlal_u16(v_s2, vget_low_u16 (v_column_sum_4), ++ (uint16x4_t) { 8, 7, 6, 5 }); ++ v_s2 = vmlal_u16(v_s2, vget_high_u16(v_column_sum_4), ++ (uint16x4_t) { 4, 3, 2, 1 }); ++ return v_s2; ++} ++ ++/* ++ * Handle leftover data. ++ */ ++uLong ZLIB_INTERNAL leftover_handler(uint32_t s1, uint32_t s2, const Bytef *buf, z_size_t len) ++{ ++ if (len) { ++ if (len >= 16) { ++ s2 += (s1 += *buf++); ++ s2 += (s1 += *buf++); ++ s2 += (s1 += *buf++); ++ s2 += (s1 += *buf++); ++ ++ s2 += (s1 += *buf++); ++ s2 += (s1 += *buf++); ++ s2 += (s1 += *buf++); ++ s2 += (s1 += *buf++); ++ ++ s2 += (s1 += *buf++); ++ s2 += (s1 += *buf++); ++ s2 += (s1 += *buf++); ++ s2 += (s1 += *buf++); ++ ++ s2 += (s1 += *buf++); ++ s2 += (s1 += *buf++); ++ s2 += (s1 += *buf++); ++ s2 += (s1 += *buf++); ++ ++ len -= 16; ++ } ++ ++ while (len--) { ++ s2 += (s1 += *buf++); ++ } ++ ++ if (s1 >= BASE) ++ s1 -= BASE; ++ s2 %= BASE; ++ } ++ ++ /* ++ * Return the recombined sums. ++ */ ++ return s1 | (s2 << 16); ++} ++ ++uLong ZLIB_INTERNAL adler32_simd_(uLong adler, const Bytef *buf, z_size_t len) ++{ ++ /* ++ * Split Adler-32 into component sums. ++ */ ++ uint32_t s1 = adler & 0xffff; ++ uint32_t s2 = adler >> 16; ++ /* ++ * Serially compute s1 & s2, until the data is 16-byte aligned. ++ */ ++ if ((uintptr_t)buf & 0xf) { ++ while ((uintptr_t)buf & 0xf) { ++ s2 += (s1 += *buf++); ++ --len; ++ } ++ if (s1 >= BASE) ++ s1 -= BASE; ++ s2 %= BASE; ++ } ++ /* ++ * Process the data in blocks. ++ */ ++ const unsigned BLOCK_SIZE = 1 << 5; ++ z_size_t blocks = len / BLOCK_SIZE; ++ len -= blocks * BLOCK_SIZE; ++ while (blocks) { ++ unsigned n = NMAX / BLOCK_SIZE; /* The NMAX constraint. */ ++ if (n > blocks) ++ n = (unsigned) blocks; ++ blocks -= n; ++ /* ++ * Process n blocks of data. At most NMAX data bytes can be ++ * processed before s2 must be reduced modulo BASE. ++ */ ++ uint32x4_t v_s2 = (uint32x4_t) { 0, 0, 0, s1 * n }; ++ uint32x4_t v_s1 = (uint32x4_t) { 0, 0, 0, 0 }; ++ ++ uint16x8_t v_column_sum_1 = vdupq_n_u16(0); ++ uint16x8_t v_column_sum_2 = vdupq_n_u16(0); ++ uint16x8_t v_column_sum_3 = vdupq_n_u16(0); ++ uint16x8_t v_column_sum_4 = vdupq_n_u16(0); ++ do { ++ /* ++ * Load 32 input bytes. ++ */ ++ const uint8x16_t bytes1 = vld1q_u8((uint8_t*)(buf)); ++ const uint8x16_t bytes2 = vld1q_u8((uint8_t*)(buf + 16)); ++ /* ++ * Add previous block byte sum to v_s2. ++ */ ++ v_s2 = vaddq_u32(v_s2, v_s1); ++ /* ++ * Horizontally add the bytes for s1. ++ */ ++ v_s1 = vpadalq_u16(v_s1, vpadalq_u8(vpaddlq_u8(bytes1), bytes2)); ++ /* ++ * Vertically add the bytes for s2. ++ */ ++ v_column_sum_1 = vaddw_u8(v_column_sum_1, vget_low_u8 (bytes1)); ++ v_column_sum_2 = vaddw_u8(v_column_sum_2, vget_high_u8(bytes1)); ++ v_column_sum_3 = vaddw_u8(v_column_sum_3, vget_low_u8 (bytes2)); ++ v_column_sum_4 = vaddw_u8(v_column_sum_4, vget_high_u8(bytes2)); ++ buf += BLOCK_SIZE; ++ } while (--n); ++ v_s2 = mul_add_bytes(v_s2, v_column_sum_1, v_column_sum_2, v_column_sum_3, v_column_sum_4); ++ /* ++ * Sum epi32 ints v_s1(s2) and accumulate in s1(s2). ++ */ ++ uint32x2_t sum1 = vpadd_u32(vget_low_u32(v_s1), vget_high_u32(v_s1)); ++ uint32x2_t sum2 = vpadd_u32(vget_low_u32(v_s2), vget_high_u32(v_s2)); ++ uint32x2_t s1s2 = vpadd_u32(sum1, sum2); ++ ++ s1 += vget_lane_u32(s1s2, 0); ++ s2 += vget_lane_u32(s1s2, 1); ++ /* ++ * Reduce. ++ */ ++ s1 %= BASE; ++ s2 %= BASE; ++ } ++ return leftover_handler(s1, s2, buf, len); ++ ++} ++#endif ++ + uLong ZEXPORT adler32_z(adler, buf, len) + uLong adler; + const Bytef *buf; +@@ -92,6 +254,11 @@ uLong ZEXPORT adler32_z(adler, buf, len) + unsigned long sum2; + unsigned n; + ++#if defined(ADLER32_SIMD_NEON) ++ if (buf && len >= 64) ++ return adler32_simd_(adler, buf, len); ++#endif ++ + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; +diff --git a/jdk/src/share/native/java/util/zip/zlib/zcrc32.c b/jdk/src/share/native/java/util/zip/zlib/zcrc32.c +index c1965fd..ee4e440 100644 +--- a/jdk/src/share/native/java/util/zip/zlib/zcrc32.c ++++ b/jdk/src/share/native/java/util/zip/zlib/zcrc32.c +@@ -257,7 +257,56 @@ uLong ZEXPORT crc32_z(crc, buf, len) + return crc ^ 0xffffffffUL; + } + +-/* ========================================================================= */ ++ ++#ifdef CRC32_ARMV8_CRC32 ++#include ++ ++uLong ZEXPORT crc32(crc, buf, len) ++ uLong crc; ++ const unsigned char FAR *buf; ++ uInt len; ++{ ++ ++ uint32_t c = (uint32_t) ~crc; ++ ++ if (buf == Z_NULL) return 0UL; ++ ++ while (len && ((uintptr_t)buf & 7)) { ++ c = __crc32b(c, *buf++); ++ --len; ++ } ++ ++ const uint64_t *buf8 = (const uint64_t *)buf; ++ ++ while (len >= 64) { ++ c = __crc32d(c, *buf8++); ++ c = __crc32d(c, *buf8++); ++ c = __crc32d(c, *buf8++); ++ c = __crc32d(c, *buf8++); ++ ++ c = __crc32d(c, *buf8++); ++ c = __crc32d(c, *buf8++); ++ c = __crc32d(c, *buf8++); ++ c = __crc32d(c, *buf8++); ++ len -= 64; ++ } ++ ++ while (len >= 8) { ++ c = __crc32d(c, *buf8++); ++ len -= 8; ++ } ++ ++ buf = (const unsigned char *)buf8; ++ ++ while (len--) { ++ c = __crc32b(c, *buf++); ++ } ++ ++ return ~c; ++} ++ ++#else ++ + uLong ZEXPORT crc32(crc, buf, len) + uLong crc; + const unsigned char FAR *buf; +@@ -266,6 +315,8 @@ uLong ZEXPORT crc32(crc, buf, len) + return crc32_z(crc, buf, len); + } + ++#endif ++ + #ifdef BYFOUR + + /*