diff --git a/0041-Reuse-translet-in-XSLTC-for-specjvm-xml-transform.patch b/0041-Reuse-translet-in-XSLTC-for-specjvm-xml-transform.patch index 5b34c97f9692845f84b0baeb83c3cfa35f5f885c..dcbde36ca0ef49a79424e320ce16252973c95551 100644 --- a/0041-Reuse-translet-in-XSLTC-for-specjvm-xml-transform.patch +++ b/0041-Reuse-translet-in-XSLTC-for-specjvm-xml-transform.patch @@ -8,7 +8,9 @@ Subject: Reuse translet in XSLTC for XML hotspot/src/share/vm/runtime/arguments.cpp | 2 + hotspot/src/share/vm/runtime/arguments.hpp | 3 + .../src/share/vm/utilities/accessFlags.hpp | 1 + - 7 files changed, 64 insertions(+), 3 deletions(-) + .../transform/TestXmlTransletEnhance.java | 83 +++++++++++++++++++ + 8 files changed, 144 insertions(+), 3 deletions(-) + create mode 100644 jdk/test/javax/xml/jaxp/transform/TestXmlTransletEnhance.java diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index d8e99e622..b9fde38dc 100644 @@ -180,6 +182,95 @@ index bc56262d1..b20f0f740 100644 void set_has_finalizer() { atomic_set_bits(JVM_ACC_HAS_FINALIZER); } void set_has_final_method() { atomic_set_bits(JVM_ACC_HAS_FINAL_METHOD); } void set_is_cloneable() { atomic_set_bits(JVM_ACC_IS_CLONEABLE); } +diff --git a/jdk/test/javax/xml/jaxp/transform/TestXmlTransletEnhance.java b/jdk/test/javax/xml/jaxp/transform/TestXmlTransletEnhance.java +new file mode 100644 +index 000000000..73b848de8 +--- /dev/null ++++ b/jdk/test/javax/xml/jaxp/transform/TestXmlTransletEnhance.java +@@ -0,0 +1,83 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2012-2023. All rights reserved. ++ */ ++ ++ ++/* @test ++ * @summary a test for xml translet enhance ++ * @library /lib/testlibrary ++ * @run main TestXmlTransletEnhance ++ */ ++ ++import javax.xml.transform.TransformerFactory; ++import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl; ++import java.lang.reflect.Field; ++import static jdk.testlibrary.Asserts.assertEquals; ++ ++public class TestXmlTransletEnhance { ++ static final boolean expectedResult = true; ++ ++ public static void main(String[] args) throws InterruptedException { ++ ++ Thread thread = new Mythread("BenchmarkThread xml "); ++ thread.start(); ++ thread.join(); ++ boolean ret = SharedData.getInstance().getResult(); ++ assertEquals(ret, expectedResult); ++ ++ } ++ ++ static class Mythread extends Thread { ++ Mythread(String name){ ++ super(name); ++ } ++ ++ @Override ++ public void run(){ ++ ++ try { ++ ++ TransformerFactory tf = TransformerFactory.newInstance(); ++ TransformerFactoryImpl transformer = new TransformerFactoryImpl(); ++ Class clazz = transformer.getClass(); ++ ++ Field generateTransletFiled = clazz.getDeclaredField("_generateTranslet"); ++ Field autoTransletFiled = clazz.getDeclaredField("_autoTranslet"); ++ ++ generateTransletFiled.setAccessible(true); ++ autoTransletFiled.setAccessible(true); ++ ++ boolean value1 = (boolean)generateTransletFiled.get(transformer); ++ boolean value2 = (boolean)autoTransletFiled.get(transformer); ++ ++ SharedData.getInstance().setResult(value1 && value2); ++ ++ } catch (NoSuchFieldException| IllegalAccessException | SecurityException | IllegalArgumentException e) { ++ e.printStackTrace(); ++ } ++ } ++ } ++ ++ static class SharedData { ++ private static SharedData instance; ++ private boolean result; ++ ++ private SharedData() { ++ } ++ ++ public static synchronized SharedData getInstance() { ++ if (instance == null) { ++ instance = new SharedData(); ++ } ++ return instance; ++ } ++ ++ public synchronized boolean getResult() { ++ return result; ++ } ++ ++ public synchronized void setResult(boolean result) { ++ this.result = result; ++ } ++ } ++} -- 2.22.0 diff --git a/8148470-Metadata-print-routines-should-not-print-to-.patch b/8148470-Metadata-print-routines-should-not-print-to-.patch deleted file mode 100644 index 501cb3c8501c91e651f2f0627afbc2edac793066..0000000000000000000000000000000000000000 --- a/8148470-Metadata-print-routines-should-not-print-to-.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 42bb9ed9c5d4b0c8b07fb184ce1ab26718b376a5 Mon Sep 17 00:00:00 2001 -Subject: 8148470: Metadata print routines should not print to tty ---- - hotspot/src/share/vm/oops/metadata.hpp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/hotspot/src/share/vm/oops/metadata.hpp b/hotspot/src/share/vm/oops/metadata.hpp -index 372faa953..34dd66afd 100644 ---- a/hotspot/src/share/vm/oops/metadata.hpp -+++ b/hotspot/src/share/vm/oops/metadata.hpp -@@ -60,13 +60,13 @@ class Metadata : public MetaspaceObj { - if (this == NULL) - st->print("NULL"); - else -- print_on(tty); -+ print_on(st); - } - void print_value_on_maybe_null(outputStream* st) const { - if (this == NULL) - st->print("NULL"); - else -- print_value_on(tty); -+ print_value_on(st); - } - - virtual void print_on(outputStream* st) const; // First level print --- -2.22.0 - diff --git a/8193682-Infinite-loop-in-ZipOutputStream.close.patch b/8193682-Infinite-loop-in-ZipOutputStream.close.patch deleted file mode 100644 index 628b67fbfa20b14d45a40f0494b85819951e10a0..0000000000000000000000000000000000000000 --- a/8193682-Infinite-loop-in-ZipOutputStream.close.patch +++ /dev/null @@ -1,352 +0,0 @@ -From ba4213c7350e7a145a142d0cbe54718a8c92b93c Mon Sep 17 00:00:00 2001 -Subject: 8193682: Infinite loop in ZipOutputStream.close() ---- - .../java/util/zip/DeflaterOutputStream.java | 9 +- - .../java/util/zip/GZIPOutputStream.java | 38 +++-- - .../java/util/zip/ZipOutputStream.java | 96 ++++++------ - jdk/test/java/util/zip/CloseDeflaterTest.java | 147 ++++++++++++++++++ - 4 files changed, 226 insertions(+), 64 deletions(-) - create mode 100644 jdk/test/java/util/zip/CloseDeflaterTest.java - -diff --git a/jdk/src/share/classes/java/util/zip/DeflaterOutputStream.java b/jdk/src/share/classes/java/util/zip/DeflaterOutputStream.java -index a1f768cae..f4cf79693 100644 ---- a/jdk/src/share/classes/java/util/zip/DeflaterOutputStream.java -+++ b/jdk/src/share/classes/java/util/zip/DeflaterOutputStream.java -@@ -235,9 +235,12 @@ class DeflaterOutputStream extends FilterOutputStream { - */ - public void close() throws IOException { - if (!closed) { -- finish(); -- if (usesDefaultDeflater) -- def.end(); -+ try { -+ finish(); -+ } finally { -+ if (usesDefaultDeflater) -+ def.end(); -+ } - out.close(); - closed = true; - } -diff --git a/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java b/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java -index 2c1cd409b..1c3f8592e 100644 ---- a/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java -+++ b/jdk/src/share/classes/java/util/zip/GZIPOutputStream.java -@@ -154,24 +154,30 @@ class GZIPOutputStream extends DeflaterOutputStream { - */ - public void finish() throws IOException { - if (!def.finished()) { -- def.finish(); -- while (!def.finished()) { -- int len = def.deflate(buf, 0, buf.length); -- if (def.finished() && len <= buf.length - TRAILER_SIZE) { -- // last deflater buffer. Fit trailer at the end -- writeTrailer(buf, len); -- len = len + TRAILER_SIZE; -- out.write(buf, 0, len); -- return; -+ try { -+ def.finish(); -+ while (!def.finished()) { -+ int len = def.deflate(buf, 0, buf.length); -+ if (def.finished() && len <= buf.length - TRAILER_SIZE) { -+ // last deflater buffer. Fit trailer at the end -+ writeTrailer(buf, len); -+ len = len + TRAILER_SIZE; -+ out.write(buf, 0, len); -+ return; -+ } -+ if (len > 0) -+ out.write(buf, 0, len); - } -- if (len > 0) -- out.write(buf, 0, len); -+ // if we can't fit the trailer at the end of the last -+ // deflater buffer, we write it separately -+ byte[] trailer = new byte[TRAILER_SIZE]; -+ writeTrailer(trailer, 0); -+ out.write(trailer); -+ } catch (IOException e) { -+ if (usesDefaultDeflater) -+ def.end(); -+ throw e; - } -- // if we can't fit the trailer at the end of the last -- // deflater buffer, we write it separately -- byte[] trailer = new byte[TRAILER_SIZE]; -- writeTrailer(trailer, 0); -- out.write(trailer); - } - } - -diff --git a/jdk/src/share/classes/java/util/zip/ZipOutputStream.java b/jdk/src/share/classes/java/util/zip/ZipOutputStream.java -index 6b480aa1d..f001ddf00 100644 ---- a/jdk/src/share/classes/java/util/zip/ZipOutputStream.java -+++ b/jdk/src/share/classes/java/util/zip/ZipOutputStream.java -@@ -247,59 +247,65 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { - public void closeEntry() throws IOException { - ensureOpen(); - if (current != null) { -- ZipEntry e = current.entry; -- switch (e.method) { -- case DEFLATED: -- def.finish(); -- while (!def.finished()) { -- deflate(); -- } -- if ((e.flag & 8) == 0) { -- // verify size, compressed size, and crc-32 settings -- if (e.size != def.getBytesRead()) { -- throw new ZipException( -- "invalid entry size (expected " + e.size + -- " but got " + def.getBytesRead() + " bytes)"); -+ try { -+ ZipEntry e = current.entry; -+ switch (e.method) { -+ case DEFLATED: -+ def.finish(); -+ while (!def.finished()) { -+ deflate(); - } -- if (e.csize != def.getBytesWritten()) { -+ if ((e.flag & 8) == 0) { -+ // verify size, compressed size, and crc-32 settings -+ if (e.size != def.getBytesRead()) { -+ throw new ZipException( -+ "invalid entry size (expected " + e.size + -+ " but got " + def.getBytesRead() + " bytes)"); -+ } -+ if (e.csize != def.getBytesWritten()) { -+ throw new ZipException( -+ "invalid entry compressed size (expected " + -+ e.csize + " but got " + def.getBytesWritten() + " bytes)"); -+ } -+ if (e.crc != crc.getValue()) { -+ throw new ZipException( -+ "invalid entry CRC-32 (expected 0x" + -+ Long.toHexString(e.crc) + " but got 0x" + -+ Long.toHexString(crc.getValue()) + ")"); -+ } -+ } else { -+ e.size = def.getBytesRead(); -+ e.csize = def.getBytesWritten(); -+ e.crc = crc.getValue(); -+ writeEXT(e); -+ } -+ def.reset(); -+ written += e.csize; -+ break; -+ case STORED: -+ // we already know that both e.size and e.csize are the same -+ if (e.size != written - locoff) { - throw new ZipException( -- "invalid entry compressed size (expected " + -- e.csize + " but got " + def.getBytesWritten() + " bytes)"); -+ "invalid entry size (expected " + e.size + -+ " but got " + (written - locoff) + " bytes)"); - } - if (e.crc != crc.getValue()) { - throw new ZipException( -- "invalid entry CRC-32 (expected 0x" + -- Long.toHexString(e.crc) + " but got 0x" + -- Long.toHexString(crc.getValue()) + ")"); -+ "invalid entry crc-32 (expected 0x" + -+ Long.toHexString(e.crc) + " but got 0x" + -+ Long.toHexString(crc.getValue()) + ")"); - } -- } else { -- e.size = def.getBytesRead(); -- e.csize = def.getBytesWritten(); -- e.crc = crc.getValue(); -- writeEXT(e); -+ break; -+ default: -+ throw new ZipException("invalid compression method"); - } -- def.reset(); -- written += e.csize; -- break; -- case STORED: -- // we already know that both e.size and e.csize are the same -- if (e.size != written - locoff) { -- throw new ZipException( -- "invalid entry size (expected " + e.size + -- " but got " + (written - locoff) + " bytes)"); -- } -- if (e.crc != crc.getValue()) { -- throw new ZipException( -- "invalid entry crc-32 (expected 0x" + -- Long.toHexString(e.crc) + " but got 0x" + -- Long.toHexString(crc.getValue()) + ")"); -- } -- break; -- default: -- throw new ZipException("invalid compression method"); -+ crc.reset(); -+ current = null; -+ } catch (IOException e) { -+ if (usesDefaultDeflater && !(e instanceof ZipException)) -+ def.end(); -+ throw e; - } -- crc.reset(); -- current = null; - } - } - -diff --git a/jdk/test/java/util/zip/CloseDeflaterTest.java b/jdk/test/java/util/zip/CloseDeflaterTest.java -new file mode 100644 -index 000000000..8aa4960f5 ---- /dev/null -+++ b/jdk/test/java/util/zip/CloseDeflaterTest.java -@@ -0,0 +1,147 @@ -+/* -+ * Copyright (c) 2021, 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 8193682 -+ * @summary Test Infinite loop while writing on closed GZipOutputStream , ZipOutputStream and JarOutputStream. -+ * @run testng CloseDeflaterTest -+ */ -+import java.io.*; -+import java.util.Random; -+import java.util.jar.JarOutputStream; -+import java.util.zip.GZIPOutputStream; -+import java.util.zip.ZipOutputStream; -+import java.util.zip.ZipEntry; -+ -+import org.testng.annotations.BeforeTest; -+import org.testng.annotations.DataProvider; -+import org.testng.annotations.Test; -+import static org.testng.Assert.fail; -+ -+ -+public class CloseDeflaterTest { -+ -+ //number of bytes to write -+ private static final int INPUT_LENGTH= 512; -+ //OutputStream that will throw an exception during a write operation -+ private static OutputStream outStream = new OutputStream() { -+ @Override -+ public void write(byte[] b, int off, int len) throws IOException { -+ //throw exception during write -+ throw new IOException(); -+ } -+ @Override -+ public void write(byte b[]) throws IOException {} -+ @Override -+ public void write(int b) throws IOException {} -+ }; -+ private static byte[] inputBytes = new byte[INPUT_LENGTH]; -+ private static Random rand = new Random(); -+ -+ @DataProvider(name = "testgzipinput") -+ public Object[][] testGZipInput() { -+ //testGZip will close the GZipOutputStream using close() method when the boolean -+ //useCloseMethod is set to true and finish() method if the value is set to false -+ return new Object[][] { -+ { GZIPOutputStream.class, true }, -+ { GZIPOutputStream.class, false }, -+ }; -+ } -+ -+ @DataProvider(name = "testzipjarinput") -+ public Object[][] testZipAndJarInput() { -+ //testZipAndJarInput will perfrom write/closeEntry operations on JarOutputStream when the boolean -+ //useJar is set to true and on ZipOutputStream if the value is set to false -+ return new Object[][] { -+ { JarOutputStream.class, true }, -+ { ZipOutputStream.class, false }, -+ }; -+ } -+ -+ @BeforeTest -+ public void before_test() -+ { -+ //add inputBytes array with random bytes to write into Zip -+ rand.nextBytes(inputBytes); -+ } -+ -+ //Test for infinite loop by writing bytes to closed GZIPOutputStream -+ @Test(dataProvider = "testgzipinput") -+ public void testGZip(Class type, boolean useCloseMethod) throws IOException { -+ GZIPOutputStream zip = new GZIPOutputStream(outStream); -+ try { -+ zip.write(inputBytes, 0, INPUT_LENGTH); -+ //close zip -+ if(useCloseMethod) { -+ zip.close(); -+ } else { -+ zip.finish(); -+ } -+ } catch (IOException e) { -+ //expected -+ } -+ for (int i = 0; i < 3; i++) { -+ try { -+ //write on a closed GZIPOutputStream -+ zip.write(inputBytes, 0, INPUT_LENGTH); -+ fail("Deflater closed exception not thrown"); -+ } catch (NullPointerException e) { -+ //expected , Deflater has been closed exception -+ } -+ } -+ } -+ -+ //Test for infinite loop by writing bytes to closed ZipOutputStream/JarOutputStream -+ @Test(dataProvider = "testzipjarinput") -+ public void testZipCloseEntry(Class type,boolean useJar) throws IOException { -+ ZipOutputStream zip = null; -+ if(useJar) { -+ zip = new JarOutputStream(outStream); -+ } else { -+ zip = new ZipOutputStream(outStream); -+ } -+ try { -+ zip.putNextEntry(new ZipEntry("")); -+ } catch (IOException e) { -+ //expected to throw IOException since putNextEntry calls write method -+ } -+ try { -+ zip.write(inputBytes, 0, INPUT_LENGTH); -+ //close zip entry -+ zip.closeEntry(); -+ } catch (IOException e) { -+ //expected -+ } -+ for (int i = 0; i < 3; i++) { -+ try { -+ //write on a closed ZipOutputStream -+ zip.write(inputBytes, 0, INPUT_LENGTH); -+ fail("Deflater closed exception not thrown"); -+ } catch (NullPointerException e) { -+ //expected , Deflater has been closed exception -+ } -+ } -+ } -+ -+} --- -2.22.0 - diff --git a/8202952.patch b/8202952.patch new file mode 100644 index 0000000000000000000000000000000000000000..368a3934ee5c1d0ea1d93bd6b948cc6543f298c7 --- /dev/null +++ b/8202952.patch @@ -0,0 +1,25 @@ +From 5fafa8bd0a85d93ff0480bc2d163c4070742d8f5 Mon Sep 17 00:00:00 2001 +Date: Fri, 22 Jan 2021 11:26:11 +0800 +Subject: 8202952:C2:Unexpected dead nodes after + matching + +Bug url: https://bugs.openjdk.java.net/browse/JDK-8202952 +--- + hotspot/src/share/vm/opto/matcher.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp +index 70e8af221..f5d30c3af 100644 +--- a/hotspot/src/share/vm/opto/matcher.cpp ++++ b/hotspot/src/share/vm/opto/matcher.cpp +@@ -2230,6 +2230,7 @@ void Matcher::find_shared( Node *n ) { + // AtomicAdd is not an addressing expression. + // Cheap to find it by looking for screwy base. + !adr->in(AddPNode::Base)->is_top() && ++ LP64_ONLY( off->get_long() == (int) (off->get_long()) && ) // immL32 + // Are there other uses besides address expressions? + !is_visited(adr) ) { + address_visited.set(adr->_idx); // Flag as address_visited +-- +2.19.0 + diff --git a/8213397-Stack-dump-should-show-more-clearly-when-a-t.patch b/8213397-Stack-dump-should-show-more-clearly-when-a-t.patch deleted file mode 100644 index b45886f2f94db57bc5ae6ebf379c34e3a849ce18..0000000000000000000000000000000000000000 --- a/8213397-Stack-dump-should-show-more-clearly-when-a-t.patch +++ /dev/null @@ -1,392 +0,0 @@ -From 3a774c78473c4fc3dcd1dc39f8c9daec4c5a6502 Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 14:45:54 +0800 -Subject: 8213397-Stack-dump-should-show-more-clearly-when-a-t.patch - ---- - hotspot/src/share/vm/oops/instanceKlass.cpp | 23 +- - hotspot/src/share/vm/runtime/thread.cpp | 2 + - hotspot/src/share/vm/runtime/thread.hpp | 8 + - .../src/share/vm/runtime/thread.inline.hpp | 12 + - hotspot/src/share/vm/runtime/vframe.cpp | 8 + - .../TestThreadDumpClassInitMonitor.java | 217 ++++++++++++++++++ - 6 files changed, 259 insertions(+), 11 deletions(-) - create mode 100644 hotspot/test/runtime/Thread/TestThreadDumpClassInitMonitor.java - -diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp -index 538645bbe..993778270 100644 ---- a/hotspot/src/share/vm/oops/instanceKlass.cpp -+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp -@@ -920,25 +920,28 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) { - - bool wait = false; - -+ assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl"); -+ JavaThread* jt = (JavaThread*)THREAD; -+ - // refer to the JVM book page 47 for description of steps - // Step 1 - { - oop init_lock = this_oop->init_lock(); - ObjectLocker ol(init_lock, THREAD, init_lock != NULL); - -- Thread *self = THREAD; // it's passed the current thread -- - // Step 2 - // If we were to use wait() instead of waitInterruptibly() then - // we might end up throwing IE from link/symbol resolution sites - // that aren't expected to throw. This would wreak havoc. See 6320309. -- while(this_oop->is_being_initialized() && !this_oop->is_reentrant_initialization(self)) { -- wait = true; -- ol.waitUninterruptibly(CHECK); -+ while (this_oop->is_being_initialized() && !this_oop->is_reentrant_initialization(jt)) { -+ wait = true; -+ jt->set_class_to_be_initialized(this_oop()); -+ ol.waitUninterruptibly(jt); -+ jt->set_class_to_be_initialized(NULL); - } - - // Step 3 -- if (this_oop->is_being_initialized() && this_oop->is_reentrant_initialization(self)) { -+ if (this_oop->is_being_initialized() && this_oop->is_reentrant_initialization(jt)) { - DTRACE_CLASSINIT_PROBE_WAIT(recursive, InstanceKlass::cast(this_oop()), -1,wait); - return; - } -@@ -968,7 +971,7 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) { - - // Step 6 - this_oop->set_init_state(being_initialized); -- this_oop->set_init_thread(self); -+ this_oop->set_init_thread(jt); - } - - // Step 7 -@@ -1004,8 +1007,6 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) { - - // Step 8 - { -- assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl"); -- JavaThread* jt = (JavaThread*)THREAD; - DTRACE_CLASSINIT_PROBE_WAIT(clinit, InstanceKlass::cast(this_oop()), -1,wait); - // Timer includes any side effects of class initialization (resolution, - // etc), but not recursive entry into call_class_initializer(). -@@ -1031,14 +1032,14 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) { - CLEAR_PENDING_EXCEPTION; - // JVMTI has already reported the pending exception - // JVMTI internal flag reset is needed in order to report ExceptionInInitializerError -- JvmtiExport::clear_detected_exception((JavaThread*)THREAD); -+ JvmtiExport::clear_detected_exception(jt); - { - EXCEPTION_MARK; - this_oop->set_initialization_state_and_notify(initialization_error, THREAD); - CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below - // JVMTI has already reported the pending exception - // JVMTI internal flag reset is needed in order to report ExceptionInInitializerError -- JvmtiExport::clear_detected_exception((JavaThread*)THREAD); -+ JvmtiExport::clear_detected_exception(jt); - } - DTRACE_CLASSINIT_PROBE_WAIT(error, InstanceKlass::cast(this_oop()), -1,wait); - if (e->is_a(SystemDictionary::Error_klass())) { -diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp -index 2be226463..50543ac73 100644 ---- a/hotspot/src/share/vm/runtime/thread.cpp -+++ b/hotspot/src/share/vm/runtime/thread.cpp -@@ -1538,6 +1538,8 @@ void JavaThread::initialize() { - _popframe_preserved_args_size = 0; - _frames_to_pop_failed_realloc = 0; - -+_class_to_be_initialized = NULL; -+ - pd_initialize(); - } - -diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp -index 220fe9316..1d3caf9aa 100644 ---- a/hotspot/src/share/vm/runtime/thread.hpp -+++ b/hotspot/src/share/vm/runtime/thread.hpp -@@ -1802,11 +1802,19 @@ public: - bool is_attaching_via_jni() const { return _jni_attach_state == _attaching_via_jni; } - bool has_attached_via_jni() const { return is_attaching_via_jni() || _jni_attach_state == _attached_via_jni; } - inline void set_done_attaching_via_jni(); -+ -+ // Stack dump assistance: Track the class we want to initialize but for which we have to wait -+ // on its init_lock() because it is already being initialized. -+ inline void set_class_to_be_initialized(InstanceKlass* k); -+ inline InstanceKlass* class_to_be_initialized() const; -+ - private: - // This field is used to determine if a thread has claimed - // a par_id: it is UINT_MAX if the thread has not claimed a par_id; - // otherwise its value is the par_id that has been claimed. - uint _claimed_par_id; -+ -+ InstanceKlass* _class_to_be_initialized; - public: - uint get_claimed_par_id() { return _claimed_par_id; } - void set_claimed_par_id(uint id) { _claimed_par_id = id;} -diff --git a/hotspot/src/share/vm/runtime/thread.inline.hpp b/hotspot/src/share/vm/runtime/thread.inline.hpp -index b05e0ec5c..d3ab3aba9 100644 ---- a/hotspot/src/share/vm/runtime/thread.inline.hpp -+++ b/hotspot/src/share/vm/runtime/thread.inline.hpp -@@ -74,4 +74,16 @@ inline void JavaThread::set_done_attaching_via_jni() { - OrderAccess::fence(); - } - -+// Allow tracking of class initialization monitor use -+inline void JavaThread::set_class_to_be_initialized(InstanceKlass* k) { -+ assert((k == NULL && _class_to_be_initialized != NULL) || -+ (k != NULL && _class_to_be_initialized == NULL), "incorrect usage"); -+ assert(this == Thread::current(), "Only the current thread can set this field"); -+ _class_to_be_initialized = k; -+} -+ -+inline InstanceKlass* JavaThread::class_to_be_initialized() const { -+ return _class_to_be_initialized; -+} -+ - #endif // SHARE_VM_RUNTIME_THREAD_INLINE_HPP -diff --git a/hotspot/src/share/vm/runtime/vframe.cpp b/hotspot/src/share/vm/runtime/vframe.cpp -index b3a6d0770..93d62ade7 100644 ---- a/hotspot/src/share/vm/runtime/vframe.cpp -+++ b/hotspot/src/share/vm/runtime/vframe.cpp -@@ -176,6 +176,14 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { - Klass* k = obj->klass(); - st->print_cr("\t- %s <" INTPTR_FORMAT "> (a %s)", "parking to wait for ", (address)obj, k->external_name()); - } -+ else if (thread()->osthread()->get_state() == OBJECT_WAIT) { -+ // We are waiting on an Object monitor but Object.wait() isn't the -+ // top-frame, so we should be waiting on a Class initialization monitor. -+ InstanceKlass* k = thread()->class_to_be_initialized(); -+ if (k != NULL) { -+ st->print_cr("\t- waiting on the Class initialization monitor for %s", k->external_name()); -+ } -+ } - } - - -diff --git a/hotspot/test/runtime/Thread/TestThreadDumpClassInitMonitor.java b/hotspot/test/runtime/Thread/TestThreadDumpClassInitMonitor.java -new file mode 100644 -index 000000000..8aa218efb ---- /dev/null -+++ b/hotspot/test/runtime/Thread/TestThreadDumpClassInitMonitor.java -@@ -0,0 +1,217 @@ -+/* -+ * Copyright (c) 2019, 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 8213397 8217337 -+ * @summary Check that the thread dump shows when a thread is blocked -+ * on a class initialization monitor -+ * -+ * @library /testlibrary -+ * @run main/othervm TestThreadDumpClassInitMonitor -+ */ -+ -+import com.oracle.java.testlibrary.*; -+ -+import java.io.IOException; -+import java.util.List; -+import java.lang.management.ManagementFactory; -+import java.lang.management.RuntimeMXBean; -+ -+public class TestThreadDumpClassInitMonitor { -+ // jstack tends to be closely bound to the VM that we are running -+ // so use getTestJDKTool() instead of getCompileJDKTool() or even -+ // getJDKTool() which can fall back to "compile.jdk". -+ final static String JSTACK = JDKToolFinder.getTestJDKTool("jstack"); -+ final static String PID = getPid(); -+ final static Thread current = Thread.currentThread(); -+ -+ /* -+ * This is the output we're looking for: -+ * -+ * "TestThread" #22 prio=5 os_prio=0 cpu=1.19ms elapsed=0.80s tid=0x00007f8f9405d800 nid=0x568b in Object.wait() [0x00007f8fd94d0000] -+ * java.lang.Thread.State: RUNNABLE -+ * Thread: 0x00007f8f9405d800 [0x568b] State: _at_safepoint _has_called_back 0 _at_poll_safepoint 0 // DEBUG ONLY -+ * JavaThread state: _thread_blocked // DEBUG ONLY -+ * at TestThreadDumpClassInitMonitor$Target$1.run(TestThreadDumpClassInitMonitor.java:69) -+ * - waiting on the Class initialization monitor for TestThreadDumpClassInitMonitor$Target -+ * -+ */ -+ final static String TEST_THREAD = "TestThread"; -+ final static String TEST_THREAD_ENTRY = "\"" + TEST_THREAD; -+ final static String IN_OBJECT_WAIT = "in Object.wait()"; -+ final static String THREAD_STATE = "java.lang.Thread.State: RUNNABLE"; -+ final static String THREAD_INFO = "Thread:"; // the details are not important -+ final static String JAVATHREAD_STATE = "JavaThread state: _thread_blocked"; -+ final static String CURRENT_METHOD = "at TestThreadDumpClassInitMonitor$Target$1.run"; -+ final static String WAIT_INFO = "- waiting on the Class initialization monitor for TestThreadDumpClassInitMonitor$Target"; -+ -+ volatile static boolean ready = false; -+ -+ static List stackDump; // jstack output as lines -+ -+ static class Target { -+ -+ static int field; -+ -+ // The main thread will initialize this class and so -+ // execute the actual test logic here. -+ static { -+ if (Thread.currentThread() != current) { -+ throw new Error("Initialization logic error"); -+ } -+ System.out.println("Initializing Target class in main thread"); -+ -+ Thread t = new Thread() { -+ public void run() { -+ System.out.println("Test thread about to access Target"); -+ ready = true; // tell main thread we're close -+ // This will block until the main thread completes -+ // static initialization of target -+ Target.field = 42; -+ System.out.println("Test thread done"); -+ } -+ }; -+ t.setName(TEST_THREAD); -+ t.start(); -+ -+ // We want to run jstack once the test thread is blocked but -+ // there's no programmatic way to detect that. So we check the flag -+ // that will be set just before it should block, then by the time -+ // we can exec jstack it should be ready. -+ try { -+ while (!ready) { -+ Thread.sleep(200); -+ } -+ } -+ catch (InterruptedException ie) { -+ throw new Error("Shouldn't happen"); -+ } -+ -+ // Now run jstack -+ try { -+ ProcessBuilder pb = new ProcessBuilder(JSTACK, PID); -+ OutputAnalyzer output = new OutputAnalyzer(pb.start()); -+ output.shouldHaveExitValue(0); -+ stackDump = output.asLines(); -+ } -+ catch (IOException ioe) { -+ throw new Error("Launching jstack failed", ioe); -+ } -+ } -+ } -+ -+ -+ public static void main(String[] args) throws Throwable { -+ // Implicitly run the main test logic -+ Target.field = 21; -+ -+ // Now check the output of jstack -+ try { -+ // product builds miss 2 lines of information in the stack -+ boolean isProduct = !Platform.isDebugBuild(); -+ int foundLines = 0; -+ parseStack: for (String line : stackDump) { -+ switch(foundLines) { -+ case 0: { -+ if (!line.startsWith(TEST_THREAD_ENTRY)) { -+ continue; -+ } -+ foundLines++; -+ if (!line.contains(IN_OBJECT_WAIT)) { -+ throw new Error("Unexpected initial stack line: " + line); -+ } -+ continue; -+ } -+ case 1: { -+ if (!line.trim().equals(THREAD_STATE)) { -+ throw new Error("Unexpected thread state line: " + line); -+ } -+ if (isProduct) { -+ foundLines += 3; -+ } else { -+ foundLines++; -+ } -+ continue; -+ } -+ case 2: { // Debug build -+ if (!line.startsWith(THREAD_INFO)) { -+ throw new Error("Unexpected thread info line: " + line); -+ } -+ foundLines++; -+ continue; -+ } -+ case 3: { // Debug build -+ if (!line.trim().equals(JAVATHREAD_STATE)) { -+ throw new Error("Unexpected JavaThread state line: " + line); -+ } -+ foundLines++; -+ continue; -+ } -+ case 4: { -+ if (!line.trim().startsWith(CURRENT_METHOD)) { -+ throw new Error("Unexpected current method line: " + line); -+ } -+ foundLines++; -+ continue; -+ } -+ case 5: { -+ if (!line.trim().equals(WAIT_INFO)) { -+ throw new Error("Unexpected monitor information line: " + line); -+ } -+ break parseStack; -+ } -+ default: throw new Error("Logic error in case statement"); -+ } -+ } -+ -+ if (foundLines == 0) { -+ throw new Error("Unexpected stack content - did not find line starting with " -+ + TEST_THREAD_ENTRY); -+ } -+ } -+ catch (Error e) { -+ // Dump the full stack trace on error so we can check the content -+ for (String line : stackDump) { -+ System.out.println(line); -+ } -+ throw e; -+ } -+ } -+ -+ // This helper relies on RuntimeMXBean.getName() returning a string -+ // that looks like this: 5436@mt-haku -+ // -+ // The testlibrary has tryFindJvmPid(), but that uses a separate -+ // process which is much more expensive for finding out your own PID. -+ // -+ static String getPid() { -+ RuntimeMXBean runtimebean = ManagementFactory.getRuntimeMXBean(); -+ String vmname = runtimebean.getName(); -+ int i = vmname.indexOf('@'); -+ if (i != -1) { -+ vmname = vmname.substring(0, i); -+ } -+ return vmname; -+ } -+} -\ No newline at end of file --- -2.22.0 - diff --git a/8254723-Add-diagnostic-command-to-write-Linux-perf-m.patch b/8254723-Add-diagnostic-command-to-write-Linux-perf-m.patch deleted file mode 100644 index c3e3ca9fe0fe2f97fd826a110dc56e6f96f13316..0000000000000000000000000000000000000000 --- a/8254723-Add-diagnostic-command-to-write-Linux-perf-m.patch +++ /dev/null @@ -1,277 +0,0 @@ -From 6a5759c82b869c4d931273609aa19eb1a84df8db Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:12:51 +0800 -Subject: 8254723-Add-diagnostic-command-to-write-Linux-perf-m.patch - ---- - hotspot/src/os/linux/vm/globals_linux.hpp | 5 +- - hotspot/src/os/linux/vm/os_linux.cpp | 6 ++ - hotspot/src/share/vm/code/codeCache.cpp | 36 ++++++++ - hotspot/src/share/vm/code/codeCache.hpp | 1 + - hotspot/src/share/vm/runtime/java.cpp | 6 ++ - .../share/vm/services/diagnosticCommand.cpp | 7 ++ - .../share/vm/services/diagnosticCommand.hpp | 23 +++++ - .../test/serviceability/dcmd/PerfMapTest.java | 84 +++++++++++++++++++ - 8 files changed, 167 insertions(+), 1 deletion(-) - create mode 100644 hotspot/test/serviceability/dcmd/PerfMapTest.java - -diff --git a/hotspot/src/os/linux/vm/globals_linux.hpp b/hotspot/src/os/linux/vm/globals_linux.hpp -index f98bde41a..5cbe686d3 100644 ---- a/hotspot/src/os/linux/vm/globals_linux.hpp -+++ b/hotspot/src/os/linux/vm/globals_linux.hpp -@@ -55,7 +55,10 @@ - product(bool, PreferContainerQuotaForCPUCount, true, \ - "Calculate the container CPU availability based on the value" \ - " of quotas (if set), when true. Otherwise, use the CPU" \ -- " shares value, provided it is less than quota.") -+ " shares value, provided it is less than quota.") \ -+ \ -+ diagnostic(bool, DumpPerfMapAtExit, false, \ -+ "Write map file for Linux perf tool at exit") - - // - // Defines Linux-specific default values. The flags are available on all -diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp -index a1cc85ca3..197b5c193 100644 ---- a/hotspot/src/os/linux/vm/os_linux.cpp -+++ b/hotspot/src/os/linux/vm/os_linux.cpp -@@ -5648,6 +5648,12 @@ jint os::init_2(void) - // initialize thread priority policy - prio_init(); - -+ if (DumpPerfMapAtExit && FLAG_IS_DEFAULT(UseCodeCacheFlushing)) { -+ // Disable code cache flushing to ensure the map file written at -+ // exit contains all nmethods generated during execution. -+ FLAG_SET_DEFAULT(UseCodeCacheFlushing, false); -+ } -+ - return JNI_OK; - } - -diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp -index 37f24b5e9..97ad3ba79 100644 ---- a/hotspot/src/share/vm/code/codeCache.cpp -+++ b/hotspot/src/share/vm/code/codeCache.cpp -@@ -1033,3 +1033,39 @@ void CodeCache::log_state(outputStream* st) { - unallocated_capacity()); - } - -+#ifdef LINUX -+void CodeCache::write_perf_map() { -+ MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); -+ -+ // Perf expects to find the map file at /tmp/perf-.map. -+ char fname[32]; -+ jio_snprintf(fname, sizeof(fname), "/tmp/perf-%d.map", os::current_process_id()); -+ -+ fileStream fs(fname, "w"); -+ if (!fs.is_open()) { -+ DEBUG_ONLY(warning("[codecache] Failed to create %s for perf map", fname)); -+ return; -+ } -+ -+ FOR_ALL_ALIVE_BLOBS(cb) { -+ if (cb->is_nmethod()) { -+ nmethod *nm = (nmethod *) cb; -+ assert(!nm->is_unloaded(), "Tautology"); -+ ResourceMark rm; -+ const char* method_name = nm->method()->name_and_sig_as_C_string(); -+ fs.print_cr(INTPTR_FORMAT " " INTPTR_FORMAT " %s", -+ (intptr_t)cb->code_begin(), (intptr_t)cb->code_size(), -+ method_name); -+ } -+ if (cb->is_runtime_stub()) { -+ RuntimeStub *stub = (RuntimeStub *) cb; -+ ResourceMark rm; -+ const char* method_name = stub->name(); -+ fs.print_cr(INTPTR_FORMAT " " INTPTR_FORMAT " %s", -+ (intptr_t)cb->code_begin(), (intptr_t)cb->code_size(), -+ method_name); -+ } -+ } -+} -+ -+#endif // LINUX -diff --git a/hotspot/src/share/vm/code/codeCache.hpp b/hotspot/src/share/vm/code/codeCache.hpp -index ab1417b19..0aad2d648 100644 ---- a/hotspot/src/share/vm/code/codeCache.hpp -+++ b/hotspot/src/share/vm/code/codeCache.hpp -@@ -158,6 +158,7 @@ class CodeCache : AllStatic { - static void print_trace(const char* event, CodeBlob* cb, int size = 0) PRODUCT_RETURN; - static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage - static void log_state(outputStream* st); -+ LINUX_ONLY(static void write_perf_map();) - - // Dcmd (Diagnostic commands) - static void print_codelist(outputStream* st); -diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp -index 5a628b73e..fec8fb94d 100644 ---- a/hotspot/src/share/vm/runtime/java.cpp -+++ b/hotspot/src/share/vm/runtime/java.cpp -@@ -537,6 +537,12 @@ void before_exit(JavaThread * thread) { - BytecodeHistogram::print(); - } - -+#ifdef LINUX -+ if (DumpPerfMapAtExit) { -+ CodeCache::write_perf_map(); -+ } -+#endif -+ - if (JvmtiExport::should_post_thread_life()) { - JvmtiExport::post_thread_end(thread); - } -diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp -index 416dc77ce..f8f6ad546 100644 ---- a/hotspot/src/share/vm/services/diagnosticCommand.cpp -+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp -@@ -36,6 +36,7 @@ - #include "services/management.hpp" - #include "utilities/macros.hpp" - #include "oops/objArrayOop.hpp" -+#include "code/codeCache.hpp" - - #ifdef LINUX - #include "trimCHeapDCmd.hpp" -@@ -81,6 +82,7 @@ void DCmdRegistrant::register_dcmds(){ - #ifdef LINUX - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); -+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - #endif // LINUX - - // Enhanced JMX Agent Support -@@ -868,3 +870,8 @@ void CodeCacheDCmd::execute(DCmdSource source, TRAPS) { - VMThread::execute(&printCodeCacheOp); - } - -+#ifdef LINUX -+void PerfMapDCmd::execute(DCmdSource source, TRAPS) { -+ CodeCache::write_perf_map(); -+} -+#endif // LINUX -\ No newline at end of file -diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp -index 3733fa7f7..d446aab4e 100644 ---- a/hotspot/src/share/vm/services/diagnosticCommand.hpp -+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp -@@ -590,4 +590,27 @@ public: - virtual void execute(DCmdSource source, TRAPS); - }; - -+#ifdef LINUX -+class PerfMapDCmd : public DCmd { -+public: -+ PerfMapDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} -+ static const char* name() { -+ return "Compiler.perfmap"; -+ } -+ static const char* description() { -+ return "Write map file for Linux perf tool."; -+ } -+ static const char* impact() { -+ return "Low"; -+ } -+ static const JavaPermission permission() { -+ JavaPermission p = {"java.lang.management.ManagementPermission", -+ "monitor", NULL}; -+ return p; -+ } -+ static int num_arguments() { return 0; } -+ virtual void execute(DCmdSource source, TRAPS); -+}; -+#endif // LINUX -+ - #endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP -diff --git a/hotspot/test/serviceability/dcmd/PerfMapTest.java b/hotspot/test/serviceability/dcmd/PerfMapTest.java -new file mode 100644 -index 000000000..1807b2a7f ---- /dev/null -+++ b/hotspot/test/serviceability/dcmd/PerfMapTest.java -@@ -0,0 +1,84 @@ -+/* -+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, Arm Limited. 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 PerfMapTest -+ * @bug 8254723 -+ * @requires os.family == "linux" -+ * @library /testlibrary -+ * @run testng/othervm PerfMapTest -+ * @summary Test of diagnostic command Compiler.perfmap -+ */ -+ -+import org.testng.annotations.Test; -+import org.testng.Assert; -+ -+import com.oracle.java.testlibrary.OutputAnalyzer; -+import com.oracle.java.testlibrary.CommandExecutor; -+import com.oracle.java.testlibrary.JMXExecutor; -+import com.oracle.java.testlibrary.ProcessTools; -+ -+import java.io.IOException; -+import java.nio.file.Files; -+import java.nio.file.Path; -+import java.nio.file.Paths; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+/** -+ * Call jcmd Compiler.perfmap and check the output file has the expected -+ * format. -+ */ -+public class PerfMapTest { -+ -+ static final Pattern LINE_PATTERN = -+ Pattern.compile("^((?:0x)?\\p{XDigit}+)\\s+((?:0x)?\\p{XDigit}+)\\s+(.*)$"); -+ -+ public void run(CommandExecutor executor) throws Exception { -+ OutputAnalyzer output = executor.execute("Compiler.perfmap"); -+ -+ output.stderrShouldBeEmpty(); -+ output.stdoutShouldBeEmpty(); -+ -+ final long pid = ProcessTools.getProcessId(); -+ final Path path = Paths.get(String.format("/tmp/perf-%d.map", pid)); -+ -+ Assert.assertTrue(Files.exists(path)); -+ -+ // Sanity check the file contents -+ try { -+ for (String entry : Files.readAllLines(path)) { -+ Matcher m = LINE_PATTERN.matcher(entry); -+ Assert.assertTrue(m.matches(), "Invalid file format: " + entry); -+ } -+ } catch (IOException e) { -+ Assert.fail(e.toString()); -+ } -+ } -+ -+ @Test -+ public void jmx() throws Exception { -+ run(new JMXExecutor()); -+ } -+} --- -2.22.0 - diff --git a/8263557-Possible-NULL-dereference-in-Arena-destruct_.patch b/8263557-Possible-NULL-dereference-in-Arena-destruct_.patch deleted file mode 100644 index 481b9230c2e407e0ea76f2f75f3c5f6d48096803..0000000000000000000000000000000000000000 --- a/8263557-Possible-NULL-dereference-in-Arena-destruct_.patch +++ /dev/null @@ -1,25 +0,0 @@ -From facc89d6a5776a26193c9321111c8489e4af525f Mon Sep 17 00:00:00 2001 -Subject: 8263557: Possible NULL dereference in Arena::destruct_contents() - ---- - hotspot/src/share/vm/memory/allocation.cpp | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/hotspot/src/share/vm/memory/allocation.cpp b/hotspot/src/share/vm/memory/allocation.cpp -index 3cd30a686..abbcc6c49 100644 ---- a/hotspot/src/share/vm/memory/allocation.cpp -+++ b/hotspot/src/share/vm/memory/allocation.cpp -@@ -521,7 +521,9 @@ void Arena::destruct_contents() { - // reset size before chop to avoid a rare racing condition - // that can have total arena memory exceed total chunk memory - set_size_in_bytes(0); -- _first->chop(); -+ if (_first != NULL) { -+ _first->chop(); -+ } - reset(); - } - --- -2.22.0 - diff --git a/8278794-Infinite-loop-in-DeflaterOutputStream.finish.patch b/8278794-Infinite-loop-in-DeflaterOutputStream.finish.patch deleted file mode 100644 index ee61f2742d573c1a6fe7c9a573a1ad2d85ace4fc..0000000000000000000000000000000000000000 --- a/8278794-Infinite-loop-in-DeflaterOutputStream.finish.patch +++ /dev/null @@ -1,238 +0,0 @@ -From e5bf7f105c0066f770f5cdc65f94410d45d11f0f Mon Sep 17 00:00:00 2001 -Subject: 8278794: Infinite loop in DeflaterOutputStream.finish() - ---- - .../share/classes/java/util/zip/Deflater.java | 10 ++ - .../java/util/zip/DeflaterOutputStream.java | 14 +- - .../java/util/zip/ZipOutputStream.java | 4 +- - jdk/test/java/util/zip/CloseDeflaterTest.java | 147 ------------------ - 4 files changed, 22 insertions(+), 153 deletions(-) - delete mode 100644 jdk/test/java/util/zip/CloseDeflaterTest.java - -diff --git a/jdk/src/share/classes/java/util/zip/Deflater.java b/jdk/src/share/classes/java/util/zip/Deflater.java -index 3bb5f9901..bffa397d9 100644 ---- a/jdk/src/share/classes/java/util/zip/Deflater.java -+++ b/jdk/src/share/classes/java/util/zip/Deflater.java -@@ -559,6 +559,16 @@ class Deflater { - throw new NullPointerException("Deflater has been closed"); - } - -+ /** -+ * Returns the value of 'finish' flag. -+ * 'finish' will be set to true if def.finish() method is called. -+ */ -+ boolean shouldFinish() { -+ synchronized (zsRef) { -+ return finish; -+ } -+ } -+ - private static native void initIDs(); - private native static long init(int level, int strategy, boolean nowrap); - private native static void setDictionary(long addr, byte[] b, int off, int len); -diff --git a/jdk/src/share/classes/java/util/zip/DeflaterOutputStream.java b/jdk/src/share/classes/java/util/zip/DeflaterOutputStream.java -index f4cf79693..c698a0147 100644 ---- a/jdk/src/share/classes/java/util/zip/DeflaterOutputStream.java -+++ b/jdk/src/share/classes/java/util/zip/DeflaterOutputStream.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 1996, 2022, 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 -@@ -221,9 +221,15 @@ class DeflaterOutputStream extends FilterOutputStream { - */ - public void finish() throws IOException { - if (!def.finished()) { -- def.finish(); -- while (!def.finished()) { -- deflate(); -+ try{ -+ def.finish(); -+ while (!def.finished()) { -+ deflate(); -+ } -+ } catch(IOException e) { -+ if (usesDefaultDeflater) -+ def.end(); -+ throw e; - } - } - } -diff --git a/jdk/src/share/classes/java/util/zip/ZipOutputStream.java b/jdk/src/share/classes/java/util/zip/ZipOutputStream.java -index f001ddf00..cd9194276 100644 ---- a/jdk/src/share/classes/java/util/zip/ZipOutputStream.java -+++ b/jdk/src/share/classes/java/util/zip/ZipOutputStream.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 1996, 2022, 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 -@@ -302,7 +302,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants { - crc.reset(); - current = null; - } catch (IOException e) { -- if (usesDefaultDeflater && !(e instanceof ZipException)) -+ if (def.shouldFinish() && usesDefaultDeflater && !(e instanceof ZipException)) - def.end(); - throw e; - } -diff --git a/jdk/test/java/util/zip/CloseDeflaterTest.java b/jdk/test/java/util/zip/CloseDeflaterTest.java -deleted file mode 100644 -index 8aa4960f5..000000000 ---- a/jdk/test/java/util/zip/CloseDeflaterTest.java -+++ /dev/null -@@ -1,147 +0,0 @@ --/* -- * Copyright (c) 2021, 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 8193682 -- * @summary Test Infinite loop while writing on closed GZipOutputStream , ZipOutputStream and JarOutputStream. -- * @run testng CloseDeflaterTest -- */ --import java.io.*; --import java.util.Random; --import java.util.jar.JarOutputStream; --import java.util.zip.GZIPOutputStream; --import java.util.zip.ZipOutputStream; --import java.util.zip.ZipEntry; -- --import org.testng.annotations.BeforeTest; --import org.testng.annotations.DataProvider; --import org.testng.annotations.Test; --import static org.testng.Assert.fail; -- -- --public class CloseDeflaterTest { -- -- //number of bytes to write -- private static final int INPUT_LENGTH= 512; -- //OutputStream that will throw an exception during a write operation -- private static OutputStream outStream = new OutputStream() { -- @Override -- public void write(byte[] b, int off, int len) throws IOException { -- //throw exception during write -- throw new IOException(); -- } -- @Override -- public void write(byte b[]) throws IOException {} -- @Override -- public void write(int b) throws IOException {} -- }; -- private static byte[] inputBytes = new byte[INPUT_LENGTH]; -- private static Random rand = new Random(); -- -- @DataProvider(name = "testgzipinput") -- public Object[][] testGZipInput() { -- //testGZip will close the GZipOutputStream using close() method when the boolean -- //useCloseMethod is set to true and finish() method if the value is set to false -- return new Object[][] { -- { GZIPOutputStream.class, true }, -- { GZIPOutputStream.class, false }, -- }; -- } -- -- @DataProvider(name = "testzipjarinput") -- public Object[][] testZipAndJarInput() { -- //testZipAndJarInput will perfrom write/closeEntry operations on JarOutputStream when the boolean -- //useJar is set to true and on ZipOutputStream if the value is set to false -- return new Object[][] { -- { JarOutputStream.class, true }, -- { ZipOutputStream.class, false }, -- }; -- } -- -- @BeforeTest -- public void before_test() -- { -- //add inputBytes array with random bytes to write into Zip -- rand.nextBytes(inputBytes); -- } -- -- //Test for infinite loop by writing bytes to closed GZIPOutputStream -- @Test(dataProvider = "testgzipinput") -- public void testGZip(Class type, boolean useCloseMethod) throws IOException { -- GZIPOutputStream zip = new GZIPOutputStream(outStream); -- try { -- zip.write(inputBytes, 0, INPUT_LENGTH); -- //close zip -- if(useCloseMethod) { -- zip.close(); -- } else { -- zip.finish(); -- } -- } catch (IOException e) { -- //expected -- } -- for (int i = 0; i < 3; i++) { -- try { -- //write on a closed GZIPOutputStream -- zip.write(inputBytes, 0, INPUT_LENGTH); -- fail("Deflater closed exception not thrown"); -- } catch (NullPointerException e) { -- //expected , Deflater has been closed exception -- } -- } -- } -- -- //Test for infinite loop by writing bytes to closed ZipOutputStream/JarOutputStream -- @Test(dataProvider = "testzipjarinput") -- public void testZipCloseEntry(Class type,boolean useJar) throws IOException { -- ZipOutputStream zip = null; -- if(useJar) { -- zip = new JarOutputStream(outStream); -- } else { -- zip = new ZipOutputStream(outStream); -- } -- try { -- zip.putNextEntry(new ZipEntry("")); -- } catch (IOException e) { -- //expected to throw IOException since putNextEntry calls write method -- } -- try { -- zip.write(inputBytes, 0, INPUT_LENGTH); -- //close zip entry -- zip.closeEntry(); -- } catch (IOException e) { -- //expected -- } -- for (int i = 0; i < 3; i++) { -- try { -- //write on a closed ZipOutputStream -- zip.write(inputBytes, 0, INPUT_LENGTH); -- fail("Deflater closed exception not thrown"); -- } catch (NullPointerException e) { -- //expected , Deflater has been closed exception -- } -- } -- } -- --} --- -2.22.0 - diff --git a/8283441-C2-segmentation-fault-in-ciMethodBlocks-make.patch b/8283441-C2-segmentation-fault-in-ciMethodBlocks-make.patch new file mode 100644 index 0000000000000000000000000000000000000000..5e41bd132d423cc91448e6409f8e871b793b7613 --- /dev/null +++ b/8283441-C2-segmentation-fault-in-ciMethodBlocks-make.patch @@ -0,0 +1,227 @@ +From d85c283f3bb1fd5f1d96c076e858a7409af19aae Mon Sep 17 00:00:00 2001 +Subject: 8283441: C2: segmentation fault in ciMethodBlocks::make_block_at(int) + +Bug url: https://bugs.openjdk.org/browse/JDK-8283441 +--- + hotspot/src/share/vm/c1/c1_GraphBuilder.cpp | 12 ++++-- + hotspot/src/share/vm/ci/ciMethodBlocks.cpp | 17 +++++--- + .../src/share/vm/compiler/methodLiveness.cpp | 9 ++-- + hotspot/test/compiler/parsing/Custom.jasm | 38 +++++++++++++++++ + ...UnreachableBlockFallsThroughEndOfCode.java | 42 +++++++++++++++++++ + 5 files changed, 106 insertions(+), 12 deletions(-) + create mode 100644 hotspot/test/compiler/parsing/Custom.jasm + create mode 100644 hotspot/test/compiler/parsing/UnreachableBlockFallsThroughEndOfCode.java + +diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +index eb8ffe5e5..db353541f 100644 +--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp ++++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +@@ -206,8 +206,10 @@ void BlockListBuilder::handle_exceptions(BlockBegin* current, int cur_bci) { + } + + void BlockListBuilder::handle_jsr(BlockBegin* current, int sr_bci, int next_bci) { +- // start a new block after jsr-bytecode and link this block into cfg +- make_block_at(next_bci, current); ++ if (next_bci < method()->code_size()) { ++ // start a new block after jsr-bytecode and link this block into cfg ++ make_block_at(next_bci, current); ++ } + + // start a new block at the subroutine entry at mark it with special flag + BlockBegin* sr_block = make_block_at(sr_bci, current); +@@ -227,6 +229,8 @@ void BlockListBuilder::set_leaders() { + // branch target and a modification of the successor lists. + BitMap bci_block_start = method()->bci_block_start(); + ++ int end_bci = method()->code_size(); ++ + ciBytecodeStream s(method()); + while (s.next() != ciBytecodeStream::EOBC()) { + int cur_bci = s.cur_bci(); +@@ -297,7 +301,9 @@ void BlockListBuilder::set_leaders() { + case Bytecodes::_if_acmpne: // fall through + case Bytecodes::_ifnull: // fall through + case Bytecodes::_ifnonnull: +- make_block_at(s.next_bci(), current); ++ if (s.next_bci() < end_bci) { ++ make_block_at(s.next_bci(), current); ++ } + make_block_at(s.get_dest(), current); + current = NULL; + break; +diff --git a/hotspot/src/share/vm/ci/ciMethodBlocks.cpp b/hotspot/src/share/vm/ci/ciMethodBlocks.cpp +index 3ce828ecb..bb3937c15 100644 +--- a/hotspot/src/share/vm/ci/ciMethodBlocks.cpp ++++ b/hotspot/src/share/vm/ci/ciMethodBlocks.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2006, 2022, 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 +@@ -33,12 +33,13 @@ + + + ciBlock *ciMethodBlocks::block_containing(int bci) { ++ assert(bci >= 0 && bci < _code_size, "valid bytecode range"); + ciBlock *blk = _bci_to_block[bci]; + return blk; + } + + bool ciMethodBlocks::is_block_start(int bci) { +- assert(bci >=0 && bci < _code_size, "valid bytecode range"); ++ assert(bci >= 0 && bci < _code_size, "valid bytecode range"); + ciBlock *b = _bci_to_block[bci]; + assert(b != NULL, "must have block for bytecode"); + return b->start_bci() == bci; +@@ -146,7 +147,9 @@ void ciMethodBlocks::do_analysis() { + case Bytecodes::_ifnonnull : + { + cur_block->set_control_bci(bci); +- ciBlock *fall_through = make_block_at(s.next_bci()); ++ if (s.next_bci() < limit_bci) { ++ ciBlock *fall_through = make_block_at(s.next_bci()); ++ } + int dest_bci = s.get_dest(); + ciBlock *dest = make_block_at(dest_bci); + break; +@@ -166,7 +169,9 @@ void ciMethodBlocks::do_analysis() { + case Bytecodes::_jsr : + { + cur_block->set_control_bci(bci); +- ciBlock *ret = make_block_at(s.next_bci()); ++ if (s.next_bci() < limit_bci) { ++ ciBlock *ret = make_block_at(s.next_bci()); ++ } + int dest_bci = s.get_dest(); + ciBlock *dest = make_block_at(dest_bci); + break; +@@ -224,7 +229,9 @@ void ciMethodBlocks::do_analysis() { + case Bytecodes::_jsr_w : + { + cur_block->set_control_bci(bci); +- ciBlock *ret = make_block_at(s.next_bci()); ++ if (s.next_bci() < limit_bci) { ++ ciBlock *ret = make_block_at(s.next_bci()); ++ } + int dest_bci = s.get_far_dest(); + ciBlock *dest = make_block_at(dest_bci); + break; +diff --git a/hotspot/src/share/vm/compiler/methodLiveness.cpp b/hotspot/src/share/vm/compiler/methodLiveness.cpp +index eda1ab156..7fb496dc9 100644 +--- a/hotspot/src/share/vm/compiler/methodLiveness.cpp ++++ b/hotspot/src/share/vm/compiler/methodLiveness.cpp +@@ -268,10 +268,11 @@ void MethodLiveness::init_basic_blocks() { + case Bytecodes::_ifnull: + case Bytecodes::_ifnonnull: + // Two way branch. Set predecessors at each destination. +- dest = _block_map->at(bytes.next_bci()); +- assert(dest != NULL, "must be a block immediately following this one."); +- dest->add_normal_predecessor(current_block); +- ++ if (bytes.next_bci() < method_len) { ++ dest = _block_map->at(bytes.next_bci()); ++ assert(dest != NULL, "must be a block immediately following this one."); ++ dest->add_normal_predecessor(current_block); ++ } + dest = _block_map->at(bytes.get_dest()); + assert(dest != NULL, "branch desination must start a block."); + dest->add_normal_predecessor(current_block); +diff --git a/hotspot/test/compiler/parsing/Custom.jasm b/hotspot/test/compiler/parsing/Custom.jasm +new file mode 100644 +index 000000000..78bfc518d +--- /dev/null ++++ b/hotspot/test/compiler/parsing/Custom.jasm +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++package compiler/parsing; ++ ++super public class Custom { ++ ++ public static Method test:"(I)V" stack 2 locals 1 { ++ return; ++Loop: ++ // Unreachable block ++ iload_0; ++ bipush 100; ++ if_icmpge Loop; ++ // Falls through ++ } ++ ++} +\ No newline at end of file +diff --git a/hotspot/test/compiler/parsing/UnreachableBlockFallsThroughEndOfCode.java b/hotspot/test/compiler/parsing/UnreachableBlockFallsThroughEndOfCode.java +new file mode 100644 +index 000000000..5b1d17d97 +--- /dev/null ++++ b/hotspot/test/compiler/parsing/UnreachableBlockFallsThroughEndOfCode.java +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2022, 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 UnreachableBlockFallsThroughEndOfCode.java ++ * @bug 8283441 ++ * @compile Custom.jasm UnreachableBlockFallsThroughEndOfCode.java ++ * @summary Compiling method that falls off the end of the code array ++ * @run main/othervm -XX:TieredStopAtLevel=1 -Xbatch compiler.parsing.UnreachableBlockFallsThroughEndOfCode ++ * @run main/othervm -XX:-TieredCompilation -Xbatch compiler.parsing.UnreachableBlockFallsThroughEndOfCode ++ */ ++ ++ package compiler.parsing; ++ ++ public class UnreachableBlockFallsThroughEndOfCode { ++ public static void main(String[] strArr) { ++ for (int i = 0; i < 20000; i++) { ++ Custom.test(i); ++ } ++ } ++ } +\ No newline at end of file +-- +2.22.0 + diff --git a/8285516-clearPassword-should-be-called-in-a-finally-.patch b/8285516-clearPassword-should-be-called-in-a-finally-.patch deleted file mode 100644 index 8d7c2d6a20893190a7788bc09b08e964e2972167..0000000000000000000000000000000000000000 --- a/8285516-clearPassword-should-be-called-in-a-finally-.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 42884748f75ef4ea6e0cc8e537c831cb258961f8 Mon Sep 17 00:00:00 2001 -Subject: 8285516: clearPassword should be called in a finally try block - ---- - .../share/classes/sun/security/pkcs12/PKCS12KeyStore.java | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java -index 0457b1e5c..63e0afc2a 100644 ---- a/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java -+++ b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java -@@ -837,14 +837,14 @@ public final class PKCS12KeyStore extends KeyStoreSpi { - { - SecretKey skey = null; - -+ PBEKeySpec keySpec = new PBEKeySpec(password); - try { -- PBEKeySpec keySpec = new PBEKeySpec(password); - SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE"); - skey = skFac.generateSecret(keySpec); -- keySpec.clearPassword(); - } catch (Exception e) { -- throw new IOException("getSecretKey failed: " + -- e.getMessage(), e); -+ throw new IOException("getSecretKey failed: " + e.getMessage(), e); -+ } finally { -+ keySpec.clearPassword(); - } - return skey; - } --- -2.22.0 - diff --git a/8293344-JDK-8242181-broke-stack-printing-for-non-att.patch b/8293344-JDK-8242181-broke-stack-printing-for-non-att.patch deleted file mode 100644 index 6160d6a2b8dea2b498c322d1301dcf379a8b9f3d..0000000000000000000000000000000000000000 --- a/8293344-JDK-8242181-broke-stack-printing-for-non-att.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 1b17272792968ae8b888c7ccb99133a4aee6b97f Mon Sep 17 00:00:00 2001 -Subject: 8293344: JDK-8242181 broke stack printing for non-attached threads ---- - hotspot/src/share/vm/utilities/elfFile.cpp | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/hotspot/src/share/vm/utilities/elfFile.cpp b/hotspot/src/share/vm/utilities/elfFile.cpp -index 81bd44109..448963b2d 100644 ---- a/hotspot/src/share/vm/utilities/elfFile.cpp -+++ b/hotspot/src/share/vm/utilities/elfFile.cpp -@@ -318,7 +318,6 @@ bool ElfFile::specifies_noexecstack() { - - bool ElfFile::get_source_info(const uint32_t offset_in_library, char* filename, const size_t filename_len, - int* line, bool is_pc_after_call) { -- ResourceMark rm; - if (!load_dwarf_file()) { - // Some ELF libraries do not provide separate .debuginfo files. Check if the current ELF file has the required - // DWARF sections. If so, treat the current ELF file as DWARF file. --- -2.22.0 - diff --git a/8294906-Memory-leak-in-PKCS11-NSS-TLS-server.patch b/8294906-Memory-leak-in-PKCS11-NSS-TLS-server.patch deleted file mode 100644 index 5dbfc417f7f3fffb15c30c1e38f4e9ab1a2747d0..0000000000000000000000000000000000000000 --- a/8294906-Memory-leak-in-PKCS11-NSS-TLS-server.patch +++ /dev/null @@ -1,338 +0,0 @@ -From 44a22ec75a0ef4200ba824e9e00b56b735b911a0 Mon Sep 17 00:00:00 2001 -Subject: 8294906: Memory leak in PKCS11 NSS TLS server ---- - .../pkcs11/P11TlsKeyMaterialGenerator.java | 14 ++-- - .../crypto/provider/TLS/TestKeyMaterial.java | 31 ++++++++- - .../sun/crypto/provider/TLS/keymatdata.txt | 34 ++++++++++ - .../security/pkcs11/tls/TestKeyMaterial.java | 65 +++++++++++++------ - .../sun/security/pkcs11/tls/keymatdata.txt | 34 ++++++++++ - 5 files changed, 151 insertions(+), 27 deletions(-) - -diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java b/jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java -index f6848278c..4242ff756 100644 ---- a/jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java -+++ b/jdk/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2005, 2022, 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 -@@ -193,15 +193,19 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi { - SecretKey clientMacKey, serverMacKey; - - // The MAC size may be zero for GCM mode. -- // -- // PKCS11 does not support GCM mode as the author made the comment, -- // so the macBits is unlikely to be zero. It's only a place holder. - if (macBits != 0) { - clientMacKey = P11Key.secretKey - (session, out.hClientMacSecret, "MAC", macBits, attributes); - serverMacKey = P11Key.secretKey - (session, out.hServerMacSecret, "MAC", macBits, attributes); - } else { -+ // NSS allocates MAC keys even if macBits is zero -+ if (out.hClientMacSecret != CK_INVALID_HANDLE) { -+ token.p11.C_DestroyObject(session.id(), out.hClientMacSecret); -+ } -+ if (out.hServerMacSecret != CK_INVALID_HANDLE) { -+ token.p11.C_DestroyObject(session.id(), out.hServerMacSecret); -+ } - clientMacKey = null; - serverMacKey = null; - } -@@ -213,6 +217,8 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi { - serverCipherKey = P11Key.secretKey(session, out.hServerKey, - cipherAlgorithm, expandedKeyBits, attributes); - } else { -+ assert out.hClientKey == 0; -+ assert out.hServerKey == 0; - clientCipherKey = null; - serverCipherKey = null; - } -diff --git a/jdk/test/com/sun/crypto/provider/TLS/TestKeyMaterial.java b/jdk/test/com/sun/crypto/provider/TLS/TestKeyMaterial.java -index 8874070f4..6569c0c4f 100644 ---- a/jdk/test/com/sun/crypto/provider/TLS/TestKeyMaterial.java -+++ b/jdk/test/com/sun/crypto/provider/TLS/TestKeyMaterial.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2005, 2022, 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 -@@ -60,6 +60,7 @@ public class TestKeyMaterial extends Utils { - byte[] clientRandom = null; - byte[] serverRandom = null; - String cipherAlgorithm = null; -+ String hashAlgorithm = null; // TLS1.2+ only - int keyLength = 0; - int expandedKeyLength = 0; - int ivLength = 0; -@@ -93,6 +94,8 @@ public class TestKeyMaterial extends Utils { - serverRandom = parse(data); - } else if (line.startsWith("km-cipalg:")) { - cipherAlgorithm = data; -+ } else if (line.startsWith("km-hashalg:")) { -+ hashAlgorithm = data; - } else if (line.startsWith("km-keylen:")) { - keyLength = Integer.parseInt(data); - } else if (line.startsWith("km-explen:")) { -@@ -118,14 +121,36 @@ public class TestKeyMaterial extends Utils { - n++; - - KeyGenerator kg = -- KeyGenerator.getInstance("SunTlsKeyMaterial", provider); -+ KeyGenerator.getInstance(minor == 3 ? -+ "SunTls12KeyMaterial" : -+ "SunTlsKeyMaterial", provider); - SecretKey masterKey = - new SecretKeySpec(master, "TlsMasterSecret"); -+ int prfHashLength, prfBlockSize; -+ -+ if (hashAlgorithm != null) { -+ switch (hashAlgorithm) { -+ case "SHA-256": -+ prfHashLength = 32; -+ prfBlockSize = 64; -+ break; -+ case "SHA-384": -+ prfHashLength = 48; -+ prfBlockSize = 128; -+ break; -+ default: -+ throw new RuntimeException("Unexpected hashalg: " + -+ hashAlgorithm); -+ } -+ } else { -+ prfHashLength = -1; -+ prfBlockSize = -1; -+ } - TlsKeyMaterialParameterSpec spec = - new TlsKeyMaterialParameterSpec(masterKey, major, minor, - clientRandom, serverRandom, cipherAlgorithm, - keyLength, expandedKeyLength, ivLength, macLength, -- null, -1, -1); -+ hashAlgorithm, prfHashLength, prfBlockSize); - - kg.init(spec); - TlsKeyMaterialSpec result = -diff --git a/jdk/test/com/sun/crypto/provider/TLS/keymatdata.txt b/jdk/test/com/sun/crypto/provider/TLS/keymatdata.txt -index 391f30000..a3ff869b6 100644 ---- a/jdk/test/com/sun/crypto/provider/TLS/keymatdata.txt -+++ b/jdk/test/com/sun/crypto/provider/TLS/keymatdata.txt -@@ -3646,3 +3646,37 @@ km-civ: 17:bd:47:89:54:be:04:23 - km-siv: 34:8a:e8:24:84:38:c4:e1 - km-cmackey: e8:f0:b5:7b:a7:cc:2f:5e:43:ef:d3:dd:4e:8c:f9:6f:51:d7:84:df - km-smackey: fc:0c:77:20:c2:28:d3:11:ba:57:13:d8:0b:2d:f1:30:89:c6:35:69 -+km-master: f1:05:15:45:33:be:50:d6:88:0b:03:bb:88:9b:ef:d4:3b:98:aa:40:13:71:3c:1c:d9:df:34:c7:50:75:ad:5c:0a:d4:fe:ed:d5:58:6b:ff:2b:ce:c6:12:bc:6b:7e:dc -+km-major: 3 -+km-minor: 3 -+km-crandom: 42:f3:36:8e:9d:c9:69:3e:c1:8a:38:d3:e0:ec:2b:58:c2:e0:0c:de:4f:f3:af:51:d2:5c:bc:b2:c3:3b:1e:56 -+km-srandom: 42:f3:36:8e:fa:fd:23:3e:fd:f9:bc:88:3c:98:93:f3:c3:1d:9c:2a:4a:3b:02:a7:40:d4:64:04:59:e9:65:97 -+km-cipalg: AES -+km-hashalg: SHA-256 -+km-keylen: 16 -+km-explen: 0 -+km-ivlen: 4 -+km-maclen: 0 -+km-ccipkey: 60:7a:45:a9:6e:76:58:ea:d9:44:c5:25:f8:92:f1:26 -+km-scipkey: 42:c0:ed:75:a2:51:21:7c:50:74:9d:78:9a:f7:35:2b -+km-civ: a1:3c:3e:4a -+km-siv: 85:ab:ee:70 -+km-cmackey: (null) -+km-smackey: (null) -+km-master: f1:05:15:45:33:be:50:d6:88:0b:03:bb:88:9b:ef:d4:3b:98:aa:40:13:71:3c:1c:d9:df:34:c7:50:75:ad:5c:0a:d4:fe:ed:d5:58:6b:ff:2b:ce:c6:12:bc:6b:7e:dc -+km-major: 3 -+km-minor: 3 -+km-crandom: 42:f3:36:8e:9d:c9:69:3e:c1:8a:38:d3:e0:ec:2b:58:c2:e0:0c:de:4f:f3:af:51:d2:5c:bc:b2:c3:3b:1e:56 -+km-srandom: 42:f3:36:8e:fa:fd:23:3e:fd:f9:bc:88:3c:98:93:f3:c3:1d:9c:2a:4a:3b:02:a7:40:d4:64:04:59:e9:65:97 -+km-cipalg: AES -+km-hashalg: SHA-384 -+km-keylen: 32 -+km-explen: 0 -+km-ivlen: 4 -+km-maclen: 0 -+km-ccipkey: 3c:03:17:61:1e:88:4a:aa:01:4c:ac:6c:f8:bb:91:c3:0e:ec:57:c7:bf:07:ff:eb:49:22:f9:80:12:64:72:2a -+km-scipkey: f8:00:8e:b2:dc:25:98:f1:97:00:55:28:60:a3:65:da:42:89:18:bb:40:94:53:d2:75:2a:29:e5:aa:94:1d:7a -+km-civ: 24:02:76:6f -+km-siv: 3b:6d:33:5a -+km-cmackey: (null) -+km-smackey: (null) -\ No newline at end of file -diff --git a/jdk/test/sun/security/pkcs11/tls/TestKeyMaterial.java b/jdk/test/sun/security/pkcs11/tls/TestKeyMaterial.java -index 534398a1a..e138a5b1d 100644 ---- a/jdk/test/sun/security/pkcs11/tls/TestKeyMaterial.java -+++ b/jdk/test/sun/security/pkcs11/tls/TestKeyMaterial.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2005, 2022, 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 -@@ -21,9 +21,9 @@ - * questions. - */ - --/** -+/* - * @test -- * @bug 6316539 -+ * @bug 6316539 8136355 8294906 - * @summary Known-answer-test for TlsKeyMaterial generator - * @author Andreas Sterbenz - * @library .. -@@ -34,12 +34,16 @@ - import java.io.BufferedReader; - import java.nio.file.Files; - import java.nio.file.Paths; -+import java.security.InvalidAlgorithmParameterException; - import java.security.Provider; -+import java.security.ProviderException; - import java.util.Arrays; -+ - import javax.crypto.KeyGenerator; - import javax.crypto.SecretKey; - import javax.crypto.spec.IvParameterSpec; - import javax.crypto.spec.SecretKeySpec; -+ - import sun.security.internal.spec.TlsKeyMaterialParameterSpec; - import sun.security.internal.spec.TlsKeyMaterialSpec; - -@@ -48,6 +52,7 @@ public class TestKeyMaterial extends PKCS11Test { - private static final int PREFIX_LENGTH = "km-master: ".length(); - - public static void main(String[] args) throws Exception { -+ System.out.println("NSS Version: " + getNSSVersion()); - main(new TestKeyMaterial(), args); - } - -@@ -70,6 +75,7 @@ public class TestKeyMaterial extends PKCS11Test { - byte[] clientRandom = null; - byte[] serverRandom = null; - String cipherAlgorithm = null; -+ String hashAlgorithm = null; // TLS1.2+ only - int keyLength = 0; - int expandedKeyLength = 0; - int ivLength = 0; -@@ -103,6 +109,8 @@ public class TestKeyMaterial extends PKCS11Test { - serverRandom = parse(data); - } else if (line.startsWith("km-cipalg:")) { - cipherAlgorithm = data; -+ } else if (line.startsWith("km-hashalg:")) { -+ hashAlgorithm = data; - } else if (line.startsWith("km-keylen:")) { - keyLength = Integer.parseInt(data); - } else if (line.startsWith("km-explen:")) { -@@ -128,30 +136,47 @@ public class TestKeyMaterial extends PKCS11Test { - n++; - - KeyGenerator kg = -- KeyGenerator.getInstance("SunTlsKeyMaterial", provider); -+ KeyGenerator.getInstance(minor == 3 ? -+ "SunTls12KeyMaterial" : -+ "SunTlsKeyMaterial", provider); - SecretKey masterKey = - new SecretKeySpec(master, "TlsMasterSecret"); -+ // prfHashLength and prfBlockSize are ignored by PKCS11 provider - TlsKeyMaterialParameterSpec spec = - new TlsKeyMaterialParameterSpec(masterKey, major, minor, - clientRandom, serverRandom, cipherAlgorithm, - keyLength, expandedKeyLength, ivLength, macLength, -- null, -1, -1); -- -- kg.init(spec); -- TlsKeyMaterialSpec result = -- (TlsKeyMaterialSpec)kg.generateKey(); -- match(lineNumber, clientCipherBytes, -- result.getClientCipherKey(), cipherAlgorithm); -- match(lineNumber, serverCipherBytes, -- result.getServerCipherKey(), cipherAlgorithm); -- match(lineNumber, clientIv, result.getClientIv(), ""); -- match(lineNumber, serverIv, result.getServerIv(), ""); -- match(lineNumber, clientMacBytes, result.getClientMacKey(), ""); -- match(lineNumber, serverMacBytes, result.getServerMacKey(), ""); -- -- } else { -+ hashAlgorithm, -1 /*ignored*/, -1 /*ignored*/); -+ -+ try { -+ kg.init(spec); -+ TlsKeyMaterialSpec result = -+ (TlsKeyMaterialSpec)kg.generateKey(); -+ match(lineNumber, clientCipherBytes, -+ result.getClientCipherKey(), cipherAlgorithm); -+ match(lineNumber, serverCipherBytes, -+ result.getServerCipherKey(), cipherAlgorithm); -+ match(lineNumber, clientIv, result.getClientIv(), ""); -+ match(lineNumber, serverIv, result.getServerIv(), ""); -+ match(lineNumber, clientMacBytes, result.getClientMacKey(), ""); -+ match(lineNumber, serverMacBytes, result.getServerMacKey(), ""); -+ } catch (ProviderException pe) { -+ if (provider.getName().indexOf("NSS") != -1) { -+ Throwable t = pe.getCause(); -+ if (expandedKeyLength != 0 -+ && t.getMessage().indexOf( -+ "CKR_MECHANISM_PARAM_INVALID") != -1) { -+ // NSS removed support for export-grade cipher suites in 3.28, -+ // see https://bugzilla.mozilla.org/show_bug.cgi?id=1252849 -+ System.out.println("Ignore known NSS failure on CKR_MECHANISM_PARAM_INVALID"); -+ continue; -+ } -+ } -+ throw pe; -+ } -+ } else { - throw new Exception("Unknown line: " + line); -- } -+ } - } - if (n == 0) { - throw new Exception("no tests"); -diff --git a/jdk/test/sun/security/pkcs11/tls/keymatdata.txt b/jdk/test/sun/security/pkcs11/tls/keymatdata.txt -index 391f30000..1d1ee6369 100644 ---- a/jdk/test/sun/security/pkcs11/tls/keymatdata.txt -+++ b/jdk/test/sun/security/pkcs11/tls/keymatdata.txt -@@ -3646,3 +3646,37 @@ km-civ: 17:bd:47:89:54:be:04:23 - km-siv: 34:8a:e8:24:84:38:c4:e1 - km-cmackey: e8:f0:b5:7b:a7:cc:2f:5e:43:ef:d3:dd:4e:8c:f9:6f:51:d7:84:df - km-smackey: fc:0c:77:20:c2:28:d3:11:ba:57:13:d8:0b:2d:f1:30:89:c6:35:69 -+km-master: f1:05:15:45:33:be:50:d6:88:0b:03:bb:88:9b:ef:d4:3b:98:aa:40:13:71:3c:1c:d9:df:34:c7:50:75:ad:5c:0a:d4:fe:ed:d5:58:6b:ff:2b:ce:c6:12:bc:6b:7e:dc -+km-major: 3 -+km-minor: 3 -+km-crandom: 42:f3:36:8e:9d:c9:69:3e:c1:8a:38:d3:e0:ec:2b:58:c2:e0:0c:de:4f:f3:af:51:d2:5c:bc:b2:c3:3b:1e:56 -+km-srandom: 42:f3:36:8e:fa:fd:23:3e:fd:f9:bc:88:3c:98:93:f3:c3:1d:9c:2a:4a:3b:02:a7:40:d4:64:04:59:e9:65:97 -+km-cipalg: AES -+km-hashalg: SHA-256 -+km-keylen: 16 -+km-explen: 0 -+km-ivlen: 4 -+km-maclen: 0 -+km-ccipkey: 60:7a:45:a9:6e:76:58:ea:d9:44:c5:25:f8:92:f1:26 -+km-scipkey: 42:c0:ed:75:a2:51:21:7c:50:74:9d:78:9a:f7:35:2b -+km-civ: a1:3c:3e:4a -+km-siv: 85:ab:ee:70 -+km-cmackey: (null) -+km-smackey: (null) -+km-master: f1:05:15:45:33:be:50:d6:88:0b:03:bb:88:9b:ef:d4:3b:98:aa:40:13:71:3c:1c:d9:df:34:c7:50:75:ad:5c:0a:d4:fe:ed:d5:58:6b:ff:2b:ce:c6:12:bc:6b:7e:dc -+km-major: 3 -+km-minor: 3 -+km-crandom: 42:f3:36:8e:9d:c9:69:3e:c1:8a:38:d3:e0:ec:2b:58:c2:e0:0c:de:4f:f3:af:51:d2:5c:bc:b2:c3:3b:1e:56 -+km-srandom: 42:f3:36:8e:fa:fd:23:3e:fd:f9:bc:88:3c:98:93:f3:c3:1d:9c:2a:4a:3b:02:a7:40:d4:64:04:59:e9:65:97 -+km-cipalg: AES -+km-hashalg: SHA-384 -+km-keylen: 32 -+km-explen: 0 -+km-ivlen: 4 -+km-maclen: 0 -+km-ccipkey: 3c:03:17:61:1e:88:4a:aa:01:4c:ac:6c:f8:bb:91:c3:0e:ec:57:c7:bf:07:ff:eb:49:22:f9:80:12:64:72:2a -+km-scipkey: f8:00:8e:b2:dc:25:98:f1:97:00:55:28:60:a3:65:da:42:89:18:bb:40:94:53:d2:75:2a:29:e5:aa:94:1d:7a -+km-civ: 24:02:76:6f -+km-siv: 3b:6d:33:5a -+km-cmackey: (null) -+km-smackey: (null) --- -2.22.0 - diff --git a/8295068-SSLEngine-throws-NPE-parsing-CertificateRequ.patch b/8295068-SSLEngine-throws-NPE-parsing-CertificateRequ.patch deleted file mode 100644 index ff03757816aaead59e817849bae4c7327115d1ad..0000000000000000000000000000000000000000 --- a/8295068-SSLEngine-throws-NPE-parsing-CertificateRequ.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 559bf67072bcf7fe854d03aebdfb49e02bd75899 Mon Sep 17 00:00:00 2001 -From: DXwangg -Date: Mon, 25 Sep 2023 09:50:38 +0800 -Subject: [PATCH] 8295068: SSLEngine throws NPE parsing CertificateRequests - ---- - jdk/src/share/classes/sun/security/ssl/CertificateRequest.java | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/jdk/src/share/classes/sun/security/ssl/CertificateRequest.java b/jdk/src/share/classes/sun/security/ssl/CertificateRequest.java -index 475ec42c..ad0325e4 100644 ---- a/jdk/src/share/classes/sun/security/ssl/CertificateRequest.java -+++ b/jdk/src/share/classes/sun/security/ssl/CertificateRequest.java -@@ -135,7 +135,7 @@ final class CertificateRequest { - ArrayList keyTypes = new ArrayList<>(3); - for (byte id : ids) { - ClientCertificateType cct = ClientCertificateType.valueOf(id); -- if (cct.isAvailable) { -+ if (cct != null && cct.isAvailable) { - keyTypes.add(cct.keyAlgorithm); - } - } --- -2.39.0 - diff --git a/8308682-Enhance-AES-performance.patch b/8308682-Enhance-AES-performance.patch deleted file mode 100644 index 84a1e1c4796bbeca319c72bbace07b23459430f9..0000000000000000000000000000000000000000 --- a/8308682-Enhance-AES-performance.patch +++ /dev/null @@ -1,708 +0,0 @@ -From 6926e9b83bc3f9b785d5298786a5c41e247b2a3f Mon Sep 17 00:00:00 2001 -Date: Mon, 16 Oct 2023 10:56:30 +0800 -Subject: [PATCH 1/5] 8308682: Enhance AES performance - -Bug url: https://bugs.openjdk.org/browse/JDK-8308682 ---- - .../src/cpu/aarch64/vm/assembler_aarch64.hpp | 2 + - .../cpu/aarch64/vm/stubGenerator_aarch64.cpp | 451 +++++++++--------- - .../compiler/codegen/aes/CTR_Wraparound.java | 169 +++++++ - 3 files changed, 406 insertions(+), 216 deletions(-) - create mode 100644 hotspot/test/compiler/codegen/aes/CTR_Wraparound.java - -diff --git a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp -index 9202e61f8..b12095aca 100644 ---- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp -+++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp -@@ -2140,6 +2140,8 @@ public: - INSN(sshl, 0, 0b010001); - INSN(ushl, 1, 0b010001); - -+ INSN(cmhi, 1, 0b001101); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D -+ - #undef INSN - - #define INSN(NAME, opc, opc2) \ -diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp -index 565fe559c..f61028d50 100644 ---- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp -+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp -@@ -2804,265 +2804,284 @@ class StubGenerator: public StubCodeGenerator { - return start; - } - -+ // Big-endian 128-bit + 64-bit -> 128-bit addition. -+ // Inputs: 128-bits. in is preserved. -+ // The least-significant 64-bit word is in the upper dword of the vector -+ // inc (the 64-bit increment) is preserved. Its lower dword must be zero -+ // Output: result -+ void be_add_128_64(FloatRegister result, FloatRegister in, -+ FloatRegister inc, FloatRegister tmp) { -+ assert_different_registers(result, tmp, inc); -+ -+ __ addv(result, __ T2D, in, inc); // Add inc to the least-significant dword of input -+ __ cmhi(tmp, __ T2D, inc, result); // Check for result overflowing -+ __ ins(tmp, __ D, tmp, 0, 1); // Move LSD of comparison result to MSD -+ __ ins(tmp, __ D, inc, 1, 0); // Move 0 to LSD of comparison result -+ __ subv(result, __ T2D, result, tmp); // Subtract -1 from MSD if there was an overflow -+ } -+ - // CTR AES crypt. -- // Arguments: -- // -- // Inputs: -- // c_rarg0 - source byte array address -- // c_rarg1 - destination byte array address -- // c_rarg2 - K (key) in little endian int array -- // c_rarg3 - counter vector byte array address -- // c_rarg4 - input length -- // c_rarg5 - saved encryptedCounter start -- // c_rarg6 - saved used length -+ // Arguments: -+ // -+ // Inputs: -+ // c_rarg0 - source byte array address -+ // c_rarg1 - destination byte array address -+ // c_rarg2 - K (key) in little endian int array -+ // c_rarg3 - counter vector byte array address -+ // c_rarg4 - input length -+ // c_rarg5 - saved encryptedCounter start -+ // c_rarg6 - saved used length -+ // -+ // Output: -+ // r0 - input length -+ // -+ address generate_counterMode_AESCrypt() { -+ const Register in = c_rarg0; -+ const Register out = c_rarg1; -+ const Register key = c_rarg2; -+ const Register counter = c_rarg3; -+ const Register saved_len = c_rarg4, len = r10; -+ const Register saved_encrypted_ctr = c_rarg5; -+ const Register used_ptr = c_rarg6, used = r12; -+ -+ const Register offset = r7; -+ const Register keylen = r11; -+ -+ const unsigned char block_size = 16; -+ const int bulk_width = 4; -+ // NB: bulk_width can be 4 or 8. 8 gives slightly faster -+ // performance with larger data sizes, but it also means that the -+ // fast path isn't used until you have at least 8 blocks, and up -+ // to 127 bytes of data will be executed on the slow path. For -+ // that reason, and also so as not to blow away too much icache, 4 -+ // blocks seems like a sensible compromise. -+ -+ // Algorithm: - // -- // Output: -- // r0 - input length -+ // if (len == 0) { -+ // goto DONE; -+ // } -+ // int result = len; -+ // do { -+ // if (used >= blockSize) { -+ // if (len >= bulk_width * blockSize) { -+ // CTR_large_block(); -+ // if (len == 0) -+ // goto DONE; -+ // } -+ // for (;;) { -+ // 16ByteVector v0 = counter; -+ // embeddedCipher.encryptBlock(v0, 0, encryptedCounter, 0); -+ // used = 0; -+ // if (len < blockSize) -+ // break; /* goto NEXT */ -+ // 16ByteVector v1 = load16Bytes(in, offset); -+ // v1 = v1 ^ encryptedCounter; -+ // store16Bytes(out, offset); -+ // used = blockSize; -+ // offset += blockSize; -+ // len -= blockSize; -+ // if (len == 0) -+ // goto DONE; -+ // } -+ // } -+ // NEXT: -+ // out[outOff++] = (byte)(in[inOff++] ^ encryptedCounter[used++]); -+ // len--; -+ // } while (len != 0); -+ // DONE: -+ // return result; - // -- address generate_counterMode_AESCrypt() { -- const Register in = c_rarg0; -- const Register out = c_rarg1; -- const Register key = c_rarg2; -- const Register counter = c_rarg3; -- const Register saved_len = c_rarg4, len = r10; -- const Register saved_encrypted_ctr = c_rarg5; -- const Register used_ptr = c_rarg6, used = r12; -- -- const Register offset = r7; -- const Register keylen = r11; -- -- const unsigned char block_size = 16; -- const int bulk_width = 4; -- // NB: bulk_width can be 4 or 8. 8 gives slightly faster -- // performance with larger data sizes, but it also means that the -- // fast path isn't used until you have at least 8 blocks, and up -- // to 127 bytes of data will be executed on the slow path. For -- // that reason, and also so as not to blow away too much icache, 4 -- // blocks seems like a sensible compromise. -- -- // Algorithm: -- // -- // if (len == 0) { -- // goto DONE; -- // } -- // int result = len; -- // do { -- // if (used >= blockSize) { -- // if (len >= bulk_width * blockSize) { -- // CTR_large_block(); -- // if (len == 0) -- // goto DONE; -- // } -- // for (;;) { -- // 16ByteVector v0 = counter; -- // embeddedCipher.encryptBlock(v0, 0, encryptedCounter, 0); -- // used = 0; -- // if (len < blockSize) -- // break; /* goto NEXT */ -- // 16ByteVector v1 = load16Bytes(in, offset); -- // v1 = v1 ^ encryptedCounter; -- // store16Bytes(out, offset); -- // used = blockSize; -- // offset += blockSize; -- // len -= blockSize; -- // if (len == 0) -- // goto DONE; -- // } -- // } -- // NEXT: -- // out[outOff++] = (byte)(in[inOff++] ^ encryptedCounter[used++]); -- // len--; -- // } while (len != 0); -- // DONE: -- // return result; -- // -- // CTR_large_block() -- // Wide bulk encryption of whole blocks. -+ // CTR_large_block() -+ // Wide bulk encryption of whole blocks. - -- __ align(CodeEntryAlignment); -- StubCodeMark mark(this, "StubRoutines", "counterMode_AESCrypt"); -- const address start = __ pc(); -- __ enter(); -+ __ align(CodeEntryAlignment); -+ StubCodeMark mark(this, "StubRoutines", "counterMode_AESCrypt"); -+ const address start = __ pc(); -+ __ enter(); - -- Label DONE, CTR_large_block, large_block_return; -- __ ldrw(used, Address(used_ptr)); -- __ cbzw(saved_len, DONE); -+ Label DONE, CTR_large_block, large_block_return; -+ __ ldrw(used, Address(used_ptr)); -+ __ cbzw(saved_len, DONE); - -- __ mov(len, saved_len); -- __ mov(offset, 0); -+ __ mov(len, saved_len); -+ __ mov(offset, 0); - -- // Compute #rounds for AES based on the length of the key array -- __ ldrw(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); -+ // Compute #rounds for AES based on the length of the key array -+ __ ldrw(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); - -- __ aesenc_loadkeys(key, keylen); -+ __ aesenc_loadkeys(key, keylen); - -- { -- Label L_CTR_loop, NEXT; -+ { -+ Label L_CTR_loop, NEXT; - -- __ bind(L_CTR_loop); -+ __ bind(L_CTR_loop); - -- __ cmp(used, block_size); -- __ br(__ LO, NEXT); -+ __ cmp(used, block_size); -+ __ br(__ LO, NEXT); - -- // Maybe we have a lot of data -- __ subsw(rscratch1, len, bulk_width * block_size); -- __ br(__ HS, CTR_large_block); -- __ BIND(large_block_return); -- __ cbzw(len, DONE); -+ // Maybe we have a lot of data -+ __ subsw(rscratch1, len, bulk_width * block_size); -+ __ br(__ HS, CTR_large_block); -+ __ BIND(large_block_return); -+ __ cbzw(len, DONE); - -- // Setup the counter -- __ movi(v4, __ T4S, 0); -- __ movi(v5, __ T4S, 1); -- __ ins(v4, __ S, v5, 3, 3); // v4 contains { 0, 0, 0, 1 } -+ // Setup the counter -+ __ movi(v4, __ T4S, 0); -+ __ movi(v5, __ T4S, 1); -+ __ ins(v4, __ S, v5, 2, 2); // v4 contains { 0, 1 } - -- __ ld1(v0, __ T16B, counter); // Load the counter into v0 -- __ rev32(v16, __ T16B, v0); -- __ addv(v16, __ T4S, v16, v4); -- __ rev32(v16, __ T16B, v16); -- __ st1(v16, __ T16B, counter); // Save the incremented counter back -+ // 128-bit big-endian increment -+ __ ld1(v0, __ T16B, counter); -+ __ rev64(v16, __ T16B, v0); -+ be_add_128_64(v16, v16, v4, /*tmp*/v5); -+ __ rev64(v16, __ T16B, v16); -+ __ st1(v16, __ T16B, counter); -+ // Previous counter value is in v0 -+ // v4 contains { 0, 1 } - -- { -- // We have fewer than bulk_width blocks of data left. Encrypt -- // them one by one until there is less than a full block -- // remaining, being careful to save both the encrypted counter -- // and the counter. -- -- Label inner_loop; -- __ bind(inner_loop); -- // Counter to encrypt is in v0 -- __ aesecb_encrypt(noreg, noreg, keylen); -- __ st1(v0, __ T16B, saved_encrypted_ctr); -- -- // Do we have a remaining full block? -- -- __ mov(used, 0); -- __ cmp(len, block_size); -- __ br(__ LO, NEXT); -- -- // Yes, we have a full block -- __ ldrq(v1, Address(in, offset)); -- __ eor(v1, __ T16B, v1, v0); -- __ strq(v1, Address(out, offset)); -- __ mov(used, block_size); -- __ add(offset, offset, block_size); -- -- __ subw(len, len, block_size); -- __ cbzw(len, DONE); -- -- // Increment the counter, store it back -- __ orr(v0, __ T16B, v16, v16); -- __ rev32(v16, __ T16B, v16); -- __ addv(v16, __ T4S, v16, v4); -- __ rev32(v16, __ T16B, v16); -- __ st1(v16, __ T16B, counter); // Save the incremented counter back -- -- __ b(inner_loop); -- } -+ { -+ // We have fewer than bulk_width blocks of data left. Encrypt -+ // them one by one until there is less than a full block -+ // remaining, being careful to save both the encrypted counter -+ // and the counter. - -- __ BIND(NEXT); -- -- // Encrypt a single byte, and loop. -- // We expect this to be a rare event. -- __ ldrb(rscratch1, Address(in, offset)); -- __ ldrb(rscratch2, Address(saved_encrypted_ctr, used)); -- __ eor(rscratch1, rscratch1, rscratch2); -- __ strb(rscratch1, Address(out, offset)); -- __ add(offset, offset, 1); -- __ add(used, used, 1); -- __ subw(len, len,1); -- __ cbnzw(len, L_CTR_loop); -- } -+ Label inner_loop; -+ __ bind(inner_loop); -+ // Counter to encrypt is in v0 -+ __ aesecb_encrypt(noreg, noreg, keylen); -+ __ st1(v0, __ T16B, saved_encrypted_ctr); - -- __ bind(DONE); -- __ strw(used, Address(used_ptr)); -- __ mov(r0, saved_len); -+ // Do we have a remaining full block? - -- __ leave(); // required for proper stackwalking of RuntimeStub frame -- __ ret(lr); -+ __ mov(used, 0); -+ __ cmp(len, block_size); -+ __ br(__ LO, NEXT); - -- // Bulk encryption -+ // Yes, we have a full block -+ __ ldrq(v1, Address(in, offset)); -+ __ eor(v1, __ T16B, v1, v0); -+ __ strq(v1, Address(out, offset)); -+ __ mov(used, block_size); -+ __ add(offset, offset, block_size); - -- __ BIND (CTR_large_block); -- assert(bulk_width == 4 || bulk_width == 8, "must be"); -+ __ subw(len, len, block_size); -+ __ cbzw(len, DONE); - -- if (bulk_width == 8) { -- __ sub(sp, sp, 4 * 16); -- __ st1(v12, v13, v14, v15, __ T16B, Address(sp)); -+ // Increment the counter, store it back -+ __ orr(v0, __ T16B, v16, v16); -+ __ rev64(v16, __ T16B, v16); -+ be_add_128_64(v16, v16, v4, /*tmp*/v5); -+ __ rev64(v16, __ T16B, v16); -+ __ st1(v16, __ T16B, counter); // Save the incremented counter back -+ -+ __ b(inner_loop); - } -- __ sub(sp, sp, 4 * 16); -- __ st1(v8, v9, v10, v11, __ T16B, Address(sp)); -- RegSet saved_regs = (RegSet::of(in, out, offset) -- + RegSet::of(saved_encrypted_ctr, used_ptr, len)); -- __ push(saved_regs, sp); -- __ andr(len, len, -16 * bulk_width); // 8/4 encryptions, 16 bytes per encryption -- __ add(in, in, offset); -- __ add(out, out, offset); - -- // Keys should already be loaded into the correct registers -+ __ BIND(NEXT); -+ -+ // Encrypt a single byte, and loop. -+ // We expect this to be a rare event. -+ __ ldrb(rscratch1, Address(in, offset)); -+ __ ldrb(rscratch2, Address(saved_encrypted_ctr, used)); -+ __ eor(rscratch1, rscratch1, rscratch2); -+ __ strb(rscratch1, Address(out, offset)); -+ __ add(offset, offset, 1); -+ __ add(used, used, 1); -+ __ subw(len, len,1); -+ __ cbnzw(len, L_CTR_loop); -+ } - -- __ ld1(v0, __ T16B, counter); // v0 contains the first counter -- __ rev32(v16, __ T16B, v0); // v16 contains byte-reversed counter -+ __ bind(DONE); -+ __ strw(used, Address(used_ptr)); -+ __ mov(r0, saved_len); - -- // AES/CTR loop -- { -- Label L_CTR_loop; -- __ BIND(L_CTR_loop); -+ __ leave(); // required for proper stackwalking of RuntimeStub frame -+ __ ret(lr); - -- // Setup the counters -- __ movi(v8, __ T4S, 0); -- __ movi(v9, __ T4S, 1); -- __ ins(v8, __ S, v9, 3, 3); // v8 contains { 0, 0, 0, 1 } -+ // Bulk encryption - -- for (FloatRegister f = v0; f < v0 + bulk_width; f++) { -- __ rev32(f, __ T16B, v16); -- __ addv(v16, __ T4S, v16, v8); -- } -+ __ BIND (CTR_large_block); -+ assert(bulk_width == 4 || bulk_width == 8, "must be"); - -- __ ld1(v8, v9, v10, v11, __ T16B, __ post(in, 4 * 16)); -+ if (bulk_width == 8) { -+ __ sub(sp, sp, 4 * 16); -+ __ st1(v12, v13, v14, v15, __ T16B, Address(sp)); -+ } -+ __ sub(sp, sp, 4 * 16); -+ __ st1(v8, v9, v10, v11, __ T16B, Address(sp)); -+ RegSet saved_regs = (RegSet::of(in, out, offset) -+ + RegSet::of(saved_encrypted_ctr, used_ptr, len)); -+ __ push(saved_regs, sp); -+ __ andr(len, len, -16 * bulk_width); // 8/4 encryptions, 16 bytes per encryption -+ __ add(in, in, offset); -+ __ add(out, out, offset); - -- // Encrypt the counters -- __ aesecb_encrypt(noreg, noreg, keylen, v0, bulk_width); -+ // Keys should already be loaded into the correct registers - -- if (bulk_width == 8) { -- __ ld1(v12, v13, v14, v15, __ T16B, __ post(in, 4 * 16)); -- } -+ __ ld1(v0, __ T16B, counter); // v0 contains the first counter -+ __ rev64(v16, __ T16B, v0); // v16 contains byte-reversed counter - -- // XOR the encrypted counters with the inputs -- for (int i = 0; i < bulk_width; i++) { -- __ eor(v0 + i, __ T16B, v0 + i, v8 + i); -- } -+ // AES/CTR loop -+ { -+ Label L_CTR_loop; -+ __ BIND(L_CTR_loop); - -- // Write the encrypted data -- __ st1(v0, v1, v2, v3, __ T16B, __ post(out, 4 * 16)); -- if (bulk_width == 8) { -- __ st1(v4, v5, v6, v7, __ T16B, __ post(out, 4 * 16)); -- } -+ // Setup the counters -+ __ movi(v8, __ T4S, 0); -+ __ movi(v9, __ T4S, 1); -+ __ ins(v8, __ S, v9, 2, 2); // v8 contains { 0, 1 } - -- __ subw(len, len, 16 * bulk_width); -- __ cbnzw(len, L_CTR_loop); -+ for (FloatRegister f = v0; f < v0 + bulk_width; f++) { -+ __ rev64(f, __ T16B, v16); -+ be_add_128_64(v16, v16, v8, /*tmp*/v9); - } - -- // Save the counter back where it goes -- __ rev32(v16, __ T16B, v16); -- __ st1(v16, __ T16B, counter); -+ __ ld1(v8, v9, v10, v11, __ T16B, __ post(in, 4 * 16)); - -- __ pop(saved_regs, sp); -+ // Encrypt the counters -+ __ aesecb_encrypt(noreg, noreg, keylen, v0, bulk_width); - -- __ ld1(v8, v9, v10, v11, __ T16B, __ post(sp, 4 * 16)); - if (bulk_width == 8) { -- __ ld1(v12, v13, v14, v15, __ T16B, __ post(sp, 4 * 16)); -+ __ ld1(v12, v13, v14, v15, __ T16B, __ post(in, 4 * 16)); - } - -- __ andr(rscratch1, len, -16 * bulk_width); -- __ sub(len, len, rscratch1); -- __ add(offset, offset, rscratch1); -- __ mov(used, 16); -- __ strw(used, Address(used_ptr)); -- __ b(large_block_return); -+ // XOR the encrypted counters with the inputs -+ for (int i = 0; i < bulk_width; i++) { -+ __ eor(v0 + i, __ T16B, v0 + i, v8 + i); -+ } - -- return start; -+ // Write the encrypted data -+ __ st1(v0, v1, v2, v3, __ T16B, __ post(out, 4 * 16)); -+ if (bulk_width == 8) { -+ __ st1(v4, v5, v6, v7, __ T16B, __ post(out, 4 * 16)); -+ } -+ -+ __ subw(len, len, 16 * bulk_width); -+ __ cbnzw(len, L_CTR_loop); - } - -+ // Save the counter back where it goes -+ __ rev64(v16, __ T16B, v16); -+ __ st1(v16, __ T16B, counter); -+ -+ __ pop(saved_regs, sp); -+ -+ __ ld1(v8, v9, v10, v11, __ T16B, __ post(sp, 4 * 16)); -+ if (bulk_width == 8) { -+ __ ld1(v12, v13, v14, v15, __ T16B, __ post(sp, 4 * 16)); -+ } -+ -+ __ andr(rscratch1, len, -16 * bulk_width); -+ __ sub(len, len, rscratch1); -+ __ add(offset, offset, rscratch1); -+ __ mov(used, 16); -+ __ strw(used, Address(used_ptr)); -+ __ b(large_block_return); -+ -+ return start; -+ } -+ - - - // Arguments: -diff --git a/hotspot/test/compiler/codegen/aes/CTR_Wraparound.java b/hotspot/test/compiler/codegen/aes/CTR_Wraparound.java -new file mode 100644 -index 000000000..f578b432c ---- /dev/null -+++ b/hotspot/test/compiler/codegen/aes/CTR_Wraparound.java -@@ -0,0 +1,169 @@ -+import javax.crypto.Cipher; -+import javax.crypto.spec.IvParameterSpec; -+import javax.crypto.spec.SecretKeySpec; -+import java.lang.reflect.Executable; -+import java.util.Arrays; -+import java.util.Random; -+import java.util.concurrent.Callable; -+ -+/** -+ * @test -+ * @bug 8308682 -+ * @summary Check for 128-bit AES/CTR wraparound -+ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox /compiler/testlibrary -+ * @build CTR_Wraparound -+ * @run main ClassFileInstaller sun.hotspot.WhiteBox -+ * sun.hotspot.WhiteBox$WhiteBoxPermission -+ * @run main/othervm -Xbootclasspath/a:. -+ * -XX:+UnlockDiagnosticVMOptions -+ * -XX:+WhiteBoxAPI -+ * CTR_Wraparound 32 -+ * @run main/othervm -Xbootclasspath/a:. -+ * -XX:+UnlockDiagnosticVMOptions -+ * -XX:+WhiteBoxAPI -+ * CTR_Wraparound 1009 -+ * @run main/othervm -Xbootclasspath/a:. -+ * -XX:+UnlockDiagnosticVMOptions -+ * -XX:+WhiteBoxAPI -+ * CTR_Wraparound 2048 -+ */ -+ -+public class CTR_Wraparound extends CompilerWhiteBoxTest { -+ private static final String ALGO = "AES/CTR/NoPadding"; -+ private static final int LOOPS = 100000; -+ private int length; -+ private int maxOffset; -+ -+ public CTR_Wraparound(int len,int offset){ -+ super(new CTR_WraparoundTestCase()); -+ length = len; -+ maxOffset = offset; -+ } -+ -+ public static class CTR_WraparoundTestCase implements TestCase { -+ -+ public String name() { -+ return "CTR_WraparoundTestCase"; -+ } -+ -+ public Executable getExecutable(){ -+ try { -+ return Class.forName("com.sun.crypto.provider.CounterMode").getDeclaredMethod("implCrypt", byte[].class, int.class, int.class, byte[].class, int.class); -+ } catch (NoSuchMethodException e) { -+ throw new RuntimeException("Test bug, method unavailable. " + e); -+ } catch (ClassNotFoundException e) { -+ throw new RuntimeException("Test bug, class unavailable. " + e); -+ } -+ } -+ -+ public Callable getCallable() { -+ return null; -+ } -+ -+ public boolean isOsr() { -+ return false; -+ } -+ -+ } -+ -+ private static boolean isServerVM(String VMName) { return VMName.toLowerCase().contains("server");} -+ -+ -+ -+ protected static boolean checkIntrinsicForCompilationLevel(Executable method, int compLevel) { -+ boolean intrinsicEnabled = Boolean.valueOf(getVMOption("UseAESCTRIntrinsics")); -+ boolean intrinsicAvailable = WHITE_BOX.isIntrinsicAvailable(method, -+ compLevel); -+ if(intrinsicAvailable && intrinsicEnabled){ -+ return true; -+ } -+ return false; -+ } -+ -+ public static void main(String[] args) throws Exception { -+ int length = Integer.parseInt(args[0]); -+ int maxOffset = 60; -+ if (args.length > 1) { -+ maxOffset = Integer.parseInt(args[1]); -+ System.out.println("InitialOffset = " + maxOffset); -+ } -+ new CTR_Wraparound(length,maxOffset).test(); -+ } -+ -+ @Override -+ protected void test() throws Exception { -+ -+ String VMName = System.getProperty("java.vm.name"); -+ Executable intrinsicMethod = testCase.getExecutable(); -+ boolean isIntrinsicEnabled = false; -+ if (isServerVM(VMName)) { -+ if (TIERED_COMPILATION) { -+ isIntrinsicEnabled = checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_SIMPLE); -+ } -+ isIntrinsicEnabled = checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_FULL_OPTIMIZATION); -+ } else { -+ isIntrinsicEnabled = checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_SIMPLE); -+ } -+ if(!isIntrinsicEnabled){ -+ return; -+ } -+ -+ -+ long SEED = Long.getLong("jdk.test.lib.random.seed", new Random().nextLong()); -+ Random random = new Random(SEED); -+ -+ byte[] keyBytes = new byte[32]; -+ Arrays.fill(keyBytes, (byte)0xff); -+ SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); -+ -+ byte[] ivBytes = new byte[16]; -+ -+ Arrays.fill(ivBytes, (byte)0xff); -+ -+ byte[][] plaintext = new byte[maxOffset][]; -+ byte[][] ciphertext = new byte[maxOffset][]; -+ -+ for (int offset = 0; offset < maxOffset; offset++) { -+ ivBytes[ivBytes.length - 1] = (byte)-offset; -+ IvParameterSpec iv = new IvParameterSpec(ivBytes); -+ -+ Cipher encryptCipher = Cipher.getInstance(ALGO); -+ Cipher decryptCipher = Cipher.getInstance(ALGO); -+ -+ encryptCipher.init(Cipher.ENCRYPT_MODE, key, iv); -+ decryptCipher.init(Cipher.DECRYPT_MODE, key, iv); -+ -+ plaintext[offset] = new byte[length]; -+ ciphertext[offset] = new byte[length]; -+ random.nextBytes(plaintext[offset]); -+ -+ byte[] decrypted = new byte[length]; -+ -+ encryptCipher.doFinal(plaintext[offset], 0, length, ciphertext[offset]); -+ decryptCipher.doFinal(ciphertext[offset], 0, length, decrypted); -+ -+ if (!Arrays.equals(plaintext[offset], decrypted)) { -+ throw new Exception("mismatch in setup at offset " + offset); -+ } -+ } -+ -+ for (int offset = 0; offset < maxOffset; offset++) { -+ ivBytes[ivBytes.length - 1] = (byte)-offset; -+ IvParameterSpec iv = new IvParameterSpec(ivBytes); -+ -+ Cipher encryptCipher = Cipher.getInstance(ALGO); -+ -+ encryptCipher.init(Cipher.ENCRYPT_MODE, key, iv); -+ -+ byte[] encrypted = new byte[length]; -+ -+ for (int i = 0; i < LOOPS; i++) { -+ encryptCipher.doFinal(plaintext[offset], 0, length, encrypted); -+ if (!Arrays.equals(ciphertext[offset], encrypted)) { -+ throw new Exception("array mismatch at offset " + offset -+ + " with length " + length); -+ } -+ } -+ } -+ } -+} --- -2.19.1 - diff --git a/8312065-Socket.connect-does-not-timeout-when-profili.patch b/8312065-Socket.connect-does-not-timeout-when-profili.patch deleted file mode 100644 index e97b68c31a4d426edf13213510900414370373df..0000000000000000000000000000000000000000 --- a/8312065-Socket.connect-does-not-timeout-when-profili.patch +++ /dev/null @@ -1,366 +0,0 @@ -From 941ebd7303bce4242121cc2173d5fd6dcff2226a Mon Sep 17 00:00:00 2001 -Subject: 8312065: Socket.connect does not timeout when profiling - ---- - jdk/src/aix/native/java/net/aix_close.c | 56 +++++++++--------- - jdk/src/solaris/native/java/net/bsd_close.c | 57 ++++++++++--------- - jdk/src/solaris/native/java/net/linux_close.c | 57 ++++++++++--------- - 3 files changed, 86 insertions(+), 84 deletions(-) - -diff --git a/jdk/src/aix/native/java/net/aix_close.c b/jdk/src/aix/native/java/net/aix_close.c -index 90d57b42f..3402293c6 100644 ---- a/jdk/src/aix/native/java/net/aix_close.c -+++ b/jdk/src/aix/native/java/net/aix_close.c -@@ -53,8 +53,8 @@ - #include - #include - #include -- - #include -+#include "jvm.h" - - /* - * Stack allocated by thread when doing blocking operation -@@ -376,61 +376,61 @@ int NET_SocketClose(int fd) { - /************** Basic I/O operations here ***************/ - - /* -- * Macro to perform a blocking IO operation. Restarts -- * automatically if interrupted by signal (other than -- * our wakeup signal) -+ * Macro to perform a blocking IO operation. -+ * If interrupted by signal (other than our wakeup signal), and if RETRY is true, -+ * then restarts automatically - */ --#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \ -- int ret; \ -- threadEntry_t self; \ -- fdEntry_t *fdEntry = getFdEntry(FD); \ -- if (fdEntry == NULL) { \ -- errno = EBADF; \ -- return -1; \ -- } \ -- do { \ -- startOp(fdEntry, &self); \ -- ret = FUNC; \ -- endOp(fdEntry, &self); \ -- } while (ret == -1 && errno == EINTR); \ -- return ret; \ -+#define BLOCKING_IO_RETURN_INT(FD, FUNC, RETRY) { \ -+ int ret; \ -+ threadEntry_t self; \ -+ fdEntry_t *fdEntry = getFdEntry(FD); \ -+ if (fdEntry == NULL) { \ -+ errno = EBADF; \ -+ return -1; \ -+ } \ -+ do { \ -+ startOp(fdEntry, &self); \ -+ ret = FUNC; \ -+ endOp(fdEntry, &self); \ -+ } while ((RETRY) && ret == -1 && errno == EINTR); \ -+ return ret; \ - } - - int NET_Read(int s, void* buf, size_t len) { -- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) ); -+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0), JNI_TRUE); - } - - int NET_NonBlockingRead(int s, void* buf, size_t len) { -- BLOCKING_IO_RETURN_INT(s, recv(s, buf, len, MSG_NONBLOCK)); -+ BLOCKING_IO_RETURN_INT(s, recv(s, buf, len, MSG_NONBLOCK), JNI_TRUE); - } - - int NET_ReadV(int s, const struct iovec * vector, int count) { -- BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) ); -+ BLOCKING_IO_RETURN_INT( s, readv(s, vector, count), JNI_TRUE); - } - - int NET_RecvFrom(int s, void *buf, int len, unsigned int flags, - struct sockaddr *from, int *fromlen) { - socklen_t socklen = *fromlen; -- BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen) ); -+ BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen), JNI_TRUE); - *fromlen = socklen; - } - - int NET_Send(int s, void *msg, int len, unsigned int flags) { -- BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) ); -+ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags), JNI_TRUE); - } - - int NET_WriteV(int s, const struct iovec * vector, int count) { -- BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) ); -+ BLOCKING_IO_RETURN_INT( s, writev(s, vector, count), JNI_TRUE); - } - - int NET_SendTo(int s, const void *msg, int len, unsigned int - flags, const struct sockaddr *to, int tolen) { -- BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) ); -+ BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen), JNI_TRUE); - } - - int NET_Accept(int s, struct sockaddr *addr, int *addrlen) { - socklen_t socklen = *addrlen; -- BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen) ); -+ BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen), JNI_TRUE); - *addrlen = socklen; - } - -@@ -490,13 +490,13 @@ int NET_Connect(int s, struct sockaddr *addr, int addrlen) { - - #ifndef USE_SELECT - int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { -- BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) ); -+ BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout), JNI_FALSE); - } - #else - int NET_Select(int s, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) { - BLOCKING_IO_RETURN_INT( s-1, -- select(s, readfds, writefds, exceptfds, timeout) ); -+ select(s, readfds, writefds, exceptfds, timeout), JNI_FALSE); - } - #endif - -diff --git a/jdk/src/solaris/native/java/net/bsd_close.c b/jdk/src/solaris/native/java/net/bsd_close.c -index 89a20707c..37a6e5688 100644 ---- a/jdk/src/solaris/native/java/net/bsd_close.c -+++ b/jdk/src/solaris/native/java/net/bsd_close.c -@@ -39,6 +39,7 @@ - #include - #include - #include -+#include "jvm.h" - - /* - * Stack allocated by thread when doing blocking operation -@@ -347,55 +348,55 @@ int NET_SocketClose(int fd) { - /************** Basic I/O operations here ***************/ - - /* -- * Macro to perform a blocking IO operation. Restarts -- * automatically if interrupted by signal (other than -- * our wakeup signal) -+ * Macro to perform a blocking IO operation. -+ * If interrupted by signal (other than our wakeup signal), and if RETRY is true, -+ * then restarts automatically - */ --#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \ -- int ret; \ -- threadEntry_t self; \ -- fdEntry_t *fdEntry = getFdEntry(FD); \ -- if (fdEntry == NULL) { \ -- errno = EBADF; \ -- return -1; \ -- } \ -- do { \ -- startOp(fdEntry, &self); \ -- ret = FUNC; \ -- endOp(fdEntry, &self); \ -- } while (ret == -1 && errno == EINTR); \ -- return ret; \ -+#define BLOCKING_IO_RETURN_INT(FD, FUNC, RETRY) { \ -+ int ret; \ -+ threadEntry_t self; \ -+ fdEntry_t *fdEntry = getFdEntry(FD); \ -+ if (fdEntry == NULL) { \ -+ errno = EBADF; \ -+ return -1; \ -+ } \ -+ do { \ -+ startOp(fdEntry, &self); \ -+ ret = FUNC; \ -+ endOp(fdEntry, &self); \ -+ } while ((RETRY) && ret == -1 && errno == EINTR); \ -+ return ret; \ - } - - int NET_Read(int s, void* buf, size_t len) { -- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) ); -+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0), JNI_TRUE); - } - - int NET_NonBlockingRead(int s, void* buf, size_t len) { -- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT)); -+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT), JNI_TRUE); - } - - int NET_ReadV(int s, const struct iovec * vector, int count) { -- BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) ); -+ BLOCKING_IO_RETURN_INT( s, readv(s, vector, count), JNI_TRUE); - } - - int NET_RecvFrom(int s, void *buf, int len, unsigned int flags, - struct sockaddr *from, int *fromlen) { - /* casting int *fromlen -> socklen_t* Both are ints */ -- BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen) ); -+ BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, (socklen_t *)fromlen), JNI_TRUE); - } - - int NET_Send(int s, void *msg, int len, unsigned int flags) { -- BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) ); -+ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags), JNI_TRUE); - } - - int NET_WriteV(int s, const struct iovec * vector, int count) { -- BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) ); -+ BLOCKING_IO_RETURN_INT( s, writev(s, vector, count), JNI_TRUE); - } - - int NET_SendTo(int s, const void *msg, int len, unsigned int - flags, const struct sockaddr *to, int tolen) { -- BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) ); -+ BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen), JNI_TRUE); - } - - int NET_Accept(int s, struct sockaddr *addr, int *addrlen) { -@@ -403,22 +404,22 @@ int NET_Accept(int s, struct sockaddr *addr, int *addrlen) { - int error = accept(s, addr, &len); - if (error != -1) - *addrlen = (int)len; -- BLOCKING_IO_RETURN_INT( s, error ); -+ BLOCKING_IO_RETURN_INT( s, error, JNI_TRUE); - } - - int NET_Connect(int s, struct sockaddr *addr, int addrlen) { -- BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) ); -+ BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen), JNI_TRUE); - } - - #ifndef USE_SELECT - int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { -- BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) ); -+ BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout), JNI_FALSE); - } - #else - int NET_Select(int s, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) { - BLOCKING_IO_RETURN_INT( s-1, -- select(s, readfds, writefds, exceptfds, timeout) ); -+ select(s, readfds, writefds, exceptfds, timeout), JNI_FALSE); - } - #endif - -diff --git a/jdk/src/solaris/native/java/net/linux_close.c b/jdk/src/solaris/native/java/net/linux_close.c -index f4c53a0d0..2a31b1591 100644 ---- a/jdk/src/solaris/native/java/net/linux_close.c -+++ b/jdk/src/solaris/native/java/net/linux_close.c -@@ -37,6 +37,7 @@ - #include - #include - #include -+#include "jvm.h" - - /* - * Stack allocated by thread when doing blocking operation -@@ -343,77 +344,77 @@ int NET_SocketClose(int fd) { - /************** Basic I/O operations here ***************/ - - /* -- * Macro to perform a blocking IO operation. Restarts -- * automatically if interrupted by signal (other than -- * our wakeup signal) -+ * Macro to perform a blocking IO operation. -+ * If interrupted by signal (other than our wakeup signal), and if RETRY is true, -+ * then restarts automatically - */ --#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \ -- int ret; \ -- threadEntry_t self; \ -- fdEntry_t *fdEntry = getFdEntry(FD); \ -- if (fdEntry == NULL) { \ -- errno = EBADF; \ -- return -1; \ -- } \ -- do { \ -- startOp(fdEntry, &self); \ -- ret = FUNC; \ -- endOp(fdEntry, &self); \ -- } while (ret == -1 && errno == EINTR); \ -- return ret; \ -+#define BLOCKING_IO_RETURN_INT(FD, FUNC, RETRY) { \ -+ int ret; \ -+ threadEntry_t self; \ -+ fdEntry_t *fdEntry = getFdEntry(FD); \ -+ if (fdEntry == NULL) { \ -+ errno = EBADF; \ -+ return -1; \ -+ } \ -+ do { \ -+ startOp(fdEntry, &self); \ -+ ret = FUNC; \ -+ endOp(fdEntry, &self); \ -+ } while ((RETRY) && ret == -1 && errno == EINTR); \ -+ return ret; \ - } - - int NET_Read(int s, void* buf, size_t len) { -- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) ); -+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0), JNI_TRUE); - } - - int NET_NonBlockingRead(int s, void* buf, size_t len) { -- BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT) ); -+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT), JNI_TRUE); - } - - int NET_ReadV(int s, const struct iovec * vector, int count) { -- BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) ); -+ BLOCKING_IO_RETURN_INT( s, readv(s, vector, count), JNI_TRUE); - } - - int NET_RecvFrom(int s, void *buf, int len, unsigned int flags, - struct sockaddr *from, int *fromlen) { - socklen_t socklen = *fromlen; -- BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen) ); -+ BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen), JNI_TRUE); - *fromlen = socklen; - } - - int NET_Send(int s, void *msg, int len, unsigned int flags) { -- BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) ); -+ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags), JNI_TRUE); - } - - int NET_WriteV(int s, const struct iovec * vector, int count) { -- BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) ); -+ BLOCKING_IO_RETURN_INT( s, writev(s, vector, count), JNI_TRUE); - } - - int NET_SendTo(int s, const void *msg, int len, unsigned int - flags, const struct sockaddr *to, int tolen) { -- BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) ); -+ BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen), JNI_TRUE); - } - - int NET_Accept(int s, struct sockaddr *addr, int *addrlen) { - socklen_t socklen = *addrlen; -- BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen) ); -+ BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen), JNI_TRUE); - *addrlen = socklen; - } - - int NET_Connect(int s, struct sockaddr *addr, int addrlen) { -- BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) ); -+ BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen), JNI_TRUE); - } - - #ifndef USE_SELECT - int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { -- BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) ); -+ BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout), JNI_FALSE); - } - #else - int NET_Select(int s, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) { - BLOCKING_IO_RETURN_INT( s-1, -- select(s, readfds, writefds, exceptfds, timeout) ); -+ select(s, readfds, writefds, exceptfds, timeout), JNI_FALSE); - } - #endif - --- -2.22.0 - diff --git a/8312200-Fix-Parse-catch_call_exceptions-memory-leak.patch b/8312200-Fix-Parse-catch_call_exceptions-memory-leak.patch deleted file mode 100644 index fb9f3c3002ad4cd74606e1d738992bfcdaae153c..0000000000000000000000000000000000000000 --- a/8312200-Fix-Parse-catch_call_exceptions-memory-leak.patch +++ /dev/null @@ -1,96 +0,0 @@ -From c8190e59dbdcb9f52af521994523bae6b893716b Mon Sep 17 00:00:00 2001 -Subject: 8312200: Fix Parse::catch_call_exceptions memory leak - ---- - hotspot/src/share/vm/opto/doCall.cpp | 35 ++++++++++++++-------------- - 1 file changed, 18 insertions(+), 17 deletions(-) - -diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp -index 1b2b77c71..f41e6d386 100644 ---- a/hotspot/src/share/vm/opto/doCall.cpp -+++ b/hotspot/src/share/vm/opto/doCall.cpp -@@ -698,24 +698,25 @@ void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) { - Node* i_o = this->i_o(); - - // Add a CatchNode. -- GrowableArray* bcis = new (C->node_arena()) GrowableArray(C->node_arena(), 8, 0, -1); -- GrowableArray* extypes = new (C->node_arena()) GrowableArray(C->node_arena(), 8, 0, NULL); -- GrowableArray* saw_unloaded = new (C->node_arena()) GrowableArray(C->node_arena(), 8, 0, 0); -+ Arena tmp_mem(mtCompiler); -+ GrowableArray bcis(&tmp_mem, 8, 0, -1); -+ GrowableArray extypes(&tmp_mem, 8, 0, NULL); -+ GrowableArray saw_unloaded(&tmp_mem, 8, 0, -1); - - bool default_handler = false; - for (; !handlers.is_done(); handlers.next()) { -- ciExceptionHandler* h = handlers.handler(); -- int h_bci = h->handler_bci(); -- ciInstanceKlass* h_klass = h->is_catch_all() ? env()->Throwable_klass() : h->catch_klass(); -+ ciExceptionHandler* h = handlers.handler(); -+ int h_bci = h->handler_bci(); -+ ciInstanceKlass* h_klass = h->is_catch_all() ? env()->Throwable_klass() : h->catch_klass(); - // Do not introduce unloaded exception types into the graph: - if (!h_klass->is_loaded()) { -- if (saw_unloaded->contains(h_bci)) { -+ if (saw_unloaded.contains(h_bci)) { - /* We've already seen an unloaded exception with h_bci, - so don't duplicate. Duplication will cause the CatchNode to be - unnecessarily large. See 4713716. */ - continue; - } else { -- saw_unloaded->append(h_bci); -+ saw_unloaded.append(h_bci); - } - } - const Type* h_extype = TypeOopPtr::make_from_klass(h_klass); -@@ -723,19 +724,19 @@ void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) { - h_extype = h_extype->join(TypeInstPtr::NOTNULL); - assert(!h_extype->empty(), "sanity"); - // Note: It's OK if the BCIs repeat themselves. -- bcis->append(h_bci); -- extypes->append(h_extype); -+ bcis.append(h_bci); -+ extypes.append(h_extype); - if (h_bci == -1) { - default_handler = true; - } - } - - if (!default_handler) { -- bcis->append(-1); -- extypes->append(TypeOopPtr::make_from_klass(env()->Throwable_klass())->is_instptr()); -+ bcis.append(-1); -+ extypes.append(TypeOopPtr::make_from_klass(env()->Throwable_klass())->is_instptr()); - } - -- int len = bcis->length(); -+ int len = bcis.length(); - CatchNode *cn = new (C) CatchNode(control(), i_o, len+1); - Node *catch_ = _gvn.transform(cn); - -@@ -746,18 +747,18 @@ void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) { - PreserveJVMState pjvms(this); - // Locals are just copied from before the call. - // Get control from the CatchNode. -- int handler_bci = bcis->at(i); -+ int handler_bci = bcis.at(i); - Node* ctrl = _gvn.transform( new (C) CatchProjNode(catch_, i+1,handler_bci)); - // This handler cannot happen? - if (ctrl == top()) continue; - set_control(ctrl); - - // Create exception oop -- const TypeInstPtr* extype = extypes->at(i)->is_instptr(); -- Node *ex_oop = _gvn.transform(new (C) CreateExNode(extypes->at(i), ctrl, i_o)); -+ const TypeInstPtr* extype = extypes.at(i)->is_instptr(); -+ Node *ex_oop = _gvn.transform(new (C) CreateExNode(extypes.at(i), ctrl, i_o)); - - // Handle unloaded exception classes. -- if (saw_unloaded->contains(handler_bci)) { -+ if (saw_unloaded.contains(handler_bci)) { - // An unloaded exception type is coming here. Do an uncommon trap. - #ifndef PRODUCT - // We do not expect the same handler bci to take both cold unloaded --- -2.22.0 - diff --git a/8313626-C2-crash-due-to-unexpected-exception-control.patch b/8313626-C2-crash-due-to-unexpected-exception-control.patch deleted file mode 100644 index baf3f9465c4eace903145b88c9630016390f4562..0000000000000000000000000000000000000000 --- a/8313626-C2-crash-due-to-unexpected-exception-control.patch +++ /dev/null @@ -1,226 +0,0 @@ -From ca014e842f05da9d929152c7e5f7cd56d30629e5 Mon Sep 17 00:00:00 2001 -Subject: 8313626: C2 crash due to unexpected exception control flow - ---- - hotspot/src/share/vm/opto/doCall.cpp | 4 + - .../compiler/MissingSafepointOnTryCatch.jasm | 112 ++++++++++++++++++ - .../TestMissingSafepointOnTryCatch.java | 66 +++++++++++ - 3 files changed, 182 insertions(+) - create mode 100644 jdk/test/jdk/jfr/event/compiler/MissingSafepointOnTryCatch.jasm - create mode 100644 jdk/test/jdk/jfr/event/compiler/TestMissingSafepointOnTryCatch.java - -diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp -index 1b2b77c71..7a7aba359 100644 ---- a/hotspot/src/share/vm/opto/doCall.cpp -+++ b/hotspot/src/share/vm/opto/doCall.cpp -@@ -892,6 +892,8 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) { - tty->print_cr(" Catching every inline exception bci:%d -> handler_bci:%d", bci(), handler_bci); - } - #endif -+ // If this is a backwards branch in the bytecodes, add safepoint -+ maybe_add_safepoint(handler_bci); - merge_exception(handler_bci); // jump to handler - return; // No more handling to be done here! - } -@@ -925,6 +927,8 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) { - tty->cr(); - } - #endif -+ // If this is a backwards branch in the bytecodes, add safepoint -+ maybe_add_safepoint(handler_bci); - merge_exception(handler_bci); - } - set_control(not_subtype_ctrl); -diff --git a/jdk/test/jdk/jfr/event/compiler/MissingSafepointOnTryCatch.jasm b/jdk/test/jdk/jfr/event/compiler/MissingSafepointOnTryCatch.jasm -new file mode 100644 -index 000000000..413736e59 ---- /dev/null -+++ b/jdk/test/jdk/jfr/event/compiler/MissingSafepointOnTryCatch.jasm -@@ -0,0 +1,112 @@ -+/* -+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2023, 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. -+ */ -+ -+public class MissingSafepointOnTryCatch version 52:0 { -+ -+ static Method m:"()V" { -+ return; -+ } -+ -+ static Method test1:"()V" stack 1 { -+ try t; -+ invokestatic m:"()V"; -+ return; -+ -+ catch t java/lang/Throwable; -+ stack_map class java/lang/Throwable; -+ athrow; -+ endtry t; -+ } -+ -+ static Method test2:"()V" stack 1 { -+ try t0; -+ try t1; -+ invokestatic m:"()V"; -+ endtry t1; -+ return; -+ -+ catch t1 java/lang/Exception; -+ stack_map class java/lang/Exception; -+ return; -+ -+ catch t0 java/lang/Throwable; -+ stack_map class java/lang/Throwable; -+ athrow; -+ endtry t0; -+ } -+ -+ public static Method th:"()V" -+ throws java/lang/Exception -+ stack 2 locals 0 -+ { -+ new class java/lang/Exception; -+ dup; -+ invokespecial Method java/lang/Exception."":"()V"; -+ athrow; -+ } -+ -+ static Method test3:"()V" stack 1 locals 2 { -+ try t; -+ invokestatic m:"()V"; -+ iconst_1; -+ istore_0; -+ iconst_0; -+ istore_1; -+ return; -+ catch t java/lang/Throwable; -+ stack_map class java/lang/Throwable; -+ invokestatic th:"()V"; -+ return; -+ endtry t; -+ } -+ -+ static Method test4:"()V" stack 2 locals 2 { -+ try t; -+ invokestatic m:"()V"; -+ iconst_1; -+ istore_0; -+ iconst_0; -+ istore_1; -+ return; -+ catch t java/lang/Throwable; -+ stack_map class java/lang/Throwable; -+ iconst_1; -+ istore_0; -+ invokestatic th:"()V"; -+ return; -+ endtry t; -+ } -+ -+ static Method testInfinite:"()V" stack 1 { -+ try t; -+ invokestatic th:"()V"; -+ return; -+ -+ catch t java/lang/Throwable; -+ stack_map class java/lang/Throwable; -+ athrow; -+ endtry t; -+ } -+ -+} // end Class MissingSafepointOnTryCatch -diff --git a/jdk/test/jdk/jfr/event/compiler/TestMissingSafepointOnTryCatch.java b/jdk/test/jdk/jfr/event/compiler/TestMissingSafepointOnTryCatch.java -new file mode 100644 -index 000000000..fa579b7d4 ---- /dev/null -+++ b/jdk/test/jdk/jfr/event/compiler/TestMissingSafepointOnTryCatch.java -@@ -0,0 +1,66 @@ -+/* -+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2023, 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 8313626 -+ * @library /lib / -+ * @summary assert(false) failed: malformed control flow to missing safepoint on backedge of a try-catch -+ * @compile MissingSafepointOnTryCatch.jasm -+ * @run main/othervm -XX:CompileCommand=quiet -+ * -XX:CompileCommand=compileonly,MissingSafepointOnTryCatch::test* -+ * -XX:CompileCommand=dontinline,MissingSafepointOnTryCatch::m -+ * -XX:CompileCommand=inline,MissingSafepointOnTryCatch::th -+ * -XX:-TieredCompilation -Xcomp TestMissingSafepointOnTryCatch -+ */ -+ -+import jdk.test.lib.Utils; -+ -+public class TestMissingSafepointOnTryCatch { -+ -+ public static void infiniteLoop() { -+ try { -+ Thread thread = new Thread() { -+ public void run() { -+ MissingSafepointOnTryCatch.testInfinite(); -+ } -+ }; -+ thread.setDaemon(true); -+ thread.start(); -+ Thread.sleep(Utils.adjustTimeout(500)); -+ } catch (Exception e) {} -+ } -+ -+ public static void main(String[] args) { -+ try { -+ // to make sure java/lang/Exception class is resolved -+ MissingSafepointOnTryCatch.th(); -+ } catch (Exception e) {} -+ MissingSafepointOnTryCatch.test1(); -+ MissingSafepointOnTryCatch.test2(); -+ MissingSafepointOnTryCatch.test3(); -+ MissingSafepointOnTryCatch.test4(); -+ infiniteLoop(); -+ } -+} --- -2.22.0 - diff --git a/8314236-Overflow-in-Collections.rotate.patch b/8314236-Overflow-in-Collections.rotate.patch deleted file mode 100644 index 4a2fb30aa346c46f0f2716abe660848bce780a36..0000000000000000000000000000000000000000 --- a/8314236-Overflow-in-Collections.rotate.patch +++ /dev/null @@ -1,127 +0,0 @@ -From 11bd45aac555a00c705c8bf480a179bb063b1c44 Mon Sep 17 00:00:00 2001 -Subject: 8314236: Overflow in Collections.rotate ---- - .../share/classes/java/util/Collections.java | 9 +- - .../java/util/Collections/RotateHuge.java | 85 +++++++++++++++++++ - 2 files changed, 90 insertions(+), 4 deletions(-) - create mode 100644 jdk/test/java/util/Collections/RotateHuge.java - -diff --git a/jdk/src/share/classes/java/util/Collections.java b/jdk/src/share/classes/java/util/Collections.java -index 3ab4c5ec0..9aa373841 100644 ---- a/jdk/src/share/classes/java/util/Collections.java -+++ b/jdk/src/share/classes/java/util/Collections.java -@@ -789,15 +789,16 @@ public class Collections { - if (distance == 0) - return; - -- for (int cycleStart = 0, nMoved = 0; nMoved != size; cycleStart++) { -+ int bound = size - distance; -+ for (int cycleStart = 0, nMoved = 0; nMoved < size; cycleStart++) { - T displaced = list.get(cycleStart); - int i = cycleStart; - do { -- i += distance; -- if (i >= size) -+ if (i >= bound) - i -= size; -+ i += distance; - displaced = list.set(i, displaced); -- nMoved ++; -+ nMoved++; - } while (i != cycleStart); - } - } -diff --git a/jdk/test/java/util/Collections/RotateHuge.java b/jdk/test/java/util/Collections/RotateHuge.java -new file mode 100644 -index 000000000..a6f8f739c ---- /dev/null -+++ b/jdk/test/java/util/Collections/RotateHuge.java -@@ -0,0 +1,85 @@ -+/* -+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2023, 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 8314236 -+ * @summary Overflow in Collections.rotate -+ */ -+ -+import com.sun.crypto.provider.Preconditions; -+ -+import java.util.AbstractList; -+import java.util.Collections; -+import java.util.List; -+import java.util.RandomAccess; -+ -+public class RotateHuge { -+ -+ private static final class MockList extends AbstractList -+ implements RandomAccess { -+ private final int size; -+ -+ public MockList(final int size) { -+ if (size < 0) -+ throw new IllegalArgumentException("Illegal size: " + size); -+ this.size = size; -+ } -+ -+ @Override -+ public Object get(final int index) { -+ Preconditions.checkIndex(index, size, null); -+ return null; -+ } -+ -+ @Override -+ public Object set(final int index, final Object element) { -+ Preconditions.checkIndex(index, size, null); -+ return null; -+ } -+ -+ @Override -+ public int size() { -+ return size; -+ } -+ } -+ -+ public static void main(final String[] args) { -+ testRotate((1 << 30) + 1, -(1 << 30) - 2); -+ testRotate((1 << 30) + 1, 1 << 30); -+ testRotate(Integer.MAX_VALUE, Integer.MIN_VALUE); -+ testRotate(Integer.MAX_VALUE, Integer.MIN_VALUE + 3); -+ testRotate(Integer.MAX_VALUE, 2); -+ testRotate(Integer.MAX_VALUE, Integer.MAX_VALUE - 1); -+ } -+ -+ /* -+ * This test covers only index computations. -+ * Correctness of elements rotation is not checked. -+ */ -+ private static void testRotate(final int size, final int distance) { -+ final List list = new MockList(size); -+ Collections.rotate(list, distance); -+ } -+} --- -2.22.0 - diff --git a/Add-metaspace-memory-allocation-failure-validation.patch b/Add-metaspace-memory-allocation-failure-validation.patch deleted file mode 100644 index 9f0a82e84d9ed3e1b49973fc2414af21fac23a1d..0000000000000000000000000000000000000000 --- a/Add-metaspace-memory-allocation-failure-validation.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 0778f0119083ae33aea5ce9b5a1b44f565f45397 Mon Sep 17 00:00:00 2001 -Date: Thu, 19 Oct 2023 15:25:43 +0800 -Subject: [PATCH 4/5] Add metaspace memory allocation failure validation - ---- - hotspot/src/share/vm/memory/metaspace.cpp | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp -index 0569500c1..f39ae41f3 100644 ---- a/hotspot/src/share/vm/memory/metaspace.cpp -+++ b/hotspot/src/share/vm/memory/metaspace.cpp -@@ -571,7 +571,7 @@ class OccupancyMap : public CHeapObj { - assert(_map_size * 8 >= num_bits, "sanity"); - _map[0] = (uint8_t*) os::malloc(_map_size, mtInternal); - _map[1] = (uint8_t*) os::malloc(_map_size, mtInternal); -- assert(_map[0] != NULL && _map[1] != NULL, "Occupancy Map: allocation failed."); -+ guarantee(_map[0] != NULL && _map[1] != NULL, "Metaspace Occupancy Map: allocation failed."); - memset(_map[1], 0, _map_size); - memset(_map[0], 0, _map_size); - // Sanity test: the first respectively last possible chunk start address in -@@ -918,6 +918,14 @@ void VirtualSpaceNode::print_map(outputStream* st, bool is_class) const { - char* lines[NUM_LINES]; - for (int i = 0; i < NUM_LINES; i ++) { - lines[i] = (char*)os::malloc(line_len, mtInternal); -+ // Only print the VirtualSpaceNode memory layout during metaspace OOM. -+ // If it fails,we should return instead of hanging the VM. -+ if (lines[i] == NULL) { -+ for (int j = 0; j < i; j ++) { -+ os::free(lines[j]); -+ } -+ return; -+ } - } - int pos = 0; - const MetaWord* p = bottom(); --- -2.19.1 - diff --git a/Dynamic-CDS-Archive.patch b/Dynamic-CDS-Archive.patch index 30a6ff8169def8d3ed47633f5431a0b3a19d72dd..edccdea2d34992af8b341928e6630b677a2897e3 100644 --- a/Dynamic-CDS-Archive.patch +++ b/Dynamic-CDS-Archive.patch @@ -3047,8 +3047,12 @@ index 8dd4e6b21..6a2d8077f 100644 void SymbolTable::buckets_unlink(int start_idx, int end_idx, BucketUnlinkContext* context, size_t* memory_total) { for (int i = start_idx; i < end_idx; ++i) { -@@ -228,7 +244,22 @@ Symbol* SymbolTable::lookup(int index, const char* name, - java_lang_String::hash_code((const jbyte*)s, len); +@@ -225,10 +241,25 @@ Symbol* SymbolTable::lookup(int index, const char* name, + unsigned int SymbolTable::hash_symbol(const char* s, int len) { + return use_alternate_hashcode() ? + AltHashing::halfsiphash_32(seed(), (const uint8_t*)s, len) : +- java_lang_String::hash_code(s, len); ++ java_lang_String::hash_code((const jbyte*)s, len); } +#if INCLUDE_CDS diff --git a/Fix-crash-in-JNI-s-GetDoubleArrayRegion-and-SetDoubl.patch b/Fix-crash-in-JNI-s-GetDoubleArrayRegion-and-SetDoubl.patch deleted file mode 100644 index a625db8c3c81921bd665a3ac156ae4957bd06dfe..0000000000000000000000000000000000000000 --- a/Fix-crash-in-JNI-s-GetDoubleArrayRegion-and-SetDoubl.patch +++ /dev/null @@ -1,53 +0,0 @@ -From ff782010bb5610fb9bb9e9ebbf131ba71124d299 Mon Sep 17 00:00:00 2001 -Subject: Fix crash in JNI's GetDoubleArrayRegion and SetDoubleArrayRegion ---- - hotspot/src/share/vm/prims/jni.cpp | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp -index 953300ebc..c0d789b42 100644 ---- a/hotspot/src/share/vm/prims/jni.cpp -+++ b/hotspot/src/share/vm/prims/jni.cpp -@@ -3805,7 +3805,7 @@ jni_Get##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, - int sc = TypeArrayKlass::cast(src->klass())->log2_element_size(); \ - memcpy((u_char*) buf, \ - (u_char*) src->Tag##_at_addr(start), \ -- len << sc); \ -+ (size_t)len << sc); \ - } \ - } \ - JNI_END -@@ -3840,7 +3840,7 @@ jni_Get##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, - int sc = TypeArrayKlass::cast(src->klass())->log2_element_size(); \ - memcpy((u_char*) buf, \ - (u_char*) src->Tag##_at_addr(start), \ -- len << sc); \ -+ (size_t)len << sc); \ - } \ - } \ - JNI_END -@@ -3888,8 +3888,8 @@ jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, - if (len > 0) { \ - int sc = TypeArrayKlass::cast(dst->klass())->log2_element_size(); \ - memcpy((u_char*) dst->Tag##_at_addr(start), \ -- (u_char*) buf, \ -- len << sc); \ -+ (u_char*) buf, \ -+ (size_t)len << sc); \ - } \ - } \ - JNI_END -@@ -3923,8 +3923,8 @@ jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, - if (len > 0) { \ - int sc = TypeArrayKlass::cast(dst->klass())->log2_element_size(); \ - memcpy((u_char*) dst->Tag##_at_addr(start), \ -- (u_char*) buf, \ -- len << sc); \ -+ (u_char*) buf, \ -+ (size_t)len << sc); \ - } \ - } \ - JNI_END --- -2.22.0 - diff --git a/Fix-the-memory-leak-of-MetaspaceAllocationTest.patch b/Fix-the-memory-leak-of-MetaspaceAllocationTest.patch deleted file mode 100644 index 896d6f9a06bee9526d65267a4425205a3f07fc72..0000000000000000000000000000000000000000 --- a/Fix-the-memory-leak-of-MetaspaceAllocationTest.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 1c55195c050d26f7c3ef53ed8f4ff25f398cfa1e Mon Sep 17 00:00:00 2001 -Date: Thu, 19 Oct 2023 11:24:12 +0800 -Subject: [PATCH 2/5] Fix the memory leak of MetaspaceAllocationTest - ---- - hotspot/src/share/vm/memory/metaspace.cpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp -index 0569500c1..847af1ce9 100644 ---- a/hotspot/src/share/vm/memory/metaspace.cpp -+++ b/hotspot/src/share/vm/memory/metaspace.cpp -@@ -5712,6 +5712,8 @@ public: - for (int i = 0; i < NUM_PARALLEL_METASPACES; i ++) { - if (_spaces[i].space != NULL) { - delete _spaces[i].space; -+ } -+ if (_spaces[i].lock != NULL) { - delete _spaces[i].lock; - } - } --- -2.19.1 - diff --git a/Record-the-number-of-processes-to-errlog-file.patch.patch b/Record-the-number-of-processes-to-errlog-file.patch.patch deleted file mode 100644 index 5e6e66b8a0630faa695e67ebd6ff81e4192c5bf0..0000000000000000000000000000000000000000 --- a/Record-the-number-of-processes-to-errlog-file.patch.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 752494be2626cb819c92269e26f53833b2538160 Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 14:46:56 +0800 -Subject: Record-the-number-of-processes-to-errlog-file.patch - ---- - hotspot/src/os/linux/vm/os_linux.cpp | 24 ++++++++++++++++++++++++ - hotspot/src/os/linux/vm/os_linux.hpp | 1 + - 2 files changed, 25 insertions(+) - -diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp -index 72839eb5a..a1cc85ca3 100644 ---- a/hotspot/src/os/linux/vm/os_linux.cpp -+++ b/hotspot/src/os/linux/vm/os_linux.cpp -@@ -2256,6 +2256,10 @@ void os::print_os_info(outputStream* st) { - - os::Posix::print_load_average(st); - -+ if (ExtensiveErrorReports) { -+ os::Linux::print_system_process_count(st); -+ } -+ - os::Linux::print_system_memory_info(st); - st->cr(); - -@@ -2323,6 +2327,26 @@ void os::Linux::print_libversion_info(outputStream* st) { - st->cr(); - } - -+void os::Linux::print_system_process_count(outputStream* st) { -+ // system process count -+ DIR *dir = opendir("/proc"); -+ if (dir == NULL) { -+ return; -+ } -+ -+ st->print("system process count:"); -+ uint count = 0; -+ struct dirent *ptr; -+ while ((ptr = readdir(dir)) != NULL) { -+ if(ptr->d_type == DT_DIR && isdigit((ptr->d_name)[0])) { -+ count++; -+ } -+ } -+ (void) closedir(dir); -+ st->print("%u", count); -+ st->cr(); -+} -+ - void os::Linux::print_system_memory_info(outputStream* st) { - st->print("\n/proc/meminfo:\n"); - _print_ascii_file("/proc/meminfo", st); -diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp -index a516335d2..19dde2e58 100644 ---- a/hotspot/src/os/linux/vm/os_linux.hpp -+++ b/hotspot/src/os/linux/vm/os_linux.hpp -@@ -124,6 +124,7 @@ class Linux { - static void print_container_info(outputStream* st); - static void print_distro_info(outputStream* st); - static void print_libversion_info(outputStream* st); -+ static void print_system_process_count(outputStream* st); - static void print_proc_sys_info(outputStream* st); - - public: --- -2.22.0 - diff --git a/The-OverWriteOldestGCLog-option-is-added-to-control.patch b/The-OverWriteOldestGCLog-option-is-added-to-control.patch deleted file mode 100644 index d80eddd2aa16fc24bf3e014ddbae9976a6d1bb6e..0000000000000000000000000000000000000000 --- a/The-OverWriteOldestGCLog-option-is-added-to-control.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 2fd15967a7974d1d61cc7aa706c82733c572964d Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:14:11 +0800 -Subject: The-OverWriteOldestGCLog-option-is-added-to-control - ---- - hotspot/src/share/vm/runtime/globals.hpp | 3 ++ - hotspot/src/share/vm/utilities/ostream.cpp | 45 ++++++++++++++++++++++ - 2 files changed, 48 insertions(+) - -diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp -index 4f649bd45..fdd9db149 100644 ---- a/hotspot/src/share/vm/runtime/globals.hpp -+++ b/hotspot/src/share/vm/runtime/globals.hpp -@@ -2571,6 +2571,9 @@ class CommandLineFlags { - "GC log file size, requires UseGCLogFileRotation. " \ - "Set to 0 to only trigger rotation via jcmd") \ - \ -+ product(bool, OverWriteOldestGCLog, false, \ -+ "Over write the oldest gclog") \ -+ \ - /* JVMTI heap profiling */ \ - \ - diagnostic(bool, TraceJVMTIObjectTagging, false, \ -diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp -index f4e127145..133b5a7c0 100644 ---- a/hotspot/src/share/vm/utilities/ostream.cpp -+++ b/hotspot/src/share/vm/utilities/ostream.cpp -@@ -843,6 +843,48 @@ gcLogFileStream::~gcLogFileStream() { - delete _file_lock; - } - -+static uintx next_file_number(const char* filename) { -+ uintx next_num; -+ uintx index; -+ char gclog[JVM_MAXPATHLEN]; -+ struct stat st; -+ long oldestTime = LONG_MAX; -+ bool normal_file_exist; -+ bool current_file_exist; -+ for (index = 0; index < NumberOfGCLogFiles; ++index) { -+ // normal gc log file -+ jio_snprintf(gclog, JVM_MAXPATHLEN, "%s.%d", filename, index); -+ normal_file_exist = (os::stat(gclog, &st) == 0); -+ if (normal_file_exist && oldestTime > st.st_mtime) { -+ oldestTime = st.st_mtime; -+ next_num = index; -+ } -+ -+ // current gc log file -+ jio_snprintf(gclog, JVM_MAXPATHLEN, "%s.%d" CURRENTAPPX, filename, index); -+ current_file_exist = (os::stat(gclog, &st) == 0); -+ if (current_file_exist && oldestTime > st.st_mtime) { -+ oldestTime = st.st_mtime; -+ next_num = index; -+ } -+ -+ // Stop looking if we find an unused file name -+ if (!normal_file_exist && !current_file_exist) { -+ next_num = index; -+ break; -+ } -+ } -+ // remove the existing normal file -+ char exist_file_name[JVM_MAXPATHLEN]; -+ jio_snprintf(exist_file_name, JVM_MAXPATHLEN, "%s.%d", filename, next_num); -+ if (access(exist_file_name, 0) == 0) { // mode 0: Check whether the file exists, F_OK=0. F_OK will cause Windows build failure. Use 0 instead. -+ if (remove(exist_file_name) != 0) { -+ warning("Could not delete existing normal file %s\n", exist_file_name); -+ } -+ } -+ return next_num; -+} -+ - gcLogFileStream::gcLogFileStream(const char* file_name) : _file_lock(NULL) { - _cur_file_num = 0; - _bytes_written = 0L; -@@ -857,6 +899,9 @@ gcLogFileStream::gcLogFileStream(const char* file_name) : _file_lock(NULL) { - - // gc log file rotation - if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) { -+ if (OverWriteOldestGCLog) { -+ _cur_file_num = next_file_number(_file_name); -+ } - char tempbuf[JVM_MAXPATHLEN]; - jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num); - _file = fopen(tempbuf, "w"); --- -2.22.0 - diff --git a/add-0010-8301749-Tracking-malloc-pooled-memory-size.patch b/add-0010-8301749-Tracking-malloc-pooled-memory-size.patch deleted file mode 100644 index 5e3056ba14658c1aa9e6d71f944a9d12cf2b3708..0000000000000000000000000000000000000000 --- a/add-0010-8301749-Tracking-malloc-pooled-memory-size.patch +++ /dev/null @@ -1,311 +0,0 @@ -From fe0409dd4a7b26a623d2e0ad77be635b20f11d29 Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 14:44:51 +0800 -Subject: add 0010-8301749-Tracking-malloc-pooled-memory-size - ---- - hotspot/src/os/linux/vm/mallocInfoDcmd.cpp | 62 +++++++++++++++++++ - hotspot/src/os/linux/vm/mallocInfoDcmd.hpp | 51 +++++++++++++++ - hotspot/src/os/linux/vm/os_linux.cpp | 10 +++ - hotspot/src/os/linux/vm/os_linux.hpp | 4 ++ - .../share/vm/services/diagnosticCommand.cpp | 2 + - .../serviceability/dcmd/MallocInfoTest.java | 54 ++++++++++++++++ - .../com/oracle/java/testlibrary/Platform.java | 18 +++++- - 7 files changed, 199 insertions(+), 2 deletions(-) - create mode 100644 hotspot/src/os/linux/vm/mallocInfoDcmd.cpp - create mode 100644 hotspot/src/os/linux/vm/mallocInfoDcmd.hpp - create mode 100644 hotspot/test/serviceability/dcmd/MallocInfoTest.java - -diff --git a/hotspot/src/os/linux/vm/mallocInfoDcmd.cpp b/hotspot/src/os/linux/vm/mallocInfoDcmd.cpp -new file mode 100644 -index 000000000..4e50a8e13 ---- /dev/null -+++ b/hotspot/src/os/linux/vm/mallocInfoDcmd.cpp -@@ -0,0 +1,62 @@ -+/* -+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#include "precompiled.hpp" -+#include "mallocInfoDcmd.hpp" -+#include "os_linux.hpp" -+#include "utilities/globalDefinitions.hpp" -+#include "utilities/ostream.hpp" -+ -+#include -+ -+const char* malloc_info_unavailable = "Error: malloc_info(3) not available."; -+ -+void MallocInfoDcmd::execute(DCmdSource source, TRAPS) { -+#ifdef __GLIBC__ -+ char* buf; -+ size_t size; -+ FILE* stream = ::open_memstream(&buf, &size); -+ if (stream == NULL) { -+ _output->print_cr("Error: Could not call malloc_info(3)"); -+ return; -+ } -+ -+ int err = os::Linux::malloc_info(stream); -+ if (err == 0) { -+ fflush(stream); -+ _output->print_raw(buf); -+ _output->cr(); -+ } else if (err == -1) { -+ _output->print_cr("Error: %s", strerror(errno)); -+ } else if (err == -2) { -+ _output->print_cr("%s", malloc_info_unavailable); -+ } else { -+ ShouldNotReachHere(); -+ } -+ ::fclose(stream); -+ ::free(buf); -+#else -+ _output->print_cr(malloc_info_unavailable); -+#endif // __GLIBC__ -+} -diff --git a/hotspot/src/os/linux/vm/mallocInfoDcmd.hpp b/hotspot/src/os/linux/vm/mallocInfoDcmd.hpp -new file mode 100644 -index 000000000..deb154415 ---- /dev/null -+++ b/hotspot/src/os/linux/vm/mallocInfoDcmd.hpp -@@ -0,0 +1,51 @@ -+/* -+ * Copyright (c) 2023, 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. -+ * -+ */ -+ -+#ifndef OS_LINUX_MALLOCINFODCMD_HPP -+#define OS_LINUX_MALLOCINFODCMD_HPP -+ -+#include "services/diagnosticCommand.hpp" -+ -+class outputStream; -+ -+class MallocInfoDcmd : public DCmd { -+public: -+ MallocInfoDcmd(outputStream* output, bool heap) : DCmd(output, heap) {} -+ static const char* name() { -+ return "System.native_heap_info"; -+ } -+ static const char* description() { -+ return "Attempts to output information regarding native heap usage through malloc_info(3). If unsuccessful outputs \"Error: \" and a reason."; -+ } -+ static const char* impact() { -+ return "Low"; -+ } -+ static const JavaPermission permission() { -+ JavaPermission p = { "java.lang.management.ManagementPermission", "monitor", NULL }; -+ return p; -+ } -+ void execute(DCmdSource source, TRAPS); -+}; -+ -+#endif // OS_LINUX_MALLOCINFODCMD_HPP -diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp -index cf3a166aa..72839eb5a 100644 ---- a/hotspot/src/os/linux/vm/os_linux.cpp -+++ b/hotspot/src/os/linux/vm/os_linux.cpp -@@ -177,6 +177,8 @@ typedef struct glibc_mallinfo (*mallinfo_func_t)(void); - typedef struct os::Linux::glibc_mallinfo2 (*mallinfo2_func_t)(void); - static mallinfo_func_t g_mallinfo = NULL; - static mallinfo2_func_t g_mallinfo2 = NULL; -+typedef int (*malloc_info_func_t)(int options, FILE *stream); -+static malloc_info_func_t g_malloc_info = NULL; - #endif // __GLIBC__ - - static jlong initial_time_count=0; -@@ -5416,6 +5418,7 @@ void os::init(void) { - #ifdef __GLIBC__ - g_mallinfo = CAST_TO_FN_PTR(mallinfo_func_t, dlsym(RTLD_DEFAULT, "mallinfo")); - g_mallinfo2 = CAST_TO_FN_PTR(mallinfo2_func_t, dlsym(RTLD_DEFAULT, "mallinfo2")); -+ g_malloc_info = CAST_TO_FN_PTR(malloc_info_func_t, dlsym(RTLD_DEFAULT, "malloc_info")); - #endif // __GLIBC__ - - // _main_thread points to the thread that created/loaded the JVM. -@@ -7072,6 +7075,13 @@ os::Linux::mallinfo_retval_t os::Linux::get_mallinfo(glibc_mallinfo2* out) { - } - return os::Linux::ok; - } -+ -+int os::Linux::malloc_info(FILE* stream) { -+ if (g_malloc_info == NULL) { -+ return -2; -+ } -+ return g_malloc_info(0, stream); -+} - #endif // __GLIBC__ - - // Trim-native support -diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp -index 39a2b4989..a516335d2 100644 ---- a/hotspot/src/os/linux/vm/os_linux.hpp -+++ b/hotspot/src/os/linux/vm/os_linux.hpp -@@ -488,6 +488,10 @@ public: - // If we only have mallinfo(), values may be 32-bit truncated, which is signaled via - // "ok_but_possibly_wrapped". - static mallinfo_retval_t get_mallinfo(glibc_mallinfo2* out); -+ -+ // Calls out to GNU extension malloc_info if available -+ // otherwise does nothing and returns -2. -+ static int malloc_info(FILE* stream); - #endif - - static bool isbound_to_all_node() { -diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp -index 50050a169..416dc77ce 100644 ---- a/hotspot/src/share/vm/services/diagnosticCommand.cpp -+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp -@@ -39,6 +39,7 @@ - - #ifdef LINUX - #include "trimCHeapDCmd.hpp" -+#include "mallocInfoDcmd.hpp" - #endif - - PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC -@@ -79,6 +80,7 @@ void DCmdRegistrant::register_dcmds(){ - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - #ifdef LINUX - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); -+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - #endif // LINUX - - // Enhanced JMX Agent Support -diff --git a/hotspot/test/serviceability/dcmd/MallocInfoTest.java b/hotspot/test/serviceability/dcmd/MallocInfoTest.java -new file mode 100644 -index 000000000..bc8ab3ef4 ---- /dev/null -+++ b/hotspot/test/serviceability/dcmd/MallocInfoTest.java -@@ -0,0 +1,54 @@ -+/* -+ * Copyright (c) 2023, 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. -+ */ -+ -+import org.testng.annotations.Test; -+import com.oracle.java.testlibrary.*; -+ -+/* -+ * @test -+ * @summary Test of diagnostic command System.native_heap_info -+ * @library /testlibrary -+ * @requires (os.family=="linux") -+ * @modules java.base/jdk.internal.misc -+ * java.compiler -+ * java.management -+ * jdk.internal.jvmstat/sun.jvmstat.monitor -+ * @run testng MallocInfoTest -+ */ -+public class MallocInfoTest { -+ public void run(CommandExecutor executor) { -+ OutputAnalyzer output = executor.execute("System.native_heap_info"); -+ if (!Platform.isMusl()) { -+ output.shouldNotContain("Error: "); -+ output.shouldContain("(buf[i]); - if (card_ptr != NULL) { - // Set the entry to null, so we don't do it again (via the test - // above) if we reconsider this buffer. -- if (consume) buf[ind] = NULL; -- if (!cl->do_card_ptr(card_ptr, worker_i)) return false; -+ if (consume) { -+ buf[i] = NULL; -+ } -+ if (!cl->do_card_ptr(card_ptr, worker_i)) { -+ return false; -+ } - } - } - return true; -@@ -71,7 +89,7 @@ bool DirtyCardQueue::apply_closure_to_buffer(CardTableEntryClosure* cl, - DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : - PtrQueueSet(notify_when_complete), - _mut_process_closure(NULL), -- _shared_dirty_card_queue(this, true /*perm*/), -+ _shared_dirty_card_queue(this, true /* permanent */), - _free_ids(NULL), - _processed_buffers_mut(0), _processed_buffers_rs_thread(0) - { -@@ -83,13 +101,19 @@ uint DirtyCardQueueSet::num_par_ids() { - return (uint)os::initial_active_processor_count(); - } - --void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock, -+void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, -+ Monitor* cbl_mon, -+ Mutex* fl_lock, - int process_completed_threshold, - int max_completed_queue, -- Mutex* lock, PtrQueueSet* fl_owner) { -+ Mutex* lock, -+ DirtyCardQueueSet* fl_owner) { - _mut_process_closure = cl; -- PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, -- max_completed_queue, fl_owner); -+ PtrQueueSet::initialize(cbl_mon, -+ fl_lock, -+ process_completed_threshold, -+ max_completed_queue, -+ fl_owner); - set_buffer_size(G1UpdateBufferSize); - _shared_dirty_card_queue.set_lock(lock); - _free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon); -@@ -103,7 +127,7 @@ void DirtyCardQueueSet::iterate_closure_all_threads(CardTableEntryClosure* cl, - bool consume, - uint worker_i) { - assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint."); -- for(JavaThread* t = Threads::first(); t; t = t->next()) { -+ for (JavaThread* t = Threads::first(); t; t = t->next()) { - bool b = t->dirty_card_queue().apply_closure(cl, consume); - guarantee(b, "Should not be interrupted."); - } -@@ -160,8 +184,7 @@ bool DirtyCardQueueSet::mut_process_buffer(void** buf) { - } - - --BufferNode* --DirtyCardQueueSet::get_completed_buffer(int stop_at) { -+BufferNode* DirtyCardQueueSet::get_completed_buffer(int stop_at) { - BufferNode* nd = NULL; - MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); - -@@ -178,12 +201,11 @@ DirtyCardQueueSet::get_completed_buffer(int stop_at) { - _n_completed_buffers--; - assert(_n_completed_buffers >= 0, "Invariant"); - } -- debug_only(assert_completed_buffer_list_len_correct_locked()); -+ DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); - return nd; - } - --bool DirtyCardQueueSet:: --apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, -+bool DirtyCardQueueSet::apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, - uint worker_i, - BufferNode* nd) { - if (nd != NULL) { -@@ -259,7 +281,7 @@ void DirtyCardQueueSet::clear() { - } - _n_completed_buffers = 0; - _completed_buffers_tail = NULL; -- debug_only(assert_completed_buffer_list_len_correct_locked()); -+ DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); - } - while (buffers_to_delete != NULL) { - BufferNode* nd = buffers_to_delete; -@@ -291,10 +313,11 @@ void DirtyCardQueueSet::concatenate_logs() { - for (JavaThread* t = Threads::first(); t; t = t->next()) { - DirtyCardQueue& dcq = t->dirty_card_queue(); - if (dcq.size() != 0) { -- void **buf = t->dirty_card_queue().get_buf(); -+ void **buf = dcq.get_buf(); - // We must NULL out the unused entries, then enqueue. -- for (size_t i = 0; i < t->dirty_card_queue().get_index(); i += oopSize) { -- buf[PtrQueue::byte_index_to_index((int)i)] = NULL; -+ size_t limit = dcq.byte_index_to_index(dcq.get_index()); -+ for (size_t i = 0; i < limit; ++i) { -+ buf[i] = NULL; - } - enqueue_complete_buffer(dcq.get_buf(), dcq.get_index()); - dcq.reinitialize(); -diff --git a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp -index 986c0ea3c..250145937 100644 ---- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp -+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp -@@ -29,6 +29,7 @@ - #include "memory/allocation.hpp" - - class FreeIdSet; -+class DirtyCardQueueSet; - - // A closure class for processing card table entries. Note that we don't - // require these closure objects to be stack-allocated. -@@ -42,14 +43,11 @@ public: - // A ptrQueue whose elements are "oops", pointers to object heads. - class DirtyCardQueue: public PtrQueue { - public: -- DirtyCardQueue(PtrQueueSet* qset_, bool perm = false) : -- // Dirty card queues are always active, so we create them with their -- // active field set to true. -- PtrQueue(qset_, perm, true /* active */) { } -+ DirtyCardQueue(DirtyCardQueueSet* qset, bool permanent = false); - - // Flush before destroying; queue may be used to capture pending work while - // doing something else, with auto-flush on completion. -- ~DirtyCardQueue() { if (!is_permanent()) flush(); } -+ ~DirtyCardQueue(); - - // Process queue entries and release resources. - void flush() { flush_impl(); } -@@ -72,7 +70,6 @@ public: - bool consume = true, - uint worker_i = 0); - void **get_buf() { return _buf;} -- void set_buf(void **buf) {_buf = buf;} - size_t get_index() { return _index;} - void reinitialize() { _buf = 0; _sz = 0; _index = 0;} - }; -@@ -101,10 +98,13 @@ class DirtyCardQueueSet: public PtrQueueSet { - public: - DirtyCardQueueSet(bool notify_when_complete = true); - -- void initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock, -+ void initialize(CardTableEntryClosure* cl, -+ Monitor* cbl_mon, -+ Mutex* fl_lock, - int process_completed_threshold, - int max_completed_queue, -- Mutex* lock, PtrQueueSet* fl_owner = NULL); -+ Mutex* lock, -+ DirtyCardQueueSet* fl_owner = NULL); - - // The number of parallel ids that can be claimed to allow collector or - // mutator threads to do card-processing work. -diff --git a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp -index 2845d5186..c92b081c3 100644 ---- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp -+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp -@@ -30,24 +30,25 @@ - #include "runtime/mutexLocker.hpp" - #include "runtime/thread.inline.hpp" - --PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) : -+PtrQueue::PtrQueue(PtrQueueSet* qset, bool permanent, bool active) : - _qset(qset), _buf(NULL), _index(0), _sz(0), _active(active), -- _perm(perm), _lock(NULL) -+ _permanent(permanent), _lock(NULL) - {} - - PtrQueue::~PtrQueue() { -- assert(_perm || (_buf == NULL), "queue must be flushed before delete"); -+ assert(_permanent || (_buf == NULL), "queue must be flushed before delete"); - } - - void PtrQueue::flush_impl() { -- if (!_perm && _buf != NULL) { -+ if (!_permanent && _buf != NULL) { - if (_index == _sz) { - // No work to do. - qset()->deallocate_buffer(_buf); - } else { - // We must NULL out the unused entries, then enqueue. -- for (size_t i = 0; i < _index; i += oopSize) { -- _buf[byte_index_to_index((int)i)] = NULL; -+ size_t limit = byte_index_to_index(_index); -+ for (size_t i = 0; i < limit; ++i) { -+ _buf[i] = NULL; - } - qset()->enqueue_complete_buffer(_buf); - } -@@ -66,8 +67,8 @@ void PtrQueue::enqueue_known_active(void* ptr) { - } - - assert(_index > 0, "postcondition"); -- _index -= oopSize; -- _buf[byte_index_to_index((int)_index)] = ptr; -+ _index -= sizeof(void*); -+ _buf[byte_index_to_index(_index)] = ptr; - assert(0 <= _index && _index <= _sz, "Invariant."); - } - -@@ -100,6 +101,26 @@ PtrQueueSet::PtrQueueSet(bool notify_when_complete) : - _fl_owner = this; - } - -+PtrQueueSet::~PtrQueueSet() { -+ // There are presently only a couple (derived) instances ever -+ // created, and they are permanent, so no harm currently done by -+ // doing nothing here. -+} -+ -+void PtrQueueSet::initialize(Monitor* cbl_mon, -+ Mutex* fl_lock, -+ int process_completed_threshold, -+ int max_completed_queue, -+ PtrQueueSet *fl_owner) { -+ _max_completed_queue = max_completed_queue; -+ _process_completed_threshold = process_completed_threshold; -+ _completed_queue_padding = 0; -+ assert(cbl_mon != NULL && fl_lock != NULL, "Init order issue?"); -+ _cbl_mon = cbl_mon; -+ _fl_lock = fl_lock; -+ _fl_owner = (fl_owner != NULL) ? fl_owner : this; -+} -+ - void** PtrQueueSet::allocate_buffer() { - assert(_sz > 0, "Didn't set a buffer size."); - MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag); -@@ -234,7 +255,7 @@ void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) { - if (_notify_when_complete) - _cbl_mon->notify(); - } -- debug_only(assert_completed_buffer_list_len_correct_locked()); -+ DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); - } - - int PtrQueueSet::completed_buffers_list_length() { -@@ -259,7 +280,7 @@ void PtrQueueSet::assert_completed_buffer_list_len_correct_locked() { - - void PtrQueueSet::set_buffer_size(size_t sz) { - assert(_sz == 0 && sz > 0, "Should be called only once."); -- _sz = sz * oopSize; -+ _sz = sz * sizeof(void*); - } - - // Merge lists of buffers. Notify the processing threads. -diff --git a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp -index 27404f0a9..9c969b2ad 100644 ---- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp -+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp -@@ -40,44 +40,49 @@ class PtrQueueSet; - class PtrQueue VALUE_OBJ_CLASS_SPEC { - friend class VMStructs; - --protected: -+ // Noncopyable - not defined. -+ PtrQueue(const PtrQueue&); -+ PtrQueue& operator=(const PtrQueue&); -+ - // The ptr queue set to which this queue belongs. -- PtrQueueSet* _qset; -+ PtrQueueSet* const _qset; - - // Whether updates should be logged. - bool _active; - -+ // If true, the queue is permanent, and doesn't need to deallocate -+ // its buffer in the destructor (since that obtains a lock which may not -+ // be legally locked by then. -+ const bool _permanent; -+ -+protected: - // The buffer. - void** _buf; -- // The index at which an object was last enqueued. Starts at "_sz" -+ // The (byte) index at which an object was last enqueued. Starts at "_sz" - // (indicating an empty buffer) and goes towards zero. - size_t _index; - -- // The size of the buffer. -+ // The (byte) size of the buffer. - size_t _sz; - -- // If true, the queue is permanent, and doesn't need to deallocate -- // its buffer in the destructor (since that obtains a lock which may not -- // be legally locked by then. -- bool _perm; -- - // If there is a lock associated with this buffer, this is that lock. - Mutex* _lock; - - PtrQueueSet* qset() { return _qset; } -- bool is_permanent() const { return _perm; } -+ bool is_permanent() const { return _permanent; } - - // Process queue entries and release resources, if not permanent. - void flush_impl(); - --public: - // Initialize this queue to contain a null buffer, and be part of the - // given PtrQueueSet. -- PtrQueue(PtrQueueSet* qset, bool perm = false, bool active = false); -+ PtrQueue(PtrQueueSet* qset, bool permanent = false, bool active = false); - - // Requires queue flushed or permanent. - ~PtrQueue(); - -+public: -+ - // Associate a lock with a ptr queue. - void set_lock(Mutex* lock) { _lock = lock; } - -@@ -129,13 +134,9 @@ public: - - bool is_active() { return _active; } - -- static int byte_index_to_index(int ind) { -- assert((ind % oopSize) == 0, "Invariant."); -- return ind / oopSize; -- } -- -- static int index_to_byte_index(int byte_ind) { -- return byte_ind * oopSize; -+ static size_t byte_index_to_index(size_t ind) { -+ assert((ind % sizeof(void*)) == 0, "Invariant."); -+ return ind / sizeof(void*); - } - - // To support compiler. -@@ -246,26 +247,21 @@ protected: - return false; - } - --public: - // Create an empty ptr queue set. - PtrQueueSet(bool notify_when_complete = false); -+ ~PtrQueueSet(); - - // Because of init-order concerns, we can't pass these as constructor - // arguments. -- void initialize(Monitor* cbl_mon, Mutex* fl_lock, -+ void initialize(Monitor* cbl_mon, -+ Mutex* fl_lock, - int process_completed_threshold, - int max_completed_queue, -- PtrQueueSet *fl_owner = NULL) { -- _max_completed_queue = max_completed_queue; -- _process_completed_threshold = process_completed_threshold; -- _completed_queue_padding = 0; -- assert(cbl_mon != NULL && fl_lock != NULL, "Init order issue?"); -- _cbl_mon = cbl_mon; -- _fl_lock = fl_lock; -- _fl_owner = (fl_owner != NULL) ? fl_owner : this; -- } -+ PtrQueueSet *fl_owner = NULL); -+ -+public: - -- // Return an empty oop array of size _sz (required to be non-zero). -+ // Return an empty array of size _sz (required to be non-zero). - void** allocate_buffer(); - - // Return an empty buffer to the free list. The "buf" argument is -diff --git a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp -index d423c69ac..8c70b6795 100644 ---- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp -+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp -@@ -35,6 +35,15 @@ - - PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC - -+ObjPtrQueue::ObjPtrQueue(SATBMarkQueueSet* qset, bool permanent) : -+ // SATB queues are only active during marking cycles. We create -+ // them with their active field set to false. If a thread is -+ // created during a cycle and its SATB queue needs to be activated -+ // before the thread starts running, we'll need to set its active -+ // field to true. This is done in JavaThread::initialize_queues(). -+ PtrQueue(qset, permanent, false /* active */) -+{ } -+ - void ObjPtrQueue::flush() { - // Filter now to possibly save work later. If filtering empties the - // buffer then flush_impl can deallocate the buffer. -@@ -101,7 +110,6 @@ inline bool requires_marking(const void* entry, G1CollectedHeap* heap) { - void ObjPtrQueue::filter() { - G1CollectedHeap* g1h = G1CollectedHeap::heap(); - void** buf = _buf; -- size_t sz = _sz; - - if (buf == NULL) { - // nothing to do -@@ -109,43 +117,37 @@ void ObjPtrQueue::filter() { - } - - // Used for sanity checking at the end of the loop. -- debug_only(size_t entries = 0; size_t retained = 0;) -+ DEBUG_ONLY(size_t entries = 0; size_t retained = 0;) - -- size_t i = sz; -- size_t new_index = sz; -+ assert(_index <= _sz, "invariant"); -+ void** limit = &buf[byte_index_to_index(_index)]; -+ void** src = &buf[byte_index_to_index(_sz)]; -+ void** dst = src; - -- while (i > _index) { -- assert(i > 0, "we should have at least one more entry to process"); -- i -= oopSize; -- debug_only(entries += 1;) -- void** p = &buf[byte_index_to_index((int) i)]; -- void* entry = *p; -+ while (limit < src) { -+ DEBUG_ONLY(entries += 1;) -+ --src; -+ void* entry = *src; - // NULL the entry so that unused parts of the buffer contain NULLs - // at the end. If we are going to retain it we will copy it to its - // final place. If we have retained all entries we have visited so - // far, we'll just end up copying it to the same place. -- *p = NULL; -+ *src = NULL; - - if (requires_marking(entry, g1h) && !g1h->isMarkedNext((oop)entry)) { -- assert(new_index > 0, "we should not have already filled up the buffer"); -- new_index -= oopSize; -- assert(new_index >= i, -- "new_index should never be below i, as we alwaysr compact 'up'"); -- void** new_p = &buf[byte_index_to_index((int) new_index)]; -- assert(new_p >= p, "the destination location should never be below " -- "the source as we always compact 'up'"); -- assert(*new_p == NULL, -- "we should have already cleared the destination location"); -- *new_p = entry; -- debug_only(retained += 1;) -+ --dst; -+ assert(*dst == NULL, "filtering destination should be clear"); -+ *dst = entry; -+ DEBUG_ONLY(retained += 1;); - } - } -+ size_t new_index = pointer_delta(dst, buf, 1); - - #ifdef ASSERT -- size_t entries_calc = (sz - _index) / oopSize; -+ size_t entries_calc = (_sz - _index) / sizeof(void*); - assert(entries == entries_calc, "the number of entries we counted " - "should match the number of entries we calculated"); -- size_t retained_calc = (sz - new_index) / oopSize; -+ size_t retained_calc = (_sz - new_index) / sizeof(void*); - assert(retained == retained_calc, "the number of retained entries we counted " - "should match the number of retained entries we calculated"); - #endif // ASSERT -@@ -172,11 +174,8 @@ bool ObjPtrQueue::should_enqueue_buffer() { - - filter(); - -- size_t sz = _sz; -- size_t all_entries = sz / oopSize; -- size_t retained_entries = (sz - _index) / oopSize; -- size_t perc = retained_entries * 100 / all_entries; -- bool should_enqueue = perc > (size_t) G1SATBBufferEnqueueingThresholdPercent; -+ size_t percent_used = ((_sz - _index) * 100) / _sz; -+ bool should_enqueue = percent_used > G1SATBBufferEnqueueingThresholdPercent; - return should_enqueue; - } - -@@ -187,8 +186,8 @@ void ObjPtrQueue::apply_closure_and_empty(SATBBufferClosure* cl) { - assert(_index % sizeof(void*) == 0, "invariant"); - assert(_sz % sizeof(void*) == 0, "invariant"); - assert(_index <= _sz, "invariant"); -- cl->do_buffer(_buf + byte_index_to_index((int)_index), -- byte_index_to_index((int)(_sz - _index))); -+ cl->do_buffer(_buf + byte_index_to_index(_index), -+ byte_index_to_index(_sz - _index)); - _index = _sz; - } - } -@@ -214,7 +213,7 @@ void ObjPtrQueue::print(const char* name, - - SATBMarkQueueSet::SATBMarkQueueSet() : - PtrQueueSet(), -- _shared_satb_queue(this, true /*perm*/) { } -+ _shared_satb_queue(this, true /* permanent */) { } - - void SATBMarkQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock, - int process_completed_threshold, -@@ -301,7 +300,7 @@ bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) - // Filtering can result in non-full completed buffers; see - // should_enqueue_buffer. - assert(_sz % sizeof(void*) == 0, "invariant"); -- size_t limit = ObjPtrQueue::byte_index_to_index((int)_sz); -+ size_t limit = ObjPtrQueue::byte_index_to_index(_sz); - for (size_t i = 0; i < limit; ++i) { - if (buf[i] != NULL) { - // Found the end of the block of NULLs; process the remainder. -diff --git a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp -index 594895919..6651210a3 100644 ---- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp -+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp -@@ -50,13 +50,7 @@ private: - void filter(); - - public: -- ObjPtrQueue(PtrQueueSet* qset, bool perm = false) : -- // SATB queues are only active during marking cycles. We create -- // them with their active field set to false. If a thread is -- // created during a cycle and its SATB queue needs to be activated -- // before the thread starts running, we'll need to set its active -- // field to true. This is done in JavaThread::initialize_queues(). -- PtrQueue(qset, perm, false /* active */) { } -+ ObjPtrQueue(SATBMarkQueueSet* qset, bool permanent = false); - - // Process queue entries and free resources. - void flush(); -diff --git a/hotspot/test/gc/g1/TestPtrQueueSize.java b/hotspot/test/gc/g1/TestPtrQueueSize.java -new file mode 100644 -index 000000000..f46c95bec ---- /dev/null -+++ b/hotspot/test/gc/g1/TestPtrQueueSize.java -@@ -0,0 +1,58 @@ -+/* -+ * Copyright (c) 2023, 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 TestPtrQueueSize.java -+* @key gc -+* @bug 6899049 -+* @summary Test size of PtrQueue; used by dirtyCardQueue and satbQueue -+* @library /testlibrary -+*/ -+ -+import com.oracle.java.testlibrary.ProcessTools; -+import com.oracle.java.testlibrary.OutputAnalyzer; -+ -+ public class TestPtrQueueSize { -+ public static void main(String[] args) throws Exception { -+ -+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", -+ "-XX:G1SATBBufferSize=716M", -+ "-Xms1024m", -+ "-Xmx4096m", -+ SystemGCTest.class.getName()); -+ -+ OutputAnalyzer output = new OutputAnalyzer(pb.start()); -+ -+ System.out.println("Output:\n" + output.getOutput()); -+ -+ output.shouldHaveExitValue(0); -+ } -+ -+ static class SystemGCTest { -+ public static void main(String [] args) { -+ for (int i = 0; i < 500; ++i) { -+ byte[] bArray = new byte[1024*1024]; -+ } -+ } -+ } -+ } -\ No newline at end of file --- -2.22.0 - diff --git a/add-8142508-To-bring-j.u.z.ZipFile-s-native-implemen.patch b/add-8142508-To-bring-j.u.z.ZipFile-s-native-implemen.patch deleted file mode 100644 index 0bbe9545dbc69f5013cbda3bb804e2f7c96875bd..0000000000000000000000000000000000000000 --- a/add-8142508-To-bring-j.u.z.ZipFile-s-native-implemen.patch +++ /dev/null @@ -1,2911 +0,0 @@ -From 7590fffae62f5a4157ab7612c186b442c81d5682 Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:15:39 +0800 -Subject: add 8142508-To-bring-j.u.z.ZipFile-s-native-implementati - ---- - jdk/make/mapfiles/libzip/mapfile-vers | 23 +- - jdk/make/mapfiles/libzip/reorder-sparc | 17 - - jdk/make/mapfiles/libzip/reorder-sparcv9 | 16 - - jdk/make/mapfiles/libzip/reorder-x86 | 19 - - .../share/classes/java/util/jar/JarFile.java | 5 +- - .../share/classes/java/util/zip/ZipCoder.java | 21 +- - .../share/classes/java/util/zip/ZipFile.java | 933 ++++++++++++++---- - .../share/classes/java/util/zip/ZipUtils.java | 79 +- - .../sun/misc/JavaUtilZipFileAccess.java | 1 + - jdk/src/share/classes/sun/misc/VM.java | 3 - - jdk/src/share/native/java/util/zip/ZipFile.c | 403 -------- - jdk/src/share/native/java/util/zip/zip_util.c | 29 +- - jdk/src/share/native/java/util/zip/zip_util.h | 1 - - jdk/test/java/nio/file/spi/TestProvider.java | 274 ++++- - .../java/util/zip/ZipFile/TestZipFile.java | 375 +++++++ - .../imageio/plugins/png/ItxtUtf8Test.java | 2 +- - 16 files changed, 1440 insertions(+), 761 deletions(-) - delete mode 100644 jdk/src/share/native/java/util/zip/ZipFile.c - create mode 100644 jdk/test/java/util/zip/ZipFile/TestZipFile.java - -diff --git a/jdk/make/mapfiles/libzip/mapfile-vers b/jdk/make/mapfiles/libzip/mapfile-vers -index 5d33990c3..e7394ae61 100644 ---- a/jdk/make/mapfiles/libzip/mapfile-vers -+++ b/jdk/make/mapfiles/libzip/mapfile-vers -@@ -1,5 +1,5 @@ - # --# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. -+# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. - # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - # - # This code is free software; you can redistribute it and/or modify it -@@ -27,7 +27,6 @@ - - SUNWprivate_1.1 { - global: -- Java_java_util_jar_JarFile_getMetaInfEntryNames; - Java_java_util_zip_Adler32_update; - Java_java_util_zip_Adler32_updateBytes; - Java_java_util_zip_Adler32_updateByteBuffer; -@@ -48,26 +47,6 @@ SUNWprivate_1.1 { - Java_java_util_zip_Inflater_initIDs; - Java_java_util_zip_Inflater_reset; - Java_java_util_zip_Inflater_setDictionary; -- Java_java_util_zip_ZipFile_close; -- Java_java_util_zip_ZipFile_getCommentBytes; -- Java_java_util_zip_ZipFile_freeEntry; -- Java_java_util_zip_ZipFile_getEntry; -- Java_java_util_zip_ZipFile_getEntryBytes; -- Java_java_util_zip_ZipFile_getEntryCrc; -- Java_java_util_zip_ZipFile_getEntryCSize; -- Java_java_util_zip_ZipFile_getEntryFlag; -- Java_java_util_zip_ZipFile_getEntryMethod; -- Java_java_util_zip_ZipFile_getEntrySize; -- Java_java_util_zip_ZipFile_getEntryTime; -- Java_java_util_zip_ZipFile_getNextEntry; -- Java_java_util_zip_ZipFile_getZipMessage; -- Java_java_util_zip_ZipFile_getTotal; -- Java_java_util_zip_ZipFile_initIDs; -- Java_java_util_zip_ZipFile_open; -- Java_java_util_zip_ZipFile_read; -- Java_java_util_zip_ZipFile_startsWithLOC; -- Java_java_util_zip_ZipFile_getManifestNum; -- - ZIP_Close; - ZIP_CRC32; - ZIP_FindEntry; -diff --git a/jdk/make/mapfiles/libzip/reorder-sparc b/jdk/make/mapfiles/libzip/reorder-sparc -index 9d3aae88e..b1957dce7 100644 ---- a/jdk/make/mapfiles/libzip/reorder-sparc -+++ b/jdk/make/mapfiles/libzip/reorder-sparc -@@ -15,31 +15,14 @@ text: .text%ZIP_GetEntry; - text: .text%ZIP_Lock; - text: .text%ZIP_Unlock; - text: .text%ZIP_FreeEntry; --text: .text%Java_java_util_zip_ZipFile_initIDs; --text: .text%Java_java_util_zip_ZipFile_open; --text: .text%Java_java_util_zip_ZipFile_getTotal; --text: .text%Java_java_util_zip_ZipFile_startsWithLOC; --text: .text%Java_java_util_zip_ZipFile_getManifestNum; --text: .text%Java_java_util_zip_ZipFile_getEntry; --text: .text%Java_java_util_zip_ZipFile_freeEntry; --text: .text%Java_java_util_zip_ZipFile_getEntryTime; --text: .text%Java_java_util_zip_ZipFile_getEntryCrc; --text: .text%Java_java_util_zip_ZipFile_getEntryCSize; --text: .text%Java_java_util_zip_ZipFile_getEntrySize; --text: .text%Java_java_util_zip_ZipFile_getEntryFlag; --text: .text%Java_java_util_zip_ZipFile_getEntryMethod; --text: .text%Java_java_util_zip_ZipFile_getEntryBytes; - text: .text%Java_java_util_zip_Inflater_initIDs; - text: .text%Java_java_util_zip_Inflater_init; - text: .text%inflateInit2_; - text: .text%zcalloc; - text: .text%Java_java_util_zip_Inflater_inflateBytes; --text: .text%Java_java_util_zip_ZipFile_read; - text: .text%ZIP_Read; - text: .text%zcfree; --text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames; - text: .text%Java_java_util_zip_Inflater_reset; - text: .text%Java_java_util_zip_Inflater_end; - text: .text%inflateEnd; --text: .text%Java_java_util_zip_ZipFile_close; - text: .text%ZIP_Close; -diff --git a/jdk/make/mapfiles/libzip/reorder-sparcv9 b/jdk/make/mapfiles/libzip/reorder-sparcv9 -index bf127e9cf..458d4c34f 100644 ---- a/jdk/make/mapfiles/libzip/reorder-sparcv9 -+++ b/jdk/make/mapfiles/libzip/reorder-sparcv9 -@@ -15,20 +15,6 @@ text: .text%ZIP_Lock; - text: .text%readLOC: OUTPUTDIR/zip_util.o; - text: .text%ZIP_Unlock; - text: .text%ZIP_FreeEntry; --text: .text%Java_java_util_zip_ZipFile_initIDs; --text: .text%Java_java_util_zip_ZipFile_open; --text: .text%Java_java_util_zip_ZipFile_getTotal; --text: .text%Java_java_util_zip_ZipFile_startsWithLOC; --text: .text%Java_java_util_zip_ZipFile_getManifestNum; --text: .text%Java_java_util_zip_ZipFile_getEntry; --text: .text%Java_java_util_zip_ZipFile_freeEntry; --text: .text%Java_java_util_zip_ZipFile_getEntryTime; --text: .text%Java_java_util_zip_ZipFile_getEntryCrc; --text: .text%Java_java_util_zip_ZipFile_getEntryCSize; --text: .text%Java_java_util_zip_ZipFile_getEntrySize; --text: .text%Java_java_util_zip_ZipFile_getEntryFlag; --text: .text%Java_java_util_zip_ZipFile_getEntryMethod; --text: .text%Java_java_util_zip_ZipFile_getEntryBytes; - text: .text%Java_java_util_zip_Inflater_initIDs; - text: .text%Java_java_util_zip_Inflater_init; - text: .text%inflateInit2_; -@@ -36,7 +22,6 @@ text: .text%zcalloc; - text: .text%inflateReset; - text: .text%Java_java_util_zip_Inflater_inflateBytes; - text: .text%inflate; --text: .text%Java_java_util_zip_ZipFile_read; - text: .text%ZIP_Read; - text: .text%huft_build: OUTPUTDIR/inftrees.o; - text: .text%zcfree; -@@ -45,6 +30,5 @@ text: .text%ZIP_ReadEntry; - text: .text%InflateFully; - text: .text%inflateEnd; - text: .text%Java_java_util_zip_Inflater_reset; --text: .text%Java_java_util_zip_ZipFile_close; - text: .text%ZIP_Close; - text: .text%Java_java_util_zip_Inflater_end; -diff --git a/jdk/make/mapfiles/libzip/reorder-x86 b/jdk/make/mapfiles/libzip/reorder-x86 -index d4e84c38c..62f11a990 100644 ---- a/jdk/make/mapfiles/libzip/reorder-x86 -+++ b/jdk/make/mapfiles/libzip/reorder-x86 -@@ -16,36 +16,17 @@ text: .text%ZIP_Lock; - text: .text%readLOC: OUTPUTDIR/zip_util.o; - text: .text%ZIP_Unlock; - text: .text%ZIP_FreeEntry; --text: .text%Java_java_util_zip_ZipFile_initIDs; --text: .text%Java_java_util_zip_ZipFile_open; --text: .text%Java_java_util_zip_ZipFile_getTotal; --text: .text%Java_java_util_zip_ZipFile_startsWithLOC; --text: .text%Java_java_util_zip_ZipFile_getManifestNum; --text: .text%Java_java_util_zip_ZipFile_getEntry; --text: .text%Java_java_util_zip_ZipFile_freeEntry; --text: .text%Java_java_util_zip_ZipFile_getEntryTime; --text: .text%Java_java_util_zip_ZipFile_getEntryCrc; --text: .text%Java_java_util_zip_ZipFile_getEntryCSize; --text: .text%Java_java_util_zip_ZipFile_getEntrySize; --text: .text%Java_java_util_zip_ZipFile_getEntryFlag; --text: .text%Java_java_util_zip_ZipFile_getEntryMethod; --text: .text%Java_java_util_zip_ZipFile_getEntryBytes; --text: .text%Java_java_util_zip_Inflater_initIDs; --text: .text%Java_java_util_zip_Inflater_init; - text: .text%inflateInit2_; - text: .text%zcalloc; - text: .text%inflateReset; - text: .text%Java_java_util_zip_Inflater_inflateBytes; - text: .text%inflate; --text: .text%Java_java_util_zip_ZipFile_read; - text: .text%ZIP_Read; - text: .text%huft_build: OUTPUTDIR/inftrees.o; - text: .text%zcfree; --text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames; - text: .text%ZIP_ReadEntry; - text: .text%InflateFully; - text: .text%inflateEnd; - text: .text%Java_java_util_zip_Inflater_reset; --text: .text%Java_java_util_zip_ZipFile_close; - text: .text%ZIP_Close; - text: .text%Java_java_util_zip_Inflater_end; -diff --git a/jdk/src/share/classes/java/util/jar/JarFile.java b/jdk/src/share/classes/java/util/jar/JarFile.java -index a26dcc4a1..2878e175e 100644 ---- a/jdk/src/share/classes/java/util/jar/JarFile.java -+++ b/jdk/src/share/classes/java/util/jar/JarFile.java -@@ -213,7 +213,10 @@ class JarFile extends ZipFile { - return man; - } - -- private native String[] getMetaInfEntryNames(); -+ private String[] getMetaInfEntryNames() { -+ return sun.misc.SharedSecrets.getJavaUtilZipFileAccess() -+ .getMetaInfEntryNames((ZipFile)this); -+ } - - /** - * Returns the JarEntry for the given entry name or -diff --git a/jdk/src/share/classes/java/util/zip/ZipCoder.java b/jdk/src/share/classes/java/util/zip/ZipCoder.java -index b920b820e..243d6e8c0 100644 ---- a/jdk/src/share/classes/java/util/zip/ZipCoder.java -+++ b/jdk/src/share/classes/java/util/zip/ZipCoder.java -@@ -43,7 +43,7 @@ import sun.nio.cs.ArrayEncoder; - - final class ZipCoder { - -- String toString(byte[] ba, int length) { -+ String toString(byte[] ba, int off, int length) { - CharsetDecoder cd = decoder().reset(); - int len = (int)(length * cd.maxCharsPerByte()); - char[] ca = new char[len]; -@@ -53,12 +53,12 @@ final class ZipCoder { - // CodingErrorAction.REPLACE mode. ZipCoder uses - // REPORT mode. - if (isUTF8 && cd instanceof ArrayDecoder) { -- int clen = ((ArrayDecoder)cd).decode(ba, 0, length, ca); -+ int clen = ((ArrayDecoder)cd).decode(ba, off, length, ca); - if (clen == -1) // malformed - throw new IllegalArgumentException("MALFORMED"); - return new String(ca, 0, clen); - } -- ByteBuffer bb = ByteBuffer.wrap(ba, 0, length); -+ ByteBuffer bb = ByteBuffer.wrap(ba, off, length); - CharBuffer cb = CharBuffer.wrap(ca); - CoderResult cr = cd.decode(bb, cb, true); - if (!cr.isUnderflow()) -@@ -69,8 +69,12 @@ final class ZipCoder { - return new String(ca, 0, cb.position()); - } - -+ String toString(byte[] ba, int length) { -+ return toString(ba, 0, length); -+ } -+ - String toString(byte[] ba) { -- return toString(ba, ba.length); -+ return toString(ba, 0, ba.length); - } - - byte[] getBytes(String s) { -@@ -111,13 +115,16 @@ final class ZipCoder { - return utf8.getBytes(s); - } - -- - String toStringUTF8(byte[] ba, int len) { -+ return toStringUTF8(ba, 0, len); -+ } -+ -+ String toStringUTF8(byte[] ba, int off, int len) { - if (isUTF8) -- return toString(ba, len); -+ return toString(ba, off, len); - if (utf8 == null) - utf8 = new ZipCoder(StandardCharsets.UTF_8); -- return utf8.toString(ba, len); -+ return utf8.toString(ba, off, len); - } - - boolean isUTF8() { -diff --git a/jdk/src/share/classes/java/util/zip/ZipFile.java b/jdk/src/share/classes/java/util/zip/ZipFile.java -index 9f8aff6ef..5d9b0de97 100644 ---- a/jdk/src/share/classes/java/util/zip/ZipFile.java -+++ b/jdk/src/share/classes/java/util/zip/ZipFile.java -@@ -30,14 +30,24 @@ import java.io.InputStream; - import java.io.IOException; - import java.io.EOFException; - import java.io.File; -+import java.io.FileNotFoundException; -+import java.io.RandomAccessFile; - import java.nio.charset.Charset; - import java.nio.charset.StandardCharsets; -+import java.nio.file.attribute.BasicFileAttributes; -+import java.nio.file.Path; -+import java.nio.file.Files; -+import java.nio.file.NoSuchFileException; -+ - import java.util.ArrayDeque; -+import java.util.ArrayList; -+import java.util.Arrays; - import java.util.Deque; - import java.util.Enumeration; - import java.util.HashMap; - import java.util.Iterator; - import java.util.Map; -+import java.util.Objects; - import java.util.NoSuchElementException; - import java.util.Spliterator; - import java.util.Spliterators; -@@ -46,7 +56,9 @@ import java.util.jar.JarFile; - import java.util.stream.Stream; - import java.util.stream.StreamSupport; - -+import static java.util.zip.ZipConstants.*; - import static java.util.zip.ZipConstants64.*; -+import static java.util.zip.ZipUtils.*; - - /** - * This class is used to read entries from a zip file. -@@ -59,12 +71,11 @@ import static java.util.zip.ZipConstants64.*; - */ - public - class ZipFile implements ZipConstants, Closeable { -- private long jzfile; // address of jzfile data -+ - private final String name; // zip file name -- private final int total; // total number of entries -- private final boolean locsig; // if zip file starts with LOCSIG (usually true) - private volatile boolean closeRequested = false; -- private int manifestNum = 0; // number of META-INF/MANIFEST.MF, case insensitive -+ private Source zsrc; -+ private ZipCoder zc; - - private static final int STORED = ZipEntry.STORED; - private static final int DEFLATED = ZipEntry.DEFLATED; -@@ -83,26 +94,11 @@ class ZipFile implements ZipConstants, Closeable { - */ - public static final int OPEN_DELETE = 0x4; - -- static { -- /* Zip library is loaded from System.initializeSystemClass */ -- initIDs(); -- } -- -- private static native void initIDs(); -- -- private static final boolean usemmap; -- - private static final boolean ensuretrailingslash; - - static { -- // A system prpperty to disable mmap use to avoid vm crash when -- // in-use zip file is accidently overwritten by others. -- String prop = sun.misc.VM.getSavedProperty("sun.zip.disableMemoryMapping"); -- usemmap = (prop == null || -- !(prop.length() == 0 || prop.equalsIgnoreCase("true"))); -- - // see getEntry() for details -- prop = sun.misc.VM.getSavedProperty("jdk.util.zip.ensureTrailingSlash"); -+ String prop = sun.misc.VM.getSavedProperty("jdk.util.zip.ensureTrailingSlash"); - ensuretrailingslash = prop == null || !prop.equalsIgnoreCase("false"); - } - -@@ -171,8 +167,6 @@ class ZipFile implements ZipConstants, Closeable { - this(file, OPEN_READ); - } - -- private ZipCoder zc; -- - /** - * Opens a new ZipFile to read from the specified - * File object in the specified mode. The mode argument -@@ -224,17 +218,13 @@ class ZipFile implements ZipConstants, Closeable { - sm.checkDelete(name); - } - } -- if (charset == null) -- throw new NullPointerException("charset is null"); -+ Objects.requireNonNull(charset, "charset"); - this.zc = ZipCoder.get(charset); -+ this.name = name; - long t0 = System.nanoTime(); -- jzfile = open(name, mode, file.lastModified(), usemmap); -+ this.zsrc = Source.get(file, (mode & OPEN_DELETE) != 0); - sun.misc.PerfCounter.getZipFileOpenTime().addElapsedTimeFrom(t0); - sun.misc.PerfCounter.getZipFileCount().increment(); -- this.name = name; -- this.total = getTotal(jzfile); -- this.locsig = startsWithLOC(jzfile); -- this.manifestNum = getManifestNum(jzfile); - } - - /** -@@ -268,6 +258,7 @@ class ZipFile implements ZipConstants, Closeable { - - /** - * Opens a ZIP file for reading given the specified File object. -+ * - * @param file the ZIP file to be opened for reading - * @param charset - * The {@linkplain java.nio.charset.Charset charset} to be -@@ -298,10 +289,10 @@ class ZipFile implements ZipConstants, Closeable { - public String getComment() { - synchronized (this) { - ensureOpen(); -- byte[] bcomm = getCommentBytes(jzfile); -- if (bcomm == null) -+ if (zsrc.comment == null) { - return null; -- return zc.toString(bcomm, bcomm.length); -+ } -+ return zc.toString(zsrc.comment); - } - } - -@@ -314,47 +305,29 @@ class ZipFile implements ZipConstants, Closeable { - * @throws IllegalStateException if the zip file has been closed - */ - public ZipEntry getEntry(String name) { -- if (name == null) { -- throw new NullPointerException("name"); -- } -- long jzentry = 0; -+ -+ Objects.requireNonNull(name, "name"); - synchronized (this) { - ensureOpen(); -- jzentry = getEntry(jzfile, zc.getBytes(name), true); -- if (jzentry != 0) { -- // If no entry is found for the specified 'name' and -- // the 'name' does not end with a forward slash '/', -- // the implementation tries to find the entry with a -- // slash '/' appended to the end of the 'name', before -- // returning null. When such entry is found, the name -- // that actually is found (with a slash '/' attached) -- // is used -- // (disabled if jdk.util.zip.ensureTrailingSlash=false) -- ZipEntry ze = ensuretrailingslash ? getZipEntry(null, jzentry) -- : getZipEntry(name, jzentry); -- freeEntry(jzfile, jzentry); -- return ze; -+ int pos = zsrc.getEntryPos(zc.getBytes(name), true); -+ if (pos != -1) { -+ return ensuretrailingslash ? getZipEntry(null, pos) -+ : getZipEntry(name, pos); - } - } - return null; - } - -- private static native long getEntry(long jzfile, byte[] name, -- boolean addSlash); -- -- // freeEntry releases the C jzentry struct. -- private static native void freeEntry(long jzfile, long jzentry); -- -- // the outstanding inputstreams that need to be closed, -+ // The outstanding inputstreams that need to be closed, - // mapped to the inflater objects they use. - private final Map streams = new WeakHashMap<>(); - - /** - * Returns an input stream for reading the contents of the specified - * zip file entry. -- * -- *

Closing this ZIP file will, in turn, close all input -- * streams that have been returned by invocations of this method. -+ *

-+ * Closing this ZIP file will, in turn, close all input streams that -+ * have been returned by invocations of this method. - * - * @param entry the zip file entry - * @return the input stream for reading the contents of the specified -@@ -364,37 +337,38 @@ class ZipFile implements ZipConstants, Closeable { - * @throws IllegalStateException if the zip file has been closed - */ - public InputStream getInputStream(ZipEntry entry) throws IOException { -- if (entry == null) { -- throw new NullPointerException("entry"); -- } -- long jzentry = 0; -+ Objects.requireNonNull(entry, "entry"); -+ int pos = -1; - ZipFileInputStream in = null; - synchronized (this) { - ensureOpen(); - if (!zc.isUTF8() && (entry.flag & EFS) != 0) { -- jzentry = getEntry(jzfile, zc.getBytesUTF8(entry.name), false); -+ pos = zsrc.getEntryPos(zc.getBytesUTF8(entry.name), false); - } else { -- jzentry = getEntry(jzfile, zc.getBytes(entry.name), false); -+ pos = zsrc.getEntryPos(zc.getBytes(entry.name), false); - } -- if (jzentry == 0) { -+ if (pos == -1) { - return null; - } -- in = new ZipFileInputStream(jzentry); -- -- switch (getEntryMethod(jzentry)) { -+ in = new ZipFileInputStream(zsrc.cen, pos); -+ switch (CENHOW(zsrc.cen, pos)) { - case STORED: - synchronized (streams) { - streams.put(in, null); - } - return in; - case DEFLATED: -+ // Inflater likes a bit of slack - // MORE: Compute good size for inflater stream: -- long size = getEntrySize(jzentry) + 2; // Inflater likes a bit of slack -- if (size > 65536) size = 8192; -- if (size <= 0) size = 4096; -+ long size = CENLEN(zsrc.cen, pos) + 2; -+ if (size > 65536) { -+ size = 8192; -+ } -+ if (size <= 0) { -+ size = 4096; -+ } - Inflater inf = getInflater(); -- InputStream is = -- new ZipFileInflaterInputStream(in, inf, (int)size); -+ InputStream is = new ZipFileInflaterInputStream(in, inf, (int)size); - synchronized (streams) { - streams.put(is, inf); - } -@@ -467,8 +441,8 @@ class ZipFile implements ZipConstants, Closeable { - private Inflater getInflater() { - Inflater inf; - synchronized (inflaterCache) { -- while (null != (inf = inflaterCache.poll())) { -- if (false == inf.ended()) { -+ while ((inf = inflaterCache.poll()) != null) { -+ if (!inf.ended()) { - return inf; - } - } -@@ -480,7 +454,7 @@ class ZipFile implements ZipConstants, Closeable { - * Releases the specified inflater to the list of available inflaters. - */ - private void releaseInflater(Inflater inf) { -- if (false == inf.ended()) { -+ if (!inf.ended()) { - inf.reset(); - synchronized (inflaterCache) { - inflaterCache.add(inf); -@@ -489,7 +463,7 @@ class ZipFile implements ZipConstants, Closeable { - } - - // List of available Inflater objects for decompression -- private Deque inflaterCache = new ArrayDeque<>(); -+ private final Deque inflaterCache = new ArrayDeque<>(); - - /** - * Returns the path name of the ZIP file. -@@ -501,9 +475,13 @@ class ZipFile implements ZipConstants, Closeable { - - private class ZipEntryIterator implements Enumeration, Iterator { - private int i = 0; -+ private final int entryCount; - - public ZipEntryIterator() { -- ensureOpen(); -+ synchronized (ZipFile.this) { -+ ensureOpen(); -+ this.entryCount = zsrc.total; -+ } - } - - public boolean hasMoreElements() { -@@ -511,10 +489,7 @@ class ZipFile implements ZipConstants, Closeable { - } - - public boolean hasNext() { -- synchronized (ZipFile.this) { -- ensureOpen(); -- return i < total; -- } -+ return i < entryCount; - } - - public ZipEntry nextElement() { -@@ -524,28 +499,11 @@ class ZipFile implements ZipConstants, Closeable { - public ZipEntry next() { - synchronized (ZipFile.this) { - ensureOpen(); -- if (i >= total) { -+ if (!hasNext()) { - throw new NoSuchElementException(); - } -- long jzentry = getNextEntry(jzfile, i++); -- if (jzentry == 0) { -- String message; -- if (closeRequested) { -- message = "ZipFile concurrently closed"; -- } else { -- message = getZipMessage(ZipFile.this.jzfile); -- } -- throw new ZipError("jzentry == 0" + -- ",\n jzfile = " + ZipFile.this.jzfile + -- ",\n total = " + ZipFile.this.total + -- ",\n name = " + ZipFile.this.name + -- ",\n i = " + i + -- ",\n message = " + message -- ); -- } -- ZipEntry ze = getZipEntry(null, jzentry); -- freeEntry(jzfile, jzentry); -- return ze; -+ // each "entry" has 3 ints in table entries -+ return getZipEntry(null, zsrc.getEntryPos(i++ * 3)); - } - } - } -@@ -575,50 +533,53 @@ class ZipFile implements ZipConstants, Closeable { - Spliterator.IMMUTABLE | Spliterator.NONNULL), false); - } - -- private ZipEntry getZipEntry(String name, long jzentry) { -- ZipEntry e = new ZipEntry(); -- e.flag = getEntryFlag(jzentry); // get the flag first -- if (name != null) { -- e.name = name; -- } else { -- byte[] bname = getEntryBytes(jzentry, JZENTRY_NAME); -- if (bname == null) { -- e.name = ""; // length 0 empty name -- } else if (!zc.isUTF8() && (e.flag & EFS) != 0) { -- e.name = zc.toStringUTF8(bname, bname.length); -+ /* Checks ensureOpen() before invoke this method */ -+ private ZipEntry getZipEntry(String name, int pos) { -+ byte[] cen = zsrc.cen; -+ int nlen = CENNAM(cen, pos); -+ int elen = CENEXT(cen, pos); -+ int clen = CENCOM(cen, pos); -+ int flag = CENFLG(cen, pos); -+ if (name == null) { -+ if (!zc.isUTF8() && (flag & EFS) != 0) { -+ name = zc.toStringUTF8(cen, pos + CENHDR, nlen); - } else { -- e.name = zc.toString(bname, bname.length); -- } -- } -- e.xdostime = getEntryTime(jzentry); -- e.crc = getEntryCrc(jzentry); -- e.size = getEntrySize(jzentry); -- e.csize = getEntryCSize(jzentry); -- e.method = getEntryMethod(jzentry); -- e.setExtra0(getEntryBytes(jzentry, JZENTRY_EXTRA), false); -- byte[] bcomm = getEntryBytes(jzentry, JZENTRY_COMMENT); -- if (bcomm == null) { -- e.comment = null; -- } else { -- if (!zc.isUTF8() && (e.flag & EFS) != 0) { -- e.comment = zc.toStringUTF8(bcomm, bcomm.length); -+ name = zc.toString(cen, pos + CENHDR, nlen); -+ } -+ } -+ ZipEntry e = new ZipEntry(name); -+ e.flag = flag; -+ e.xdostime = CENTIM(cen, pos); -+ e.crc = CENCRC(cen, pos); -+ e.size = CENLEN(cen, pos); -+ e.csize = CENSIZ(cen, pos); -+ e.method = CENHOW(cen, pos); -+ if (elen != 0) { -+ int start = pos + CENHDR + nlen; -+ e.setExtra0(Arrays.copyOfRange(cen, start, start + elen), true); -+ } -+ if (clen != 0) { -+ int start = pos + CENHDR + nlen + elen; -+ if (!zc.isUTF8() && (flag & EFS) != 0) { -+ e.comment = zc.toStringUTF8(cen, start, clen); - } else { -- e.comment = zc.toString(bcomm, bcomm.length); -+ e.comment = zc.toString(cen, start, clen); - } - } - return e; - } - -- private static native long getNextEntry(long jzfile, int i); -- - /** - * Returns the number of entries in the ZIP file. -+ * - * @return the number of entries in the ZIP file - * @throws IllegalStateException if the zip file has been closed - */ - public int size() { -- ensureOpen(); -- return total; -+ synchronized (this) { -+ ensureOpen(); -+ return zsrc.total; -+ } - } - - /** -@@ -630,14 +591,15 @@ class ZipFile implements ZipConstants, Closeable { - * @throws IOException if an I/O error has occurred - */ - public void close() throws IOException { -- if (closeRequested) -+ if (closeRequested) { - return; -+ } - closeRequested = true; - - synchronized (this) { - // Close streams, release their inflaters - synchronized (streams) { -- if (false == streams.isEmpty()) { -+ if (!streams.isEmpty()) { - Map copy = new HashMap<>(streams); - streams.clear(); - for (Map.Entry e : copy.entrySet()) { -@@ -649,21 +611,17 @@ class ZipFile implements ZipConstants, Closeable { - } - } - } -- - // Release cached inflaters -- Inflater inf; - synchronized (inflaterCache) { -- while (null != (inf = inflaterCache.poll())) { -+ Inflater inf; -+ while ((inf = inflaterCache.poll()) != null) { - inf.end(); - } - } -- -- if (jzfile != 0) { -- // Close the zip file -- long zf = this.jzfile; -- jzfile = 0; -- -- close(zf); -+ // Release zip src -+ if (zsrc != null) { -+ Source.close(zsrc); -+ zsrc = null; - } - } - } -@@ -686,14 +644,11 @@ class ZipFile implements ZipConstants, Closeable { - close(); - } - -- private static native void close(long jzfile); -- - private void ensureOpen() { - if (closeRequested) { - throw new IllegalStateException("zip file closed"); - } -- -- if (jzfile == 0) { -+ if (zsrc == null) { - throw new IllegalStateException("The object is not initialized."); - } - } -@@ -709,40 +664,99 @@ class ZipFile implements ZipConstants, Closeable { - * (possibly compressed) zip file entry. - */ - private class ZipFileInputStream extends InputStream { -- private volatile boolean zfisCloseRequested = false; -- protected long jzentry; // address of jzentry data -+ private volatile boolean closeRequested = false; - private long pos; // current position within entry data - protected long rem; // number of remaining bytes within entry - protected long size; // uncompressed size of this entry - -- ZipFileInputStream(long jzentry) { -- pos = 0; -- rem = getEntryCSize(jzentry); -- size = getEntrySize(jzentry); -- this.jzentry = jzentry; -+ ZipFileInputStream(byte[] cen, int cenpos) throws IOException { -+ rem = CENSIZ(cen, cenpos); -+ size = CENLEN(cen, cenpos); -+ pos = CENOFF(cen, cenpos); -+ // zip64 -+ if (rem == ZIP64_MAGICVAL || size == ZIP64_MAGICVAL || -+ pos == ZIP64_MAGICVAL) { -+ checkZIP64(cen, cenpos); -+ } -+ // negative for lazy initialization, see getDataOffset(); -+ pos = - (pos + ZipFile.this.zsrc.locpos); -+ } -+ -+ private void checkZIP64(byte[] cen, int cenpos) throws IOException { -+ int off = cenpos + CENHDR + CENNAM(cen, cenpos); -+ int end = off + CENEXT(cen, cenpos); -+ while (off + 4 < end) { -+ int tag = get16(cen, off); -+ int sz = get16(cen, off + 2); -+ off += 4; -+ if (off + sz > end) // invalid data -+ break; -+ if (tag == EXTID_ZIP64) { -+ if (size == ZIP64_MAGICVAL) { -+ if (sz < 8 || (off + 8) > end) -+ break; -+ size = get64(cen, off); -+ sz -= 8; -+ off += 8; -+ } -+ if (rem == ZIP64_MAGICVAL) { -+ if (sz < 8 || (off + 8) > end) -+ break; -+ rem = get64(cen, off); -+ sz -= 8; -+ off += 8; -+ } -+ if (pos == ZIP64_MAGICVAL) { -+ if (sz < 8 || (off + 8) > end) -+ break; -+ pos = get64(cen, off); -+ sz -= 8; -+ off += 8; -+ } -+ break; -+ } -+ off += sz; -+ } -+ } -+ -+ /* The Zip file spec explicitly allows the LOC extra data size to -+ * be different from the CEN extra data size. Since we cannot trust -+ * the CEN extra data size, we need to read the LOC to determine -+ * the entry data offset. -+ */ -+ private long initDataOffset() throws IOException { -+ if (pos <= 0) { -+ byte[] loc = new byte[LOCHDR]; -+ pos = -pos; -+ int len = ZipFile.this.zsrc.readFullyAt(loc, 0, loc.length, pos); -+ if (len != LOCHDR) { -+ throw new ZipException("ZipFile error reading zip file"); -+ } -+ if (LOCSIG(loc) != LOCSIG) { -+ throw new ZipException("ZipFile invalid LOC header (bad signature)"); -+ } -+ pos += LOCHDR + LOCNAM(loc) + LOCEXT(loc); -+ } -+ return pos; - } - - public int read(byte b[], int off, int len) throws IOException { - synchronized (ZipFile.this) { -- long rem = this.rem; -- long pos = this.pos; -+ ensureOpenOrZipException(); -+ initDataOffset(); - if (rem == 0) { - return -1; - } -- if (len <= 0) { -- return 0; -- } - if (len > rem) { - len = (int) rem; - } -- -- // Check if ZipFile open -- ensureOpenOrZipException(); -- len = ZipFile.read(ZipFile.this.jzfile, jzentry, pos, b, -- off, len); -+ if (len <= 0) { -+ return 0; -+ } -+ len = ZipFile.this.zsrc.readAt(b, off, len, pos); - if (len > 0) { -- this.pos = (pos + len); -- this.rem = (rem - len); -+ pos += len; -+ rem -= len; - } - } - if (rem == 0) { -@@ -760,11 +774,16 @@ class ZipFile implements ZipConstants, Closeable { - } - } - -- public long skip(long n) { -- if (n > rem) -- n = rem; -- pos += n; -- rem -= n; -+ public long skip(long n) throws IOException { -+ synchronized (ZipFile.this) { -+ ensureOpenOrZipException(); -+ initDataOffset(); -+ if (n > rem) { -+ n = rem; -+ } -+ pos += n; -+ rem -= n; -+ } - if (rem == 0) { - close(); - } -@@ -780,17 +799,11 @@ class ZipFile implements ZipConstants, Closeable { - } - - public void close() { -- if (zfisCloseRequested) -+ if (closeRequested) { - return; -- zfisCloseRequested = true; -- -- rem = 0; -- synchronized (ZipFile.this) { -- if (jzentry != 0 && ZipFile.this.jzfile != 0) { -- freeEntry(ZipFile.this.jzfile, jzentry); -- jzentry = 0; -- } - } -+ closeRequested = true; -+ rem = 0; - synchronized (streams) { - streams.remove(this); - } -@@ -805,7 +818,10 @@ class ZipFile implements ZipConstants, Closeable { - sun.misc.SharedSecrets.setJavaUtilZipFileAccess( - new sun.misc.JavaUtilZipFileAccess() { - public boolean startsWithLocHeader(ZipFile zip) { -- return zip.startsWithLocHeader(); -+ return zip.zsrc.startsWithLoc; -+ } -+ public String[] getMetaInfEntryNames(ZipFile zip) { -+ return zip.getMetaInfEntryNames(); - } - public int getManifestNum(JarFile jar) { - return ((ZipFile)jar).getManifestNum(); -@@ -815,11 +831,27 @@ class ZipFile implements ZipConstants, Closeable { - } - - /** -- * Returns {@code true} if, and only if, the zip file begins with {@code -- * LOCSIG}. -+ * Returns an array of strings representing the names of all entries -+ * that begin with "META-INF/" (case ignored). This method is used -+ * in JarFile, via SharedSecrets, as an optimization when looking up -+ * manifest and signature file entries. Returns null if no entries -+ * were found. - */ -- private boolean startsWithLocHeader() { -- return locsig; -+ private String[] getMetaInfEntryNames() { -+ synchronized (this) { -+ ensureOpen(); -+ if (zsrc.metanames == null) { -+ return null; -+ } -+ String[] names = new String[zsrc.metanames.length]; -+ byte[] cen = zsrc.cen; -+ for (int i = 0; i < names.length; i++) { -+ int pos = zsrc.metanames[i]; -+ names[i] = new String(cen, pos + CENHDR, CENNAM(cen, pos), -+ StandardCharsets.UTF_8); -+ } -+ return names; -+ } - } - - /* -@@ -830,31 +862,506 @@ class ZipFile implements ZipConstants, Closeable { - private int getManifestNum() { - synchronized (this) { - ensureOpen(); -- return manifestNum; -+ return zsrc.manifestNum; - } - } -+ -+ private static class Source { -+ // "META-INF/".length() -+ private static final int META_INF_LEN = 9; -+ private final Key key; // the key in files -+ private int refs = 1; -+ -+ private RandomAccessFile zfile; // zfile of the underlying zip file -+ private byte[] cen; // CEN & ENDHDR -+ private long locpos; // position of first LOC header (usually 0) -+ private byte[] comment; // zip file comment -+ // list of meta entries in META-INF dir -+ private int[] metanames; -+ private int manifestNum = 0; // number of META-INF/MANIFEST.MF, case insensitive -+ private final boolean startsWithLoc; // true, if zip file starts with LOCSIG (usually true) -+ -+ // A Hashmap for all entries. -+ // -+ // A cen entry of Zip/JAR file. As we have one for every entry in every active Zip/JAR, -+ // We might have a lot of these in a typical system. In order to save space we don't -+ // keep the name in memory, but merely remember a 32 bit {@code hash} value of the -+ // entry name and its offset {@code pos} in the central directory hdeader. -+ // -+ // private static class Entry { -+ // int hash; // 32 bit hashcode on name -+ // int next; // hash chain: index into entries -+ // int pos; // Offset of central directory file header -+ // } -+ // private Entry[] entries; // array of hashed cen entry -+ // -+ // To reduce the total size of entries further, we use a int[] here to store 3 "int" -+ // {@code hash}, {@code next and {@code "pos for each entry. The entry can then be -+ // referred by their index of their positions in the {@code entries}. -+ // -+ private int[] entries; // array of hashed cen entry -+ private int addEntry(int index, int hash, int next, int pos) { -+ entries[index++] = hash; -+ entries[index++] = next; -+ entries[index++] = pos; -+ return index; -+ } -+ private int getEntryHash(int index) { return entries[index]; } -+ private int getEntryNext(int index) { return entries[index + 1]; } -+ private int getEntryPos(int index) { return entries[index + 2]; } -+ private static final int ZIP_ENDCHAIN = -1; -+ private int total; // total number of entries -+ private int[] table; // Hash chain heads: indexes into entries -+ private int tablelen; // number of hash heads -+ -+ private static class Key { -+ BasicFileAttributes attrs; -+ File file; -+ -+ public Key(File file, BasicFileAttributes attrs) { -+ this.attrs = attrs; -+ this.file = file; -+ } -+ -+ public int hashCode() { -+ long t = attrs.lastModifiedTime().toMillis(); -+ return ((int)(t ^ (t >>> 32))) + file.hashCode(); -+ } -+ -+ public boolean equals(Object obj) { -+ if (obj instanceof Key) { -+ Key key = (Key)obj; -+ if (!attrs.lastModifiedTime().equals(key.attrs.lastModifiedTime())) { -+ return false; -+ } -+ Object fk = attrs.fileKey(); -+ if (fk != null) { -+ return fk.equals(key.attrs.fileKey()); -+ } else { -+ return file.equals(key.file); -+ } -+ } -+ return false; -+ } -+ } -+ private static final HashMap files = new HashMap<>(); -+ -+ -+ public static Source get(File file, boolean toDelete) throws IOException { -+ Key key = null; -+ try { -+ key = new Key(file, -+ Files.readAttributes(file.toPath(), BasicFileAttributes.class)); -+ } catch (NoSuchFileException exception) { -+ throw new FileNotFoundException(exception.getMessage()); -+ } -+ Source src = null; -+ synchronized (files) { -+ src = files.get(key); -+ if (src != null) { -+ src.refs++; -+ return src; -+ } -+ } -+ src = new Source(key, toDelete); -+ -+ synchronized (files) { -+ if (files.containsKey(key)) { // someone else put in first -+ src.close(); // close the newly created one -+ src = files.get(key); -+ src.refs++; -+ return src; -+ } -+ files.put(key, src); -+ return src; -+ } -+ } -+ -+ private static void close(Source src) throws IOException { -+ synchronized (files) { -+ if (--src.refs == 0) { -+ files.remove(src.key); -+ src.close(); -+ } -+ } -+ } -+ -+ private Source(Key key, boolean toDelete) throws IOException { -+ this.key = key; -+ this.zfile = new RandomAccessFile(key.file, "r"); -+ if (toDelete) { -+ key.file.delete(); -+ } -+ try { -+ initCEN(-1); -+ byte[] buf = new byte[4]; -+ readFullyAt(buf, 0, 4, 0); -+ this.startsWithLoc = (LOCSIG(buf) == LOCSIG); -+ } catch (IOException x) { -+ try { -+ this.zfile.close(); -+ } catch (IOException xx) {} -+ throw x; -+ } -+ } -+ -+ private void close() throws IOException { -+ zfile.close(); -+ zfile = null; -+ cen = null; -+ entries = null; -+ table = null; -+ manifestNum = 0; -+ metanames = null; -+ } -+ -+ private static final int BUF_SIZE = 8192; -+ private final int readFullyAt(byte[] buf, int off, int len, long pos) -+ throws IOException -+ { -+ synchronized(zfile) { -+ zfile.seek(pos); -+ int N = len; -+ while (N > 0) { -+ int n = Math.min(BUF_SIZE, N); -+ zfile.readFully(buf, off, n); -+ off += n; -+ N -= n; -+ } -+ return len; -+ } -+ } -+ -+ private final int readAt(byte[] buf, int off, int len, long pos) -+ throws IOException -+ { -+ synchronized(zfile) { -+ zfile.seek(pos); -+ return zfile.read(buf, off, len); -+ } -+ } -+ -+ private static final int hashN(byte[] a, int off, int len) { -+ int h = 1; -+ while (len-- > 0) { -+ h = 31 * h + a[off++]; -+ } -+ return h; -+ } -+ -+ private static final int hash_append(int hash, byte b) { -+ return hash * 31 + b; -+ } - -- private static native long open(String name, int mode, long lastModified, -- boolean usemmap) throws IOException; -- private static native int getTotal(long jzfile); -- private static native boolean startsWithLOC(long jzfile); -- private static native int getManifestNum(long jzfile); -- private static native int read(long jzfile, long jzentry, -- long pos, byte[] b, int off, int len); -- -- // access to the native zentry object -- private static native long getEntryTime(long jzentry); -- private static native long getEntryCrc(long jzentry); -- private static native long getEntryCSize(long jzentry); -- private static native long getEntrySize(long jzentry); -- private static native int getEntryMethod(long jzentry); -- private static native int getEntryFlag(long jzentry); -- private static native byte[] getCommentBytes(long jzfile); -- -- private static final int JZENTRY_NAME = 0; -- private static final int JZENTRY_EXTRA = 1; -- private static final int JZENTRY_COMMENT = 2; -- private static native byte[] getEntryBytes(long jzentry, int type); -- -- private static native String getZipMessage(long jzfile); -+ private static class End { -+ int centot; // 4 bytes -+ long cenlen; // 4 bytes -+ long cenoff; // 4 bytes -+ long endpos; // 4 bytes -+ } -+ -+ /* -+ * Searches for end of central directory (END) header. The contents of -+ * the END header will be read and placed in endbuf. Returns the file -+ * position of the END header, otherwise returns -1 if the END header -+ * was not found or an error occurred. -+ */ -+ private End findEND() throws IOException { -+ long ziplen = zfile.length(); -+ if (ziplen <= 0) -+ zerror("zip file is empty"); -+ End end = new End(); -+ byte[] buf = new byte[READBLOCKSZ]; -+ long minHDR = (ziplen - END_MAXLEN) > 0 ? ziplen - END_MAXLEN : 0; -+ long minPos = minHDR - (buf.length - ENDHDR); -+ for (long pos = ziplen - buf.length; pos >= minPos; pos -= (buf.length - ENDHDR)) { -+ int off = 0; -+ if (pos < 0) { -+ // Pretend there are some NUL bytes before start of file -+ off = (int)-pos; -+ Arrays.fill(buf, 0, off, (byte)0); -+ } -+ int len = buf.length - off; -+ if (readFullyAt(buf, off, len, pos + off) != len ) { -+ zerror("zip END header not found"); -+ } -+ // Now scan the block backwards for END header signature -+ for (int i = buf.length - ENDHDR; i >= 0; i--) { -+ if (buf[i+0] == (byte)'P' && -+ buf[i+1] == (byte)'K' && -+ buf[i+2] == (byte)'\005' && -+ buf[i+3] == (byte)'\006') { -+ // Found ENDSIG header -+ byte[] endbuf = Arrays.copyOfRange(buf, i, i + ENDHDR); -+ end.centot = ENDTOT(endbuf); -+ end.cenlen = ENDSIZ(endbuf); -+ end.cenoff = ENDOFF(endbuf); -+ end.endpos = pos + i; -+ int comlen = ENDCOM(endbuf); -+ if (end.endpos + ENDHDR + comlen != ziplen) { -+ // ENDSIG matched, however the size of file comment in it does -+ // not match the real size. One "common" cause for this problem -+ // is some "extra" bytes are padded at the end of the zipfile. -+ // Let's do some extra verification, we don't care about the -+ // performance in this situation. -+ byte[] sbuf = new byte[4]; -+ long cenpos = end.endpos - end.cenlen; -+ long locpos = cenpos - end.cenoff; -+ if (cenpos < 0 || -+ locpos < 0 || -+ readFullyAt(sbuf, 0, sbuf.length, cenpos) != 4 || -+ GETSIG(sbuf) != CENSIG || -+ readFullyAt(sbuf, 0, sbuf.length, locpos) != 4 || -+ GETSIG(sbuf) != LOCSIG) { -+ continue; -+ } -+ } -+ if (comlen > 0) { // this zip file has comlen -+ comment = new byte[comlen]; -+ if (readFullyAt(comment, 0, comlen, end.endpos + ENDHDR) != comlen) { -+ zerror("zip comment read failed"); -+ } -+ } -+ if (end.cenlen == ZIP64_MAGICVAL || -+ end.cenoff == ZIP64_MAGICVAL || -+ end.centot == ZIP64_MAGICCOUNT) -+ { -+ // need to find the zip64 end; -+ try { -+ byte[] loc64 = new byte[ZIP64_LOCHDR]; -+ if (readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR) -+ != loc64.length || GETSIG(loc64) != ZIP64_LOCSIG) { -+ return end; -+ } -+ long end64pos = ZIP64_LOCOFF(loc64); -+ byte[] end64buf = new byte[ZIP64_ENDHDR]; -+ if (readFullyAt(end64buf, 0, end64buf.length, end64pos) -+ != end64buf.length || GETSIG(end64buf) != ZIP64_ENDSIG) { -+ return end; -+ } -+ // end64 found, re-calcualte everything. -+ end.cenlen = ZIP64_ENDSIZ(end64buf); -+ end.cenoff = ZIP64_ENDOFF(end64buf); -+ end.centot = (int)ZIP64_ENDTOT(end64buf); // assume total < 2g -+ end.endpos = end64pos; -+ } catch (IOException x) {} // no zip64 loc/end -+ } -+ return end; -+ } -+ } -+ } -+ zerror("zip END header not found"); -+ return null; //make compiler happy -+ } -+ -+ // Reads zip file central directory. -+ private void initCEN(int knownTotal) throws IOException { -+ if (knownTotal == -1) { -+ End end = findEND(); -+ if (end.endpos == 0) { -+ locpos = 0; -+ total = 0; -+ entries = new int[0]; -+ cen = null; -+ return; // only END header present -+ } -+ if (end.cenlen > end.endpos) -+ zerror("invalid END header (bad central directory size)"); -+ long cenpos = end.endpos - end.cenlen; // position of CEN table -+ // Get position of first local file (LOC) header, taking into -+ // account that there may be a stub prefixed to the zip file. -+ locpos = cenpos - end.cenoff; -+ if (locpos < 0) { -+ zerror("invalid END header (bad central directory offset)"); -+ } -+ // read in the CEN and END -+ cen = new byte[(int)(end.cenlen + ENDHDR)]; -+ if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) { -+ zerror("read CEN tables failed"); -+ } -+ total = end.centot; -+ } else { -+ total = knownTotal; -+ } -+ // hash table for entries -+ entries = new int[total * 3]; -+ tablelen = ((total/2) | 1); // Odd -> fewer collisions -+ table = new int[tablelen]; -+ Arrays.fill(table, ZIP_ENDCHAIN); -+ int idx = 0; -+ int hash = 0; -+ int next = -1; -+ -+ // list for all meta entries -+ ArrayList metanamesList = null; -+ -+ // Iterate through the entries in the central directory -+ int i = 0; -+ int hsh = 0; -+ int pos = 0; -+ int limit = cen.length - ENDHDR; -+ manifestNum = 0; -+ while (pos + CENHDR <= limit) { -+ if (i >= total) { -+ // This will only happen if the zip file has an incorrect -+ // ENDTOT field, which usually means it contains more than -+ // 65535 entries. -+ initCEN(countCENHeaders(cen, limit)); -+ return; -+ } -+ if (CENSIG(cen, pos) != CENSIG) -+ zerror("invalid CEN header (bad signature)"); -+ int method = CENHOW(cen, pos); -+ int nlen = CENNAM(cen, pos); -+ int elen = CENEXT(cen, pos); -+ int clen = CENCOM(cen, pos); -+ if ((CENFLG(cen, pos) & 1) != 0) -+ zerror("invalid CEN header (encrypted entry)"); -+ if (method != STORED && method != DEFLATED) -+ zerror("invalid CEN header (bad compression method: " + method + ")"); -+ if (pos + CENHDR + nlen > limit) -+ zerror("invalid CEN header (bad header size)"); -+ // Record the CEN offset and the name hash in our hash cell. -+ hash = hashN(cen, pos + CENHDR, nlen); -+ hsh = (hash & 0x7fffffff) % tablelen; -+ next = table[hsh]; -+ table[hsh] = idx; -+ idx = addEntry(idx, hash, next, pos); -+ // Adds name to metanames. -+ if (isMetaName(cen, pos + CENHDR, nlen)) { -+ if (metanamesList == null) -+ metanamesList = new ArrayList<>(4); -+ metanamesList.add(pos); -+ if (isManifestName(cen, pos + CENHDR + -+ META_INF_LEN, nlen - META_INF_LEN)) { -+ manifestNum++; -+ } -+ } -+ // skip ext and comment -+ pos += (CENHDR + nlen + elen + clen); -+ i++; -+ } -+ total = i; -+ if (metanamesList != null) { -+ metanames = new int[metanamesList.size()]; -+ for (int j = 0, len = metanames.length; j < len; j++) { -+ metanames[j] = metanamesList.get(j); -+ } -+ } -+ if (pos + ENDHDR != cen.length) { -+ zerror("invalid CEN header (bad header size)"); -+ } -+ } -+ -+ private static void zerror(String msg) throws ZipException { -+ throw new ZipException(msg); -+ } -+ -+ /* -+ * Returns the {@code pos} of the zip cen entry corresponding to the -+ * specified entry name, or -1 if not found. -+ */ -+ private int getEntryPos(byte[] name, boolean addSlash) { -+ if (total == 0) { -+ return -1; -+ } -+ int hsh = hashN(name, 0, name.length); -+ int idx = table[(hsh & 0x7fffffff) % tablelen]; -+ /* -+ * This while loop is an optimization where a double lookup -+ * for name and name+/ is being performed. The name char -+ * array has enough room at the end to try again with a -+ * slash appended if the first table lookup does not succeed. -+ */ -+ while(true) { -+ /* -+ * Search down the target hash chain for a entry whose -+ * 32 bit hash matches the hashed name. -+ */ -+ while (idx != ZIP_ENDCHAIN) { -+ if (getEntryHash(idx) == hsh) { -+ // The CEN name must match the specfied one -+ int pos = getEntryPos(idx); -+ if (name.length == CENNAM(cen, pos)) { -+ boolean matched = true; -+ int nameoff = pos + CENHDR; -+ for (int i = 0; i < name.length; i++) { -+ if (name[i] != cen[nameoff++]) { -+ matched = false; -+ break; -+ } -+ } -+ if (matched) { -+ return pos; -+ } -+ } -+ } -+ idx = getEntryNext(idx); -+ } -+ /* If not addSlash, or slash is already there, we are done */ -+ if (!addSlash || name[name.length - 1] == '/') { -+ return -1; -+ } -+ /* Add slash and try once more */ -+ name = Arrays.copyOf(name, name.length + 1); -+ name[name.length - 1] = '/'; -+ hsh = hash_append(hsh, (byte)'/'); -+ //idx = table[hsh % tablelen]; -+ idx = table[(hsh & 0x7fffffff) % tablelen]; -+ addSlash = false; -+ } -+ } -+ -+ /** -+ * Returns true if the bytes represent a non-directory name -+ * beginning with "META-INF/", disregarding ASCII case. -+ */ -+ private static boolean isMetaName(byte[] name, int off, int len) { -+ // Use the "oldest ASCII trick in the book" -+ return len > 9 // "META-INF/".length() -+ && name[off + len - 1] != '/' // non-directory -+ && (name[off++] | 0x20) == 'm' -+ && (name[off++] | 0x20) == 'e' -+ && (name[off++] | 0x20) == 't' -+ && (name[off++] | 0x20) == 'a' -+ && (name[off++] ) == '-' -+ && (name[off++] | 0x20) == 'i' -+ && (name[off++] | 0x20) == 'n' -+ && (name[off++] | 0x20) == 'f' -+ && (name[off] ) == '/'; -+ } -+ -+ /* -+ * Check if the bytes represents a name equals to MANIFEST.MF -+ */ -+ private boolean isManifestName(byte[] name, int off, int len) { -+ return (len == 11 // "MANIFEST.MF".length() -+ && (name[off++] | 0x20) == 'm' -+ && (name[off++] | 0x20) == 'a' -+ && (name[off++] | 0x20) == 'n' -+ && (name[off++] | 0x20) == 'i' -+ && (name[off++] | 0x20) == 'f' -+ && (name[off++] | 0x20) == 'e' -+ && (name[off++] | 0x20) == 's' -+ && (name[off++] | 0x20) == 't' -+ && (name[off++] ) == '.' -+ && (name[off++] | 0x20) == 'm' -+ && (name[off] | 0x20) == 'f'); -+ } -+ -+ /* -+ * Counts the number of CEN headers in a central directory extending -+ * from BEG to END. Might return a bogus answer if the zip file is -+ * corrupt, but will not crash. -+ */ -+ static int countCENHeaders(byte[] cen, int end) { -+ int count = 0; -+ int pos = 0; -+ while (pos + CENHDR <= end) { -+ count++; -+ pos += (CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos)); -+ } -+ return count; -+ } -+ } - } -diff --git a/jdk/src/share/classes/java/util/zip/ZipUtils.java b/jdk/src/share/classes/java/util/zip/ZipUtils.java -index cd8b05278..a9b9db948 100644 ---- a/jdk/src/share/classes/java/util/zip/ZipUtils.java -+++ b/jdk/src/share/classes/java/util/zip/ZipUtils.java -@@ -29,6 +29,8 @@ import java.nio.file.attribute.FileTime; - import java.util.Date; - import java.util.concurrent.TimeUnit; - -+import static java.util.zip.ZipConstants.ENDHDR; -+ - class ZipUtils { - - // used to adjust values between Windows and java epoch -@@ -126,7 +128,7 @@ class ZipUtils { - * The bytes are assumed to be in Intel (little-endian) byte order. - */ - public static final int get16(byte b[], int off) { -- return Byte.toUnsignedInt(b[off]) | (Byte.toUnsignedInt(b[off+1]) << 8); -+ return (b[off] & 0xff) | ((b[off + 1] & 0xff) << 8); - } - - /** -@@ -144,4 +146,79 @@ class ZipUtils { - public static final long get64(byte b[], int off) { - return get32(b, off) | (get32(b, off+4) << 32); - } -+ -+ // fields access methods -+ static final int CH(byte[] b, int n) { -+ return b[n] & 0xff ; -+ } -+ -+ static final int SH(byte[] b, int n) { -+ return (b[n] & 0xff) | ((b[n + 1] & 0xff) << 8); -+ } -+ -+ static final long LG(byte[] b, int n) { -+ return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL; -+ } -+ -+ static final long LL(byte[] b, int n) { -+ return (LG(b, n)) | (LG(b, n + 4) << 32); -+ } -+ -+ static final long GETSIG(byte[] b) { -+ return LG(b, 0); -+ } -+ -+ // local file (LOC) header fields -+ static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature -+ static final int LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract -+ static final int LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags -+ static final int LOCHOW(byte[] b) { return SH(b, 8); } // compression method -+ static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time -+ static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data -+ static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size -+ static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size -+ static final int LOCNAM(byte[] b) { return SH(b, 26);} // filename length -+ static final int LOCEXT(byte[] b) { return SH(b, 28);} // extra field length -+ -+ // extra local (EXT) header fields -+ static final long EXTCRC(byte[] b) { return LG(b, 4);} // crc of uncompressed data -+ static final long EXTSIZ(byte[] b) { return LG(b, 8);} // compressed size -+ static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size -+ -+ // end of central directory header (END) fields -+ static final int ENDSUB(byte[] b) { return SH(b, 8); } // number of entries on this disk -+ static final int ENDTOT(byte[] b) { return SH(b, 10);} // total number of entries -+ static final long ENDSIZ(byte[] b) { return LG(b, 12);} // central directory size -+ static final long ENDOFF(byte[] b) { return LG(b, 16);} // central directory offset -+ static final int ENDCOM(byte[] b) { return SH(b, 20);} // size of zip file comment -+ static final int ENDCOM(byte[] b, int off) { return SH(b, off + 20);} -+ -+ // zip64 end of central directory recoder fields -+ static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);} // total number of entries on disk -+ static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);} // total number of entries -+ static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);} // central directory size -+ static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);} // central directory offset -+ static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);} // zip64 end offset -+ -+ // central directory header (CEN) fields -+ static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); } -+ static final int CENVEM(byte[] b, int pos) { return SH(b, pos + 4); } -+ static final int CENVER(byte[] b, int pos) { return SH(b, pos + 6); } -+ static final int CENFLG(byte[] b, int pos) { return SH(b, pos + 8); } -+ static final int CENHOW(byte[] b, int pos) { return SH(b, pos + 10);} -+ static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);} -+ static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);} -+ static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);} -+ static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);} -+ static final int CENNAM(byte[] b, int pos) { return SH(b, pos + 28);} -+ static final int CENEXT(byte[] b, int pos) { return SH(b, pos + 30);} -+ static final int CENCOM(byte[] b, int pos) { return SH(b, pos + 32);} -+ static final int CENDSK(byte[] b, int pos) { return SH(b, pos + 34);} -+ static final int CENATT(byte[] b, int pos) { return SH(b, pos + 36);} -+ static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);} -+ static final long CENOFF(byte[] b, int pos) { return LG(b, pos + 42);} -+ -+ // The END header is followed by a variable length comment of size < 64k. -+ static final long END_MAXLEN = 0xFFFF + ENDHDR; -+ static final int READBLOCKSZ = 128; - } -diff --git a/jdk/src/share/classes/sun/misc/JavaUtilZipFileAccess.java b/jdk/src/share/classes/sun/misc/JavaUtilZipFileAccess.java -index 0d931d1db..d140f54a5 100644 ---- a/jdk/src/share/classes/sun/misc/JavaUtilZipFileAccess.java -+++ b/jdk/src/share/classes/sun/misc/JavaUtilZipFileAccess.java -@@ -31,5 +31,6 @@ import java.util.zip.ZipFile; - public interface JavaUtilZipFileAccess { - public boolean startsWithLocHeader(ZipFile zip); - public int getManifestNum(JarFile zip); -+ public String[] getMetaInfEntryNames(ZipFile zip); - } - -diff --git a/jdk/src/share/classes/sun/misc/VM.java b/jdk/src/share/classes/sun/misc/VM.java -index 3e64628c6..cb757b3e3 100644 ---- a/jdk/src/share/classes/sun/misc/VM.java -+++ b/jdk/src/share/classes/sun/misc/VM.java -@@ -310,9 +310,6 @@ public class VM { - // used by java.lang.Integer.IntegerCache - props.remove("java.lang.Integer.IntegerCache.high"); - -- // used by java.util.zip.ZipFile -- props.remove("sun.zip.disableMemoryMapping"); -- - // used by sun.launcher.LauncherHelper - props.remove("sun.java.launcher.diag"); - -diff --git a/jdk/src/share/native/java/util/zip/ZipFile.c b/jdk/src/share/native/java/util/zip/ZipFile.c -deleted file mode 100644 -index 8e3698290..000000000 ---- a/jdk/src/share/native/java/util/zip/ZipFile.c -+++ /dev/null -@@ -1,403 +0,0 @@ --/* -- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * This code is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License version 2 only, as -- * published by the Free Software Foundation. Oracle designates this -- * particular file as subject to the "Classpath" exception as provided -- * by Oracle in the LICENSE file that accompanied this code. -- * -- * 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. -- */ -- --/* -- * Native method support for java.util.zip.ZipFile -- */ -- --#include --#include --#include --#include --#include --#include --#include "jlong.h" --#include "jvm.h" --#include "jni.h" --#include "jni_util.h" --#include "zip_util.h" --#ifdef WIN32 --#include "io_util_md.h" --#else --#include "io_util.h" --#endif -- --#include "java_util_zip_ZipFile.h" --#include "java_util_jar_JarFile.h" -- --#define DEFLATED 8 --#define STORED 0 -- --static jfieldID jzfileID; -- --static int OPEN_READ = java_util_zip_ZipFile_OPEN_READ; --static int OPEN_DELETE = java_util_zip_ZipFile_OPEN_DELETE; -- --JNIEXPORT void JNICALL --Java_java_util_zip_ZipFile_initIDs(JNIEnv *env, jclass cls) --{ -- jzfileID = (*env)->GetFieldID(env, cls, "jzfile", "J"); -- assert(jzfileID != 0); --} -- --static void --ThrowZipException(JNIEnv *env, const char *msg) --{ -- jstring s = NULL; -- jobject x; -- -- if (msg != NULL) { -- s = JNU_NewStringPlatform(env, msg); -- } -- if (s != NULL) { -- x = JNU_NewObjectByName(env, -- "java/util/zip/ZipException", -- "(Ljava/lang/String;)V", s); -- if (x != NULL) { -- (*env)->Throw(env, x); -- } -- } --} -- --JNIEXPORT jlong JNICALL --Java_java_util_zip_ZipFile_open(JNIEnv *env, jclass cls, jstring name, -- jint mode, jlong lastModified, -- jboolean usemmap) --{ -- const char *path = JNU_GetStringPlatformChars(env, name, 0); -- char *msg = 0; -- jlong result = 0; -- int flag = 0; -- jzfile *zip = 0; -- -- if (mode & OPEN_READ) flag |= O_RDONLY; -- if (mode & OPEN_DELETE) flag |= JVM_O_DELETE; -- -- if (path != 0) { -- zip = ZIP_Get_From_Cache(path, &msg, lastModified); -- if (zip == 0 && msg == 0) { -- ZFILE zfd = 0; --#ifdef WIN32 -- zfd = winFileHandleOpen(env, name, flag); -- if (zfd == -1) { -- /* Exception already pending. */ -- goto finally; -- } --#else -- zfd = JVM_Open(path, flag, 0); -- if (zfd < 0) { -- throwFileNotFoundException(env, name); -- goto finally; -- } --#endif -- zip = ZIP_Put_In_Cache0(path, zfd, &msg, lastModified, usemmap); -- } -- -- if (zip != 0) { -- result = ptr_to_jlong(zip); -- } else if (msg != 0) { -- ThrowZipException(env, msg); -- free(msg); -- } else if (errno == ENOMEM) { -- JNU_ThrowOutOfMemoryError(env, 0); -- } else { -- ThrowZipException(env, "error in opening zip file"); -- } --finally: -- JNU_ReleaseStringPlatformChars(env, name, path); -- } -- return result; --} -- --JNIEXPORT jint JNICALL --Java_java_util_zip_ZipFile_getTotal(JNIEnv *env, jclass cls, jlong zfile) --{ -- jzfile *zip = jlong_to_ptr(zfile); -- -- return zip->total; --} -- --JNIEXPORT jboolean JNICALL --Java_java_util_zip_ZipFile_startsWithLOC(JNIEnv *env, jclass cls, jlong zfile) --{ -- jzfile *zip = jlong_to_ptr(zfile); -- -- return zip->locsig; --} -- --JNIEXPORT jint JNICALL --Java_java_util_zip_ZipFile_getManifestNum(JNIEnv *env, jclass cls, jlong zfile) --{ -- jzfile *zip = jlong_to_ptr(zfile); -- -- return zip->manifestNum; --} -- --JNIEXPORT void JNICALL --Java_java_util_zip_ZipFile_close(JNIEnv *env, jclass cls, jlong zfile) --{ -- ZIP_Close(jlong_to_ptr(zfile)); --} -- --JNIEXPORT jlong JNICALL --Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile, -- jbyteArray name, jboolean addSlash) --{ --#define MAXNAME 1024 -- jzfile *zip = jlong_to_ptr(zfile); -- jsize ulen = (*env)->GetArrayLength(env, name); -- char buf[MAXNAME+2], *path; -- jzentry *ze; -- -- if (ulen > MAXNAME) { -- path = malloc(ulen + 2); -- if (path == 0) { -- JNU_ThrowOutOfMemoryError(env, 0); -- return 0; -- } -- } else { -- path = buf; -- } -- (*env)->GetByteArrayRegion(env, name, 0, ulen, (jbyte *)path); -- path[ulen] = '\0'; -- ze = ZIP_GetEntry2(zip, path, (jint)ulen, addSlash); -- if (path != buf) { -- free(path); -- } -- return ptr_to_jlong(ze); --} -- --JNIEXPORT void JNICALL --Java_java_util_zip_ZipFile_freeEntry(JNIEnv *env, jclass cls, jlong zfile, -- jlong zentry) --{ -- jzfile *zip = jlong_to_ptr(zfile); -- jzentry *ze = jlong_to_ptr(zentry); -- ZIP_FreeEntry(zip, ze); --} -- --JNIEXPORT jlong JNICALL --Java_java_util_zip_ZipFile_getNextEntry(JNIEnv *env, jclass cls, jlong zfile, -- jint n) --{ -- jzentry *ze = ZIP_GetNextEntry(jlong_to_ptr(zfile), n); -- return ptr_to_jlong(ze); --} -- --JNIEXPORT jint JNICALL --Java_java_util_zip_ZipFile_getEntryMethod(JNIEnv *env, jclass cls, jlong zentry) --{ -- jzentry *ze = jlong_to_ptr(zentry); -- return ze->csize != 0 ? DEFLATED : STORED; --} -- --JNIEXPORT jint JNICALL --Java_java_util_zip_ZipFile_getEntryFlag(JNIEnv *env, jclass cls, jlong zentry) --{ -- jzentry *ze = jlong_to_ptr(zentry); -- return ze->flag; --} -- --JNIEXPORT jlong JNICALL --Java_java_util_zip_ZipFile_getEntryCSize(JNIEnv *env, jclass cls, jlong zentry) --{ -- jzentry *ze = jlong_to_ptr(zentry); -- return ze->csize != 0 ? ze->csize : ze->size; --} -- --JNIEXPORT jlong JNICALL --Java_java_util_zip_ZipFile_getEntrySize(JNIEnv *env, jclass cls, jlong zentry) --{ -- jzentry *ze = jlong_to_ptr(zentry); -- return ze->size; --} -- --JNIEXPORT jlong JNICALL --Java_java_util_zip_ZipFile_getEntryTime(JNIEnv *env, jclass cls, jlong zentry) --{ -- jzentry *ze = jlong_to_ptr(zentry); -- return (jlong)ze->time & 0xffffffffUL; --} -- --JNIEXPORT jlong JNICALL --Java_java_util_zip_ZipFile_getEntryCrc(JNIEnv *env, jclass cls, jlong zentry) --{ -- jzentry *ze = jlong_to_ptr(zentry); -- return (jlong)ze->crc & 0xffffffffUL; --} -- --JNIEXPORT jbyteArray JNICALL --Java_java_util_zip_ZipFile_getCommentBytes(JNIEnv *env, -- jclass cls, -- jlong zfile) --{ -- jzfile *zip = jlong_to_ptr(zfile); -- jbyteArray jba = NULL; -- -- if (zip->comment != NULL) { -- if ((jba = (*env)->NewByteArray(env, zip->clen)) == NULL) -- return NULL; -- (*env)->SetByteArrayRegion(env, jba, 0, zip->clen, (jbyte*)zip->comment); -- } -- return jba; --} -- --JNIEXPORT jbyteArray JNICALL --Java_java_util_zip_ZipFile_getEntryBytes(JNIEnv *env, -- jclass cls, -- jlong zentry, jint type) --{ -- jzentry *ze = jlong_to_ptr(zentry); -- int len = 0; -- jbyteArray jba = NULL; -- switch (type) { -- case java_util_zip_ZipFile_JZENTRY_NAME: -- if (ze->name != 0) { -- len = (int)ze->nlen; -- if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL) -- break; -- (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte *)ze->name); -- } -- break; -- case java_util_zip_ZipFile_JZENTRY_EXTRA: -- if (ze->extra != 0) { -- unsigned char *bp = (unsigned char *)&ze->extra[0]; -- len = (bp[0] | (bp[1] << 8)); -- if (len <= 0 || (jba = (*env)->NewByteArray(env, len)) == NULL) -- break; -- (*env)->SetByteArrayRegion(env, jba, 0, len, &ze->extra[2]); -- } -- break; -- case java_util_zip_ZipFile_JZENTRY_COMMENT: -- if (ze->comment != 0) { -- len = (int)strlen(ze->comment); -- if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL) -- break; -- (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte*)ze->comment); -- } -- break; -- } -- return jba; --} -- --JNIEXPORT jint JNICALL --Java_java_util_zip_ZipFile_read(JNIEnv *env, jclass cls, jlong zfile, -- jlong zentry, jlong pos, jbyteArray bytes, -- jint off, jint len) --{ -- jzfile *zip = jlong_to_ptr(zfile); -- char *msg; -- --#define BUFSIZE 8192 -- /* copy via tmp stack buffer: */ -- jbyte buf[BUFSIZE]; -- -- if (len > BUFSIZE) { -- len = BUFSIZE; -- } -- -- ZIP_Lock(zip); -- len = ZIP_Read(zip, jlong_to_ptr(zentry), pos, buf, len); -- msg = zip->msg; -- ZIP_Unlock(zip); -- if (len != -1) { -- (*env)->SetByteArrayRegion(env, bytes, off, len, buf); -- } -- -- if (len == -1) { -- if (msg != 0) { -- ThrowZipException(env, msg); -- } else { -- char errmsg[128]; -- sprintf(errmsg, "errno: %d, error: %s\n", -- errno, "Error reading ZIP file"); -- JNU_ThrowIOExceptionWithLastError(env, errmsg); -- } -- } -- -- return len; --} -- --/* -- * Returns an array of strings representing the names of all entries -- * that begin with "META-INF/" (case ignored). This native method is -- * used in JarFile as an optimization when looking up manifest and -- * signature file entries. Returns null if no entries were found. -- */ --JNIEXPORT jobjectArray JNICALL --Java_java_util_jar_JarFile_getMetaInfEntryNames(JNIEnv *env, jobject obj) --{ -- jlong zfile = (*env)->GetLongField(env, obj, jzfileID); -- jzfile *zip; -- int i, count; -- jobjectArray result = 0; -- -- if (zfile == 0) { -- JNU_ThrowByName(env, -- "java/lang/IllegalStateException", "zip file closed"); -- return NULL; -- } -- zip = jlong_to_ptr(zfile); -- -- /* count the number of valid ZIP metanames */ -- count = 0; -- if (zip->metanames != 0) { -- for (i = 0; i < zip->metacount; i++) { -- if (zip->metanames[i] != 0) { -- count++; -- } -- } -- } -- -- /* If some names were found then build array of java strings */ -- if (count > 0) { -- jclass cls = JNU_ClassString(env); -- CHECK_NULL_RETURN(cls, NULL); -- result = (*env)->NewObjectArray(env, count, cls, 0); -- CHECK_NULL_RETURN(result, NULL); -- if (result != 0) { -- for (i = 0; i < count; i++) { -- jstring str = (*env)->NewStringUTF(env, zip->metanames[i]); -- if (str == 0) { -- break; -- } -- (*env)->SetObjectArrayElement(env, result, i, str); -- (*env)->DeleteLocalRef(env, str); -- } -- } -- } -- return result; --} -- --JNIEXPORT jstring JNICALL --Java_java_util_zip_ZipFile_getZipMessage(JNIEnv *env, jclass cls, jlong zfile) --{ -- jzfile *zip = jlong_to_ptr(zfile); -- char *msg = zip->msg; -- if (msg == NULL) { -- return NULL; -- } -- return JNU_NewStringPlatform(env, msg); --} -diff --git a/jdk/src/share/native/java/util/zip/zip_util.c b/jdk/src/share/native/java/util/zip/zip_util.c -index ff59c5ecc..ffe094065 100644 ---- a/jdk/src/share/native/java/util/zip/zip_util.c -+++ b/jdk/src/share/native/java/util/zip/zip_util.c -@@ -74,8 +74,6 @@ static void freeCEN(jzfile *); - #define PATH_MAX 1024 - #endif - --#define META_INF_LEN 9 /* "META-INF/".length() */ -- - static jint INITIAL_META_COUNT = 2; /* initial number of entries in meta name array */ - - #ifdef LINUX -@@ -475,25 +473,6 @@ isMetaName(const char *name, int length) - return 1; - } - --/* -- * Check if the bytes represents a name equals to MANIFEST.MF -- */ --static int --isManifestName(const char *name, int length) --{ -- const char *s; -- if (length != (int)sizeof("MANIFEST.MF") - 1) -- return 0; -- for (s = "MANIFEST.MF"; *s != '\0'; s++) { -- char c = *name++; -- // Avoid toupper; it's locale-dependent -- if (c >= 'a' && c <= 'z') c += 'A' - 'a'; -- if (*s != c) -- return 0; -- } -- return 1; --} -- - /* - * Increases the capacity of zip->metanames. - * Returns non-zero in case of allocation error. -@@ -564,7 +543,6 @@ freeCEN(jzfile *zip) - { - free(zip->entries); zip->entries = NULL; - free(zip->table); zip->table = NULL; -- zip->manifestNum = 0; - freeMetaNames(zip); - } - -@@ -718,8 +696,6 @@ readCEN(jzfile *zip, jint knownTotal) - for (j = 0; j < tablelen; j++) - table[j] = ZIP_ENDCHAIN; - -- zip->manifestNum = 0; -- - /* Iterate through the entries in the central directory */ - for (i = 0, cp = cenbuf; cp <= cenend - CENHDR; i++, cp += CENSIZE(cp)) { - /* Following are unsigned 16-bit */ -@@ -747,12 +723,9 @@ readCEN(jzfile *zip, jint knownTotal) - ZIP_FORMAT_ERROR("invalid CEN header (bad header size)"); - - /* if the entry is metadata add it to our metadata names */ -- if (isMetaName((char *)cp+CENHDR, nlen)) { -- if (isManifestName((char *)cp+CENHDR+META_INF_LEN, nlen-META_INF_LEN)) -- zip->manifestNum++; -+ if (isMetaName((char *)cp+CENHDR, nlen)) - if (addMetaName(zip, (char *)cp+CENHDR, nlen) != 0) - goto Catch; -- } - - /* Record the CEN offset and the name hash in our hash cell. */ - entries[i].cenpos = cenpos + (cp - cenbuf); -diff --git a/jdk/src/share/native/java/util/zip/zip_util.h b/jdk/src/share/native/java/util/zip/zip_util.h -index 2a7ae4b7e..a64668cd6 100644 ---- a/jdk/src/share/native/java/util/zip/zip_util.h -+++ b/jdk/src/share/native/java/util/zip/zip_util.h -@@ -229,7 +229,6 @@ typedef struct jzfile { /* Zip file */ - char **metanames; /* array of meta names (may have null names) */ - jint metacurrent; /* the next empty slot in metanames array */ - jint metacount; /* number of slots in metanames array */ -- jint manifestNum; /* number of META-INF/MANIFEST.MF, case insensitive */ - jlong lastModified; /* last modified time */ - jlong locpos; /* position of first LOC header (usually 0) */ - } jzfile; -diff --git a/jdk/test/java/nio/file/spi/TestProvider.java b/jdk/test/java/nio/file/spi/TestProvider.java -index b2744f4c0..c975b8e27 100644 ---- a/jdk/test/java/nio/file/spi/TestProvider.java -+++ b/jdk/test/java/nio/file/spi/TestProvider.java -@@ -21,20 +21,34 @@ - * questions. - */ - --import java.nio.file.spi.FileSystemProvider; -+import java.io.File; - import java.nio.file.*; --import java.nio.file.attribute.*; -+import java.nio.file.attribute.BasicFileAttributes; -+import java.nio.file.attribute.FileAttribute; -+import java.nio.file.attribute.FileAttributeView; -+import java.nio.file.attribute.UserPrincipalLookupService; -+import java.nio.file.spi.FileSystemProvider; - import java.nio.channels.SeekableByteChannel; - import java.net.URI; --import java.util.*; - import java.io.IOException; -+import java.util.Collections; -+import java.util.Iterator; -+import java.util.Map; -+import java.util.Set; - - public class TestProvider extends FileSystemProvider { - -- private final FileSystem theFileSystem; -+ private final FileSystemProvider defaultProvider; -+ private final TestFileSystem theFileSystem; - - public TestProvider(FileSystemProvider defaultProvider) { -- theFileSystem = new TestFileSystem(this); -+ this.defaultProvider = defaultProvider; -+ FileSystem fs = defaultProvider.getFileSystem(URI.create("file:/")); -+ this.theFileSystem = new TestFileSystem(fs, this); -+ } -+ -+ FileSystemProvider defaultProvider() { -+ return defaultProvider; - } - - @Override -@@ -43,8 +57,8 @@ public class TestProvider extends FileSystemProvider { - } - - @Override -- public FileSystem newFileSystem(URI uri, Map env) { -- throw new RuntimeException("not implemented"); -+ public FileSystem newFileSystem(URI uri, Map env) throws IOException { -+ return defaultProvider.newFileSystem(uri, env); - } - - @Override -@@ -54,7 +68,8 @@ public class TestProvider extends FileSystemProvider { - - @Override - public Path getPath(URI uri) { -- throw new RuntimeException("not implemented"); -+ Path path = defaultProvider.getPath(uri); -+ return theFileSystem.wrap(path); - } - - @Override -@@ -70,7 +85,8 @@ public class TestProvider extends FileSystemProvider { - LinkOption... options) - throws IOException - { -- throw new RuntimeException("not implemented"); -+ Path delegate = theFileSystem.unwrap(file); -+ return defaultProvider.readAttributes(delegate, attributes, options); - } - - @Override -@@ -79,7 +95,8 @@ public class TestProvider extends FileSystemProvider { - LinkOption... options) - throws IOException - { -- throw new RuntimeException("not implemented"); -+ Path delegate = theFileSystem.unwrap(file); -+ return defaultProvider.readAttributes(delegate, type, options); - } - - @Override -@@ -87,13 +104,14 @@ public class TestProvider extends FileSystemProvider { - Class type, - LinkOption... options) - { -- throw new RuntimeException("not implemented"); -+ Path delegate = theFileSystem.unwrap(file); -+ return defaultProvider.getFileAttributeView(delegate, type, options); - } - -- - @Override - public void delete(Path file) throws IOException { -- throw new RuntimeException("not implemented"); -+ Path delegate = theFileSystem.unwrap(file); -+ defaultProvider.delete(delegate); - } - - @Override -@@ -110,10 +128,11 @@ public class TestProvider extends FileSystemProvider { - - @Override - public Path readSymbolicLink(Path link) throws IOException { -- throw new RuntimeException("not implemented"); -+ Path delegate = theFileSystem.unwrap(link); -+ Path target = defaultProvider.readSymbolicLink(delegate); -+ return theFileSystem.wrap(target); - } - -- - @Override - public void copy(Path source, Path target, CopyOption... options) - throws IOException -@@ -140,7 +159,8 @@ public class TestProvider extends FileSystemProvider { - public void createDirectory(Path dir, FileAttribute... attrs) - throws IOException - { -- throw new RuntimeException("not implemented"); -+ Path delegate = theFileSystem.unwrap(dir); -+ defaultProvider.createDirectory(delegate, attrs); - } - - @Override -@@ -149,13 +169,13 @@ public class TestProvider extends FileSystemProvider { - FileAttribute... attrs) - throws IOException - { -- throw new RuntimeException("not implemented"); -+ Path delegate = theFileSystem.unwrap(file); -+ return defaultProvider.newByteChannel(delegate, options, attrs); - } - -- - @Override - public boolean isHidden(Path file) throws IOException { -- throw new RuntimeException("not implemented"); -+ throw new ReadOnlyFileSystemException(); - } - - @Override -@@ -176,12 +196,26 @@ public class TestProvider extends FileSystemProvider { - } - - static class TestFileSystem extends FileSystem { -+ private final FileSystem delegate; - private final TestProvider provider; - -- TestFileSystem(TestProvider provider) { -+ TestFileSystem(FileSystem delegate, TestProvider provider) { -+ this.delegate = delegate; - this.provider = provider; - } - -+ Path wrap(Path path) { -+ return (path != null) ? new TestPath(this, path) : null; -+ } -+ -+ Path unwrap(Path wrapper) { -+ if (wrapper == null) -+ throw new NullPointerException(); -+ if (!(wrapper instanceof TestPath)) -+ throw new ProviderMismatchException(); -+ return ((TestPath)wrapper).unwrap(); -+ } -+ - @Override - public FileSystemProvider provider() { - return provider; -@@ -194,17 +228,17 @@ public class TestProvider extends FileSystemProvider { - - @Override - public boolean isOpen() { -- throw new RuntimeException("not implemented"); -+ return true; - } - - @Override - public boolean isReadOnly() { -- throw new RuntimeException("not implemented"); -+ return false; - } - - @Override - public String getSeparator() { -- throw new RuntimeException("not implemented"); -+ return delegate.getSeparator(); - } - - @Override -@@ -219,27 +253,209 @@ public class TestProvider extends FileSystemProvider { - - @Override - public Set supportedFileAttributeViews() { -- throw new RuntimeException("not implemented"); -+ return delegate.supportedFileAttributeViews(); - } - - @Override - public Path getPath(String first, String... more) { -- throw new RuntimeException("not implemented"); -+ Path path = delegate.getPath(first, more); -+ return wrap(path); - } - - @Override - public PathMatcher getPathMatcher(String syntaxAndPattern) { -- throw new RuntimeException("not implemented"); -+ return delegate.getPathMatcher(syntaxAndPattern); - } - - @Override - public UserPrincipalLookupService getUserPrincipalLookupService() { -- throw new RuntimeException("not implemented"); -+ return delegate.getUserPrincipalLookupService(); - } - - @Override - public WatchService newWatchService() throws IOException { -- throw new RuntimeException("not implemented"); -+ throw new UnsupportedOperationException(); -+ } -+ } -+ -+ static class TestPath implements Path { -+ private final TestFileSystem fs; -+ private final Path delegate; -+ -+ TestPath(TestFileSystem fs, Path delegate) { -+ this.fs = fs; -+ this.delegate = delegate; -+ } -+ -+ Path unwrap() { -+ return delegate; -+ } -+ -+ @Override -+ public FileSystem getFileSystem() { -+ return fs; -+ } -+ -+ @Override -+ public boolean isAbsolute() { -+ return delegate.isAbsolute(); -+ } -+ -+ @Override -+ public Path getRoot() { -+ return fs.wrap(delegate.getRoot()); -+ } -+ -+ @Override -+ public Path getParent() { -+ return fs.wrap(delegate.getParent()); -+ } -+ -+ @Override -+ public int getNameCount() { -+ return delegate.getNameCount(); -+ } -+ -+ @Override -+ public Path getFileName() { -+ return fs.wrap(delegate.getFileName()); -+ } -+ -+ @Override -+ public Path getName(int index) { -+ return fs.wrap(delegate.getName(index)); -+ } -+ -+ @Override -+ public Path subpath(int beginIndex, int endIndex) { -+ return fs.wrap(delegate.subpath(beginIndex, endIndex)); -+ } -+ -+ @Override -+ public boolean startsWith(Path other) { -+ return delegate.startsWith(fs.unwrap(other)); -+ } -+ -+ @Override -+ public boolean startsWith(String other) { -+ return delegate.startsWith(other); -+ } -+ -+ @Override -+ public boolean endsWith(Path other) { -+ return delegate.endsWith(fs.unwrap(other)); -+ } -+ -+ @Override -+ public boolean endsWith(String other) { -+ return delegate.endsWith(other); -+ } -+ -+ @Override -+ public Path normalize() { -+ return fs.wrap(delegate.normalize()); -+ } -+ -+ @Override -+ public Path resolve(Path other) { -+ return fs.wrap(delegate.resolve(fs.unwrap(other))); -+ } -+ -+ @Override -+ public Path resolve(String other) { -+ return fs.wrap(delegate.resolve(other)); -+ } -+ -+ @Override -+ public Path resolveSibling(Path other) { -+ return fs.wrap(delegate.resolveSibling(fs.unwrap(other))); -+ } -+ -+ @Override -+ public Path resolveSibling(String other) { -+ return fs.wrap(delegate.resolveSibling(other)); -+ } -+ -+ @Override -+ public Path relativize(Path other) { -+ return fs.wrap(delegate.relativize(fs.unwrap(other))); -+ } -+ -+ @Override -+ public boolean equals(Object other) { -+ if (!(other instanceof TestPath)) -+ return false; -+ return delegate.equals(fs.unwrap((TestPath) other)); -+ } -+ -+ @Override -+ public int hashCode() { -+ return delegate.hashCode(); -+ } -+ -+ @Override -+ public String toString() { -+ return delegate.toString(); -+ } -+ -+ @Override -+ public URI toUri() { -+ String ssp = delegate.toUri().getSchemeSpecificPart(); -+ return URI.create(fs.provider().getScheme() + ":" + ssp); -+ } -+ -+ @Override -+ public Path toAbsolutePath() { -+ return fs.wrap(delegate.toAbsolutePath()); -+ } -+ -+ @Override -+ public Path toRealPath(LinkOption... options) throws IOException { -+ return fs.wrap(delegate.toRealPath(options)); -+ } -+ -+ @Override -+ public File toFile() { -+ return new File(toString()); -+ } -+ -+ @Override -+ public Iterator iterator() { -+ final Iterator itr = delegate.iterator(); -+ return new Iterator() { -+ @Override -+ public boolean hasNext() { -+ return itr.hasNext(); -+ } -+ @Override -+ public Path next() { -+ return fs.wrap(itr.next()); -+ } -+ @Override -+ public void remove() { -+ itr.remove(); -+ } -+ }; -+ } -+ -+ @Override -+ public int compareTo(Path other) { -+ return delegate.compareTo(fs.unwrap(other)); -+ } -+ -+ @Override -+ public WatchKey register(WatchService watcher, -+ WatchEvent.Kind[] events, -+ WatchEvent.Modifier... modifiers) -+ { -+ throw new UnsupportedOperationException(); -+ } -+ -+ @Override -+ public WatchKey register(WatchService watcher, -+ WatchEvent.Kind... events) -+ { -+ throw new UnsupportedOperationException(); - } - } --} -+} -\ No newline at end of file -diff --git a/jdk/test/java/util/zip/ZipFile/TestZipFile.java b/jdk/test/java/util/zip/ZipFile/TestZipFile.java -new file mode 100644 -index 000000000..30bae3bb9 ---- /dev/null -+++ b/jdk/test/java/util/zip/ZipFile/TestZipFile.java -@@ -0,0 +1,375 @@ -+/* -+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2023, 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 8142508 -+ * @summary Tests various ZipFile apis -+ * @run main/manual TestZipFile -+ */ -+ -+import java.io.*; -+import java.lang.reflect.Method; -+import java.nio.file.*; -+import java.nio.file.attribute.*; -+import java.util.*; -+import java.util.concurrent.*; -+import java.util.zip.*; -+ -+public class TestZipFile { -+ -+ private static Random r = new Random(); -+ private static int N = 50; -+ private static int NN = 10; -+ private static int ENUM = 10000; -+ private static int ESZ = 10000; -+ private static ExecutorService executor = Executors.newFixedThreadPool(20); -+ private static Set paths = new HashSet<>(); -+ -+ static void realMain (String[] args) throws Throwable { -+ -+ try { -+ for (int i = 0; i < N; i++) { -+ test(r.nextInt(ENUM), r.nextInt(ESZ), false, true); -+ test(r.nextInt(ENUM), r.nextInt(ESZ), true, true); -+ } -+ -+ for (int i = 0; i < NN; i++) { -+ test(r.nextInt(ENUM), 100000 + r.nextInt(ESZ), false, true); -+ test(r.nextInt(ENUM), 100000 + r.nextInt(ESZ), true, true); -+ testCachedDelete(); -+ testCachedOverwrite(); -+ //test(r.nextInt(ENUM), r.nextInt(ESZ), false, true); -+ } -+ -+ test(70000, 1000, false, true); // > 65536 entry number; -+ testDelete(); // OPEN_DELETE -+ -+ executor.shutdown(); -+ executor.awaitTermination(10, TimeUnit.MINUTES); -+ } finally { -+ for (Path path : paths) { -+ Files.deleteIfExists(path); -+ } -+ } -+ } -+ -+ static void test(int numEntry, int szMax, boolean addPrefix, boolean cleanOld) { -+ String name = "zftest" + r.nextInt() + ".zip"; -+ Zip zip = new Zip(name, numEntry, szMax, addPrefix, cleanOld); -+ for (int i = 0; i < NN; i++) { -+ executor.submit(() -> doTest(zip)); -+ } -+ } -+ -+ // test scenario: -+ // (1) open the ZipFile(zip) with OPEN_READ | OPEN_DELETE -+ // (2) test the ZipFile works correctly -+ // (3) check the zip is deleted after ZipFile gets closed -+ static void testDelete() throws Throwable { -+ String name = "zftest" + r.nextInt() + ".zip"; -+ Zip zip = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true); -+ try (ZipFile zf = new ZipFile(new File(zip.name), -+ ZipFile.OPEN_READ | ZipFile.OPEN_DELETE )) -+ { -+ doTest0(zip, zf); -+ } -+ Path p = Paths.get(name); -+ if (Files.exists(p)) { -+ fail("Failed to delete " + name + " with OPEN_DELETE"); -+ } -+ } -+ -+ // test scenario: -+ // (1) keep a ZipFile(zip1) alive (in ZipFile's cache), dont close it -+ // (2) delete zip1 and create zip2 with the same name the zip1 with zip2 -+ // (3) zip1 tests should fail, but no crash -+ // (4) zip2 tasks should all get zip2, then pass normal testing. -+ static void testCachedDelete() throws Throwable { -+ String name = "zftest" + r.nextInt() + ".zip"; -+ Zip zip1 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true); -+ -+ try (ZipFile zf = new ZipFile(zip1.name)) { -+ for (int i = 0; i < NN; i++) { -+ executor.submit(() -> verifyNoCrash(zip1)); -+ } -+ // delete the "zip1" and create a new one to test -+ Zip zip2 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true); -+ /* -+ System.out.println("========================================"); -+ System.out.printf(" zip1=%s, mt=%d, enum=%d%n ->attrs=[key=%s, sz=%d, mt=%d]%n", -+ zip1.name, zip1.lastModified, zip1.entries.size(), -+ zip1.attrs.fileKey(), zip1.attrs.size(), zip1.attrs.lastModifiedTime().toMillis()); -+ System.out.printf(" zip2=%s, mt=%d, enum=%d%n ->attrs=[key=%s, sz=%d, mt=%d]%n", -+ zip2.name, zip2.lastModified, zip2.entries.size(), -+ zip2.attrs.fileKey(), zip2.attrs.size(), zip2.attrs.lastModifiedTime().toMillis()); -+ */ -+ for (int i = 0; i < NN; i++) { -+ executor.submit(() -> doTest(zip2)); -+ } -+ } -+ } -+ -+ // overwrite the "zip1" and create a new one to test. So the two zip files -+ // have the same fileKey, but probably different lastModified() -+ static void testCachedOverwrite() throws Throwable { -+ String name = "zftest" + r.nextInt() + ".zip"; -+ Zip zip1 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true); -+ try (ZipFile zf = new ZipFile(zip1.name)) { -+ for (int i = 0; i < NN; i++) { -+ executor.submit(() -> verifyNoCrash(zip1)); -+ } -+ // overwrite the "zip1" with new contents -+ Zip zip2 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, false); -+ for (int i = 0; i < NN; i++) { -+ executor.submit(() -> doTest(zip2)); -+ } -+ } -+ } -+ -+ // This method is used to replace the InputStream.readAllBytes method(need JDK version >= 9). -+ public static byte[] readAllBytes(InputStream inputStream) throws IOException { -+ byte[] buffer = new byte[1024]; -+ int len; -+ try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { -+ while ((len = inputStream.read(buffer)) > -1) { -+ outputStream.write(buffer, 0, len); -+ } -+ return outputStream.toByteArray(); -+ } catch (IOException e) { -+ throw e; -+ } -+ } -+ -+ // just check the entries and contents. since the file has been either overwritten -+ // or deleted/rewritten, we only care if it crahes or not. -+ static void verifyNoCrash(Zip zip) throws RuntimeException { -+ try (ZipFile zf = new ZipFile(zip.name)) { -+ List zlist = new ArrayList(zip.entries.keySet()); -+ String[] elist = zf.stream().map( e -> e.getName()).toArray(String[]::new); -+ if (!Arrays.equals(elist, -+ zlist.stream().map( e -> e.getName()).toArray(String[]::new))) -+ { -+ //System.out.printf("++++++ LIST NG [%s] entries.len=%d, expected=%d+++++++%n", -+ // zf.getName(), elist.length, zlist.size()); -+ return; -+ } -+ for (ZipEntry ze : zlist) { -+ byte[] zdata = zip.entries.get(ze); -+ ZipEntry e = zf.getEntry(ze.getName()); -+ if (e != null) { -+ checkEqual(e, ze); -+ if (!e.isDirectory()) { -+ // check with readAllBytes -+ try (InputStream is = zf.getInputStream(e)) { -+ if (!Arrays.equals(zdata, readAllBytes(is))) { -+ //System.out.printf("++++++ BYTES NG [%s]/[%s] ++++++++%n", -+ // zf.getName(), ze.getName()); -+ } -+ } -+ } -+ } -+ } -+ } catch (Throwable t) { -+ // t.printStackTrace(); -+ // fail(t.toString()); -+ } -+ } -+ -+ static void checkEqual(ZipEntry x, ZipEntry y) { -+ if (x.getName().equals(y.getName()) && -+ x.isDirectory() == y.isDirectory() && -+ x.getMethod() == y.getMethod() && -+ (x.getTime() / 2000) == y.getTime() / 2000 && -+ x.getSize() == y.getSize() && -+ x.getCompressedSize() == y.getCompressedSize() && -+ x.getCrc() == y.getCrc() && -+ x.getComment().equals(y.getComment()) -+ ) { -+ pass(); -+ } else { -+ fail(x + " not equal to " + y); -+ System.out.printf(" %s %s%n", x.getName(), y.getName()); -+ System.out.printf(" %d %d%n", x.getMethod(), y.getMethod()); -+ System.out.printf(" %d %d%n", x.getTime(), y.getTime()); -+ System.out.printf(" %d %d%n", x.getSize(), y.getSize()); -+ System.out.printf(" %d %d%n", x.getCompressedSize(), y.getCompressedSize()); -+ System.out.printf(" %d %d%n", x.getCrc(), y.getCrc()); -+ System.out.println("-----------------"); -+ } -+ } -+ -+ static void doTest(Zip zip) throws RuntimeException { -+ //Thread me = Thread.currentThread(); -+ try (ZipFile zf = new ZipFile(zip.name)) { -+ doTest0(zip, zf); -+ } catch (Throwable t) { -+ throw new RuntimeException(t); -+ } -+ } -+ -+ static void doTest0(Zip zip, ZipFile zf) throws Throwable { -+ List list = new ArrayList(zip.entries.keySet()); -+ // (1) check entry list, in expected order -+ if (!check(Arrays.equals( -+ list.stream().map( e -> e.getName()).toArray(String[]::new), -+ zf.stream().map( e -> e.getName()).toArray(String[]::new)))) { -+ return; -+ } -+ // (2) shuffle, and check each entry and its bytes -+ Collections.shuffle(list); -+ for (ZipEntry ze : list) { -+ byte[] data = zip.entries.get(ze); -+ ZipEntry e = zf.getEntry(ze.getName()); -+ checkEqual(e, ze); -+ if (!e.isDirectory()) { -+ // check with readAllBytes -+ try (InputStream is = zf.getInputStream(e)) { -+ check(Arrays.equals(data, readAllBytes(is))); -+ } -+ // check with smaller sized buf -+ try (InputStream is = zf.getInputStream(e)) { -+ byte[] buf = new byte[(int)e.getSize()]; -+ int sz = r.nextInt((int)e.getSize()/4 + 1) + 1; -+ int off = 0; -+ int n; -+ while ((n = is.read(buf, off, buf.length - off)) > 0) { -+ off += n; -+ } -+ check(is.read() == -1); -+ check(Arrays.equals(data, buf)); -+ } -+ } -+ } -+ // (3) check getMetaInfEntryNames -+ String[] metas = list.stream() -+ .map( e -> e.getName()) -+ .filter( s -> s.startsWith("META-INF/")) -+ .sorted() -+ .toArray(String[]::new); -+ if (metas.length > 0) { -+ // meta-inf entries -+ Method getMetas = ZipFile.class.getDeclaredMethod("getMetaInfEntryNames"); -+ getMetas.setAccessible(true); -+ String[] names = (String[])getMetas.invoke(zf); -+ if (names == null) { -+ fail("Failed to get metanames from " + zf); -+ } else { -+ Arrays.sort(names); -+ check(Arrays.equals(names, metas)); -+ } -+ } -+ } -+ -+ private static class Zip { -+ String name; -+ Map entries; -+ BasicFileAttributes attrs; -+ long lastModified; -+ -+ Zip(String name, int num, int szMax, boolean prefix, boolean clean) { -+ this.name = name; -+ entries = new LinkedHashMap<>(num); -+ try { -+ Path p = Paths.get(name); -+ if (clean) { -+ Files.deleteIfExists(p); -+ } -+ paths.add(p); -+ } catch (Exception x) { -+ throw (RuntimeException)x; -+ } -+ -+ try (FileOutputStream fos = new FileOutputStream(name); -+ BufferedOutputStream bos = new BufferedOutputStream(fos); -+ ZipOutputStream zos = new ZipOutputStream(bos)) -+ { -+ if (prefix) { -+ byte[] bytes = new byte[r.nextInt(1000)]; -+ r.nextBytes(bytes); -+ bos.write(bytes); -+ } -+ CRC32 crc = new CRC32(); -+ for (int i = 0; i < num; i++) { -+ String ename = "entry-" + i + "-name-" + r.nextLong(); -+ ZipEntry ze = new ZipEntry(ename); -+ int method = r.nextBoolean() ? ZipEntry.STORED : ZipEntry.DEFLATED; -+ writeEntry(zos, crc, ze, ZipEntry.STORED, szMax); -+ } -+ // add some manifest entries -+ for (int i = 0; i < r.nextInt(20); i++) { -+ String meta = "META-INF/" + "entry-" + i + "-metainf-" + r.nextLong(); -+ ZipEntry ze = new ZipEntry(meta); -+ writeEntry(zos, crc, ze, ZipEntry.STORED, szMax); -+ } -+ } catch (Exception x) { -+ throw (RuntimeException)x; -+ } -+ try { -+ this.attrs = Files.readAttributes(Paths.get(name), BasicFileAttributes.class); -+ this.lastModified = new File(name).lastModified(); -+ } catch (Exception x) { -+ throw (RuntimeException)x; -+ } -+ } -+ -+ private void writeEntry(ZipOutputStream zos, CRC32 crc, -+ ZipEntry ze, int method, int szMax) -+ throws IOException -+ { -+ ze.setMethod(method); -+ byte[] data = new byte[r.nextInt(szMax + 1)]; -+ r.nextBytes(data); -+ if (method == ZipEntry.STORED) { // must set size/csize/crc -+ ze.setSize(data.length); -+ ze.setCompressedSize(data.length); -+ crc.reset(); -+ crc.update(data); -+ ze.setCrc(crc.getValue()); -+ } -+ ze.setTime(System.currentTimeMillis()); -+ ze.setComment(ze.getName()); -+ zos.putNextEntry(ze); -+ zos.write(data); -+ zos.closeEntry(); -+ entries.put(ze, data); -+ } -+ } -+ -+ //--------------------- Infrastructure --------------------------- -+ static volatile int passed = 0, failed = 0; -+ static void pass() {passed++;} -+ static void pass(String msg) {System.out.println(msg); passed++;} -+ static void fail() {failed++; Thread.dumpStack();} -+ static void fail(String msg) {System.out.println(msg); fail();} -+ static void unexpected(Throwable t) {failed++; t.printStackTrace();} -+ static void unexpected(Throwable t, String msg) { -+ System.out.println(msg); failed++; t.printStackTrace();} -+ static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;} -+ -+ public static void main(String[] args) throws Throwable { -+ try {realMain(args);} catch (Throwable t) {unexpected(t);} -+ System.out.println("\nPassed = " + passed + " failed = " + failed); -+ if (failed > 0) throw new AssertionError("Some tests failed");} -+} -\ No newline at end of file -diff --git a/jdk/test/javax/imageio/plugins/png/ItxtUtf8Test.java b/jdk/test/javax/imageio/plugins/png/ItxtUtf8Test.java -index 89853c639..74938bcda 100644 ---- a/jdk/test/javax/imageio/plugins/png/ItxtUtf8Test.java -+++ b/jdk/test/javax/imageio/plugins/png/ItxtUtf8Test.java -@@ -30,7 +30,7 @@ - * - * @run main ItxtUtf8Test - * -- * @run main/othervm/timeout=10 -Xmx2m ItxtUtf8Test truncate -+ * @run main/othervm/timeout=10 -Xmx4m ItxtUtf8Test truncate - */ - - import java.awt.image.BufferedImage; --- -2.22.0 - diff --git a/add-8146431-j.u.z.ZipFile.getEntry-throws-AIOOBE.patch b/add-8146431-j.u.z.ZipFile.getEntry-throws-AIOOBE.patch deleted file mode 100644 index 4c466e90a13a344e48f1eac26b563063c6918e42..0000000000000000000000000000000000000000 --- a/add-8146431-j.u.z.ZipFile.getEntry-throws-AIOOBE.patch +++ /dev/null @@ -1,52 +0,0 @@ -From b6a24b666a1c7536e35afaba4057cc8eac6fe48f Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:25:03 +0800 -Subject: add 8146431-j.u.z.ZipFile.getEntry-throws-AIOOBE - ---- - jdk/src/share/classes/java/util/zip/ZipFile.java | 2 +- - jdk/test/java/util/zip/ZipFile/TestZipFile.java | 9 ++++++++- - 2 files changed, 9 insertions(+), 2 deletions(-) - -diff --git a/jdk/src/share/classes/java/util/zip/ZipFile.java b/jdk/src/share/classes/java/util/zip/ZipFile.java -index 38b642bdc..36135a9c0 100644 ---- a/jdk/src/share/classes/java/util/zip/ZipFile.java -+++ b/jdk/src/share/classes/java/util/zip/ZipFile.java -@@ -1313,7 +1313,7 @@ class ZipFile implements ZipConstants, Closeable { - idx = getEntryNext(idx); - } - /* If not addSlash, or slash is already there, we are done */ -- if (!addSlash || name[name.length - 1] == '/') { -+ if (!addSlash || name.length == 0 || name[name.length - 1] == '/') { - return -1; - } - // Add a slash to the hash code -diff --git a/jdk/test/java/util/zip/ZipFile/TestZipFile.java b/jdk/test/java/util/zip/ZipFile/TestZipFile.java -index 30bae3bb9..773f47558 100644 ---- a/jdk/test/java/util/zip/ZipFile/TestZipFile.java -+++ b/jdk/test/java/util/zip/ZipFile/TestZipFile.java -@@ -24,7 +24,7 @@ - - /* - * @test -- * @bug 8142508 -+ * @bug 8142508 8146431 - * @summary Tests various ZipFile apis - * @run main/manual TestZipFile - */ -@@ -230,6 +230,13 @@ public class TestZipFile { - } - - static void doTest0(Zip zip, ZipFile zf) throws Throwable { -+ // (0) check zero-length entry name, no AIOOBE -+ try { -+ check(zf.getEntry("") == null);; -+ } catch (Throwable t) { -+ unexpected(t); -+ } -+ - List list = new ArrayList(zip.entries.keySet()); - // (1) check entry list, in expected order - if (!check(Arrays.equals( --- -2.22.0 - diff --git a/add-8147940-Modify-testcase-this-test-does-not-assum.patch b/add-8147940-Modify-testcase-this-test-does-not-assum.patch deleted file mode 100644 index 5a45309f2fea493c7188c5a2307c174f3b8fcce0..0000000000000000000000000000000000000000 --- a/add-8147940-Modify-testcase-this-test-does-not-assum.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 40b88d64b144bd1b94b2a887c132ec88b3a9a39d Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:26:13 +0800 -Subject: add 8147940-Modify-testcase-this-test-does-not-assume-th - ---- - ...stG1TraceEagerReclaimHumongousObjects.java | 45 +------------------ - 1 file changed, 1 insertion(+), 44 deletions(-) - -diff --git a/hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java b/hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java -index e653554c9..aca54daf6 100644 ---- a/hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java -+++ b/hotspot/test/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2014, 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 -@@ -36,36 +36,6 @@ import java.util.LinkedList; - - public class TestG1TraceEagerReclaimHumongousObjects { - public static void main(String[] args) throws Exception { -- testGCLogs(); -- testHumongousObjectGCLogs(); -- } -- -- private static void testGCLogs() throws Exception { -- -- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", -- "-Xms128M", -- "-Xmx128M", -- "-Xmn16M", -- "-XX:G1HeapRegionSize=1M", -- "-XX:+PrintGC", -- "-XX:+UnlockExperimentalVMOptions", -- "-XX:G1LogLevel=finest", -- "-XX:+G1TraceEagerReclaimHumongousObjects", -- GCTest.class.getName()); -- -- OutputAnalyzer output = new OutputAnalyzer(pb.start()); -- -- // As G1EagerReclaimHumongousObjects is set(default), below logs should be displayed. -- // And GCTest doesn't have humongous objects, so values should be zero. -- output.shouldContain("[Humongous Reclaim"); -- output.shouldContain("[Humongous Total: 0]"); -- output.shouldContain("[Humongous Candidate: 0]"); -- output.shouldContain("[Humongous Reclaimed: 0]"); -- -- output.shouldHaveExitValue(0); -- } -- -- private static void testHumongousObjectGCLogs() throws Exception { - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", - "-Xms128M", - "-Xmx128M", -@@ -92,19 +62,6 @@ public class TestG1TraceEagerReclaimHumongousObjects { - output.shouldHaveExitValue(0); - } - -- static class GCTest { -- private static byte[] garbage; -- -- public static void main(String [] args) { -- System.out.println("Creating garbage"); -- // create 128MB of garbage. This should result in at least one GC -- for (int i = 0; i < 1024; i++) { -- garbage = new byte[128 * 1024]; -- } -- System.out.println("Done"); -- } -- } -- - static class GCWithHumongousObjectTest { - - public static final int M = 1024*1024; --- -2.22.0 - diff --git a/add-8170831-ZipFile-implementation-no-longer-caches-.patch b/add-8170831-ZipFile-implementation-no-longer-caches-.patch deleted file mode 100644 index 4a7be7e2b43d5b7f7f672d4e172913a4165ec09d..0000000000000000000000000000000000000000 --- a/add-8170831-ZipFile-implementation-no-longer-caches-.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 8e3e20eef3f18d023ffc327a9fae30c34de84773 Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:24:45 +0800 -Subject: add 8170831-ZipFile-implementation-no-longer-caches-the - ---- - jdk/src/share/classes/java/util/zip/ZipFile.java | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - -diff --git a/jdk/src/share/classes/java/util/zip/ZipFile.java b/jdk/src/share/classes/java/util/zip/ZipFile.java -index b6a6c2a48..38b642bdc 100644 ---- a/jdk/src/share/classes/java/util/zip/ZipFile.java -+++ b/jdk/src/share/classes/java/util/zip/ZipFile.java -@@ -342,7 +342,9 @@ class ZipFile implements ZipConstants, Closeable { - ZipFileInputStream in = null; - synchronized (this) { - ensureOpen(); -- if (!zc.isUTF8() && (entry.flag & EFS) != 0) { -+ if (Objects.equals(lastEntryName, entry.name)) { -+ pos = lastEntryPos; -+ } else if (!zc.isUTF8() && (entry.flag & EFS) != 0) { - pos = zsrc.getEntryPos(zc.getBytesUTF8(entry.name), false); - } else { - pos = zsrc.getEntryPos(zc.getBytes(entry.name), false); -@@ -533,6 +535,9 @@ class ZipFile implements ZipConstants, Closeable { - Spliterator.IMMUTABLE | Spliterator.NONNULL), false); - } - -+ private String lastEntryName; -+ private int lastEntryPos; -+ - /* Checks ensureOpen() before invoke this method */ - private ZipEntry getZipEntry(String name, int pos) { - byte[] cen = zsrc.cen; -@@ -566,6 +571,8 @@ class ZipFile implements ZipConstants, Closeable { - e.comment = zc.toString(cen, start, clen); - } - } -+ lastEntryName = e.name; -+ lastEntryPos = pos; - return e; - } - --- -2.22.0 - diff --git a/add-8191924-Adjust-DelegatingClassLoader-s-metadata-.patch b/add-8191924-Adjust-DelegatingClassLoader-s-metadata-.patch deleted file mode 100644 index 45c255800cf88862ef58d37dfcc5045f88cfd5e0..0000000000000000000000000000000000000000 --- a/add-8191924-Adjust-DelegatingClassLoader-s-metadata-.patch +++ /dev/null @@ -1,100 +0,0 @@ -From 64123e7422fb9441c8999aaa1ddfdf639295fea1 Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:26:33 +0800 -Subject: add 8191924-Adjust-DelegatingClassLoader-s-metadata-spac - ---- - hotspot/src/share/vm/memory/metaspace.cpp | 31 ++++++++++++++++++++--- - 1 file changed, 28 insertions(+), 3 deletions(-) - -diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp -index 07259e649..d65a81267 100644 ---- a/hotspot/src/share/vm/memory/metaspace.cpp -+++ b/hotspot/src/share/vm/memory/metaspace.cpp -@@ -1206,7 +1206,10 @@ class SpaceManager : public CHeapObj { - Mutex* const _lock; - - // Type of metadata allocated. -- Metaspace::MetadataType _mdtype; -+ const Metaspace::MetadataType _mdtype; -+ -+ // Type of metaspace -+ const Metaspace::MetaspaceType _space_type; - - // List of chunks in use by this SpaceManager. Allocations - // are done from the current chunk. The list is used for deallocating -@@ -1218,6 +1221,10 @@ class SpaceManager : public CHeapObj { - // If class space manager, small chunks are unlimited - static uint const _small_chunk_limit; - -+ // Maximum number of specialize chunks to allocate for anonymous and delegating -+ // metadata space to a SpaceManager -+ static uint const _anon_and_delegating_metadata_specialize_chunk_limit; -+ - // Sum of all space in allocated chunks - size_t _allocated_blocks_words; - -@@ -1270,6 +1277,7 @@ class SpaceManager : public CHeapObj { - - public: - SpaceManager(Metaspace::MetadataType mdtype, -+ Metaspace::MetaspaceType space_type, - Mutex* lock); - ~SpaceManager(); - -@@ -1385,6 +1393,7 @@ class SpaceManager : public CHeapObj { - }; - - uint const SpaceManager::_small_chunk_limit = 4; -+uint const SpaceManager::_anon_and_delegating_metadata_specialize_chunk_limit = 4; - - const char* SpaceManager::_expand_lock_name = - "SpaceManager chunk allocation lock"; -@@ -3409,6 +3418,20 @@ size_t SpaceManager::calc_chunk_size(size_t word_size) { - // once a medium chunk has been allocated, no more small - // chunks will be allocated. - size_t chunk_word_size; -+ -+ // Special case for anonymous metadata space. -+ // Anonymous metadata space is usually small, with majority within 1K - 2K range and -+ // rarely about 4K (64-bits JVM). -+ // Instead of jumping to SmallChunk after initial chunk exhausted, keeping allocation -+ // from SpecializeChunk up to _anon_or_delegating_metadata_specialize_chunk_limit (4) -+ // reduces space waste from 60+% to around 30%. -+ if ((_space_type == Metaspace::AnonymousMetaspaceType || _space_type == Metaspace::ReflectionMetaspaceType) && -+ _mdtype == Metaspace::NonClassType && -+ sum_count_in_chunks_in_use(SpecializedIndex) < _anon_and_delegating_metadata_specialize_chunk_limit && -+ word_size + Metachunk::overhead() <= SpecializedChunk) { -+ return SpecializedChunk; -+ } -+ - if (chunks_in_use(MediumIndex) == NULL && - sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) { - chunk_word_size = (size_t) small_chunk_size(); -@@ -3517,8 +3540,10 @@ void SpaceManager::print_on(outputStream* st) const { - } - - SpaceManager::SpaceManager(Metaspace::MetadataType mdtype, -+ Metaspace::MetaspaceType space_type, - Mutex* lock) : - _mdtype(mdtype), -+ _space_type(space_type), - _allocated_blocks_words(0), - _allocated_chunks_words(0), - _allocated_chunks_count(0), -@@ -4926,11 +4951,11 @@ void Metaspace::initialize(Mutex* lock, MetaspaceType type) { - verify_global_initialization(); - - // Allocate SpaceManager for metadata objects. -- _vsm = new SpaceManager(NonClassType, lock); -+ _vsm = new SpaceManager(NonClassType, type, lock); - - if (using_class_space()) { - // Allocate SpaceManager for classes. -- _class_vsm = new SpaceManager(ClassType, lock); -+ _class_vsm = new SpaceManager(ClassType, type, lock); - } else { - _class_vsm = NULL; - } --- -2.22.0 - diff --git a/add-8198423-Improve-metaspace-chunk-allocation.patch b/add-8198423-Improve-metaspace-chunk-allocation.patch deleted file mode 100644 index 4a33cdeb2d0cef50a66513dd37bd30453aff5b58..0000000000000000000000000000000000000000 --- a/add-8198423-Improve-metaspace-chunk-allocation.patch +++ /dev/null @@ -1,2770 +0,0 @@ -From 0ec0400ef6367812d4f256468ea2adda569baaff Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:16:04 +0800 -Subject: add 8198423-Improve-metaspace-chunk-allocation - ---- - hotspot/src/share/vm/memory/metachunk.cpp | 93 +- - hotspot/src/share/vm/memory/metachunk.hpp | 93 +- - hotspot/src/share/vm/memory/metaspace.cpp | 1808 ++++++++++++++--- - hotspot/src/share/vm/memory/metaspace.hpp | 18 +- - hotspot/src/share/vm/prims/jni.cpp | 4 +- - .../share/vm/utilities/globalDefinitions.hpp | 1 + - 6 files changed, 1742 insertions(+), 275 deletions(-) - -diff --git a/hotspot/src/share/vm/memory/metachunk.cpp b/hotspot/src/share/vm/memory/metachunk.cpp -index 6cb6625b1..50d0c97eb 100644 ---- a/hotspot/src/share/vm/memory/metachunk.cpp -+++ b/hotspot/src/share/vm/memory/metachunk.cpp -@@ -25,6 +25,7 @@ - #include "precompiled.hpp" - #include "memory/allocation.hpp" - #include "memory/metachunk.hpp" -+#include "utilities/align.hpp" - #include "utilities/copy.hpp" - #include "utilities/debug.hpp" - -@@ -32,8 +33,6 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC - - class VirtualSpaceNode; - --const size_t metadata_chunk_initialize = 0xf7f7f7f7; -- - size_t Metachunk::object_alignment() { - // Must align pointers and sizes to 8, - // so that 64 bit types get correctly aligned. -@@ -51,21 +50,22 @@ size_t Metachunk::overhead() { - - // Metachunk methods - --Metachunk::Metachunk(size_t word_size, -+Metachunk::Metachunk(ChunkIndex chunktype, bool is_class, size_t word_size, - VirtualSpaceNode* container) - : Metabase(word_size), -+ _chunk_type(chunktype), -+ _is_class(is_class), -+ _sentinel(CHUNK_SENTINEL), -+ _origin(origin_normal), -+ _use_count(0), - _top(NULL), - _container(container) - { - _top = initial_top(); --#ifdef ASSERT - set_is_tagged_free(false); -- size_t data_word_size = pointer_delta(end(), -- _top, -- sizeof(MetaWord)); -- Copy::fill_to_words((HeapWord*)_top, -- data_word_size, -- metadata_chunk_initialize); -+#ifdef ASSERT -+ mangle(uninitMetaWordVal); -+ verify(); - #endif - } - -@@ -91,33 +91,63 @@ size_t Metachunk::free_word_size() const { - void Metachunk::print_on(outputStream* st) const { - st->print_cr("Metachunk:" - " bottom " PTR_FORMAT " top " PTR_FORMAT -- " end " PTR_FORMAT " size " SIZE_FORMAT, -- bottom(), _top, end(), word_size()); -+ " end " PTR_FORMAT " size " SIZE_FORMAT " (%s)", -+ bottom(), _top, end(), word_size(), -+ chunk_size_name(get_chunk_type())); - if (Verbose) { - st->print_cr(" used " SIZE_FORMAT " free " SIZE_FORMAT, - used_word_size(), free_word_size()); - } - } - --#ifndef PRODUCT --void Metachunk::mangle() { -- // Mangle the payload of the chunk and not the links that -+#ifdef ASSERT -+void Metachunk::mangle(juint word_value) { -+ // Overwrite the payload of the chunk and not the links that - // maintain list of chunks. -- HeapWord* start = (HeapWord*)(bottom() + overhead()); -+ HeapWord* start = (HeapWord*)initial_top(); - size_t size = word_size() - overhead(); -- Copy::fill_to_words(start, size, metadata_chunk_initialize); -+ Copy::fill_to_words(start, size, word_value); - } --#endif // PRODUCT - - void Metachunk::verify() { --#ifdef ASSERT -- // Cannot walk through the blocks unless the blocks have -- // headers with sizes. -- assert(bottom() <= _top && -- _top <= (MetaWord*)end(), -- "Chunk has been smashed"); --#endif -- return; -+ assert(is_valid_sentinel(), err_msg("Chunk " PTR_FORMAT ": sentinel invalid", p2i(this))); -+ const ChunkIndex chunk_type = get_chunk_type(); -+ assert(is_valid_chunktype(chunk_type), err_msg("Chunk " PTR_FORMAT ": Invalid chunk type.", p2i(this))); -+ if (chunk_type != HumongousIndex) { -+ assert(word_size() == get_size_for_nonhumongous_chunktype(chunk_type, is_class()), -+ err_msg("Chunk " PTR_FORMAT ": wordsize " SIZE_FORMAT " does not fit chunk type %s.", -+ p2i(this), word_size(), chunk_size_name(chunk_type))); -+ } -+ assert(is_valid_chunkorigin(get_origin()), err_msg("Chunk " PTR_FORMAT ": Invalid chunk origin.", p2i(this))); -+ assert(bottom() <= _top && _top <= (MetaWord*)end(), -+ err_msg("Chunk " PTR_FORMAT ": Chunk top out of chunk bounds.", p2i(this))); -+ -+ // For non-humongous chunks, starting address shall be aligned -+ // to its chunk size. Humongous chunks start address is -+ // aligned to specialized chunk size. -+ const size_t required_alignment = -+ (chunk_type != HumongousIndex ? word_size() : get_size_for_nonhumongous_chunktype(SpecializedIndex, is_class())) * sizeof(MetaWord); -+ assert(is_aligned((address)this, required_alignment), -+ err_msg("Chunk " PTR_FORMAT ": (size " SIZE_FORMAT ") not aligned to " SIZE_FORMAT ".", -+ p2i(this), word_size() * sizeof(MetaWord), required_alignment)); -+} -+ -+#endif // ASSERT -+ -+// Helper, returns a descriptive name for the given index. -+const char* chunk_size_name(ChunkIndex index) { -+ switch (index) { -+ case SpecializedIndex: -+ return "specialized"; -+ case SmallIndex: -+ return "small"; -+ case MediumIndex: -+ return "medium"; -+ case HumongousIndex: -+ return "humongous"; -+ default: -+ return "Invalid index"; -+ } - } - - /////////////// Unit tests /////////////// -@@ -127,11 +157,16 @@ void Metachunk::verify() { - class TestMetachunk { - public: - static void test() { -- size_t size = 2 * 1024 * 1024; -- void* memory = malloc(size); -+ const ChunkIndex chunk_type = MediumIndex; -+ const bool is_class = false; -+ const size_t word_size = get_size_for_nonhumongous_chunktype(chunk_type, is_class); -+ // Allocate the chunk with correct alignment. -+ void* memory = malloc(word_size * BytesPerWord * 2); - assert(memory != NULL, "Failed to malloc 2MB"); -+ -+ void* p_placement = align_up(memory, word_size * BytesPerWord); - -- Metachunk* metachunk = ::new (memory) Metachunk(size / BytesPerWord, NULL); -+ Metachunk* metachunk = ::new (p_placement) Metachunk(chunk_type, is_class, word_size, NULL); - - assert(metachunk->bottom() == (MetaWord*)metachunk, "assert"); - assert(metachunk->end() == (uintptr_t*)metachunk + metachunk->size(), "assert"); -diff --git a/hotspot/src/share/vm/memory/metachunk.hpp b/hotspot/src/share/vm/memory/metachunk.hpp -index 7889b622c..b679f1b1e 100644 ---- a/hotspot/src/share/vm/memory/metachunk.hpp -+++ b/hotspot/src/share/vm/memory/metachunk.hpp -@@ -94,6 +94,61 @@ class Metabase VALUE_OBJ_CLASS_SPEC { - // | | | | - // +--------------+ <- bottom --+ --+ - -+// ChunkIndex defines the type of chunk. -+// Chunk types differ by size: specialized < small < medium, chunks -+// larger than medium are humongous chunks of varying size. -+enum ChunkIndex { -+ ZeroIndex = 0, -+ SpecializedIndex = ZeroIndex, -+ SmallIndex = SpecializedIndex + 1, -+ MediumIndex = SmallIndex + 1, -+ HumongousIndex = MediumIndex + 1, -+ NumberOfFreeLists = 3, -+ NumberOfInUseLists = 4 -+}; -+ -+// Utility functions. -+size_t get_size_for_nonhumongous_chunktype(ChunkIndex chunk_type, bool is_class); -+ChunkIndex get_chunk_type_by_size(size_t size, bool is_class); -+ -+// Returns a descriptive name for a chunk type. -+const char* chunk_size_name(ChunkIndex index); -+ -+// Verify chunk type. -+inline bool is_valid_chunktype(ChunkIndex index) { -+ return index == SpecializedIndex || index == SmallIndex || -+ index == MediumIndex || index == HumongousIndex; -+} -+ -+inline bool is_valid_nonhumongous_chunktype(ChunkIndex index) { -+ return is_valid_chunktype(index) && index != HumongousIndex; -+} -+ -+enum ChunkOrigin { -+ // Chunk normally born (via take_from_committed) -+ origin_normal = 1, -+ // Chunk was born as padding chunk -+ origin_pad = 2, -+ // Chunk was born as leftover chunk in VirtualSpaceNode::retire -+ origin_leftover = 3, -+ // Chunk was born as result of a merge of smaller chunks -+ origin_merge = 4, -+ // Chunk was born as result of a split of a larger chunk -+ origin_split = 5, -+ -+ origin_minimum = origin_normal, -+ origin_maximum = origin_split, -+ origins_count = origin_maximum + 1 -+}; -+ -+inline bool is_valid_chunkorigin(ChunkOrigin origin) { -+ return origin == origin_normal || -+ origin == origin_pad || -+ origin == origin_leftover || -+ origin == origin_merge || -+ origin == origin_split; -+} -+ - class Metachunk : public Metabase { - friend class TestMetachunk; - // The VirtualSpaceNode containing this chunk. -@@ -102,8 +157,21 @@ class Metachunk : public Metabase { - // Current allocation top. - MetaWord* _top; - -- DEBUG_ONLY(bool _is_tagged_free;) -+ // A 32bit sentinel for debugging purposes. -+ enum { CHUNK_SENTINEL = 0x4d4554EF, // "MET" -+ CHUNK_SENTINEL_INVALID = 0xFEEEEEEF -+ }; -+ -+ uint32_t _sentinel; - -+ const ChunkIndex _chunk_type; -+ const bool _is_class; -+ // Whether the chunk is free (in freelist) or in use by some class loader. -+ bool _is_tagged_free; -+ -+ ChunkOrigin _origin; -+ int _use_count; -+ - MetaWord* initial_top() const { return (MetaWord*)this + overhead(); } - MetaWord* top() const { return _top; } - -@@ -120,7 +188,7 @@ class Metachunk : public Metabase { - // Size of the Metachunk header, including alignment. - static size_t overhead(); - -- Metachunk(size_t word_size , VirtualSpaceNode* container); -+ Metachunk(ChunkIndex chunktype, bool is_class, size_t word_size, VirtualSpaceNode* container); - - MetaWord* allocate(size_t word_size); - -@@ -140,17 +208,28 @@ class Metachunk : public Metabase { - size_t used_word_size() const; - size_t free_word_size() const; - --#ifdef ASSERT - bool is_tagged_free() { return _is_tagged_free; } - void set_is_tagged_free(bool v) { _is_tagged_free = v; } --#endif - - bool contains(const void* ptr) { return bottom() <= ptr && ptr < _top; } - -- NOT_PRODUCT(void mangle();) -- - void print_on(outputStream* st) const; -- void verify(); -+ -+ bool is_valid_sentinel() const { return _sentinel == CHUNK_SENTINEL; } -+ void remove_sentinel() { _sentinel = CHUNK_SENTINEL_INVALID; } -+ -+ int get_use_count() const { return _use_count; } -+ void inc_use_count() { _use_count ++; } -+ -+ ChunkOrigin get_origin() const { return _origin; } -+ void set_origin(ChunkOrigin orig) { _origin = orig; } -+ -+ ChunkIndex get_chunk_type() const { return _chunk_type; } -+ bool is_class() const { return _is_class; } -+ -+ DEBUG_ONLY(void mangle(juint word_value);) -+ DEBUG_ONLY(void verify();) -+ - }; - - // Metablock is the unit of allocation from a Chunk. -diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp -index cc5bd4544..07259e649 100644 ---- a/hotspot/src/share/vm/memory/metaspace.cpp -+++ b/hotspot/src/share/vm/memory/metaspace.cpp -@@ -46,6 +46,7 @@ - #include "runtime/orderAccess.inline.hpp" - #include "services/memTracker.hpp" - #include "services/memoryService.hpp" -+#include "utilities/align.hpp" - #include "utilities/copy.hpp" - #include "utilities/debug.hpp" - -@@ -57,6 +58,13 @@ typedef BinaryTreeDictionary > ChunkTreeDictionar - // Set this constant to enable slow integrity checking of the free chunk lists - const bool metaspace_slow_verify = false; - -+// Helper function that does a bunch of checks for a chunk. -+DEBUG_ONLY(static void do_verify_chunk(Metachunk* chunk);) -+ -+// Given a Metachunk, update its in-use information (both in the -+// chunk and the occupancy map). -+static void do_update_in_use_info_for_chunk(Metachunk* chunk, bool inuse); -+ - size_t const allocation_from_dictionary_limit = 4 * K; - - MetaWord* last_allocated = 0; -@@ -64,33 +72,6 @@ MetaWord* last_allocated = 0; - size_t Metaspace::_compressed_class_space_size; - const MetaspaceTracer* Metaspace::_tracer = NULL; - --// Used in declarations in SpaceManager and ChunkManager --enum ChunkIndex { -- ZeroIndex = 0, -- SpecializedIndex = ZeroIndex, -- SmallIndex = SpecializedIndex + 1, -- MediumIndex = SmallIndex + 1, -- HumongousIndex = MediumIndex + 1, -- NumberOfFreeLists = 3, -- NumberOfInUseLists = 4 --}; -- --// Helper, returns a descriptive name for the given index. --static const char* chunk_size_name(ChunkIndex index) { -- switch (index) { -- case SpecializedIndex: -- return "specialized"; -- case SmallIndex: -- return "small"; -- case MediumIndex: -- return "medium"; -- case HumongousIndex: -- return "humongous"; -- default: -- return "Invalid index"; -- } --} -- - enum ChunkSizes { // in words. - ClassSpecializedChunk = 128, - SpecializedChunk = 128, -@@ -100,11 +81,69 @@ enum ChunkSizes { // in words. - MediumChunk = 8 * K - }; - -+// Returns size of this chunk type. -+size_t get_size_for_nonhumongous_chunktype(ChunkIndex chunktype, bool is_class) { -+ assert(is_valid_nonhumongous_chunktype(chunktype), "invalid chunk type."); -+ size_t size = 0; -+ if (is_class) { -+ switch(chunktype) { -+ case SpecializedIndex: size = ClassSpecializedChunk; break; -+ case SmallIndex: size = ClassSmallChunk; break; -+ case MediumIndex: size = ClassMediumChunk; break; -+ default: -+ ShouldNotReachHere(); -+ } -+ } else { -+ switch(chunktype) { -+ case SpecializedIndex: size = SpecializedChunk; break; -+ case SmallIndex: size = SmallChunk; break; -+ case MediumIndex: size = MediumChunk; break; -+ default: -+ ShouldNotReachHere(); -+ } -+ } -+ return size; -+} -+ -+ChunkIndex get_chunk_type_by_size(size_t size, bool is_class) { -+ if (is_class) { -+ if (size == ClassSpecializedChunk) { -+ return SpecializedIndex; -+ } else if (size == ClassSmallChunk) { -+ return SmallIndex; -+ } else if (size == ClassMediumChunk) { -+ return MediumIndex; -+ } else if (size > ClassMediumChunk) { -+ assert(is_aligned(size, ClassSpecializedChunk), "Invalid chunk size"); -+ return HumongousIndex; -+ } -+ } else { -+ if (size == SpecializedChunk) { -+ return SpecializedIndex; -+ } else if (size == SmallChunk) { -+ return SmallIndex; -+ } else if (size == MediumChunk) { -+ return MediumIndex; -+ } else if (size > MediumChunk) { -+ assert(is_aligned(size, SpecializedChunk), "Invalid chunk size"); -+ return HumongousIndex; -+ } -+ } -+ ShouldNotReachHere(); -+ return (ChunkIndex)-1; -+} -+ -+ - static ChunkIndex next_chunk_index(ChunkIndex i) { - assert(i < NumberOfInUseLists, "Out of bound"); - return (ChunkIndex) (i+1); - } - -+static ChunkIndex prev_chunk_index(ChunkIndex i) { -+ assert(i > ZeroIndex, "Out of bound"); -+ return (ChunkIndex) (i-1); -+} -+ - static const char* scale_unit(size_t scale) { - switch(scale) { - case 1: return "BYTES"; -@@ -131,24 +170,33 @@ class ChunkManager : public CHeapObj { - // SpecializedChunk - // SmallChunk - // MediumChunk -- // HumongousChunk - ChunkList _free_chunks[NumberOfFreeLists]; - -+ // Whether or not this is the class chunkmanager. -+ const bool _is_class; -+ -+ // Return non-humongous chunk list by its index. -+ ChunkList* free_chunks(ChunkIndex index); -+ -+ // Returns non-humongous chunk list for the given chunk word size. -+ ChunkList* find_free_chunks_list(size_t word_size); -+ - // HumongousChunk - ChunkTreeDictionary _humongous_dictionary; - -- // ChunkManager in all lists of this type -+ // Returns the humongous chunk dictionary. -+ ChunkTreeDictionary* humongous_dictionary() { -+ return &_humongous_dictionary; -+ } -+ -+ // Size, in metaspace words, of all chunks managed by this ChunkManager - size_t _free_chunks_total; -+ // Number of chunks in this ChunkManager - size_t _free_chunks_count; - -- void dec_free_chunks_total(size_t v) { -- assert(_free_chunks_count > 0 && -- _free_chunks_total > 0, -- "About to go negative"); -- Atomic::add_ptr(-1, &_free_chunks_count); -- jlong minus_v = (jlong) - (jlong) v; -- Atomic::add_ptr(minus_v, &_free_chunks_total); -- } -+ // Update counters after a chunk was added or removed removed. -+ void account_for_added_chunk(const Metachunk* c); -+ void account_for_removed_chunk(const Metachunk* c); - - // Debug support - -@@ -169,6 +217,29 @@ class ChunkManager : public CHeapObj { - } - void verify_free_chunks_count(); - -+ // Given a pointer to a chunk, attempts to merge it with neighboring -+ // free chunks to form a bigger chunk. Returns true if successful. -+ bool attempt_to_coalesce_around_chunk(Metachunk* chunk, ChunkIndex target_chunk_type); -+ -+ // Helper for chunk merging: -+ // Given an address range with 1-n chunks which are all supposed to be -+ // free and hence currently managed by this ChunkManager, remove them -+ // from this ChunkManager and mark them as invalid. -+ // - This does not correct the occupancy map. -+ // - This does not adjust the counters in ChunkManager. -+ // - Does not adjust container count counter in containing VirtualSpaceNode. -+ // Returns number of chunks removed. -+ int remove_chunks_in_area(MetaWord* p, size_t word_size); -+ -+ // Helper for chunk splitting: given a target chunk size and a larger free chunk, -+ // split up the larger chunk into n smaller chunks, at least one of which should be -+ // the target chunk of target chunk size. The smaller chunks, including the target -+ // chunk, are returned to the freelist. The pointer to the target chunk is returned. -+ // Note that this chunk is supposed to be removed from the freelist right away. -+ Metachunk* split_chunk(size_t target_chunk_word_size, Metachunk* chunk); -+ -+ public: -+ - struct ChunkManagerStatistics { - size_t num_by_type[NumberOfFreeLists]; - size_t single_size_by_type[NumberOfFreeLists]; -@@ -181,16 +252,15 @@ class ChunkManager : public CHeapObj { - void get_statistics(ChunkManagerStatistics* stat) const; - static void print_statistics(const ChunkManagerStatistics* stat, outputStream* out, size_t scale); - -- public: - -- ChunkManager(size_t specialized_size, size_t small_size, size_t medium_size) -- : _free_chunks_total(0), _free_chunks_count(0) { -- _free_chunks[SpecializedIndex].set_size(specialized_size); -- _free_chunks[SmallIndex].set_size(small_size); -- _free_chunks[MediumIndex].set_size(medium_size); -+ ChunkManager(bool is_class) -+ : _is_class(is_class), _free_chunks_total(0), _free_chunks_count(0) { -+ _free_chunks[SpecializedIndex].set_size(get_size_for_nonhumongous_chunktype(SpecializedIndex, is_class)); -+ _free_chunks[SmallIndex].set_size(get_size_for_nonhumongous_chunktype(SmallIndex, is_class)); -+ _free_chunks[MediumIndex].set_size(get_size_for_nonhumongous_chunktype(MediumIndex, is_class)); - } - -- // add or delete (return) a chunk to the global freelist. -+ // Add or delete (return) a chunk to the global freelist. - Metachunk* chunk_freelist_allocate(size_t word_size); - - // Map a size to a list index assuming that there are lists -@@ -200,13 +270,24 @@ class ChunkManager : public CHeapObj { - // Map a given index to the chunk size. - size_t size_by_index(ChunkIndex index) const; - -- // Remove the chunk from its freelist. It is -- // expected to be on one of the _free_chunks[] lists. -+ bool is_class() const { return _is_class; } -+ -+ // Convenience accessors. -+ size_t medium_chunk_word_size() const { return size_by_index(MediumIndex); } -+ size_t small_chunk_word_size() const { return size_by_index(SmallIndex); } -+ size_t specialized_chunk_word_size() const { return size_by_index(SpecializedIndex); } -+ -+ // Take a chunk from the ChunkManager. The chunk is expected to be in -+ // the chunk manager (the freelist if non-humongous, the dictionary if -+ // humongous). - void remove_chunk(Metachunk* chunk); - -+ // Return a single chunk of type index to the ChunkManager. -+ void return_single_chunk(ChunkIndex index, Metachunk* chunk); -+ - // Add the simple linked list of chunks to the freelist of chunks - // of type index. -- void return_chunks(ChunkIndex index, Metachunk* chunks); -+ void return_chunk_list(ChunkIndex index, Metachunk* chunk); - - // Total of the space in the free chunks list - size_t free_chunks_total_words(); -@@ -215,19 +296,6 @@ class ChunkManager : public CHeapObj { - // Number of chunks in the free chunks list - size_t free_chunks_count(); - -- void inc_free_chunks_total(size_t v, size_t count = 1) { -- Atomic::add_ptr(count, &_free_chunks_count); -- Atomic::add_ptr(v, &_free_chunks_total); -- } -- ChunkTreeDictionary* humongous_dictionary() { -- return &_humongous_dictionary; -- } -- -- ChunkList* free_chunks(ChunkIndex index); -- -- // Returns the list for the given chunk word size. -- ChunkList* find_free_chunks_list(size_t word_size); -- - // Remove from a list by size. Selects list based on size of chunk. - Metachunk* free_chunks_get(size_t chunk_word_size); - -@@ -329,6 +397,294 @@ class BlockFreelist VALUE_OBJ_CLASS_SPEC { - void print_on(outputStream* st) const; - }; - -+// Helper for Occupancy Bitmap. A type trait to give an all-bits-are-one-unsigned constant. -+template struct all_ones { static const T value; }; -+template <> struct all_ones { static const uint64_t value = 0xFFFFFFFFFFFFFFFFULL; }; -+template <> struct all_ones { static const uint32_t value = 0xFFFFFFFF; }; -+ -+// The OccupancyMap is a bitmap which, for a given VirtualSpaceNode, -+// keeps information about -+// - where a chunk starts -+// - whether a chunk is in-use or free -+// A bit in this bitmap represents one range of memory in the smallest -+// chunk size (SpecializedChunk or ClassSpecializedChunk). -+class OccupancyMap : public CHeapObj { -+ -+ // The address range this map covers. -+ const MetaWord* const _reference_address; -+ const size_t _word_size; -+ -+ // The word size of a specialized chunk, aka the number of words one -+ // bit in this map represents. -+ const size_t _smallest_chunk_word_size; -+ -+ // map data -+ // Data are organized in two bit layers: -+ // The first layer is the chunk-start-map. Here, a bit is set to mark -+ // the corresponding region as the head of a chunk. -+ // The second layer is the in-use-map. Here, a set bit indicates that -+ // the corresponding belongs to a chunk which is in use. -+ uint8_t* _map[2]; -+ -+ enum { layer_chunk_start_map = 0, layer_in_use_map = 1 }; -+ -+ // length, in bytes, of bitmap data -+ size_t _map_size; -+ -+ // Returns true if bit at position pos at bit-layer layer is set. -+ bool get_bit_at_position(unsigned pos, unsigned layer) const { -+ assert(layer == 0 || layer == 1, err_msg("Invalid layer %d", layer)); -+ const unsigned byteoffset = pos / 8; -+ assert(byteoffset < _map_size, -+ err_msg("invalid byte offset (%u), map size is " SIZE_FORMAT ".", byteoffset, _map_size)); -+ const unsigned mask = 1 << (pos % 8); -+ return (_map[layer][byteoffset] & mask) > 0; -+ } -+ -+ // Changes bit at position pos at bit-layer layer to value v. -+ void set_bit_at_position(unsigned pos, unsigned layer, bool v) { -+ assert(layer == 0 || layer == 1, err_msg("Invalid layer %d", layer)); -+ const unsigned byteoffset = pos / 8; -+ assert(byteoffset < _map_size, -+ err_msg("invalid byte offset (%u), map size is " SIZE_FORMAT ".", byteoffset, _map_size)); -+ const unsigned mask = 1 << (pos % 8); -+ if (v) { -+ _map[layer][byteoffset] |= mask; -+ } else { -+ _map[layer][byteoffset] &= ~mask; -+ } -+ } -+ -+ // Optimized case of is_any_bit_set_in_region for 32/64bit aligned access: -+ // pos is 32/64 aligned and num_bits is 32/64. -+ // This is the typical case when coalescing to medium chunks, whose size is -+ // 32 or 64 times the specialized chunk size (depending on class or non class -+ // case), so they occupy 64 bits which should be 64bit aligned, because -+ // chunks are chunk-size aligned. -+ template -+ bool is_any_bit_set_in_region_3264(unsigned pos, unsigned num_bits, unsigned layer) const { -+ assert(_map_size > 0, "not initialized"); -+ assert(layer == 0 || layer == 1, err_msg("Invalid layer %d.", layer)); -+ assert(pos % (sizeof(T) * 8) == 0, err_msg("Bit position must be aligned (%u).", pos)); -+ assert(num_bits == (sizeof(T) * 8), err_msg("Number of bits incorrect (%u).", num_bits)); -+ const size_t byteoffset = pos / 8; -+ assert(byteoffset <= (_map_size - sizeof(T)), -+ err_msg("Invalid byte offset (" SIZE_FORMAT "), map size is " SIZE_FORMAT ".", byteoffset, _map_size)); -+ const T w = *(T*)(_map[layer] + byteoffset); -+ return w > 0 ? true : false; -+ } -+ -+ // Returns true if any bit in region [pos1, pos1 + num_bits) is set in bit-layer layer. -+ bool is_any_bit_set_in_region(unsigned pos, unsigned num_bits, unsigned layer) const { -+ if (pos % 32 == 0 && num_bits == 32) { -+ return is_any_bit_set_in_region_3264(pos, num_bits, layer); -+ } else if (pos % 64 == 0 && num_bits == 64) { -+ return is_any_bit_set_in_region_3264(pos, num_bits, layer); -+ } else { -+ for (unsigned n = 0; n < num_bits; n ++) { -+ if (get_bit_at_position(pos + n, layer)) { -+ return true; -+ } -+ } -+ } -+ return false; -+ } -+ -+ // Returns true if any bit in region [p, p+word_size) is set in bit-layer layer. -+ bool is_any_bit_set_in_region(MetaWord* p, size_t word_size, unsigned layer) const { -+ assert(word_size % _smallest_chunk_word_size == 0, -+ err_msg("Region size " SIZE_FORMAT " not a multiple of smallest chunk size.", word_size)); -+ const unsigned pos = get_bitpos_for_address(p); -+ const unsigned num_bits = (unsigned) (word_size / _smallest_chunk_word_size); -+ return is_any_bit_set_in_region(pos, num_bits, layer); -+ } -+ -+ // Optimized case of set_bits_of_region for 32/64bit aligned access: -+ // pos is 32/64 aligned and num_bits is 32/64. -+ // This is the typical case when coalescing to medium chunks, whose size -+ // is 32 or 64 times the specialized chunk size (depending on class or non -+ // class case), so they occupy 64 bits which should be 64bit aligned, -+ // because chunks are chunk-size aligned. -+ template -+ void set_bits_of_region_T(unsigned pos, unsigned num_bits, unsigned layer, bool v) { -+ assert(pos % (sizeof(T) * 8) == 0, err_msg("Bit position must be aligned to %u (%u).", -+ (unsigned)(sizeof(T) * 8), pos)); -+ assert(num_bits == (sizeof(T) * 8), err_msg("Number of bits incorrect (%u), expected %u.", -+ num_bits, (unsigned)(sizeof(T) * 8))); -+ const size_t byteoffset = pos / 8; -+ assert(byteoffset <= (_map_size - sizeof(T)), -+ err_msg("invalid byte offset (" SIZE_FORMAT "), map size is " SIZE_FORMAT ".", byteoffset, _map_size)); -+ T* const pw = (T*)(_map[layer] + byteoffset); -+ *pw = v ? all_ones::value : (T) 0; -+ } -+ -+ // Set all bits in a region starting at pos to a value. -+ void set_bits_of_region(unsigned pos, unsigned num_bits, unsigned layer, bool v) { -+ assert(_map_size > 0, "not initialized"); -+ assert(layer == 0 || layer == 1, err_msg("Invalid layer %d.", layer)); -+ if (pos % 32 == 0 && num_bits == 32) { -+ set_bits_of_region_T(pos, num_bits, layer, v); -+ } else if (pos % 64 == 0 && num_bits == 64) { -+ set_bits_of_region_T(pos, num_bits, layer, v); -+ } else { -+ for (unsigned n = 0; n < num_bits; n ++) { -+ set_bit_at_position(pos + n, layer, v); -+ } -+ } -+ } -+ -+ // Helper: sets all bits in a region [p, p+word_size). -+ void set_bits_of_region(MetaWord* p, size_t word_size, unsigned layer, bool v) { -+ assert(word_size % _smallest_chunk_word_size == 0, -+ err_msg("Region size " SIZE_FORMAT " not a multiple of smallest chunk size.", word_size)); -+ const unsigned pos = get_bitpos_for_address(p); -+ const unsigned num_bits = (unsigned) (word_size / _smallest_chunk_word_size); -+ set_bits_of_region(pos, num_bits, layer, v); -+ } -+ -+ // Helper: given an address, return the bit position representing that address. -+ unsigned get_bitpos_for_address(const MetaWord* p) const { -+ assert(_reference_address != NULL, "not initialized"); -+ assert(p >= _reference_address && p < _reference_address + _word_size, -+ err_msg("Address %p out of range for occupancy map [%p..%p).", -+ p, _reference_address, _reference_address + _word_size)); -+ assert(is_aligned(p, _smallest_chunk_word_size * sizeof(MetaWord)), -+ err_msg("Address not aligned (%p).", p)); -+ const ptrdiff_t d = (p - _reference_address) / _smallest_chunk_word_size; -+ assert(d >= 0 && (size_t)d < _map_size * 8, "Sanity."); -+ return (unsigned) d; -+ } -+ -+ public: -+ -+ OccupancyMap(const MetaWord* reference_address, size_t word_size, size_t smallest_chunk_word_size) : -+ _reference_address(reference_address), _word_size(word_size), -+ _smallest_chunk_word_size(smallest_chunk_word_size) { -+ assert(reference_address != NULL, "invalid reference address"); -+ assert(is_aligned(reference_address, smallest_chunk_word_size), -+ "Reference address not aligned to smallest chunk size."); -+ assert(is_aligned(word_size, smallest_chunk_word_size), -+ "Word_size shall be a multiple of the smallest chunk size."); -+ // Calculate bitmap size: one bit per smallest_chunk_word_size'd area. -+ size_t num_bits = word_size / smallest_chunk_word_size; -+ _map_size = (num_bits + 7) / 8; -+ assert(_map_size * 8 >= num_bits, "sanity"); -+ _map[0] = (uint8_t*) os::malloc(_map_size, mtInternal); -+ _map[1] = (uint8_t*) os::malloc(_map_size, mtInternal); -+ assert(_map[0] != NULL && _map[1] != NULL, "Occupancy Map: allocation failed."); -+ memset(_map[1], 0, _map_size); -+ memset(_map[0], 0, _map_size); -+ // Sanity test: the first respectively last possible chunk start address in -+ // the covered range shall map to the first and last bit in the bitmap. -+ assert(get_bitpos_for_address(reference_address) == 0, -+ "First chunk address in range must map to fist bit in bitmap."); -+ assert(get_bitpos_for_address(reference_address + word_size - smallest_chunk_word_size) == num_bits - 1, -+ "Last chunk address in range must map to last bit in bitmap."); -+ } -+ -+ ~OccupancyMap() { -+ os::free(_map[0]); -+ os::free(_map[1]); -+ } -+ -+ // Returns true if at address x a chunk is starting. -+ bool chunk_starts_at_address(MetaWord* p) const { -+ const unsigned pos = get_bitpos_for_address(p); -+ return get_bit_at_position(pos, layer_chunk_start_map); -+ } -+ -+ void set_chunk_starts_at_address(MetaWord* p, bool v) { -+ const unsigned pos = get_bitpos_for_address(p); -+ set_bit_at_position(pos, layer_chunk_start_map, v); -+ } -+ -+ // Removes all chunk-start-bits inside a region, typically as a -+ // result of a chunk merge. -+ void wipe_chunk_start_bits_in_region(MetaWord* p, size_t word_size) { -+ set_bits_of_region(p, word_size, layer_chunk_start_map, false); -+ } -+ -+ // Returns true if there are life (in use) chunks in the region limited -+ // by [p, p+word_size). -+ bool is_region_in_use(MetaWord* p, size_t word_size) const { -+ return is_any_bit_set_in_region(p, word_size, layer_in_use_map); -+ } -+ -+ // Marks the region starting at p with the size word_size as in use -+ // or free, depending on v. -+ void set_region_in_use(MetaWord* p, size_t word_size, bool v) { -+ set_bits_of_region(p, word_size, layer_in_use_map, v); -+ } -+ -+#ifdef ASSERT -+ // Verify occupancy map for the address range [from, to). -+ // We need to tell it the address range, because the memory the -+ // occupancy map is covering may not be fully comitted yet. -+ void verify(MetaWord* from, MetaWord* to) { -+ Metachunk* chunk = NULL; -+ int nth_bit_for_chunk = 0; -+ MetaWord* chunk_end = NULL; -+ for (MetaWord* p = from; p < to; p += _smallest_chunk_word_size) { -+ const unsigned pos = get_bitpos_for_address(p); -+ // Check the chunk-starts-info: -+ if (get_bit_at_position(pos, layer_chunk_start_map)) { -+ // Chunk start marked in bitmap. -+ chunk = (Metachunk*) p; -+ if (chunk_end != NULL) { -+ assert(chunk_end == p, err_msg("Unexpected chunk start found at %p (expected " -+ "the next chunk to start at %p).", p, chunk_end)); -+ } -+ assert(chunk->is_valid_sentinel(), err_msg("Invalid chunk at address %p.", p)); -+ if (chunk->get_chunk_type() != HumongousIndex) { -+ guarantee(is_aligned(p, chunk->word_size()), err_msg("Chunk %p not aligned.", p)); -+ } -+ chunk_end = p + chunk->word_size(); -+ nth_bit_for_chunk = 0; -+ assert(chunk_end <= to, "Chunk end overlaps test address range."); -+ } else { -+ // No chunk start marked in bitmap. -+ assert(chunk != NULL, "Chunk should start at start of address range."); -+ assert(p < chunk_end, err_msg("Did not find expected chunk start at %p.", p)); -+ nth_bit_for_chunk ++; -+ } -+ // Check the in-use-info: -+ const bool in_use_bit = get_bit_at_position(pos, layer_in_use_map); -+ if (in_use_bit) { -+ assert(!chunk->is_tagged_free(), err_msg("Chunk %p: marked in-use in map but is free (bit %u).", -+ chunk, nth_bit_for_chunk)); -+ } else { -+ assert(chunk->is_tagged_free(), err_msg("Chunk %p: marked free in map but is in use (bit %u).", -+ chunk, nth_bit_for_chunk)); -+ } -+ } -+ } -+ -+ // Verify that a given chunk is correctly accounted for in the bitmap. -+ void verify_for_chunk(Metachunk* chunk) { -+ assert(chunk_starts_at_address((MetaWord*) chunk), -+ err_msg("No chunk start marked in map for chunk %p.", chunk)); -+ // For chunks larger than the minimal chunk size, no other chunk -+ // must start in its area. -+ if (chunk->word_size() > _smallest_chunk_word_size) { -+ assert(!is_any_bit_set_in_region(((MetaWord*) chunk) + _smallest_chunk_word_size, -+ chunk->word_size() - _smallest_chunk_word_size, layer_chunk_start_map), -+ "No chunk must start within another chunk."); -+ } -+ if (!chunk->is_tagged_free()) { -+ assert(is_region_in_use((MetaWord*)chunk, chunk->word_size()), -+ err_msg("Chunk %p is in use but marked as free in map (%d %d).", -+ chunk, chunk->get_chunk_type(), chunk->get_origin())); -+ } else { -+ assert(!is_region_in_use((MetaWord*)chunk, chunk->word_size()), -+ err_msg("Chunk %p is free but marked as in-use in map (%d %d).", -+ chunk, chunk->get_chunk_type(), chunk->get_origin())); -+ } -+ } -+ -+#endif // ASSERT -+ -+}; -+ - // A VirtualSpaceList node. - class VirtualSpaceNode : public CHeapObj { - friend class VirtualSpaceList; -@@ -336,6 +692,9 @@ class VirtualSpaceNode : public CHeapObj { - // Link to next VirtualSpaceNode - VirtualSpaceNode* _next; - -+ // Whether this node is contained in class or metaspace. -+ const bool _is_class; -+ - // total in the VirtualSpace - MemRegion _reserved; - ReservedSpace _rs; -@@ -344,6 +703,8 @@ class VirtualSpaceNode : public CHeapObj { - // count of chunks contained in this VirtualSpace - uintx _container_count; - -+ OccupancyMap* _occupancy_map; -+ - // Convenience functions to access the _virtual_space - char* low() const { return virtual_space()->low(); } - char* high() const { return virtual_space()->high(); } -@@ -354,16 +715,28 @@ class VirtualSpaceNode : public CHeapObj { - - // Committed but unused space in the virtual space - size_t free_words_in_vs() const; -+ -+ // True if this node belongs to class metaspace. -+ bool is_class() const { return _is_class; } -+ -+ // Helper function for take_from_committed: allocate padding chunks -+ // until top is at the given address. -+ void allocate_padding_chunks_until_top_is_at(MetaWord* target_top); -+ - public: - -- VirtualSpaceNode(size_t byte_size); -- VirtualSpaceNode(ReservedSpace rs) : _top(NULL), _next(NULL), _rs(rs), _container_count(0) {} -+ VirtualSpaceNode(bool is_class, size_t byte_size); -+ VirtualSpaceNode(bool is_class, ReservedSpace rs) : -+ _is_class(is_class), _top(NULL), _next(NULL), _rs(rs), _container_count(0), _occupancy_map(NULL) {} - ~VirtualSpaceNode(); - - // Convenience functions for logical bottom and end - MetaWord* bottom() const { return (MetaWord*) _virtual_space.low(); } - MetaWord* end() const { return (MetaWord*) _virtual_space.high(); } - -+ const OccupancyMap* occupancy_map() const { return _occupancy_map; } -+ OccupancyMap* occupancy_map() { return _occupancy_map; } -+ - bool contains(const void* ptr) { return ptr >= low() && ptr < high(); } - - size_t reserved_words() const { return _virtual_space.reserved_size() / BytesPerWord; } -@@ -424,12 +797,18 @@ class VirtualSpaceNode : public CHeapObj { - // the smallest chunk size. - void retire(ChunkManager* chunk_manager); - --#ifdef ASSERT -- // Debug support -- void mangle(); --#endif - - void print_on(outputStream* st) const; -+ void print_map(outputStream* st, bool is_class) const; -+ -+ // Debug support -+ DEBUG_ONLY(void mangle();) -+ // Verify counters, all chunks in this list node and the occupancy map. -+ DEBUG_ONLY(void verify();) -+ // Verify that all free chunks in this node are ideally merged -+ // (there not should be multiple small chunks where a large chunk could exist.) -+ DEBUG_ONLY(void verify_free_chunks_are_ideally_merged();) -+ - }; - - #define assert_is_ptr_aligned(ptr, alignment) \ -@@ -458,7 +837,8 @@ static bool should_commit_large_pages_when_reserving(size_t bytes) { - } - - // byte_size is the size of the associated virtualspace. --VirtualSpaceNode::VirtualSpaceNode(size_t bytes) : _top(NULL), _next(NULL), _rs(), _container_count(0) { -+VirtualSpaceNode::VirtualSpaceNode(bool is_class, size_t bytes) : -+ _is_class(is_class), _top(NULL), _next(NULL), _rs(), _container_count(0), _occupancy_map(NULL) { - assert_is_size_aligned(bytes, Metaspace::reserve_alignment()); - - #if INCLUDE_CDS -@@ -504,12 +884,14 @@ VirtualSpaceNode::VirtualSpaceNode(size_t bytes) : _top(NULL), _next(NULL), _rs( - } - - void VirtualSpaceNode::purge(ChunkManager* chunk_manager) { -+ DEBUG_ONLY(this->verify();) - Metachunk* chunk = first_chunk(); - Metachunk* invalid_chunk = (Metachunk*) top(); - while (chunk < invalid_chunk ) { - assert(chunk->is_tagged_free(), "Should be tagged free"); - MetaWord* next = ((MetaWord*)chunk) + chunk->word_size(); - chunk_manager->remove_chunk(chunk); -+ chunk->remove_sentinel(); - assert(chunk->next() == NULL && - chunk->prev() == NULL, - "Was not removed from its list"); -@@ -517,6 +899,88 @@ void VirtualSpaceNode::purge(ChunkManager* chunk_manager) { - } - } - -+void VirtualSpaceNode::print_map(outputStream* st, bool is_class) const { -+ -+ if (bottom() == top()) { -+ return; -+ } -+ -+ const size_t spec_chunk_size = is_class ? ClassSpecializedChunk : SpecializedChunk; -+ const size_t small_chunk_size = is_class ? ClassSmallChunk : SmallChunk; -+ const size_t med_chunk_size = is_class ? ClassMediumChunk : MediumChunk; -+ -+ int line_len = 100; -+ const size_t section_len = align_up(spec_chunk_size * line_len, med_chunk_size); -+ line_len = (int)(section_len / spec_chunk_size); -+ -+ static const int NUM_LINES = 4; -+ -+ char* lines[NUM_LINES]; -+ for (int i = 0; i < NUM_LINES; i ++) { -+ lines[i] = (char*)os::malloc(line_len, mtInternal); -+ } -+ int pos = 0; -+ const MetaWord* p = bottom(); -+ const Metachunk* chunk = (const Metachunk*)p; -+ const MetaWord* chunk_end = p + chunk->word_size(); -+ while (p < top()) { -+ if (pos == line_len) { -+ pos = 0; -+ for (int i = 0; i < NUM_LINES; i ++) { -+ st->fill_to(22); -+ st->print_raw(lines[i], line_len); -+ st->cr(); -+ } -+ } -+ if (pos == 0) { -+ st->print(PTR_FORMAT ":", p2i(p)); -+ } -+ if (p == chunk_end) { -+ chunk = (Metachunk*)p; -+ chunk_end = p + chunk->word_size(); -+ } -+ // line 1: chunk starting points (a dot if that area is a chunk start). -+ lines[0][pos] = p == (const MetaWord*)chunk ? '.' : ' '; -+ -+ // Line 2: chunk type (x=spec, s=small, m=medium, h=humongous), uppercase if -+ // chunk is in use. -+ const bool chunk_is_free = ((Metachunk*)chunk)->is_tagged_free(); -+ if (chunk->word_size() == spec_chunk_size) { -+ lines[1][pos] = chunk_is_free ? 'x' : 'X'; -+ } else if (chunk->word_size() == small_chunk_size) { -+ lines[1][pos] = chunk_is_free ? 's' : 'S'; -+ } else if (chunk->word_size() == med_chunk_size) { -+ lines[1][pos] = chunk_is_free ? 'm' : 'M'; -+ } else if (chunk->word_size() > med_chunk_size) { -+ lines[1][pos] = chunk_is_free ? 'h' : 'H'; -+ } else { -+ ShouldNotReachHere(); -+ } -+ -+ // Line 3: chunk origin -+ const ChunkOrigin origin = chunk->get_origin(); -+ lines[2][pos] = origin == origin_normal ? ' ' : '0' + (int) origin; -+ -+ // Line 4: Virgin chunk? Virgin chunks are chunks created as a byproduct of padding or splitting, -+ // but were never used. -+ lines[3][pos] = chunk->get_use_count() > 0 ? ' ' : 'v'; -+ -+ p += spec_chunk_size; -+ pos ++; -+ } -+ if (pos > 0) { -+ for (int i = 0; i < NUM_LINES; i ++) { -+ st->fill_to(22); -+ st->print_raw(lines[i], line_len); -+ st->cr(); -+ } -+ } -+ for (int i = 0; i < NUM_LINES; i ++) { -+ os::free(lines[i]); -+ } -+} -+ -+ - #ifdef ASSERT - uint VirtualSpaceNode::container_count_slow() { - uint count = 0; -@@ -524,6 +988,7 @@ uint VirtualSpaceNode::container_count_slow() { - Metachunk* invalid_chunk = (Metachunk*) top(); - while (chunk < invalid_chunk ) { - MetaWord* next = ((MetaWord*)chunk) + chunk->word_size(); -+ do_verify_chunk(chunk); - // Don't count the chunks on the free lists. Those are - // still part of the VirtualSpaceNode but not currently - // counted. -@@ -536,6 +1001,77 @@ uint VirtualSpaceNode::container_count_slow() { - } - #endif - -+#ifdef ASSERT -+// Verify counters, all chunks in this list node and the occupancy map. -+void VirtualSpaceNode::verify() { -+ uintx num_in_use_chunks = 0; -+ Metachunk* chunk = first_chunk(); -+ Metachunk* invalid_chunk = (Metachunk*) top(); -+ -+ // Iterate the chunks in this node and verify each chunk. -+ while (chunk < invalid_chunk ) { -+ DEBUG_ONLY(do_verify_chunk(chunk);) -+ if (!chunk->is_tagged_free()) { -+ num_in_use_chunks ++; -+ } -+ MetaWord* next = ((MetaWord*)chunk) + chunk->word_size(); -+ chunk = (Metachunk*) next; -+ } -+ assert(_container_count == num_in_use_chunks, err_msg("Container count mismatch (real: " UINTX_FORMAT -+ ", counter: " UINTX_FORMAT ".", num_in_use_chunks, _container_count)); -+ // Also verify the occupancy map. -+ occupancy_map()->verify(this->bottom(), this->top()); -+} -+#endif // ASSERT -+ -+#ifdef ASSERT -+// Verify that all free chunks in this node are ideally merged -+// (there not should be multiple small chunks where a large chunk could exist.) -+void VirtualSpaceNode::verify_free_chunks_are_ideally_merged() { -+ Metachunk* chunk = first_chunk(); -+ Metachunk* invalid_chunk = (Metachunk*) top(); -+ // Shorthands. -+ const size_t size_med = (is_class() ? ClassMediumChunk : MediumChunk) * BytesPerWord; -+ const size_t size_small = (is_class() ? ClassSmallChunk : SmallChunk) * BytesPerWord; -+ int num_free_chunks_since_last_med_boundary = -1; -+ int num_free_chunks_since_last_small_boundary = -1; -+ while (chunk < invalid_chunk ) { -+ // Test for missed chunk merge opportunities: count number of free chunks since last chunk boundary. -+ // Reset the counter when encountering a non-free chunk. -+ if (chunk->get_chunk_type() != HumongousIndex) { -+ if (chunk->is_tagged_free()) { -+ // Count successive free, non-humongous chunks. -+ if (is_aligned(chunk, size_small)) { -+ assert(num_free_chunks_since_last_small_boundary <= 1, -+ err_msg("Missed chunk merge opportunity at " PTR_FORMAT " for chunk size " SIZE_FORMAT_HEX ".", p2i(chunk) - size_small, size_small)); -+ num_free_chunks_since_last_small_boundary = 0; -+ } else if (num_free_chunks_since_last_small_boundary != -1) { -+ num_free_chunks_since_last_small_boundary ++; -+ } -+ if (is_aligned(chunk, size_med)) { -+ assert(num_free_chunks_since_last_med_boundary <= 1, -+ err_msg("Missed chunk merge opportunity at " PTR_FORMAT " for chunk size " SIZE_FORMAT_HEX ".", p2i(chunk) - size_med, size_med)); -+ num_free_chunks_since_last_med_boundary = 0; -+ } else if (num_free_chunks_since_last_med_boundary != -1) { -+ num_free_chunks_since_last_med_boundary ++; -+ } -+ } else { -+ // Encountering a non-free chunk, reset counters. -+ num_free_chunks_since_last_med_boundary = -1; -+ num_free_chunks_since_last_small_boundary = -1; -+ } -+ } else { -+ // One cannot merge areas with a humongous chunk in the middle. Reset counters. -+ num_free_chunks_since_last_med_boundary = -1; -+ num_free_chunks_since_last_small_boundary = -1; -+ } -+ -+ MetaWord* next = ((MetaWord*)chunk) + chunk->word_size(); -+ chunk = (Metachunk*) next; -+ } -+} -+#endif // ASSERT -+ - // List of VirtualSpaces for metadata allocation. - class VirtualSpaceList : public CHeapObj { - friend class VirtualSpaceNode; -@@ -623,6 +1159,7 @@ class VirtualSpaceList : public CHeapObj { - void purge(ChunkManager* chunk_manager); - - void print_on(outputStream* st) const; -+ void print_map(outputStream* st) const; - - class VirtualSpaceListIterator : public StackObj { - VirtualSpaceNode* _virtual_spaces; -@@ -728,8 +1265,6 @@ class SpaceManager : public CHeapObj { - - Mutex* lock() const { return _lock; } - -- const char* chunk_size_name(ChunkIndex index) const; -- - protected: - void initialize(); - -@@ -945,6 +1480,9 @@ void BlockFreelist::print_on(outputStream* st) const { - - VirtualSpaceNode::~VirtualSpaceNode() { - _rs.release(); -+ if (_occupancy_map != NULL) { -+ delete _occupancy_map; -+ } - #ifdef ASSERT - size_t word_size = sizeof(*this) / BytesPerWord; - Copy::fill_to_words((HeapWord*) this, word_size, 0xf1f1f1f1); -@@ -964,10 +1502,124 @@ size_t VirtualSpaceNode::free_words_in_vs() const { - return pointer_delta(end(), top(), sizeof(MetaWord)); - } - -+// Given an address larger than top(), allocate padding chunks until top is at the given address. -+void VirtualSpaceNode::allocate_padding_chunks_until_top_is_at(MetaWord* target_top) { -+ -+ assert(target_top > top(), "Sanity"); -+ -+ // Padding chunks are added to the freelist. -+ ChunkManager* const chunk_manager = Metaspace::get_chunk_manager(this->is_class()); -+ -+ // shorthands -+ const size_t spec_word_size = chunk_manager->specialized_chunk_word_size(); -+ const size_t small_word_size = chunk_manager->small_chunk_word_size(); -+ const size_t med_word_size = chunk_manager->medium_chunk_word_size(); -+ -+ while (top() < target_top) { -+ -+ // We could make this coding more generic, but right now we only deal with two possible chunk sizes -+ // for padding chunks, so it is not worth it. -+ size_t padding_chunk_word_size = small_word_size; -+ if (is_aligned(top(), small_word_size * sizeof(MetaWord)) == false) { -+ assert_is_ptr_aligned(top(), spec_word_size * sizeof(MetaWord)); // Should always hold true. -+ padding_chunk_word_size = spec_word_size; -+ } -+ MetaWord* here = top(); -+ assert_is_ptr_aligned(here, padding_chunk_word_size * sizeof(MetaWord)); -+ inc_top(padding_chunk_word_size); -+ -+ // Create new padding chunk. -+ ChunkIndex padding_chunk_type = get_chunk_type_by_size(padding_chunk_word_size, is_class()); -+ assert(padding_chunk_type == SpecializedIndex || padding_chunk_type == SmallIndex, "sanity"); -+ -+ Metachunk* const padding_chunk = -+ ::new (here) Metachunk(padding_chunk_type, is_class(), padding_chunk_word_size, this); -+ assert(padding_chunk == (Metachunk*)here, "Sanity"); -+ DEBUG_ONLY(padding_chunk->set_origin(origin_pad);) -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("Created padding chunk in %s at " -+ PTR_FORMAT ", size " SIZE_FORMAT_HEX ".", -+ (is_class() ? "class space " : "metaspace"), -+ p2i(padding_chunk), padding_chunk->word_size() * sizeof(MetaWord)); -+ } -+ -+ // Mark chunk start in occupancy map. -+ occupancy_map()->set_chunk_starts_at_address((MetaWord*)padding_chunk, true); -+ -+ // Chunks are born as in-use (see MetaChunk ctor). So, before returning -+ // the padding chunk to its chunk manager, mark it as in use (ChunkManager -+ // will assert that). -+ do_update_in_use_info_for_chunk(padding_chunk, true); -+ -+ // Return Chunk to freelist. -+ inc_container_count(); -+ chunk_manager->return_single_chunk(padding_chunk_type, padding_chunk); -+ // Please note: at this point, ChunkManager::return_single_chunk() -+ // may already have merged the padding chunk with neighboring chunks, so -+ // it may have vanished at this point. Do not reference the padding -+ // chunk beyond this point. -+ } -+ -+ assert(top() == target_top, "Sanity"); -+ -+} // allocate_padding_chunks_until_top_is_at() -+ - // Allocates the chunk from the virtual space only. - // This interface is also used internally for debugging. Not all - // chunks removed here are necessarily used for allocation. - Metachunk* VirtualSpaceNode::take_from_committed(size_t chunk_word_size) { -+ // Non-humongous chunks are to be allocated aligned to their chunk -+ // size. So, start addresses of medium chunks are aligned to medium -+ // chunk size, those of small chunks to small chunk size and so -+ // forth. This facilitates merging of free chunks and reduces -+ // fragmentation. Chunk sizes are spec < small < medium, with each -+ // larger chunk size being a multiple of the next smaller chunk -+ // size. -+ // Because of this alignment, me may need to create a number of padding -+ // chunks. These chunks are created and added to the freelist. -+ -+ // The chunk manager to which we will give our padding chunks. -+ ChunkManager* const chunk_manager = Metaspace::get_chunk_manager(this->is_class()); -+ -+ // shorthands -+ const size_t spec_word_size = chunk_manager->specialized_chunk_word_size(); -+ const size_t small_word_size = chunk_manager->small_chunk_word_size(); -+ const size_t med_word_size = chunk_manager->medium_chunk_word_size(); -+ -+ assert(chunk_word_size == spec_word_size || chunk_word_size == small_word_size || -+ chunk_word_size >= med_word_size, "Invalid chunk size requested."); -+ -+ // Chunk alignment (in bytes) == chunk size unless humongous. -+ // Humongous chunks are aligned to the smallest chunk size (spec). -+ const size_t required_chunk_alignment = (chunk_word_size > med_word_size ? -+ spec_word_size : chunk_word_size) * sizeof(MetaWord); -+ -+ // Do we have enough space to create the requested chunk plus -+ // any padding chunks needed? -+ MetaWord* const next_aligned = -+ static_cast(align_up(top(), required_chunk_alignment)); -+ if (!is_available((next_aligned - top()) + chunk_word_size)) { -+ return NULL; -+ } -+ -+ // Before allocating the requested chunk, allocate padding chunks if necessary. -+ // We only need to do this for small or medium chunks: specialized chunks are the -+ // smallest size, hence always aligned. Homungous chunks are allocated unaligned -+ // (implicitly, also aligned to smallest chunk size). -+ if ((chunk_word_size == med_word_size || chunk_word_size == small_word_size) && next_aligned > top()) { -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("Creating padding chunks in %s between %p and %p...", -+ (is_class() ? "class space " : "metaspace"), -+ top(), next_aligned); -+ } -+ allocate_padding_chunks_until_top_is_at(next_aligned); -+ // Now, top should be aligned correctly. -+ assert_is_ptr_aligned(top(), required_chunk_alignment); -+ } -+ -+ // Now, top should be aligned correctly. -+ assert_is_ptr_aligned(top(), required_chunk_alignment); -+ - // Bottom of the new chunk - MetaWord* chunk_limit = top(); - assert(chunk_limit != NULL, "Not safe to call this method"); -@@ -991,7 +1643,20 @@ Metachunk* VirtualSpaceNode::take_from_committed(size_t chunk_word_size) { - inc_top(chunk_word_size); - - // Initialize the chunk -- Metachunk* result = ::new (chunk_limit) Metachunk(chunk_word_size, this); -+ ChunkIndex chunk_type = get_chunk_type_by_size(chunk_word_size, is_class()); -+ Metachunk* result = ::new (chunk_limit) Metachunk(chunk_type, is_class(), chunk_word_size, this); -+ assert(result == (Metachunk*)chunk_limit, "Sanity"); -+ occupancy_map()->set_chunk_starts_at_address((MetaWord*)result, true); -+ do_update_in_use_info_for_chunk(result, true); -+ -+ inc_container_count(); -+ -+ DEBUG_ONLY(chunk_manager->locked_verify()); -+ DEBUG_ONLY(this->verify()); -+ DEBUG_ONLY(do_verify_chunk(result)); -+ -+ result->inc_use_count(); -+ - return result; - } - -@@ -1010,6 +1675,16 @@ bool VirtualSpaceNode::expand_by(size_t min_words, size_t preferred_words) { - size_t commit = MIN2(preferred_bytes, uncommitted); - bool result = virtual_space()->expand_by(commit, false); - -+ if (TraceMetadataChunkAllocation) { -+ if (result) { -+ gclog_or_tty->print_cr("Expanded %s virtual space list node by " SIZE_FORMAT " words.", -+ (is_class() ? "class" : "non-class"), commit); -+ } else { -+ gclog_or_tty->print_cr("Failed to expand %s virtual space list node by " SIZE_FORMAT " words.", -+ (is_class() ? "class" : "non-class"), commit); -+ } -+ } -+ - assert(result, "Failed to commit memory"); - - return result; -@@ -1018,9 +1693,6 @@ bool VirtualSpaceNode::expand_by(size_t min_words, size_t preferred_words) { - Metachunk* VirtualSpaceNode::get_chunk_vs(size_t chunk_word_size) { - assert_lock_strong(SpaceManager::expand_lock()); - Metachunk* result = take_from_committed(chunk_word_size); -- if (result != NULL) { -- inc_container_count(); -- } - return result; - } - -@@ -1060,6 +1732,10 @@ bool VirtualSpaceNode::initialize() { - _rs.size() / BytesPerWord)); - } - -+ // Initialize Occupancy Map. -+ const size_t smallest_chunk_size = is_class() ? ClassSpecializedChunk : SpecializedChunk; -+ _occupancy_map = new OccupancyMap(bottom(), reserved_words(), smallest_chunk_size); -+ - return result; - } - -@@ -1140,8 +1816,140 @@ void ChunkManager::remove_chunk(Metachunk* chunk) { - humongous_dictionary()->remove_chunk(chunk); - } - -- // Chunk is being removed from the chunks free list. -- dec_free_chunks_total(chunk->word_size()); -+ // Chunk has been removed from the chunks free list, update counters. -+ account_for_removed_chunk(chunk); -+} -+ -+bool ChunkManager::attempt_to_coalesce_around_chunk(Metachunk* chunk, ChunkIndex target_chunk_type) { -+ assert_lock_strong(SpaceManager::expand_lock()); -+ assert(chunk != NULL, "invalid chunk pointer"); -+ // Check for valid merge combinations. -+ assert((chunk->get_chunk_type() == SpecializedIndex && -+ (target_chunk_type == SmallIndex || target_chunk_type == MediumIndex)) || -+ (chunk->get_chunk_type() == SmallIndex && target_chunk_type == MediumIndex), -+ "Invalid chunk merge combination."); -+ -+ const size_t target_chunk_word_size = -+ get_size_for_nonhumongous_chunktype(target_chunk_type, this->is_class()); -+ -+ // [ prospective merge region ) -+ MetaWord* const p_merge_region_start = -+ (MetaWord*) align_down(chunk, target_chunk_word_size * sizeof(MetaWord)); -+ MetaWord* const p_merge_region_end = -+ p_merge_region_start + target_chunk_word_size; -+ -+ // We need the VirtualSpaceNode containing this chunk and its occupancy map. -+ VirtualSpaceNode* const vsn = chunk->container(); -+ OccupancyMap* const ocmap = vsn->occupancy_map(); -+ -+ // The prospective chunk merge range must be completely contained by the -+ // committed range of the virtual space node. -+ if (p_merge_region_start < vsn->bottom() || p_merge_region_end > vsn->top()) { -+ return false; -+ } -+ -+ // Only attempt to merge this range if at its start a chunk starts and at its end -+ // a chunk ends. If a chunk (can only be humongous) straddles either start or end -+ // of that range, we cannot merge. -+ if (!ocmap->chunk_starts_at_address(p_merge_region_start)) { -+ return false; -+ } -+ if (p_merge_region_end < vsn->top() && -+ !ocmap->chunk_starts_at_address(p_merge_region_end)) { -+ return false; -+ } -+ -+ // Now check if the prospective merge area contains live chunks. If it does we cannot merge. -+ if (ocmap->is_region_in_use(p_merge_region_start, target_chunk_word_size)) { -+ return false; -+ } -+ -+ // Success! Remove all chunks in this region... -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("%s: coalescing chunks in area [%p-%p)...", -+ (is_class() ? "class space" : "metaspace"), -+ p_merge_region_start, p_merge_region_end); -+ } -+ -+ const int num_chunks_removed = -+ remove_chunks_in_area(p_merge_region_start, target_chunk_word_size); -+ -+ // ... and create a single new bigger chunk. -+ Metachunk* const p_new_chunk = -+ ::new (p_merge_region_start) Metachunk(target_chunk_type, is_class(), target_chunk_word_size, vsn); -+ assert(p_new_chunk == (Metachunk*)p_merge_region_start, "Sanity"); -+ p_new_chunk->set_origin(origin_merge); -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("%s: created coalesced chunk at %p, size " SIZE_FORMAT_HEX ".", -+ (is_class() ? "class space" : "metaspace"), -+ p_new_chunk, p_new_chunk->word_size() * sizeof(MetaWord)); -+ } -+ -+ // Fix occupancy map: remove old start bits of the small chunks and set new start bit. -+ ocmap->wipe_chunk_start_bits_in_region(p_merge_region_start, target_chunk_word_size); -+ ocmap->set_chunk_starts_at_address(p_merge_region_start, true); -+ -+ // Mark chunk as free. Note: it is not necessary to update the occupancy -+ // map in-use map, because the old chunks were also free, so nothing -+ // should have changed. -+ p_new_chunk->set_is_tagged_free(true); -+ -+ // Add new chunk to its freelist. -+ ChunkList* const list = free_chunks(target_chunk_type); -+ list->return_chunk_at_head(p_new_chunk); -+ -+ // And adjust ChunkManager:: _free_chunks_count (_free_chunks_total -+ // should not have changed, because the size of the space should be the same) -+ _free_chunks_count -= num_chunks_removed; -+ _free_chunks_count ++; -+ -+ // VirtualSpaceNode::container_count does not have to be modified: -+ // it means "number of active (non-free) chunks", so merging free chunks -+ // should not affect that count. -+ -+ // At the end of a chunk merge, run verification tests. -+ DEBUG_ONLY(this->locked_verify()); -+ DEBUG_ONLY(vsn->verify()); -+ -+ return true; -+} -+ -+// Remove all chunks in the given area - the chunks are supposed to be free - -+// from their corresponding freelists. Mark them as invalid. -+// - This does not correct the occupancy map. -+// - This does not adjust the counters in ChunkManager. -+// - Does not adjust container count counter in containing VirtualSpaceNode -+// Returns number of chunks removed. -+int ChunkManager::remove_chunks_in_area(MetaWord* p, size_t word_size) { -+ assert(p != NULL && word_size > 0, "Invalid range."); -+ const size_t smallest_chunk_size = get_size_for_nonhumongous_chunktype(SpecializedIndex, is_class()); -+ assert_is_size_aligned(word_size, smallest_chunk_size); -+ -+ Metachunk* const start = (Metachunk*) p; -+ const Metachunk* const end = (Metachunk*)(p + word_size); -+ Metachunk* cur = start; -+ int num_removed = 0; -+ while (cur < end) { -+ Metachunk* next = (Metachunk*)(((MetaWord*)cur) + cur->word_size()); -+ DEBUG_ONLY(do_verify_chunk(cur)); -+ assert(cur->get_chunk_type() != HumongousIndex, err_msg("Unexpected humongous chunk found at %p.", cur)); -+ assert(cur->is_tagged_free(), err_msg("Chunk expected to be free (%p)", cur)); -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("%s: removing chunk %p, size " SIZE_FORMAT_HEX ".", -+ (is_class() ? "class space" : "metaspace"), -+ cur, cur->word_size() * sizeof(MetaWord)); -+ } -+ cur->remove_sentinel(); -+ // Note: cannot call ChunkManager::remove_chunk, because that -+ // modifies the counters in ChunkManager, which we do not want. So -+ // we call remove_chunk on the freelist directly (see also the -+ // splitting function which does the same). -+ ChunkList* const list = free_chunks(list_index(cur->word_size())); -+ list->remove_chunk(cur); -+ num_removed ++; -+ cur = next; -+ } -+ return num_removed; - } - - // Walk the list of VirtualSpaceNodes and delete -@@ -1161,6 +1969,10 @@ void VirtualSpaceList::purge(ChunkManager* chunk_manager) { - // Don't free the current virtual space since it will likely - // be needed soon. - if (vsl->container_count() == 0 && vsl != current_virtual_space()) { -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("Purging VirtualSpaceNode " PTR_FORMAT " (capacity: " SIZE_FORMAT -+ ", used: " SIZE_FORMAT ").", p2i(vsl), vsl->capacity_words_in_vs(), vsl->used_words_in_vs()); -+ } - // Unlink it from the list - if (prev_vsl == vsl) { - // This is the case of the current node being the first node. -@@ -1221,17 +2033,24 @@ void VirtualSpaceList::retire_current_virtual_space() { - } - - void VirtualSpaceNode::retire(ChunkManager* chunk_manager) { -+ assert(this->is_class() == chunk_manager->is_class(), "Wrong ChunkManager?"); - for (int i = (int)MediumIndex; i >= (int)ZeroIndex; --i) { - ChunkIndex index = (ChunkIndex)i; -- size_t chunk_size = chunk_manager->free_chunks(index)->size(); -+ size_t chunk_size = chunk_manager->size_by_index(index); - - while (free_words_in_vs() >= chunk_size) { - DEBUG_ONLY(verify_container_count();) - Metachunk* chunk = get_chunk_vs(chunk_size); -- assert(chunk != NULL, "allocation should have been successful"); -- -- chunk_manager->return_chunks(index, chunk); -- chunk_manager->inc_free_chunks_total(chunk_size); -+ // Chunk will be allocated aligned, so allocation may require -+ // additional padding chunks. That may cause above allocation to -+ // fail. Just ignore the failed allocation and continue with the -+ // next smaller chunk size. As the VirtualSpaceNode comitted -+ // size should be a multiple of the smallest chunk size, we -+ // should always be able to fill the VirtualSpace completely. -+ if (chunk == NULL) { -+ break; -+ } -+ chunk_manager->return_single_chunk(index, chunk); - DEBUG_ONLY(verify_container_count();) - } - } -@@ -1259,7 +2078,7 @@ VirtualSpaceList::VirtualSpaceList(ReservedSpace rs) : - _virtual_space_count(0) { - MutexLockerEx cl(SpaceManager::expand_lock(), - Mutex::_no_safepoint_check_flag); -- VirtualSpaceNode* class_entry = new VirtualSpaceNode(rs); -+ VirtualSpaceNode* class_entry = new VirtualSpaceNode(is_class(), rs); - bool succeeded = class_entry->initialize(); - if (succeeded) { - link_vs(class_entry); -@@ -1291,7 +2110,7 @@ bool VirtualSpaceList::create_new_virtual_space(size_t vs_word_size) { - assert_is_size_aligned(vs_byte_size, Metaspace::reserve_alignment()); - - // Allocate the meta virtual space and initialize it. -- VirtualSpaceNode* new_entry = new VirtualSpaceNode(vs_byte_size); -+ VirtualSpaceNode* new_entry = new VirtualSpaceNode(is_class(), vs_byte_size); - if (!new_entry->initialize()) { - delete new_entry; - return false; -@@ -1345,12 +2164,22 @@ bool VirtualSpaceList::expand_by(size_t min_words, size_t preferred_words) { - assert_is_size_aligned(preferred_words, Metaspace::commit_alignment_words()); - assert(min_words <= preferred_words, "Invalid arguments"); - -+ const char* const class_or_not = (is_class() ? "class" : "non-class"); -+ - if (!MetaspaceGC::can_expand(min_words, this->is_class())) { -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("Cannot expand %s virtual space list.", -+ class_or_not); -+ } - return false; - } - - size_t allowed_expansion_words = MetaspaceGC::allowed_expansion(); - if (allowed_expansion_words < min_words) { -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("Cannot expand %s virtual space list (must try gc first).", -+ class_or_not); -+ } - return false; - } - -@@ -1361,8 +2190,16 @@ bool VirtualSpaceList::expand_by(size_t min_words, size_t preferred_words) { - min_words, - max_expansion_words); - if (vs_expanded) { -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("Expanded %s virtual space list.", -+ class_or_not); -+ } - return true; - } -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("%s virtual space list: retire current node.", -+ class_or_not); -+ } - retire_current_virtual_space(); - - // Get another virtual space. -@@ -1386,6 +2223,24 @@ bool VirtualSpaceList::expand_by(size_t min_words, size_t preferred_words) { - return false; - } - -+// Given a chunk, calculate the largest possible padding space which -+// could be required when allocating it. -+static size_t largest_possible_padding_size_for_chunk(size_t chunk_word_size, bool is_class) { -+ const ChunkIndex chunk_type = get_chunk_type_by_size(chunk_word_size, is_class); -+ if (chunk_type != HumongousIndex) { -+ // Normal, non-humongous chunks are allocated at chunk size -+ // boundaries, so the largest padding space required would be that -+ // minus the smallest chunk size. -+ const size_t smallest_chunk_size = is_class ? ClassSpecializedChunk : SpecializedChunk; -+ return chunk_word_size - smallest_chunk_size; -+ } else { -+ // Humongous chunks are allocated at smallest-chunksize -+ // boundaries, so there is no padding required. -+ return 0; -+ } -+} -+ -+ - Metachunk* VirtualSpaceList::get_new_chunk(size_t chunk_word_size, size_t suggested_commit_granularity) { - - // Allocate a chunk out of the current virtual space. -@@ -1398,7 +2253,11 @@ Metachunk* VirtualSpaceList::get_new_chunk(size_t chunk_word_size, size_t sugges - // The expand amount is currently only determined by the requested sizes - // and not how much committed memory is left in the current virtual space. - -- size_t min_word_size = align_size_up(chunk_word_size, Metaspace::commit_alignment_words()); -+ // We must have enough space for the requested size and any -+ // additional reqired padding chunks. -+ const size_t size_for_padding = largest_possible_padding_size_for_chunk(chunk_word_size, this->is_class()); -+ -+ size_t min_word_size = align_size_up(chunk_word_size + size_for_padding, Metaspace::commit_alignment_words()); - size_t preferred_word_size = align_size_up(suggested_commit_granularity, Metaspace::commit_alignment_words()); - if (min_word_size >= preferred_word_size) { - // Can happen when humongous chunks are allocated. -@@ -1424,6 +2283,18 @@ void VirtualSpaceList::print_on(outputStream* st) const { - } - } - -+void VirtualSpaceList::print_map(outputStream* st) const { -+ VirtualSpaceNode* list = virtual_space_list(); -+ VirtualSpaceListIterator iter(list); -+ unsigned i = 0; -+ while (iter.repeat()) { -+ st->print_cr("Node %u:", i); -+ VirtualSpaceNode* node = iter.get_next(); -+ node->print_map(st, this->is_class()); -+ i ++; -+ } -+} -+ - // MetaspaceGC methods - - // VM_CollectForMetadataAllocation is the vm operation used to GC. -@@ -1547,6 +2418,10 @@ bool MetaspaceGC::can_expand(size_t word_size, bool is_class) { - if (is_class && Metaspace::using_class_space()) { - size_t class_committed = MetaspaceAux::committed_bytes(Metaspace::ClassType); - if (class_committed + word_size * BytesPerWord > CompressedClassSpaceSize) { -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("Cannot expand %s metaspace by " SIZE_FORMAT " words (CompressedClassSpaceSize = " SIZE_FORMAT " words)", -+ (is_class ? "class" : "non-class"), word_size, CompressedClassSpaceSize / sizeof(MetaWord)); -+ } - return false; - } - } -@@ -1554,6 +2429,10 @@ bool MetaspaceGC::can_expand(size_t word_size, bool is_class) { - // Check if the user has imposed a limit on the metaspace memory. - size_t committed_bytes = MetaspaceAux::committed_bytes(); - if (committed_bytes + word_size * BytesPerWord > MaxMetaspaceSize) { -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("Cannot expand %s metaspace by " SIZE_FORMAT " words (MaxMetaspaceSize = " SIZE_FORMAT " words)", -+ (is_class ? "class" : "non-class"), word_size, MaxMetaspaceSize / sizeof(MetaWord)); -+ } - return false; - } - -@@ -1571,6 +2450,11 @@ size_t MetaspaceGC::allowed_expansion() { - size_t left_until_max = MaxMetaspaceSize - committed_bytes; - size_t left_until_GC = capacity_until_gc - committed_bytes; - size_t left_to_commit = MIN2(left_until_GC, left_until_max); -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("allowed expansion words: " SIZE_FORMAT -+ " (left_until_max: " SIZE_FORMAT ", left_until_GC: " SIZE_FORMAT ".", -+ left_to_commit / BytesPerWord, left_until_max / BytesPerWord, left_until_GC / BytesPerWord); -+ } - - return left_to_commit / BytesPerWord; - } -@@ -1762,6 +2646,25 @@ size_t ChunkManager::free_chunks_total_bytes() { - return free_chunks_total_words() * BytesPerWord; - } - -+// Update internal accounting after a chunk was added -+void ChunkManager::account_for_added_chunk(const Metachunk* c) { -+ assert_lock_strong(SpaceManager::expand_lock()); -+ _free_chunks_count ++; -+ _free_chunks_total += c->word_size(); -+} -+ -+// Update internal accounting after a chunk was removed -+void ChunkManager::account_for_removed_chunk(const Metachunk* c) { -+ assert_lock_strong(SpaceManager::expand_lock()); -+ assert(_free_chunks_count >= 1, -+ err_msg("ChunkManager::_free_chunks_count: about to go negative (" SIZE_FORMAT ").", _free_chunks_count)); -+ assert(_free_chunks_total >= c->word_size(), -+ err_msg("ChunkManager::_free_chunks_total: about to go negative" -+ "(now: " SIZE_FORMAT ", decrement value: " SIZE_FORMAT ").", _free_chunks_total, c->word_size())); -+ _free_chunks_count --; -+ _free_chunks_total -= c->word_size(); -+} -+ - size_t ChunkManager::free_chunks_count() { - #ifdef ASSERT - if (!UseConcMarkSweepGC && !SpaceManager::expand_lock()->is_locked()) { -@@ -1775,6 +2678,22 @@ size_t ChunkManager::free_chunks_count() { - return _free_chunks_count; - } - -+ChunkIndex ChunkManager::list_index(size_t size) { -+ if (size_by_index(SpecializedIndex) == size) { -+ return SpecializedIndex; -+ } -+ if (size_by_index(SmallIndex) == size) { -+ return SmallIndex; -+ } -+ const size_t med_size = size_by_index(MediumIndex); -+ if (med_size == size) { -+ return MediumIndex; -+ } -+ -+ assert(size > med_size, "Not a humongous chunk"); -+ return HumongousIndex; -+} -+ - size_t ChunkManager::size_by_index(ChunkIndex index) const { - index_bounds_check(index); - assert(index != HumongousIndex, "Do not call for humongous chunks."); -@@ -1820,6 +2739,17 @@ void ChunkManager::verify() { - void ChunkManager::locked_verify() { - locked_verify_free_chunks_count(); - locked_verify_free_chunks_total(); -+ for (ChunkIndex i = ZeroIndex; i < NumberOfFreeLists; i = next_chunk_index(i)) { -+ ChunkList* list = free_chunks(i); -+ if (list != NULL) { -+ Metachunk* chunk = list->head(); -+ while (chunk) { -+ DEBUG_ONLY(do_verify_chunk(chunk);) -+ assert(chunk->is_tagged_free(), "Chunk should be tagged as free."); -+ chunk = chunk->next(); -+ } -+ } -+ } - } - - void ChunkManager::locked_print_free_chunks(outputStream* st) { -@@ -1879,18 +2809,166 @@ ChunkList* ChunkManager::find_free_chunks_list(size_t word_size) { - return free_chunks(index); - } - -+// Helper for chunk splitting: given a target chunk size and a larger free chunk, -+// split up the larger chunk into n smaller chunks, at least one of which should be -+// the target chunk of target chunk size. The smaller chunks, including the target -+// chunk, are returned to the freelist. The pointer to the target chunk is returned. -+// Note that this chunk is supposed to be removed from the freelist right away. -+Metachunk* ChunkManager::split_chunk(size_t target_chunk_word_size, Metachunk* larger_chunk) { -+ assert(larger_chunk->word_size() > target_chunk_word_size, "Sanity"); -+ -+ const ChunkIndex larger_chunk_index = larger_chunk->get_chunk_type(); -+ const ChunkIndex target_chunk_index = get_chunk_type_by_size(target_chunk_word_size, is_class()); -+ -+ MetaWord* const region_start = (MetaWord*)larger_chunk; -+ const size_t region_word_len = larger_chunk->word_size(); -+ MetaWord* const region_end = region_start + region_word_len; -+ VirtualSpaceNode* const vsn = larger_chunk->container(); -+ OccupancyMap* const ocmap = vsn->occupancy_map(); -+ -+ // Any larger non-humongous chunk size is a multiple of any smaller chunk size. -+ // Since non-humongous chunks are aligned to their chunk size, the larger chunk should start -+ // at an address suitable to place the smaller target chunk. -+ assert_is_ptr_aligned(region_start, target_chunk_word_size); -+ -+ // Remove old chunk. -+ free_chunks(larger_chunk_index)->remove_chunk(larger_chunk); -+ larger_chunk->remove_sentinel(); -+ -+ // Prevent access to the old chunk from here on. -+ larger_chunk = NULL; -+ // ... and wipe it. -+ DEBUG_ONLY(memset(region_start, 0xfe, region_word_len * BytesPerWord)); -+ -+ // In its place create first the target chunk... -+ MetaWord* p = region_start; -+ Metachunk* target_chunk = ::new (p) Metachunk(target_chunk_index, is_class(), target_chunk_word_size, vsn); -+ assert(target_chunk == (Metachunk*)p, "Sanity"); -+ target_chunk->set_origin(origin_split); -+ -+ // Note: we do not need to mark its start in the occupancy map -+ // because it coincides with the old chunk start. -+ -+ // Mark chunk as free and return to the freelist. -+ do_update_in_use_info_for_chunk(target_chunk, false); -+ free_chunks(target_chunk_index)->return_chunk_at_head(target_chunk); -+ -+ // This chunk should now be valid and can be verified. -+ DEBUG_ONLY(do_verify_chunk(target_chunk)); -+ -+ // In the remaining space create the remainder chunks. -+ p += target_chunk->word_size(); -+ assert(p < region_end, "Sanity"); -+ -+ while (p < region_end) { -+ -+ // Find the largest chunk size which fits the alignment requirements at address p. -+ ChunkIndex this_chunk_index = prev_chunk_index(larger_chunk_index); -+ size_t this_chunk_word_size = 0; -+ for(;;) { -+ this_chunk_word_size = get_size_for_nonhumongous_chunktype(this_chunk_index, is_class()); -+ if (is_aligned(p, this_chunk_word_size * BytesPerWord)) { -+ break; -+ } else { -+ this_chunk_index = prev_chunk_index(this_chunk_index); -+ assert(this_chunk_index >= target_chunk_index, "Sanity"); -+ } -+ } -+ -+ assert(this_chunk_word_size >= target_chunk_word_size, "Sanity"); -+ assert(is_aligned(p, this_chunk_word_size * BytesPerWord), "Sanity"); -+ assert(p + this_chunk_word_size <= region_end, "Sanity"); -+ -+ // Create splitting chunk. -+ Metachunk* this_chunk = ::new (p) Metachunk(this_chunk_index, is_class(), this_chunk_word_size, vsn); -+ assert(this_chunk == (Metachunk*)p, "Sanity"); -+ this_chunk->set_origin(origin_split); -+ ocmap->set_chunk_starts_at_address(p, true); -+ do_update_in_use_info_for_chunk(this_chunk, false); -+ -+ // This chunk should be valid and can be verified. -+ DEBUG_ONLY(do_verify_chunk(this_chunk)); -+ -+ // Return this chunk to freelist and correct counter. -+ free_chunks(this_chunk_index)->return_chunk_at_head(this_chunk); -+ _free_chunks_count ++; -+ -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("Created chunk at " PTR_FORMAT ", word size " -+ SIZE_FORMAT_HEX " (%s), in split region [" PTR_FORMAT "..." PTR_FORMAT ").", -+ p2i(this_chunk), this_chunk->word_size(), chunk_size_name(this_chunk_index), -+ p2i(region_start), p2i(region_end)); -+ } -+ -+ p += this_chunk_word_size; -+ -+ } -+ -+ return target_chunk; -+} -+ - Metachunk* ChunkManager::free_chunks_get(size_t word_size) { - assert_lock_strong(SpaceManager::expand_lock()); - - slow_locked_verify(); - - Metachunk* chunk = NULL; -+ bool we_did_split_a_chunk = false; -+ - if (list_index(word_size) != HumongousIndex) { -+ - ChunkList* free_list = find_free_chunks_list(word_size); - assert(free_list != NULL, "Sanity check"); - - chunk = free_list->head(); - -+ if (chunk == NULL) { -+ // Split large chunks into smaller chunks if there are no smaller chunks, just large chunks. -+ // This is the counterpart of the coalescing-upon-chunk-return. -+ -+ ChunkIndex target_chunk_index = get_chunk_type_by_size(word_size, is_class()); -+ -+ // Is there a larger chunk we could split? -+ Metachunk* larger_chunk = NULL; -+ ChunkIndex larger_chunk_index = next_chunk_index(target_chunk_index); -+ while (larger_chunk == NULL && larger_chunk_index < NumberOfFreeLists) { -+ larger_chunk = free_chunks(larger_chunk_index)->head(); -+ if (larger_chunk == NULL) { -+ larger_chunk_index = next_chunk_index(larger_chunk_index); -+ } -+ } -+ -+ if (larger_chunk != NULL) { -+ assert(larger_chunk->word_size() > word_size, "Sanity"); -+ assert(larger_chunk->get_chunk_type() == larger_chunk_index, "Sanity"); -+ -+ // We found a larger chunk. Lets split it up: -+ // - remove old chunk -+ // - in its place, create new smaller chunks, with at least one chunk -+ // being of target size, the others sized as large as possible. This -+ // is to make sure the resulting chunks are "as coalesced as possible" -+ // (similar to VirtualSpaceNode::retire()). -+ // Note: during this operation both ChunkManager and VirtualSpaceNode -+ // are temporarily invalid, so be careful with asserts. -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("%s: splitting chunk " PTR_FORMAT -+ ", word size " SIZE_FORMAT_HEX " (%s), to get a chunk of word size " SIZE_FORMAT_HEX " (%s)...", -+ (is_class() ? "class space" : "metaspace"), p2i(larger_chunk), larger_chunk->word_size(), -+ chunk_size_name(larger_chunk_index), word_size, chunk_size_name(target_chunk_index)); -+ } -+ -+ chunk = split_chunk(word_size, larger_chunk); -+ -+ // This should have worked. -+ assert(chunk != NULL, "Sanity"); -+ assert(chunk->word_size() == word_size, "Sanity"); -+ assert(chunk->is_tagged_free(), "Sanity"); -+ -+ we_did_split_a_chunk = true; -+ -+ } -+ } -+ - if (chunk == NULL) { - return NULL; - } -@@ -1899,9 +2977,8 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) { - free_list->remove_chunk(chunk); - - if (TraceMetadataChunkAllocation && Verbose) { -- gclog_or_tty->print_cr("ChunkManager::free_chunks_get: free_list " -- PTR_FORMAT " head " PTR_FORMAT " size " SIZE_FORMAT, -- free_list, chunk, chunk->word_size()); -+ gclog_or_tty->print_cr("ChunkManager::free_chunks_get: free_list: " PTR_FORMAT " chunks left: " SSIZE_FORMAT ".", -+ p2i(free_list), free_list->count()); - } - } else { - chunk = humongous_dictionary()->get_chunk( -@@ -1921,20 +2998,26 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) { - } - } - -- // Chunk is being removed from the chunks free list. -- dec_free_chunks_total(chunk->word_size()); -+ // Chunk has been removed from the chunk manager; update counters. -+ account_for_removed_chunk(chunk); -+ do_update_in_use_info_for_chunk(chunk, true); -+ chunk->container()->inc_container_count(); -+ chunk->inc_use_count(); - - // Remove it from the links to this freelist - chunk->set_next(NULL); - chunk->set_prev(NULL); -+ -+ // Run some verifications (some more if we did a chunk split) - #ifdef ASSERT -- // Chunk is no longer on any freelist. Setting to false make container_count_slow() -- // work. -- chunk->set_is_tagged_free(false); -+ locked_verify(); -+ VirtualSpaceNode* const vsn = chunk->container(); -+ vsn->verify(); -+ if (we_did_split_a_chunk) { -+ vsn->verify_free_chunks_are_ideally_merged(); -+ } - #endif -- chunk->container()->inc_container_count(); - -- slow_locked_verify(); - return chunk; - } - -@@ -1968,6 +3051,97 @@ Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) { - return chunk; - } - -+void ChunkManager::return_single_chunk(ChunkIndex index, Metachunk* chunk) { -+ assert_lock_strong(SpaceManager::expand_lock()); -+ DEBUG_ONLY(do_verify_chunk(chunk);) -+ assert(chunk->get_chunk_type() == index, "Chunk does not match expected index."); -+ assert(chunk != NULL, "Expected chunk."); -+ assert(chunk->container() != NULL, "Container should have been set."); -+ assert(chunk->is_tagged_free() == false, "Chunk should be in use."); -+ index_bounds_check(index); -+ -+ // Note: mangle *before* returning the chunk to the freelist or dictionary. It does not -+ // matter for the freelist (non-humongous chunks), but the humongous chunk dictionary -+ // keeps tree node pointers in the chunk payload area which mangle will overwrite. -+ DEBUG_ONLY(chunk->mangle(badMetaWordVal);) -+ -+ if (index != HumongousIndex) { -+ // Return non-humongous chunk to freelist. -+ ChunkList* list = free_chunks(index); -+ assert(list->size() == chunk->word_size(), "Wrong chunk type."); -+ list->return_chunk_at_head(chunk); -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("returned one %s chunk at " PTR_FORMAT " to freelist.", -+ chunk_size_name(index), p2i(chunk)); -+ } -+ } else { -+ // Return humongous chunk to dictionary. -+ assert(chunk->word_size() > free_chunks(MediumIndex)->size(), "Wrong chunk type."); -+ assert(chunk->word_size() % free_chunks(SpecializedIndex)->size() == 0, -+ "Humongous chunk has wrong alignment."); -+ _humongous_dictionary.return_chunk(chunk); -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("returned one %s chunk at " PTR_FORMAT " (word size " SIZE_FORMAT ") to freelist.", -+ chunk_size_name(index), p2i(chunk), chunk->word_size()); -+ } -+ } -+ chunk->container()->dec_container_count(); -+ do_update_in_use_info_for_chunk(chunk, false); -+ -+ // Chunk has been added; update counters. -+ account_for_added_chunk(chunk); -+ -+ // Attempt coalesce returned chunks with its neighboring chunks: -+ // if this chunk is small or special, attempt to coalesce to a medium chunk. -+ if (index == SmallIndex || index == SpecializedIndex) { -+ if (!attempt_to_coalesce_around_chunk(chunk, MediumIndex)) { -+ // This did not work. But if this chunk is special, we still may form a small chunk? -+ if (index == SpecializedIndex) { -+ if (!attempt_to_coalesce_around_chunk(chunk, SmallIndex)) { -+ // give up. -+ } -+ } -+ } -+ } -+ -+} -+ -+void ChunkManager::return_chunk_list(ChunkIndex index, Metachunk* chunks) { -+ index_bounds_check(index); -+ if (chunks == NULL) { -+ return; -+ } -+ // tracing -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("returning list of %s chunks...", chunk_size_name(index)); -+ } -+ -+ unsigned num_chunks_returned = 0; -+ size_t size_chunks_returned = 0; -+ Metachunk* cur = chunks; -+ while (cur != NULL) { -+ // Capture the next link before it is changed -+ // by the call to return_chunk_at_head(); -+ Metachunk* next = cur->next(); -+ // tracing -+ num_chunks_returned ++; -+ size_chunks_returned += cur->word_size(); -+ -+ return_single_chunk(index, cur); -+ cur = next; -+ } -+ // tracing -+ if (TraceMetadataChunkAllocation) { -+ gclog_or_tty->print_cr("returned %u %s chunks to freelist, total word size " SIZE_FORMAT ".", -+ num_chunks_returned, chunk_size_name(index), size_chunks_returned); -+ if (index != HumongousIndex) { -+ gclog_or_tty->print_cr("updated freelist count: " SIZE_FORMAT ".", free_chunks(index)->size()); -+ } else { -+ gclog_or_tty->print_cr("updated dictionary count " SIZE_FORMAT ".", _humongous_dictionary.total_count()); -+ } -+ } -+} -+ - void ChunkManager::print_on(outputStream* out) const { - if (PrintFLSStatistics != 0) { - _humongous_dictionary.report_statistics(); -@@ -2394,31 +3568,6 @@ void SpaceManager::initialize() { - } - } - --void ChunkManager::return_chunks(ChunkIndex index, Metachunk* chunks) { -- if (chunks == NULL) { -- return; -- } -- ChunkList* list = free_chunks(index); -- assert(list->size() == chunks->word_size(), "Mismatch in chunk sizes"); -- assert_lock_strong(SpaceManager::expand_lock()); -- Metachunk* cur = chunks; -- -- // This returns chunks one at a time. If a new -- // class List can be created that is a base class -- // of FreeList then something like FreeList::prepend() -- // can be used in place of this loop -- while (cur != NULL) { -- assert(cur->container() != NULL, "Container should have been set"); -- cur->container()->dec_container_count(); -- // Capture the next link before it is changed -- // by the call to return_chunk_at_head(); -- Metachunk* next = cur->next(); -- DEBUG_ONLY(cur->set_is_tagged_free(true);) -- list->return_chunk_at_head(cur); -- cur = next; -- } --} -- - SpaceManager::~SpaceManager() { - // This call this->_lock which can't be done while holding expand_lock() - assert(sum_capacity_in_chunks_in_use() == allocated_chunks_words(), -@@ -2429,6 +3578,11 @@ SpaceManager::~SpaceManager() { - MutexLockerEx fcl(SpaceManager::expand_lock(), - Mutex::_no_safepoint_check_flag); - -+ assert(sum_count_in_chunks_in_use() == allocated_chunks_count(), -+ err_msg("sum_count_in_chunks_in_use() " SIZE_FORMAT -+ " allocated_chunks_count() " SIZE_FORMAT, -+ sum_count_in_chunks_in_use(), allocated_chunks_count())); -+ - chunk_manager()->slow_locked_verify(); - - dec_total_from_size_metrics(); -@@ -2436,112 +3590,27 @@ SpaceManager::~SpaceManager() { - if (TraceMetadataChunkAllocation && Verbose) { - gclog_or_tty->print_cr("~SpaceManager(): " PTR_FORMAT, this); - locked_print_chunks_in_use_on(gclog_or_tty); -+ if (block_freelists() != NULL) { -+ block_freelists()->print_on(gclog_or_tty); -+ } - } - -- // Do not mangle freed Metachunks. The chunk size inside Metachunks -- // is during the freeing of a VirtualSpaceNodes. -- -- // Have to update before the chunks_in_use lists are emptied -- // below. -- chunk_manager()->inc_free_chunks_total(allocated_chunks_words(), -- sum_count_in_chunks_in_use()); -- - // Add all the chunks in use by this space manager - // to the global list of free chunks. - - // Follow each list of chunks-in-use and add them to the - // free lists. Each list is NULL terminated. - -- for (ChunkIndex i = ZeroIndex; i < HumongousIndex; i = next_chunk_index(i)) { -- if (TraceMetadataChunkAllocation && Verbose) { -- gclog_or_tty->print_cr("returned %d %s chunks to freelist", -- sum_count_in_chunks_in_use(i), -- chunk_size_name(i)); -- } -+ for (ChunkIndex i = ZeroIndex; i <= HumongousIndex; i = next_chunk_index(i)) { - Metachunk* chunks = chunks_in_use(i); -- chunk_manager()->return_chunks(i, chunks); -+ chunk_manager()->return_chunk_list(i, chunks); - set_chunks_in_use(i, NULL); -- if (TraceMetadataChunkAllocation && Verbose) { -- gclog_or_tty->print_cr("updated freelist count %d %s", -- chunk_manager()->free_chunks(i)->count(), -- chunk_size_name(i)); -- } -- assert(i != HumongousIndex, "Humongous chunks are handled explicitly later"); - } - -- // The medium chunk case may be optimized by passing the head and -- // tail of the medium chunk list to add_at_head(). The tail is often -- // the current chunk but there are probably exceptions. -- -- // Humongous chunks -- if (TraceMetadataChunkAllocation && Verbose) { -- gclog_or_tty->print_cr("returned %d %s humongous chunks to dictionary", -- sum_count_in_chunks_in_use(HumongousIndex), -- chunk_size_name(HumongousIndex)); -- gclog_or_tty->print("Humongous chunk dictionary: "); -- } -- // Humongous chunks are never the current chunk. -- Metachunk* humongous_chunks = chunks_in_use(HumongousIndex); - -- while (humongous_chunks != NULL) { --#ifdef ASSERT -- humongous_chunks->set_is_tagged_free(true); --#endif -- if (TraceMetadataChunkAllocation && Verbose) { -- gclog_or_tty->print(PTR_FORMAT " (" SIZE_FORMAT ") ", -- humongous_chunks, -- humongous_chunks->word_size()); -- } -- assert(humongous_chunks->word_size() == (size_t) -- align_size_up(humongous_chunks->word_size(), -- smallest_chunk_size()), -- err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT -- " granularity %d", -- humongous_chunks->word_size(), smallest_chunk_size())); -- Metachunk* next_humongous_chunks = humongous_chunks->next(); -- humongous_chunks->container()->dec_container_count(); -- chunk_manager()->humongous_dictionary()->return_chunk(humongous_chunks); -- humongous_chunks = next_humongous_chunks; -- } -- if (TraceMetadataChunkAllocation && Verbose) { -- gclog_or_tty->cr(); -- gclog_or_tty->print_cr("updated dictionary count %d %s", -- chunk_manager()->humongous_dictionary()->total_count(), -- chunk_size_name(HumongousIndex)); -- } - chunk_manager()->slow_locked_verify(); - } - --const char* SpaceManager::chunk_size_name(ChunkIndex index) const { -- switch (index) { -- case SpecializedIndex: -- return "Specialized"; -- case SmallIndex: -- return "Small"; -- case MediumIndex: -- return "Medium"; -- case HumongousIndex: -- return "Humongous"; -- default: -- return NULL; -- } --} -- --ChunkIndex ChunkManager::list_index(size_t size) { -- if (free_chunks(SpecializedIndex)->size() == size) { -- return SpecializedIndex; -- } -- if (free_chunks(SmallIndex)->size() == size) { -- return SmallIndex; -- } -- if (free_chunks(MediumIndex)->size() == size) { -- return MediumIndex; -- } -- -- assert(size > free_chunks(MediumIndex)->size(), "Not a humongous chunk"); -- return HumongousIndex; --} -- - void SpaceManager::deallocate(MetaWord* p, size_t word_size) { - assert_lock_strong(_lock); - size_t raw_word_size = get_raw_word_size(word_size); -@@ -2693,8 +3762,8 @@ void SpaceManager::verify() { - for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { - Metachunk* curr = chunks_in_use(i); - while (curr != NULL) { -- curr->verify(); -- verify_chunk_size(curr); -+ DEBUG_ONLY(do_verify_chunk(curr);) -+ assert(curr->is_tagged_free() == false, "Chunk should be tagged as in use."); - curr = curr->next(); - } - } -@@ -2767,7 +3836,7 @@ void SpaceManager::mangle_freed_chunks() { - for (Metachunk* curr = chunks_in_use(index); - curr != NULL; - curr = curr->next()) { -- curr->mangle(); -+ curr->mangle(uninitMetaWordVal); - } - } - } -@@ -2988,9 +4057,9 @@ void MetaspaceAux::print_on(outputStream* out, Metaspace::MetadataType mdtype) { - size_t free_bytes = free_bytes_slow(mdtype); - size_t used_and_free = used_bytes + free_bytes + - free_chunks_capacity_bytes; -- out->print_cr(" Chunk accounting: used in chunks " SIZE_FORMAT -+ out->print_cr(" Chunk accounting: (used in chunks " SIZE_FORMAT - "K + unused in chunks " SIZE_FORMAT "K + " -- " capacity in free chunks " SIZE_FORMAT "K = " SIZE_FORMAT -+ " capacity in free chunks " SIZE_FORMAT "K) = " SIZE_FORMAT - "K capacity in allocated chunks " SIZE_FORMAT "K", - used_bytes / K, - free_bytes / K, -@@ -3255,6 +4324,31 @@ void MetaspaceAux::dump(outputStream* out) { - print_waste(out); - } - -+// Prints an ASCII representation of the given space. -+void MetaspaceAux::print_metaspace_map(outputStream* out, Metaspace::MetadataType mdtype) { -+ MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); -+ const bool for_class = mdtype == Metaspace::ClassType ? true : false; -+ VirtualSpaceList* const vsl = for_class ? Metaspace::class_space_list() : Metaspace::space_list(); -+ if (vsl != NULL) { -+ if (for_class) { -+ if (!Metaspace::using_class_space()) { -+ out->print_cr("No Class Space."); -+ return; -+ } -+ out->print_raw("---- Metaspace Map (Class Space) ----"); -+ } else { -+ out->print_raw("---- Metaspace Map (Non-Class Space) ----"); -+ } -+ // Print legend: -+ out->cr(); -+ out->print_cr("Chunk Types (uppercase chunks are in use): x-specialized, s-small, m-medium, h-humongous."); -+ out->cr(); -+ VirtualSpaceList* const vsl = for_class ? Metaspace::class_space_list() : Metaspace::space_list(); -+ vsl->print_map(out); -+ out->cr(); -+ } -+} -+ - void MetaspaceAux::verify_free_chunks() { - Metaspace::chunk_manager_metadata()->verify(); - if (Metaspace::using_class_space()) { -@@ -3523,7 +4617,7 @@ void Metaspace::initialize_class_space(ReservedSpace rs) { - err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), CompressedClassSpaceSize)); - assert(using_class_space(), "Must be using class space"); - _class_space_list = new VirtualSpaceList(rs); -- _chunk_manager_class = new ChunkManager(ClassSpecializedChunk, ClassSmallChunk, ClassMediumChunk); -+ _chunk_manager_class = new ChunkManager(true/*is_class*/); - - if (!_class_space_list->initialization_succeeded()) { - vm_exit_during_initialization("Failed to setup compressed class space virtual space list."); -@@ -3627,7 +4721,7 @@ void Metaspace::global_initialize() { - cds_total = FileMapInfo::shared_spaces_size(); - cds_total = align_size_up(cds_total, _reserve_alignment); - _space_list = new VirtualSpaceList(cds_total/wordSize); -- _chunk_manager_metadata = new ChunkManager(SpecializedChunk, SmallChunk, MediumChunk); -+ _chunk_manager_metadata = new ChunkManager(false/*metaspace*/); - - if (!_space_list->initialization_succeeded()) { - vm_exit_during_initialization("Unable to dump shared archive.", NULL); -@@ -3777,7 +4871,7 @@ void Metaspace::global_initialize() { - - // Initialize the list of virtual spaces. - _space_list = new VirtualSpaceList(word_size); -- _chunk_manager_metadata = new ChunkManager(SpecializedChunk, SmallChunk, MediumChunk); -+ _chunk_manager_metadata = new ChunkManager(false/*metaspace*/); - - if (!_space_list->initialization_succeeded()) { - vm_exit_during_initialization("Unable to setup metadata virtual space list.", NULL); -@@ -4071,6 +5165,8 @@ void Metaspace::report_metadata_oome(ClassLoaderData* loader_data, size_t word_s - ChunkManager::print_all_chunkmanagers(gclog_or_tty); - } - -+ MetaspaceAux::print_metaspace_map(gclog_or_tty, mdtype); -+ - bool out_of_compressed_class_space = false; - if (is_class_space_allocation(mdtype)) { - Metaspace* metaspace = loader_data->metaspace_non_null(); -@@ -4236,6 +5332,24 @@ void Metaspace::dump(outputStream* const out) const { - } - } - -+#ifdef ASSERT -+static void do_verify_chunk(Metachunk* chunk) { -+ guarantee(chunk != NULL, "Sanity"); -+ // Verify chunk itself; then verify that it is consistent with the -+ // occupany map of its containing node. -+ chunk->verify(); -+ VirtualSpaceNode* const vsn = chunk->container(); -+ OccupancyMap* const ocmap = vsn->occupancy_map(); -+ ocmap->verify_for_chunk(chunk); -+} -+#endif -+ -+static void do_update_in_use_info_for_chunk(Metachunk* chunk, bool inuse) { -+ chunk->set_is_tagged_free(!inuse); -+ OccupancyMap* const ocmap = chunk->container()->occupancy_map(); -+ ocmap->set_region_in_use((MetaWord*)chunk, chunk->word_size(), inuse); -+} -+ - /////////////// Unit tests /////////////// - - #ifndef PRODUCT -@@ -4326,16 +5440,16 @@ class TestVirtualSpaceNodeTest { - STATIC_ASSERT(SmallChunk % SpecializedChunk == 0); - - { // No committed memory in VSN -- ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk); -- VirtualSpaceNode vsn(vsn_test_size_bytes); -+ ChunkManager cm(false); -+ VirtualSpaceNode vsn(false, vsn_test_size_bytes); - vsn.initialize(); - vsn.retire(&cm); - assert(cm.sum_free_chunks_count() == 0, "did not commit any memory in the VSN"); - } - - { // All of VSN is committed, half is used by chunks -- ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk); -- VirtualSpaceNode vsn(vsn_test_size_bytes); -+ ChunkManager cm(false); -+ VirtualSpaceNode vsn(false, vsn_test_size_bytes); - vsn.initialize(); - vsn.expand_by(vsn_test_size_words, vsn_test_size_words); - vsn.get_chunk_vs(MediumChunk); -@@ -4349,8 +5463,8 @@ class TestVirtualSpaceNodeTest { - // This doesn't work for systems with vm_page_size >= 16K. - if (page_chunks < MediumChunk) { - // 4 pages of VSN is committed, some is used by chunks -- ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk); -- VirtualSpaceNode vsn(vsn_test_size_bytes); -+ ChunkManager cm(false); -+ VirtualSpaceNode vsn(false, vsn_test_size_bytes); - - vsn.initialize(); - vsn.expand_by(page_chunks, page_chunks); -@@ -4370,8 +5484,8 @@ class TestVirtualSpaceNodeTest { - } - - { // Half of VSN is committed, a humongous chunk is used -- ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk); -- VirtualSpaceNode vsn(vsn_test_size_bytes); -+ ChunkManager cm(false); -+ VirtualSpaceNode vsn(false, vsn_test_size_bytes); - vsn.initialize(); - vsn.expand_by(MediumChunk * 2, MediumChunk * 2); - vsn.get_chunk_vs(MediumChunk + SpecializedChunk); // Humongous chunks will be aligned up to MediumChunk + SpecializedChunk -@@ -4402,7 +5516,7 @@ class TestVirtualSpaceNodeTest { - - static void test_is_available_positive() { - // Reserve some memory. -- VirtualSpaceNode vsn(os::vm_allocation_granularity()); -+ VirtualSpaceNode vsn(false, os::vm_allocation_granularity()); - assert(vsn.initialize(), "Failed to setup VirtualSpaceNode"); - - // Commit some memory. -@@ -4420,7 +5534,7 @@ class TestVirtualSpaceNodeTest { - - static void test_is_available_negative() { - // Reserve some memory. -- VirtualSpaceNode vsn(os::vm_allocation_granularity()); -+ VirtualSpaceNode vsn(false, os::vm_allocation_granularity()); - assert(vsn.initialize(), "Failed to setup VirtualSpaceNode"); - - // Commit some memory. -@@ -4435,7 +5549,7 @@ class TestVirtualSpaceNodeTest { - - static void test_is_available_overflow() { - // Reserve some memory. -- VirtualSpaceNode vsn(os::vm_allocation_granularity()); -+ VirtualSpaceNode vsn(false, os::vm_allocation_granularity()); - assert(vsn.initialize(), "Failed to setup VirtualSpaceNode"); - - // Commit some memory. -@@ -4460,11 +5574,240 @@ class TestVirtualSpaceNodeTest { - } - }; - --void TestVirtualSpaceNode_test() { -- TestVirtualSpaceNodeTest::test(); -- TestVirtualSpaceNodeTest::test_is_available(); -+#ifdef DEBUG_VERBOSE -+ -+struct chunkmanager_statistics_t { -+ int num_specialized_chunks; -+ int num_small_chunks; -+ int num_medium_chunks; -+ int num_humongous_chunks; -+}; -+ -+void test_metaspace_retrieve_chunkmanager_statistics(Metaspace::MetadataType mdType, chunkmanager_statistics_t* out) { -+ ChunkManager* const chunk_manager = Metaspace::get_chunk_manager(mdType); -+ ChunkManager::ChunkManagerStatistics stat; -+ chunk_manager->get_statistics(&stat); -+ out->num_specialized_chunks = (int)stat.num_by_type[SpecializedIndex]; -+ out->num_small_chunks = (int)stat.num_by_type[SmallIndex]; -+ out->num_medium_chunks = (int)stat.num_by_type[MediumIndex]; -+ out->num_humongous_chunks = (int)stat.num_humongous_chunks; -+} -+ -+static void print_chunkmanager_statistics(outputStream* st, Metaspace::MetadataType mdType) { -+ chunkmanager_statistics_t stat; -+ test_metaspace_retrieve_chunkmanager_statistics(mdType, &stat); -+ st->print_cr("free chunks: %d / %d / %d / %d", stat.num_specialized_chunks, stat.num_small_chunks, -+ stat.num_medium_chunks, stat.num_humongous_chunks); -+} -+ -+#endif // DEBUG_VERBOSE -+ -+struct chunk_geometry_t { -+ size_t specialized_chunk_word_size; -+ size_t small_chunk_word_size; -+ size_t medium_chunk_word_size; -+}; -+ -+void test_metaspace_retrieve_chunk_geometry(Metaspace::MetadataType mdType, chunk_geometry_t* out) { -+ if (mdType == Metaspace::NonClassType) { -+ out->specialized_chunk_word_size = SpecializedChunk; -+ out->small_chunk_word_size = SmallChunk; -+ out->medium_chunk_word_size = MediumChunk; -+ } else { -+ out->specialized_chunk_word_size = ClassSpecializedChunk; -+ out->small_chunk_word_size = ClassSmallChunk; -+ out->medium_chunk_word_size = ClassMediumChunk; -+ } -+} -+ -+#define NUM_PARALLEL_METASPACES 50 -+#define MAX_PER_METASPACE_ALLOCATION_WORDSIZE (512 * K) -+ -+class MetaspaceAllocationTest { -+protected: -+ -+ struct { -+ size_t allocated; -+ Mutex* lock; -+ Metaspace* space; -+ bool is_empty() const { return allocated == 0; } -+ bool is_full() const { return allocated >= MAX_PER_METASPACE_ALLOCATION_WORDSIZE; } -+ } _spaces[NUM_PARALLEL_METASPACES]; -+ -+ chunk_geometry_t _chunk_geometry; -+ -+ void create_space(int i) { -+ assert(i >= 0 && i < NUM_PARALLEL_METASPACES, "Sanity"); -+ assert(_spaces[i].space == NULL && _spaces[i].allocated == 0, "Sanity"); -+ if (_spaces[i].lock == NULL) { -+ _spaces[i].lock = new Mutex(Monitor::native, "gtest-MetaspaceAllocationTest-lock", false); -+ assert(_spaces[i].lock != NULL, "_spaces[i].lock is NULL"); -+ } -+ // Let every ~10th space be an anonymous one to test different allocation patterns. -+ const Metaspace::MetaspaceType msType = (os::random() % 100 < 10) ? -+ Metaspace::AnonymousMetaspaceType : Metaspace::StandardMetaspaceType; -+ _spaces[i].space = new Metaspace(_spaces[i].lock, msType); -+ _spaces[i].allocated = 0; -+ assert(_spaces[i].space != NULL, "_spaces[i].space is NULL"); -+ } -+ -+ // Returns the index of a random space where index is [0..metaspaces) and which is -+ // empty, non-empty or full. -+ // Returns -1 if no matching space exists. -+ enum fillgrade { fg_empty, fg_non_empty, fg_full }; -+ int get_random_matching_space(int metaspaces, fillgrade fg) { -+ const int start_index = os::random() % metaspaces; -+ int i = start_index; -+ do { -+ if (fg == fg_empty && _spaces[i].is_empty()) { -+ return i; -+ } else if ((fg == fg_full && _spaces[i].is_full()) || -+ (fg == fg_non_empty && !_spaces[i].is_full() && !_spaces[i].is_empty())) { -+ return i; -+ } -+ i ++; -+ if (i == metaspaces) { -+ i = 0; -+ } -+ } while (i != start_index); -+ return -1; -+ } -+ -+ int get_random_emtpy_space(int metaspaces) { return get_random_matching_space(metaspaces, fg_empty); } -+ int get_random_non_emtpy_space(int metaspaces) { return get_random_matching_space(metaspaces, fg_non_empty); } -+ int get_random_full_space(int metaspaces) { return get_random_matching_space(metaspaces, fg_full); } -+ -+public: -+ -+ virtual void SetUp() { -+ ::memset(_spaces, 0, sizeof(_spaces)); -+ test_metaspace_retrieve_chunk_geometry(Metaspace::NonClassType, &_chunk_geometry); -+ } -+ -+ virtual void TearDown() { -+ for (int i = 0; i < NUM_PARALLEL_METASPACES; i ++) { -+ if (_spaces[i].space != NULL) { -+ delete _spaces[i].space; -+ delete _spaces[i].lock; -+ } -+ } -+ } -+ -+ void do_test(Metaspace::MetadataType mdType, int metaspaces, int phases, int allocs_per_phase, -+ float probability_for_large_allocations // 0.0-1.0 -+ ) { -+ // Alternate between breathing in (allocating n blocks for a random Metaspace) and -+ // breathing out (deleting a random Metaspace). The intent is to stress the coalescation -+ // and splitting of free chunks. -+ int phases_done = 0; -+ bool allocating = true; -+ while (phases_done < phases) { -+ bool force_switch = false; -+ if (allocating) { -+ // Allocate space from metaspace, with a preference for completely empty spaces. This -+ // should provide a good mixture of metaspaces in the virtual space. -+ int index = get_random_emtpy_space(metaspaces); -+ if (index == -1) { -+ index = get_random_non_emtpy_space(metaspaces); -+ } -+ if (index == -1) { -+ // All spaces are full, switch to freeing. -+ force_switch = true; -+ } else { -+ // create space if it does not yet exist. -+ if (_spaces[index].space == NULL) { -+ create_space(index); -+ } -+ // Allocate a bunch of blocks from it. Mostly small stuff but mix in large allocations -+ // to force humongous chunk allocations. -+ int allocs_done = 0; -+ while (allocs_done < allocs_per_phase && !_spaces[index].is_full()) { -+ size_t size = 0; -+ int r = os::random() % 1000; -+ if ((float)r < probability_for_large_allocations * 1000.0) { -+ size = (os::random() % _chunk_geometry.medium_chunk_word_size) + _chunk_geometry.medium_chunk_word_size; -+ } else { -+ size = os::random() % 64; -+ } -+ MetaWord* const p = _spaces[index].space->allocate(size, mdType); -+ if (p == NULL) { -+ // We very probably did hit the metaspace "until-gc" limit. -+#ifdef DEBUG_VERBOSE -+ tty->print_cr("OOM for " SIZE_FORMAT " words. ", size); -+#endif -+ // Just switch to deallocation and resume tests. -+ force_switch = true; -+ break; -+ } else { -+ _spaces[index].allocated += size; -+ allocs_done ++; -+ } -+ } -+ } -+ } else { -+ // freeing: find a metaspace and delete it, with preference for completely filled spaces. -+ int index = get_random_full_space(metaspaces); -+ if (index == -1) { -+ index = get_random_non_emtpy_space(metaspaces); -+ } -+ if (index == -1) { -+ force_switch = true; -+ } else { -+ assert(_spaces[index].space != NULL && _spaces[index].allocated > 0, "Sanity"); -+ delete _spaces[index].space; -+ _spaces[index].space = NULL; -+ _spaces[index].allocated = 0; -+ } -+ } -+ -+ if (force_switch) { -+ allocating = !allocating; -+ } else { -+ // periodically switch between allocating and freeing, but prefer allocation because -+ // we want to intermingle allocations of multiple metaspaces. -+ allocating = os::random() % 5 < 4; -+ } -+ phases_done ++; -+#ifdef DEBUG_VERBOSE -+ int metaspaces_in_use = 0; -+ size_t total_allocated = 0; -+ for (int i = 0; i < metaspaces; i ++) { -+ if (_spaces[i].allocated > 0) { -+ total_allocated += _spaces[i].allocated; -+ metaspaces_in_use ++; -+ } -+ } -+ tty->print("%u:\tspaces: %d total words: " SIZE_FORMAT "\t\t\t", phases_done, metaspaces_in_use, total_allocated); -+ print_chunkmanager_statistics(tty, mdType); -+#endif -+ } -+#ifdef DEBUG_VERBOSE -+ tty->print_cr("Test finished. "); -+ MetaspaceAux::print_metaspace_map(tty, mdType); -+ print_chunkmanager_statistics(tty, mdType); -+#endif -+ } -+}; -+ -+void MetaspaceAllocation_test(Metaspace::MetadataType mdType, int metaspaces, int phases, int allocs_per_phase, float probability_for_large_allocations) { -+ MetaspaceAllocationTest test; -+ test.SetUp(); -+ test.do_test(mdType, metaspaces, phases, allocs_per_phase, probability_for_large_allocations); -+ test.TearDown(); - } - -+void run_MetaspaceAllocation_test(){ -+ MetaspaceAllocation_test(Metaspace::NonClassType, 1, 1000, 100, 0); -+ MetaspaceAllocation_test(Metaspace::ClassType, 1, 1000, 100, 0); -+ MetaspaceAllocation_test(Metaspace::NonClassType, NUM_PARALLEL_METASPACES, 100, 1000, 0.0); -+ MetaspaceAllocation_test(Metaspace::ClassType, NUM_PARALLEL_METASPACES, 100, 1000, 0.0); -+ MetaspaceAllocation_test(Metaspace::NonClassType, NUM_PARALLEL_METASPACES, 100, 1000, .006f); -+} -+ -+#endif // !PRODUCT -+ -+#ifdef ASSERT -+ - // The following test is placed here instead of a gtest / unittest file - // because the ChunkManager class is only available in this file. - class SpaceManagerTest : AllStatic { -@@ -4517,7 +5860,7 @@ void SpaceManager_test_adjust_initial_chunk_size() { - // The following test is placed here instead of a gtest / unittest file - // because the ChunkManager class is only available in this file. - void ChunkManager_test_list_index() { -- ChunkManager manager(ClassSpecializedChunk, ClassSmallChunk, ClassMediumChunk); -+ ChunkManager manager(true); - - // Test previous bug where a query for a humongous class metachunk, - // incorrectly matched the non-class medium metachunk size. -@@ -4550,4 +5893,5 @@ void ChunkManager_test_list_index() { - } - } - --#endif -+#endif // ASSERT -+ -diff --git a/hotspot/src/share/vm/memory/metaspace.hpp b/hotspot/src/share/vm/memory/metaspace.hpp -index ff1b23299..11944d393 100644 ---- a/hotspot/src/share/vm/memory/metaspace.hpp -+++ b/hotspot/src/share/vm/memory/metaspace.hpp -@@ -147,11 +147,6 @@ class Metaspace : public CHeapObj { - return mdtype == ClassType ? class_vsm() : vsm(); - } - -- // Allocate space for metadata of type mdtype. This is space -- // within a Metachunk and is used by -- // allocate(ClassLoaderData*, size_t, bool, MetadataType, TRAPS) -- MetaWord* allocate(size_t word_size, MetadataType mdtype); -- - // Virtual Space lists for both classes and other metadata - static VirtualSpaceList* _space_list; - static VirtualSpaceList* _class_space_list; -@@ -162,6 +157,10 @@ class Metaspace : public CHeapObj { - static const MetaspaceTracer* _tracer; - - public: -+ // Allocate space for metadata of type mdtype. This is space -+ // within a Metachunk and is used by -+ // allocate(ClassLoaderData*, size_t, bool, MetadataType, TRAPS) -+ MetaWord* allocate(size_t word_size, MetadataType mdtype); - static VirtualSpaceList* space_list() { return _space_list; } - static VirtualSpaceList* class_space_list() { return _class_space_list; } - static VirtualSpaceList* get_space_list(MetadataType mdtype) { -@@ -176,6 +175,11 @@ class Metaspace : public CHeapObj { - return mdtype == ClassType ? chunk_manager_class() : chunk_manager_metadata(); - } - -+ // convenience function -+ static ChunkManager* get_chunk_manager(bool is_class) { -+ return is_class ? chunk_manager_class() : chunk_manager_metadata(); -+ } -+ - static const MetaspaceTracer* tracer() { return _tracer; } - - private: -@@ -386,6 +390,10 @@ class MetaspaceAux : AllStatic { - - static void print_class_waste(outputStream* out); - static void print_waste(outputStream* out); -+ -+ // Prints an ASCII representation of the given space. -+ static void print_metaspace_map(outputStream* out, Metaspace::MetadataType mdtype); -+ - static void dump(outputStream* out); - static void verify_free_chunks(); - // Checks that the values returned by allocated_capacity_bytes() and -diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp -index dccbf1e8a..953300ebc 100644 ---- a/hotspot/src/share/vm/prims/jni.cpp -+++ b/hotspot/src/share/vm/prims/jni.cpp -@@ -5112,9 +5112,9 @@ void TestReservedSpace_test(); - void TestReserveMemorySpecial_test(); - void TestVirtualSpace_test(); - void TestMetaspaceAux_test(); -+void run_MetaspaceAllocation_test(); - void SpaceManager_test_adjust_initial_chunk_size(); - void TestMetachunk_test(); --void TestVirtualSpaceNode_test(); - void TestNewSize_test(); - void TestKlass_test(); - void Test_linked_list(); -@@ -5137,8 +5137,8 @@ void execute_internal_vm_tests() { - run_unit_test(TestReserveMemorySpecial_test()); - run_unit_test(TestVirtualSpace_test()); - run_unit_test(TestMetaspaceAux_test()); -+ run_unit_test(run_MetaspaceAllocation_test()); - run_unit_test(TestMetachunk_test()); -- run_unit_test(TestVirtualSpaceNode_test()); - run_unit_test(GlobalDefinitions::test_globals()); - run_unit_test(GlobalDefinitions::test_proper_unit()); - run_unit_test(GCTimerAllTest::all()); -diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp -index 12eea20fc..efa430663 100644 ---- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp -+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp -@@ -1079,6 +1079,7 @@ const int badHandleValue = 0xBC; // value used to zap - const int badResourceValue = 0xAB; // value used to zap resource area - const int freeBlockPad = 0xBA; // value used to pad freed blocks. - const int uninitBlockPad = 0xF1; // value used to zap newly malloc'd blocks. -+const juint uninitMetaWordVal= 0xf7f7f7f7; // value used to zap newly allocated metachunk - const intptr_t badJNIHandleVal = (intptr_t) CONST64(0xFEFEFEFEFEFEFEFE); // value used to zap jni handle area - const juint badHeapWordVal = 0xBAADBABE; // value used to zap heap after GC - const juint badMetaWordVal = 0xBAADFADE; // value used to zap metadata heap after GC --- -2.22.0 - diff --git a/add-8226530-ZipFile-reads-wrong-entry-size-from-ZIP6.patch b/add-8226530-ZipFile-reads-wrong-entry-size-from-ZIP6.patch deleted file mode 100644 index c0df133f9d6512cbb541baf7177f48f05038794d..0000000000000000000000000000000000000000 --- a/add-8226530-ZipFile-reads-wrong-entry-size-from-ZIP6.patch +++ /dev/null @@ -1,274 +0,0 @@ -From 131462b71b86d97bd7dadf7a099d4395d9057423 Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:16:36 +0800 -Subject: add 8226530-ZipFile-reads-wrong-entry-size-from-ZIP64-en - ---- - .../share/classes/java/util/zip/ZipEntry.java | 41 +++-- - .../share/classes/java/util/zip/ZipFile.java | 2 +- - .../classes/java/util/zip/ZipInputStream.java | 4 +- - .../java/util/zip/ZipFile/Zip64SizeTest.java | 147 ++++++++++++++++++ - 4 files changed, 179 insertions(+), 15 deletions(-) - create mode 100644 jdk/test/java/util/zip/ZipFile/Zip64SizeTest.java - -diff --git a/jdk/src/share/classes/java/util/zip/ZipEntry.java b/jdk/src/share/classes/java/util/zip/ZipEntry.java -index aa93bcb36..4a15428ac 100644 ---- a/jdk/src/share/classes/java/util/zip/ZipEntry.java -+++ b/jdk/src/share/classes/java/util/zip/ZipEntry.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 1995, 2019, 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 -@@ -440,7 +440,7 @@ class ZipEntry implements ZipConstants, Cloneable { - * @see #getExtra() - */ - public void setExtra(byte[] extra) { -- setExtra0(extra, false); -+ setExtra0(extra, false, true); - } - - /** -@@ -450,8 +450,11 @@ class ZipEntry implements ZipConstants, Cloneable { - * the extra field data bytes - * @param doZIP64 - * if true, set size and csize from ZIP64 fields if present -+ * @param isLOC -+ * true if setting the extra field for a LOC, false if for -+ * a CEN - */ -- void setExtra0(byte[] extra, boolean doZIP64) { -+ void setExtra0(byte[] extra, boolean doZIP64, boolean isLOC) { - if (extra != null) { - if (extra.length > 0xFFFF) { - throw new IllegalArgumentException("invalid extra field length"); -@@ -468,15 +471,29 @@ class ZipEntry implements ZipConstants, Cloneable { - switch (tag) { - case EXTID_ZIP64: - if (doZIP64) { -- // LOC extra zip64 entry MUST include BOTH original -- // and compressed file size fields. -- // If invalid zip64 extra fields, simply skip. Even -- // it's rare, it's possible the entry size happens to -- // be the magic value and it "accidently" has some -- // bytes in extra match the id. -- if (sz >= 16) { -- size = get64(extra, off); -- csize = get64(extra, off + 8); -+ if (isLOC) { -+ // LOC extra zip64 entry MUST include BOTH original -+ // and compressed file size fields. -+ // If invalid zip64 extra fields, simply skip. Even -+ // it's rare, it's possible the entry size happens to -+ // be the magic value and it "accidently" has some -+ // bytes in extra match the id. -+ if (sz >= 16) { -+ size = get64(extra, off); -+ csize = get64(extra, off + 8); -+ } -+ } else { -+ // CEN extra zip64 -+ if (size == ZIP64_MAGICVAL) { -+ if (off + 8 > len) // invalid zip64 extra -+ break; // fields, just skip -+ size = get64(extra, off); -+ } -+ if (csize == ZIP64_MAGICVAL) { -+ if (off + 16 > len) // invalid zip64 extra -+ break; // fields, just skip -+ csize = get64(extra, off + 8); -+ } - } - } - break; -diff --git a/jdk/src/share/classes/java/util/zip/ZipFile.java b/jdk/src/share/classes/java/util/zip/ZipFile.java -index 5d9b0de97..9e854e84d 100644 ---- a/jdk/src/share/classes/java/util/zip/ZipFile.java -+++ b/jdk/src/share/classes/java/util/zip/ZipFile.java -@@ -556,7 +556,7 @@ class ZipFile implements ZipConstants, Closeable { - e.method = CENHOW(cen, pos); - if (elen != 0) { - int start = pos + CENHDR + nlen; -- e.setExtra0(Arrays.copyOfRange(cen, start, start + elen), true); -+ e.setExtra0(Arrays.copyOfRange(cen, start, start + elen), true, false); - } - if (clen != 0) { - int start = pos + CENHDR + nlen + elen; -diff --git a/jdk/src/share/classes/java/util/zip/ZipInputStream.java b/jdk/src/share/classes/java/util/zip/ZipInputStream.java -index 98526ef82..398dd70ad 100644 ---- a/jdk/src/share/classes/java/util/zip/ZipInputStream.java -+++ b/jdk/src/share/classes/java/util/zip/ZipInputStream.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 1996, 2019, 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 -@@ -320,7 +320,7 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants { - byte[] extra = new byte[len]; - readFully(extra, 0, len); - e.setExtra0(extra, -- e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL); -+ e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL, true); - } - return e; - } -diff --git a/jdk/test/java/util/zip/ZipFile/Zip64SizeTest.java b/jdk/test/java/util/zip/ZipFile/Zip64SizeTest.java -new file mode 100644 -index 000000000..be701e480 ---- /dev/null -+++ b/jdk/test/java/util/zip/ZipFile/Zip64SizeTest.java -@@ -0,0 +1,147 @@ -+/* -+ * Copyright (c) 2019, 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. -+ */ -+import org.testng.annotations.AfterMethod; -+import org.testng.annotations.BeforeMethod; -+import org.testng.annotations.Test; -+ -+import java.io.*; -+import java.nio.file.Files; -+import java.nio.file.Path; -+import java.util.List; -+import java.util.zip.ZipEntry; -+import java.util.zip.ZipFile; -+import java.util.zip.ZipOutputStream; -+ -+import static org.testng.Assert.assertTrue; -+ -+/** -+ * @test -+ * @bug 8226530 -+ * @summary ZIP File System tests that leverage DirectoryStream -+ * @modules java.base -+ * @compile Zip64SizeTest.java -+ * @run testng Zip64SizeTest -+ */ -+public class Zip64SizeTest { -+ -+ private static final int BUFFER_SIZE = 2048; -+ // ZIP file to create -+ private static final String ZIP_FILE_NAME = "Zip64SizeTest.zip"; -+ // File that will be created with a size greater than 0xFFFFFFFF -+ private static final String LARGE_FILE_NAME = "LargeZipEntry.txt"; -+ // File that will be created with a size less than 0xFFFFFFFF -+ private static final String SMALL_FILE_NAME = "SmallZipEntry.txt"; -+ // List of files to be added to the ZIP file -+ private static final List ZIP_ENTRIES = List.of(LARGE_FILE_NAME, -+ SMALL_FILE_NAME); -+ private static final long LARGE_FILE_SIZE = 5L * 1024L * 1024L * 1024L; // 5GB -+ private static final long SMALL_FILE_SIZE = 0x100000L; // 1024L x 1024L; -+ -+ /** -+ * Validate that if the size of a ZIP entry exceeds 0xFFFFFFFF, that the -+ * correct size is returned from the ZIP64 Extended information. -+ * @throws IOException -+ */ -+ @Test -+ private static void validateZipEntrySizes() throws IOException { -+ createFiles(); -+ createZipFile(); -+ System.out.println("Validating Zip Entry Sizes"); -+ try (ZipFile zip = new ZipFile(ZIP_FILE_NAME)) { -+ ZipEntry ze = zip.getEntry(LARGE_FILE_NAME); -+ System.out.printf("Entry: %s, size= %s%n", ze.getName(), ze.getSize()); -+ assertTrue(ze.getSize() == LARGE_FILE_SIZE); -+ ze = zip.getEntry(SMALL_FILE_NAME); -+ System.out.printf("Entry: %s, size= %s%n", ze.getName(), ze.getSize()); -+ assertTrue(ze.getSize() == SMALL_FILE_SIZE); -+ -+ } -+ } -+ -+ /** -+ * Delete the files created for use by the test -+ * @throws IOException if an error occurs deleting the files -+ */ -+ private static void deleteFiles() throws IOException { -+ Files.deleteIfExists(Path.of(ZIP_FILE_NAME)); -+ Files.deleteIfExists(Path.of(LARGE_FILE_NAME)); -+ Files.deleteIfExists(Path.of(SMALL_FILE_NAME)); -+ } -+ -+ /** -+ * Create the ZIP file adding an entry whose size exceeds 0xFFFFFFFF -+ * @throws IOException if an error occurs creating the ZIP File -+ */ -+ private static void createZipFile() throws IOException { -+ try (FileOutputStream fos = new FileOutputStream(ZIP_FILE_NAME); -+ ZipOutputStream zos = new ZipOutputStream(fos)) { -+ System.out.printf("Creating Zip file: %s%n", ZIP_FILE_NAME); -+ for (String srcFile : ZIP_ENTRIES) { -+ System.out.printf("...Adding Entry: %s%n", srcFile); -+ File fileToZip = new File(srcFile); -+ try (FileInputStream fis = new FileInputStream(fileToZip)) { -+ ZipEntry zipEntry = new ZipEntry(fileToZip.getName()); -+ zipEntry.setSize(fileToZip.length()); -+ zos.putNextEntry(zipEntry); -+ byte[] bytes = new byte[BUFFER_SIZE]; -+ int length; -+ while ((length = fis.read(bytes)) >= 0) { -+ zos.write(bytes, 0, length); -+ } -+ } -+ } -+ } -+ } -+ -+ /** -+ * Create the files that will be added to the ZIP file -+ * @throws IOException if there is a problem creating the files -+ */ -+ private static void createFiles() throws IOException { -+ try (RandomAccessFile largeFile = new RandomAccessFile(LARGE_FILE_NAME, "rw"); -+ RandomAccessFile smallFile = new RandomAccessFile(SMALL_FILE_NAME, "rw")) { -+ System.out.printf("Creating %s%n", LARGE_FILE_NAME); -+ largeFile.setLength(LARGE_FILE_SIZE); -+ System.out.printf("Creating %s%n", SMALL_FILE_NAME); -+ smallFile.setLength(SMALL_FILE_SIZE); -+ } -+ } -+ -+ /** -+ * Make sure the needed test files do not exist prior to executing the test -+ * @throws IOException -+ */ -+ @BeforeMethod -+ public void setUp() throws IOException { -+ deleteFiles(); -+ } -+ -+ /** -+ * Remove the files created for the test -+ * @throws IOException -+ */ -+ @AfterMethod -+ public void tearDown() throws IOException { -+ deleteFiles(); -+ } -+} -\ No newline at end of file --- -2.22.0 - diff --git a/add-8226530-test-case-fixed.patch b/add-8226530-test-case-fixed.patch deleted file mode 100644 index 5e0fb22a9d9ccd10b28ddeec80bbe0d53bdad55c..0000000000000000000000000000000000000000 --- a/add-8226530-test-case-fixed.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 6430afa36959aa740f47d64427f06c755ea1549f Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:25:27 +0800 -Subject: add 8226530-test-case-fixed - ---- - jdk/test/java/util/zip/ZipFile/Zip64SizeTest.java | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - -diff --git a/jdk/test/java/util/zip/ZipFile/Zip64SizeTest.java b/jdk/test/java/util/zip/ZipFile/Zip64SizeTest.java -index be701e480..c466ffa07 100644 ---- a/jdk/test/java/util/zip/ZipFile/Zip64SizeTest.java -+++ b/jdk/test/java/util/zip/ZipFile/Zip64SizeTest.java -@@ -26,7 +26,8 @@ import org.testng.annotations.Test; - - import java.io.*; - import java.nio.file.Files; --import java.nio.file.Path; -+import java.nio.file.Paths; -+import java.util.Arrays; - import java.util.List; - import java.util.zip.ZipEntry; - import java.util.zip.ZipFile; -@@ -52,7 +53,7 @@ public class Zip64SizeTest { - // File that will be created with a size less than 0xFFFFFFFF - private static final String SMALL_FILE_NAME = "SmallZipEntry.txt"; - // List of files to be added to the ZIP file -- private static final List ZIP_ENTRIES = List.of(LARGE_FILE_NAME, -+ private static final List ZIP_ENTRIES = Arrays.asList(LARGE_FILE_NAME, - SMALL_FILE_NAME); - private static final long LARGE_FILE_SIZE = 5L * 1024L * 1024L * 1024L; // 5GB - private static final long SMALL_FILE_SIZE = 0x100000L; // 1024L x 1024L; -@@ -83,9 +84,9 @@ public class Zip64SizeTest { - * @throws IOException if an error occurs deleting the files - */ - private static void deleteFiles() throws IOException { -- Files.deleteIfExists(Path.of(ZIP_FILE_NAME)); -- Files.deleteIfExists(Path.of(LARGE_FILE_NAME)); -- Files.deleteIfExists(Path.of(SMALL_FILE_NAME)); -+ Files.deleteIfExists(Paths.get(ZIP_FILE_NAME)); -+ Files.deleteIfExists(Paths.get(LARGE_FILE_NAME)); -+ Files.deleteIfExists(Paths.get(SMALL_FILE_NAME)); - } - - /** -@@ -144,4 +145,4 @@ public class Zip64SizeTest { - public void tearDown() throws IOException { - deleteFiles(); - } --} -\ No newline at end of file -+} --- -2.22.0 - diff --git a/add-8227041-runtime-memory-RunUnitTestsConcurrently.patch b/add-8227041-runtime-memory-RunUnitTestsConcurrently.patch deleted file mode 100644 index f6de00f663d326d79a35ceb0d37953e756965fdb..0000000000000000000000000000000000000000 --- a/add-8227041-runtime-memory-RunUnitTestsConcurrently.patch +++ /dev/null @@ -1,23 +0,0 @@ -From 627e452a58f0c8fc5504ec2ccd3de69924ab1484 Mon Sep 17 00:00:00 2001 -Date: Fri, 22 Sep 2023 14:45:50 +0800 -Subject: add 8227041-runtime-memory-RunUnitTestsConcurrently - ---- - hotspot/src/share/vm/memory/metaspace.cpp | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp -index d65a81267..0569500c1 100644 ---- a/hotspot/src/share/vm/memory/metaspace.cpp -+++ b/hotspot/src/share/vm/memory/metaspace.cpp -@@ -5432,7 +5432,6 @@ class TestMetaspaceAuxTest : AllStatic { - static void test() { - test_reserved(); - test_committed(); -- test_virtual_space_list_large_chunk(); - } - }; - --- -2.22.0 - diff --git a/add-8242842-Avoid-reallocating-name-when-checking-fo.patch b/add-8242842-Avoid-reallocating-name-when-checking-fo.patch deleted file mode 100644 index d07f9074c20e40bb4f104bc1f17d5636764afc7f..0000000000000000000000000000000000000000 --- a/add-8242842-Avoid-reallocating-name-when-checking-fo.patch +++ /dev/null @@ -1,70 +0,0 @@ -From be90711b32cb79822222d31f258ff4e0f45a616c Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:24:07 +0800 -Subject: add 8242842-Avoid-reallocating-name-when-checking-for-tr - ---- - .../share/classes/java/util/zip/ZipFile.java | 25 ++++++++++++------- - 1 file changed, 16 insertions(+), 9 deletions(-) - -diff --git a/jdk/src/share/classes/java/util/zip/ZipFile.java b/jdk/src/share/classes/java/util/zip/ZipFile.java -index 9e854e84d..b6a6c2a48 100644 ---- a/jdk/src/share/classes/java/util/zip/ZipFile.java -+++ b/jdk/src/share/classes/java/util/zip/ZipFile.java -@@ -1049,7 +1049,7 @@ class ZipFile implements ZipConstants, Closeable { - return h; - } - -- private static final int hash_append(int hash, byte b) { -+ private static final int hashAppend(int hash, byte b) { - return hash * 31 + b; - } - -@@ -1267,11 +1267,13 @@ class ZipFile implements ZipConstants, Closeable { - } - int hsh = hashN(name, 0, name.length); - int idx = table[(hsh & 0x7fffffff) % tablelen]; -+ boolean appendSlash = false; - /* - * This while loop is an optimization where a double lookup -- * for name and name+/ is being performed. The name char -- * array has enough room at the end to try again with a -- * slash appended if the first table lookup does not succeed. -+ * for name and name+/ is being performed. The name byte -+ * array will be updated with an added slash only if the first -+ * table lookup fails and there is a matching hash value for -+ * name+/. - */ - while(true) { - /* -@@ -1282,6 +1284,11 @@ class ZipFile implements ZipConstants, Closeable { - if (getEntryHash(idx) == hsh) { - // The CEN name must match the specfied one - int pos = getEntryPos(idx); -+ if (appendSlash) { -+ name = Arrays.copyOf(name, name.length + 1); -+ name[name.length - 1] = '/'; -+ appendSlash = false; -+ } - if (name.length == CENNAM(cen, pos)) { - boolean matched = true; - int nameoff = pos + CENHDR; -@@ -1302,11 +1309,11 @@ class ZipFile implements ZipConstants, Closeable { - if (!addSlash || name[name.length - 1] == '/') { - return -1; - } -- /* Add slash and try once more */ -- name = Arrays.copyOf(name, name.length + 1); -- name[name.length - 1] = '/'; -- hsh = hash_append(hsh, (byte)'/'); -- //idx = table[hsh % tablelen]; -+ // Add a slash to the hash code -+ hsh = hashAppend(hsh, (byte)'/'); -+ // If we find a match on the new hash code, we need to append a -+ // slash when comparing -+ appendSlash = true; - idx = table[(hsh & 0x7fffffff) % tablelen]; - addSlash = false; - } --- -2.22.0 - diff --git a/add-Adapting-IOException-of-Zip-to-ZipException.patch b/add-Adapting-IOException-of-Zip-to-ZipException.patch deleted file mode 100644 index 882eeda039c4296222c4283f48df58461375d60d..0000000000000000000000000000000000000000 --- a/add-Adapting-IOException-of-Zip-to-ZipException.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 7965b56b3269b8e553ce929a466466990c9d0c07 Mon Sep 17 00:00:00 2001 -Date: Fri, 22 Sep 2023 14:45:16 +0800 -Subject: add Adapting-IOException-of-Zip-to-ZipException - ---- - jdk/src/share/classes/java/util/zip/ZipFile.java | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/jdk/src/share/classes/java/util/zip/ZipFile.java b/jdk/src/share/classes/java/util/zip/ZipFile.java -index 36135a9c0..e603e83d3 100644 ---- a/jdk/src/share/classes/java/util/zip/ZipFile.java -+++ b/jdk/src/share/classes/java/util/zip/ZipFile.java -@@ -970,7 +970,11 @@ class ZipFile implements ZipConstants, Closeable { - return src; - } - } -- src = new Source(key, toDelete); -+ try { -+ src = new Source(key, toDelete); -+ } catch (IOException exception) { -+ throw new ZipException(exception.getMessage()); -+ } - - synchronized (files) { - if (files.containsKey(key)) { // someone else put in first --- -2.22.0 - diff --git a/add-Do-not-collect_class-when-DynamicCDS-dump.patch b/add-Do-not-collect_class-when-DynamicCDS-dump.patch deleted file mode 100644 index ba2ba67fc529a3297aa0eb8240ff8fa96fa4a741..0000000000000000000000000000000000000000 --- a/add-Do-not-collect_class-when-DynamicCDS-dump.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 32657f9ef4e781254fb918adef8802d9998ef083 Mon Sep 17 00:00:00 2001 -Date: Fri, 22 Sep 2023 14:44:01 +0800 -Subject: add Do-not-collect_class-when-DynamicCDS-dump - ---- - hotspot/src/share/vm/classfile/dictionary.cpp | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp -index 530c3fdfb..79aaa99e5 100644 ---- a/hotspot/src/share/vm/classfile/dictionary.cpp -+++ b/hotspot/src/share/vm/classfile/dictionary.cpp -@@ -209,7 +209,9 @@ void Dictionary::remove_classes_in_error_state(void f(Klass*)) { - _current_class_entry = NULL; - } - free_entry(probe); -- f(ik); -+ if (DumpSharedSpaces) { -+ f(ik); -+ } - ResourceMark rm; - tty->print_cr("Preload Warning: Removed error class: %s", ik->external_name()); - continue; --- -2.22.0 - diff --git a/add-Fix-aarch64-runtime-thread-signal-transfer-bug.patch b/add-Fix-aarch64-runtime-thread-signal-transfer-bug.patch deleted file mode 100644 index 8e17274c4597f408163f946040cd684224ad93f1..0000000000000000000000000000000000000000 --- a/add-Fix-aarch64-runtime-thread-signal-transfer-bug.patch +++ /dev/null @@ -1,153 +0,0 @@ -From c4fd69c76c41b7b6168f1071d50143566f7d269e Mon Sep 17 00:00:00 2001 -Date: Fri, 22 Sep 2023 14:48:33 +0800 -Subject: [PATCH] add Fix-aarch64-runtime-thread-signal-transfer-bug - ---- - .../src/cpu/aarch64/vm/vm_version_aarch64.hpp | 7 ++ - hotspot/src/os/linux/vm/os_linux.cpp | 3 + - .../linux_aarch64/vm/thread_linux_aarch64.cpp | 69 +++++++++++++++++++ - .../linux_aarch64/vm/thread_linux_aarch64.hpp | 2 + - 4 files changed, 82 insertions(+), 5 deletions(-) - -diff --git a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.hpp -index 7f3a53262..9dfc3465e 100644 ---- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.hpp -+++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.hpp -@@ -63,6 +63,7 @@ public: - CPU_BROADCOM = 'B', - CPU_CAVIUM = 'C', - CPU_DEC = 'D', -+ CPU_HISILICON = 'H', - CPU_INFINEON = 'I', - CPU_MOTOROLA = 'M', - CPU_NVIDIA = 'N', -@@ -93,6 +94,12 @@ public: - static int cpu_variant() { return _variant; } - static int cpu_revision() { return _revision; } - static int cpu_cpuFeatures() { return _cpuFeatures; } -+ static bool is_hisi_enabled() { -+ if (_cpu == CPU_HISILICON && (_model == 0xd01 || _model == 0xd02)) { -+ return true; -+ } -+ return false; -+ } - static ByteSize dczid_el0_offset() { return byte_offset_of(PsrInfo, dczid_el0); } - static ByteSize ctr_el0_offset() { return byte_offset_of(PsrInfo, ctr_el0); } - static bool is_zva_enabled() { -diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp -index 197b5c193..3ed8cde6b 100644 ---- a/hotspot/src/os/linux/vm/os_linux.cpp -+++ b/hotspot/src/os/linux/vm/os_linux.cpp -@@ -5754,6 +5754,9 @@ void os::set_native_thread_name(const char *name) { - const int rc = Linux::_pthread_setname_np(pthread_self(), buf); - // ERANGE should not happen; all other errors should just be ignored. - assert(rc != ERANGE, "pthread_setname_np failed"); -+#ifdef AARCH64 -+ ((JavaThread*)Thread::current())->os_linux_aarch64_options(name); -+#endif - } - } - -diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp b/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp -index 87e42318a..bc4b03561 100644 ---- a/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp -+++ b/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.cpp -@@ -25,6 +25,7 @@ - #include "precompiled.hpp" - #include "runtime/frame.inline.hpp" - #include "runtime/thread.inline.hpp" -+#include "runtime/arguments.hpp" - - // For Forte Analyzer AsyncGetCallTrace profiling support - thread is - // currently interrupted by SIGPROF -@@ -39,6 +40,74 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, - return pd_get_top_frame(fr_addr, ucontext, isInJava); - } - -+inline unsigned int stringHash(const char* str) { -+ unsigned int seed = 13; -+ unsigned int hash = 0; -+ while(*str) { -+ hash = hash * seed + (*str++); -+ } -+ -+ return (hash & 0x7fffffff); -+} -+ -+void JavaThread::os_linux_aarch64_options(const char *name) { -+ if (name == NULL || strlen(name) < 20) { -+ return; -+ } -+ -+ char firstStr[16] ; -+ char secondStr[20]; -+ memcpy(firstStr, name, 15); -+ firstStr[15] = '\0'; -+ -+ if (stringHash(firstStr) != 1216735539) { -+ return; -+ } -+ -+ int i = 0; -+ for (int j = 16; (name[j] != '\0') && name[j] != ' ' && i < 20; i++, j++) { -+ secondStr[i] = name[j]; -+ } -+ secondStr[i] = '\0'; -+ -+ if (VM_Version::is_hisi_enabled()) { -+ if (stringHash(firstStr) == 1216735539) { -+#ifdef COMPILER2 -+ const static intx tTypeProfileMajorReceiverPercent = TypeProfileMajorReceiverPercent; -+ const static intx tLoopUnrollLimit = LoopUnrollLimit; -+ if (stringHash(secondStr) == 2046673384) { -+ // makes specjvm compiler.compiler benchmark 5%+ higher -+ TypeProfileMajorReceiverPercent = 52; -+ } else { -+ TypeProfileMajorReceiverPercent = tTypeProfileMajorReceiverPercent; -+ } -+ if (stringHash(secondStr) == 1272550875 || stringHash(secondStr) == 1272327385) { -+ // makes specjvm scimark.sor.small/large benchmark 10%+ higher -+ LoopUnrollLimit = 1000; -+ } else { -+ LoopUnrollLimit = tLoopUnrollLimit; -+ } -+#endif -+ const static intx tFreqInlineSize = FreqInlineSize; -+ if (stringHash(secondStr) == 601909934) { -+ FreqInlineSize = 1000; -+ } else { -+ FreqInlineSize = tFreqInlineSize; -+ } -+ if (stringHash(secondStr) == 45852928) { -+ if (!UseFastSerializer) { -+ UseFastSerializer = true; -+ } -+ } else if (UseFastSerializer) { -+ UseFastSerializer = false; -+ } -+ if (stringHash(secondStr) == 21805) { -+ Arguments::set_transletEnhance(true); -+ } -+ } -+ } -+} -+ - bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { - assert(this->is_Java_thread(), "must be JavaThread"); - JavaThread* jt = (JavaThread *)this; -diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp b/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp -index a2f0135c2..251e523df 100644 ---- a/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp -+++ b/hotspot/src/os_cpu/linux_aarch64/vm/thread_linux_aarch64.hpp -@@ -66,6 +66,8 @@ - bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, - bool isInJava); - -+ void os_linux_aarch64_options(const char *name); -+ - bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava); - private: - bool pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava); --- -2.22.0 - diff --git a/add-add-Count-instance-klass-when-loading-from-jsa-f.patch b/add-add-Count-instance-klass-when-loading-from-jsa-f.patch deleted file mode 100644 index a0d966f0f8898353a038563ce8c44d210b2d754d..0000000000000000000000000000000000000000 --- a/add-add-Count-instance-klass-when-loading-from-jsa-f.patch +++ /dev/null @@ -1,60 +0,0 @@ -From fccc34c57f171463e871d8beeb4f97a67abc03da Mon Sep 17 00:00:00 2001 -Date: Fri, 22 Sep 2023 14:44:32 +0800 -Subject: add add-Count-instance-klass-when-loading-from-jsa-file - ---- - hotspot/src/share/vm/classfile/classLoaderData.cpp | 5 ++++- - hotspot/src/share/vm/oops/instanceKlass.cpp | 1 - - hotspot/src/share/vm/oops/instanceKlass.hpp | 1 + - 3 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp -index 12b7e5036..ba86a0ebc 100644 ---- a/hotspot/src/share/vm/classfile/classLoaderData.cpp -+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp -@@ -64,6 +64,7 @@ - #include "utilities/growableArray.hpp" - #include "utilities/macros.hpp" - #include "utilities/ostream.hpp" -+#include "oops/instanceKlass.hpp" - - ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL; - -@@ -304,7 +305,9 @@ void ClassLoaderData::add_class(Klass* k) { - k->set_next_link(old_value); - // link the new item into the list - _klasses = k; -- -+ if(k->oop_is_instance()){ -+ InstanceKlass::inc_instance_classes(); -+ } - if (TraceClassLoaderData && Verbose && k->class_loader_data() != NULL) { - ResourceMark rm; - tty->print_cr("[TraceClassLoaderData] Adding k: " PTR_FORMAT " %s to CLD: " -diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp -index 993778270..00aea4377 100644 ---- a/hotspot/src/share/vm/oops/instanceKlass.cpp -+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp -@@ -232,7 +232,6 @@ InstanceKlass* InstanceKlass::allocate_instance_klass( - // including classes in the bootstrap (NULL) class loader. - loader_data->add_class(ik); - -- Atomic::inc(&_total_instanceKlass_count); - return ik; - } - -diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp -index 6e36fa4ce..973480341 100644 ---- a/hotspot/src/share/vm/oops/instanceKlass.hpp -+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp -@@ -175,6 +175,7 @@ class InstanceKlass: public Klass { - initialization_error // error happened during initialization - }; - -+ static void inc_instance_classes() { Atomic::inc(&_total_instanceKlass_count); } - static int number_of_instance_classes() { return _total_instanceKlass_count; } - - private: --- -2.22.0 - diff --git a/add-fix-lock_fd-no-close-and-improve-KAEProvider.patch b/add-fix-lock_fd-no-close-and-improve-KAEProvider.patch deleted file mode 100644 index d67645167cf0a2bd43a0217e68ce57fa80d162d5..0000000000000000000000000000000000000000 --- a/add-fix-lock_fd-no-close-and-improve-KAEProvider.patch +++ /dev/null @@ -1,227 +0,0 @@ -From eb4284c06d643ec1204a922ccc06970331055bc4 Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:23:38 +0800 -Subject: add fix-lock_fd-no-close-and-improve-KAEProvider - ---- - hotspot/src/share/vm/memory/filemap.cpp | 21 +++++++++++++++++++ - hotspot/src/share/vm/memory/filemap.hpp | 2 ++ - .../src/share/vm/memory/metaspaceShared.cpp | 4 ++++ - hotspot/src/share/vm/prims/unsafe.cpp | 1 + - .../security/openssl/KAESM4Cipher.java | 6 ++++-- - .../security/openssl/kae_keyagreement_dh.c | 6 ++++-- - .../security/openssl/kae_keyagreement_ecdh.c | 7 ++++--- - .../security/openssl/kae_symmetric_cipher.c | 11 ++++++---- - 8 files changed, 47 insertions(+), 11 deletions(-) - -diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp -index 0d217078a..166fe2b80 100644 ---- a/hotspot/src/share/vm/memory/filemap.cpp -+++ b/hotspot/src/share/vm/memory/filemap.cpp -@@ -181,6 +181,18 @@ FileMapInfo::~FileMapInfo() { - _file_open = false; - _fd = -1; - } -+ -+ if (DumpSharedSpaces && UseAppCDS && AppCDSLockFile != NULL) { -+ // delete appcds.lock -+ if (_lock_file_open) { -+ if (::close(_lock_fd) < 0) { -+ fail_stop("Unable to close the lock file."); -+ } -+ _lock_file_open = false; -+ _lock_fd = -1; -+ } -+ remove(_appcds_file_lock_path); -+ } - } - - void FileMapInfo::populate_header(size_t alignment) { -@@ -606,6 +618,8 @@ void FileMapInfo::open_for_write() { - "2. You have the permission.\n 3. Make sure no other process using the same lock file.\n"); - fail_stop("Failed to create appcds lock file, the lock path is: %s.", _appcds_file_lock_path); - } -+ _lock_fd = lock_fd; -+ _lock_file_open = true; - tty->print_cr("You are using file lock %s in concurrent mode", AppCDSLockFile); - } - #endif -@@ -772,6 +786,13 @@ void FileMapInfo::write_bytes_aligned(const void* buffer, int nbytes) { - - void FileMapInfo::close() { - if (UseAppCDS && AppCDSLockFile != NULL) { -+ if (_lock_file_open) { -+ if (::close(_lock_fd) < 0) { -+ fail_stop("Unable to close the lock file."); -+ } -+ _lock_file_open = false; -+ _lock_fd = -1; -+ } - // delete appcds.lock - remove(_appcds_file_lock_path); - } -diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp -index debfb5049..f6cf43a64 100644 ---- a/hotspot/src/share/vm/memory/filemap.hpp -+++ b/hotspot/src/share/vm/memory/filemap.hpp -@@ -74,6 +74,8 @@ private: - bool _is_mapped; - int _fd; - size_t _file_offset; -+ int _lock_fd; -+ bool _lock_file_open; - - private: - static SharedClassPathEntry* _classpath_entry_table; -diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp -index e6bd39d85..eea79cc09 100644 ---- a/hotspot/src/share/vm/memory/metaspaceShared.cpp -+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp -@@ -829,6 +829,10 @@ int MetaspaceShared::preload_and_dump(const char * class_list_path, - TempNewSymbol class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD); - guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol."); - -+ // If preload_and_dump has anonymous class failed ,pls del this class_name in classlist -+ if (TraceClassLoading) { -+ tty->print_cr("preload_and_dump start: %s", class_name); -+ } - Handle loader = UseAppCDS ? SystemDictionary::java_system_loader() : Handle(); - Klass* klass = SystemDictionary::resolve_or_null(class_name_symbol, - loader, -diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp -index fa3e46782..d6c33dd33 100644 ---- a/hotspot/src/share/vm/prims/unsafe.cpp -+++ b/hotspot/src/share/vm/prims/unsafe.cpp -@@ -1042,6 +1042,7 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env, - - if (DumpSharedSpaces) { - tty->print_cr("failed: must not create anonymous classes when dumping."); -+ tty->print_cr("Please delete the last class_name prefixed with \"preload_and_dump start\" from -XX:SharedClassListFile to avoid anonymous classes."); - JVM_Halt(0); - } - -diff --git a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAESM4Cipher.java b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAESM4Cipher.java -index cca619e1a..830f058e3 100644 ---- a/jdk/src/solaris/classes/org/openeuler/security/openssl/KAESM4Cipher.java -+++ b/jdk/src/solaris/classes/org/openeuler/security/openssl/KAESM4Cipher.java -@@ -356,8 +356,10 @@ abstract class KAESM4Cipher extends KAESymmetricCipherBase { - throw new InvalidAlgorithmParameterException("Wrong IV length: iv is null "); - } - if (mode == Mode.CTR) { -- if (ivBytes.length < 8) { -- throw new InvalidAlgorithmParameterException("Wrong IV length: CTR mode requires IV of at least: 8 bytes."); -+ // For compatibility, SM4 CTR allows 8 < IV < blockSize, the remaining bytes will be filled with 0 in engineInit -+ if (ivBytes.length < 8 || ivBytes.length > blockSize) { -+ throw new InvalidAlgorithmParameterException("Wrong IV length: CTR mode requires IV of at least" + -+ "8 bytes, and no greater than " + blockSize + "bytes"); - } - return; - } -diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_dh.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_dh.c -index d8d2ee7cb..74af15a51 100644 ---- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_dh.c -+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_dh.c -@@ -117,7 +117,7 @@ JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAEDHKeyAgreeme - KAE_ThrowRuntimeException(env, "GetByteArrayFromBigNum failed in nativeComputeKey."); - goto cleanup; - } -- KAE_TRACE("Java_org_openeuler_security_openssl_KAEDHKeyAgreement_nativeGenerateSecret finished!"); -+ KAE_TRACE("Java_org_openeuler_security_openssl_KAEDHKeyAgreement_nativeComputeKey finished!"); - - cleanup: - if (dh != NULL) -@@ -130,8 +130,10 @@ cleanup: - KAE_ReleaseBigNumFromByteArray(p_bn); - if (g_bn != NULL) - KAE_ReleaseBigNumFromByteArray(g_bn); -- if (secret != NULL) -+ if (secret != NULL) { -+ memset(secret, 0, pSizeInByte); - free(secret); -+ } - if (computeKeyRetBn != NULL) - BN_free(computeKeyRetBn); - -diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_ecdh.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_ecdh.c -index 5fc4d68fd..877a915f0 100644 ---- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_ecdh.c -+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_keyagreement_ecdh.c -@@ -30,7 +30,7 @@ - #include "org_openeuler_security_openssl_KAEECDHKeyAgreement.h" - - static void FreeGenerateSecretParam(BIGNUM* s, BIGNUM* wX, BIGNUM* wY, -- EC_POINT* pub, EC_KEY* eckey, EC_GROUP* group, unsigned char* shareKey) -+ EC_POINT* pub, EC_KEY* eckey, EC_GROUP* group, unsigned char* shareKey, int shareKeyLen) - { - KAE_ReleaseBigNumFromByteArray(s); - KAE_ReleaseBigNumFromByteArray(wX); -@@ -45,6 +45,7 @@ static void FreeGenerateSecretParam(BIGNUM* s, BIGNUM* wX, BIGNUM* wY, - EC_GROUP_free(group); - } - if (shareKey != NULL) { -+ memset(shareKey, 0, shareKeyLen); - free(shareKey); - } - } -@@ -106,10 +107,10 @@ JNIEXPORT jbyteArray JNICALL Java_org_openeuler_security_openssl_KAEECDHKeyAgree - goto cleanup; - } - (*env)->SetByteArrayRegion(env, javaBytes, 0, expectSecretLen, (jbyte*)shareKey); -- FreeGenerateSecretParam(s, wX, wY, pub, eckey, group, shareKey); -+ FreeGenerateSecretParam(s, wX, wY, pub, eckey, group, shareKey, expectSecretLen); - return javaBytes; - - cleanup: -- FreeGenerateSecretParam(s, wX, wY, pub, eckey, group, shareKey); -+ FreeGenerateSecretParam(s, wX, wY, pub, eckey, group, shareKey, expectSecretLen); - return NULL; - } -diff --git a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_symmetric_cipher.c b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_symmetric_cipher.c -index 43f6326b2..ec8894f1a 100644 ---- a/jdk/src/solaris/native/org/openeuler/security/openssl/kae_symmetric_cipher.c -+++ b/jdk/src/solaris/native/org/openeuler/security/openssl/kae_symmetric_cipher.c -@@ -119,13 +119,15 @@ static const EVP_CIPHER* EVPGetAesCipherByName(JNIEnv* env, const char* algo) - } - } - --void FreeMemoryFromInit(JNIEnv* env, jbyteArray iv, jbyte* ivBytes, jbyteArray key, jbyte* keyBytes) -+void FreeMemoryFromInit(JNIEnv* env, jbyteArray iv, jbyte* ivBytes, jbyteArray key, jbyte* keyBytes, -+ int keyLength) - { - if (ivBytes != NULL) { - (*env)->ReleaseByteArrayElements(env, iv, ivBytes, 0); - } - if (keyBytes != NULL) { -- (*env)->ReleaseByteArrayElements(env, key, keyBytes, 0); -+ memset(keyBytes, 0, keyLength); -+ (*env)->ReleaseByteArrayElements(env, key, keyBytes, JNI_ABORT); - } - } - -@@ -143,6 +145,7 @@ Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeInit(JNIEnv* en - jbyte* ivBytes = NULL; - const EVP_CIPHER* cipher = NULL; - ENGINE* kaeEngine = NULL; -+ int keyLength = (*env)->GetArrayLength(env, key); - - const char* algo = (*env)->GetStringUTFChars(env, cipherType, 0); - if (StartsWith("aes", algo)) { -@@ -180,14 +183,14 @@ Java_org_openeuler_security_openssl_KAESymmetricCipherBase_nativeInit(JNIEnv* en - - EVP_CIPHER_CTX_set_padding(ctx, padding ? 1 : 0); - -- FreeMemoryFromInit(env, iv, ivBytes, key, keyBytes); -+ FreeMemoryFromInit(env, iv, ivBytes, key, keyBytes, keyLength); - return (jlong)ctx; - - cleanup: - if (ctx != NULL) { - EVP_CIPHER_CTX_free(ctx); - } -- FreeMemoryFromInit(env, iv, ivBytes, key, keyBytes); -+ FreeMemoryFromInit(env, iv, ivBytes, key, keyBytes, keyLength); - return 0; - } - --- -2.22.0 - diff --git a/add-fix-windows-build-Dynamic-CDS-failure.patch b/add-fix-windows-build-Dynamic-CDS-failure.patch deleted file mode 100644 index 1a34bef623b1b3b22fd28728a40c2c0fe2312238..0000000000000000000000000000000000000000 --- a/add-fix-windows-build-Dynamic-CDS-failure.patch +++ /dev/null @@ -1,43 +0,0 @@ -From d0212dc187a9693da07ce2fce0ea0935eebf0457 Mon Sep 17 00:00:00 2001 -Date: Fri, 22 Sep 2023 14:46:23 +0800 -Subject: add fix-windows-build-Dynamic-CDS-failure - ---- - hotspot/make/windows/makefiles/vm.make | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/hotspot/make/windows/makefiles/vm.make b/hotspot/make/windows/makefiles/vm.make -index 77a56ad54..fd5e5d224 100644 ---- a/hotspot/make/windows/makefiles/vm.make -+++ b/hotspot/make/windows/makefiles/vm.make -@@ -149,6 +149,7 @@ VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/code - VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/interpreter - VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/ci - VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/classfile -+VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/cds - VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/gc_implementation/parallelScavenge - VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/gc_implementation/shared - VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/gc_implementation/parNew -@@ -234,6 +235,9 @@ arguments.obj: $(WorkSpace)\src\share\vm\runtime\arguments.cpp - {$(COMMONSRC)\share\vm\classfile}.cpp.obj:: - $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< - -+{$(COMMONSRC)\share\vm\cds}.cpp.obj:: -+ $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< -+ - {$(COMMONSRC)\share\vm\gc_implementation\parallelScavenge}.cpp.obj:: - $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< - -@@ -317,6 +321,9 @@ arguments.obj: $(WorkSpace)\src\share\vm\runtime\arguments.cpp - {$(ALTSRC)\share\vm\classfile}.cpp.obj:: - $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< - -+{$(ALTSRC)\share\vm\cds}.cpp.obj:: -+ $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< -+ - {$(ALTSRC)\share\vm\gc_implementation\parallelScavenge}.cpp.obj:: - $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< - --- -2.22.0 - diff --git a/add-make-Appcds-jsa-rw-region-deterministic.patch b/add-make-Appcds-jsa-rw-region-deterministic.patch deleted file mode 100644 index 1f3a339e656f3611348f4ce8a88c83f38aba0e80..0000000000000000000000000000000000000000 --- a/add-make-Appcds-jsa-rw-region-deterministic.patch +++ /dev/null @@ -1,306 +0,0 @@ -From b35f73bec878c712e9fed512361b5fa424dc3fda Mon Sep 17 00:00:00 2001 -Date: Thu, 21 Sep 2023 15:15:17 +0800 -Subject: add make-Appcds-jsa-rw-region-deterministic - ---- - .../share/vm/classfile/classFileParser.hpp | 1 + - .../share/vm/classfile/classLoaderData.hpp | 2 +- - .../src/share/vm/classfile/defaultMethods.cpp | 6 +++- - hotspot/src/share/vm/classfile/dictionary.cpp | 6 +++- - hotspot/src/share/vm/classfile/dictionary.hpp | 2 +- - .../share/vm/classfile/systemDictionary.cpp | 24 ++++++++++++++-- - .../share/vm/classfile/systemDictionary.hpp | 2 +- - .../src/share/vm/memory/metaspaceShared.cpp | 28 +++++++++++-------- - hotspot/src/share/vm/runtime/mutex.cpp | 2 +- - hotspot/src/share/vm/runtime/os.cpp | 5 +++- - hotspot/src/share/vm/runtime/os.hpp | 2 +- - hotspot/src/share/vm/runtime/synchronizer.cpp | 2 +- - 12 files changed, 59 insertions(+), 23 deletions(-) - -diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp -index 1900f0abf..dda7c92d9 100644 ---- a/hotspot/src/share/vm/classfile/classFileParser.hpp -+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp -@@ -42,6 +42,7 @@ class FieldLayoutInfo; - // The bytes describing the class file structure is read from a Stream object - - class ClassFileParser VALUE_OBJ_CLASS_SPEC { -+ friend class SystemDictionary; - private: - bool _need_verify; - bool _relax_verify; -diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp -index 7155257ed..0bb2e1000 100644 ---- a/hotspot/src/share/vm/classfile/classLoaderData.hpp -+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp -@@ -211,7 +211,6 @@ class ClassLoaderData : public CHeapObj { - JFR_ONLY(DEFINE_TRACE_ID_FIELD;) - - void set_next(ClassLoaderData* next) { _next = next; } -- ClassLoaderData* next() const { return _next; } - - ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies); - ~ClassLoaderData(); -@@ -238,6 +237,7 @@ class ClassLoaderData : public CHeapObj { - void clear_claimed() { _claimed = 0; } - bool claimed() const { return _claimed == 1; } - bool claim(); -+ ClassLoaderData* next() const { return _next; } - - bool is_alive(BoolObjectClosure* is_alive_closure) const; - -diff --git a/hotspot/src/share/vm/classfile/defaultMethods.cpp b/hotspot/src/share/vm/classfile/defaultMethods.cpp -index 196622aed..0becb35ed 100644 ---- a/hotspot/src/share/vm/classfile/defaultMethods.cpp -+++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp -@@ -909,7 +909,11 @@ static void switchover_constant_pool(BytecodeConstantPool* bpool, - if (new_methods->length() > 0) { - ConstantPool* cp = bpool->create_constant_pool(CHECK); - if (cp != klass->constants()) { -- klass->class_loader_data()->add_to_deallocate_list(klass->constants()); -+ ClassLoaderData* loader_data = klass->class_loader_data(); -+ while (DumpSharedSpaces && loader_data->next() != NULL) { -+ loader_data = loader_data->next(); -+ } -+ loader_data->add_to_deallocate_list(klass->constants()); - klass->set_constants(cp); - cp->set_pool_holder(klass); - -diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp -index d41372ecc..530c3fdfb 100644 ---- a/hotspot/src/share/vm/classfile/dictionary.cpp -+++ b/hotspot/src/share/vm/classfile/dictionary.cpp -@@ -196,7 +196,7 @@ void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) { - _pd_cache_table->roots_oops_do(strong, weak); - } - --void Dictionary::remove_classes_in_error_state() { -+void Dictionary::remove_classes_in_error_state(void f(Klass*)) { - assert(DynamicDumpSharedSpaces || DumpSharedSpaces, "supported only when dumping"); - DictionaryEntry* probe = NULL; - for (int index = 0; index < table_size(); index++) { -@@ -209,6 +209,7 @@ void Dictionary::remove_classes_in_error_state() { - _current_class_entry = NULL; - } - free_entry(probe); -+ f(ik); - ResourceMark rm; - tty->print_cr("Preload Warning: Removed error class: %s", ik->external_name()); - continue; -@@ -420,6 +421,9 @@ void Dictionary::add_protection_domain(int index, unsigned int hash, - instanceKlassHandle klass, - ClassLoaderData* loader_data, Handle protection_domain, - TRAPS) { -+ if (DumpSharedSpaces) { -+ return; -+ } - Symbol* klass_name = klass->name(); - DictionaryEntry* entry = get_entry(index, hash, klass_name, loader_data); - -diff --git a/hotspot/src/share/vm/classfile/dictionary.hpp b/hotspot/src/share/vm/classfile/dictionary.hpp -index 9ed0defb8..8a88fa2e4 100644 ---- a/hotspot/src/share/vm/classfile/dictionary.hpp -+++ b/hotspot/src/share/vm/classfile/dictionary.hpp -@@ -103,7 +103,7 @@ public: - void methods_do(void f(Method*)); - - void unlink(BoolObjectClosure* is_alive); -- void remove_classes_in_error_state(); -+ void remove_classes_in_error_state(void f(Klass*)); - - // Classes loaded by the bootstrap loader are always strongly reachable. - // If we're not doing class unloading, all classes are strongly reachable. -diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp -index 9089a762d..c8f66e830 100644 ---- a/hotspot/src/share/vm/classfile/systemDictionary.cpp -+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp -@@ -1170,6 +1170,26 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name, - parsed_name, - verify, - THREAD); -+ if (DumpSharedSpaces && k.is_null()) { -+ if (loader_data) { -+ ClassLoaderData* cld = loader_data; -+ while (cld->next() != NULL) -+ cld = cld->next(); -+ ConstantPool* cp = parser._cp; -+ if (cp) { -+ cld->add_to_deallocate_list(cp); -+ } -+ Array* m = parser._methods; -+ if (m) { -+ for (int i = 0; i < m->length(); i++) { -+ Method* method = m->at(i); -+ if (method != NULL) { -+ cld->add_to_deallocate_list(method); -+ } -+ } -+ } -+ } -+ } - const char* pkg = "java/"; - size_t pkglen = strlen(pkg); - if (!HAS_PENDING_EXCEPTION && -@@ -2036,8 +2056,8 @@ void SystemDictionary::methods_do(void f(Method*)) { - invoke_method_table()->methods_do(f); - } - --void SystemDictionary::remove_classes_in_error_state() { -- dictionary()->remove_classes_in_error_state(); -+void SystemDictionary::remove_classes_in_error_state(void f(Klass*)) { -+ dictionary()->remove_classes_in_error_state(f); - } - - // ---------------------------------------------------------------------------- -diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp -index cfc15c20e..e39c1de62 100644 ---- a/hotspot/src/share/vm/classfile/systemDictionary.hpp -+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp -@@ -347,7 +347,7 @@ public: - static bool do_unloading(BoolObjectClosure* is_alive, bool clean_alive = true); - - // Used by DumpSharedSpaces only to remove classes that failed verification -- static void remove_classes_in_error_state(); -+ static void remove_classes_in_error_state(void f(Klass*)); - - static int calculate_systemdictionary_size(int loadedclasses); - -diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp -index b31d0a3fb..e6bd39d85 100644 ---- a/hotspot/src/share/vm/memory/metaspaceShared.cpp -+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp -@@ -216,6 +216,10 @@ static void patch_deallocate_meta_vtables(void** vtbl_list, void* new_vtable_sta - ((ConstantPool*)m)->remove_unshareable_info(); - *(void**)m = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, m); - } -+ else if (m->is_method()) { -+ ((Method*)m)->remove_unshareable_info(); -+ *(void**)m = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, m); -+ } - } - } - } -@@ -442,6 +446,7 @@ public: - _md_vs.initialize(md_rs, SharedMiscDataSize); - _mc_vs.initialize(mc_rs, SharedMiscCodeSize); - _class_promote_order = class_promote_order; -+ _global_klass_objects = new GrowableArray(1000); - } - - VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; } -@@ -465,13 +470,6 @@ void VM_PopulateDumpSharedSpace::doit() { - SystemDictionary::invoke_method_table()->number_of_entries() == 0, - "invoke method table is not saved"); - -- // At this point, many classes have been loaded. -- // Gather systemDictionary classes in a global array and do everything to -- // that so we don't have to walk the SystemDictionary again. -- _global_klass_objects = new GrowableArray(1000); -- Universe::basic_type_classes_do(collect_classes); -- SystemDictionary::classes_do(collect_classes); -- - tty->print_cr("Number of classes %d", _global_klass_objects->length()); - { - int num_type_array = 0, num_obj_array = 0, num_inst = 0; -@@ -702,7 +700,7 @@ void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) { - - // 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(); -+ SystemDictionary::remove_classes_in_error_state(collect_classes); - } - - // Copy the dependencies from C_HEAP-alloced GrowableArrays to RO-alloced -@@ -785,6 +783,9 @@ void MetaspaceShared::preload_and_dump(TRAPS) { - // Rewrite and link classes - tty->print_cr("Rewriting and linking classes ..."); - -+ // Create here because link_and_cleanup_shared_classes need the _global_klass_objects -+ ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); -+ VM_PopulateDumpSharedSpace op(loader_data, class_promote_order); - // Link any classes which got missed. This would happen if we have loaded classes that - // were not explicitly specified in the classlist. E.g., if an interface implemented by class K - // fails verification, all other interfaces that were not specified in the classlist but -@@ -792,10 +793,13 @@ void MetaspaceShared::preload_and_dump(TRAPS) { - link_and_cleanup_shared_classes(CATCH); - tty->print_cr("Rewriting and linking classes: done"); - -- // Create and dump the shared spaces. Everything so far is loaded -- // with the null class loader. -- ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); -- VM_PopulateDumpSharedSpace op(loader_data, class_promote_order); -+ // At this point, many classes have been loaded. -+ // Gather systemDictionary classes in a global array and do everything to -+ // that so we don't have to walk the SystemDictionary again. -+ Universe::basic_type_classes_do(collect_classes); -+ SystemDictionary::classes_do(collect_classes); -+ -+ // Dump the shared spaces. - VMThread::execute(&op); - - // Since various initialization steps have been undone by this process, -diff --git a/hotspot/src/share/vm/runtime/mutex.cpp b/hotspot/src/share/vm/runtime/mutex.cpp -index 92bd50662..b1159d02e 100644 ---- a/hotspot/src/share/vm/runtime/mutex.cpp -+++ b/hotspot/src/share/vm/runtime/mutex.cpp -@@ -276,7 +276,7 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC - // Useful for spin loops as the compiler can't optimize it away. - - static inline jint MarsagliaXORV (jint x) { -- if (x == 0) x = 1|os::random() ; -+ if (x == 0) x = 1|os::random(DumpSharedSpaces) ; - x ^= x << 6; - x ^= ((unsigned)x) >> 21; - x ^= x << 7 ; -diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp -index 43d66e85e..ff35e8b3a 100644 ---- a/hotspot/src/share/vm/runtime/os.cpp -+++ b/hotspot/src/share/vm/runtime/os.cpp -@@ -770,7 +770,7 @@ void os::init_random(long initval) { - } - - --long os::random() { -+long os::random(bool skip) { - /* standard, well-known linear congruential random generator with - * next_rand = (16807*seed) mod (2**31-1) - * see -@@ -801,6 +801,9 @@ long os::random() { - lo &= m; - ++lo; - } -+ if (skip) { -+ return lo; -+ } - return (_rand_seed = lo); - } - -diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp -index 988977b17..07beeed8c 100644 ---- a/hotspot/src/share/vm/runtime/os.hpp -+++ b/hotspot/src/share/vm/runtime/os.hpp -@@ -800,7 +800,7 @@ class os: AllStatic { - static int sigexitnum_pd(); - - // random number generation -- static long random(); // return 32bit pseudorandom number -+ static long random(bool skip = false); // return 32bit pseudorandom number - static void init_random(long initval); // initialize random sequence - - // Structured OS Exception support -diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp -index 8400bff11..e83ecd1d2 100644 ---- a/hotspot/src/share/vm/runtime/synchronizer.cpp -+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp -@@ -1657,7 +1657,7 @@ void ObjectSynchronizer::deflate_idle_monitors() { - - // TODO: Add objectMonitor leak detection. - // Audit/inventory the objectMonitors -- make sure they're all accounted for. -- GVars.stwRandom = os::random() ; -+ GVars.stwRandom = os::random(DumpSharedSpaces) ; - GVars.stwCycle ++ ; - } - --- -2.22.0 - diff --git a/add-missing-test-case.patch b/add-missing-test-case.patch index 312f3bb488f64b7eeadc74e6c8edd0beea0fc269..b3acf9c2d9097aa43fc505599286b3dd4c421879 100644 --- a/add-missing-test-case.patch +++ b/add-missing-test-case.patch @@ -31,7 +31,7 @@ index 2ee40289..8ab268b5 100644 @@ -1,6 +1,8 @@ /* * @test -+ * @author zl ++ * @author zhangli * @bug 8203699 + * @summary see https://code.huawei.com/HuaweiJDK/JVM-team/JVM/issues/1368 * @run testng/othervm test.java.lang.invoke.lookup.TestDefenderMethodLookup @@ -51,7 +51,7 @@ index 00000000..bd22ba83 + * @build com.huawei.openjdk.adaptiveheap.TestAdaptiveHeap + * @run main/othervm com.huawei.openjdk.adaptiveheap.TestAdaptiveHeap -Xms16G -Xmx16G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1PeriodicGCLoadThreshold=20 -XX:G1PeriodicGCInterval=15000 -XX:+G1Uncommit + * @summary test adaptheap -+ * @author wrs ++ * @author wangruishun + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; @@ -91,7 +91,7 @@ index 00000000..9b614024 --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ -+8.392.8.0.13 ++8.382.5.0.13 -- 2.23.0 diff --git a/change-value-of-GCLockerRetryAllocationCount-from-2-.patch b/change-value-of-GCLockerRetryAllocationCount-from-2-.patch deleted file mode 100644 index a74ca540612d462d228cc2712fa2126f2105454b..0000000000000000000000000000000000000000 --- a/change-value-of-GCLockerRetryAllocationCount-from-2-.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 9b431c9bba018a2dd2bb6850cfd674b51207bf49 Mon Sep 17 00:00:00 2001 -Date: Thu, 19 Oct 2023 01:37:43 +0000 -Subject: [PATCH 3/5] change value of GCLockerRetryAllocationCount from 2 to - 1000 to avoid OOM - ---- - hotspot/src/share/vm/runtime/globals.hpp | 2 +- - .../g1/TestGcLockerEvacFailureThreaded.java | 124 ++++++++++++++++++ - 2 files changed, 125 insertions(+), 1 deletion(-) - create mode 100644 hotspot/test/gc/g1/TestGcLockerEvacFailureThreaded.java - -diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp -index fdd9db149..65806a475 100644 ---- a/hotspot/src/share/vm/runtime/globals.hpp -+++ b/hotspot/src/share/vm/runtime/globals.hpp -@@ -1575,7 +1575,7 @@ class CommandLineFlags { - "How much the GC can expand the eden by while the GC locker " \ - "is active (as a percentage)") \ - \ -- diagnostic(uintx, GCLockerRetryAllocationCount, 2, \ -+ diagnostic(uintx, GCLockerRetryAllocationCount, 1000, \ - "Number of times to retry allocations when " \ - "blocked by the GC locker") \ - \ -diff --git a/hotspot/test/gc/g1/TestGcLockerEvacFailureThreaded.java b/hotspot/test/gc/g1/TestGcLockerEvacFailureThreaded.java -new file mode 100644 -index 000000000..74accd951 ---- /dev/null -+++ b/hotspot/test/gc/g1/TestGcLockerEvacFailureThreaded.java -@@ -0,0 +1,124 @@ -+import java.io.ByteArrayOutputStream; -+import java.io.IOException; -+import java.lang.ref.SoftReference; -+import java.nio.ByteBuffer; -+import java.util.ArrayList; -+import java.util.List; -+import java.util.Random; -+import java.util.zip.GZIPOutputStream; -+ -+import com.oracle.java.testlibrary.ProcessTools; -+import com.oracle.java.testlibrary.OutputAnalyzer; -+ -+/* -+ * @test TestGcLockerEvacFailureThreaded.java -+ * @bug 8048556 8137099 -+ * @summary Ensure that GCLocker does not cause early program termination. -+ * @key gc -+ * @library /testlibrary -+ */ -+public class TestGcLockerEvacFailureThreaded { -+ public static void main(String[] args) throws Exception { -+ System.out.println("Beginning test\n"); -+ -+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", -+ "-Xmx64m", -+ TestGcLocker.class.getName()); -+ -+ OutputAnalyzer output = new OutputAnalyzer(pb.start()); -+ -+ System.out.println("Output:\n" + output.getOutput()); -+ -+ output.shouldNotContain("java.lang.OutOfMemoryError"); -+ output.shouldHaveExitValue(0); -+ } -+ -+ /** -+ * Tests whether GCLocker terminates the application when forced to spin multiple times. -+ * We cause a long-running native call during which a GC is invoked by another thread. -+ */ -+ static class TestGcLocker { -+ -+ private static int gzipItemLengthBytes = 10500; -+ private static int nGzipItems = 3500; -+ private static int aliveDataItems = (int) (nGzipItems * 0.7); -+ -+ private static int nThreads = 500; -+ private static int loopSize = 1000; -+ -+ private static List dataToBeGzipped = new ArrayList<>(nGzipItems); -+ -+ private static List aliveData = new ArrayList<>(aliveDataItems); -+ -+ private static Random randomGenerator = new Random(); -+ -+ private static volatile boolean cont = true; -+ -+ private static void createData(int gzipItemLengthBytes, int nGzipItems) throws IOException { -+ for (int gzipDataIndex = 0; gzipDataIndex < nGzipItems; gzipDataIndex++) { -+ ByteBuffer buffer = ByteBuffer.allocate(gzipItemLengthBytes); -+ for (int i = 0; i < gzipItemLengthBytes/4; i++) { // since integer is 4 bytes -+ int randomInt = randomGenerator.nextInt(100); -+ buffer.putInt(randomInt); -+ } -+ byte[] data = buffer.array(); -+ dataToBeGzipped.add(data); -+ } -+ -+ for (int i = 0; i < aliveDataItems; i++) { -+ aliveData.add(new byte[0]); -+ } -+ -+ for (int gzipDataIndex = 0; gzipDataIndex < nGzipItems; gzipDataIndex++) { -+ native_critical_section(dataToBeGzipped.get(gzipDataIndex)); -+ } -+ -+ } -+ -+ public static void runTest(int loopSize) { -+ try { -+ int i = 0; -+ while (cont && (i < loopSize)) { -+ i++; -+ try { -+ native_critical_section(dataToBeGzipped.get(i % nGzipItems)); -+ } catch (OutOfMemoryError e) { -+ cont = false; //Remove this if you still want to continue after OOME -+ e.printStackTrace(); -+ } -+ } -+ -+ } catch (IOException e) { -+ cont = true; -+ e.printStackTrace(); -+ } -+ } -+ -+ private static void native_critical_section(byte[] data) throws IOException { -+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); GZIPOutputStream gzos = new GZIPOutputStream(bos)) { -+ gzos.write(data); -+ gzos.finish(); -+ byte[] compressedData = bos.toByteArray(); -+ int index = randomGenerator.nextInt(aliveDataItems); -+ aliveData.set(index, compressedData); -+ } -+ } -+ -+ public static void main(String[] args) throws InterruptedException, IOException { -+ createData(gzipItemLengthBytes, nGzipItems); -+ -+ System.gc(); //This will tell us the resident set size -+ -+ for (int i = 0; i < nThreads; i++) { -+ Thread t = new Thread() { -+ public void run() { -+ runTest(loopSize); -+ } -+ }; -+ t.start(); -+ } -+ System.out.println("Threads started"); -+ } -+ } -+} -+ --- -2.19.1 - diff --git a/fix_X509TrustManagerImpl_symantec_distrust.patch b/fix_X509TrustManagerImpl_symantec_distrust.patch index 1365d836e2bbee6e1a5340869a2908dd606bf91c..cbeefea9cb707adc84def524c3d77897109cce5a 100644 --- a/fix_X509TrustManagerImpl_symantec_distrust.patch +++ b/fix_X509TrustManagerImpl_symantec_distrust.patch @@ -35,7 +35,7 @@ diff --git a/jdk/test/sun/security/lib/cacerts/VerifyCACerts.java b/jdk/test/sun index 54e1bfa0d..c1423dc5b 100644 --- a/jdk/test/sun/security/lib/cacerts/VerifyCACerts.java +++ b/jdk/test/sun/security/lib/cacerts/VerifyCACerts.java -@@ -54,12 +54,12 @@ public class VerifyCACerts { +@@ -53,12 +53,12 @@ public class VerifyCACerts { + File.separator + "security" + File.separator + "cacerts"; // The numbers of certs now. @@ -46,10 +46,10 @@ index 54e1bfa0d..c1423dc5b 100644 // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95 private static final String CHECKSUM - = "2D:04:88:6C:52:53:54:EB:38:2D:BC:E0:AF:B7:82:F4:9E:32:A8:1A:1B:A3:AE:CF:25:CB:C2:F6:0F:4E:E1:20"; -+ = "C2:9A:86:5C:47:0F:15:58:FB:D8:31:B5:29:BB:BE:A1:09:6F:9B:60:10:AF:8E:77:4A:AE:B7:66:BB:B1:58:34"; ++ = "81:65:90:49:CF:39:8A:7B:B6:7E:88:9D:A3:E9:D4:31:0E:9B:D0:50:9E:09:76:37:E9:2A:14:74:17:6E:12:EF"; + // map of cert alias to SHA-256 fingerprint @SuppressWarnings("serial") - private static final Map FINGERPRINT_MAP @@ -111,7 +111,9 @@ public class VerifyCACerts { "7E:37:CB:8B:4C:47:09:0C:AB:36:55:1B:A6:F4:5D:B8:40:68:0F:BA:16:6A:95:2D:B1:00:71:7F:43:05:3F:C2"); put("digicerthighassuranceevrootca [jdk]", diff --git a/jdk8u-jdk8u392-b08.tar.xz b/jdk8u-jdk8u382-b05.tar.xz similarity index 82% rename from jdk8u-jdk8u392-b08.tar.xz rename to jdk8u-jdk8u382-b05.tar.xz index e026d3b0934c8a2353ecb81a39316f1f9aa7985d..dfd279342dc9be49eea6c731f1ad2f584b7a578f 100644 Binary files a/jdk8u-jdk8u392-b08.tar.xz and b/jdk8u-jdk8u382-b05.tar.xz differ diff --git a/kae-phase1.patch b/kae-phase1.patch index d7362ac7d6b13a77b0e231328bf7cbfae9e21add..89f335366c2c4b9eaafc36125d6f9442c08c6d91 100644 --- a/kae-phase1.patch +++ b/kae-phase1.patch @@ -5485,7 +5485,7 @@ index 50f65eab..a388c76a 100644 + "kae.disableKaeDispose", "read")); if (lib != null) { p.env("KRB5_CONFIG", CONF) - .env("KRB5_TRACE", Platform.isWindows() ? "CON" : "/dev/stderr") + .env("KRB5_TRACE", "/dev/stderr") -- 2.19.0 diff --git a/openjdk-1.8.0.spec b/openjdk-1.8.0.spec index b51ff460afbf1366a611fb61d199b78894682530..f5fc78843a66661eb67260d56a9478bdaa7a2f35 100644 --- a/openjdk-1.8.0.spec +++ b/openjdk-1.8.0.spec @@ -155,13 +155,13 @@ %global origin_nice OpenJDK %global top_level_dir_name %{origin} %global repo jdk8u -%global revision jdk8u392-b08 +%global revision jdk8u382-b05 %global full_revision %{repo}-%{revision} # Define IcedTea version used for SystemTap tapsets and desktop files %global icedteaver 3.15.0 -%global updatever 392 -%global buildver b08 +%global updatever 382 +%global buildver b05 # priority must be 7 digits in total. The expression is workarounding tip %global priority 1800%{updatever} @@ -925,7 +925,7 @@ Provides: java-%{javaver}-%{origin}-accessibility%{?1} = %{epoch}:%{version}-%{r Name: java-%{javaver}-%{origin} Version: %{javaver}.%{updatever}.%{buildver} -Release: 3 +Release: 7 # 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 @@ -984,6 +984,7 @@ Source20: repackReproduciblePolycies.sh Patch8: replace-vector-to-improve-performance-of-xml.validat.patch Patch10: 8221658.patch Patch18: fix-vendor-info.patch +Patch21: 8202952.patch Patch25: 8196485.patch Patch26: disable-UseLSE-on-ARMv8.1-by-default.patch Patch27: 8157570.patch @@ -1254,41 +1255,7 @@ Patch364: enhance-java-heap-oom-err-log.patch Patch365: 8014628-Support-AES-Encryption-with-HMAC-SHA2-for-Ke.patch Patch366: 8179273-sun.net.httpserver.LeftOverInputStream-shoul.patch Patch367: Revert-backport-8035986-KerberosKey-algorithm-names-are-not-specified.patch -Patch369: add-0010-8301749-Tracking-malloc-pooled-memory-size.patch -Patch370: 8213397-Stack-dump-should-show-more-clearly-when-a-t.patch -Patch371: Record-the-number-of-processes-to-errlog-file.patch.patch -Patch372: 8254723-Add-diagnostic-command-to-write-Linux-perf-m.patch -Patch373: The-OverWriteOldestGCLog-option-is-added-to-control.patch -Patch374: add-6899049-G1-Clean-up-code-in-ptrQueue.-ch-pp-and-.patch -Patch375: add-make-Appcds-jsa-rw-region-deterministic.patch -Patch377: add-8198423-Improve-metaspace-chunk-allocation.patch -Patch379: add-fix-lock_fd-no-close-and-improve-KAEProvider.patch -Patch384: add-8147940-Modify-testcase-this-test-does-not-assum.patch -Patch385: add-8191924-Adjust-DelegatingClassLoader-s-metadata-.patch -Patch386: add-Do-not-collect_class-when-DynamicCDS-dump.patch -Patch387: add-add-Count-instance-klass-when-loading-from-jsa-f.patch -Patch389: add-8227041-runtime-memory-RunUnitTestsConcurrently.patch -Patch390: add-fix-windows-build-Dynamic-CDS-failure.patch -Patch391: add-Fix-aarch64-runtime-thread-signal-transfer-bug.patch -Patch392: 8295068-SSLEngine-throws-NPE-parsing-CertificateRequ.patch -Patch393: 8308682-Enhance-AES-performance.patch -Patch394: Fix-the-memory-leak-of-MetaspaceAllocationTest.patch -Patch395: Add-metaspace-memory-allocation-failure-validation.patch -Patch396: change-value-of-GCLockerRetryAllocationCount-from-2-.patch - -#392 -Patch397: Fix-crash-in-JNI-s-GetDoubleArrayRegion-and-SetDoubl.patch -Patch398: 8263557-Possible-NULL-dereference-in-Arena-destruct_.patch -Patch399: 8294906-Memory-leak-in-PKCS11-NSS-TLS-server.patch -Patch400: 8314236-Overflow-in-Collections.rotate.patch -Patch401: 8313626-C2-crash-due-to-unexpected-exception-control.patch -Patch402: 8312200-Fix-Parse-catch_call_exceptions-memory-leak.patch -Patch403: 8193682-Infinite-loop-in-ZipOutputStream.close.patch -Patch404: 8285516-clearPassword-should-be-called-in-a-finally-.patch -Patch405: 8148470-Metadata-print-routines-should-not-print-to-.patch -Patch406: 8293344-JDK-8242181-broke-stack-printing-for-non-att.patch -Patch407: 8278794-Infinite-loop-in-DeflaterOutputStream.finish.patch -Patch408: 8312065-Socket.connect-does-not-timeout-when-profili.patch +Patch368: 8283441-C2-segmentation-fault-in-ciMethodBlocks-make.patch ############################################# # @@ -1378,7 +1345,8 @@ BuildRequires: zip BuildRequires: unzip BuildRequires: openssl-devel -#BuildRequires: java-1.8.0-openjdk-devel +# BuildRequires: java-1.8.0-openjdk-devel +BuildRequires: javapackages-filesystem BuildRequires: tzdata-java >= 2015d # Earlier versions have a bug in tree vectorization on PPC @@ -1631,6 +1599,7 @@ pushd %{top_level_dir_name} %patch8 -p1 %patch10 -p1 %patch18 -p1 +%patch21 -p1 %patch25 -p1 %patch26 -p1 %patch27 -p1 @@ -1869,40 +1838,7 @@ pushd %{top_level_dir_name} %patch365 -p1 %patch366 -p1 %patch367 -p1 -%patch369 -p1 -%patch370 -p1 -%patch371 -p1 -%patch372 -p1 -%patch373 -p1 -%patch374 -p1 -%patch375 -p1 -%patch377 -p1 -%patch379 -p1 -%patch384 -p1 -%patch385 -p1 -%patch386 -p1 -%patch387 -p1 -%patch389 -p1 -%patch390 -p1 -%patch391 -p1 -%patch392 -p1 -%patch393 -p1 -%patch394 -p1 -%patch395 -p1 -%patch396 -p1 -%patch397 -p1 -%patch398 -p1 -%patch399 -p1 -%patch400 -p1 -%patch401 -p1 -%patch402 -p1 -%patch403 -p1 -%patch404 -p1 -%patch405 -p1 -%patch406 -p1 -%patch407 -p1 -%patch408 -p1 - +%patch368 -p1 %ifarch riscv64 %patch2000 -p1 %endif @@ -2392,7 +2328,7 @@ done -- (copy_jdk_configs from %%{_libexecdir} used) or not copied at all local posix = require "posix" -local debug = false; +local debug = false SOURCE1 = "%{rpm_state_dir}/copy_jdk_configs.lua" SOURCE2 = "%{_libexecdir}/copy_jdk_configs.lua" @@ -2420,7 +2356,7 @@ else return end end -arg = nil; +arg = nil ; cjc = require "copy_jdk_configs.lua" args = {"--currentjvm", "%{uniquesuffix %{nil}}", "--jvmdir", "%{_jvmdir %{nil}}", "--origname", "%{name}", "--origjavaver", "%{javaver}", "--arch", "%{_arch}", "--temp", "%{rpm_state_dir}/%{name}.%{_arch}"} cjc.mainProgram(args) @@ -2560,83 +2496,11 @@ cjc.mainProgram(args) %endif %changelog -* Wed Nov 8 2023 kuenking111 - 1:1.8.0.392-b08.3 -- fix copy_jdk_configs bad arguments #1 to gsub got nil - -* Mon Oct 30 2023 kuenking111 - 1:1.8.0.392-b08.2 -- remove add-8142508-To-bring-j.u.z.ZipFile-s-native-implemen.patch -- remove add-8226530-ZipFile-reads-wrong-entry-size-from-ZIP6.patch -- remove add-8242842-Avoid-reallocating-name-when-checking-fo.patch -- remove add-8170831-ZipFile-implementation-no-longer-caches-.patch -- remove add-8146431-j.u.z.ZipFile.getEntry-throws-AIOOBE.patch -- remove add-8226530-test-case-fixed.patch -- remove add-Adapting-IOException-of-Zip-to-ZipException.patch - -* Wed Oct 25 2023 kuenking111 - 1:1.8.0.392-b08.1 -- add Fix-crash-in-JNI-s-GetDoubleArrayRegion-and-SetDoubl.patch -- add 8263557-Possible-NULL-dereference-in-Arena-destruct_.patch -- add 8294906-Memory-leak-in-PKCS11-NSS-TLS-server.patch -- add 8314236-Overflow-in-Collections.rotate.patch -- add 8313626-C2-crash-due-to-unexpected-exception-control.patch -- add 8312200-Fix-Parse-catch_call_exceptions-memory-leak.patch -- add 8193682-Infinite-loop-in-ZipOutputStream.close.patch -- add 8285516-clearPassword-should-be-called-in-a-finally-.patch -- add 8148470-Metadata-print-routines-should-not-print-to-.patch -- add 8293344-JDK-8242181-broke-stack-printing-for-non-att.patch -- add 8278794-Infinite-loop-in-DeflaterOutputStream.finish.patch -- add 8312065-Socket.connect-does-not-timeout-when-profili.patch -- modified fix_X509TrustManagerImpl_symantec_distrust.patch -- modified add-missing-test-case.patch - -* Fri Oct 20 2023 Autistic_boyya - 1:1.8.0.392-b08.0 -- add 8308682-Enhance-AES-performance.patch -- add Fix-the-memory-leak-of-MetaspaceAllocationTest.patch -- add Add-metaspace-memory-allocation-failure-validation.patch -- add change-value-of-GCLockerRetryAllocationCount-from-2-.patch -- del 8202952.patch -- del 8283441-C2-segmentation-fault-in-ciMethodBlocks-make.patch -- modified Dynamic-CDS-Archive.patch -- modified fix_X509TrustManagerImpl_symantec_distrust.patch -- modified kae-phase1.patch -- modified update-cacerts-and-VerifyCACerts.java-test.patch -- upgrade to jdk8u392-b08 - -* Mon Sep 25 2023 kuenking111 - 1:1.8.0.382-b05.10 -- del useless code - -* Fri Sep 22 2023 kuenking111 - 1:1.8.0.382-b05.9 -- add add-0010-8301749-Tracking-malloc-pooled-memory-size.patch -- add 8213397-Stack-dump-should-show-more-clearly-when-a-t.patch -- add Record-the-number-of-processes-to-errlog-file.patch.patch -- add 8254723-Add-diagnostic-command-to-write-Linux-perf-m.patch -- add The-OverWriteOldestGCLog-option-is-added-to-control.patch -- add add-6899049-G1-Clean-up-code-in-ptrQueue.-ch-pp-and-.patch -- add add-make-Appcds-jsa-rw-region-deterministic.patch -- add add-8142508-To-bring-j.u.z.ZipFile-s-native-implemen.patch -- add add-8198423-Improve-metaspace-chunk-allocation.patch -- add add-8226530-ZipFile-reads-wrong-entry-size-from-ZIP6.patch -- add add-fix-lock_fd-no-close-and-improve-KAEProvider.patch -- add add-8242842-Avoid-reallocating-name-when-checking-fo.patch -- add add-8170831-ZipFile-implementation-no-longer-caches-.patch -- add add-8146431-j.u.z.ZipFile.getEntry-throws-AIOOBE.patch -- add add-8226530-test-case-fixed.patch -- add add-8147940-Modify-testcase-this-test-does-not-assum.patch -- add add-8191924-Adjust-DelegatingClassLoader-s-metadata-.patch -- add add-Do-not-collect_class-when-DynamicCDS-dump.patch -- add add-add-Count-instance-klass-when-loading-from-jsa-f.patch -- add add-Adapting-IOException-of-Zip-to-ZipException.patch -- add add-8227041-runtime-memory-RunUnitTestsConcurrently.patch -- add add-fix-windows-build-Dynamic-CDS-failure.patch -- add add-Fix-aarch64-runtime-thread-signal-transfer-bug.patch -- add 8295068-SSLEngine-throws-NPE-parsing-CertificateRequ.patch - -* Mon Sep 11 2023 kuenking111 - 1:1.8.0.382-b05.8 +* Mon Sep 11 2023 kuenking111 - 1:1.8.0.382-b05.7 - Fix openjfx bingding issues +- removed 0013-8287349-AArch64-Merge-LDR-instructions-to-improve-C1.patch -* Wed Sep 6 2023 kuenking111 - 1:1.8.0.382-b05.7 -- del 0013-8287349-AArch64-Merge-LDR-instructions-to-improve-C1.patch - -* Fri Sep 1 2023 noah - 1:1.8.0.382-b05.6 +* Wed Sep 1 2023 noah - 1:1.8.0.382-b05.6 - removed cjc backward comaptiblity, to fix when both rpm 4.16 and 4.17 are in transaction * Wed Aug 30 2023 kuenking111 - 1:1.8.0.382-b05.5 diff --git a/repackReproduciblePolycies.sh b/repackReproduciblePolycies.sh index f356bd3984d511edc787bed4b743d325c98acd5a..4cc638e8c9f9b2123b4476c344b74263436a6981 100644 --- a/repackReproduciblePolycies.sh +++ b/repackReproduciblePolycies.sh @@ -15,9 +15,11 @@ if [ ! -f $ORIG ]; then continue fi d=`mktemp -d` +export JAVA_HOME=$PWD/jdk8u382-b05 +echo $JAVA_HOME NW=$d/$f pushd $d - jar xf $ORIG + $JAVA_HOME/bin/jar xf $ORIG cat $M # sed -i "s/Created-By.*/Created-By: 1.7.0/g" $M sed -i "s/Created-By.*/Created-By: $2/g" $M diff --git a/update-cacerts-and-VerifyCACerts.java-test.patch b/update-cacerts-and-VerifyCACerts.java-test.patch index dc4681f3d1e961831d4358d4a3e3a4d6b3370108..4a1fe9a768bfd9259b9f58bcde456ff60b52cbb8 100644 --- a/update-cacerts-and-VerifyCACerts.java-test.patch +++ b/update-cacerts-and-VerifyCACerts.java-test.patch @@ -253,7 +253,7 @@ diff --git a/jdk/test/sun/security/lib/cacerts/VerifyCACerts.java b/jdk/test/sun index dd107fc..791ddb6 100644 --- a/jdk/test/sun/security/lib/cacerts/VerifyCACerts.java +++ b/jdk/test/sun/security/lib/cacerts/VerifyCACerts.java -@@ -54,12 +54,12 @@ public class VerifyCACerts { +@@ -53,12 +53,12 @@ public class VerifyCACerts { + File.separator + "security" + File.separator + "cacerts"; // The numbers of certs now. @@ -263,11 +263,11 @@ index dd107fc..791ddb6 100644 // SHA-256 of cacerts, can be generated with // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95 private static final String CHECKSUM -- = "88:72:92:56:FF:E5:A3:E4:39:98:6D:18:0B:BA:CC:0B:66:CB:1D:6D:52:CE:D7:C8:AD:63:B7:F1:5F:02:24:52"; +- = "72:C7:B8:9E:54:94:D2:D9:C0:E5:9F:F7:C3:8C:3B:18:D7:42:23:82:51:F2:AD:A1:14:26:E0:4A:F2:5F:AE:80"; + = "2D:04:88:6C:52:53:54:EB:38:2D:BC:E0:AF:B7:82:F4:9E:32:A8:1A:1B:A3:AE:CF:25:CB:C2:F6:0F:4E:E1:20"; + // map of cert alias to SHA-256 fingerprint @SuppressWarnings("serial") - private static final Map FINGERPRINT_MAP @@ -93,12 +93,6 @@ public class VerifyCACerts { "E7:93:C9:B0:2F:D8:AA:13:E2:1C:31:22:8A:CC:B0:81:19:64:3B:74:9C:89:89:64:B1:74:6D:46:C3:D4:CB:D2"); put("usertrusteccca [jdk]",