From a72afb3845a7d245d462904e75b9368efefc0d39 Mon Sep 17 00:00:00 2001
From: Naoto Sato
Date: Thu, 4 Jan 2024 17:51:03 +0000
Subject: [PATCH 01/66] 8322647: Short name for the `Europe/Lisbon` time zone
is incorrect
Reviewed-by: joehw
Backport-of: ad31ec5c5f120082cedd7b9ece45b6b44147c0c5
---
.../tools/cldrconverter/CLDRConverter.java | 41 +++++++++++--
.../test/java/time/format/TestUTCParse.java | 12 ++--
.../resources/cldr/TimeZoneNamesTest.java | 61 +++++++++++++++----
3 files changed, 92 insertions(+), 22 deletions(-)
diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java
index b6298c00c9a..442a245f92f 100644
--- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java
+++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024, 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
@@ -1289,25 +1289,58 @@ private static Map coverageLevelsMap() throws Exception {
*/
private static void generateTZDBShortNamesMap() throws IOException {
Files.walk(Path.of(tzDataDir), 1, FileVisitOption.FOLLOW_LINKS)
- .filter(p -> p.toFile().isFile())
+ .filter(p -> p.toFile().isFile() && !p.endsWith("jdk11_backward"))
.forEach(p -> {
try {
String zone = null;
String rule = null;
String format = null;
+ boolean inVanguard = false;
+ boolean inRearguard = false;
for (var line : Files.readAllLines(p)) {
- if (line.contains("#STDOFF")) continue;
+ // Interpret the line in rearguard mode so that STD/DST
+ // correctly handles negative DST cases, such as "GMT/IST"
+ // vs. "IST/GMT" case for Europe/Dublin
+ if (inVanguard) {
+ if (line.startsWith("# Rearguard")) {
+ inVanguard = false;
+ inRearguard = true;
+ }
+ continue;
+ } else if (line.startsWith("# Vanguard")) {
+ inVanguard = true;
+ continue;
+ }
+ if (inRearguard) {
+ if (line.startsWith("# End of rearguard")) {
+ inRearguard = false;
+ continue;
+ } else {
+ if (line.startsWith("#\t")) {
+ line = line.substring(1); // omit #
+ }
+ }
+ }
+ if (line.isBlank() || line.matches("^[ \t]*#.*")) {
+ // ignore blank/comment lines
+ continue;
+ }
+ // remove comments in-line
line = line.replaceAll("[ \t]*#.*", "");
// Zone line
if (line.startsWith("Zone")) {
+ if (zone != null) {
+ tzdbShortNamesMap.put(zone, format + NBSP + rule);
+ }
var zl = line.split("[ \t]+", -1);
zone = zl[1];
rule = zl[3];
format = zl[4];
} else {
if (zone != null) {
- if (line.isBlank()) {
+ if (line.startsWith("Rule") ||
+ line.startsWith("Link")) {
tzdbShortNamesMap.put(zone, format + NBSP + rule);
zone = null;
rule = null;
diff --git a/test/jdk/java/time/test/java/time/format/TestUTCParse.java b/test/jdk/java/time/test/java/time/format/TestUTCParse.java
index 6da94f04f04..c1766b47030 100644
--- a/test/jdk/java/time/test/java/time/format/TestUTCParse.java
+++ b/test/jdk/java/time/test/java/time/format/TestUTCParse.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, 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
@@ -23,7 +23,7 @@
/*
* @test
* @modules jdk.localedata
- * @bug 8303440 8317979
+ * @bug 8303440 8317979 8322647
* @summary Test parsing "UTC-XX:XX" text works correctly
*/
package test.java.time.format;
@@ -43,8 +43,8 @@
public class TestUTCParse {
static {
- // Assuming CLDR's SHORT name for "America/Juneau"
- // produces "UTC\u212209:00"
+ // Assuming CLDR's SHORT name for "America/Manaus"
+ // produces "UTC\u221204:00"
System.setProperty("java.locale.providers", "CLDR");
}
@@ -60,9 +60,9 @@ public Object[][] utcZoneIdStrings() {
@Test
public void testUTCShortNameRoundTrip() {
var fmt = DateTimeFormatter.ofPattern("z", Locale.FRANCE);
- var zdt = ZonedDateTime.of(2023, 3, 3, 0, 0, 0, 0, ZoneId.of("America/Juneau"));
+ var zdt = ZonedDateTime.of(2023, 3, 3, 0, 0, 0, 0, ZoneId.of("America/Manaus"));
var formatted = fmt.format(zdt);
- assertEquals(formatted, "UTC\u221209:00");
+ assertEquals(formatted, "UTC\u221204:00");
assertEquals(fmt.parse(formatted).query(TemporalQueries.zoneId()), zdt.getZone());
}
diff --git a/test/jdk/sun/util/resources/cldr/TimeZoneNamesTest.java b/test/jdk/sun/util/resources/cldr/TimeZoneNamesTest.java
index eb56c087ad6..a468f6b1f1b 100644
--- a/test/jdk/sun/util/resources/cldr/TimeZoneNamesTest.java
+++ b/test/jdk/sun/util/resources/cldr/TimeZoneNamesTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2024, 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
@@ -23,9 +23,10 @@
/*
* @test
- * @bug 8181157 8202537 8234347 8236548 8261279
+ * @bug 8181157 8202537 8234347 8236548 8261279 8322647
* @modules jdk.localedata
- * @summary Checks CLDR time zone names are generated correctly at runtime
+ * @summary Checks CLDR time zone names are generated correctly at
+ * either build or runtime
* @run testng/othervm -Djava.locale.providers=CLDR TimeZoneNamesTest
*/
@@ -45,8 +46,8 @@
@Test
public class TimeZoneNamesTest {
- @DataProvider(name="noResourceTZs")
- Object[][] data() {
+ @DataProvider
+ Object[][] sampleTZs() {
return new Object[][] {
// tzid, locale, style, expected
@@ -174,11 +175,49 @@ Object[][] data() {
"UTC+03:00",
"heure : Istanbul",
"UTC+03:00"},
+
+ // Short names derived from TZDB at build time
+ {"Europe/Lisbon", Locale.US, "Western European Standard Time",
+ "WET",
+ "Western European Summer Time",
+ "WEST",
+ "Western European Time",
+ "WET"},
+ {"Atlantic/Azores", Locale.US, "Azores Standard Time",
+ "GMT-01:00",
+ "Azores Summer Time",
+ "GMT",
+ "Azores Time",
+ "GMT-01:00"},
+ {"Australia/Perth", Locale.US, "Australian Western Standard Time",
+ "AWST",
+ "Australian Western Daylight Time",
+ "AWDT",
+ "Western Australia Time",
+ "AWT"},
+ {"Africa/Harare", Locale.US, "Central Africa Time",
+ "CAT",
+ "Harare Daylight Time",
+ "CAT",
+ "Harare Time",
+ "CAT"},
+ {"Europe/Dublin", Locale.US, "Greenwich Mean Time",
+ "GMT",
+ "Irish Standard Time",
+ "IST",
+ "Dublin Time",
+ "GMT"},
+ {"Pacific/Gambier", Locale.US, "Gambier Time",
+ "GMT-09:00",
+ "Gambier Daylight Time",
+ "GMT-09:00",
+ "Gambier Time",
+ "GMT-09:00"},
};
}
- @Test(dataProvider="noResourceTZs")
+ @Test(dataProvider="sampleTZs")
public void test_tzNames(String tzid, Locale locale, String lstd, String sstd, String ldst, String sdst, String lgen, String sgen) {
// Standard time
assertEquals(TimeZone.getTimeZone(tzid).getDisplayName(false, TimeZone.LONG, locale), lstd);
@@ -197,16 +236,14 @@ public void test_tzNames(String tzid, Locale locale, String lstd, String sstd, S
@Test
public void test_getZoneStrings() {
assertFalse(
- Arrays.stream(Locale.getAvailableLocales())
+ Locale.availableLocales()
.limit(30)
.peek(l -> System.out.println("Locale: " + l))
.map(l -> DateFormatSymbols.getInstance(l).getZoneStrings())
- .flatMap(zs -> Arrays.stream(zs))
+ .flatMap(Arrays::stream)
.peek(names -> System.out.println(" tz: " + names[0]))
- .flatMap(names -> Arrays.stream(names))
- .filter(name -> Objects.isNull(name) || name.isEmpty())
- .findAny()
- .isPresent(),
+ .flatMap(Arrays::stream)
+ .anyMatch(name -> Objects.isNull(name) || name.isEmpty()),
"getZoneStrings() returned array containing non-empty string element(s)");
}
}
From a6e35650f9a643d9a1dabda93656a74fa49cf8dd Mon Sep 17 00:00:00 2001
From: Aleksei Voitylov
Date: Thu, 4 Jan 2024 18:19:11 +0000
Subject: [PATCH 02/66] 8321515: ARM32: Move method resolution information out
of the cpCache properly
Reviewed-by: shade
Backport-of: f573f6d233d5ea1657018c3c806fee0fac382ac3
---
src/hotspot/cpu/arm/interp_masm_arm.cpp | 6 +++-
.../arm/templateInterpreterGenerator_arm.cpp | 9 +++--
src/hotspot/cpu/arm/templateTable_arm.cpp | 33 +++++++++++--------
3 files changed, 29 insertions(+), 19 deletions(-)
diff --git a/src/hotspot/cpu/arm/interp_masm_arm.cpp b/src/hotspot/cpu/arm/interp_masm_arm.cpp
index 481c3d09e58..635acd781f9 100644
--- a/src/hotspot/cpu/arm/interp_masm_arm.cpp
+++ b/src/hotspot/cpu/arm/interp_masm_arm.cpp
@@ -303,15 +303,19 @@ void InterpreterMacroAssembler::load_field_entry(Register cache, Register index,
}
void InterpreterMacroAssembler::load_method_entry(Register cache, Register index, int bcp_offset) {
+ assert_different_registers(cache, index);
+
// Get index out of bytecode pointer
get_index_at_bcp(index, bcp_offset, cache /* as tmp */, sizeof(u2));
+
+ // sizeof(ResolvedMethodEntry) is not a power of 2 on Arm, so can't use shift
mov(cache, sizeof(ResolvedMethodEntry));
mul(index, index, cache); // Scale the index to be the entry index * sizeof(ResolvedMethodEntry)
// load constant pool cache pointer
ldr(cache, Address(FP, frame::interpreter_frame_cache_offset * wordSize));
// Get address of method entries array
- ldr(cache, Address(cache, ConstantPoolCache::method_entries_offset()));
+ ldr(cache, Address(cache, in_bytes(ConstantPoolCache::method_entries_offset())));
add(cache, cache, Array::base_offset_in_bytes());
add(cache, cache, index);
}
diff --git a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp
index ba9a3fd7a9b..efaf78ee568 100644
--- a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp
+++ b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp
@@ -370,17 +370,16 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
if (index_size == sizeof(u4)) {
__ load_resolved_indy_entry(Rcache, Rindex);
__ ldrh(Rcache, Address(Rcache, in_bytes(ResolvedIndyEntry::num_parameters_offset())));
- __ check_stack_top();
- __ add(Rstack_top, Rstack_top, AsmOperand(Rcache, lsl, Interpreter::logStackElementSize));
} else {
// Pop N words from the stack
assert(index_size == sizeof(u2), "Can only be u2");
__ load_method_entry(Rcache, Rindex);
- __ ldrh(Rcache, Address(Rcache, in_bytes(ResolvedIndyEntry::num_parameters_offset())));
- __ check_stack_top();
- __ add(Rstack_top, Rstack_top, AsmOperand(Rcache, lsl, Interpreter::logStackElementSize));
+ __ ldrh(Rcache, Address(Rcache, in_bytes(ResolvedMethodEntry::num_parameters_offset())));
}
+ __ check_stack_top();
+ __ add(Rstack_top, Rstack_top, AsmOperand(Rcache, lsl, Interpreter::logStackElementSize));
+
__ convert_retval_to_tos(state);
__ check_and_handle_popframe();
diff --git a/src/hotspot/cpu/arm/templateTable_arm.cpp b/src/hotspot/cpu/arm/templateTable_arm.cpp
index e478f08c977..55a0120e7c7 100644
--- a/src/hotspot/cpu/arm/templateTable_arm.cpp
+++ b/src/hotspot/cpu/arm/templateTable_arm.cpp
@@ -3666,15 +3666,15 @@ void TemplateTable::prepare_invoke(Register Rcache, Register recv) {
// load receiver if needed (after extra argument is pushed so parameter size is correct)
if (load_receiver) {
__ ldrh(recv, Address(Rcache, in_bytes(ResolvedMethodEntry::num_parameters_offset())));
- Address recv_addr = __ receiver_argument_address(Rstack_top, Rtemp, recv);
- __ ldr(recv, recv_addr);
+ __ add(recv, Rstack_top, AsmOperand(recv, lsl, Interpreter::logStackElementSize));
+ __ ldr(recv, Address(recv, -Interpreter::stackElementSize));
__ verify_oop(recv);
}
// load return address
{ const address table = (address) Interpreter::invoke_return_entry_table_for(code);
- __ mov_slow(Rtemp, table);
- __ ldr(LR, Address::indexed_ptr(Rtemp, ret_type));
+ __ mov_slow(LR, table);
+ __ ldr(LR, Address::indexed_ptr(LR, ret_type));
}
}
@@ -3744,10 +3744,13 @@ void TemplateTable::invokevirtual(int byte_no) {
void TemplateTable::invokespecial(int byte_no) {
transition(vtos, vtos);
assert(byte_no == f1_byte, "use this argument");
+
const Register Rrecv = R2_tmp;
- load_resolved_method_entry_special_or_static(R2_tmp, // ResolvedMethodEntry*
+ const Register Rflags = R3_tmp;
+
+ load_resolved_method_entry_special_or_static(Rrecv, // ResolvedMethodEntry*
Rmethod, // Method*
- R3_tmp); // Flags
+ Rflags); // Flags
prepare_invoke(Rrecv, Rrecv);
__ verify_oop(Rrecv);
__ null_check(Rrecv, Rtemp);
@@ -3760,12 +3763,16 @@ void TemplateTable::invokespecial(int byte_no) {
void TemplateTable::invokestatic(int byte_no) {
transition(vtos, vtos);
assert(byte_no == f1_byte, "use this argument");
- load_resolved_method_entry_special_or_static(R2_tmp, // ResolvedMethodEntry*
+
+ const Register Rrecv = R2_tmp;
+ const Register Rflags = R3_tmp;
+
+ load_resolved_method_entry_special_or_static(Rrecv, // ResolvedMethodEntry*
Rmethod, // Method*
- R3_tmp); // Flags
- prepare_invoke(R2_tmp, R2_tmp);
+ Rflags); // Flags
+ prepare_invoke(Rrecv, Rrecv);
// do the call
- __ profile_call(R2_tmp);
+ __ profile_call(Rrecv);
__ jump_from_interpreted(Rmethod);
}
@@ -3788,10 +3795,10 @@ void TemplateTable::invokeinterface(int byte_no) {
const Register Rflags = R3_tmp;
const Register Rklass = R2_tmp; // Note! Same register with Rrecv
- load_resolved_method_entry_interface(R2_tmp, // ResolvedMethodEntry*
- R1_tmp, // Klass*
+ load_resolved_method_entry_interface(Rrecv, // ResolvedMethodEntry*
+ Rinterf, // Klass*
Rmethod, // Method* or itable/vtable index
- R3_tmp); // Flags
+ Rflags); // Flags
prepare_invoke(Rrecv, Rrecv);
// First check for Object case, then private interface method,
From b121931959e08951a8cc02eb925a77657441f175 Mon Sep 17 00:00:00 2001
From: Joe Wang
Date: Fri, 5 Jan 2024 02:26:02 +0000
Subject: [PATCH 03/66] 8322214: Return value of XMLInputFactory.getProperty()
changed from boolean to String in JDK 22 early access builds
Reviewed-by: naoto, iris
Backport-of: 755722ced60a686799c7f419feae61c04ce41f09
---
.../xerces/internal/impl/PropertyManager.java | 7 +-
.../internal/parsers/AbstractSAXParser.java | 9 +-
.../common/dtd/DTDPropertiesTest.java | 132 ++++++++++++++++++
3 files changed, 144 insertions(+), 4 deletions(-)
create mode 100644 test/jaxp/javax/xml/jaxp/unittest/common/dtd/DTDPropertiesTest.java
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java
index da21fb4a511..c8d032109a0 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2024, 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
@@ -46,7 +46,7 @@
* @author K Venugopal
* @author Sunitha Reddy
*
- * @LastModified: Nov 2023
+ * @LastModified: Jan 2024
*/
public class PropertyManager {
@@ -184,6 +184,9 @@ public boolean containsProperty(String property) {
* @return the value of a property
*/
public Object getProperty(String property) {
+ if (XMLInputFactory.SUPPORT_DTD.equals(property)) {
+ return fSecurityManager.is(XMLSecurityManager.Limit.STAX_SUPPORT_DTD);
+ }
/**
* Check to see if the property is managed by the security manager *
*/
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser.java
index ff4e047d4ca..614bd2fdc99 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -79,7 +79,7 @@
* @author Arnaud Le Hors, IBM
* @author Andy Clark, IBM
*
- * @LastModified: July 2023
+ * @LastModified: Jan 2024
*/
@SuppressWarnings("deprecation")
public abstract class AbstractSAXParser
@@ -1831,6 +1831,11 @@ else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
}
*/
+ // Handle properties managed by XMLSecurityManager
+ if (featureId.equals(XMLSecurityManager.DISALLOW_DTD)) {
+ return securityManager.is(XMLSecurityManager.Limit.XERCES_DISALLOW_DTD);
+ }
+
return fConfiguration.getFeature(featureId);
}
catch (XMLConfigurationException e) {
diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/dtd/DTDPropertiesTest.java b/test/jaxp/javax/xml/jaxp/unittest/common/dtd/DTDPropertiesTest.java
new file mode 100644
index 00000000000..14215004937
--- /dev/null
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/dtd/DTDPropertiesTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2024, 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 common.dtd;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.stream.XMLInputFactory;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.xml.sax.XMLReader;
+
+/*
+ * @test
+ * @bug 8322214
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng common.dtd.DTDPropertiesTest
+ * @summary Verifies the getProperty function on DTD properties works the same
+ * as before the property 'jdk.xml.dtd.support' was introduced.
+ */
+public class DTDPropertiesTest {
+ // Xerces Property
+ public static final String DISALLOW_DTD = "http://apache.org/xml/features/disallow-doctype-decl";
+
+ /*
+ * DataProvider for verifying Xerces' disallow-DTD feature
+ * Fields: property name, setting (null indicates not specified), expected
+ */
+ @DataProvider(name = "XercesProperty")
+ public Object[][] getXercesProperty() throws Exception {
+ return new Object[][] {
+ { DISALLOW_DTD, null, false},
+ { DISALLOW_DTD, true, true},
+ { DISALLOW_DTD, false, false},
+ };
+ }
+
+ /*
+ * DataProvider for verifying StAX's supportDTD feature
+ * Fields: property name, setting (null indicates not specified), expected
+ */
+ @DataProvider(name = "StAXProperty")
+ public Object[][] getStAXProperty() throws Exception {
+ return new Object[][] {
+ { XMLInputFactory.SUPPORT_DTD, null, true},
+ { XMLInputFactory.SUPPORT_DTD, true, true},
+ { XMLInputFactory.SUPPORT_DTD, false, false},
+ };
+ }
+
+ /**
+ * Verifies the disallow DTD feature with SAX.
+ *
+ * @param name the name of the property
+ * @param setting the setting of the property, null means not specified
+ * @param expected the expected value
+ * @throws Exception if the test fails
+ */
+ @Test(dataProvider = "XercesProperty")
+ public void testSAX(String name, Boolean setting, Boolean expected) throws Exception {
+ SAXParserFactory spf = SAXParserFactory.newDefaultInstance();
+ if (setting != null) {
+ spf.setFeature(name, setting);
+ }
+ Assert.assertEquals((Boolean)spf.getFeature(name), expected);
+ System.out.println(spf.getFeature(name));
+
+
+ SAXParser saxParser = spf.newSAXParser();
+ XMLReader reader = saxParser.getXMLReader();
+ Assert.assertEquals((Boolean)reader.getFeature(name), expected);
+ System.out.println(reader.getFeature(name));
+ }
+
+ /**
+ * Verifies the disallow DTD feature with DOM.
+ *
+ * @param name the name of the property
+ * @param setting the setting of the property, null means not specified
+ * @param expected the expected value
+ * @throws Exception if the test fails
+ */
+ @Test(dataProvider = "XercesProperty")
+ public void testDOM(String name, Boolean setting, Boolean expected) throws Exception {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance();
+ if (setting != null) {
+ dbf.setFeature(name, setting);
+ }
+ Assert.assertEquals((Boolean)dbf.getFeature(name), expected);
+ System.out.println(dbf.getFeature(name));
+ }
+
+ /**
+ * Verifies the StAX's supportDTD feature.
+ *
+ * @param name the name of the property
+ * @param setting the setting of the property, null means not specified
+ * @param expected the expected value
+ * @throws Exception if the test fails
+ */
+ @Test(dataProvider = "StAXProperty")
+ public void testStAX(String name, Boolean setting, Boolean expected) throws Exception {
+ XMLInputFactory xif = XMLInputFactory.newInstance();
+ if (setting != null) {
+ xif.setProperty(name, setting);
+ }
+ Assert.assertEquals((Boolean)xif.getProperty(name), expected);
+ System.out.println((Boolean)xif.getProperty(name));
+ }
+}
From bb0e203d134b35bb1078c3be10f7a6952f6c75bc Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Fri, 5 Jan 2024 12:43:15 +0000
Subject: [PATCH 04/66] 8321582: yield .class not parsed
correctly.
Reviewed-by: shade, vromero
Backport-of: ce8399fd6071766114f5f201b6e44a7abdba9f5a
---
.../sun/tools/javac/parser/JavacParser.java | 1 +
.../javac/switchexpr/ExpressionSwitch.java | 29 +++++++++++++++++--
2 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
index 78be89ec1ea..d83fb85b7f2 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
@@ -2853,6 +2853,7 @@ List blockStatement() {
case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
case NULL: case IDENTIFIER: case TRUE: case FALSE:
case NEW: case SWITCH: case THIS: case SUPER:
+ case BYTE, CHAR, SHORT, INT, LONG, FLOAT, DOUBLE, VOID, BOOLEAN:
isYieldStatement = true;
break;
case PLUSPLUS: case SUBSUB:
diff --git a/test/langtools/tools/javac/switchexpr/ExpressionSwitch.java b/test/langtools/tools/javac/switchexpr/ExpressionSwitch.java
index b5c94d3ce94..1c040052e69 100644
--- a/test/langtools/tools/javac/switchexpr/ExpressionSwitch.java
+++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitch.java
@@ -1,12 +1,12 @@
/*
* @test /nodynamiccopyright/
- * @bug 8206986 8222169 8224031 8240964 8267119 8268670
+ * @bug 8206986 8222169 8224031 8240964 8267119 8268670 8321582
* @summary Check expression switch works.
- * @compile/fail/ref=ExpressionSwitch-old.out --release 9 -XDrawDiagnostics ExpressionSwitch.java
* @compile ExpressionSwitch.java
* @run main ExpressionSwitch
*/
+// * @compile/fail/ref=ExpressionSwitch-old.out --release 9 -XDrawDiagnostics ExpressionSwitch.java
import java.util.Objects;
import java.util.function.Supplier;
@@ -35,6 +35,16 @@ private void run() {
localClass(T.A);
assertEquals(castSwitchExpressions(T.A), "A");
testTypeInference(true, 0);
+ assertEquals(yieldPrimitiveDotClass("byte"), byte.class);
+ assertEquals(yieldPrimitiveDotClass("char"), char.class);
+ assertEquals(yieldPrimitiveDotClass("short"), short.class);
+ assertEquals(yieldPrimitiveDotClass("int"), int.class);
+ assertEquals(yieldPrimitiveDotClass("long"), long.class);
+ assertEquals(yieldPrimitiveDotClass("float"), float.class);
+ assertEquals(yieldPrimitiveDotClass("double"), double.class);
+ assertEquals(yieldPrimitiveDotClass("void"), void.class);
+ assertEquals(yieldPrimitiveDotClass("boolean"), boolean.class);
+ assertEquals(yieldPrimitiveDotClass("other"), null);
}
private String print(T t) {
@@ -140,6 +150,21 @@ private boolean yieldUnaryNotOperator(String s, boolean b) {
};
}
+ private Class> yieldPrimitiveDotClass(String s) {
+ return switch (s) {
+ case "byte": yield byte.class;
+ case "char": yield char.class;
+ case "short": yield short.class;
+ case "int": yield int.class;
+ case "long": yield long.class;
+ case "float": yield float.class;
+ case "double": yield double.class;
+ case "void": yield void.class;
+ case "boolean": yield boolean.class;
+ default: yield null;
+ };
+ }
+
private void localClass(T t) {
String good = "good";
class L {
From 01cb043b293e7bec822fb034008ad42b1cb8b481 Mon Sep 17 00:00:00 2001
From: Patricio Chilano Mateo
Date: Fri, 5 Jan 2024 15:52:47 +0000
Subject: [PATCH 05/66] 8320275: assert(_chunk->bitmap().at(index)) failed: Bit
not set at index
Reviewed-by: dholmes
Backport-of: e9e694f4ef7b080d7fe1ad5b2f2daa2fccd0456e
---
.../cpu/aarch64/sharedRuntime_aarch64.cpp | 12 +++++---
src/hotspot/cpu/arm/sharedRuntime_arm.cpp | 1 -
src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp | 2 +-
src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 12 +++++---
src/hotspot/cpu/s390/sharedRuntime_s390.cpp | 2 +-
src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp | 3 +-
src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 12 +++++---
src/hotspot/share/c1/c1_FrameMap.cpp | 2 +-
src/hotspot/share/code/nmethod.cpp | 2 +-
src/hotspot/share/oops/method.hpp | 3 +-
src/hotspot/share/oops/stackChunkOop.hpp | 2 +-
.../share/oops/stackChunkOop.inline.hpp | 3 +-
src/hotspot/share/prims/foreignGlobals.cpp | 2 +-
.../share/runtime/continuationFreezeThaw.cpp | 30 ++++++++++++++-----
src/hotspot/share/runtime/frame.cpp | 2 +-
src/hotspot/share/runtime/sharedRuntime.cpp | 4 +--
src/hotspot/share/runtime/signature.cpp | 21 +++++++------
17 files changed, 72 insertions(+), 43 deletions(-)
diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
index c7b45ff0dde..8694734c751 100644
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
@@ -310,7 +310,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
uint int_args = 0;
uint fp_args = 0;
- uint stk_args = 0; // inc by 2 each time
+ uint stk_args = 0;
for (int i = 0; i < total_args_passed; i++) {
switch (sig_bt[i]) {
@@ -322,8 +322,9 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
if (int_args < Argument::n_int_register_parameters_j) {
regs[i].set1(INT_ArgReg[int_args++]->as_VMReg());
} else {
+ stk_args = align_up(stk_args, 2);
regs[i].set1(VMRegImpl::stack2reg(stk_args));
- stk_args += 2;
+ stk_args += 1;
}
break;
case T_VOID:
@@ -340,6 +341,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
if (int_args < Argument::n_int_register_parameters_j) {
regs[i].set2(INT_ArgReg[int_args++]->as_VMReg());
} else {
+ stk_args = align_up(stk_args, 2);
regs[i].set2(VMRegImpl::stack2reg(stk_args));
stk_args += 2;
}
@@ -348,8 +350,9 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
if (fp_args < Argument::n_float_register_parameters_j) {
regs[i].set1(FP_ArgReg[fp_args++]->as_VMReg());
} else {
+ stk_args = align_up(stk_args, 2);
regs[i].set1(VMRegImpl::stack2reg(stk_args));
- stk_args += 2;
+ stk_args += 1;
}
break;
case T_DOUBLE:
@@ -357,6 +360,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
if (fp_args < Argument::n_float_register_parameters_j) {
regs[i].set2(FP_ArgReg[fp_args++]->as_VMReg());
} else {
+ stk_args = align_up(stk_args, 2);
regs[i].set2(VMRegImpl::stack2reg(stk_args));
stk_args += 2;
}
@@ -367,7 +371,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
}
}
- return align_up(stk_args, 2);
+ return stk_args;
}
// Patch the callers callsite with entry to compiled code if it exists.
diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
index 9a65f9f09fe..716c7b7575e 100644
--- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
+++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp
@@ -441,7 +441,6 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
}
}
- if (slot & 1) slot++;
return slot;
}
diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
index 824996168a9..3382df355da 100644
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
+++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
@@ -734,7 +734,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
ShouldNotReachHere();
}
}
- return align_up(stk, 2);
+ return stk;
}
#if defined(COMPILER1) || defined(COMPILER2)
diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
index 36430e126f9..582aa400875 100644
--- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp
@@ -266,7 +266,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
uint int_args = 0;
uint fp_args = 0;
- uint stk_args = 0; // inc by 2 each time
+ uint stk_args = 0;
for (int i = 0; i < total_args_passed; i++) {
switch (sig_bt[i]) {
@@ -278,8 +278,9 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
if (int_args < Argument::n_int_register_parameters_j) {
regs[i].set1(INT_ArgReg[int_args++]->as_VMReg());
} else {
+ stk_args = align_up(stk_args, 2);
regs[i].set1(VMRegImpl::stack2reg(stk_args));
- stk_args += 2;
+ stk_args += 1;
}
break;
case T_VOID:
@@ -295,6 +296,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
if (int_args < Argument::n_int_register_parameters_j) {
regs[i].set2(INT_ArgReg[int_args++]->as_VMReg());
} else {
+ stk_args = align_up(stk_args, 2);
regs[i].set2(VMRegImpl::stack2reg(stk_args));
stk_args += 2;
}
@@ -303,8 +305,9 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
if (fp_args < Argument::n_float_register_parameters_j) {
regs[i].set1(FP_ArgReg[fp_args++]->as_VMReg());
} else {
+ stk_args = align_up(stk_args, 2);
regs[i].set1(VMRegImpl::stack2reg(stk_args));
- stk_args += 2;
+ stk_args += 1;
}
break;
case T_DOUBLE:
@@ -312,6 +315,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
if (fp_args < Argument::n_float_register_parameters_j) {
regs[i].set2(FP_ArgReg[fp_args++]->as_VMReg());
} else {
+ stk_args = align_up(stk_args, 2);
regs[i].set2(VMRegImpl::stack2reg(stk_args));
stk_args += 2;
}
@@ -321,7 +325,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
}
}
- return align_up(stk_args, 2);
+ return stk_args;
}
// Patch the callers callsite with entry to compiled code if it exists.
diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
index 4798f35f19d..ed1795cfa33 100644
--- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
+++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
@@ -755,7 +755,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
ShouldNotReachHere();
}
}
- return align_up(stk, 2);
+ return stk;
}
int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp
index 3ae539bac8d..571160523cb 100644
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp
@@ -528,8 +528,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
}
}
- // return value can be odd number of VMRegImpl stack slots make multiple of 2
- return align_up(stack, 2);
+ return stack;
}
// Patch the callers callsite with entry to compiled code if it exists.
diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
index bf15dab0703..faa423bcf8e 100644
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
@@ -498,7 +498,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
uint int_args = 0;
uint fp_args = 0;
- uint stk_args = 0; // inc by 2 each time
+ uint stk_args = 0;
for (int i = 0; i < total_args_passed; i++) {
switch (sig_bt[i]) {
@@ -510,8 +510,9 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
if (int_args < Argument::n_int_register_parameters_j) {
regs[i].set1(INT_ArgReg[int_args++]->as_VMReg());
} else {
+ stk_args = align_up(stk_args, 2);
regs[i].set1(VMRegImpl::stack2reg(stk_args));
- stk_args += 2;
+ stk_args += 1;
}
break;
case T_VOID:
@@ -528,6 +529,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
if (int_args < Argument::n_int_register_parameters_j) {
regs[i].set2(INT_ArgReg[int_args++]->as_VMReg());
} else {
+ stk_args = align_up(stk_args, 2);
regs[i].set2(VMRegImpl::stack2reg(stk_args));
stk_args += 2;
}
@@ -536,8 +538,9 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
if (fp_args < Argument::n_float_register_parameters_j) {
regs[i].set1(FP_ArgReg[fp_args++]->as_VMReg());
} else {
+ stk_args = align_up(stk_args, 2);
regs[i].set1(VMRegImpl::stack2reg(stk_args));
- stk_args += 2;
+ stk_args += 1;
}
break;
case T_DOUBLE:
@@ -545,6 +548,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
if (fp_args < Argument::n_float_register_parameters_j) {
regs[i].set2(FP_ArgReg[fp_args++]->as_VMReg());
} else {
+ stk_args = align_up(stk_args, 2);
regs[i].set2(VMRegImpl::stack2reg(stk_args));
stk_args += 2;
}
@@ -555,7 +559,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
}
}
- return align_up(stk_args, 2);
+ return stk_args;
}
// Patch the callers callsite with entry to compiled code if it exists.
diff --git a/src/hotspot/share/c1/c1_FrameMap.cpp b/src/hotspot/share/c1/c1_FrameMap.cpp
index c55e41f4583..ace4fe8209d 100644
--- a/src/hotspot/share/c1/c1_FrameMap.cpp
+++ b/src/hotspot/share/c1/c1_FrameMap.cpp
@@ -72,7 +72,7 @@ CallingConvention* FrameMap::java_calling_convention(const BasicTypeArray* signa
}
}
- intptr_t out_preserve = SharedRuntime::java_calling_convention(sig_bt, regs, sizeargs);
+ intptr_t out_preserve = align_up(SharedRuntime::java_calling_convention(sig_bt, regs, sizeargs), 2);
LIR_OprList* args = new LIR_OprList(signature->length());
for (i = 0; i < sizeargs;) {
BasicType t = sig_bt[i];
diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp
index 64adc566a24..75582201087 100644
--- a/src/hotspot/share/code/nmethod.cpp
+++ b/src/hotspot/share/code/nmethod.cpp
@@ -3017,7 +3017,7 @@ void nmethod::print_nmethod_labels(outputStream* stream, address block_begin, bo
assert(sig_index == sizeargs, "");
}
const char* spname = "sp"; // make arch-specific?
- intptr_t out_preserve = SharedRuntime::java_calling_convention(sig_bt, regs, sizeargs);
+ SharedRuntime::java_calling_convention(sig_bt, regs, sizeargs);
int stack_slot_offset = this->frame_size() * wordSize;
int tab1 = 14, tab2 = 24;
int sig_index = 0;
diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp
index 34f982d9f40..89d5ccbb168 100644
--- a/src/hotspot/share/oops/method.hpp
+++ b/src/hotspot/share/oops/method.hpp
@@ -395,7 +395,8 @@ class Method : public Metadata {
void remove_unshareable_flags() NOT_CDS_RETURN;
// the number of argument reg slots that the compiled method uses on the stack.
- int num_stack_arg_slots() const { return constMethod()->num_stack_arg_slots(); }
+ int num_stack_arg_slots(bool rounded = true) const {
+ return rounded ? align_up(constMethod()->num_stack_arg_slots(), 2) : constMethod()->num_stack_arg_slots(); }
virtual void metaspace_pointers_do(MetaspaceClosure* iter);
virtual MetaspaceObj::Type type() const { return MethodType; }
diff --git a/src/hotspot/share/oops/stackChunkOop.hpp b/src/hotspot/share/oops/stackChunkOop.hpp
index 36b06ecd324..abfe47ad3f1 100644
--- a/src/hotspot/share/oops/stackChunkOop.hpp
+++ b/src/hotspot/share/oops/stackChunkOop.hpp
@@ -155,7 +155,7 @@ class stackChunkOopDesc : public instanceOopDesc {
inline void* gc_data() const;
inline BitMapView bitmap() const;
- inline BitMap::idx_t bit_index_for(intptr_t* p) const;
+ inline BitMap::idx_t bit_index_for(address p) const;
inline intptr_t* address_for_bit(BitMap::idx_t index) const;
template inline BitMap::idx_t bit_index_for(OopT* p) const;
template inline OopT* address_for_bit(BitMap::idx_t index) const;
diff --git a/src/hotspot/share/oops/stackChunkOop.inline.hpp b/src/hotspot/share/oops/stackChunkOop.inline.hpp
index e1993207266..c7590861032 100644
--- a/src/hotspot/share/oops/stackChunkOop.inline.hpp
+++ b/src/hotspot/share/oops/stackChunkOop.inline.hpp
@@ -256,12 +256,13 @@ inline BitMapView stackChunkOopDesc::bitmap() const {
return bitmap;
}
-inline BitMap::idx_t stackChunkOopDesc::bit_index_for(intptr_t* p) const {
+inline BitMap::idx_t stackChunkOopDesc::bit_index_for(address p) const {
return UseCompressedOops ? bit_index_for((narrowOop*)p) : bit_index_for((oop*)p);
}
template
inline BitMap::idx_t stackChunkOopDesc::bit_index_for(OopT* p) const {
+ assert(is_aligned(p, alignof(OopT)), "should be aligned: " PTR_FORMAT, p2i(p));
assert(p >= (OopT*)start_address(), "Address not in chunk");
return p - (OopT*)start_address();
}
diff --git a/src/hotspot/share/prims/foreignGlobals.cpp b/src/hotspot/share/prims/foreignGlobals.cpp
index f3653d29886..11b0b8ace7c 100644
--- a/src/hotspot/share/prims/foreignGlobals.cpp
+++ b/src/hotspot/share/prims/foreignGlobals.cpp
@@ -140,7 +140,7 @@ int ForeignGlobals::compute_out_arg_bytes(const GrowableArray& out_re
int ForeignGlobals::java_calling_convention(const BasicType* signature, int num_args, GrowableArray& out_regs) {
VMRegPair* vm_regs = NEW_RESOURCE_ARRAY(VMRegPair, num_args);
- int slots = SharedRuntime::java_calling_convention(signature, vm_regs, num_args);
+ int slots = align_up(SharedRuntime::java_calling_convention(signature, vm_regs, num_args), 2);
for (int i = 0; i < num_args; i++) {
VMRegPair pair = vm_regs[i];
// note, we ignore second here. Signature should consist of register-size values. So there should be
diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp
index fe1dfc62ee4..969e14f150e 100644
--- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp
+++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp
@@ -1775,7 +1775,7 @@ class ThawBase : public StackObj {
inline void before_thaw_java_frame(const frame& hf, const frame& caller, bool bottom, int num_frame);
inline void after_thaw_java_frame(const frame& f, bool bottom);
inline void patch(frame& f, const frame& caller, bool bottom);
- void clear_bitmap_bits(intptr_t* start, int range);
+ void clear_bitmap_bits(address start, address end);
NOINLINE void recurse_thaw_interpreted_frame(const frame& hf, frame& caller, int num_frames);
void recurse_thaw_compiled_frame(const frame& hf, frame& caller, int num_frames, bool stub_caller);
@@ -2166,13 +2166,22 @@ inline void ThawBase::patch(frame& f, const frame& caller, bool bottom) {
assert(!bottom || (_cont.is_empty() != Continuation::is_cont_barrier_frame(f)), "");
}
-void ThawBase::clear_bitmap_bits(intptr_t* start, int range) {
+void ThawBase::clear_bitmap_bits(address start, address end) {
+ assert(is_aligned(start, wordSize), "should be aligned: " PTR_FORMAT, p2i(start));
+ assert(is_aligned(end, VMRegImpl::stack_slot_size), "should be aligned: " PTR_FORMAT, p2i(end));
+
// we need to clear the bits that correspond to arguments as they reside in the caller frame
- // or they will keep objects that are otherwise unreachable alive
- log_develop_trace(continuations)("clearing bitmap for " INTPTR_FORMAT " - " INTPTR_FORMAT, p2i(start), p2i(start+range));
+ // or they will keep objects that are otherwise unreachable alive.
+
+ // Align `end` if UseCompressedOops is not set to avoid UB when calculating the bit index, since
+ // `end` could be at an odd number of stack slots from `start`, i.e might not be oop aligned.
+ // If that's the case the bit range corresponding to the last stack slot should not have bits set
+ // anyways and we assert that before returning.
+ address effective_end = UseCompressedOops ? end : align_down(end, wordSize);
+ log_develop_trace(continuations)("clearing bitmap for " INTPTR_FORMAT " - " INTPTR_FORMAT, p2i(start), p2i(effective_end));
stackChunkOop chunk = _cont.tail();
- chunk->bitmap().clear_range(chunk->bit_index_for(start),
- chunk->bit_index_for(start+range));
+ chunk->bitmap().clear_range(chunk->bit_index_for(start), chunk->bit_index_for(effective_end));
+ assert(chunk->bitmap().count_one_bits(chunk->bit_index_for(effective_end), chunk->bit_index_for(end)) == 0, "bits should not be set");
}
NOINLINE void ThawBase::recurse_thaw_interpreted_frame(const frame& hf, frame& caller, int num_frames) {
@@ -2225,7 +2234,9 @@ NOINLINE void ThawBase::recurse_thaw_interpreted_frame(const frame& hf, frame& c
_cont.tail()->fix_thawed_frame(caller, SmallRegisterMap::instance);
} else if (_cont.tail()->has_bitmap() && locals > 0) {
assert(hf.is_heap_frame(), "should be");
- clear_bitmap_bits(heap_frame_bottom - locals, locals);
+ address start = (address)(heap_frame_bottom - locals);
+ address end = (address)heap_frame_bottom;
+ clear_bitmap_bits(start, end);
}
DEBUG_ONLY(after_thaw_java_frame(f, is_bottom_frame);)
@@ -2298,7 +2309,10 @@ void ThawBase::recurse_thaw_compiled_frame(const frame& hf, frame& caller, int n
// can only fix caller once this frame is thawed (due to callee saved regs); this happens on the stack
_cont.tail()->fix_thawed_frame(caller, SmallRegisterMap::instance);
} else if (_cont.tail()->has_bitmap() && added_argsize > 0) {
- clear_bitmap_bits(heap_frame_top + ContinuationHelper::CompiledFrame::size(hf) + frame::metadata_words_at_top, added_argsize);
+ address start = (address)(heap_frame_top + ContinuationHelper::CompiledFrame::size(hf) + frame::metadata_words_at_top);
+ int stack_args_slots = f.cb()->as_compiled_method()->method()->num_stack_arg_slots(false /* rounded */);
+ int argsize_in_bytes = stack_args_slots * VMRegImpl::stack_slot_size;
+ clear_bitmap_bits(start, start + argsize_in_bytes);
}
DEBUG_ONLY(after_thaw_java_frame(f, is_bottom_frame);)
diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp
index f4893bae5db..c68180e105b 100644
--- a/src/hotspot/share/runtime/frame.cpp
+++ b/src/hotspot/share/runtime/frame.cpp
@@ -1439,7 +1439,7 @@ void frame::describe(FrameValues& values, int frame_no, const RegisterMap* reg_m
assert(sig_index == sizeargs, "");
}
int stack_arg_slots = SharedRuntime::java_calling_convention(sig_bt, regs, sizeargs);
- assert(stack_arg_slots == m->num_stack_arg_slots(), "");
+ assert(stack_arg_slots == m->num_stack_arg_slots(false /* rounded */), "");
int out_preserve = SharedRuntime::out_preserve_stack_slots();
int sig_index = 0;
int arg_index = (m->is_static() ? 0 : -1);
diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp
index 9d582b790a1..94d42622c81 100644
--- a/src/hotspot/share/runtime/sharedRuntime.cpp
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp
@@ -2004,7 +2004,7 @@ void SharedRuntime::check_member_name_argument_is_last_argument(const methodHand
assert(member_arg_pos >= 0 && member_arg_pos < total_args_passed, "oob");
assert(sig_bt[member_arg_pos] == T_OBJECT, "dispatch argument must be an object");
- int comp_args_on_stack = java_calling_convention(sig_bt, regs_without_member_name, total_args_passed - 1);
+ java_calling_convention(sig_bt, regs_without_member_name, total_args_passed - 1);
for (int i = 0; i < member_arg_pos; i++) {
VMReg a = regs_with_member_name[i].first();
@@ -3102,7 +3102,7 @@ void AdapterHandlerLibrary::create_native_wrapper(const methodHandle& method) {
BasicType ret_type = si.return_type();
// Now get the compiled-Java arguments layout.
- int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed);
+ SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed);
// Generate the compiled-to-native wrapper code
nm = SharedRuntime::generate_native_wrapper(&_masm, method, compile_id, sig_bt, regs, ret_type);
diff --git a/src/hotspot/share/runtime/signature.cpp b/src/hotspot/share/runtime/signature.cpp
index b085bf5fd05..081bdd2e0d3 100644
--- a/src/hotspot/share/runtime/signature.cpp
+++ b/src/hotspot/share/runtime/signature.cpp
@@ -178,7 +178,6 @@ void Fingerprinter::compute_fingerprint_and_return_type(bool static_flag) {
}
#if defined(_LP64) && !defined(ZERO)
- _stack_arg_slots = align_up(_stack_arg_slots, 2);
#ifdef ASSERT
int dbg_stack_arg_slots = compute_num_stack_arg_slots(_signature, _param_size, static_flag);
assert(_stack_arg_slots == dbg_stack_arg_slots, "fingerprinter: %d full: %d", _stack_arg_slots, dbg_stack_arg_slots);
@@ -235,14 +234,17 @@ void Fingerprinter::do_type_calling_convention(BasicType type) {
case T_BYTE:
case T_SHORT:
case T_INT:
-#if defined(PPC64) || defined(S390)
if (_int_args < Argument::n_int_register_parameters_j) {
_int_args++;
} else {
+#if defined(PPC64) || defined(S390)
+ _stack_arg_slots += 1;
+#else
+ _stack_arg_slots = align_up(_stack_arg_slots, 2);
_stack_arg_slots += 1;
+#endif // defined(PPC64) || defined(S390)
}
break;
-#endif // defined(PPC64) || defined(S390)
case T_LONG:
case T_OBJECT:
case T_ARRAY:
@@ -250,26 +252,27 @@ void Fingerprinter::do_type_calling_convention(BasicType type) {
if (_int_args < Argument::n_int_register_parameters_j) {
_int_args++;
} else {
- PPC64_ONLY(_stack_arg_slots = align_up(_stack_arg_slots, 2));
- S390_ONLY(_stack_arg_slots = align_up(_stack_arg_slots, 2));
+ _stack_arg_slots = align_up(_stack_arg_slots, 2);
_stack_arg_slots += 2;
}
break;
case T_FLOAT:
-#if defined(PPC64) || defined(S390)
if (_fp_args < Argument::n_float_register_parameters_j) {
_fp_args++;
} else {
+#if defined(PPC64) || defined(S390)
+ _stack_arg_slots += 1;
+#else
+ _stack_arg_slots = align_up(_stack_arg_slots, 2);
_stack_arg_slots += 1;
+#endif // defined(PPC64) || defined(S390)
}
break;
-#endif // defined(PPC64) || defined(S390)
case T_DOUBLE:
if (_fp_args < Argument::n_float_register_parameters_j) {
_fp_args++;
} else {
- PPC64_ONLY(_stack_arg_slots = align_up(_stack_arg_slots, 2));
- S390_ONLY(_stack_arg_slots = align_up(_stack_arg_slots, 2));
+ _stack_arg_slots = align_up(_stack_arg_slots, 2);
_stack_arg_slots += 2;
}
break;
From 28279ee615b3b6df7428da84365d2310ba814f60 Mon Sep 17 00:00:00 2001
From: Tobias Hartmann
Date: Fri, 5 Jan 2024 17:31:26 +0000
Subject: [PATCH 06/66] 8322985: [BACKOUT] 8318562: Computational test more
than 2x slower when AVX instructions are used
Reviewed-by: shade, kvn
Backport-of: ed9f3243f04718a50bbdc589437872f7215c0e08
---
src/hotspot/cpu/x86/macroAssembler_x86.cpp | 86 -----------
src/hotspot/cpu/x86/macroAssembler_x86.hpp | 17 ---
src/hotspot/cpu/x86/x86_64.ad | 4 +-
.../bench/vm/compiler/x86/ComputePI.java | 142 ------------------
4 files changed, 2 insertions(+), 247 deletions(-)
delete mode 100644 test/micro/org/openjdk/bench/vm/compiler/x86/ComputePI.java
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
index aec1f3c9105..88296656485 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
@@ -1871,92 +1871,6 @@ void MacroAssembler::cmpoop(Register src1, jobject src2, Register rscratch) {
}
#endif
-void MacroAssembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
- if ((UseAVX > 0) && (dst != src)) {
- xorpd(dst, dst);
- }
- Assembler::cvtss2sd(dst, src);
-}
-
-void MacroAssembler::cvtss2sd(XMMRegister dst, Address src) {
- if (UseAVX > 0) {
- xorpd(dst, dst);
- }
- Assembler::cvtss2sd(dst, src);
-}
-
-void MacroAssembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
- if ((UseAVX > 0) && (dst != src)) {
- xorps(dst, dst);
- }
- Assembler::cvtsd2ss(dst, src);
-}
-
-void MacroAssembler::cvtsd2ss(XMMRegister dst, Address src) {
- if (UseAVX > 0) {
- xorps(dst, dst);
- }
- Assembler::cvtsd2ss(dst, src);
-}
-
-void MacroAssembler::cvtsi2sdl(XMMRegister dst, Register src) {
- if (UseAVX > 0) {
- xorpd(dst, dst);
- }
- Assembler::cvtsi2sdl(dst, src);
-}
-
-void MacroAssembler::cvtsi2sdl(XMMRegister dst, Address src) {
- if (UseAVX > 0) {
- xorpd(dst, dst);
- }
- Assembler::cvtsi2sdl(dst, src);
-}
-
-void MacroAssembler::cvtsi2ssl(XMMRegister dst, Register src) {
- if (UseAVX > 0) {
- xorps(dst, dst);
- }
- Assembler::cvtsi2ssl(dst, src);
-}
-
-void MacroAssembler::cvtsi2ssl(XMMRegister dst, Address src) {
- if (UseAVX > 0) {
- xorps(dst, dst);
- }
- Assembler::cvtsi2ssl(dst, src);
-}
-
-#ifdef _LP64
-void MacroAssembler::cvtsi2sdq(XMMRegister dst, Register src) {
- if (UseAVX > 0) {
- xorpd(dst, dst);
- }
- Assembler::cvtsi2sdq(dst, src);
-}
-
-void MacroAssembler::cvtsi2sdq(XMMRegister dst, Address src) {
- if (UseAVX > 0) {
- xorpd(dst, dst);
- }
- Assembler::cvtsi2sdq(dst, src);
-}
-
-void MacroAssembler::cvtsi2ssq(XMMRegister dst, Register src) {
- if (UseAVX > 0) {
- xorps(dst, dst);
- }
- Assembler::cvtsi2ssq(dst, src);
-}
-
-void MacroAssembler::cvtsi2ssq(XMMRegister dst, Address src) {
- if (UseAVX > 0) {
- xorps(dst, dst);
- }
- Assembler::cvtsi2ssq(dst, src);
-}
-#endif // _LP64
-
void MacroAssembler::locked_cmpxchgptr(Register reg, AddressLiteral adr, Register rscratch) {
assert(rscratch != noreg || always_reachable(adr), "missing");
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
index ea6a37d16ed..1908703b9bf 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
@@ -800,23 +800,6 @@ class MacroAssembler: public Assembler {
void cmpxchgptr(Register reg, Address adr);
-
- // cvt instructions
- void cvtss2sd(XMMRegister dst, XMMRegister src);
- void cvtss2sd(XMMRegister dst, Address src);
- void cvtsd2ss(XMMRegister dst, XMMRegister src);
- void cvtsd2ss(XMMRegister dst, Address src);
- void cvtsi2sdl(XMMRegister dst, Register src);
- void cvtsi2sdl(XMMRegister dst, Address src);
- void cvtsi2ssl(XMMRegister dst, Register src);
- void cvtsi2ssl(XMMRegister dst, Address src);
-#ifdef _LP64
- void cvtsi2sdq(XMMRegister dst, Register src);
- void cvtsi2sdq(XMMRegister dst, Address src);
- void cvtsi2ssq(XMMRegister dst, Register src);
- void cvtsi2ssq(XMMRegister dst, Address src);
-#endif
-
void locked_cmpxchgptr(Register reg, AddressLiteral adr, Register rscratch = noreg);
void imulptr(Register dst, Register src) { LP64_ONLY(imulq(dst, src)) NOT_LP64(imull(dst, src)); }
diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad
index 759dd8a1d48..80f281a1bf9 100644
--- a/src/hotspot/cpu/x86/x86_64.ad
+++ b/src/hotspot/cpu/x86/x86_64.ad
@@ -10095,7 +10095,7 @@ instruct cmpD_imm(rRegI dst, regD src, immD con, rFlagsReg cr) %{
instruct convF2D_reg_reg(regD dst, regF src)
%{
match(Set dst (ConvF2D src));
- effect(TEMP dst);
+
format %{ "cvtss2sd $dst, $src" %}
ins_encode %{
__ cvtss2sd ($dst$$XMMRegister, $src$$XMMRegister);
@@ -10117,7 +10117,7 @@ instruct convF2D_reg_mem(regD dst, memory src)
instruct convD2F_reg_reg(regF dst, regD src)
%{
match(Set dst (ConvD2F src));
- effect(TEMP dst);
+
format %{ "cvtsd2ss $dst, $src" %}
ins_encode %{
__ cvtsd2ss ($dst$$XMMRegister, $src$$XMMRegister);
diff --git a/test/micro/org/openjdk/bench/vm/compiler/x86/ComputePI.java b/test/micro/org/openjdk/bench/vm/compiler/x86/ComputePI.java
deleted file mode 100644
index 7d8e479172e..00000000000
--- a/test/micro/org/openjdk/bench/vm/compiler/x86/ComputePI.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.
- */
-
-package org.openjdk.bench.vm.compiler;
-
-import org.openjdk.jmh.annotations.Benchmark;
-import org.openjdk.jmh.annotations.BenchmarkMode;
-import org.openjdk.jmh.annotations.Fork;
-import org.openjdk.jmh.annotations.Measurement;
-import org.openjdk.jmh.annotations.Mode;
-import org.openjdk.jmh.annotations.OutputTimeUnit;
-import org.openjdk.jmh.annotations.Scope;
-import org.openjdk.jmh.annotations.Setup;
-import org.openjdk.jmh.annotations.State;
-import org.openjdk.jmh.annotations.Warmup;
-
-import java.util.concurrent.TimeUnit;
-
-@State(Scope.Thread)
-@BenchmarkMode(Mode.AverageTime)
-@OutputTimeUnit(TimeUnit.NANOSECONDS)
-@Warmup(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
-@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
-@Fork(value = 3)
-public class ComputePI {
-
- @Benchmark
- public double compute_pi_int_dbl() {
- double pi = 4.0;
- boolean sign = false;
-
- for (int i = 3; i < 1000; i += 2) {
- if (sign) {
- pi += 4.0 / i;
- } else {
- pi -= 4.0 / i;
- }
- sign = !sign;
- }
- return pi;
- }
-
- @Benchmark
- public double compute_pi_int_flt() {
- float pi = 4.0f;
- boolean sign = false;
-
- for (int i = 3; i < 1000; i += 2) {
- if (sign) {
- pi += 4.0f / i;
- } else {
- pi -= 4.0f / i;
- }
- sign = !sign;
- }
- return pi;
- }
-
- @Benchmark
- public double compute_pi_long_dbl() {
- double pi = 4.0;
- boolean sign = false;
-
- for (long i = 3; i < 1000; i += 2) {
- if (sign) {
- pi += 4.0 / i;
- } else {
- pi -= 4.0 / i;
- }
- sign = !sign;
- }
- return pi;
- }
-
- @Benchmark
- public double compute_pi_long_flt() {
- float pi = 4.0f;
- boolean sign = false;
-
- for (long i = 3; i < 1000; i += 2) {
- if (sign) {
- pi += 4.0f / i;
- } else {
- pi -= 4.0f / i;
- }
- sign = !sign;
- }
- return pi;
- }
-
- @Benchmark
- public double compute_pi_flt_dbl() {
- double pi = 4.0;
- boolean sign = false;
-
- for (float i = 3.0f; i < 1000.0f; i += 2.0f) {
- if (sign) {
- pi += 4.0 / i;
- } else {
- pi -= 4.0 / i;
- }
- sign = !sign;
- }
- return pi;
- }
-
- @Benchmark
- public double compute_pi_dbl_flt() {
- float pi = 4.0f;
- boolean sign = false;
-
- for (float i = 3.0f; i < 1000.0f; i += 2.0f) {
- if (sign) {
- pi += 4.0f / i;
- } else {
- pi -= 4.0f / i;
- }
- sign = !sign;
- }
- return pi;
- }
-}
From 6aace1819c7473db1c9dc6a79a825cc20e7df11d Mon Sep 17 00:00:00 2001
From: David Holmes
Date: Fri, 5 Jan 2024 21:02:40 +0000
Subject: [PATCH 07/66] 8319948: jcmd man page needs to be updated
Reviewed-by: alanb
Backport-of: 028ec7e744f06cd8429b7b74d7b6f7020133aa94
---
src/jdk.jcmd/share/man/jcmd.1 | 302 ++++++++++++++++++++++++----------
1 file changed, 213 insertions(+), 89 deletions(-)
diff --git a/src/jdk.jcmd/share/man/jcmd.1 b/src/jdk.jcmd/share/man/jcmd.1
index 4157cf600e1..422b99adaa5 100644
--- a/src/jdk.jcmd/share/man/jcmd.1
+++ b/src/jdk.jcmd/share/man/jcmd.1
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
+.\" Copyright (c) 2012, 2024, 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
@@ -164,35 +164,38 @@ The following \f[I]options\f[R] must be specified using either
\f[V]-all\f[R]: (Optional) Show help for all commands (BOOLEAN, false) .
.RE
.TP
-\f[V]Compiler.codecache\f[R]
-Prints code cache layout and bounds.
+\f[V]Compiler.CodeHeap_Analytics\f[R] [\f[I]function\f[R]] [\f[I]granularity\f[R]]
+Print CodeHeap analytics
.RS
.PP
-Impact: Low
-.RE
-.TP
-\f[V]Compiler.codelist\f[R]
-Prints all compiled methods in code cache that are alive.
-.RS
+Impact: Low: Depends on code heap size and content.
+Holds CodeCache_lock during analysis step, usually sub-second duration.
.PP
-Impact: Medium
+\f[I]arguments\f[R]:
+.PP
+\f[I]function\f[R]: (Optional) Function to be performed (aggregate,
+UsedSpace, FreeSpace, MethodCount, MethodSpace, MethodAge, MethodNames,
+discard (STRING, all)
+.PP
+\f[I]granularity\f[R]: (Optional) Detail level - smaller value -> more
+detail (INT, 4096)
.RE
.TP
-\f[V]Compiler.perfmap\f[R] (Linux only)
-Write map file for Linux perf tool.
+\f[V]Compiler.codecache\f[R]
+Prints code cache layout and bounds.
.RS
.PP
Impact: Low
.RE
.TP
-\f[V]Compiler.queue\f[R]
-Prints methods queued for compilation.
+\f[V]Compiler.codelist\f[R]
+Prints all compiled methods in code cache that are alive.
.RS
.PP
-Impact: Low
+Impact: Medium
.RE
.TP
-\f[V]Compiler.directives_add *filename* *arguments*\f[R]
+\f[V]Compiler.directives_add\f[R] \f[I]arguments\f[R]
Adds compiler directives from a file.
.RS
.PP
@@ -225,6 +228,38 @@ Remove latest added compiler directive.
Impact: Low
.RE
.TP
+\f[V]Compiler.memory\f[R] [\f[I]options\f[R]]
+Print compilation footprint
+.RS
+.PP
+Impact: Medium: Pause time depends on number of compiled methods
+.PP
+\f[B]Note:\f[R]
+.PP
+The \f[I]options\f[R] must be specified using either \f[I]key\f[R] or
+\f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax.
+.PP
+\f[I]options\f[R]:
+.IP \[bu] 2
+\f[V]-H\f[R]: (Optional) Human readable format (BOOLEAN, false)
+.IP \[bu] 2
+\f[V]-s\f[R]: (Optional) Minimum memory size (MEMORY SIZE, 0)
+.RE
+.TP
+\f[V]Compiler.perfmap\f[R] (Linux only)
+Write map file for Linux perf tool.
+.RS
+.PP
+Impact: Low
+.RE
+.TP
+\f[V]Compiler.queue\f[R]
+Prints methods queued for compilation.
+.RS
+.PP
+Impact: Low
+.RE
+.TP
\f[V]GC.class_histogram\f[R] [\f[I]options\f[R]]
Provides statistics about the Java heap usage.
.RS
@@ -281,6 +316,12 @@ gzipped format using the given compression level.
.IP \[bu] 2
\f[V]-overwrite\f[R]: (Optional) If specified, the dump file will be
overwritten if it exists (BOOLEAN, false)
+.IP \[bu] 2
+\f[V]-parallel\f[R]: (Optional) Number of parallel threads to use for
+heap dump.
+The VM will try to use the specified number of threads, but might use
+fewer.
+(INT, 1)
.PP
\f[I]arguments\f[R]:
.IP \[bu] 2
@@ -344,6 +385,11 @@ If no parameters are entered, the current settings are displayed.
.PP
\f[I]options\f[R]:
.IP \[bu] 2
+\f[V]dumppath\f[R]: (Optional) Path to the location where a recording
+file is written in case the VM runs into a critical error, such as a
+system crash.
+(STRING, The default location is the current directory)
+.IP \[bu] 2
\f[V]globalbuffercount\f[R]: (Optional) Number of global buffers.
This option is a legacy option: change the \f[V]memorysize\f[R]
parameter to alter the number of global buffers.
@@ -641,7 +687,7 @@ Impact: Low
.RE
.TP
\f[V]JVMTI.data_dump\f[R]
-Signals the JVM to do a data-dump request for JVMTI.
+Signal the JVM to do a data-dump request for JVMTI.
.RS
.PP
Impact: High
@@ -757,8 +803,45 @@ Stops the remote management agent.
Impact: Low --- no impact
.RE
.TP
+\f[V]System.dump_map\f[R] [\f[I]options\f[R]] (Linux only)
+Dumps an annotated process memory map to an output file.
+.RS
+.PP
+Impact: Low
+.PP
+\f[B]Note:\f[R]
+.PP
+The following \f[I]options\f[R] must be specified using either
+\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax.
+.PP
+\f[I]options\f[R]:
+.IP \[bu] 2
+\f[V]-H\f[R]: (Optional) Human readable format (BOOLEAN, false)
+.IP \[bu] 2
+\f[V]-F\f[R]: (Optional) File path (STRING,
+\[dq]vm_memory_map_.txt\[dq])
+.RE
+.TP
+\f[V]System.map\f[R] [\f[I]options\f[R]] (Linux only)
+Prints an annotated process memory map of the VM process.
+.RS
+.PP
+Impact: Low
+.PP
+\f[B]Note:\f[R]
+.PP
+The following \f[I]options\f[R] must be specified using either
+\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax.
+.PP
+\f[I]options\f[R]:
+.IP \[bu] 2
+\f[V]-H\f[R]: (Optional) Human readable format (BOOLEAN, false)
+.RE
+.TP
\f[V]System.native_heap_info\f[R] (Linux only)
-Prints information about native heap usage through malloc_info(3).
+Attempts to output information regarding native heap usage through
+malloc_info(3).
+If unsuccessful outputs \[dq]Error: \[dq] and a reason.
.RS
.PP
Impact: Low
@@ -771,6 +854,31 @@ Attempts to free up memory by trimming the C-heap.
Impact: Low
.RE
.TP
+\f[V]Thread.dump_to_file\f[R] [\f[I]options\f[R]] \f[I]filepath\f[R]
+Dump threads, with stack traces, to a file in plain text or JSON format.
+.RS
+.PP
+Impact: Medium: Depends on the number of threads.
+.PP
+\f[B]Note:\f[R]
+.PP
+The following \f[I]options\f[R] must be specified using either
+\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax.
+.PP
+\f[I]options\f[R]:
+.IP \[bu] 2
+\f[V]-overwrite\f[R]: (Optional) May overwrite existing file (BOOLEAN,
+false)
+.IP \[bu] 2
+\f[V]-format\f[R]: (Optional) Output format (\[dq]plain\[dq] or
+\[dq]json\[dq]) (STRING, plain)
+.PP
+\f[I]arguments\f[R]:
+.IP \[bu] 2
+\f[V]filepath\f[R]: The file path to the output file (STRING, no default
+value)
+.RE
+.TP
\f[V]Thread.print\f[R] [\f[I]options\f[R]]
Prints all threads with stacktraces.
.RS
@@ -792,7 +900,7 @@ false)
.RE
.TP
\f[V]VM.cds\f[R] [\f[I]arguments\f[R]]
-Dumps a static or dynamic shared archive that includes all currently
+Dump a static or dynamic shared archive that includes all currently
loaded classes.
.RS
.PP
@@ -818,78 +926,98 @@ If \f[V]dynamic_dump\f[R] is specified, the target JVM must be started
with the JVM option \f[V]-XX:+RecordDynamicDumpInfo\f[R].
.RE
.TP
-\f[V]VM.classloaders\f[R] [\f[I]options\f[R]]
-Prints classloader hierarchy.
+\f[V]VM.class_hierarchy\f[R] [\f[I]options\f[R]] [\f[I]arguments\f[R]]
+Print a list of all loaded classes, indented to show the class
+hierarchy.
+The name of each class is followed by the ClassLoaderData* of its
+ClassLoader, or \[dq]null\[dq] if it is loaded by the bootstrap class
+loader.
.RS
.PP
-Impact: Medium --- Depends on number of class loaders and classes
-loaded.
+Impact: Medium --- depends on the number of loaded classes.
+.PP
+\f[B]Note:\f[R]
.PP
The following \f[I]options\f[R] must be specified using either
\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax.
.PP
\f[I]options\f[R]:
.IP \[bu] 2
-\f[V]show-classes\f[R]: (Optional) Print loaded classes.
+\f[V]-i\f[R]: (Optional) Inherited interfaces should be printed.
(BOOLEAN, false)
.IP \[bu] 2
-\f[V]verbose\f[R]: (Optional) Print detailed information.
+\f[V]-s\f[R]: (Optional) If a classname is specified, print its
+subclasses in addition to its superclasses.
+Without this option only the superclasses will be printed.
(BOOLEAN, false)
+.PP
+\f[I]arguments\f[R]:
.IP \[bu] 2
-\f[V]fold\f[R]: (Optional) Show loaders of the same name and class as
-one.
-(BOOLEAN, true)
+\f[I]classname\f[R]: (Optional) The name of the class whose hierarchy
+should be printed.
+If not specified, all class hierarchies are printed.
+(STRING, no default value)
+.RE
+.TP
+\f[V]VM.classes\f[R] [\f[I]options\f[R]]
+Print all loaded classes
+.RS
+.PP
+Impact: Medium: Depends on number of loaded classes.
+.PP
+The following \f[I]options\f[R] must be specified using either
+\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax.
+.PP
+\f[I]options\f[R]:
+.IP \[bu] 2
+\f[V]-verbose\f[R]: (Optional) Dump the detailed content of a Java
+class.
+Some classes are annotated with flags: \f[V]F\f[R] = has, or inherits, a
+non-empty finalize method, \f[V]f\f[R] = has final method, \f[V]W\f[R] =
+methods rewritten, \f[V]C\f[R] = marked with \f[V]\[at]Contended\f[R]
+annotation, \f[V]R\f[R] = has been redefined, \f[V]S\f[R] = is shared
+class (BOOLEAN, false)
.RE
.TP
\f[V]VM.classloader_stats\f[R]
-Prints statistics about all ClassLoaders.
+Print statistics about all ClassLoaders.
.RS
.PP
Impact: Low
.RE
.TP
-\f[V]VM.class_hierarchy\f[R] [\f[I]options\f[R]] [\f[I]arguments\f[R]]
-Prints a list of all loaded classes, indented to show the class
-hierarchy.
-The name of each class is followed by the ClassLoaderData* of its
-ClassLoader, or \[dq]null\[dq] if it is loaded by the bootstrap class
-loader.
+\f[V]VM.classloaders\f[R] [\f[I]options\f[R]]
+Prints classloader hierarchy.
.RS
.PP
-Impact: Medium --- depends on the number of loaded classes.
-.PP
-\f[B]Note:\f[R]
+Impact: Medium --- Depends on number of class loaders and classes
+loaded.
.PP
The following \f[I]options\f[R] must be specified using either
\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax.
.PP
\f[I]options\f[R]:
.IP \[bu] 2
-\f[V]-i\f[R]: (Optional) Inherited interfaces should be printed.
+\f[V]show-classes\f[R]: (Optional) Print loaded classes.
(BOOLEAN, false)
.IP \[bu] 2
-\f[V]-s\f[R]: (Optional) If a classname is specified, print its
-subclasses in addition to its superclasses.
-Without this option only the superclasses will be printed.
+\f[V]verbose\f[R]: (Optional) Print detailed information.
(BOOLEAN, false)
-.PP
-\f[I]arguments\f[R]:
.IP \[bu] 2
-\f[I]classname\f[R]: (Optional) The name of the class whose hierarchy
-should be printed.
-If not specified, all class hierarchies are printed.
-(STRING, no default value)
+\f[V]fold\f[R]: (Optional) Show loaders of the same name and class as
+one.
+(BOOLEAN, true)
.RE
.TP
\f[V]VM.command_line\f[R]
-Prints the command line used to start this VM instance.
+Print the command line used to start this VM instance.
.RS
.PP
Impact: Low
.RE
.TP
\f[V]VM.dynlibs\f[R]
-Prints the loaded dynamic libraries.
+Print loaded dynamic libraries.
.RS
.PP
Impact: Low
@@ -918,8 +1046,25 @@ If omitted, all events are printed.
(STRING, no default value)
.RE
.TP
+\f[V]VM.flags\f[R] [\f[I]options\f[R]]
+Print the VM flag options and their current values.
+.RS
+.PP
+Impact: Low
+.PP
+\f[B]Note:\f[R]
+.PP
+The following \f[I]options\f[R] must be specified using either
+\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax.
+.PP
+\f[I]options\f[R]:
+.IP \[bu] 2
+\f[V]-all\f[R]: (Optional) Prints all flags supported by the VM
+(BOOLEAN, false).
+.RE
+.TP
\f[V]VM.info\f[R]
-Prints information about the JVM environment and status.
+Print information about the JVM environment and status.
.RS
.PP
Impact: Low
@@ -964,23 +1109,6 @@ configuration.
(BOOLEAN, no default value)
.RE
.TP
-\f[V]VM.flags\f[R] [\f[I]options\f[R]]
-Prints the VM flag options and their current values.
-.RS
-.PP
-Impact: Low
-.PP
-\f[B]Note:\f[R]
-.PP
-The following \f[I]options\f[R] must be specified using either
-\f[I]key\f[R] or \f[I]key\f[R]\f[V]=\f[R]\f[I]value\f[R] syntax.
-.PP
-\f[I]options\f[R]:
-.IP \[bu] 2
-\f[V]-all\f[R]: (Optional) Prints all flags supported by the VM
-(BOOLEAN, false).
-.RE
-.TP
\f[V]VM.metaspace\f[R] [\f[I]options\f[R]]
Prints the statistics for the metaspace
.RS
@@ -1015,6 +1143,10 @@ classes for each loader.
space.
(BOOLEAN, false)
.IP \[bu] 2
+\f[V]chunkfreelist\f[R]: (Optional) Shows details about global chunk
+free lists (ChunkManager).
+(BOOLEAN, false)
+.IP \[bu] 2
\f[V]scale\f[R]: (Optional) Memory usage in which to scale.
Valid values are: 1, KB, MB or GB (fixed scale) or \[dq]dynamic\[dq] for
a dynamically chosen scale.
@@ -1022,7 +1154,7 @@ a dynamically chosen scale.
.RE
.TP
\f[V]VM.native_memory\f[R] [\f[I]options\f[R]]
-Prints native memory usage
+Print native memory usage
.RS
.PP
Impact: Medium
@@ -1064,16 +1196,8 @@ purpose.
(STRING, KB)
.RE
.TP
-\f[V]VM.print_touched_methods\f[R]
-Prints all methods that have ever been touched during the lifetime of
-this JVM.
-.RS
-.PP
-Impact: Medium --- depends on Java content.
-.RE
-.TP
\f[V]VM.set_flag\f[R] [\f[I]arguments\f[R]]
-Sets the VM flag option by using the provided value.
+Sets VM flag option using the provided value.
.RS
.PP
Impact: Low
@@ -1088,7 +1212,7 @@ no default value)
.RE
.TP
\f[V]VM.stringtable\f[R] [\f[I]options\f[R]]
-Dumps the string table.
+Dump string table.
.RS
.PP
Impact: Medium --- depends on the Java content.
@@ -1105,7 +1229,7 @@ table (BOOLEAN, false)
.RE
.TP
\f[V]VM.symboltable\f[R] [\f[I]options\f[R]]
-Dumps the symbol table.
+Dump symbol table.
.RS
.PP
Impact: Medium --- depends on the Java content.
@@ -1121,6 +1245,13 @@ The following \f[I]options\f[R] must be specified using either
table (BOOLEAN, false)
.RE
.TP
+\f[V]VM.system_properties\f[R]
+Print system properties.
+.RS
+.PP
+Impact: Low
+.RE
+.TP
\f[V]VM.systemdictionary\f[R]
Prints the statistics for dictionary hashtable sizes and bucket length.
.RS
@@ -1138,15 +1269,8 @@ The following \f[I]options\f[R] must be specified using either
for all class loaders (BOOLEAN, false) .
.RE
.TP
-\f[V]VM.system_properties\f[R]
-Prints the system properties.
-.RS
-.PP
-Impact: Low
-.RE
-.TP
\f[V]VM.uptime\f[R] [\f[I]options\f[R]]
-Prints the VM uptime.
+Print VM uptime.
.RS
.PP
Impact: Low
@@ -1163,7 +1287,7 @@ The following \f[I]options\f[R] must be specified using either
.RE
.TP
\f[V]VM.version\f[R]
-Prints JVM version information.
+Print JVM version information.
.RS
.PP
Impact: Low
From 0442d772b0eb253aebf8638eb966957ab2b694c2 Mon Sep 17 00:00:00 2001
From: Tobias Hartmann
Date: Mon, 8 Jan 2024 11:36:26 +0000
Subject: [PATCH 08/66] 8310844: [AArch64] C1 compilation fails because monitor
offset in OSR buffer is too large for immediate
Reviewed-by: chagedorn
Backport-of: ade21a965f8a5fc889cd48bba76fad507bdeddf5
---
.../cpu/aarch64/c1_LIRAssembler_aarch64.cpp | 5 +-
.../compiler/c1/TestLargeMonitorOffset.java | 146 ++++++++++++++++++
2 files changed, 149 insertions(+), 2 deletions(-)
create mode 100644 test/hotspot/jtreg/compiler/c1/TestLargeMonitorOffset.java
diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
index 360ef7a747a..b83d6185062 100644
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -282,7 +282,8 @@ void LIR_Assembler::osr_entry() {
__ bind(L);
}
#endif
- __ ldp(r19, r20, Address(OSR_buf, slot_offset));
+ __ ldr(r19, Address(OSR_buf, slot_offset));
+ __ ldr(r20, Address(OSR_buf, slot_offset + BytesPerWord));
__ str(r19, frame_map()->address_for_monitor_lock(i));
__ str(r20, frame_map()->address_for_monitor_object(i));
}
diff --git a/test/hotspot/jtreg/compiler/c1/TestLargeMonitorOffset.java b/test/hotspot/jtreg/compiler/c1/TestLargeMonitorOffset.java
new file mode 100644
index 00000000000..d5cdb6bee52
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/c1/TestLargeMonitorOffset.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2024, 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 8310844
+ * @summary Verify that monitors with large offset in the OSR buffer are handled properly.
+ * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,TestLargeMonitorOffset::* TestLargeMonitorOffset
+ */
+
+public class TestLargeMonitorOffset {
+
+ public static void test() {
+ long l1, l2, l3, l4, l5, l6, l7, l8, l9, l10,
+ l11, l12, l13, l14, l15, l16, l17, l18, l19, l20,
+ l21, l22, l23, l24, l25, l26, l27, l28, l29, l30,
+ l31, l32, l33, l34, l35, l36, l37, l38, l39, l40,
+ l41, l42, l43, l44, l45, l46, l47, l48, l49, l50,
+ l51, l52, l53, l54, l55, l56, l57, l58, l59, l60,
+ l61, l62, l63, l64, l65, l66, l67, l68, l69, l70,
+ l71, l72, l73, l74, l75, l76, l77, l78, l79, l80,
+ l81, l82, l83, l84, l85, l86, l87, l88, l89, l90,
+ l91, l92, l93, l94, l95, l96, l97, l98, l99, l100,
+ l101, l102, l103, l104, l105, l106, l107, l108, l109, l110,
+ l111, l112, l113, l114, l115, l116, l117, l118, l119, l120,
+ l121, l122, l123, l124, l125, l126, l127, l128, l129, l130,
+ l131, l132, l133, l134, l135, l136, l137, l138, l139, l140,
+ l141, l142, l143, l144, l145, l146, l147, l148, l149, l150,
+ l151, l152, l153, l154, l155, l156, l157, l158, l159, l160,
+ l161, l162, l163, l164, l165, l166, l167, l168, l169, l170,
+ l171, l172, l173, l174, l175, l176, l177, l178, l179, l180,
+ l181, l182, l183, l184, l185, l186, l187, l188, l189, l190,
+ l191, l192, l193, l194, l195, l196, l197, l198, l199, l200,
+ l201, l202, l203, l204, l205, l206, l207, l208, l209, l210,
+ l211, l212, l213, l214, l215, l216, l217, l218, l219, l220,
+ l221, l222, l223, l224, l225, l226, l227, l228, l229, l230,
+ l231, l232, l233, l234, l235, l236, l237, l238, l239, l240,
+ l241, l242, l243, l244, l245, l246, l247, l248, l249, l250,
+ l251, l252, l253, l254, l255, l256, l257, l258, l259, l260,
+ l261, l262, l263, l264, l265, l266, l267, l268, l269, l270,
+ l271, l272, l273, l274, l275, l276, l277, l278, l279, l280,
+ l281, l282, l283, l284, l285, l286, l287, l288, l289, l290,
+ l291, l292, l293, l294, l295, l296, l297, l298, l299, l300,
+ l301, l302, l303, l304, l305, l306, l307, l308, l309, l310,
+ l311, l312, l313, l314, l315, l316, l317, l318, l319, l320,
+ l321, l322, l323, l324, l325, l326, l327, l328, l329, l330,
+ l331, l332, l333, l334, l335, l336, l337, l338, l339, l340,
+ l341, l342, l343, l344, l345, l346, l347, l348, l349, l350,
+ l351, l352, l353, l354, l355, l356, l357, l358, l359, l360,
+ l361, l362, l363, l364, l365, l366, l367, l368, l369, l370,
+ l371, l372, l373, l374, l375, l376, l377, l378, l379, l380,
+ l381, l382, l383, l384, l385, l386, l387, l388, l389, l390,
+ l391, l392, l393, l394, l395, l396, l397, l398, l399, l400,
+ l401, l402, l403, l404, l405, l406, l407, l408, l409, l410,
+ l411, l412, l413, l414, l415, l416, l417, l418, l419, l420,
+ l421, l422, l423, l424, l425, l426, l427, l428, l429, l430,
+ l431, l432, l433, l434, l435, l436, l437, l438, l439, l440,
+ l441, l442, l443, l444, l445, l446, l447, l448, l449, l450,
+ l451, l452, l453, l454, l455, l456, l457, l458, l459, l460,
+ l461, l462, l463, l464, l465, l466, l467, l468, l469, l470,
+ l471, l472, l473, l474, l475, l476, l477, l478, l479, l480,
+ l481, l482, l483, l484, l485, l486, l487, l488, l489, l490,
+ l491, l492, l493, l494, l495, l496, l497, l498, l499, l500,
+ l501, l502, l503, l504, l505, l506, l507, l508, l509, l510,
+ l511, l512, l513, l514, l515, l516, l517, l518, l519, l520,
+ l521, l522, l523, l524, l525, l526, l527, l528, l529, l530,
+ l531, l532, l533, l534, l535, l536, l537, l538, l539, l540,
+ l541, l542, l543, l544, l545, l546, l547, l548, l549, l550,
+ l551, l552, l553, l554, l555, l556, l557, l558, l559, l560,
+ l561, l562, l563, l564, l565, l566, l567, l568, l569, l570,
+ l571, l572, l573, l574, l575, l576, l577, l578, l579, l580,
+ l581, l582, l583, l584, l585, l586, l587, l588, l589, l590,
+ l591, l592, l593, l594, l595, l596, l597, l598, l599, l600,
+ l601, l602, l603, l604, l605, l606, l607, l608, l609, l610,
+ l611, l612, l613, l614, l615, l616, l617, l618, l619, l620,
+ l621, l622, l623, l624, l625, l626, l627, l628, l629, l630,
+ l631, l632, l633, l634, l635, l636, l637, l638, l639, l640,
+ l641, l642, l643, l644, l645, l646, l647, l648, l649, l650,
+ l651, l652, l653, l654, l655, l656, l657, l658, l659, l660,
+ l661, l662, l663, l664, l665, l666, l667, l668, l669, l670,
+ l671, l672, l673, l674, l675, l676, l677, l678, l679, l680,
+ l681, l682, l683, l684, l685, l686, l687, l688, l689, l690,
+ l691, l692, l693, l694, l695, l696, l697, l698, l699, l700,
+ l701, l702, l703, l704, l705, l706, l707, l708, l709, l710,
+ l711, l712, l713, l714, l715, l716, l717, l718, l719, l720,
+ l721, l722, l723, l724, l725, l726, l727, l728, l729, l730,
+ l731, l732, l733, l734, l735, l736, l737, l738, l739, l740,
+ l741, l742, l743, l744, l745, l746, l747, l748, l749, l750,
+ l751, l752, l753, l754, l755, l756, l757, l758, l759, l760,
+ l761, l762, l763, l764, l765, l766, l767, l768, l769, l770,
+ l771, l772, l773, l774, l775, l776, l777, l778, l779, l780,
+ l781, l782, l783, l784, l785, l786, l787, l788, l789, l790,
+ l791, l792, l793, l794, l795, l796, l797, l798, l799, l800,
+ l801, l802, l803, l804, l805, l806, l807, l808, l809, l810,
+ l811, l812, l813, l814, l815, l816, l817, l818, l819, l820,
+ l821, l822, l823, l824, l825, l826, l827, l828, l829, l830,
+ l831, l832, l833, l834, l835, l836, l837, l838, l839, l840,
+ l841, l842, l843, l844, l845, l846, l847, l848, l849, l850,
+ l851, l852, l853, l854, l855, l856, l857, l858, l859, l860,
+ l861, l862, l863, l864, l865, l866, l867, l868, l869, l870,
+ l871, l872, l873, l874, l875, l876, l877, l878, l879, l880,
+ l881, l882, l883, l884, l885, l886, l887, l888, l889, l890,
+ l891, l892, l893, l894, l895, l896, l897, l898, l899, l900,
+ l901, l902, l903, l904, l905, l906, l907, l908, l909, l910,
+ l911, l912, l913, l914, l915, l916, l917, l918, l919, l920,
+ l921, l922, l923, l924, l925, l926, l927, l928, l929, l930,
+ l931, l932, l933, l934, l935, l936, l937, l938, l939, l940,
+ l941, l942, l943, l944, l945, l946, l947, l948, l949, l950,
+ l951, l952, l953, l954, l955, l956, l957, l958, l959, l960,
+ l961, l962, l963, l964, l965, l966, l967, l968, l969, l970,
+ l971, l972, l973, l974, l975, l976, l977, l978, l979, l980,
+ l981, l982, l983, l984, l985, l986, l987, l988, l989, l990,
+ l991, l992, l993, l994, l995, l996, l997, l998, l999, l1000;
+
+ synchronized (TestLargeMonitorOffset.class) {
+ // Trigger OSR compilation with monitor in the OSR buffer
+ for (int i = 0; i < 1_000_000; ++i) {
+
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ test();
+ }
+}
From f27efd6a299dd4c2c6445f71aa0fe9739b597591 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?=
Date: Mon, 8 Jan 2024 12:46:32 +0000
Subject: [PATCH 09/66] 8322489: 22-b27: Up to 7% regression in all
Footprint3-*-G1/ZGC
Reviewed-by: egahlin
Backport-of: 09c6c4ff021b7dc719c0b1e0dfb041b03bba1b5d
---
src/hotspot/share/jfr/jfr.cpp | 4 +++-
.../checkpoint/jfrCheckpointManager.cpp | 8 +++----
.../checkpoint/jfrCheckpointWriter.hpp | 1 +
.../share/jfr/recorder/jfrRecorder.cpp | 24 +++++++++++++------
.../share/jfr/recorder/jfrRecorder.hpp | 1 +
.../jfr/support/jfrDeprecationManager.cpp | 4 +++-
6 files changed, 29 insertions(+), 13 deletions(-)
diff --git a/src/hotspot/share/jfr/jfr.cpp b/src/hotspot/share/jfr/jfr.cpp
index 45848fb0243..03b47bcd21d 100644
--- a/src/hotspot/share/jfr/jfr.cpp
+++ b/src/hotspot/share/jfr/jfr.cpp
@@ -67,7 +67,9 @@ void Jfr::on_create_vm_3() {
}
void Jfr::on_unloading_classes() {
- JfrCheckpointManager::on_unloading_classes();
+ if (JfrRecorder::is_created() || JfrRecorder::is_started_on_commandline()) {
+ JfrCheckpointManager::on_unloading_classes();
+ }
}
bool Jfr::is_excluded(Thread* t) {
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
index 799d6ef899d..0aed916702e 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
@@ -117,16 +117,16 @@ bool JfrCheckpointManager::initialize_early() {
assert(_thread_local_mspace == nullptr, "invariant");
_thread_local_mspace = new JfrThreadLocalCheckpointMspace();
if (_thread_local_mspace == nullptr || !_thread_local_mspace->initialize(thread_local_buffer_size,
- thread_local_buffer_prealloc_count,
- thread_local_buffer_prealloc_count)) {
+ thread_local_buffer_prealloc_count,
+ thread_local_buffer_prealloc_count)) {
return false;
}
assert(_virtual_thread_local_mspace == nullptr, "invariant");
_virtual_thread_local_mspace = new JfrThreadLocalCheckpointMspace();
if (_virtual_thread_local_mspace == nullptr || !_virtual_thread_local_mspace->initialize(virtual_thread_local_buffer_size,
- JFR_MSPACE_UNLIMITED_CACHE_SIZE,
- virtual_thread_local_buffer_prealloc_count)) {
+ JFR_MSPACE_UNLIMITED_CACHE_SIZE,
+ virtual_thread_local_buffer_prealloc_count)) {
return false;
}
return true;
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp
index f99159b3a51..a8ec2fd70f5 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp
@@ -55,6 +55,7 @@ struct JfrCheckpointContext {
class JfrCheckpointWriter : public JfrCheckpointWriterBase {
friend class JfrCheckpointManager;
+ friend class JfrDeprecationManager;
friend class JfrSerializerRegistration;
friend class JfrTypeManager;
private:
diff --git a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp
index 40c3d7a8c4f..cc460f8c2aa 100644
--- a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp
+++ b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp
@@ -86,9 +86,6 @@ bool JfrRecorder::create_oop_storages() {
return ObjectSampler::create_oop_storage();
}
-// Subsystem
-static JfrCheckpointManager* _checkpoint_manager = nullptr;
-
bool JfrRecorder::on_create_vm_1() {
if (!is_disabled()) {
if (FlightRecorder || is_started_on_commandline()) {
@@ -99,9 +96,10 @@ bool JfrRecorder::on_create_vm_1() {
return false;
}
- _checkpoint_manager = JfrCheckpointManager::create();
- if (_checkpoint_manager == nullptr || !_checkpoint_manager->initialize_early()) {
- return false;
+ if (is_started_on_commandline()) {
+ if (!create_checkpoint_manager()) {
+ return false;
+ }
}
// fast time initialization
@@ -292,7 +290,7 @@ bool JfrRecorder::create_components() {
if (!create_storage()) {
return false;
}
- if (!create_checkpoint_manager()) {
+ if (!initialize_checkpoint_manager()) {
return false;
}
if (!create_stacktrace_repository()) {
@@ -321,6 +319,7 @@ static JfrStackTraceRepository* _stack_trace_repository;
static JfrStringPool* _stringpool = nullptr;
static JfrOSInterface* _os_interface = nullptr;
static JfrThreadSampling* _thread_sampling = nullptr;
+static JfrCheckpointManager* _checkpoint_manager = nullptr;
bool JfrRecorder::create_java_event_writer() {
return JfrJavaEventWriter::initialize();
@@ -357,6 +356,17 @@ bool JfrRecorder::create_storage() {
}
bool JfrRecorder::create_checkpoint_manager() {
+ assert(_checkpoint_manager == nullptr, "invariant");
+ _checkpoint_manager = JfrCheckpointManager::create();
+ return _checkpoint_manager != nullptr && _checkpoint_manager->initialize_early();
+}
+
+bool JfrRecorder::initialize_checkpoint_manager() {
+ if (_checkpoint_manager == nullptr) {
+ if (!create_checkpoint_manager()) {
+ return false;
+ }
+ }
assert(_checkpoint_manager != nullptr, "invariant");
assert(_repository != nullptr, "invariant");
return _checkpoint_manager->initialize(&_repository->chunkwriter());
diff --git a/src/hotspot/share/jfr/recorder/jfrRecorder.hpp b/src/hotspot/share/jfr/recorder/jfrRecorder.hpp
index 3e2541fad98..9f4969b0187 100644
--- a/src/hotspot/share/jfr/recorder/jfrRecorder.hpp
+++ b/src/hotspot/share/jfr/recorder/jfrRecorder.hpp
@@ -42,6 +42,7 @@ class JfrRecorder : public JfrCHeapObj {
static bool on_create_vm_2();
static bool on_create_vm_3();
static bool create_checkpoint_manager();
+ static bool initialize_checkpoint_manager();
static bool create_chunk_repository();
static bool create_java_event_writer();
static bool create_jvmti_agent();
diff --git a/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp b/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp
index a36b85dbb7e..5f5c87d239c 100644
--- a/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp
+++ b/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp
@@ -371,8 +371,10 @@ void JfrDeprecationManager::write_edges(JfrChunkWriter& cw, Thread* thread, bool
void JfrDeprecationManager::on_type_set(JfrCheckpointWriter& writer, JfrChunkWriter* cw, Thread* thread) {
assert(_pending_list.is_empty(), "invariant");
- if (writer.has_data() && _pending_head != nullptr) {
+ if (_pending_head != nullptr) {
save_type_set_blob(writer);
+ } else {
+ writer.cancel();
}
if (cw != nullptr) {
write_edges(*cw, thread);
From 2110300246da2c36e1abbf6e33d05c318af1f9ae Mon Sep 17 00:00:00 2001
From: Erik Gahlin
Date: Mon, 8 Jan 2024 12:58:58 +0000
Subject: [PATCH 10/66] 8322142: JFR: Periodic tasks aren't orphaned between
recordings
Reviewed-by: mgronlun
Backport-of: 1551928502c8ed96350e7b4f1316ea35587407fe
---
.../jdk/jfr/internal/periodic/BatchManager.java | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/BatchManager.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/BatchManager.java
index 141cf1a932b..8d51cb1de6f 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/BatchManager.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/periodic/BatchManager.java
@@ -63,11 +63,7 @@ private void groupTasksIntoBatches(List tasks) {
}
for (PeriodicTask task : activeSortedTasks(tasks)) {
if (task.isSchedulable()) {
- Batch batch = task.getBatch();
- // If new task, or period has changed, find new batch
- if (batch == null) {
- batch = findBatch(task.getPeriod());
- }
+ Batch batch = findBatch(task.getPeriod(), task.getBatch());
batch.add(task);
}
}
@@ -89,7 +85,7 @@ private List activeSortedTasks(List unsorted) {
return tasks;
}
- private Batch findBatch(long period) {
+ private Batch findBatch(long period, Batch oldBatch) {
// All events with a period less than 1000 ms
// get their own unique batch. The rationale for
// this is to avoid a scenario where a user (mistakenly) specifies
@@ -102,7 +98,7 @@ private Batch findBatch(long period) {
return batch;
}
}
- Batch batch = new Batch(period);
+ Batch batch = oldBatch != null ? oldBatch : new Batch(period);
batches.add(batch);
return batch;
}
From 29ed3878cc51fadccc0023795e056195d108a9a2 Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Mon, 8 Jan 2024 14:02:57 +0000
Subject: [PATCH 11/66] 8322532: JShell : Unnamed variable issue
Reviewed-by: asotona
Backport-of: f0cfd361bd6a98dc1192dab2116fdd3904f130f8
---
.../share/classes/jdk/jshell/CompletenessAnalyzer.java | 2 +-
test/langtools/jdk/jshell/VariablesTest.java | 8 +++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java b/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java
index 1579a48786c..663ca164a3d 100644
--- a/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java
+++ b/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java
@@ -190,7 +190,7 @@ static enum TK {
EOF(TokenKind.EOF, 0), //
ERROR(TokenKind.ERROR, XERRO), //
IDENTIFIER(TokenKind.IDENTIFIER, XEXPR1|XDECL1|XTERM), //
- UNDERSCORE(TokenKind.UNDERSCORE, XDECL1), // _
+ UNDERSCORE(TokenKind.UNDERSCORE, XDECL1|XEXPR), // _
CLASS(TokenKind.CLASS, XEXPR|XDECL1|XBRACESNEEDED), // class decl (MAPPED: DOTCLASS)
MONKEYS_AT(TokenKind.MONKEYS_AT, XEXPR|XDECL1), // @
IMPORT(TokenKind.IMPORT, XDECL1|XSTART), // import -- consider declaration
diff --git a/test/langtools/jdk/jshell/VariablesTest.java b/test/langtools/jdk/jshell/VariablesTest.java
index 51ccbd17d60..56546955e08 100644
--- a/test/langtools/jdk/jshell/VariablesTest.java
+++ b/test/langtools/jdk/jshell/VariablesTest.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8144903 8177466 8191842 8211694 8213725 8239536 8257236 8252409 8294431
+ * @bug 8144903 8177466 8191842 8211694 8213725 8239536 8257236 8252409 8294431 8322532
* @summary Tests for EvaluationState.variables
* @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api
@@ -621,4 +621,10 @@ public void varAnonymousClassAndStaticField() { //JDK-8294431
assertEval("var obj = new Object() { public static final String msg = \"hello\"; };");
}
+ public void underscoreAsLambdaParameter() { //JDK-8322532
+ assertAnalyze("Func f = _ -> 0; int i;",
+ "Func f = _ -> 0;",
+ " int i;", true);
+ }
+
}
From e5f3366efacff124b895ead742d1d0200589a59e Mon Sep 17 00:00:00 2001
From: Goetz Lindenmaier
Date: Tue, 9 Jan 2024 11:21:19 +0000
Subject: [PATCH 12/66] 8322418: Problem list
gc/TestAllocHumongousFragment.java subtests for 8298781
Reviewed-by: clanger
Backport-of: 6de23bf36e125c77f6f17235d81a33ff25b942fe
---
test/hotspot/jtreg/ProblemList.txt | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt
index 01634e28062..e3e0d785d23 100644
--- a/test/hotspot/jtreg/ProblemList.txt
+++ b/test/hotspot/jtreg/ProblemList.txt
@@ -85,6 +85,11 @@ gc/epsilon/TestMemoryMXBeans.java 8206434 generic-all
gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java 8156755 generic-all
gc/g1/logging/TestG1LoggingFailure.java 8169634 generic-all
gc/g1/humongousObjects/TestHeapCounters.java 8178918 generic-all
+gc/TestAllocHumongousFragment.java#adaptive 8298781 generic-all
+gc/TestAllocHumongousFragment.java#aggressive 8298781 generic-all
+gc/TestAllocHumongousFragment.java#iu-aggressive 8298781 generic-all
+gc/TestAllocHumongousFragment.java#g1 8298781 generic-all
+gc/TestAllocHumongousFragment.java#static 8298781 generic-all
gc/stress/gclocker/TestExcessGCLockerCollections.java 8229120 generic-all
gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all
gc/stress/gclocker/TestGCLockerWithSerial.java 8180622 generic-all
From acc4829ec39b3a7dacd3e2a872ba3becd89b175e Mon Sep 17 00:00:00 2001
From: Dan Lutker
Date: Tue, 9 Jan 2024 17:53:56 +0000
Subject: [PATCH 13/66] 8322725: (tz) Update Timezone Data to 2023d
Reviewed-by: naoto, iris
Backport-of: 2a9c3589d941d9a57e536ea0b3d7919c6ddb82dc
---
src/java.base/share/data/tzdata/VERSION | 2 +-
src/java.base/share/data/tzdata/africa | 7 ---
src/java.base/share/data/tzdata/antarctica | 57 ++++++++++++++++++-
src/java.base/share/data/tzdata/asia | 6 +-
src/java.base/share/data/tzdata/australasia | 8 ++-
src/java.base/share/data/tzdata/backward | 1 -
src/java.base/share/data/tzdata/europe | 29 +++++++---
src/java.base/share/data/tzdata/iso3166.tab | 17 ++++--
src/java.base/share/data/tzdata/leapseconds | 8 +--
src/java.base/share/data/tzdata/northamerica | 3 +-
src/java.base/share/data/tzdata/southamerica | 6 ++
src/java.base/share/data/tzdata/zone.tab | 24 ++++----
.../java/util/TimeZone/TimeZoneData/VERSION | 2 +-
.../util/TimeZone/TimeZoneData/aliases.txt | 1 -
14 files changed, 125 insertions(+), 46 deletions(-)
diff --git a/src/java.base/share/data/tzdata/VERSION b/src/java.base/share/data/tzdata/VERSION
index 66bd061e8bc..560884d1a82 100644
--- a/src/java.base/share/data/tzdata/VERSION
+++ b/src/java.base/share/data/tzdata/VERSION
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2023c
+tzdata2023d
diff --git a/src/java.base/share/data/tzdata/africa b/src/java.base/share/data/tzdata/africa
index a73405fdb01..b4789b16c71 100644
--- a/src/java.base/share/data/tzdata/africa
+++ b/src/java.base/share/data/tzdata/africa
@@ -308,13 +308,6 @@ Rule Egypt 2007 only - Sep Thu>=1 24:00 0 -
# reproduced by other (more accessible) sites[, e.g.,]...
# http://elgornal.net/news/news.aspx?id=4699258
-# From Paul Eggert (2014-06-04):
-# Sarah El Deeb and Lee Keath of AP report that the Egyptian government says
-# the change is because of blackouts in Cairo, even though Ahram Online (cited
-# above) says DST had no affect on electricity consumption. There is
-# no information about when DST will end this fall. See:
-# http://abcnews.go.com/International/wireStory/el-sissi-pushes-egyptians-line-23614833
-
# From Steffen Thorsen (2015-04-08):
# Egypt will start DST on midnight after Thursday, April 30, 2015.
# This is based on a law (no 35) from May 15, 2014 saying it starts the last
diff --git a/src/java.base/share/data/tzdata/antarctica b/src/java.base/share/data/tzdata/antarctica
index 3de5e726eb4..fc7176cd0d5 100644
--- a/src/java.base/share/data/tzdata/antarctica
+++ b/src/java.base/share/data/tzdata/antarctica
@@ -103,6 +103,11 @@
# - 2018 Oct 7 4:00 - 2019 Mar 17 3:00 - 2019 Oct 4 3:00 - 2020 Mar 8 3:00
# and now - 2020 Oct 4 0:01
+# From Paul Eggert (2023-12-20):
+# Transitions from 2021 on are taken from:
+# https://www.timeanddate.com/time/zone/antarctica/casey
+# retrieved at various dates.
+
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Antarctica/Casey 0 - -00 1969
8:00 - +08 2009 Oct 18 2:00
@@ -116,7 +121,12 @@ Zone Antarctica/Casey 0 - -00 1969
8:00 - +08 2019 Oct 4 3:00
11:00 - +11 2020 Mar 8 3:00
8:00 - +08 2020 Oct 4 0:01
- 11:00 - +11
+ 11:00 - +11 2021 Mar 14 0:00
+ 8:00 - +08 2021 Oct 3 0:01
+ 11:00 - +11 2022 Mar 13 0:00
+ 8:00 - +08 2022 Oct 2 0:01
+ 11:00 - +11 2023 Mar 9 3:00
+ 8:00 - +08
Zone Antarctica/Davis 0 - -00 1957 Jan 13
7:00 - +07 1964 Nov
0 - -00 1969 Feb
@@ -263,7 +273,50 @@ Zone Antarctica/Troll 0 - -00 2005 Feb 12
# year-round from 1960/61 to 1992
# Vostok, since 1957-12-16, temporarily closed 1994-02/1994-11
-# See Asia/Urumqi.
+# From Craig Mundell (1994-12-15):
+# http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP
+# Vostok, which is one of the Russian stations, is set on the same
+# time as Moscow, Russia.
+#
+# From Lee Hotz (2001-03-08):
+# I queried the folks at Columbia who spent the summer at Vostok and this is
+# what they had to say about time there:
+# "in the US Camp (East Camp) we have been on New Zealand (McMurdo)
+# time, which is 12 hours ahead of GMT. The Russian Station Vostok was
+# 6 hours behind that (although only 2 miles away, i.e. 6 hours ahead
+# of GMT). This is a time zone I think two hours east of Moscow. The
+# natural time zone is in between the two: 8 hours ahead of GMT."
+#
+# From Paul Eggert (2001-05-04):
+# This seems to be hopelessly confusing, so I asked Lee Hotz about it
+# in person. He said that some Antarctic locations set their local
+# time so that noon is the warmest part of the day, and that this
+# changes during the year and does not necessarily correspond to mean
+# solar noon. So the Vostok time might have been whatever the clocks
+# happened to be during their visit. So we still don't really know what time
+# it is at Vostok.
+#
+# From Zakhary V. Akulov (2023-12-17 22:00:48 +0700):
+# ... from December, 18, 2023 00:00 by my decision the local time of
+# the Antarctic research base Vostok will correspond to UTC+5.
+# (2023-12-19): We constantly interact with Progress base, with company who
+# builds new wintering station, with sledge convoys, with aviation - they all
+# use UTC+5. Besides, difference between Moscow time is just 2 hours now, not 4.
+# (2023-12-19, in response to the question "Has local time at Vostok
+# been UTC+6 ever since 1957, or has it changed before?"): No. At least
+# since my antarctic career start, 10 years ago, Vostok base has UTC+7.
+# (In response to a 2023-12-18 question "from 02:00 to 00:00 today"): This.
+#
+# From Paul Eggert (2023-12-18):
+# For lack of better info, guess Vostok was at +07 from founding through today,
+# except when closed.
+
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
+Zone Antarctica/Vostok 0 - -00 1957 Dec 16
+ 7:00 - +07 1994 Feb
+ 0 - -00 1994 Nov
+ 7:00 - +07 2023 Dec 18 2:00
+ 5:00 - +05
# S Africa - year-round bases
# Marion Island, -4653+03752
diff --git a/src/java.base/share/data/tzdata/asia b/src/java.base/share/data/tzdata/asia
index 6a048c3ad28..f86f84b2d27 100644
--- a/src/java.base/share/data/tzdata/asia
+++ b/src/java.base/share/data/tzdata/asia
@@ -678,7 +678,6 @@ Zone Asia/Shanghai 8:05:43 - LMT 1901
8:00 PRC C%sT
# Xinjiang time, used by many in western China; represented by Ürümqi / Ürümchi
# / Wulumuqi. (Please use Asia/Shanghai if you prefer Beijing time.)
-# Vostok base in Antarctica matches this since 1970.
Zone Asia/Urumqi 5:50:20 - LMT 1928
6:00 - +06
@@ -3450,6 +3449,9 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
# From Heba Hamad (2023-03-22):
# ... summer time will begin in Palestine from Saturday 04-29-2023,
# 02:00 AM by 60 minutes forward.
+# From Heba Hemad (2023-10-09):
+# ... winter time will begin in Palestine from Saturday 10-28-2023,
+# 02:00 AM by 60 minutes back.
#
# From Paul Eggert (2023-03-22):
# For now, guess that spring and fall transitions will normally
@@ -3571,13 +3573,13 @@ Rule Palestine 2070 only - Oct 4 2:00 0 -
Rule Palestine 2071 only - Sep 19 2:00 0 -
Rule Palestine 2072 only - Sep 10 2:00 0 -
Rule Palestine 2072 only - Oct 15 2:00 1:00 S
+Rule Palestine 2072 max - Oct Sat<=30 2:00 0 -
Rule Palestine 2073 only - Sep 2 2:00 0 -
Rule Palestine 2073 only - Oct 7 2:00 1:00 S
Rule Palestine 2074 only - Aug 18 2:00 0 -
Rule Palestine 2074 only - Sep 29 2:00 1:00 S
Rule Palestine 2075 only - Aug 10 2:00 0 -
Rule Palestine 2075 only - Sep 14 2:00 1:00 S
-Rule Palestine 2075 max - Oct Sat<=30 2:00 0 -
Rule Palestine 2076 only - Jul 25 2:00 0 -
Rule Palestine 2076 only - Sep 5 2:00 1:00 S
Rule Palestine 2077 only - Jul 17 2:00 0 -
diff --git a/src/java.base/share/data/tzdata/australasia b/src/java.base/share/data/tzdata/australasia
index 893d7055eab..366cfd10cc1 100644
--- a/src/java.base/share/data/tzdata/australasia
+++ b/src/java.base/share/data/tzdata/australasia
@@ -414,8 +414,14 @@ Zone Antarctica/Macquarie 0 - -00 1899 Nov
# Please note that there will not be any daylight savings time change
# in Fiji for 2022-2023....
# https://www.facebook.com/FijianGovernment/posts/pfbid0mmWVTYmTibn66ybpFda75pDcf34SSpoSaskJW5gXwaKo5Sgc7273Q4fXWc6kQV6Hl
+
+# From Almaz Mingaleev (2023-10-06):
+# Cabinet approved the suspension of Daylight Saving and appropriate
+# legislative changes will be considered including the repeal of the
+# Daylight Saving Act 1998
+# https://www.fiji.gov.fj/Media-Centre/Speeches/English/CABINET-DECISIONS-3-OCTOBER-2023
#
-# From Paul Eggert (2022-10-27):
+# From Paul Eggert (2023-10-06):
# For now, assume DST is suspended indefinitely.
# Rule NAME FROM TO - IN ON AT SAVE LETTER/S
diff --git a/src/java.base/share/data/tzdata/backward b/src/java.base/share/data/tzdata/backward
index c0746d6dd1b..7ddc6cc3d93 100644
--- a/src/java.base/share/data/tzdata/backward
+++ b/src/java.base/share/data/tzdata/backward
@@ -228,7 +228,6 @@ Link America/Puerto_Rico America/Tortola
Link Pacific/Port_Moresby Antarctica/DumontDUrville
Link Pacific/Auckland Antarctica/McMurdo
Link Asia/Riyadh Antarctica/Syowa
-Link Asia/Urumqi Antarctica/Vostok
Link Europe/Berlin Arctic/Longyearbyen
Link Asia/Riyadh Asia/Aden
Link Asia/Qatar Asia/Bahrain
diff --git a/src/java.base/share/data/tzdata/europe b/src/java.base/share/data/tzdata/europe
index 446d2e1e658..f1b084f64d0 100644
--- a/src/java.base/share/data/tzdata/europe
+++ b/src/java.base/share/data/tzdata/europe
@@ -1146,6 +1146,23 @@ Zone Atlantic/Faroe -0:27:04 - LMT 1908 Jan 11 # Tórshavn
# 2. The shift *from* DST in 2023 happens as normal, but coincides with the
# shift to UTC-02 normaltime (people will not change their clocks here).
# 3. After this, DST is still observed, but as -02/-01 instead of -03/-02.
+#
+# From Múte Bourup Egede via Jógvan Svabo Samuelsen (2023-03-15):
+# Greenland will not switch to Daylight Saving Time this year, 2023,
+# because the standard time for Greenland will change from UTC -3 to UTC -2.
+# However, Greenland will change to Daylight Saving Time again in 2024
+# and onwards.
+
+# From a contributor who wishes to remain anonymous for now (2023-10-29):
+# https://www.dr.dk/nyheder/seneste/i-nat-skal-uret-stilles-en-time-tilbage-men-foerste-gang-sker-det-ikke-i-groenland
+# with a link to that page:
+# https://naalakkersuisut.gl/Nyheder/2023/10/2710_sommertid
+# ... Ittoqqortoormiit joins the time of Nuuk at March 2024.
+# What would mean that America/Scoresbysund would either be in -01 year round
+# or in -02/-01 like America/Nuuk, but no longer in -01/+00.
+#
+# From Paul Eggert (2023-10-29):
+# For now, assume it will be like America/Nuuk.
# Rule NAME FROM TO - IN ON AT SAVE LETTER/S
Rule Thule 1991 1992 - Mar lastSun 2:00 1:00 D
@@ -1166,10 +1183,12 @@ Zone America/Danmarkshavn -1:14:40 - LMT 1916 Jul 28
Zone America/Scoresbysund -1:27:52 - LMT 1916 Jul 28 # Ittoqqortoormiit
-2:00 - -02 1980 Apr 6 2:00
-2:00 C-Eur -02/-01 1981 Mar 29
- -1:00 EU -01/+00
+ -1:00 EU -01/+00 2024 Mar 31
+ -2:00 EU -02/-01
Zone America/Nuuk -3:26:56 - LMT 1916 Jul 28 # Godthåb
-3:00 - -03 1980 Apr 6 2:00
- -3:00 EU -03/-02 2023 Oct 29 1:00u
+ -3:00 EU -03/-02 2023 Mar 26 1:00u
+ -2:00 - -02 2023 Oct 29 1:00u
-2:00 EU -02/-01
Zone America/Thule -4:35:08 - LMT 1916 Jul 28 # Pituffik
-4:00 Thule A%sT
@@ -3734,11 +3753,7 @@ Zone Europe/Istanbul 1:55:52 - LMT 1880
# and not at 3:00 as would have been under EU rules.
# This is why I have set the change to EU rules into May 1996,
# so that the change in March is stil covered by the Ukraine rule.
-# The next change in October 1996 happened under EU rules....
-# TZ database holds three other zones for Ukraine.... I have not yet
-# worked out the consequences for these three zones, as we (me and my
-# US colleague David Cochrane) are still trying to get more
-# information upon these local deviations from Kiev rules.
+# The next change in October 1996 happened under EU rules.
#
# From Paul Eggert (2022-08-27):
# For now, assume that Ukraine's zones all followed the same rules,
diff --git a/src/java.base/share/data/tzdata/iso3166.tab b/src/java.base/share/data/tzdata/iso3166.tab
index cea17732dd1..7fa350ecbe3 100644
--- a/src/java.base/share/data/tzdata/iso3166.tab
+++ b/src/java.base/share/data/tzdata/iso3166.tab
@@ -26,17 +26,22 @@
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
#
-# From Paul Eggert (2022-11-18):
+# From Paul Eggert (2023-09-06):
# This file contains a table of two-letter country codes. Columns are
# separated by a single tab. Lines beginning with '#' are comments.
# All text uses UTF-8 encoding. The columns of the table are as follows:
#
# 1. ISO 3166-1 alpha-2 country code, current as of
-# ISO 3166-1 N1087 (2022-09-02). See: Updates on ISO 3166-1
-# https://isotc.iso.org/livelink/livelink/Open/16944257
-# 2. The usual English name for the coded region,
-# chosen so that alphabetic sorting of subsets produces helpful lists.
-# This is not the same as the English name in the ISO 3166 tables.
+# ISO/TC 46 N1108 (2023-04-05). See: ISO/TC 46 Documents
+# https://www.iso.org/committee/48750.html?view=documents
+# 2. The usual English name for the coded region. This sometimes
+# departs from ISO-listed names, sometimes so that sorted subsets
+# of names are useful (e.g., "Samoa (American)" and "Samoa
+# (western)" rather than "American Samoa" and "Samoa"),
+# sometimes to avoid confusion among non-experts (e.g.,
+# "Czech Republic" and "Turkey" rather than "Czechia" and "Türkiye"),
+# and sometimes to omit needless detail or churn (e.g., "Netherlands"
+# rather than "Netherlands (the)" or "Netherlands (Kingdom of the)").
#
# The table is sorted by country code.
#
diff --git a/src/java.base/share/data/tzdata/leapseconds b/src/java.base/share/data/tzdata/leapseconds
index 89ce8b89cd2..ab2c1af4bed 100644
--- a/src/java.base/share/data/tzdata/leapseconds
+++ b/src/java.base/share/data/tzdata/leapseconds
@@ -95,11 +95,11 @@ Leap 2016 Dec 31 23:59:60 + S
# Any additional leap seconds will come after this.
# This Expires line is commented out for now,
# so that pre-2020a zic implementations do not reject this file.
-#Expires 2023 Dec 28 00:00:00
+#Expires 2024 Jun 28 00:00:00
# POSIX timestamps for the data in this file:
#updated 1467936000 (2016-07-08 00:00:00 UTC)
-#expires 1703721600 (2023-12-28 00:00:00 UTC)
+#expires 1719532800 (2024-06-28 00:00:00 UTC)
-# Updated through IERS Bulletin C65
-# File expires on: 28 December 2023
+# Updated through IERS Bulletin C66
+# File expires on: 28 June 2024
diff --git a/src/java.base/share/data/tzdata/northamerica b/src/java.base/share/data/tzdata/northamerica
index e240cf35103..b96269a0e26 100644
--- a/src/java.base/share/data/tzdata/northamerica
+++ b/src/java.base/share/data/tzdata/northamerica
@@ -1,3 +1,4 @@
+#
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -1475,7 +1476,7 @@ Rule StJohns 1989 2006 - Apr Sun>=1 0:01 1:00 D
Rule StJohns 2007 2011 - Mar Sun>=8 0:01 1:00 D
Rule StJohns 2007 2010 - Nov Sun>=1 0:01 0 S
#
-# St John's has an apostrophe, but Posix file names can't have apostrophes.
+# St John's has an apostrophe, but POSIX file names can't have apostrophes.
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/St_Johns -3:30:52 - LMT 1884
-3:30:52 StJohns N%sT 1918
diff --git a/src/java.base/share/data/tzdata/southamerica b/src/java.base/share/data/tzdata/southamerica
index 4024e7180cd..da2c6239262 100644
--- a/src/java.base/share/data/tzdata/southamerica
+++ b/src/java.base/share/data/tzdata/southamerica
@@ -1720,6 +1720,12 @@ Rule Para 2010 2012 - Apr Sun>=8 0:00 0 -
# From Carlos Raúl Perasso (2014-02-28):
# Decree 1264 can be found at:
# http://www.presidencia.gov.py/archivos/documentos/DECRETO1264_ey9r8zai.pdf
+#
+# From Paul Eggert (2023-07-26):
+# Transition dates are now set by Law No. 7115, not by presidential decree.
+# https://www.abc.com.py/politica/2023/07/12/promulgacion-el-cambio-de-hora-sera-por-ley/
+# From Carlos Raúl Perasso (2023-07-27):
+# http://silpy.congreso.gov.py/descarga/ley-144138
Rule Para 2013 max - Mar Sun>=22 0:00 0 -
# Zone NAME STDOFF RULES FORMAT [UNTIL]
diff --git a/src/java.base/share/data/tzdata/zone.tab b/src/java.base/share/data/tzdata/zone.tab
index 3edb0d61c80..0a01e8777dd 100644
--- a/src/java.base/share/data/tzdata/zone.tab
+++ b/src/java.base/share/data/tzdata/zone.tab
@@ -71,7 +71,7 @@ AR -3124-06411 America/Argentina/Cordoba Argentina (most areas: CB, CC, CN, ER,
AR -2447-06525 America/Argentina/Salta Salta (SA, LP, NQ, RN)
AR -2411-06518 America/Argentina/Jujuy Jujuy (JY)
AR -2649-06513 America/Argentina/Tucuman Tucuman (TM)
-AR -2828-06547 America/Argentina/Catamarca Catamarca (CT); Chubut (CH)
+AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH)
AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR)
AR -3132-06831 America/Argentina/San_Juan San Juan (SJ)
AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ)
@@ -110,7 +110,7 @@ BN +0456+11455 Asia/Brunei
BO -1630-06809 America/La_Paz
BQ +120903-0681636 America/Kralendijk
BR -0351-03225 America/Noronha Atlantic islands
-BR -0127-04829 America/Belem Para (east); Amapa
+BR -0127-04829 America/Belem Para (east), Amapa
BR -0343-03830 America/Fortaleza Brazil (northeast: MA, PI, CE, RN, PB)
BR -0803-03454 America/Recife Pernambuco
BR -0712-04812 America/Araguaina Tocantins
@@ -130,21 +130,21 @@ BT +2728+08939 Asia/Thimphu
BW -2439+02555 Africa/Gaborone
BY +5354+02734 Europe/Minsk
BZ +1730-08812 America/Belize
-CA +4734-05243 America/St_Johns Newfoundland; Labrador (southeast)
-CA +4439-06336 America/Halifax Atlantic - NS (most areas); PE
+CA +4734-05243 America/St_Johns Newfoundland, Labrador (SE)
+CA +4439-06336 America/Halifax Atlantic - NS (most areas), PE
CA +4612-05957 America/Glace_Bay Atlantic - NS (Cape Breton)
CA +4606-06447 America/Moncton Atlantic - New Brunswick
CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas)
CA +5125-05707 America/Blanc-Sablon AST - QC (Lower North Shore)
-CA +4339-07923 America/Toronto Eastern - ON, QC (most areas)
+CA +4339-07923 America/Toronto Eastern - ON & QC (most areas)
CA +6344-06828 America/Iqaluit Eastern - NU (most areas)
-CA +484531-0913718 America/Atikokan EST - ON (Atikokan); NU (Coral H)
-CA +4953-09709 America/Winnipeg Central - ON (west); Manitoba
+CA +484531-0913718 America/Atikokan EST - ON (Atikokan), NU (Coral H)
+CA +4953-09709 America/Winnipeg Central - ON (west), Manitoba
CA +744144-0944945 America/Resolute Central - NU (Resolute)
CA +624900-0920459 America/Rankin_Inlet Central - NU (central)
CA +5024-10439 America/Regina CST - SK (most areas)
CA +5017-10750 America/Swift_Current CST - SK (midwest)
-CA +5333-11328 America/Edmonton Mountain - AB; BC (E); NT (E); SK (W)
+CA +5333-11328 America/Edmonton Mountain - AB, BC(E), NT(E), SK(W)
CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west)
CA +682059-1334300 America/Inuvik Mountain - NT (west)
CA +4906-11631 America/Creston MST - BC (Creston)
@@ -230,8 +230,8 @@ HT +1832-07220 America/Port-au-Prince
HU +4730+01905 Europe/Budapest
ID -0610+10648 Asia/Jakarta Java, Sumatra
ID -0002+10920 Asia/Pontianak Borneo (west, central)
-ID -0507+11924 Asia/Makassar Borneo (east, south); Sulawesi/Celebes, Bali, Nusa Tengarra; Timor (west)
-ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya); Malukus/Moluccas
+ID -0507+11924 Asia/Makassar Borneo (east, south), Sulawesi/Celebes, Bali, Nusa Tengarra, Timor (west)
+ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya), Malukus/Moluccas
IE +5320-00615 Europe/Dublin
IL +314650+0351326 Asia/Jerusalem
IM +5409-00428 Europe/Isle_of_Man
@@ -378,7 +378,7 @@ RU +4310+13156 Asia/Vladivostok MSK+07 - Amur River
RU +643337+1431336 Asia/Ust-Nera MSK+07 - Oymyakonsky
RU +5934+15048 Asia/Magadan MSK+08 - Magadan
RU +4658+14242 Asia/Sakhalin MSK+08 - Sakhalin Island
-RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E); N Kuril Is
+RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E), N Kuril Is
RU +5301+15839 Asia/Kamchatka MSK+09 - Kamchatka
RU +6445+17729 Asia/Anadyr MSK+09 - Bering Sea
RW -0157+03004 Africa/Kigali
@@ -441,7 +441,7 @@ US +470659-1011757 America/North_Dakota/Center Central - ND (Oliver)
US +465042-1012439 America/North_Dakota/New_Salem Central - ND (Morton rural)
US +471551-1014640 America/North_Dakota/Beulah Central - ND (Mercer)
US +394421-1045903 America/Denver Mountain (most areas)
-US +433649-1161209 America/Boise Mountain - ID (south); OR (east)
+US +433649-1161209 America/Boise Mountain - ID (south), OR (east)
US +332654-1120424 America/Phoenix MST - AZ (except Navajo)
US +340308-1181434 America/Los_Angeles Pacific
US +611305-1495401 America/Anchorage Alaska (most areas)
diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION
index c5483b48512..f92096d49aa 100644
--- a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION
+++ b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION
@@ -1 +1 @@
-tzdata2023c
+tzdata2023d
diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt b/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt
index 07c5edbafee..82bad17c553 100644
--- a/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt
+++ b/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt
@@ -148,7 +148,6 @@ Link America/Puerto_Rico America/Tortola
Link Pacific/Port_Moresby Antarctica/DumontDUrville
Link Pacific/Auckland Antarctica/McMurdo
Link Asia/Riyadh Antarctica/Syowa
-Link Asia/Urumqi Antarctica/Vostok
Link Europe/Berlin Arctic/Longyearbyen
Link Asia/Riyadh Asia/Aden
Link Asia/Qatar Asia/Bahrain
From a8df5597638c4cbcbc9a56bad7034b9af5efc32d Mon Sep 17 00:00:00 2001
From: Justin Lu
Date: Tue, 9 Jan 2024 22:55:51 +0000
Subject: [PATCH 14/66] 8321480: ISO 4217 Amendment 176 Update
Reviewed-by: naoto, iris
Backport-of: 8b24851b9d3619c41c7a6cdb9193ed26a9b732dc
---
.../GenerateCurrencyData.java | 15 +++++---
.../util/resources/CurrencyNames.properties | 4 ++-
.../data/currency/CurrencyData.properties | 10 +++---
.../java/util/Currency/ValidateISO4217.java | 35 ++++++++++---------
test/jdk/java/util/Currency/tablea1.txt | 12 +++----
5 files changed, 43 insertions(+), 33 deletions(-)
diff --git a/make/jdk/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java b/make/jdk/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java
index 561edbef034..9655e08016c 100644
--- a/make/jdk/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java
+++ b/make/jdk/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -32,6 +32,7 @@
import java.io.FileOutputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
+import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
@@ -339,9 +340,15 @@ private static void buildOtherTables() {
validCurrencyCodes.substring(i * 7 + 3, i * 7 + 6));
checkCurrencyCode(currencyCode);
int tableEntry = mainTable[(currencyCode.charAt(0) - 'A') * A_TO_Z + (currencyCode.charAt(1) - 'A')];
- if (tableEntry == INVALID_COUNTRY_ENTRY ||
- (tableEntry & SPECIAL_CASE_COUNTRY_MASK) != 0 ||
- (tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK) != (currencyCode.charAt(2) - 'A')) {
+
+ // Do not allow a future currency to be classified as an otherCurrency,
+ // otherwise it will leak out into Currency:getAvailableCurrencies
+ boolean futureCurrency = Arrays.asList(specialCaseNewCurrencies).contains(currencyCode);
+ boolean simpleCurrency = (tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK) == (currencyCode.charAt(2) - 'A');
+
+ // If neither a simple currency, or one defined in the future
+ // then the current currency is applicable to be added to the otherTable
+ if (!futureCurrency && !simpleCurrency) {
if (otherCurrenciesCount == maxOtherCurrencies) {
throw new RuntimeException("too many other currencies");
}
diff --git a/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties b/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties
index 76ad70e34c8..3cbbf15ed02 100644
--- a/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties
+++ b/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 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
@@ -269,6 +269,7 @@ XBB=XBB
XBC=XBC
XBD=XBD
XCD=XCD
+XCG=XCG
XDR=XDR
XFO=XFO
XFU=XFU
@@ -494,6 +495,7 @@ xbb=European Monetary Unit
xbc=European Unit of Account (XBC)
xbd=European Unit of Account (XBD)
xcd=East Caribbean Dollar
+xcg=Caribbean Guilder
xdr=Special Drawing Rights
xfo=French Gold Franc
xfu=French UIC-Franc
diff --git a/src/java.base/share/data/currency/CurrencyData.properties b/src/java.base/share/data/currency/CurrencyData.properties
index dbfbe799b47..1661b4cccba 100644
--- a/src/java.base/share/data/currency/CurrencyData.properties
+++ b/src/java.base/share/data/currency/CurrencyData.properties
@@ -32,7 +32,7 @@ formatVersion=3
# Version of the currency code information in this class.
# It is a serial number that accompanies with each amendment.
-dataVersion=175
+dataVersion=176
# List of all valid ISO 4217 currency codes.
# To ensure compatibility, do not remove codes.
@@ -55,7 +55,7 @@ all=ADP020-AED784-AFA004-AFN971-ALL008-AMD051-ANG532-AOA973-ARS032-ATS040-AUD036
SRD968-SRG740-SSP728-STD678-STN930-SVC222-SYP760-SZL748-THB764-TJS972-TMM795-TMT934-TND788-TOP776-\
TPE626-TRL792-TRY949-TTD780-TWD901-TZS834-UAH980-UGX800-USD840-USN997-USS998-UYI940-\
UYU858-UZS860-VEB862-VED926-VEF937-VES928-VND704-VUV548-WST882-XAF950-XAG961-XAU959-XBA955-\
- XBB956-XBC957-XBD958-XCD951-XDR960-XFO000-XFU000-XOF952-XPD964-XPF953-\
+ XBB956-XBC957-XBD958-XCD951-XCG532-XDR960-XFO000-XFU000-XOF952-XPD964-XPF953-\
XPT962-XSU994-XTS963-XUA965-XXX999-YER886-YUM891-ZAR710-ZMK894-ZMW967-ZWD716-ZWL932-\
ZWN942-ZWR935
@@ -189,11 +189,11 @@ CR=CRC
# COTE D'IVOIRE
CI=XOF
# CROATIA
-HR=HRK;2022-12-31-23-00-00;EUR
+HR=EUR
# CUBA
CU=CUP
# Curaçao
-CW=ANG
+CW=ANG;2025-04-01-04-00-00;XCG
# CYPRUS
CY=EUR
# CZECHIA
@@ -510,7 +510,7 @@ SR=SRD
# SVALBARD AND JAN MAYEN
SJ=NOK
# Sint Maarten (Dutch part)
-SX=ANG
+SX=ANG;2025-04-01-04-00-00;XCG
# ESWATINI
SZ=SZL
# SWEDEN
diff --git a/test/jdk/java/util/Currency/ValidateISO4217.java b/test/jdk/java/util/Currency/ValidateISO4217.java
index c4fdc5ca2e0..53788c899b3 100644
--- a/test/jdk/java/util/Currency/ValidateISO4217.java
+++ b/test/jdk/java/util/Currency/ValidateISO4217.java
@@ -25,7 +25,7 @@
* @test
* @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759
* 8039317 8074350 8074351 8145952 8187946 8193552 8202026 8204269
- * 8208746 8209775 8264792 8274658 8283277 8296239
+ * 8208746 8209775 8264792 8274658 8283277 8296239 8321480
* @summary Validate ISO 4217 data for Currency class.
* @modules java.base/java.util:open
* jdk.localedata
@@ -86,7 +86,7 @@ public class ValidateISO4217 {
// Codes that are obsolete, do not have related country, extra currency
private static final String otherCodes =
"ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-"
- + "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-IEP-ITL-LTL-LUF-LVL-MGF-MRO-MTL-MXV-MZM-NLG-"
+ + "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-HRK-IEP-ITL-LTL-LUF-LVL-MGF-MRO-MTL-MXV-MZM-NLG-"
+ "PTE-ROL-RUR-SDD-SIT-SLL-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-VED-"
+ "XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-"
+ "YUM-ZMK-ZWD-ZWN-ZWR";
@@ -168,7 +168,7 @@ private static void processColumns(StringTokenizer tokens, String country) throw
if (format == null) {
createDateFormat();
}
- // If the cut-over already passed, test the changed data too
+ // If the cut-over already passed, use the new curency for ISO4217Codes
if (format.parse(tokens.nextToken()).getTime() < System.currentTimeMillis()) {
currency = tokens.nextToken();
numeric = tokens.nextToken();
@@ -267,20 +267,21 @@ private static List additionalCodesProvider() {
* throws an IllegalArgumentException or returns null. The test data
* supplied is every possible combination of AA -> ZZ.
*/
- @ParameterizedTest
- @MethodSource("codeCombos")
- public void twoLetterCodesTest(String country) {
- if (codes[toIndex(country)] == UNDEFINED) {
- // if a code is undefined / 0, creating a Currency from it
- // should throw an IllegalArgumentException
- assertThrows(IllegalArgumentException.class,
- ()-> Currency.getInstance(Locale.of("", country)),
- "Error: This should be an undefined code and throw IllegalArgumentException: " + country);
- } else if (codes[toIndex(country)] == SKIPPED) {
- // if a code is marked as skipped / 2, creating a Currency from it
- // should return null
- assertNull(Currency.getInstance(Locale.of("", country)),
- "Error: Currency.getInstance() for this locale should return null: " + country);
+ @Test
+ public void twoLetterCodesTest() {
+ for (String country : codeCombos()) {
+ if (codes[toIndex(country)] == UNDEFINED) {
+ // if a code is undefined / 0, creating a Currency from it
+ // should throw an IllegalArgumentException
+ assertThrows(IllegalArgumentException.class,
+ () -> Currency.getInstance(Locale.of("", country)),
+ "Error: This should be an undefined code and throw IllegalArgumentException: " + country);
+ } else if (codes[toIndex(country)] == SKIPPED) {
+ // if a code is marked as skipped / 2, creating a Currency from it
+ // should return null
+ assertNull(Currency.getInstance(Locale.of("", country)),
+ "Error: Currency.getInstance() for this locale should return null: " + country);
+ }
}
}
diff --git a/test/jdk/java/util/Currency/tablea1.txt b/test/jdk/java/util/Currency/tablea1.txt
index 4e33a62c05e..6e85de5e6d2 100644
--- a/test/jdk/java/util/Currency/tablea1.txt
+++ b/test/jdk/java/util/Currency/tablea1.txt
@@ -1,12 +1,12 @@
#
#
-# Amendments up until ISO 4217 AMENDMENT NUMBER 175
-# (As of 31 March 2023)
+# Amendments up until ISO 4217 AMENDMENT NUMBER 176
+# (As of 06 December 2023)
#
# Version
FILEVERSION=3
-DATAVERSION=175
+DATAVERSION=176
# ISO 4217 currency data
AF AFN 971 2
@@ -67,9 +67,9 @@ CD CDF 976 2
CK NZD 554 2
CR CRC 188 2
CI XOF 952 0
-HR HRK 191 2 2022-12-31-23-00-00 EUR 978 2
+HR EUR 978 2
CU CUP 192 2
-CW ANG 532 2
+CW ANG 532 2 2025-04-01-04-00-00 XCG 532 2
CY EUR 978 2
CZ CZK 203 2
DK DKK 208 2
@@ -233,7 +233,7 @@ LK LKR 144 2
SD SDG 938 2
SR SRD 968 2
SJ NOK 578 2
-SX ANG 532 2
+SX ANG 532 2 2025-04-01-04-00-00 XCG 532 2
SZ SZL 748 2
SE SEK 752 2
CH CHF 756 2
From 6b79e792ac410cc26400431d66851c89f05c2a78 Mon Sep 17 00:00:00 2001
From: David Holmes
Date: Wed, 10 Jan 2024 04:29:04 +0000
Subject: [PATCH 15/66] 8323241: jcmd manpage should use lists for argument
lists
Reviewed-by: cjplummer
Backport-of: 075fed91bd144d94328e198b41ea2946961940e9
---
src/jdk.jcmd/share/man/jcmd.1 | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/jdk.jcmd/share/man/jcmd.1 b/src/jdk.jcmd/share/man/jcmd.1
index 422b99adaa5..43a3fb4a1f2 100644
--- a/src/jdk.jcmd/share/man/jcmd.1
+++ b/src/jdk.jcmd/share/man/jcmd.1
@@ -172,11 +172,11 @@ Impact: Low: Depends on code heap size and content.
Holds CodeCache_lock during analysis step, usually sub-second duration.
.PP
\f[I]arguments\f[R]:
-.PP
+.IP \[bu] 2
\f[I]function\f[R]: (Optional) Function to be performed (aggregate,
UsedSpace, FreeSpace, MethodCount, MethodSpace, MethodAge, MethodNames,
discard (STRING, all)
-.PP
+.IP \[bu] 2
\f[I]granularity\f[R]: (Optional) Detail level - smaller value -> more
detail (INT, 4096)
.RE
@@ -202,7 +202,7 @@ Adds compiler directives from a file.
Impact: Low
.PP
\f[I]arguments\f[R]:
-.PP
+.IP \[bu] 2
\f[I]filename\f[R]: The name of the directives file (STRING, no default
value)
.RE
From 28db238d52b0713a4ecfd15b7e7e4806c2935b3f Mon Sep 17 00:00:00 2001
From: Christoph Langer
Date: Wed, 10 Jan 2024 08:28:13 +0000
Subject: [PATCH 16/66] 8322163: runtime/Unsafe/InternalErrorTest.java fails on
Alpine after JDK-8320886
Reviewed-by: mbaesken
Backport-of: 1230853343c38787c90820d19d0626f0c37540dc
---
src/hotspot/share/utilities/copy.cpp | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/hotspot/share/utilities/copy.cpp b/src/hotspot/share/utilities/copy.cpp
index 9ead75f2ceb..ed779796943 100644
--- a/src/hotspot/share/utilities/copy.cpp
+++ b/src/hotspot/share/utilities/copy.cpp
@@ -243,6 +243,16 @@ void Copy::fill_to_memory_atomic(void* to, size_t size, jubyte value) {
}
} else {
// Not aligned, so no need to be atomic.
+#ifdef MUSL_LIBC
+ // This code is used by Unsafe and may hit the next page after truncation of mapped memory.
+ // Therefore, we use volatile to prevent compilers from replacing the loop by memset which
+ // may not trigger SIGBUS as needed (observed on Alpine Linux x86_64)
+ jbyte fill = value;
+ for (uintptr_t off = 0; off < size; off += sizeof(jbyte)) {
+ *(volatile jbyte*)(dst + off) = fill;
+ }
+#else
Copy::fill_to_bytes(dst, size, value);
+#endif
}
}
From 33f07b56ef6d519569f4345d789288022e2a28de Mon Sep 17 00:00:00 2001
From: Athijegannathan Sundararajan
Date: Wed, 10 Jan 2024 11:31:26 +0000
Subject: [PATCH 17/66] 8310995: missing @since tags in 36 jdk.dynalink classes
Reviewed-by: jlaskey
Backport-of: 176606d0cb9117ca9080261f898cd57339fa5a85
---
.../share/classes/jdk/dynalink/CallSiteDescriptor.java | 1 +
src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java | 1 +
.../share/classes/jdk/dynalink/DynamicLinkerFactory.java | 1 +
src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java | 1 +
src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java | 1 +
.../share/classes/jdk/dynalink/NamespaceOperation.java | 1 +
.../classes/jdk/dynalink/NoSuchDynamicMethodException.java | 1 +
src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java | 1 +
.../share/classes/jdk/dynalink/RelinkableCallSite.java | 1 +
.../share/classes/jdk/dynalink/SecureLookupSupplier.java | 1 +
.../share/classes/jdk/dynalink/StandardNamespace.java | 1 +
.../share/classes/jdk/dynalink/StandardOperation.java | 1 +
.../share/classes/jdk/dynalink/beans/BeansLinker.java | 1 +
.../classes/jdk/dynalink/beans/MissingMemberHandlerFactory.java | 1 +
.../share/classes/jdk/dynalink/beans/StaticClass.java | 1 +
.../share/classes/jdk/dynalink/linker/ConversionComparator.java | 2 ++
.../share/classes/jdk/dynalink/linker/GuardedInvocation.java | 1 +
.../jdk/dynalink/linker/GuardedInvocationTransformer.java | 1 +
.../classes/jdk/dynalink/linker/GuardingDynamicLinker.java | 1 +
.../jdk/dynalink/linker/GuardingDynamicLinkerExporter.java | 1 +
.../jdk/dynalink/linker/GuardingTypeConverterFactory.java | 1 +
.../share/classes/jdk/dynalink/linker/LinkRequest.java | 1 +
.../share/classes/jdk/dynalink/linker/LinkerServices.java | 1 +
.../classes/jdk/dynalink/linker/MethodHandleTransformer.java | 1 +
.../jdk/dynalink/linker/MethodTypeConversionStrategy.java | 1 +
.../jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java | 1 +
.../dynalink/linker/support/CompositeGuardingDynamicLinker.java | 1 +
.../linker/support/CompositeTypeBasedGuardingDynamicLinker.java | 1 +
.../dynalink/linker/support/DefaultInternalObjectFilter.java | 1 +
.../share/classes/jdk/dynalink/linker/support/Guards.java | 1 +
.../share/classes/jdk/dynalink/linker/support/Lookup.java | 1 +
.../classes/jdk/dynalink/linker/support/SimpleLinkRequest.java | 1 +
.../classes/jdk/dynalink/linker/support/TypeUtilities.java | 1 +
src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java | 1 +
.../jdk/dynalink/support/AbstractRelinkableCallSite.java | 1 +
.../share/classes/jdk/dynalink/support/ChainedCallSite.java | 1 +
.../classes/jdk/dynalink/support/SimpleRelinkableCallSite.java | 1 +
37 files changed, 38 insertions(+)
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java b/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java
index e1e49f22b4c..e47625fb497 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java
@@ -88,6 +88,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* the {@code MethodHandles.Lookup} object it carries. This lookup should be used
* to find method handles to set as targets of the call site described by this
* descriptor.
+ * @since 9
*/
public class CallSiteDescriptor extends SecureLookupSupplier {
private final Operation operation;
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java
index eb7de0aba75..23f4f7a8122 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java
@@ -141,6 +141,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* in the above example the {@code parseOperation} method is left unimplemented.
*
*
+ * @since 9
*/
public final class DynamicLinker {
private static final String CLASS_NAME = DynamicLinker.class.getName();
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java b/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java
index a34cff5ba12..ed211008566 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java
@@ -105,6 +105,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* {@link #setClassLoader(ClassLoader) automatically discovered} ones, and
* finally the ones configured with {@link #setFallbackLinkers(List)}; this last
* category usually includes {@link BeansLinker}.
+ * @since 9
*/
public final class DynamicLinkerFactory {
@SuppressWarnings("removal")
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java b/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java
index 7563e3946ad..5fe3e96f43e 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java
@@ -106,6 +106,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* usually containing the textual representation of the source expression that retrieved the
* callee, e.g. {@code StandardOperation.CALL.named("window.open")}.
*
+ * @since 9
*/
public final class NamedOperation implements Operation {
private final Operation baseOperation;
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java b/src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java
index 69b68d25ffc..8f5e7ede7f6 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java
@@ -66,6 +66,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* set of standard namespaces with the {@link StandardNamespace} enum. Operations
* that need to specify a namespace they operate on can be expressed using
* {@link NamespaceOperation}.
+ * @since 9
*/
public interface Namespace {
}
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java b/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java
index 322767de364..0e047849c2c 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java
@@ -134,6 +134,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* StandardNamespace.PROPERTY)
* .named("empty");
*
+ * @since 9
*/
public final class NamespaceOperation implements Operation {
private final Operation baseOperation;
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java b/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java
index bf20c23b738..8842c32c1be 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java
@@ -64,6 +64,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
/**
* Thrown at the invocation if the call site can not be linked by any available {@link GuardingDynamicLinker}.
+ * @since 9
*/
public class NoSuchDynamicMethodException extends RuntimeException {
private static final long serialVersionUID = 1L;
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java b/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java
index ba22e32c54f..ef0acbc3b57 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java
@@ -74,6 +74,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* {@code GET:PROPERTY|ELEMENT}), and finally we will refer to named operations
* by separating the base operation and the name with the colon character (e.g.
* {@code GET:PROPERTY|ELEMENT:color}).
+ * @since 9
*/
public interface Operation {
/**
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java b/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java
index 5f74edd700c..e14cfdfebd3 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java
@@ -76,6 +76,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* method handles. A relinkable call site will be managed by a
* {@link DynamicLinker} object after being associated with it using its
* {@link DynamicLinker#link(RelinkableCallSite)} method.
+ * @since 9
*/
public interface RelinkableCallSite {
/**
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/SecureLookupSupplier.java b/src/jdk.dynalink/share/classes/jdk/dynalink/SecureLookupSupplier.java
index 73ee39b9002..5ec1f2737fb 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/SecureLookupSupplier.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/SecureLookupSupplier.java
@@ -32,6 +32,7 @@
/**
* Provides security-checked access to a {@code MethodHandles.Lookup} object.
* See {@link #getLookup()} for details.
+ * @since 9
*/
public class SecureLookupSupplier {
/**
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/StandardNamespace.java b/src/jdk.dynalink/share/classes/jdk/dynalink/StandardNamespace.java
index 55b9acee703..b4c33250d38 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/StandardNamespace.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/StandardNamespace.java
@@ -62,6 +62,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
/**
* An enumeration of standard namespaces defined by Dynalink.
+ * @since 9
*/
public enum StandardNamespace implements Namespace {
/**
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java b/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java
index e58bf4e78bf..176a87acd36 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java
@@ -67,6 +67,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* disappears from their type signature.
* {@link NamedOperation} can also be used to decorate {@link #CALL} and {@link #NEW} operations with a
* diagnostic name, and as such it does not affect their type signature.
+ * @since 9
*/
public enum StandardOperation implements Operation {
/**
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java
index 386f386216c..ca09923292a 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java
@@ -135,6 +135,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* property and method names on classes and class instances, as well as access
* to per-class linkers using the {@link #getLinkerForClass(Class)}
* method.
+ * @since 9
*/
public class BeansLinker implements GuardingDynamicLinker {
private static final ClassValue linkers = new ClassValue<>() {
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MissingMemberHandlerFactory.java b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MissingMemberHandlerFactory.java
index 1fe50b916d9..c1e2f7eb71d 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MissingMemberHandlerFactory.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MissingMemberHandlerFactory.java
@@ -67,6 +67,7 @@
* exception itself, as the linkage for the missing member is often conditional.
*
* @see BeansLinker#BeansLinker(MissingMemberHandlerFactory)
+ * @since 9
*/
@FunctionalInterface
public interface MissingMemberHandlerFactory {
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java
index 62bb74cb29e..ebd6c7e55e2 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java
@@ -102,6 +102,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* constructor. You might want to expose a mechanism in your language for
* selecting a constructor with an explicit signature through
* {@link BeansLinker#getConstructorMethod(Class, String)}.
+ * @since 9
*/
public final class StaticClass implements Serializable {
private static final ClassValue staticClasses = new ClassValue<>() {
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/ConversionComparator.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/ConversionComparator.java
index 6c0dd438bbb..267752b0a23 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/ConversionComparator.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/ConversionComparator.java
@@ -70,10 +70,12 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* specific method with unrelated signatures. In these cases, language runtimes
* can be asked to resolve the ambiguity by expressing preferences for one
* conversion over the other.
+ * @since 9
*/
public interface ConversionComparator {
/**
* Enumeration of possible outcomes of comparing one conversion to another.
+ * @since 9
*/
enum Comparison {
/** The conversions cannot be compared. **/
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java
index 1a1e23981c5..174e63bff26 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java
@@ -86,6 +86,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* throw an exception of the designated type. The guard, the switch points, and
* the exception type are all optional (a guarded invocation having none of them
* is unconditionally valid).
+ * @since 9
*/
public class GuardedInvocation {
private final MethodHandle invocation;
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocationTransformer.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocationTransformer.java
index 6c775022362..fa4f0cd4545 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocationTransformer.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocationTransformer.java
@@ -67,6 +67,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* another one. Typical usage is for implementing
* {@link DynamicLinkerFactory#setPrelinkTransformer(GuardedInvocationTransformer)
* pre-link transformers}.
+ * @since 9
*/
@FunctionalInterface
public interface GuardedInvocationTransformer {
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinker.java
index c604712ae43..e94cb7b9128 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinker.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinker.java
@@ -87,6 +87,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* Languages can export linkers to other language runtimes for
* {@link DynamicLinkerFactory#setClassLoader(ClassLoader) automatic discovery}
* using a {@link GuardingDynamicLinkerExporter}.
+ * @since 9
*/
public interface GuardingDynamicLinker {
/**
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinkerExporter.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinkerExporter.java
index 03be07cf459..cd670a8fdbe 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinkerExporter.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinkerExporter.java
@@ -45,6 +45,7 @@
* security manager is present, to ensure that only trusted runtimes can
* automatically export their linkers into other runtimes.
* @see DynamicLinkerFactory#setClassLoader(ClassLoader)
+ * @since 9
*/
public abstract class GuardingDynamicLinkerExporter implements Supplier> {
/**
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java
index 981a39059af..bbd327d5bbe 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java
@@ -75,6 +75,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* these conversions, will cause more ambiguity for {@link BeansLinker} in
* selecting the correct overload when trying to link to an overloaded Java
* method.
+ * @since 9
*/
public interface GuardingTypeConverterFactory {
/**
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkRequest.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkRequest.java
index 209c1920a3f..1feeed03d15 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkRequest.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkRequest.java
@@ -69,6 +69,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* site. Instances of these requests will be constructed and passed to all
* {@link GuardingDynamicLinker} objects managed by the {@link DynamicLinker}
* that is trying to link the call site.
+ * @since 9
*/
public interface LinkRequest {
/**
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkerServices.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkerServices.java
index e66babebf33..5a028205676 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkerServices.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkerServices.java
@@ -73,6 +73,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
/**
* Interface for services provided to {@link GuardingDynamicLinker} instances by
* the {@link DynamicLinker} that owns them.
+ * @since 9
*/
public interface LinkerServices {
/**
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodHandleTransformer.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodHandleTransformer.java
index 2af6294c517..e9ccd30ffed 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodHandleTransformer.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodHandleTransformer.java
@@ -68,6 +68,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* Typical usage is for implementing
* {@link DynamicLinkerFactory#setInternalObjectsFilter(MethodHandleTransformer)
* internal objects filters}.
+ * @since 9
*/
@FunctionalInterface
public interface MethodHandleTransformer {
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodTypeConversionStrategy.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodTypeConversionStrategy.java
index b830e375c12..394f81858ff 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodTypeConversionStrategy.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodTypeConversionStrategy.java
@@ -70,6 +70,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* of
* {@link DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy)
* method invocation conversions}.
+ * @since 9
*/
@FunctionalInterface
public interface MethodTypeConversionStrategy {
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java
index 53c1a66e862..1565cfee552 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java
@@ -68,6 +68,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* linkers will fall into this category, as they recognize their native objects as Java objects of classes implementing
* a specific language-native interface or superclass. The linker mechanism can optimize the dispatch for these linkers,
* see {@link CompositeTypeBasedGuardingDynamicLinker}.
+ * @since 9
*/
public interface TypeBasedGuardingDynamicLinker extends GuardingDynamicLinker {
/**
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeGuardingDynamicLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeGuardingDynamicLinker.java
index 8ae1f4754cf..c226a9c0b17 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeGuardingDynamicLinker.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeGuardingDynamicLinker.java
@@ -72,6 +72,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* A {@link GuardingDynamicLinker} that delegates sequentially to a list of
* other guarding dynamic linkers in its
* {@link #getGuardedInvocation(LinkRequest, LinkerServices)}.
+ * @since 9
*/
public class CompositeGuardingDynamicLinker implements GuardingDynamicLinker {
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java
index 184cc8e0ab8..a0805ff57d6 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java
@@ -77,6 +77,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* returning true are then bound to the class, and next time a receiver of same
* type is encountered, the linking is delegated to those linkers only, speeding
* up dispatch.
+ * @since 9
*/
public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardingDynamicLinker {
// Using a separate static class instance so there's no strong reference from the class value back to the composite
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/DefaultInternalObjectFilter.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/DefaultInternalObjectFilter.java
index 9929eeb7e50..7a43f7ebbc0 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/DefaultInternalObjectFilter.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/DefaultInternalObjectFilter.java
@@ -80,6 +80,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* the parameter filter as being a wrapping method for exposing internal runtime
* objects wrapped into an adapter with some public interface, and the return
* value filter as being its inverse unwrapping method.
+ * @since 9
*/
public class DefaultInternalObjectFilter implements MethodHandleTransformer {
private static final MethodHandle FILTER_VARARGS = new Lookup(MethodHandles.lookup()).findStatic(
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Guards.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Guards.java
index 9a456df5ebe..7b0fd0e156b 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Guards.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Guards.java
@@ -72,6 +72,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* Utility methods for creating typical guards for
* {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}
* and for adjusting their method types.
+ * @since 9
*/
public final class Guards {
private static final Logger LOG = Logger
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java
index ecf66e7d458..25792f0108b 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java
@@ -72,6 +72,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* checked exceptions. It is useful in those cases when you're looking up
* methods within your own codebase (therefore it is an error if they are not
* present).
+ * @since 9
*/
public final class Lookup {
private final MethodHandles.Lookup lookup;
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/SimpleLinkRequest.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/SimpleLinkRequest.java
index d8cfd8a9d9c..7a00b9fe3ea 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/SimpleLinkRequest.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/SimpleLinkRequest.java
@@ -66,6 +66,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
/**
* Default simple implementation of {@link LinkRequest}.
+ * @since 9
*/
public class SimpleLinkRequest implements LinkRequest {
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java
index f5ee9e09093..2a3d667d49a 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java
@@ -70,6 +70,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
/**
* Various static utility methods for working with Java types.
+ * @since 9
*/
public final class TypeUtilities {
private TypeUtilities() {
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java b/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java
index 03c7b9603f6..1218885ae9a 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java
@@ -60,5 +60,6 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
/**
* Contains interfaces and classes that are used to link an {@code invokedynamic} call site.
+ * @since 9
*/
package jdk.dynalink;
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/support/AbstractRelinkableCallSite.java b/src/jdk.dynalink/share/classes/jdk/dynalink/support/AbstractRelinkableCallSite.java
index dbcf3ffd021..84ecfa1db38 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/support/AbstractRelinkableCallSite.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/support/AbstractRelinkableCallSite.java
@@ -75,6 +75,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* {@link #relink(GuardedInvocation, MethodHandle)} and
* {@link #resetAndRelink(GuardedInvocation, MethodHandle)}
* methods.
+ * @since 9
*/
public abstract class AbstractRelinkableCallSite extends MutableCallSite implements RelinkableCallSite {
private final CallSiteDescriptor descriptor;
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/support/ChainedCallSite.java b/src/jdk.dynalink/share/classes/jdk/dynalink/support/ChainedCallSite.java
index a026512242a..2f75b53fc3d 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/support/ChainedCallSite.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/support/ChainedCallSite.java
@@ -84,6 +84,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* Race conditions in linking are resolved by throwing away the
* {@link GuardedInvocation} produced on the losing thread without incorporating
* it into the chain, so it can lead to repeated linking for the same arguments.
+ * @since 9
*/
public class ChainedCallSite extends AbstractRelinkableCallSite {
private static final MethodHandle PRUNE_CATCHES;
diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java b/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java
index 06f50b4ff80..022d6088d01 100644
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java
@@ -71,6 +71,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* If the guard of that single invocation fails, or it has an invalidated
* switch point, or its invalidating exception triggered, then the call site
* will throw it away and ask its associated {@link DynamicLinker} to relink it.
+ * @since 9
*/
public class SimpleRelinkableCallSite extends AbstractRelinkableCallSite {
/**
From da24559051e716cf73a30bdb1b6ef4b06c45ce43 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?=
Date: Wed, 10 Jan 2024 13:59:27 +0000
Subject: [PATCH 18/66] 8316241: Test jdk/jdk/jfr/jvm/TestChunkIntegrity.java
failed
Reviewed-by: egahlin
Backport-of: b2a39c576706622b624314c89fa6d10d0b422f86
---
.../recorder/checkpoint/types/jfrTypeSet.cpp | 1037 +++++++++--------
.../checkpoint/types/jfrTypeSetUtils.cpp | 30 +-
.../checkpoint/types/jfrTypeSetUtils.hpp | 47 +-
.../traceid/jfrTraceIdLoadBarrier.inline.hpp | 41 +-
.../storage/jfrMemorySpace.inline.hpp | 2 +-
5 files changed, 626 insertions(+), 531 deletions(-)
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
index 94ac0772969..2d49c5aa405 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
@@ -66,20 +66,38 @@ static bool _class_unload = false;
static bool _flushpoint = false;
static bool _initial_type_set = true;
-static bool current_epoch() {
- return _class_unload || _flushpoint;
+static inline bool flushpoint() {
+ return _flushpoint;
}
-static bool previous_epoch() {
+static inline bool unloading() {
+ return _class_unload;
+}
+
+static inline bool current_epoch() {
+ return flushpoint() || unloading();
+}
+
+static inline bool previous_epoch() {
return !current_epoch();
}
-static bool is_initial_typeset_for_chunk() {
- return _initial_type_set && !_class_unload;
+template
+static inline bool used(const T* ptr) {
+ assert(ptr != nullptr, "invariant");
+ return current_epoch() ? USED_THIS_EPOCH(ptr) : USED_PREVIOUS_EPOCH(ptr);
+}
+
+template
+static inline bool not_used(const T* ptr) {
+ return !used(ptr);
}
-static bool is_complete() {
- return !_artifacts->has_klass_entries() && current_epoch();
+template
+static void do_artifact(const T* ptr) {
+ if (used(ptr)) {
+ _subsystem_callback->do_artifact(ptr);
+ }
}
static traceid mark_symbol(KlassPtr klass, bool leakp) {
@@ -94,66 +112,107 @@ static traceid get_bootstrap_name(bool leakp) {
return _artifacts->bootstrap_name(leakp);
}
-static const char* primitive_name(KlassPtr type_array_klass) {
- switch (type_array_klass->name()->base()[1]) {
- case JVM_SIGNATURE_BOOLEAN: return "boolean";
- case JVM_SIGNATURE_BYTE: return "byte";
- case JVM_SIGNATURE_CHAR: return "char";
- case JVM_SIGNATURE_SHORT: return "short";
- case JVM_SIGNATURE_INT: return "int";
- case JVM_SIGNATURE_LONG: return "long";
- case JVM_SIGNATURE_FLOAT: return "float";
- case JVM_SIGNATURE_DOUBLE: return "double";
+template
+static traceid artifact_id(const T* ptr) {
+ assert(ptr != nullptr, "invariant");
+ return JfrTraceId::load_raw(ptr);
+}
+
+template
+static traceid artifact_tag(const T* ptr, bool leakp) {
+ assert(ptr != nullptr, "invariant");
+ if (leakp) {
+ if (IS_NOT_LEAKP(ptr)) {
+ SET_LEAKP(ptr);
+ }
+ assert(IS_LEAKP(ptr), "invariant");
+ return artifact_id(ptr);
}
- assert(false, "invalid type array klass");
- return nullptr;
+ if (not_used(ptr)) {
+ SET_TRANSIENT(ptr);
+ }
+ assert(used(ptr), "invariant");
+ return artifact_id(ptr);
}
-static Symbol* primitive_symbol(KlassPtr type_array_klass) {
- if (type_array_klass == nullptr) {
- // void.class
- static Symbol* const void_class_name = SymbolTable::probe("void", 4);
- assert(void_class_name != nullptr, "invariant");
- return void_class_name;
+static inline bool should_do_cld_klass(const Klass* klass, bool leakp) {
+ return klass != nullptr && _artifacts->should_do_cld_klass(klass, leakp);
+}
+
+static inline KlassPtr get_cld_klass(CldPtr cld, bool leakp) {
+ if (cld == nullptr) {
+ return nullptr;
}
- const char* const primitive_type_str = primitive_name(type_array_klass);
- assert(primitive_type_str != nullptr, "invariant");
- Symbol* const primitive_type_sym = SymbolTable::probe(primitive_type_str, (int)strlen(primitive_type_str));
- assert(primitive_type_sym != nullptr, "invariant");
- return primitive_type_sym;
+ assert(leakp ? IS_LEAKP(cld) : used(cld), "invariant");
+ KlassPtr cld_klass = cld->class_loader_klass();
+ if (cld_klass == nullptr) {
+ return nullptr;
+ }
+ if (should_do_cld_klass(cld_klass, leakp)) {
+ if (current_epoch()) {
+ // This will enqueue the klass, which is important for
+ // reachability when doing clear and reset at rotation.
+ JfrTraceId::load(cld_klass);
+ } else {
+ artifact_tag(cld_klass, leakp);
+ }
+ return cld_klass;
+ }
+ return nullptr;
}
-template
-static traceid artifact_id(const T* ptr) {
- assert(ptr != nullptr, "invariant");
- return JfrTraceId::load_raw(ptr);
+static inline CldPtr get_cld(ModPtr mod) {
+ return mod != nullptr ? mod->loader_data() : nullptr;
}
-static traceid package_id(KlassPtr klass, bool leakp) {
+static ClassLoaderData* get_cld(const Klass* klass) {
assert(klass != nullptr, "invariant");
- PkgPtr pkg_entry = klass->package();
- if (pkg_entry == nullptr) {
- return 0;
- }
- if (leakp) {
- SET_LEAKP(pkg_entry);
+ if (klass->is_objArray_klass()) {
+ klass = ObjArrayKlass::cast(klass)->bottom_klass();
}
- // package implicitly tagged already
- return artifact_id(pkg_entry);
+ return klass->is_non_strong_hidden() ? nullptr : klass->class_loader_data();
+}
+
+static inline ModPtr get_module(PkgPtr pkg) {
+ return pkg != nullptr ? pkg->module() : nullptr;
+}
+
+static inline PkgPtr get_package(KlassPtr klass) {
+ return klass != nullptr ? klass->package() : nullptr;
+}
+
+static inline KlassPtr get_module_cld_klass(KlassPtr klass, bool leakp) {
+ assert(klass != nullptr, "invariant");
+ return get_cld_klass(get_cld(get_module(get_package(klass))), leakp);
+}
+
+static traceid cld_id(CldPtr cld, bool leakp) {
+ assert(cld != nullptr, "invariant");
+ return artifact_tag(cld, leakp);
}
static traceid module_id(PkgPtr pkg, bool leakp) {
assert(pkg != nullptr, "invariant");
- ModPtr module_entry = pkg->module();
- if (module_entry == nullptr) {
+ ModPtr mod = get_module(pkg);
+ if (mod == nullptr) {
return 0;
}
- if (leakp) {
- SET_LEAKP(module_entry);
- } else {
- SET_TRANSIENT(module_entry);
+ CldPtr cld = get_cld(mod);
+ if (cld != nullptr) {
+ cld_id(cld, leakp);
}
- return artifact_id(module_entry);
+ return artifact_tag(mod, leakp);
+}
+
+static traceid package_id(KlassPtr klass, bool leakp) {
+ assert(klass != nullptr, "invariant");
+ PkgPtr pkg = get_package(klass);
+ if (pkg == nullptr) {
+ return 0;
+ }
+ // Ensure module and its CLD gets tagged.
+ module_id(pkg, leakp);
+ return artifact_tag(pkg, leakp);
}
static traceid method_id(KlassPtr klass, MethodPtr method) {
@@ -162,16 +221,6 @@ static traceid method_id(KlassPtr klass, MethodPtr method) {
return METHOD_ID(klass, method);
}
-static traceid cld_id(CldPtr cld, bool leakp) {
- assert(cld != nullptr, "invariant");
- if (leakp) {
- SET_LEAKP(cld);
- } else {
- SET_TRANSIENT(cld);
- }
- return artifact_id(cld);
-}
-
template
static s4 get_flags(const T* ptr) {
assert(ptr != nullptr, "invariant");
@@ -183,73 +232,203 @@ static u4 get_primitive_flags() {
return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC;
}
-static ClassLoaderData* get_cld(const Klass* klass) {
- assert(klass != nullptr, "invariant");
- if (klass->is_objArray_klass()) {
- klass = ObjArrayKlass::cast(klass)->bottom_klass();
+class PackageFieldSelector {
+ public:
+ typedef PkgPtr TypePtr;
+ static TypePtr select(KlassPtr klass) {
+ assert(klass != nullptr, "invariant");
+ return klass->package();
}
- if (klass->is_non_strong_hidden()) return nullptr;
- return klass->class_loader_data();
-}
+};
+
+class ModuleFieldSelector {
+ public:
+ typedef ModPtr TypePtr;
+ static TypePtr select(KlassPtr klass) {
+ assert(klass != nullptr, "invariant");
+ PkgPtr pkg = klass->package();
+ return pkg != nullptr ? pkg->module() : nullptr;
+ }
+};
+
+class KlassCldFieldSelector {
+ public:
+ typedef CldPtr TypePtr;
+ static TypePtr select(KlassPtr klass) {
+ assert(klass != nullptr, "invariant");
+ return get_cld(klass);
+ }
+};
+
+class ModuleCldFieldSelector {
+ public:
+ typedef CldPtr TypePtr;
+ static TypePtr select(KlassPtr klass) {
+ assert(klass != nullptr, "invariant");
+ ModPtr mod = ModuleFieldSelector::select(klass);
+ return mod != nullptr ? mod->loader_data() : nullptr;
+ }
+};
+
+template
+class SerializePredicate {
+ bool _class_unload;
+ public:
+ SerializePredicate(bool class_unload) : _class_unload(class_unload) {}
+ bool operator()(T const& value) {
+ assert(value != nullptr, "invariant");
+ return _class_unload ? _artifacts->should_do_unloading_artifact(value) : IS_NOT_SERIALIZED(value);
+ }
+};
+
+template <>
+class SerializePredicate {
+ bool _class_unload;
+public:
+ SerializePredicate(bool class_unload) : _class_unload(class_unload) {}
+ bool operator()(const Klass* klass) {
+ assert(klass != nullptr, "invariant");
+ return _class_unload ? true : IS_NOT_SERIALIZED(klass);
+ }
+};
+
+template <>
+class SerializePredicate {
+ bool _class_unload;
+public:
+ SerializePredicate(bool class_unload) : _class_unload(class_unload) {}
+ bool operator()(const Method* method) {
+ assert(method != nullptr, "invariant");
+ return _class_unload ? true : METHOD_IS_NOT_SERIALIZED(method);
+ }
+};
template
static void set_serialized(const T* ptr) {
assert(ptr != nullptr, "invariant");
- SET_SERIALIZED(ptr);
- assert(IS_SERIALIZED(ptr), "invariant");
if (current_epoch()) {
CLEAR_THIS_EPOCH_CLEARED_BIT(ptr);
}
+ SET_SERIALIZED(ptr);
+ assert(IS_SERIALIZED(ptr), "invariant");
}
/*
- * In C++03, functions used as template parameters must have external linkage;
- * this restriction was removed in C++11. Change back to "static" and
- * rename functions when C++11 becomes available.
+ *********************** Klasses *************************
+ *
+ * When we process a Klass, we need to process its transitive closure.
+ *
+ * This includes two branches:
+ *
+ * [1] Klass -> CLD -> class_loader_Klass
+ * [2] Klass -> PackageEntry -> ModuleEntry -> CLD -> class_loader_Klass
+ *
+ * A Klass viewed as this closure becomes a node in a binary tree:
+ *
+ * Klass
+ * O
+ * / \
+ * / \
+ * [1] O O [2]
+ *
+ * We write the Klass and tag the artifacts in its closure (subtree)
+ * using preorder traversal by recursing the class_loader_Klass(es).
*
- * The weird naming is an effort to decrease the risk of name clashes.
*/
-static int write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp) {
+static void do_write_klass(JfrCheckpointWriter* writer, CldPtr cld, KlassPtr klass, bool leakp) {
assert(writer != nullptr, "invariant");
assert(_artifacts != nullptr, "invariant");
assert(klass != nullptr, "invariant");
writer->write(artifact_id(klass));
- ClassLoaderData* cld = get_cld(klass);
writer->write(cld != nullptr ? cld_id(cld, leakp) : 0);
writer->write(mark_symbol(klass, leakp));
writer->write(package_id(klass, leakp));
writer->write(klass->modifier_flags());
writer->write(klass->is_hidden());
- return 1;
+ if (!leakp) {
+ set_serialized(klass);
+ }
+}
+
+static inline bool should_write_cld_klass(KlassPtr klass, bool leakp) {
+ return klass != nullptr && (leakp || IS_NOT_SERIALIZED(klass));
+}
+
+static void write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp, int& elements) {
+ assert(elements >= 0, "invariant");
+ ClassLoaderData* cld = get_cld(klass);
+ do_write_klass(writer, cld, klass, leakp);
+ ++elements;
+ if (cld != nullptr) {
+ // Write the klass for the direct cld.
+ KlassPtr cld_klass = get_cld_klass(cld, leakp);
+ if (should_write_cld_klass(cld_klass, leakp)) {
+ write_klass(writer, cld_klass, leakp, elements);
+ }
+ }
+ KlassPtr mod_klass = get_module_cld_klass(klass, leakp);
+ if (should_write_cld_klass(mod_klass, leakp)) {
+ // Write the klass for the module cld.
+ write_klass(writer, mod_klass, leakp, elements);
+ }
}
+/*
+ * In C++03, functions used as template parameters must have external linkage;
+ * this restriction was removed in C++11. Change back to "static" and
+ * rename functions when C++11 becomes available.
+ *
+ * The weird naming is an effort to decrease the risk of name clashes.
+ */
int write__klass(JfrCheckpointWriter* writer, const void* k) {
assert(k != nullptr, "invariant");
- KlassPtr klass = (KlassPtr)k;
- set_serialized(klass);
- return write_klass(writer, klass, false);
+ KlassPtr klass = static_cast(k);
+ int elements = 0;
+ write_klass(writer, klass, false, elements);
+ return elements;
}
int write__klass__leakp(JfrCheckpointWriter* writer, const void* k) {
assert(k != nullptr, "invariant");
- KlassPtr klass = (KlassPtr)k;
+ KlassPtr klass = static_cast(k);
CLEAR_LEAKP(klass);
- return write_klass(writer, klass, true);
+ int elements = 0;
+ write_klass(writer, klass, true, elements);
+ return elements;
}
-static bool is_implied(const Klass* klass) {
- assert(klass != nullptr, "invariant");
- return klass->is_subclass_of(vmClasses::ClassLoader_klass()) || klass == vmClasses::Object_klass();
-}
+static int primitives_count = 9;
-static void do_klass(Klass* klass) {
- assert(klass != nullptr, "invariant");
- assert(_flushpoint ? USED_THIS_EPOCH(klass) : USED_PREVIOUS_EPOCH(klass), "invariant");
- assert(_subsystem_callback != nullptr, "invariant");
- _subsystem_callback->do_artifact(klass);
+static const char* primitive_name(KlassPtr type_array_klass) {
+ switch (type_array_klass->name()->base()[1]) {
+ case JVM_SIGNATURE_BOOLEAN: return "boolean";
+ case JVM_SIGNATURE_BYTE: return "byte";
+ case JVM_SIGNATURE_CHAR: return "char";
+ case JVM_SIGNATURE_SHORT: return "short";
+ case JVM_SIGNATURE_INT: return "int";
+ case JVM_SIGNATURE_LONG: return "long";
+ case JVM_SIGNATURE_FLOAT: return "float";
+ case JVM_SIGNATURE_DOUBLE: return "double";
+ }
+ assert(false, "invalid type array klass");
+ return nullptr;
}
+static Symbol* primitive_symbol(KlassPtr type_array_klass) {
+ if (type_array_klass == nullptr) {
+ // void.class
+ static Symbol* const void_class_name = SymbolTable::probe("void", 4);
+ assert(void_class_name != nullptr, "invariant");
+ return void_class_name;
+ }
+ const char* const primitive_type_str = primitive_name(type_array_klass);
+ assert(primitive_type_str != nullptr, "invariant");
+ Symbol* const primitive_type_sym = SymbolTable::probe(primitive_type_str,
+ (int)strlen(primitive_type_str));
+ assert(primitive_type_sym != nullptr, "invariant");
+ return primitive_type_sym;
+}
static traceid primitive_id(KlassPtr array_klass) {
if (array_klass == nullptr) {
@@ -271,148 +450,69 @@ static void write_primitive(JfrCheckpointWriter* writer, KlassPtr type_array_kla
writer->write(false);
}
-static void do_loader_klass(const Klass* klass) {
- if (klass != nullptr && _artifacts->should_do_loader_klass(klass)) {
- if (_leakp_writer != nullptr) {
- SET_LEAKP(klass);
- }
- SET_TRANSIENT(klass);
- _subsystem_callback->do_artifact(klass);
- }
-}
-
-static bool register_klass_unload(Klass* klass) {
- assert(klass != nullptr, "invariant");
- return JfrKlassUnloading::on_unload(klass);
-}
-
-static void do_unloading_klass(Klass* klass) {
- assert(klass != nullptr, "invariant");
- assert(_subsystem_callback != nullptr, "invariant");
- if (register_klass_unload(klass)) {
- _subsystem_callback->do_artifact(klass);
- do_loader_klass(klass->class_loader_data()->class_loader_klass());
- }
-}
-
-/*
- * Abstract klasses are filtered out unconditionally.
- * If a klass is not yet initialized, i.e yet to run its
- * it is also filtered out so we don't accidentally
- * trigger initialization.
- */
-static bool is_classloader_klass_allowed(const Klass* k) {
- assert(k != nullptr, "invariant");
- return !(k->is_abstract() || k->should_be_initialized());
-}
-
-static void do_classloaders() {
- for (ClassHierarchyIterator iter(vmClasses::ClassLoader_klass()); !iter.done(); iter.next()) {
- Klass* subk = iter.klass();
- if (is_classloader_klass_allowed(subk)) {
- do_loader_klass(subk);
- }
- }
+static bool is_initial_typeset_for_chunk() {
+ return _initial_type_set && !unloading();
}
-static int primitives_count = 9;
-
// A mirror representing a primitive class (e.g. int.class) has no reified Klass*,
// instead it has an associated TypeArrayKlass* (e.g. int[].class).
// We can use the TypeArrayKlass* as a proxy for deriving the id of the primitive class.
// The exception is the void.class, which has neither a Klass* nor a TypeArrayKlass*.
// It will use a reserved constant.
static void do_primitives() {
- // Only write the primitive classes once per chunk.
- if (is_initial_typeset_for_chunk()) {
- write_primitive(_writer, Universe::boolArrayKlassObj());
- write_primitive(_writer, Universe::byteArrayKlassObj());
- write_primitive(_writer, Universe::charArrayKlassObj());
- write_primitive(_writer, Universe::shortArrayKlassObj());
- write_primitive(_writer, Universe::intArrayKlassObj());
- write_primitive(_writer, Universe::longArrayKlassObj());
- write_primitive(_writer, Universe::floatArrayKlassObj());
- write_primitive(_writer, Universe::doubleArrayKlassObj());
- write_primitive(_writer, nullptr); // void.class
- }
+ assert(is_initial_typeset_for_chunk(), "invariant");
+ write_primitive(_writer, Universe::boolArrayKlassObj());
+ write_primitive(_writer, Universe::byteArrayKlassObj());
+ write_primitive(_writer, Universe::charArrayKlassObj());
+ write_primitive(_writer, Universe::shortArrayKlassObj());
+ write_primitive(_writer, Universe::intArrayKlassObj());
+ write_primitive(_writer, Universe::longArrayKlassObj());
+ write_primitive(_writer, Universe::floatArrayKlassObj());
+ write_primitive(_writer, Universe::doubleArrayKlassObj());
+ write_primitive(_writer, nullptr); // void.class
}
-static void do_object() {
- SET_TRANSIENT(vmClasses::Object_klass());
- do_klass(vmClasses::Object_klass());
-}
-
-static void do_klasses() {
- if (_class_unload) {
- ClassLoaderDataGraph::classes_unloading_do(&do_unloading_klass);
- return;
- }
- JfrTraceIdLoadBarrier::do_klasses(&do_klass, previous_epoch());
- do_classloaders();
- do_primitives();
- do_object();
-}
-
-template
-static void do_previous_epoch_artifact(JfrArtifactClosure* callback, T* value) {
- assert(callback != nullptr, "invariant");
- assert(value != nullptr, "invariant");
- if (USED_PREVIOUS_EPOCH(value)) {
- callback->do_artifact(value);
- }
- if (IS_SERIALIZED(value)) {
- CLEAR_SERIALIZED(value);
- }
- assert(IS_NOT_SERIALIZED(value), "invariant");
-}
-
-static void do_previous_epoch_klass(JfrArtifactClosure* callback, const Klass* value) {
- assert(callback != nullptr, "invariant");
- assert(value != nullptr, "invariant");
- if (USED_PREVIOUS_EPOCH(value)) {
- callback->do_artifact(value);
+static void do_unloading_klass(Klass* klass) {
+ assert(klass != nullptr, "invariant");
+ assert(_subsystem_callback != nullptr, "invariant");
+ if (JfrKlassUnloading::on_unload(klass)) {
+ _subsystem_callback->do_artifact(klass);
}
}
-static void do_klass_on_clear(Klass* klass) {
+static void do_klass(Klass* klass) {
assert(klass != nullptr, "invariant");
+ assert(used(klass), "invariant");
assert(_subsystem_callback != nullptr, "invariant");
- do_previous_epoch_klass(_subsystem_callback, klass);
+ _subsystem_callback->do_artifact(klass);
}
-static void do_loader_klass_on_clear(const Klass* klass) {
- if (klass != nullptr && _artifacts->should_do_loader_klass(klass)) {
- if (_leakp_writer != nullptr) {
- SET_LEAKP(klass);
- }
- SET_TRANSIENT(klass);
- do_previous_epoch_klass(_subsystem_callback, klass);
+static void do_klasses() {
+ if (unloading()) {
+ ClassLoaderDataGraph::classes_unloading_do(&do_unloading_klass);
+ return;
}
-}
-
-static void do_classloaders_on_clear() {
- for (ClassHierarchyIterator iter(vmClasses::ClassLoader_klass()); !iter.done(); iter.next()) {
- Klass* subk = iter.klass();
- if (is_classloader_klass_allowed(subk)) {
- do_loader_klass_on_clear(subk);
- }
+ if (is_initial_typeset_for_chunk()) {
+ // Only write the primitive classes once per chunk.
+ do_primitives();
}
+ JfrTraceIdLoadBarrier::do_klasses(&do_klass, previous_epoch());
}
-static void do_object_on_clear() {
- SET_TRANSIENT(vmClasses::Object_klass());
- do_klass_on_clear(vmClasses::Object_klass());
+static void do_klass_on_clear(Klass* klass) {
+ do_artifact(klass);
}
static void do_all_klasses() {
ClassLoaderDataGraph::classes_do(&do_klass_on_clear);
- do_classloaders_on_clear();
- do_object_on_clear();
}
+// KlassWriter.
typedef SerializePredicate KlassPredicate;
typedef JfrPredicatedTypeWriterImplHost KlassWriterImpl;
typedef JfrTypeWriterHost KlassWriter;
+
+// Klass registration.
typedef CompositeFunctor KlassWriterRegistration;
typedef JfrArtifactCallbackHost KlassCallback;
@@ -422,29 +522,31 @@ class LeakPredicate {
LeakPredicate(bool class_unload) {}
bool operator()(const Klass* klass) {
assert(klass != nullptr, "invariant");
- return IS_LEAKP(klass) || is_implied(klass);
+ return IS_LEAKP(klass);
}
};
+// KlassWriter for leakp. Only used during start or rotation, i.e. the previous epoch.
typedef LeakPredicate LeakKlassPredicate;
typedef JfrPredicatedTypeWriterImplHost LeakKlassWriterImpl;
typedef JfrTypeWriterHost LeakKlassWriter;
+// Composite KlassWriter with registration.
typedef CompositeFunctor CompositeKlassWriter;
typedef CompositeFunctor CompositeKlassWriterRegistration;
typedef JfrArtifactCallbackHost CompositeKlassCallback;
-static bool write_klasses() {
+static void write_klasses() {
assert(!_artifacts->has_klass_entries(), "invariant");
assert(_writer != nullptr, "invariant");
KlassArtifactRegistrator reg(_artifacts);
- KlassWriter kw(_writer, _class_unload);
+ KlassWriter kw(_writer, unloading());
KlassWriterRegistration kwr(&kw, ®);
if (_leakp_writer == nullptr) {
KlassCallback callback(&_subsystem_callback, &kwr);
do_klasses();
} else {
- LeakKlassWriter lkw(_leakp_writer, _class_unload);
+ LeakKlassWriter lkw(_leakp_writer, unloading());
CompositeKlassWriter ckw(&lkw, &kw);
CompositeKlassWriterRegistration ckwr(&ckw, ®);
CompositeKlassCallback callback(&_subsystem_callback, &ckwr);
@@ -455,32 +557,26 @@ static bool write_klasses() {
// their count is not automatically incremented.
kw.add(primitives_count);
}
- if (is_complete()) {
- return false;
- }
_artifacts->tally(kw);
- return true;
}
-static bool write_klasses_on_clear() {
+static void write_klasses_on_clear() {
assert(!_artifacts->has_klass_entries(), "invariant");
assert(_writer != nullptr, "invariant");
assert(_leakp_writer != nullptr, "invariant");
KlassArtifactRegistrator reg(_artifacts);
- KlassWriter kw(_writer, _class_unload);
+ KlassWriter kw(_writer, unloading());
KlassWriterRegistration kwr(&kw, ®);
- LeakKlassWriter lkw(_leakp_writer, _class_unload);
+ LeakKlassWriter lkw(_leakp_writer, unloading());
CompositeKlassWriter ckw(&lkw, &kw);
CompositeKlassWriterRegistration ckwr(&ckw, ®);
CompositeKlassCallback callback(&_subsystem_callback, &ckwr);
do_all_klasses();
- if (is_complete()) {
- return false;
- }
_artifacts->tally(kw);
- return true;
}
+/***** Packages *****/
+
static int write_package(JfrCheckpointWriter* writer, PkgPtr pkg, bool leakp) {
assert(writer != nullptr, "invariant");
assert(_artifacts != nullptr, "invariant");
@@ -494,98 +590,101 @@ static int write_package(JfrCheckpointWriter* writer, PkgPtr pkg, bool leakp) {
int write__package(JfrCheckpointWriter* writer, const void* p) {
assert(p != nullptr, "invariant");
- PkgPtr pkg = (PkgPtr)p;
+ PkgPtr pkg = static_cast(p);
set_serialized(pkg);
return write_package(writer, pkg, false);
}
int write__package__leakp(JfrCheckpointWriter* writer, const void* p) {
assert(p != nullptr, "invariant");
- PkgPtr pkg = (PkgPtr)p;
+ PkgPtr pkg = static_cast(p);
CLEAR_LEAKP(pkg);
return write_package(writer, pkg, true);
}
-static void do_package(PackageEntry* entry) {
- do_previous_epoch_artifact(_subsystem_callback, entry);
-}
-
-static void do_packages() {
- ClassLoaderDataGraph::packages_do(&do_package);
-}
-
-class PackageFieldSelector {
- public:
- typedef PkgPtr TypePtr;
- static TypePtr select(KlassPtr klass) {
- assert(klass != nullptr, "invariant");
- return klass->package();
- }
-};
+// PackageWriter.
typedef SerializePredicate PackagePredicate;
typedef JfrPredicatedTypeWriterImplHost PackageWriterImpl;
typedef JfrTypeWriterHost PackageWriter;
-typedef CompositeFunctor > PackageWriterWithClear;
+typedef JfrArtifactCallbackHost PackageCallback;
+
+// PackageWriter used during flush or unloading i.e. the current epoch.
typedef KlassToFieldEnvelope KlassPackageWriter;
-typedef JfrArtifactCallbackHost PackageCallback;
+// PackageWriter with clear. Only used during start or rotation, i.e. the previous epoch.
+typedef CompositeFunctor > PackageWriterWithClear;
+typedef JfrArtifactCallbackHost PackageClearCallback;
+
+// PackageWriter for leakp. Only used during start or rotation, i.e. the previous epoch.
typedef LeakPredicate LeakPackagePredicate;
typedef JfrPredicatedTypeWriterImplHost LeakPackageWriterImpl;
typedef JfrTypeWriterHost LeakPackageWriter;
+// Composite PackageWriter with clear. Only used during start or rotation, i.e. the previous epoch.
typedef CompositeFunctor CompositePackageWriter;
-typedef KlassToFieldEnvelope KlassCompositePackageWriter;
-typedef KlassToFieldEnvelope KlassPackageWriterWithClear;
typedef CompositeFunctor > CompositePackageWriterWithClear;
-typedef JfrArtifactCallbackHost CompositePackageCallback;
+typedef JfrArtifactCallbackHost CompositePackageClearCallback;
+
+static void do_package(PackageEntry* pkg) {
+ do_artifact(pkg);
+}
+
+static void do_all_packages() {
+ ClassLoaderDataGraph::packages_do(&do_package);
+}
+
+static void do_all_packages(PackageWriter& pw) {
+ do_all_packages();
+ _artifacts->tally(pw);
+}
+
+static void do_packages(PackageWriter& pw) {
+ KlassPackageWriter kpw(&pw);
+ _artifacts->iterate_klasses(kpw);
+ _artifacts->tally(pw);
+}
+
+static void write_packages_with_leakp(PackageWriter& pw) {
+ assert(_writer != nullptr, "invariant");
+ assert(_leakp_writer != nullptr, "invariant");
+ assert(previous_epoch(), "invariant");
+ LeakPackageWriter lpw(_leakp_writer, unloading());
+ CompositePackageWriter cpw(&lpw, &pw);
+ ClearArtifact clear;
+ CompositePackageWriterWithClear cpwwc(&cpw, &clear);
+ CompositePackageClearCallback callback(&_subsystem_callback, &cpwwc);
+ do_all_packages(pw);
+}
static void write_packages() {
assert(_writer != nullptr, "invariant");
- PackageWriter pw(_writer, _class_unload);
- KlassPackageWriter kpw(&pw);
+ PackageWriter pw(_writer, unloading());
if (current_epoch()) {
- _artifacts->iterate_klasses(kpw);
- _artifacts->tally(pw);
+ do_packages(pw);
return;
}
assert(previous_epoch(), "invariant");
if (_leakp_writer == nullptr) {
- _artifacts->iterate_klasses(kpw);
ClearArtifact clear;
PackageWriterWithClear pwwc(&pw, &clear);
- PackageCallback callback(&_subsystem_callback, &pwwc);
- do_packages();
- } else {
- LeakPackageWriter lpw(_leakp_writer, _class_unload);
- CompositePackageWriter cpw(&lpw, &pw);
- KlassCompositePackageWriter kcpw(&cpw);
- _artifacts->iterate_klasses(kcpw);
- ClearArtifact clear;
- CompositePackageWriterWithClear cpwwc(&cpw, &clear);
- CompositePackageCallback callback(&_subsystem_callback, &cpwwc);
- do_packages();
+ PackageClearCallback callback(&_subsystem_callback, &pwwc);
+ do_all_packages(pw);
+ return;
}
- _artifacts->tally(pw);
+ write_packages_with_leakp(pw);
}
static void write_packages_on_clear() {
assert(_writer != nullptr, "invariant");
assert(_leakp_writer != nullptr, "invariant");
assert(previous_epoch(), "invariant");
- PackageWriter pw(_writer, _class_unload);
- KlassPackageWriter kpw(&pw);
- LeakPackageWriter lpw(_leakp_writer, _class_unload);
- CompositePackageWriter cpw(&lpw, &pw);
- KlassCompositePackageWriter kcpw(&cpw);
- _artifacts->iterate_klasses(kcpw);
- ClearArtifact clear;
- CompositePackageWriterWithClear cpwwc(&cpw, &clear);
- CompositePackageCallback callback(&_subsystem_callback, &cpwwc);
- do_packages();
- _artifacts->tally(pw);
+ PackageWriter pw(_writer, unloading());
+ write_packages_with_leakp(pw);
}
+/***** Modules *****/
+
static int write_module(JfrCheckpointWriter* writer, ModPtr mod, bool leakp) {
assert(mod != nullptr, "invariant");
assert(_artifacts != nullptr, "invariant");
@@ -599,99 +698,101 @@ static int write_module(JfrCheckpointWriter* writer, ModPtr mod, bool leakp) {
int write__module(JfrCheckpointWriter* writer, const void* m) {
assert(m != nullptr, "invariant");
- ModPtr mod = (ModPtr)m;
+ ModPtr mod = static_cast(m);
set_serialized(mod);
return write_module(writer, mod, false);
}
int write__module__leakp(JfrCheckpointWriter* writer, const void* m) {
assert(m != nullptr, "invariant");
- ModPtr mod = (ModPtr)m;
+ ModPtr mod = static_cast(m);
CLEAR_LEAKP(mod);
return write_module(writer, mod, true);
}
-static void do_module(ModuleEntry* entry) {
- do_previous_epoch_artifact(_subsystem_callback, entry);
-}
-
-static void do_modules() {
- ClassLoaderDataGraph::modules_do(&do_module);
-}
-
-class ModuleFieldSelector {
- public:
- typedef ModPtr TypePtr;
- static TypePtr select(KlassPtr klass) {
- assert(klass != nullptr, "invariant");
- PkgPtr pkg = klass->package();
- return pkg != nullptr ? pkg->module() : nullptr;
- }
-};
-
+// ModuleWriter.
typedef SerializePredicate ModulePredicate;
typedef JfrPredicatedTypeWriterImplHost ModuleWriterImpl;
typedef JfrTypeWriterHost ModuleWriter;
-typedef CompositeFunctor > ModuleWriterWithClear;
-typedef JfrArtifactCallbackHost ModuleCallback;
+typedef JfrArtifactCallbackHost ModuleCallback;
+
+// ModuleWriter used during flush or unloading i.e. the current epoch.
typedef KlassToFieldEnvelope KlassModuleWriter;
+// ModuleWriter with clear. Only used during start or rotation, i.e. the previous epoch.
+typedef CompositeFunctor > ModuleWriterWithClear;
+typedef JfrArtifactCallbackHost ModuleClearCallback;
+
+// ModuleWriter for leakp. Only used during start or rotation, i.e. the previous epoch.
typedef LeakPredicate LeakModulePredicate;
typedef JfrPredicatedTypeWriterImplHost LeakModuleWriterImpl;
typedef JfrTypeWriterHost LeakModuleWriter;
+// Composite ModuleWriter with clear. Only used during start or rotation, i.e. the previous epoch.
typedef CompositeFunctor CompositeModuleWriter;
-typedef KlassToFieldEnvelope KlassCompositeModuleWriter;
typedef CompositeFunctor > CompositeModuleWriterWithClear;
-typedef JfrArtifactCallbackHost CompositeModuleCallback;
+typedef JfrArtifactCallbackHost CompositeModuleClearCallback;
+
+static void do_module(ModuleEntry* mod) {
+ do_artifact(mod);
+}
+
+static void do_all_modules() {
+ ClassLoaderDataGraph::modules_do(&do_module);
+}
+
+static void do_all_modules(ModuleWriter& mw) {
+ do_all_modules();
+ _artifacts->tally(mw);
+}
+
+static void do_modules(ModuleWriter& mw) {
+ KlassModuleWriter kmw(&mw);
+ _artifacts->iterate_klasses(kmw);
+ _artifacts->tally(mw);
+}
+
+static void write_modules_with_leakp(ModuleWriter& mw) {
+ assert(_writer != nullptr, "invariant");
+ assert(_leakp_writer != nullptr, "invariant");
+ assert(previous_epoch(), "invariant");
+ LeakModuleWriter lmw(_leakp_writer, unloading());
+ CompositeModuleWriter cmw(&lmw, &mw);
+ ClearArtifact clear;
+ CompositeModuleWriterWithClear cmwwc(&cmw, &clear);
+ CompositeModuleClearCallback callback(&_subsystem_callback, &cmwwc);
+ do_all_modules(mw);
+}
static void write_modules() {
assert(_writer != nullptr, "invariant");
- ModuleWriter mw(_writer, _class_unload);
- KlassModuleWriter kmw(&mw);
+ ModuleWriter mw(_writer, unloading());
if (current_epoch()) {
- _artifacts->iterate_klasses(kmw);
- _artifacts->tally(mw);
+ do_modules(mw);
return;
}
assert(previous_epoch(), "invariant");
if (_leakp_writer == nullptr) {
- _artifacts->iterate_klasses(kmw);
ClearArtifact clear;
ModuleWriterWithClear mwwc(&mw, &clear);
- ModuleCallback callback(&_subsystem_callback, &mwwc);
- do_modules();
- } else {
- LeakModuleWriter lmw(_leakp_writer, _class_unload);
- CompositeModuleWriter cmw(&lmw, &mw);
- KlassCompositeModuleWriter kcpw(&cmw);
- _artifacts->iterate_klasses(kcpw);
- ClearArtifact clear;
- CompositeModuleWriterWithClear cmwwc(&cmw, &clear);
- CompositeModuleCallback callback(&_subsystem_callback, &cmwwc);
- do_modules();
+ ModuleClearCallback callback(&_subsystem_callback, &mwwc);
+ do_all_modules(mw);
+ return;
}
- _artifacts->tally(mw);
+ write_modules_with_leakp(mw);
}
static void write_modules_on_clear() {
assert(_writer != nullptr, "invariant");
assert(_leakp_writer != nullptr, "invariant");
assert(previous_epoch(), "invariant");
- ModuleWriter mw(_writer, _class_unload);
- KlassModuleWriter kmw(&mw);
- LeakModuleWriter lmw(_leakp_writer, _class_unload);
- CompositeModuleWriter cmw(&lmw, &mw);
- KlassCompositeModuleWriter kcpw(&cmw);
- _artifacts->iterate_klasses(kcpw);
- ClearArtifact clear;
- CompositeModuleWriterWithClear cmwwc(&cmw, &clear);
- CompositeModuleCallback callback(&_subsystem_callback, &cmwwc);
- do_modules();
- _artifacts->tally(mw);
+ ModuleWriter mw(_writer, unloading());
+ write_modules_with_leakp(mw);
}
-static int write_classloader(JfrCheckpointWriter* writer, CldPtr cld, bool leakp) {
+/***** ClassLoaderData - CLD *****/
+
+static int write_cld(JfrCheckpointWriter* writer, CldPtr cld, bool leakp) {
assert(cld != nullptr, "invariant");
// class loader type
const Klass* class_loader_klass = cld->class_loader_klass();
@@ -701,7 +802,7 @@ static int write_classloader(JfrCheckpointWriter* writer, CldPtr cld, bool leakp
writer->write((traceid)0); // class loader type id (absence of)
writer->write(get_bootstrap_name(leakp)); // maps to synthetic name -> "bootstrap"
} else {
- assert(_class_unload ? true : IS_SERIALIZED(class_loader_klass), "invariant");
+ assert(IS_SERIALIZED(class_loader_klass), "invariant");
writer->write(artifact_id(cld)); // class loader instance id
writer->write(artifact_id(class_loader_klass)); // class loader type id
writer->write(mark_symbol(cld->name(), leakp)); // class loader instance name
@@ -709,146 +810,127 @@ static int write_classloader(JfrCheckpointWriter* writer, CldPtr cld, bool leakp
return 1;
}
-int write__classloader(JfrCheckpointWriter* writer, const void* c) {
+int write__cld(JfrCheckpointWriter* writer, const void* c) {
assert(c != nullptr, "invariant");
- CldPtr cld = (CldPtr)c;
+ CldPtr cld = static_cast(c);
set_serialized(cld);
- return write_classloader(writer, cld, false);
+ return write_cld(writer, cld, false);
}
-int write__classloader__leakp(JfrCheckpointWriter* writer, const void* c) {
+int write__cld__leakp(JfrCheckpointWriter* writer, const void* c) {
assert(c != nullptr, "invariant");
- CldPtr cld = (CldPtr)c;
+ CldPtr cld = static_cast(c);
CLEAR_LEAKP(cld);
- return write_classloader(writer, cld, true);
+ return write_cld(writer, cld, true);
}
-static void do_class_loader_data(ClassLoaderData* cld) {
- do_previous_epoch_artifact(_subsystem_callback, cld);
-}
+// CldWriter.
+typedef SerializePredicate CldPredicate;
+typedef JfrPredicatedTypeWriterImplHost CldWriterImpl;
+typedef JfrTypeWriterHost CldWriter;
+typedef JfrArtifactCallbackHost CldCallback;
-class KlassCldFieldSelector {
- public:
- typedef CldPtr TypePtr;
- static TypePtr select(KlassPtr klass) {
- assert(klass != nullptr, "invariant");
- return get_cld(klass);
- }
-};
+// CldWriter used during flush or unloading i.e. the current epoch.
+typedef KlassToFieldEnvelope KlassCldWriter;
+typedef KlassToFieldEnvelope ModuleCldWriter;
+typedef CompositeFunctor KlassAndModuleCldWriter;
-class ModuleCldFieldSelector {
-public:
- typedef CldPtr TypePtr;
- static TypePtr select(KlassPtr klass) {
- assert(klass != nullptr, "invariant");
- ModPtr mod = ModuleFieldSelector::select(klass);
- return mod != nullptr ? mod->loader_data() : nullptr;
- }
-};
+// CldWriter with clear. Only used during start or rotation, i.e. the previous epoch.
+typedef CompositeFunctor > CldWriterWithClear;
+typedef JfrArtifactCallbackHost CldClearCallback;
+
+// CldWriter for leakp. Only used during start or rotation, i.e. the previous epoch.
+typedef LeakPredicate LeakCldPredicate;
+typedef JfrPredicatedTypeWriterImplHost LeakCldWriterImpl;
+typedef JfrTypeWriterHost LeakCldWriter;
+
+// Composite CldWriter with clear. Only used during start or rotation, i.e. the previous epoch.
+typedef CompositeFunctor CompositeCldWriter;
+typedef CompositeFunctor > CompositeCldWriterWithClear;
+typedef JfrArtifactCallbackHost CompositeCldClearCallback;
class CLDCallback : public CLDClosure {
public:
- CLDCallback() {}
void do_cld(ClassLoaderData* cld) {
assert(cld != nullptr, "invariant");
- if (cld->has_class_mirror_holder()) {
- return;
+ if (!cld->has_class_mirror_holder()) {
+ do_artifact(cld);
}
- do_class_loader_data(cld);
}
};
-static void do_class_loaders() {
+static void do_all_clds() {
CLDCallback cld_cb;
ClassLoaderDataGraph::loaded_cld_do(&cld_cb);
}
-typedef SerializePredicate CldPredicate;
-typedef JfrPredicatedTypeWriterImplHost CldWriterImpl;
-typedef JfrTypeWriterHost CldWriter;
-typedef CompositeFunctor > CldWriterWithClear;
-typedef JfrArtifactCallbackHost CldCallback;
-typedef KlassToFieldEnvelope KlassCldWriter;
-typedef KlassToFieldEnvelope ModuleCldWriter;
-typedef CompositeFunctor KlassAndModuleCldWriter;
-
-typedef LeakPredicate LeakCldPredicate;
-typedef JfrPredicatedTypeWriterImplHost LeakCldWriterImpl;
-typedef JfrTypeWriterHost LeakCldWriter;
-
-typedef CompositeFunctor CompositeCldWriter;
-typedef KlassToFieldEnvelope KlassCompositeCldWriter;
-typedef KlassToFieldEnvelope ModuleCompositeCldWriter;
-typedef CompositeFunctor KlassAndModuleCompositeCldWriter;
-typedef CompositeFunctor > CompositeCldWriterWithClear;
-typedef JfrArtifactCallbackHost CompositeCldCallback;
+static void do_all_clds(CldWriter& cldw) {
+ do_all_clds();
+ _artifacts->tally(cldw);
+}
-static void write_classloaders() {
- assert(_writer != nullptr, "invariant");
- CldWriter cldw(_writer, _class_unload);
+static void do_clds(CldWriter& cldw) {
KlassCldWriter kcw(&cldw);
ModuleCldWriter mcw(&cldw);
KlassAndModuleCldWriter kmcw(&kcw, &mcw);
+ _artifacts->iterate_klasses(kmcw);
+ _artifacts->tally(cldw);
+}
+
+static void write_clds_with_leakp(CldWriter& cldw) {
+ assert(_writer != nullptr, "invariant");
+ assert(_leakp_writer != nullptr, "invariant");
+ assert(previous_epoch(), "invariant");
+ LeakCldWriter lcldw(_leakp_writer, unloading());
+ CompositeCldWriter ccldw(&lcldw, &cldw);
+ ClearArtifact clear;
+ CompositeCldWriterWithClear ccldwwc(&ccldw, &clear);
+ CompositeCldClearCallback callback(&_subsystem_callback, &ccldwwc);
+ do_all_clds(cldw);
+}
+
+static void write_clds() {
+ assert(_writer != nullptr, "invariant");
+ CldWriter cldw(_writer, unloading());
if (current_epoch()) {
- _artifacts->iterate_klasses(kmcw);
- _artifacts->tally(cldw);
+ do_clds(cldw);
return;
}
assert(previous_epoch(), "invariant");
if (_leakp_writer == nullptr) {
- _artifacts->iterate_klasses(kmcw);
ClearArtifact clear;
CldWriterWithClear cldwwc(&cldw, &clear);
- CldCallback callback(&_subsystem_callback, &cldwwc);
- do_class_loaders();
- } else {
- LeakCldWriter lcldw(_leakp_writer, _class_unload);
- CompositeCldWriter ccldw(&lcldw, &cldw);
- KlassCompositeCldWriter kccldw(&ccldw);
- ModuleCompositeCldWriter mccldw(&ccldw);
- KlassAndModuleCompositeCldWriter kmccldw(&kccldw, &mccldw);
- _artifacts->iterate_klasses(kmccldw);
- ClearArtifact clear;
- CompositeCldWriterWithClear ccldwwc(&ccldw, &clear);
- CompositeCldCallback callback(&_subsystem_callback, &ccldwwc);
- do_class_loaders();
+ CldClearCallback callback(&_subsystem_callback, &cldwwc);
+ do_all_clds(cldw);
+ return;
}
- _artifacts->tally(cldw);
+ write_clds_with_leakp(cldw);
}
-static void write_classloaders_on_clear() {
+static void write_clds_on_clear() {
assert(_writer != nullptr, "invariant");
assert(_leakp_writer != nullptr, "invariant");
- CldWriter cldw(_writer, _class_unload);
- KlassCldWriter kcw(&cldw);
- ModuleCldWriter mcw(&cldw);
- KlassAndModuleCldWriter kmcw(&kcw, &mcw);
- LeakCldWriter lcldw(_leakp_writer, _class_unload);
- CompositeCldWriter ccldw(&lcldw, &cldw);
- KlassCompositeCldWriter kccldw(&ccldw);
- ModuleCompositeCldWriter mccldw(&ccldw);
- KlassAndModuleCompositeCldWriter kmccldw(&kccldw, &mccldw);
- _artifacts->iterate_klasses(kmccldw);
- ClearArtifact clear;
- CompositeCldWriterWithClear ccldwwc(&ccldw, &clear);
- CompositeCldCallback callback(&_subsystem_callback, &ccldwwc);
- do_class_loaders();
- _artifacts->tally(cldw);
+ assert(previous_epoch(), "invariant");
+ CldWriter cldw(_writer, unloading());
+ write_clds_with_leakp(cldw);
}
-static u1 get_visibility(MethodPtr method) {
- assert(method != nullptr, "invariant");
- return const_cast(method)->is_hidden() ? (u1)1 : (u1)0;
-}
+/***** Methods *****/
template <>
void set_serialized(MethodPtr method) {
assert(method != nullptr, "invariant");
- SET_METHOD_SERIALIZED(method);
- assert(METHOD_IS_SERIALIZED(method), "invariant");
if (current_epoch()) {
CLEAR_THIS_EPOCH_METHOD_CLEARED_BIT(method);
}
+ assert(unloading() ? true : METHOD_IS_NOT_SERIALIZED(method), "invariant");
+ SET_METHOD_SERIALIZED(method);
+ assert(METHOD_IS_SERIALIZED(method), "invariant");
+}
+
+static inline u1 get_visibility(MethodPtr method) {
+ assert(method != nullptr, "invariant");
+ return const_cast(method)->is_hidden() ? (u1)1 : (u1)0;
}
static int write_method(JfrCheckpointWriter* writer, MethodPtr method, bool leakp) {
@@ -857,58 +939,37 @@ static int write_method(JfrCheckpointWriter* writer, MethodPtr method, bool leak
assert(_artifacts != nullptr, "invariant");
KlassPtr klass = method->method_holder();
assert(klass != nullptr, "invariant");
+ assert(used(klass), "invariant");
+ assert(IS_SERIALIZED(klass), "invariant");
writer->write(method_id(klass, method));
writer->write(artifact_id(klass));
writer->write(mark_symbol(method->name(), leakp));
writer->write(mark_symbol(method->signature(), leakp));
- writer->write((u2)get_flags(method));
+ writer->write(static_cast(get_flags(method)));
writer->write(get_visibility(method));
return 1;
}
int write__method(JfrCheckpointWriter* writer, const void* m) {
assert(m != nullptr, "invariant");
- MethodPtr method = (MethodPtr)m;
+ MethodPtr method = static_cast(m);
+ assert(METHOD_IS_NOT_SERIALIZED(method), "invariant");
set_serialized(method);
return write_method(writer, method, false);
}
int write__method__leakp(JfrCheckpointWriter* writer, const void* m) {
assert(m != nullptr, "invariant");
- MethodPtr method = (MethodPtr)m;
+ MethodPtr method = static_cast(m);
CLEAR_LEAKP_METHOD(method);
return write_method(writer, method, true);
}
-
-class BitMapFilter {
- ResourceBitMap _bitmap;
- public:
- explicit BitMapFilter(int length = 0) : _bitmap((size_t)length) {}
- bool operator()(size_t idx) {
- if (_bitmap.size() == 0) {
- return true;
- }
- if (_bitmap.at(idx)) {
- return false;
- }
- _bitmap.set_bit(idx);
- return true;
- }
-};
-
-class AlwaysTrue {
- public:
- explicit AlwaysTrue(int length = 0) {}
- bool operator()(size_t idx) {
- return true;
- }
-};
-
-template
+template
class MethodIteratorHost {
private:
MethodCallback _method_cb;
KlassCallback _klass_cb;
+ KlassUsedPredicate _klass_used_predicate;
MethodUsedPredicate _method_used_predicate;
MethodFlagPredicate _method_flag_predicate;
public:
@@ -918,6 +979,7 @@ class MethodIteratorHost {
bool skip_header = false) :
_method_cb(writer, class_unload, skip_header),
_klass_cb(writer, class_unload, skip_header),
+ _klass_used_predicate(current_epoch),
_method_used_predicate(current_epoch),
_method_flag_predicate(current_epoch) {}
@@ -937,7 +999,7 @@ class MethodIteratorHost {
ik = ik->previous_versions();
}
}
- return _klass_cb(klass);
+ return _klass_used_predicate(klass) ? _klass_cb(klass) : true;
}
int count() const { return _method_cb.count(); }
@@ -964,37 +1026,42 @@ typedef SerializePredicate MethodPredicate;
typedef JfrPredicatedTypeWriterImplHost MethodWriterImplTarget;
typedef Wrapper KlassCallbackStub;
typedef JfrTypeWriterHost MethodWriterImpl;
-typedef MethodIteratorHost MethodWriter;
+typedef MethodIteratorHost MethodWriter;
typedef LeakPredicate LeakMethodPredicate;
typedef JfrPredicatedTypeWriterImplHost LeakMethodWriterImplTarget;
typedef JfrTypeWriterHost LeakMethodWriterImpl;
-typedef MethodIteratorHost LeakMethodWriter;
-typedef MethodIteratorHost LeakMethodWriter;
+typedef MethodIteratorHost LeakMethodWriter;
+typedef MethodIteratorHost LeakMethodWriter;
typedef CompositeFunctor CompositeMethodWriter;
+static void write_methods_with_leakp(MethodWriter& mw) {
+ assert(_writer != nullptr, "invariant");
+ assert(_leakp_writer != nullptr, "invariant");
+ assert(previous_epoch(), "invariant");
+ LeakMethodWriter lpmw(_leakp_writer, current_epoch(), unloading());
+ CompositeMethodWriter cmw(&lpmw, &mw);
+ _artifacts->iterate_klasses(cmw);
+ _artifacts->tally(mw);
+}
+
static void write_methods() {
assert(_writer != nullptr, "invariant");
- MethodWriter mw(_writer, current_epoch(), _class_unload);
+ MethodWriter mw(_writer, current_epoch(), unloading());
if (_leakp_writer == nullptr) {
_artifacts->iterate_klasses(mw);
- } else {
- LeakMethodWriter lpmw(_leakp_writer, current_epoch(), _class_unload);
- CompositeMethodWriter cmw(&lpmw, &mw);
- _artifacts->iterate_klasses(cmw);
+ _artifacts->tally(mw);
+ return;
}
- _artifacts->tally(mw);
+ write_methods_with_leakp(mw);
}
static void write_methods_on_clear() {
assert(_writer != nullptr, "invariant");
assert(_leakp_writer != nullptr, "invariant");
assert(previous_epoch(), "invariant");
- MethodWriter mw(_writer, current_epoch(), _class_unload);
- LeakMethodWriter lpmw(_leakp_writer, current_epoch(), _class_unload);
- CompositeMethodWriter cmw(&lpmw, &mw);
- _artifacts->iterate_klasses(cmw);
- _artifacts->tally(mw);
+ MethodWriter mw(_writer, current_epoch(), unloading());
+ write_methods_with_leakp(mw);
}
template <>
@@ -1022,14 +1089,14 @@ static int write_symbol(JfrCheckpointWriter* writer, SymbolEntryPtr entry, bool
int write__symbol(JfrCheckpointWriter* writer, const void* e) {
assert(e != nullptr, "invariant");
- SymbolEntryPtr entry = (SymbolEntryPtr)e;
+ SymbolEntryPtr entry = static_cast(e);
set_serialized(entry);
return write_symbol(writer, entry, false);
}
int write__symbol__leakp(JfrCheckpointWriter* writer, const void* e) {
assert(e != nullptr, "invariant");
- SymbolEntryPtr entry = (SymbolEntryPtr)e;
+ SymbolEntryPtr entry = static_cast(e);
return write_symbol(writer, entry, true);
}
@@ -1043,14 +1110,14 @@ static int write_string(JfrCheckpointWriter* writer, StringEntryPtr entry, bool
int write__string(JfrCheckpointWriter* writer, const void* e) {
assert(e != nullptr, "invariant");
- StringEntryPtr entry = (StringEntryPtr)e;
+ StringEntryPtr entry = static_cast(e);
set_serialized(entry);
return write_string(writer, entry, false);
}
int write__string__leakp(JfrCheckpointWriter* writer, const void* e) {
assert(e != nullptr, "invariant");
- StringEntryPtr entry = (StringEntryPtr)e;
+ StringEntryPtr entry = static_cast(e);
return write_string(writer, entry, true);
}
@@ -1071,30 +1138,15 @@ typedef JfrTypeWriterHost LeakStringEntr
typedef CompositeFunctor CompositeStringWriter;
static void write_symbols_with_leakp() {
- assert(_leakp_writer != nullptr, "invariant");
- SymbolEntryWriter sw(_writer, _class_unload);
- LeakSymbolEntryWriter lsw(_leakp_writer, _class_unload);
- CompositeSymbolWriter csw(&lsw, &sw);
- _artifacts->iterate_symbols(csw);
- StringEntryWriter sew(_writer, _class_unload, true); // skip header
- LeakStringEntryWriter lsew(_leakp_writer, _class_unload, true); // skip header
- CompositeStringWriter csew(&lsew, &sew);
- _artifacts->iterate_strings(csew);
- sw.add(sew.count());
- lsw.add(lsew.count());
- _artifacts->tally(sw);
-}
-
-static void write_symbols_on_clear() {
assert(_writer != nullptr, "invariant");
assert(_leakp_writer != nullptr, "invariant");
assert(previous_epoch(), "invariant");
- SymbolEntryWriter sw(_writer, _class_unload);
- LeakSymbolEntryWriter lsw(_leakp_writer, _class_unload);
+ SymbolEntryWriter sw(_writer, unloading());
+ LeakSymbolEntryWriter lsw(_leakp_writer, unloading());
CompositeSymbolWriter csw(&lsw, &sw);
_artifacts->iterate_symbols(csw);
- StringEntryWriter sew(_writer, _class_unload, true); // skip header
- LeakStringEntryWriter lsew(_leakp_writer, _class_unload, true); // skip header
+ StringEntryWriter sew(_writer, unloading(), true); // skip header
+ LeakStringEntryWriter lsew(_leakp_writer, unloading(), true); // skip header
CompositeStringWriter csew(&lsew, &sew);
_artifacts->iterate_strings(csew);
sw.add(sew.count());
@@ -1108,17 +1160,24 @@ static void write_symbols() {
write_symbols_with_leakp();
return;
}
- SymbolEntryWriter sw(_writer, _class_unload);
+ SymbolEntryWriter sw(_writer, unloading());
_artifacts->iterate_symbols(sw);
- StringEntryWriter sew(_writer, _class_unload, true); // skip header
+ StringEntryWriter sew(_writer, unloading(), true); // skip header
_artifacts->iterate_strings(sew);
sw.add(sew.count());
_artifacts->tally(sw);
}
+static void write_symbols_on_clear() {
+ assert(_writer != nullptr, "invariant");
+ assert(_leakp_writer != nullptr, "invariant");
+ assert(previous_epoch(), "invariant");
+ write_symbols_with_leakp();
+}
+
typedef Wrapper ClearKlassBits;
typedef Wrapper ClearMethodFlag;
-typedef MethodIteratorHost ClearKlassAndMethods;
+typedef MethodIteratorHost ClearKlassAndMethods;
static void clear_klasses_and_methods() {
ClearKlassAndMethods clear(_writer);
@@ -1165,19 +1224,17 @@ size_t JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* l
setup(writer, leakp_writer, class_unload, flushpoint);
// write order is important because an individual write step
// might tag an artifact to be written in a subsequent step
- if (!write_klasses()) {
- return 0;
- }
+ write_klasses();
write_packages();
write_modules();
- write_classloaders();
+ write_clds();
write_methods();
write_symbols();
return teardown();
}
/**
- * Clear all tags from the previous epoch.
+ * Clear all tags from the previous epoch. Reset support structures.
*/
void JfrTypeSet::clear(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
ResourceMark rm;
@@ -1185,7 +1242,7 @@ void JfrTypeSet::clear(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_w
write_klasses_on_clear();
write_packages_on_clear();
write_modules_on_clear();
- write_classloaders_on_clear();
+ write_clds_on_clear();
write_methods_on_clear();
write_symbols_on_clear();
teardown();
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp
index 0876281d53f..883821f853c 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp
@@ -32,7 +32,8 @@
JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_table(nullptr),
_klass_list(nullptr),
- _total_count(0) {
+ _total_count(0),
+ _class_unload(class_unload) {
initialize(class_unload);
assert(_klass_list != nullptr, "invariant");
}
@@ -41,6 +42,7 @@ static const size_t initial_klass_list_size = 256;
const int initial_klass_loader_set_size = 64;
void JfrArtifactSet::initialize(bool class_unload) {
+ _class_unload = class_unload;
if (_symbol_table == nullptr) {
_symbol_table = JfrSymbolTable::create();
assert(_symbol_table != nullptr, "invariant");
@@ -51,6 +53,11 @@ void JfrArtifactSet::initialize(bool class_unload) {
// resource allocation
_klass_list = new GrowableArray(initial_klass_list_size);
_klass_loader_set = new GrowableArray(initial_klass_loader_set_size);
+ _klass_loader_leakp_set = new GrowableArray(initial_klass_loader_set_size);
+
+ if (class_unload) {
+ _unloading_set = new GrowableArray(initial_klass_list_size);
+ }
}
void JfrArtifactSet::clear() {
@@ -97,10 +104,27 @@ int JfrArtifactSet::entries() const {
return _klass_list->length();
}
-bool JfrArtifactSet::should_do_loader_klass(const Klass* k) {
+static inline bool not_in_set(GrowableArray* set, const Klass* k) {
+ assert(set != nullptr, "invariant");
+ assert(k != nullptr, "invariant");
+ return !JfrMutablePredicate::test(set, k);
+}
+
+bool JfrArtifactSet::should_do_cld_klass(const Klass* k, bool leakp) {
assert(k != nullptr, "invariant");
assert(_klass_loader_set != nullptr, "invariant");
- return !JfrMutablePredicate::test(_klass_loader_set, k);
+ assert(_klass_loader_leakp_set != nullptr, "invariant");
+ return not_in_set(leakp ? _klass_loader_leakp_set : _klass_loader_set, k);
+}
+
+bool JfrArtifactSet::should_do_unloading_artifact(const void* ptr) {
+ assert(ptr != nullptr, "invariant");
+ assert(_class_unload, "invariant");
+ assert(_unloading_set != nullptr, "invariant");
+ // The incoming pointers are of all kinds of different types.
+ // However, we are only interested in set membership.
+ // Treat them uniformly as const Klass* for simplicity and code reuse.
+ return not_in_set(_unloading_set, static_cast(ptr));
}
void JfrArtifactSet::register_klass(const Klass* k) {
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp
index b0c2d989de5..24424fdef3a 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp
@@ -114,28 +114,6 @@ class ClearArtifact {
}
};
-template
-class SerializePredicate {
- bool _class_unload;
- public:
- SerializePredicate(bool class_unload) : _class_unload(class_unload) {}
- bool operator()(T const& value) {
- assert(value != nullptr, "invariant");
- return _class_unload ? true : IS_NOT_SERIALIZED(value);
- }
-};
-
-template <>
-class SerializePredicate {
- bool _class_unload;
- public:
- SerializePredicate(bool class_unload) : _class_unload(class_unload) {}
- bool operator()(const Method* method) {
- assert(method != nullptr, "invariant");
- return _class_unload ? true : METHOD_IS_NOT_SERIALIZED(method);
- }
-};
-
template
class SymbolPredicate {
bool _class_unload;
@@ -150,11 +128,23 @@ class SymbolPredicate {
}
};
+class KlassUsedPredicate {
+ bool _current_epoch;
+public:
+ KlassUsedPredicate(bool current_epoch) : _current_epoch(current_epoch) {}
+ bool operator()(const Klass* klass) {
+ return _current_epoch ? USED_THIS_EPOCH(klass) : USED_PREVIOUS_EPOCH(klass);
+ }
+};
+
class MethodUsedPredicate {
bool _current_epoch;
public:
MethodUsedPredicate(bool current_epoch) : _current_epoch(current_epoch) {}
bool operator()(const Klass* klass) {
+ if (!klass->is_instance_klass()) {
+ return false;
+ }
return _current_epoch ? METHOD_USED_THIS_EPOCH(klass) : METHOD_USED_PREVIOUS_EPOCH(klass);
}
};
@@ -210,7 +200,10 @@ class JfrArtifactSet : public JfrCHeapObj {
JfrSymbolTable* _symbol_table;
GrowableArray* _klass_list;
GrowableArray* _klass_loader_set;
+ GrowableArray* _klass_loader_leakp_set;
+ GrowableArray* _unloading_set;
size_t _total_count;
+ bool _class_unload;
public:
JfrArtifactSet(bool class_unload);
@@ -235,14 +228,20 @@ class JfrArtifactSet : public JfrCHeapObj {
int entries() const;
size_t total_count() const;
void register_klass(const Klass* k);
- bool should_do_loader_klass(const Klass* k);
+ bool should_do_cld_klass(const Klass* k, bool leakp);
+ bool should_do_unloading_artifact(const void* ptr);
void increment_checkpoint_id();
template
void iterate_klasses(Functor& functor) const {
for (int i = 0; i < _klass_list->length(); ++i) {
if (!functor(_klass_list->at(i))) {
- break;
+ return;
+ }
+ }
+ for (int i = 0; i < _klass_loader_set->length(); ++i) {
+ if (!functor(_klass_loader_set->at(i))) {
+ return;
}
}
}
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp
index e5b9a33ef56..13853e14a13 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp
@@ -33,6 +33,7 @@
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.inline.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp"
+#include "jfr/support/jfrKlassExtension.hpp"
#include "oops/klass.hpp"
#include "oops/method.hpp"
#include "runtime/javaThread.hpp"
@@ -66,10 +67,14 @@ inline traceid set_used_and_get(const T* type) {
return TRACE_ID(type);
}
+// We set the 'method_and_class' bits to have a consistent
+// bit pattern set always. This is because the tag is non-atomic,
+// hence, we always need the same bit pattern in an epoch to avoid losing information.
inline void JfrTraceIdLoadBarrier::load_barrier(const Klass* klass) {
- SET_USED_THIS_EPOCH(klass);
- enqueue(klass);
- JfrTraceIdEpoch::set_changed_tag_state();
+ SET_METHOD_AND_CLASS_USED_THIS_EPOCH(klass);
+ assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant");
+ enqueue(klass);
+ JfrTraceIdEpoch::set_changed_tag_state();
}
inline traceid JfrTraceIdLoadBarrier::load(const Klass* klass) {
@@ -113,26 +118,36 @@ inline traceid JfrTraceIdLoadBarrier::load_no_enqueue(const Klass* klass, const
return (METHOD_ID(klass, method));
}
-inline traceid JfrTraceIdLoadBarrier::load(const ModuleEntry* module) {
- return set_used_and_get(module);
-}
-
-inline traceid JfrTraceIdLoadBarrier::load(const PackageEntry* package) {
- return set_used_and_get(package);
-}
-
inline traceid JfrTraceIdLoadBarrier::load(const ClassLoaderData* cld) {
assert(cld != nullptr, "invariant");
if (cld->has_class_mirror_holder()) {
return 0;
}
const Klass* const class_loader_klass = cld->class_loader_klass();
- if (class_loader_klass != nullptr && should_tag(class_loader_klass)) {
- load_barrier(class_loader_klass);
+ if (class_loader_klass != nullptr) {
+ load(class_loader_klass);
}
return set_used_and_get(cld);
}
+inline traceid JfrTraceIdLoadBarrier::load(const ModuleEntry* module) {
+ assert(module != nullptr, "invariant");
+ const ClassLoaderData* cld = module->loader_data();
+ if (cld != nullptr) {
+ load(cld);
+ }
+ return set_used_and_get(module);
+}
+
+inline traceid JfrTraceIdLoadBarrier::load(const PackageEntry* package) {
+ assert(package != nullptr, "invariant");
+ const ModuleEntry* const module_entry = package->module();
+ if (module_entry != nullptr) {
+ load(module_entry);
+ }
+ return set_used_and_get(package);
+}
+
inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass, const Method* method) {
assert(klass != nullptr, "invariant");
assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant");
diff --git a/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp b/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp
index 09a452caaa5..49ced300e55 100644
--- a/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp
+++ b/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp
@@ -626,8 +626,8 @@ inline bool ReinitializeAllReleaseRetiredOp::process(typename
const bool retired = node->retired();
node->reinitialize();
assert(node->empty(), "invariant");
- assert(!node->retired(), "invariant");
if (retired) {
+ assert(!node->retired(), "invariant");
_prev = _list.excise(_prev, node);
node->release();
mspace_release(node, _mspace);
From 46b1b1ae8ddc9466bda5af5ba2e917ded3352f4d Mon Sep 17 00:00:00 2001
From: Naoto Sato
Date: Wed, 10 Jan 2024 17:33:13 +0000
Subject: [PATCH 19/66] 8320919: Clarify Locale related system properties
Reviewed-by: iris
Backport-of: 376051a9be95e0e4acf3c59d0eba3e9ef8727d79
---
.../share/classes/java/util/Locale.java | 91 +++++++++++++++++--
1 file changed, 81 insertions(+), 10 deletions(-)
diff --git a/src/java.base/share/classes/java/util/Locale.java b/src/java.base/share/classes/java/util/Locale.java
index 8fac36fb84f..726fa7c22fc 100644
--- a/src/java.base/share/classes/java/util/Locale.java
+++ b/src/java.base/share/classes/java/util/Locale.java
@@ -45,6 +45,7 @@
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
import java.io.Serializable;
+import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.concurrent.ConcurrentHashMap;
import java.util.spi.LocaleNameProvider;
@@ -257,6 +258,74 @@
* locales. For example, {@code Locale.US} is the {@code Locale} object
* for the United States.
*
+ *
+ *
+ * The default Locale is provided for any locale-sensitive methods if no
+ * {@code Locale} is explicitly specified as an argument, such as
+ * {@link DateFormat#getInstance()}. The default Locale is determined at startup
+ * of the Java runtime and established in the following three phases:
+ *
+ * - The locale-related system properties listed below are established from the
+ * host environment. Some system properties (except for {@code user.language}) may
+ * not have values from the host environment.
+ *
+ * Shows property keys and associated values
+ *
+ * Locale-related System Properties Key |
+ * Description |
+ *
+ *
+ * {@systemProperty user.language} |
+ * {@link ##def_language language} for the default Locale,
+ * such as "en" (English) |
+ * {@systemProperty user.script} |
+ * {@link ##def_script script} for the default Locale,
+ * such as "Latn" (Latin) |
+ * {@systemProperty user.country} |
+ * {@link ##def_region country} for the default Locale,
+ * such as "US" (United States) |
+ * {@systemProperty user.variant} |
+ * {@link ##def_variant variant} for the default Locale,
+ * such as "POSIX" |
+ * {@systemProperty user.extensions} |
+ * {@link ##def_extensions extensions} for the default Locale,
+ * such as "u-ca-japanese" (Japanese Calendar) |
+ *
+ *
+ *
+ * - The values of these system properties can be overridden by values designated
+ * at startup time. If the overriding value of the {@code user.extensions} property
+ * is unparsable, it is ignored. The overriding values of other properties are not
+ * checked for syntax or validity and are used directly in the default Locale.
+ * (Typically, system property values can be provided using the {@code -D} command-line
+ * option of a launcher. For example, specifying {@code -Duser.extensions=foobarbaz}
+ * results in a default Locale with no extensions, while specifying
+ * {@code -Duser.language=foobarbaz} results in a default Locale whose language is
+ * "foobarbaz".)
+ *
+ * - The default {@code Locale} instance is constructed from the values of these
+ * system properties.
+ *
+ *
+ * Altering the system property values with {@link System#setProperties(Properties)}/
+ * {@link System#setProperty(String, String)} has no effect on the default Locale.
+ *
Once the default Locale is established, applications can query the default
+ * Locale with {@link #getDefault()} and change it with {@link #setDefault(Locale)}.
+ * If the default Locale is changed with {@link #setDefault(Locale)}, the corresponding
+ * system properties are not altered. It is not recommended that applications read
+ * these system properties and parse or interpret them as their values may be out of date.
+ *
+ *
There are finer-grained default Locales specific for each {@link Locale.Category}.
+ * These category specific default Locales can be queried by {@link #getDefault(Category)},
+ * and set by {@link #setDefault(Category, Locale)}. Construction of these category
+ * specific default Locales are determined by the corresponding system properties,
+ * which consist of the base system properties as listed above, suffixed by either
+ * {@code ".display"} or {@code ".format"} depending on the category. For example,
+ * the value of the {@code user.language.display} system property will be used in the
+ * {@code language} part of the default Locale for the {@link Locale.Category#DISPLAY}
+ * category. In the absence of category specific system properties, the "category-less"
+ * system properties are used, such as {@code user.language} in the previous example.
+ *
*
*
* If an application or a system is internationalized and provides localized
@@ -983,14 +1052,14 @@ public int hashCode() {
}
/**
- * Gets the current value of the default locale for this instance
- * of the Java Virtual Machine.
+ * Gets the current value of the {@link ##default_locale default locale} for
+ * this instance of the Java Virtual Machine.
*
* The Java Virtual Machine sets the default locale during startup
* based on the host environment. It is used by many locale-sensitive
* methods if no locale is explicitly specified.
* It can be changed using the
- * {@link #setDefault(java.util.Locale) setDefault} method.
+ * {@link #setDefault(Locale)} method.
*
* @return the default locale for this instance of the Java Virtual Machine
*/
@@ -1000,13 +1069,13 @@ public static Locale getDefault() {
}
/**
- * Gets the current value of the default locale for the specified Category
- * for this instance of the Java Virtual Machine.
+ * Gets the current value of the {@link ##default_locale default locale} for
+ * the specified Category for this instance of the Java Virtual Machine.
*
* The Java Virtual Machine sets the default locale during startup based
* on the host environment. It is used by many locale-sensitive methods
* if no locale is explicitly specified. It can be changed using the
- * setDefault(Locale.Category, Locale) method.
+ * {@link #setDefault(Locale.Category, Locale)} method.
*
* @param category the specified category to get the default locale
* @throws NullPointerException if category is null
@@ -1114,8 +1183,9 @@ private static Optional getDefaultExtensions(String extensions
}
/**
- * Sets the default locale for this instance of the Java Virtual Machine.
- * This does not affect the host locale.
+ * Sets the {@link ##default_locale default locale} for
+ * this instance of the Java Virtual Machine. This does not affect the
+ * host locale.
*
* If there is a security manager, its {@code checkPermission}
* method is called with a {@code PropertyPermission("user.language", "write")}
@@ -1148,8 +1218,9 @@ public static synchronized void setDefault(Locale newLocale) {
}
/**
- * Sets the default locale for the specified Category for this instance
- * of the Java Virtual Machine. This does not affect the host locale.
+ * Sets the {@link ##default_locale default locale} for the specified
+ * Category for this instance of the Java Virtual Machine. This does
+ * not affect the host locale.
*
* If there is a security manager, its checkPermission method is called
* with a PropertyPermission("user.language", "write") permission before
From 71cc879bd46ece4979e7beaed5461d373bdb196f Mon Sep 17 00:00:00 2001
From: Mandy Chung
Date: Wed, 10 Jan 2024 18:14:22 +0000
Subject: [PATCH 20/66] 8322809: SystemModulesMap::classNames and moduleNames
arrays do not match the order
Reviewed-by: alanb
Backport-of: f3be138eb80c9e7f6cc21afb75cda9e49b667c8a
---
.../internal/plugins/SystemModulesPlugin.java | 13 +-
.../ModuleMainClassTest.java | 145 ++++++++++++++++++
.../src/com.foo/com/foo/Main.java | 53 +++++++
.../src/com.foo/module-info.java | 27 ++++
.../src/net.foo/module-info.java | 26 ++++
.../src/net.foo/net/foo/Main.java | 54 +++++++
6 files changed, 313 insertions(+), 5 deletions(-)
create mode 100644 test/jdk/tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java
create mode 100644 test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/com/foo/Main.java
create mode 100644 test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/module-info.java
create mode 100644 test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/module-info.java
create mode 100644 test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/net/foo/Main.java
diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java
index 735c969a886..40693b33d6d 100644
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2024, 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
@@ -1827,6 +1827,9 @@ private String genSystemModulesMapClass(ClassDesc allSystemModules,
// write the class file to the pool as a resource
String rn = "/java.base/" + SYSTEM_MODULES_MAP_CLASSNAME + ".class";
+ // sort the map of module name to the class name of the generated SystemModules class
+ List> systemModulesMap = map.entrySet()
+ .stream().sorted(Map.Entry.comparingByKey()).toList();
ResourcePoolEntry e = ResourcePoolEntry.create(rn, ClassFile.of().build(
CD_SYSTEM_MODULES_MAP,
clb -> clb.withFlags(ACC_FINAL + ACC_SUPER)
@@ -1877,10 +1880,10 @@ private String genSystemModulesMapClass(ClassDesc allSystemModules,
cob.anewarray(CD_String);
int index = 0;
- for (String moduleName : sorted(map.keySet())) {
+ for (Map.Entry entry : systemModulesMap) {
cob.dup() // arrayref
.constantInstruction(index)
- .constantInstruction(moduleName)
+ .constantInstruction(entry.getKey())
.aastore();
index++;
}
@@ -1898,10 +1901,10 @@ private String genSystemModulesMapClass(ClassDesc allSystemModules,
.anewarray(CD_String);
int index = 0;
- for (String className : sorted(map.values())) {
+ for (Map.Entry entry : systemModulesMap) {
cob.dup() // arrayref
.constantInstruction(index)
- .constantInstruction(className.replace('/', '.'))
+ .constantInstruction(entry.getValue().replace('/', '.'))
.aastore();
index++;
}
diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java
new file mode 100644
index 00000000000..ca7e2bc5f30
--- /dev/null
+++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2024, 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 java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.spi.ToolProvider;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.util.FileUtils;
+
+import static jdk.test.lib.process.ProcessTools.*;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeAll;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * @test
+ * @bug 8322809
+ * @library /test/lib
+ * @modules jdk.compiler jdk.jlink
+ * @build jdk.test.lib.compiler.CompilerUtils
+ * jdk.test.lib.process.ProcessTools
+ * jdk.test.lib.util.FileUtils
+ * ModuleMainClassTest
+ * @run junit ModuleMainClassTest
+ */
+
+public class ModuleMainClassTest {
+ private static final String JAVA_HOME = System.getProperty("java.home");
+ private static final String TEST_SRC = System.getProperty("test.src");
+
+ private static final Path SRC_DIR = Path.of(TEST_SRC, "src");
+ private static final Path MODS_DIR = Path.of("mods");
+ private static final Path JMODS_DIR = Path.of("jmods");
+
+ private static final Path IMAGE = Path.of("image");
+
+ // the module names are sorted by the plugin and so these names cover
+ // the cases that are before and after the elements of `jdk.*` modules
+ // with main classes
+ private static String[] modules = new String[] {"com.foo", "net.foo"};
+
+ private static boolean hasJmods() {
+ if (!Files.exists(Paths.get(JAVA_HOME, "jmods"))) {
+ System.err.println("Test skipped. NO jmods directory");
+ return false;
+ }
+ return true;
+ }
+
+ @BeforeAll
+ public static void compileAll() throws Throwable {
+ if (!hasJmods()) return;
+
+ for (String mn : modules) {
+ Path msrc = SRC_DIR.resolve(mn);
+ assertTrue(CompilerUtils.compile(msrc, MODS_DIR,
+ "--module-source-path", SRC_DIR.toString(),
+ "--add-exports", "java.base/jdk.internal.module=" + mn));
+ }
+
+ if (Files.exists(IMAGE)) {
+ FileUtils.deleteFileTreeUnchecked(IMAGE);
+ }
+
+ // create JMOD files
+ Files.createDirectories(JMODS_DIR);
+ Stream.of(modules).forEach(mn ->
+ assertTrue(jmod("create",
+ "--class-path", MODS_DIR.resolve(mn).toString(),
+ "--main-class", mn + ".Main",
+ JMODS_DIR.resolve(mn + ".jmod").toString()) == 0)
+ );
+
+ // the run-time image created will have 4 modules with main classes
+ createImage(IMAGE, "com.foo");
+ }
+
+ @Test
+ public void testComFoo() throws Exception {
+ if (!hasJmods()) return;
+
+ Path java = IMAGE.resolve("bin").resolve("java");
+ assertTrue(executeProcess(java.toString(),
+ "-m", "com.foo")
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue() == 0);
+ }
+
+ @Test
+ public void testNetFoo() throws Exception {
+ if (!hasJmods()) return;
+
+ Path java = IMAGE.resolve("bin").resolve("java");
+ assertTrue(executeProcess(java.toString(),
+ "-m", "net.foo")
+ .outputTo(System.out)
+ .errorTo(System.out)
+ .getExitValue() == 0);
+ }
+
+ static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink")
+ .orElseThrow(() -> new RuntimeException("jlink tool not found"));
+
+ static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod")
+ .orElseThrow(() -> new RuntimeException("jmod tool not found"));
+
+ private static void createImage(Path outputDir, String... modules) throws Throwable {
+ assertTrue(JLINK_TOOL.run(System.out, System.out,
+ "--output", outputDir.toString(),
+ "--add-modules", Arrays.stream(modules).collect(Collectors.joining(",")),
+ "--module-path", JMODS_DIR.toString()) == 0);
+ }
+
+ private static int jmod(String... options) {
+ System.out.println("jmod " + Arrays.asList(options));
+ return JMOD_TOOL.run(System.out, System.out, options);
+ }
+}
diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/com/foo/Main.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/com/foo/Main.java
new file mode 100644
index 00000000000..f8b230647fa
--- /dev/null
+++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/com/foo/Main.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2024, 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 com.foo;
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.stream.Stream;
+
+/**
+ * Sanity test if SystemModules pre-resolved at link-time for com.foo
+ * with main class is loaded properly.
+ */
+public class Main {
+ public static void main(String... args) throws Exception {
+ ModuleDescriptor md = Main.class.getModule().getDescriptor();
+ System.out.println(md);
+
+ checkMainClass("com.foo", "com.foo.Main");
+ checkMainClass("net.foo", "net.foo.Main");
+ Stream.of("jdk.httpserver", "jdk.jfr").forEach(mn ->
+ ModuleFinder.ofSystem().find(mn).get().descriptor().mainClass()
+ .orElseThrow(() -> new RuntimeException(mn + " no main class"))
+ );
+ }
+
+ static void checkMainClass(String mn, String mainClass) {
+ String cn = ModuleFinder.ofSystem().find(mn).get().descriptor().mainClass().get();
+ if (!cn.equals(mainClass)) {
+ throw new RuntimeException("Mismatched main class of module " + mn + ": " + cn + " expected: " + mainClass);
+ }
+ }
+}
diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/module-info.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/module-info.java
new file mode 100644
index 00000000000..99107602506
--- /dev/null
+++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/module-info.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2024, 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.
+ */
+
+module com.foo {
+ requires jdk.httpserver;
+ requires net.foo;
+}
diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/module-info.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/module-info.java
new file mode 100644
index 00000000000..360a989d9b3
--- /dev/null
+++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/module-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2024, 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.
+ */
+
+module net.foo {
+ requires jdk.jfr;
+}
diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/net/foo/Main.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/net/foo/Main.java
new file mode 100644
index 00000000000..c147923e75a
--- /dev/null
+++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/net/foo/Main.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2024, 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 net.foo;
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.stream.Stream;
+
+/**
+ * Sanity test if SystemModules pre-resolved at link-time for net.foo
+ * with main class is loaded properly.
+ */
+public class Main {
+ public static void main(String... args) throws Exception {
+ ModuleDescriptor md = Main.class.getModule().getDescriptor();
+ System.out.println(md);
+
+ checkMainClass("com.foo", "com.foo.Main");
+ checkMainClass("net.foo", "net.foo.Main");
+ Stream.of("jdk.httpserver", "jdk.jfr").forEach(mn ->
+ ModuleFinder.ofSystem().find(mn).get().descriptor().mainClass()
+ .orElseThrow(() -> new RuntimeException(mn + " no main class"))
+ );
+ }
+
+ static void checkMainClass(String mn, String mainClass) {
+ String cn = ModuleFinder.ofSystem().find(mn).get().descriptor().mainClass().get();
+ if (!cn.equals(mainClass)) {
+ throw new RuntimeException("Mismatched main class of module " + mn + ": " + cn + " expected: " + mainClass);
+ }
+ }
+
+}
From 865cf888efbdf5533ded8ca39ef706de9b48dc15 Mon Sep 17 00:00:00 2001
From: Serguei Spitsyn
Date: Wed, 10 Jan 2024 18:16:45 +0000
Subject: [PATCH 21/66] 8311218: fatal error: stuck in
JvmtiVTMSTransitionDisabler::VTMS_transition_disable
Reviewed-by: alanb
Backport-of: 0f8e4e0a81257c678e948c341a241dc0b810494f
---
make/data/hotspot-symbols/symbols-unix | 1 +
src/hotspot/share/classfile/vmIntrinsics.hpp | 1 +
src/hotspot/share/classfile/vmSymbols.hpp | 1 +
src/hotspot/share/include/jvm.h | 3 +
src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 1 +
src/hotspot/share/opto/c2compiler.cpp | 1 +
src/hotspot/share/opto/library_call.cpp | 26 ++++-
src/hotspot/share/opto/library_call.hpp | 1 +
src/hotspot/share/prims/jvm.cpp | 16 +++
src/hotspot/share/runtime/handshake.cpp | 4 +
src/hotspot/share/runtime/javaThread.cpp | 1 +
src/hotspot/share/runtime/javaThread.hpp | 5 +
.../classes/java/lang/VirtualThread.java | 82 ++++++++-----
.../share/native/libjava/VirtualThread.c | 11 +-
.../SuspendWithInterruptLock.java | 108 ++++++++++++++++++
15 files changed, 229 insertions(+), 33 deletions(-)
create mode 100644 test/hotspot/jtreg/serviceability/jvmti/vthread/SuspendWithInterruptLock/SuspendWithInterruptLock.java
diff --git a/make/data/hotspot-symbols/symbols-unix b/make/data/hotspot-symbols/symbols-unix
index 9ca040794f3..fbb82a11fac 100644
--- a/make/data/hotspot-symbols/symbols-unix
+++ b/make/data/hotspot-symbols/symbols-unix
@@ -223,6 +223,7 @@ JVM_VirtualThreadEnd
JVM_VirtualThreadMount
JVM_VirtualThreadUnmount
JVM_VirtualThreadHideFrames
+JVM_VirtualThreadDisableSuspend
# Scoped values
JVM_EnsureMaterializedForStackWalk_func
diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp
index 8ed99d74c0b..c9bc4acbeff 100644
--- a/src/hotspot/share/classfile/vmIntrinsics.hpp
+++ b/src/hotspot/share/classfile/vmIntrinsics.hpp
@@ -597,6 +597,7 @@ class methodHandle;
do_intrinsic(_notifyJvmtiVThreadMount, java_lang_VirtualThread, notifyJvmtiMount_name, bool_void_signature, F_RN) \
do_intrinsic(_notifyJvmtiVThreadUnmount, java_lang_VirtualThread, notifyJvmtiUnmount_name, bool_void_signature, F_RN) \
do_intrinsic(_notifyJvmtiVThreadHideFrames, java_lang_VirtualThread, notifyJvmtiHideFrames_name, bool_void_signature, F_RN) \
+ do_intrinsic(_notifyJvmtiVThreadDisableSuspend, java_lang_VirtualThread, notifyJvmtiDisableSuspend_name, bool_void_signature, F_RN) \
\
/* support for UnsafeConstants */ \
do_class(jdk_internal_misc_UnsafeConstants, "jdk/internal/misc/UnsafeConstants") \
diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp
index 16ddc2602b1..fb4b059b5bd 100644
--- a/src/hotspot/share/classfile/vmSymbols.hpp
+++ b/src/hotspot/share/classfile/vmSymbols.hpp
@@ -421,6 +421,7 @@ class SerializeClosure;
template(notifyJvmtiMount_name, "notifyJvmtiMount") \
template(notifyJvmtiUnmount_name, "notifyJvmtiUnmount") \
template(notifyJvmtiHideFrames_name, "notifyJvmtiHideFrames") \
+ template(notifyJvmtiDisableSuspend_name, "notifyJvmtiDisableSuspend") \
template(doYield_name, "doYield") \
template(enter_name, "enter") \
template(enterSpecial_name, "enterSpecial") \
diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h
index cc1b3d94cbd..5d6ab27a3a1 100644
--- a/src/hotspot/share/include/jvm.h
+++ b/src/hotspot/share/include/jvm.h
@@ -1154,6 +1154,9 @@ JVM_VirtualThreadUnmount(JNIEnv* env, jobject vthread, jboolean hide);
JNIEXPORT void JNICALL
JVM_VirtualThreadHideFrames(JNIEnv* env, jobject vthread, jboolean hide);
+JNIEXPORT void JNICALL
+JVM_VirtualThreadDisableSuspend(JNIEnv* env, jobject vthread, jboolean enter);
+
/*
* Core reflection support.
*/
diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
index 5fdc70d7bc7..bac9a786fd9 100644
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp
@@ -220,6 +220,7 @@
nonstatic_field(JavaThread, _lock_stack, LockStack) \
JVMTI_ONLY(nonstatic_field(JavaThread, _is_in_VTMS_transition, bool)) \
JVMTI_ONLY(nonstatic_field(JavaThread, _is_in_tmp_VTMS_transition, bool)) \
+ JVMTI_ONLY(nonstatic_field(JavaThread, _is_disable_suspend, bool)) \
\
nonstatic_field(LockStack, _top, uint32_t) \
\
diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp
index 5e9dfcacafd..ba383a679e1 100644
--- a/src/hotspot/share/opto/c2compiler.cpp
+++ b/src/hotspot/share/opto/c2compiler.cpp
@@ -822,6 +822,7 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) {
case vmIntrinsics::_notifyJvmtiVThreadMount:
case vmIntrinsics::_notifyJvmtiVThreadUnmount:
case vmIntrinsics::_notifyJvmtiVThreadHideFrames:
+ case vmIntrinsics::_notifyJvmtiVThreadDisableSuspend:
#endif
break;
diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp
index 6e104f09b9d..c2b4eaab1bc 100644
--- a/src/hotspot/share/opto/library_call.cpp
+++ b/src/hotspot/share/opto/library_call.cpp
@@ -492,7 +492,8 @@ bool LibraryCallKit::try_to_inline(int predicate) {
"notifyJvmtiMount", false, false);
case vmIntrinsics::_notifyJvmtiVThreadUnmount: return inline_native_notify_jvmti_funcs(CAST_FROM_FN_PTR(address, OptoRuntime::notify_jvmti_vthread_unmount()),
"notifyJvmtiUnmount", false, false);
- case vmIntrinsics::_notifyJvmtiVThreadHideFrames: return inline_native_notify_jvmti_hide();
+ case vmIntrinsics::_notifyJvmtiVThreadHideFrames: return inline_native_notify_jvmti_hide();
+ case vmIntrinsics::_notifyJvmtiVThreadDisableSuspend: return inline_native_notify_jvmti_sync();
#endif
#ifdef JFR_HAVE_INTRINSICS
@@ -2950,6 +2951,29 @@ bool LibraryCallKit::inline_native_notify_jvmti_hide() {
return true;
}
+// Always update the is_disable_suspend bit.
+bool LibraryCallKit::inline_native_notify_jvmti_sync() {
+ if (!DoJVMTIVirtualThreadTransitions) {
+ return true;
+ }
+ IdealKit ideal(this);
+
+ {
+ // unconditionally update the is_disable_suspend bit in current JavaThread
+ Node* thread = ideal.thread();
+ Node* arg = _gvn.transform(argument(1)); // argument for notification
+ Node* addr = basic_plus_adr(thread, in_bytes(JavaThread::is_disable_suspend_offset()));
+ const TypePtr *addr_type = _gvn.type(addr)->isa_ptr();
+
+ sync_kit(ideal);
+ access_store_at(nullptr, addr, addr_type, arg, _gvn.type(arg), T_BOOLEAN, IN_NATIVE | MO_UNORDERED);
+ ideal.sync_kit(this);
+ }
+ final_sync(ideal);
+
+ return true;
+}
+
#endif // INCLUDE_JVMTI
#ifdef JFR_HAVE_INTRINSICS
diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp
index 55d1dc78f1f..47f9d7d4713 100644
--- a/src/hotspot/share/opto/library_call.hpp
+++ b/src/hotspot/share/opto/library_call.hpp
@@ -245,6 +245,7 @@ class LibraryCallKit : public GraphKit {
#if INCLUDE_JVMTI
bool inline_native_notify_jvmti_funcs(address funcAddr, const char* funcName, bool is_start, bool is_end);
bool inline_native_notify_jvmti_hide();
+ bool inline_native_notify_jvmti_sync();
#endif
#ifdef JFR_HAVE_INTRINSICS
diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp
index f0a30ee0311..bd6eda2d468 100644
--- a/src/hotspot/share/prims/jvm.cpp
+++ b/src/hotspot/share/prims/jvm.cpp
@@ -4008,6 +4008,22 @@ JVM_ENTRY(void, JVM_VirtualThreadHideFrames(JNIEnv* env, jobject vthread, jboole
#endif
JVM_END
+// Notification from VirtualThread about disabling JVMTI Suspend in a sync critical section.
+// Needed to avoid deadlocks with JVMTI suspend mechanism.
+JVM_ENTRY(void, JVM_VirtualThreadDisableSuspend(JNIEnv* env, jobject vthread, jboolean enter))
+#if INCLUDE_JVMTI
+ if (!DoJVMTIVirtualThreadTransitions) {
+ assert(!JvmtiExport::can_support_virtual_threads(), "sanity check");
+ return;
+ }
+ assert(thread->is_disable_suspend() != (bool)enter,
+ "nested or unbalanced monitor enter/exit is not allowed");
+ thread->toggle_is_disable_suspend();
+#else
+ fatal("Should only be called with JVMTI enabled");
+#endif
+JVM_END
+
/*
* Return the current class's class file version. The low order 16 bits of the
* returned jint contain the class's major version. The high order 16 bits
diff --git a/src/hotspot/share/runtime/handshake.cpp b/src/hotspot/share/runtime/handshake.cpp
index 50c93d666e2..a57076c021a 100644
--- a/src/hotspot/share/runtime/handshake.cpp
+++ b/src/hotspot/share/runtime/handshake.cpp
@@ -487,6 +487,10 @@ HandshakeOperation* HandshakeState::get_op_for_self(bool allow_suspend, bool che
assert(_handshakee == Thread::current(), "Must be called by self");
assert(_lock.owned_by_self(), "Lock must be held");
assert(allow_suspend || !check_async_exception, "invalid case");
+ if (allow_suspend && _handshakee->is_disable_suspend()) {
+ // filter out suspend operations while JavaThread is in disable_suspend mode
+ allow_suspend = false;
+ }
if (!allow_suspend) {
return _queue.peek(no_suspend_no_async_exception_filter);
} else if (check_async_exception && !_async_exceptions_blocked) {
diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp
index 98b2a569b72..a789988e379 100644
--- a/src/hotspot/share/runtime/javaThread.cpp
+++ b/src/hotspot/share/runtime/javaThread.cpp
@@ -440,6 +440,7 @@ JavaThread::JavaThread() :
_carrier_thread_suspended(false),
_is_in_VTMS_transition(false),
_is_in_tmp_VTMS_transition(false),
+ _is_disable_suspend(false),
#ifdef ASSERT
_is_VTMS_transition_disabler(false),
#endif
diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp
index 71bf0cc1d49..fb1355b852a 100644
--- a/src/hotspot/share/runtime/javaThread.hpp
+++ b/src/hotspot/share/runtime/javaThread.hpp
@@ -317,6 +317,7 @@ class JavaThread: public Thread {
volatile bool _carrier_thread_suspended; // Carrier thread is externally suspended
bool _is_in_VTMS_transition; // thread is in virtual thread mount state transition
bool _is_in_tmp_VTMS_transition; // thread is in temporary virtual thread mount state transition
+ bool _is_disable_suspend; // JVMTI suspend is temporarily disabled; used on current thread only
#ifdef ASSERT
bool _is_VTMS_transition_disabler; // thread currently disabled VTMS transitions
#endif
@@ -647,6 +648,9 @@ class JavaThread: public Thread {
void set_is_in_VTMS_transition(bool val);
void toggle_is_in_tmp_VTMS_transition() { _is_in_tmp_VTMS_transition = !_is_in_tmp_VTMS_transition; };
+ bool is_disable_suspend() const { return _is_disable_suspend; }
+ void toggle_is_disable_suspend() { _is_disable_suspend = !_is_disable_suspend; };
+
#ifdef ASSERT
bool is_VTMS_transition_disabler() const { return _is_VTMS_transition_disabler; }
void set_is_VTMS_transition_disabler(bool val);
@@ -811,6 +815,7 @@ class JavaThread: public Thread {
#if INCLUDE_JVMTI
static ByteSize is_in_VTMS_transition_offset() { return byte_offset_of(JavaThread, _is_in_VTMS_transition); }
static ByteSize is_in_tmp_VTMS_transition_offset() { return byte_offset_of(JavaThread, _is_in_tmp_VTMS_transition); }
+ static ByteSize is_disable_suspend_offset() { return byte_offset_of(JavaThread, _is_disable_suspend); }
#endif
// Returns the jni environment for this thread
diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java
index 2707b3ba9bd..13ba543348e 100644
--- a/src/java.base/share/classes/java/lang/VirtualThread.java
+++ b/src/java.base/share/classes/java/lang/VirtualThread.java
@@ -743,11 +743,16 @@ void unpark() {
}
} else if ((s == PINNED) || (s == TIMED_PINNED)) {
// unpark carrier thread when pinned
- synchronized (carrierThreadAccessLock()) {
- Thread carrier = carrierThread;
- if (carrier != null && ((s = state()) == PINNED || s == TIMED_PINNED)) {
- U.unpark(carrier);
+ notifyJvmtiDisableSuspend(true);
+ try {
+ synchronized (carrierThreadAccessLock()) {
+ Thread carrier = carrierThread;
+ if (carrier != null && ((s = state()) == PINNED || s == TIMED_PINNED)) {
+ U.unpark(carrier);
+ }
}
+ } finally {
+ notifyJvmtiDisableSuspend(false);
}
}
}
@@ -844,16 +849,21 @@ boolean joinNanos(long nanos) throws InterruptedException {
public void interrupt() {
if (Thread.currentThread() != this) {
checkAccess();
- synchronized (interruptLock) {
- interrupted = true;
- Interruptible b = nioBlocker;
- if (b != null) {
- b.interrupt(this);
- }
+ notifyJvmtiDisableSuspend(true);
+ try {
+ synchronized (interruptLock) {
+ interrupted = true;
+ Interruptible b = nioBlocker;
+ if (b != null) {
+ b.interrupt(this);
+ }
- // interrupt carrier thread if mounted
- Thread carrier = carrierThread;
- if (carrier != null) carrier.setInterrupt();
+ // interrupt carrier thread if mounted
+ Thread carrier = carrierThread;
+ if (carrier != null) carrier.setInterrupt();
+ }
+ } finally {
+ notifyJvmtiDisableSuspend(false);
}
} else {
interrupted = true;
@@ -872,9 +882,14 @@ boolean getAndClearInterrupt() {
assert Thread.currentThread() == this;
boolean oldValue = interrupted;
if (oldValue) {
- synchronized (interruptLock) {
- interrupted = false;
- carrierThread.clearInterrupt();
+ notifyJvmtiDisableSuspend(true);
+ try {
+ synchronized (interruptLock) {
+ interrupted = false;
+ carrierThread.clearInterrupt();
+ }
+ } finally {
+ notifyJvmtiDisableSuspend(false);
}
}
return oldValue;
@@ -899,11 +914,16 @@ Thread.State threadState() {
return Thread.State.RUNNABLE;
case RUNNING:
// if mounted then return state of carrier thread
- synchronized (carrierThreadAccessLock()) {
- Thread carrierThread = this.carrierThread;
- if (carrierThread != null) {
- return carrierThread.threadState();
+ notifyJvmtiDisableSuspend(true);
+ try {
+ synchronized (carrierThreadAccessLock()) {
+ Thread carrierThread = this.carrierThread;
+ if (carrierThread != null) {
+ return carrierThread.threadState();
+ }
}
+ } finally {
+ notifyJvmtiDisableSuspend(false);
}
// runnable, mounted
return Thread.State.RUNNABLE;
@@ -1019,14 +1039,19 @@ public String toString() {
Thread carrier = carrierThread;
if (carrier != null) {
// include the carrier thread state and name when mounted
- synchronized (carrierThreadAccessLock()) {
- carrier = carrierThread;
- if (carrier != null) {
- String stateAsString = carrier.threadState().toString();
- sb.append(stateAsString.toLowerCase(Locale.ROOT));
- sb.append('@');
- sb.append(carrier.getName());
+ notifyJvmtiDisableSuspend(true);
+ try {
+ synchronized (carrierThreadAccessLock()) {
+ carrier = carrierThread;
+ if (carrier != null) {
+ String stateAsString = carrier.threadState().toString();
+ sb.append(stateAsString.toLowerCase(Locale.ROOT));
+ sb.append('@');
+ sb.append(carrier.getName());
+ }
}
+ } finally {
+ notifyJvmtiDisableSuspend(false);
}
}
// include virtual thread state when not mounted
@@ -1125,6 +1150,9 @@ private void setCarrierThread(Thread carrier) {
@JvmtiMountTransition
private native void notifyJvmtiHideFrames(boolean hide);
+ @IntrinsicCandidate
+ private native void notifyJvmtiDisableSuspend(boolean enter);
+
private static native void registerNatives();
static {
registerNatives();
diff --git a/src/java.base/share/native/libjava/VirtualThread.c b/src/java.base/share/native/libjava/VirtualThread.c
index a0b3e082087..94dbe0b7e37 100644
--- a/src/java.base/share/native/libjava/VirtualThread.c
+++ b/src/java.base/share/native/libjava/VirtualThread.c
@@ -32,11 +32,12 @@
#define VIRTUAL_THREAD "Ljava/lang/VirtualThread;"
static JNINativeMethod methods[] = {
- { "notifyJvmtiStart", "()V", (void *)&JVM_VirtualThreadStart },
- { "notifyJvmtiEnd", "()V", (void *)&JVM_VirtualThreadEnd },
- { "notifyJvmtiMount", "(Z)V", (void *)&JVM_VirtualThreadMount },
- { "notifyJvmtiUnmount", "(Z)V", (void *)&JVM_VirtualThreadUnmount },
- { "notifyJvmtiHideFrames", "(Z)V", (void *)&JVM_VirtualThreadHideFrames },
+ { "notifyJvmtiStart", "()V", (void *)&JVM_VirtualThreadStart },
+ { "notifyJvmtiEnd", "()V", (void *)&JVM_VirtualThreadEnd },
+ { "notifyJvmtiMount", "(Z)V", (void *)&JVM_VirtualThreadMount },
+ { "notifyJvmtiUnmount", "(Z)V", (void *)&JVM_VirtualThreadUnmount },
+ { "notifyJvmtiHideFrames", "(Z)V", (void *)&JVM_VirtualThreadHideFrames },
+ { "notifyJvmtiDisableSuspend", "(Z)V", (void *)&JVM_VirtualThreadDisableSuspend },
};
JNIEXPORT void JNICALL
diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/SuspendWithInterruptLock/SuspendWithInterruptLock.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/SuspendWithInterruptLock/SuspendWithInterruptLock.java
new file mode 100644
index 00000000000..d679f382d93
--- /dev/null
+++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/SuspendWithInterruptLock/SuspendWithInterruptLock.java
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test id=default
+ * @summary Do not suspend virtual threads in a critical section.
+ * @bug 8311218
+ * @requires vm.continuations
+ * @library /testlibrary
+ * @run main/othervm SuspendWithInterruptLock
+ */
+
+/**
+ * @test id=xint
+ * @summary Do not suspend virtual threads in a critical section.
+ * @bug 8311218
+ * @requires vm.continuations
+ * @library /testlibrary
+ * @run main/othervm -Xint SuspendWithInterruptLock
+ */
+
+import jvmti.JVMTIUtils;
+
+public class SuspendWithInterruptLock {
+ static volatile boolean done;
+
+ public static void main(String[] args) throws Exception {
+ Thread yielder = Thread.ofVirtual().name("yielder").start(() -> yielder());
+ Thread stateReader = Thread.ofVirtual().name("stateReader").start(() -> stateReader(yielder));
+ Thread suspender = new Thread(() -> suspender(stateReader));
+ suspender.start();
+
+ yielder.join();
+ stateReader.join();
+ suspender.join();
+ }
+
+ static private void yielder() {
+ int iterations = 100_000;
+ while (iterations-- > 0) {
+ Thread.yield();
+ }
+ done = true;
+ }
+
+ static private void stateReader(Thread target) {
+ while (!done) {
+ target.getState();
+ }
+ }
+
+ static private void suspender(Thread target) {
+ while (!done) {
+ suspendThread(target);
+ sleep(1);
+ resumeThread(target);
+ // Allow progress
+ sleep(5);
+ }
+ }
+
+ static void suspendThread(Thread t) {
+ try {
+ JVMTIUtils.suspendThread(t);
+ } catch (JVMTIUtils.JvmtiException e) {
+ if (e.getCode() != JVMTIUtils.JVMTI_ERROR_THREAD_NOT_ALIVE) {
+ throw e;
+ }
+ }
+ }
+
+ static void resumeThread(Thread t) {
+ try {
+ JVMTIUtils.resumeThread(t);
+ } catch (JVMTIUtils.JvmtiException e) {
+ if (e.getCode() != JVMTIUtils.JVMTI_ERROR_THREAD_NOT_ALIVE) {
+ throw e;
+ }
+ }
+ }
+
+ static private void sleep(long millis) {
+ try {
+ Thread.sleep(millis);
+ } catch (InterruptedException e) {}
+ }
+}
+
From dfe52be4ef4c766fd62051120f93144c3889249d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?=
Date: Wed, 10 Jan 2024 18:47:13 +0000
Subject: [PATCH 22/66] 8323540: assert((!((((method)->is_trace_flag_set(((1 <<
4) << 8))))))) failed: invariant
Reviewed-by: egahlin
Backport-of: c1282b57f50002edd08c93aed784390cca83b9b8
---
src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
index 2d49c5aa405..8df2f6593ef 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp
@@ -953,7 +953,6 @@ static int write_method(JfrCheckpointWriter* writer, MethodPtr method, bool leak
int write__method(JfrCheckpointWriter* writer, const void* m) {
assert(m != nullptr, "invariant");
MethodPtr method = static_cast(m);
- assert(METHOD_IS_NOT_SERIALIZED(method), "invariant");
set_serialized(method);
return write_method(writer, method, false);
}
From 34222839e8a9094a12cf4a2a9acc9e7b228e6c40 Mon Sep 17 00:00:00 2001
From: Mandy Chung
Date: Wed, 10 Jan 2024 21:29:34 +0000
Subject: [PATCH 23/66] 8323547:
tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java fails to
compile
Reviewed-by: naoto
---
.../plugins/SystemModuleDescriptors/ModuleMainClassTest.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java
index ca7e2bc5f30..15207909a07 100644
--- a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java
+++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java
@@ -102,7 +102,7 @@ public static void compileAll() throws Throwable {
}
@Test
- public void testComFoo() throws Exception {
+ public void testComFoo() throws Throwable {
if (!hasJmods()) return;
Path java = IMAGE.resolve("bin").resolve("java");
@@ -114,7 +114,7 @@ public void testComFoo() throws Exception {
}
@Test
- public void testNetFoo() throws Exception {
+ public void testNetFoo() throws Throwable {
if (!hasJmods()) return;
Path java = IMAGE.resolve("bin").resolve("java");
From 6951987b65e50143ee3f1f79f7731159a0310223 Mon Sep 17 00:00:00 2001
From: Naoto Sato
Date: Thu, 11 Jan 2024 00:03:10 +0000
Subject: [PATCH 24/66] 8320788: The system properties page is missing some
properties
Reviewed-by: rriggs, iris
Backport-of: 3bd9042054116365323912ed5867b70936fe85c4
---
src/java.base/share/classes/java/lang/System.java | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java
index 0c100793167..fb2aca379da 100644
--- a/src/java.base/share/classes/java/lang/System.java
+++ b/src/java.base/share/classes/java/lang/System.java
@@ -57,6 +57,7 @@
import java.security.ProtectionDomain;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
@@ -813,6 +814,10 @@ public static native void arraycopy(Object src, int srcPos,
* Note that even if the security manager does not permit the
* {@code getProperties} operation, it may choose to permit the
* {@link #getProperty(String)} operation.
+ *
+ * Additional locale-related system properties defined by the
+ * {@link Locale##default_locale Default Locale} section in the {@code Locale}
+ * class description may also be obtained with this method.
*
* @apiNote
* Changing a standard system property may have unpredictable results
From 53084107246aaa3eb997426e0f52abc44b8f5584 Mon Sep 17 00:00:00 2001
From: Stefan Karlsson
Date: Thu, 11 Jan 2024 08:05:53 +0000
Subject: [PATCH 25/66] 8321683: Tests fail with AssertionError in
RangeWithPageSize
Reviewed-by: ehelin
Backport-of: dce7a5732e69b6d29f75b98f6cf58a567d353a59
---
test/hotspot/jtreg/runtime/os/TestTracePageSizes.java | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/test/hotspot/jtreg/runtime/os/TestTracePageSizes.java b/test/hotspot/jtreg/runtime/os/TestTracePageSizes.java
index e4ad27b46e5..a94d9af4c27 100644
--- a/test/hotspot/jtreg/runtime/os/TestTracePageSizes.java
+++ b/test/hotspot/jtreg/runtime/os/TestTracePageSizes.java
@@ -350,7 +350,7 @@ public RangeWithPageSize(String start, String end, String pageSize, String thpEl
this.start = Long.parseUnsignedLong(start, 16);
this.end = Long.parseUnsignedLong(end, 16);
this.pageSize = Long.parseLong(pageSize);
- this.thpEligible = Integer.parseInt(thpEligible) == 1;
+ this.thpEligible = thpEligible == null ? false : (Integer.parseInt(thpEligible) == 1);
vmFlagHG = false;
vmFlagHT = false;
@@ -365,12 +365,11 @@ public RangeWithPageSize(String start, String end, String pageSize, String thpEl
}
}
- // When the THP policy is 'always' instead of 'madvise, the vmFlagHG property is false.
- // Check the THPeligible property instead.
- isTHP = !vmFlagHT && this.thpEligible;
+ // When the THP policy is 'always' instead of 'madvise, the vmFlagHG property is false,
+ // therefore also check thpEligible. If this is still causing problems in the future,
+ // we might have to check the AnonHugePages field.
- // vmFlagHG should imply isTHP
- assert !vmFlagHG || isTHP;
+ isTHP = vmFlagHG || this.thpEligible;
}
public long getPageSize() {
From db3427582df5913e9299e8ecceecd9bddb3b7358 Mon Sep 17 00:00:00 2001
From: Jorn Vernee
Date: Thu, 11 Jan 2024 12:09:20 +0000
Subject: [PATCH 26/66] 8322324: java/foreign/TestStubAllocFailure.java times
out while waiting for forked process 8322637:
java/foreign/critical/TestCriticalUpcall.java timed out
Reviewed-by: mcimadamore
Backport-of: d2d58dd6a8ec366a4bc3eb12a253b252de24557e
---
test/jdk/java/foreign/UpcallTestHelper.java | 29 ++++++++++++---------
1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/test/jdk/java/foreign/UpcallTestHelper.java b/test/jdk/java/foreign/UpcallTestHelper.java
index bbc01959ccd..8adf5580f51 100644
--- a/test/jdk/java/foreign/UpcallTestHelper.java
+++ b/test/jdk/java/foreign/UpcallTestHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,8 +29,9 @@
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
-import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
public class UpcallTestHelper extends NativeTestHelper {
@@ -50,16 +51,18 @@ public OutputAnalyzer runInNewProcess(Class> target, boolean useSpec, List
Date: Thu, 11 Jan 2024 12:16:41 +0000
Subject: [PATCH 27/66] 8318971: Better Error Handling for Jar Tool When
Processing Non-existent Files
Reviewed-by: jpai
Backport-of: 8ae309ebacd6947bbad2ef168ca13702e1cba099
---
.../share/classes/sun/tools/jar/Main.java | 6 ++
test/jdk/tools/jar/InputFilesTest.java | 82 ++++++++++++++++++-
2 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java
index fce80372b1e..6163ef82647 100644
--- a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java
+++ b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java
@@ -292,6 +292,9 @@ public synchronized boolean run(String args[]) {
}
}
expand();
+ if (!ok) {
+ return false;
+ }
if (!moduleInfos.isEmpty()) {
// All actual file entries (excl manifest and module-info.class)
Set jentries = new HashSet<>();
@@ -338,6 +341,9 @@ public synchronized boolean run(String args[]) {
tmpFile = createTemporaryFile("tmpjar", ".jar");
}
expand();
+ if (!ok) {
+ return false;
+ }
try (FileInputStream in = (fname != null) ? new FileInputStream(inputFile)
: new FileInputStream(FileDescriptor.in);
FileOutputStream out = new FileOutputStream(tmpFile);
diff --git a/test/jdk/tools/jar/InputFilesTest.java b/test/jdk/tools/jar/InputFilesTest.java
index 3dc08293a76..6a0a7e29021 100644
--- a/test/jdk/tools/jar/InputFilesTest.java
+++ b/test/jdk/tools/jar/InputFilesTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8165944
+ * @bug 8165944 8318971
* @summary test several jar tool input file scenarios with variations on -C
* options with/without a --release option. Some input files are
* duplicates that sometimes cause exceptions and other times do not,
@@ -153,6 +153,84 @@ public void test6() throws IOException {
jar("cf test.jar --release 9 -C test1 a -C test2 a");
}
+ /**
+ * Containing non-existent file in the file list
+ * The final jar should not be created and correct error message should be caught.
+ * IOException is triggered as expected.
+ */
+ @Test
+ public void testNonExistentFileInput() throws IOException {
+ touch("existingTestFile.txt");
+ onCompletion = () -> rm("existingTestFile.txt");
+ try {
+ jar("cf test.jar existingTestFile.txt nonExistentTestFile.txt");
+ Assert.fail("jar tool unexpectedly completed successfully");
+ } catch (IOException e) {
+ Assert.assertEquals(e.getMessage().trim(), "nonExistentTestFile.txt : no such file or directory");
+ Assert.assertTrue(Files.notExists(Path.of("test.jar")), "Jar file should not be created.");
+ }
+ }
+
+ /**
+ * With @File as a part of jar command line, where the File is containing one or more
+ * non-existent files or directories
+ * The final jar should not be created and correct error message should be caught.
+ * IOException is triggered as expected.
+ */
+ @Test
+ public void testNonExistentFileInputClassList() throws IOException {
+ touch("existingTestFile.txt");
+ touch("classes.list");
+ Files.writeString(Path.of("classes.list"), """
+ existingTestFile.txt
+ nonExistentTestFile.txt
+ nonExistentDirectory
+ """);
+ onCompletion = () -> rm("existingTestFile.txt classes.list");
+ try {
+ jar("cf test.jar @classes.list");
+ Assert.fail("jar tool unexpectedly completed successfully");
+ } catch (IOException e) {
+ String msg = e.getMessage().trim();
+ Assert.assertTrue(msg.contains("nonExistentTestFile.txt : no such file or directory"));
+ Assert.assertTrue(msg.trim().contains("nonExistentDirectory : no such file or directory"));
+ Assert.assertTrue(Files.notExists(Path.of("test.jar")), "Jar file should not be created.");
+ }
+
+ }
+
+ /**
+ * Create a jar file; then with @File as a part of jar command line, where the File is containing one or more
+ * non-existent files or directories
+ * The final jar should not be created and correct error message should be caught.
+ * IOException is triggered as expected.
+ */
+ @Test
+ public void testUpdateNonExistentFileInputClassList() throws IOException {
+ touch("existingTestFileUpdate.txt");
+ touch("existingTestFileUpdate2.txt");
+ touch("classesUpdate.list");
+ Files.writeString(Path.of("classesUpdate.list"), """
+ existingTestFileUpdate2.txt
+ nonExistentTestFileUpdate.txt
+ nonExistentDirectoryUpdate
+ """);
+ onCompletion = () -> rm("existingTestFileUpdate.txt existingTestFileUpdate2.txt " +
+ "classesUpdate.list testUpdate.jar");
+ try {
+ jar("cf testUpdate.jar existingTestFileUpdate.txt");
+ Assert.assertTrue(Files.exists(Path.of("testUpdate.jar")));
+ jar("uf testUpdate.jar @classesUpdate.list");
+ Assert.fail("jar tool unexpectedly completed successfully");
+ } catch (IOException e) {
+ String msg = e.getMessage().trim();
+ Assert.assertFalse(msg.contains("existingTestFileUpdate.txt : no such file or directory"));
+ Assert.assertTrue(msg.contains("nonExistentTestFileUpdate.txt : no such file or directory"));
+ Assert.assertTrue(msg.trim().contains("nonExistentDirectoryUpdate : no such file or directory"));
+ }
+
+ }
+
private Stream mkpath(String... args) {
return Arrays.stream(args).map(d -> Paths.get(".", d.split("/")));
}
From 4ea14b2720e811082ad52c21d250fc0469cdfe2a Mon Sep 17 00:00:00 2001
From: Weijun Wang
Date: Thu, 11 Jan 2024 20:57:14 +0000
Subject: [PATCH 28/66] 8322971: KEM.getInstance() should check if a 3rd-party
security provider is signed
Reviewed-by: mullan, valeriep
Backport-of: 9fd855ed477bb0849ce5c774854844deec0f4c6b
---
.../share/classes/javax/crypto/KEM.java | 22 +++++---
.../sun/crypto/provider/DHKEM/Compliance.java | 47 ++++-------------
.../com/sun/crypto/provider/EvenKEMImpl.java | 51 +++++++++++++++++++
test/jdk/javax/crypto/KEM/RSA_KEM.java | 15 ++++--
4 files changed, 90 insertions(+), 45 deletions(-)
create mode 100644 test/jdk/com/sun/crypto/provider/DHKEM/java.base/com/sun/crypto/provider/EvenKEMImpl.java
diff --git a/src/java.base/share/classes/javax/crypto/KEM.java b/src/java.base/share/classes/javax/crypto/KEM.java
index e05027a7abc..7df7fa236c8 100644
--- a/src/java.base/share/classes/javax/crypto/KEM.java
+++ b/src/java.base/share/classes/javax/crypto/KEM.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
import java.security.*;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
+import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -539,10 +540,19 @@ public static KEM getInstance(String algorithm)
List list = GetInstance.getServices(
"KEM",
Objects.requireNonNull(algorithm, "null algorithm name"));
- if (list.isEmpty()) {
- throw new NoSuchAlgorithmException(algorithm + " KEM not available");
+ List allowed = new ArrayList<>();
+ for (Provider.Service s : list) {
+ if (!JceSecurity.canUseProvider(s.getProvider())) {
+ continue;
+ }
+ allowed.add(s);
+ }
+ if (allowed.isEmpty()) {
+ throw new NoSuchAlgorithmException
+ (algorithm + " KEM not available");
}
- return new KEM(algorithm, new DelayedKEM(list.toArray(new Provider.Service[0])));
+
+ return new KEM(algorithm, new DelayedKEM(allowed.toArray(new Provider.Service[0])));
}
/**
@@ -568,7 +578,7 @@ public static KEM getInstance(String algorithm, Provider provider)
if (provider == null) {
return getInstance(algorithm);
}
- GetInstance.Instance instance = GetInstance.getInstance(
+ GetInstance.Instance instance = JceSecurity.getInstance(
"KEM",
KEMSpi.class,
Objects.requireNonNull(algorithm, "null algorithm name"),
@@ -601,7 +611,7 @@ public static KEM getInstance(String algorithm, String provider)
if (provider == null) {
return getInstance(algorithm);
}
- GetInstance.Instance instance = GetInstance.getInstance(
+ GetInstance.Instance instance = JceSecurity.getInstance(
"KEM",
KEMSpi.class,
Objects.requireNonNull(algorithm, "null algorithm name"),
diff --git a/test/jdk/com/sun/crypto/provider/DHKEM/Compliance.java b/test/jdk/com/sun/crypto/provider/DHKEM/Compliance.java
index 27b72b5cf7c..22c5c89b57b 100644
--- a/test/jdk/com/sun/crypto/provider/DHKEM/Compliance.java
+++ b/test/jdk/com/sun/crypto/provider/DHKEM/Compliance.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, 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
@@ -26,7 +26,9 @@
* @bug 8297878
* @summary Key Encapsulation Mechanism API
* @library /test/lib
+ * @build java.base/com.sun.crypto.provider.EvenKEMImpl
* @modules java.base/com.sun.crypto.provider
+ * @run main/othervm Compliance
*/
import jdk.test.lib.Asserts;
import jdk.test.lib.Utils;
@@ -45,18 +47,19 @@
import com.sun.crypto.provider.DHKEM;
+import static com.sun.crypto.provider.EvenKEMImpl.isEven;
+
public class Compliance {
public static void main(String[] args) throws Exception {
basic();
conform();
determined();
- try {
- Security.insertProviderAt(new ProviderImpl(), 1);
- delayed();
- } finally {
- Security.removeProvider("XP");
- }
+ // Patch an alternate DHKEM in SunEC which is ahead of SunJCE
+ // in security provider listing.
+ Security.getProvider("SunEC")
+ .put("KEM.DHKEM", "com.sun.crypto.provider.EvenKEMImpl");
+ delayed();
}
// Encapsulated conformance checks
@@ -220,34 +223,6 @@ static byte[] calcDetermined(long seed) throws Exception {
return enc2;
}
- public static class ProviderImpl extends Provider {
- ProviderImpl() {
- super("XP", "1", "XP");
- put("KEM.DHKEM", "Compliance$KEMImpl");
- }
- }
-
- static boolean isEven(Key k) {
- return Arrays.hashCode(k.getEncoded()) % 2 == 0;
- }
-
- public static class KEMImpl extends DHKEM {
-
- @Override
- public EncapsulatorSpi engineNewEncapsulator(PublicKey pk, AlgorithmParameterSpec spec, SecureRandom secureRandom)
- throws InvalidAlgorithmParameterException, InvalidKeyException {
- if (!isEven(pk)) throw new InvalidKeyException("Only accept even keys");
- return super.engineNewEncapsulator(pk, spec, secureRandom);
- }
-
- @Override
- public DecapsulatorSpi engineNewDecapsulator(PrivateKey sk, AlgorithmParameterSpec spec)
- throws InvalidAlgorithmParameterException, InvalidKeyException {
- if (!isEven(sk)) throw new InvalidKeyException("Only accept even keys");
- return super.engineNewDecapsulator(sk, spec);
- }
- }
-
// Ensure delayed provider selection
static void delayed() throws Exception {
KeyPairGenerator g = KeyPairGenerator.getInstance("X25519");
@@ -266,7 +241,7 @@ static void delayed() throws Exception {
KEM.Encapsulator eodd = kem.newEncapsulator(odd);
KEM.Encapsulator eeven = kem.newEncapsulator(even);
Asserts.assertEQ(eodd.providerName(), "SunJCE");
- Asserts.assertEQ(eeven.providerName(), "XP");
+ Asserts.assertEQ(eeven.providerName(), "SunEC");
}
static ECPublicKey badECKey() {
diff --git a/test/jdk/com/sun/crypto/provider/DHKEM/java.base/com/sun/crypto/provider/EvenKEMImpl.java b/test/jdk/com/sun/crypto/provider/DHKEM/java.base/com/sun/crypto/provider/EvenKEMImpl.java
new file mode 100644
index 00000000000..dc478c25954
--- /dev/null
+++ b/test/jdk/com/sun/crypto/provider/DHKEM/java.base/com/sun/crypto/provider/EvenKEMImpl.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2024, 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 com.sun.crypto.provider;
+
+import java.security.*;
+import java.security.spec.*;
+import java.util.Arrays;
+
+// The alternate DHKEM implementation used by the Compliance.java test.
+public class EvenKEMImpl extends DHKEM {
+
+ public static boolean isEven(Key k) {
+ return Arrays.hashCode(k.getEncoded()) % 2 == 0;
+ }
+
+ @Override
+ public EncapsulatorSpi engineNewEncapsulator(
+ PublicKey pk, AlgorithmParameterSpec spec, SecureRandom secureRandom)
+ throws InvalidAlgorithmParameterException, InvalidKeyException {
+ if (!isEven(pk)) throw new InvalidKeyException("Only accept even keys");
+ return super.engineNewEncapsulator(pk, spec, secureRandom);
+ }
+
+ @Override
+ public DecapsulatorSpi engineNewDecapsulator(
+ PrivateKey sk, AlgorithmParameterSpec spec)
+ throws InvalidAlgorithmParameterException, InvalidKeyException {
+ if (!isEven(sk)) throw new InvalidKeyException("Only accept even keys");
+ return super.engineNewDecapsulator(sk, spec);
+ }
+}
diff --git a/test/jdk/javax/crypto/KEM/RSA_KEM.java b/test/jdk/javax/crypto/KEM/RSA_KEM.java
index c46ded77623..e666df432a6 100644
--- a/test/jdk/javax/crypto/KEM/RSA_KEM.java
+++ b/test/jdk/javax/crypto/KEM/RSA_KEM.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
* @modules java.base/sun.security.jca
* java.base/sun.security.rsa
* java.base/sun.security.util
+ * java.base/javax.crypto:+open
*/
import sun.security.jca.JCAUtil;
import sun.security.rsa.RSACore;
@@ -88,7 +89,7 @@ public static void main(String[] args) throws Exception {
KeyPair kp = g.generateKeyPair();
for (RSAKEMParameterSpec kspec : kspecs) {
SecretKey cek = KeyGenerator.getInstance("AES").generateKey();
- KEM kem1 = KEM.getInstance("RSA-KEM", p);
+ KEM kem1 = getKemImpl(p);
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, cek, new IvParameterSpec(iv));
byte[] ciphertext = c.doFinal(msg);
@@ -101,7 +102,7 @@ public static void main(String[] args) throws Exception {
AlgorithmParameters a = AlgorithmParameters.getInstance("RSA-KEM", p);
a.init(enc.params());
- KEM kem2 = KEM.getInstance("RSA-KEM", p);
+ KEM kem2 = getKemImpl(p);
KEM.Decapsulator d = kem2.newDecapsulator(kp.getPrivate(), a.getParameterSpec(AlgorithmParameterSpec.class));
SecretKey k = d.decapsulate(enc.encapsulation(), 0, d.secretSize(), "AES");
Cipher c3 = Cipher.getInstance(kspec.encAlg);
@@ -122,6 +123,14 @@ public static void main(String[] args) throws Exception {
}
}
+ // To bypass the JCE security provider signature check
+ private static KEM getKemImpl(Provider p) throws Exception {
+ var ctor = KEM.class.getDeclaredConstructor(
+ String.class, KEMSpi.class, Provider.class);
+ ctor.setAccessible(true);
+ return ctor.newInstance("RSA-KEM", new KEMImpl(), p);
+ }
+
static final String RSA_KEM = "1.2.840.113549.1.9.16.3.14";
static final String KEM_RSA = "1.0.18033.2.2.4";
From 3984a00ea91c2ea77072b5c48adfc9c89689b016 Mon Sep 17 00:00:00 2001
From: Alex Menkov
Date: Thu, 11 Jan 2024 21:12:31 +0000
Subject: [PATCH 29/66] 8322237: Heap dump contains duplicate thread records
for mounted virtual threads
Reviewed-by: sspitsyn
Backport-of: dd8ae616437398f957f9b4f09cf2c7f1d0bd0938
---
src/hotspot/share/services/heapDumper.cpp | 18 +++++++++++++++++-
.../vthread/HeapDump/VThreadInHeapDump.java | 19 ++++++++++++++++++-
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/src/hotspot/share/services/heapDumper.cpp b/src/hotspot/share/services/heapDumper.cpp
index a46101f6d8d..add86b338de 100644
--- a/src/hotspot/share/services/heapDumper.cpp
+++ b/src/hotspot/share/services/heapDumper.cpp
@@ -1641,6 +1641,19 @@ class ThreadDumper : public CHeapObj {
&& java_lang_VirtualThread::state(vt) != java_lang_VirtualThread::TERMINATED;
}
+ static bool is_vthread_mounted(oop vt) {
+ // The code should be consistent with the "mounted virtual thread" case
+ // (VM_HeapDumper::dump_stack_traces(), ThreadDumper::get_top_frame()).
+ // I.e. virtual thread is mounted if its carrierThread is not null
+ // and is_vthread_mounted() for the carrier thread returns true.
+ oop carrier_thread = java_lang_VirtualThread::carrier_thread(vt);
+ if (carrier_thread == nullptr) {
+ return false;
+ }
+ JavaThread* java_thread = java_lang_Thread::thread(carrier_thread);
+ return java_thread->is_vthread_mounted();
+ }
+
ThreadDumper(ThreadType thread_type, JavaThread* java_thread, oop thread_oop);
// affects frame_count
@@ -1918,7 +1931,10 @@ void HeapObjectDumper::do_object(oop o) {
if (o->is_instance()) {
// create a HPROF_GC_INSTANCE record for each object
DumperSupport::dump_instance(writer(), o, &_class_cache);
- if (java_lang_VirtualThread::is_instance(o) && ThreadDumper::should_dump_vthread(o)) {
+ // If we encounter an unmounted virtual thread it needs to be dumped explicitly
+ // (mounted virtual threads are dumped with their carriers).
+ if (java_lang_VirtualThread::is_instance(o)
+ && ThreadDumper::should_dump_vthread(o) && !ThreadDumper::is_vthread_mounted(o)) {
_vthread_dumper->dump_vthread(o, writer());
}
} else if (o->is_objArray()) {
diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java
index 7fe5abb800f..2243a1d37b6 100644
--- a/test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java
+++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java
@@ -26,7 +26,9 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -223,11 +225,22 @@ private static void verifyDump(File dumpFile) throws Exception {
// Log all threads with stack traces and stack references.
List threads = snapshot.getThreads();
List roots = Collections.list(snapshot.getRoots());
+ // And detect thread object duplicates.
+ Set uniqueThreads = new HashSet<>();
+
log("Threads:");
for (ThreadObject thread: threads) {
+ JavaHeapObject threadObj = snapshot.findThing(thread.getId());
+ JavaClass threadClass = threadObj.getClazz();
StackTrace st = thread.getStackTrace();
StackFrame[] frames = st.getFrames();
- log("thread " + thread.getIdString() + ", " + frames.length + " frames");
+ log("thread " + thread.getIdString() + " (" + threadClass.getName() + "), " + frames.length + " frames");
+
+ if (uniqueThreads.contains(thread.getId())) {
+ log(" - ERROR: duplicate");
+ } else {
+ uniqueThreads.add(thread.getId());
+ }
List stackRoots = findStackRoot(roots, thread);
for (int i = 0; i < frames.length; i++) {
@@ -250,6 +263,10 @@ private static void verifyDump(File dumpFile) throws Exception {
}
}
+ if (threads.size() != uniqueThreads.size()) {
+ throw new RuntimeException("Thread duplicates detected (" + (threads.size() - uniqueThreads.size()) + ")");
+ }
+
// Verify objects from thread stacks are dumped.
test(snapshot, VThreadInHeapDumpTarg.VThreadMountedReferenced.class);
test(snapshot, VThreadInHeapDumpTarg.PThreadReferenced.class);
From 46f1df38a0f972333d7ff93a00c7eb6b14d3dfb9 Mon Sep 17 00:00:00 2001
From: Joe Wang
Date: Fri, 12 Jan 2024 01:45:57 +0000
Subject: [PATCH 30/66] 8323571: Regression in source resolution process
Reviewed-by: naoto, iris
Backport-of: e4389d8dc224419b8c1ee08e9f2dea0f103c6845
---
.../internal/impl/XMLEntityManager.java | 42 ++--
.../unittest/common/catalog/NullIdTest.java | 201 ++++++++++++++++++
.../xml/jaxp/unittest/common/catalog/core.xsd | 97 +++++++++
.../jaxp/unittest/common/catalog/events.xsd | 35 +++
4 files changed, 357 insertions(+), 18 deletions(-)
create mode 100644 test/jaxp/javax/xml/jaxp/unittest/common/catalog/NullIdTest.java
create mode 100644 test/jaxp/javax/xml/jaxp/unittest/common/catalog/core.xsd
create mode 100644 test/jaxp/javax/xml/jaxp/unittest/common/catalog/events.xsd
diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java
index 6e5663bfa2c..f922849d5fa 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -94,7 +94,7 @@
* @author K.Venugopal SUN Microsystems
* @author Neeraj Bajaj SUN Microsystems
* @author Sunitha Reddy SUN Microsystems
- * @LastModified: Nov 2023
+ * @LastModified: Jan 2024
*/
public class XMLEntityManager implements XMLComponent, XMLEntityResolver {
@@ -1038,8 +1038,9 @@ public StaxXMLInputSource resolveEntityAsPerStax(XMLResourceIdentifier resourceI
}
// Step 2: custom catalog if specified
- if ((publicId != null || literalSystemId != null) &&
- staxInputSource == null && (fUseCatalog && fCatalogFile != null)) {
+ if (staxInputSource == null
+ && (publicId != null || literalSystemId != null)
+ && (fUseCatalog && fCatalogFile != null)) {
if (fCatalogResolver == null) {
fCatalogFeatures = JdkXmlUtils.getCatalogFeatures(fDefer, fCatalogFile, fPrefer, fResolve);
fCatalogResolver = CatalogManager.catalogResolver(fCatalogFeatures);
@@ -1049,8 +1050,9 @@ public StaxXMLInputSource resolveEntityAsPerStax(XMLResourceIdentifier resourceI
}
// Step 3: use the default JDK Catalog Resolver if Step 2's resolve is continue
- if ((publicId != null || literalSystemId != null) &&
- staxInputSource == null && JdkXmlUtils.isResolveContinue(fCatalogFeatures)) {
+ if (staxInputSource == null
+ && (publicId != null || literalSystemId != null)
+ && JdkXmlUtils.isResolveContinue(fCatalogFeatures)) {
initJdkCatalogResolver();
staxInputSource = resolveWithCatalogStAX(fDefCR, JdkCatalog.JDKCATALOG, publicId, literalSystemId);
@@ -1061,9 +1063,9 @@ public StaxXMLInputSource resolveEntityAsPerStax(XMLResourceIdentifier resourceI
// Note if both publicId and systemId are null, the resolution process continues as usual
if (staxInputSource != null) {
fISCreatedByResolver = true;
- } else if ((publicId == null && literalSystemId == null) ||
- (JdkXmlUtils.isResolveContinue(fCatalogFeatures) &&
- fSecurityManager.is(Limit.JDKCATALOG_RESOLVE, JdkConstants.CONTINUE))) {
+ } else if ((publicId == null && literalSystemId == null)
+ || (JdkXmlUtils.isResolveContinue(fCatalogFeatures)
+ && fSecurityManager.is(Limit.JDKCATALOG_RESOLVE, JdkConstants.CONTINUE))) {
staxInputSource = new StaxXMLInputSource(
new XMLInputSource(publicId, literalSystemId, baseSystemId, true), false);
}
@@ -1206,8 +1208,9 @@ public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) th
}
// Step 2: custom catalog if specified
- if ((publicId != null || literalSystemId != null || resourceIdentifier.getNamespace() !=null)
- && xmlInputSource == null && (fUseCatalog && fCatalogFile != null)) {
+ if (xmlInputSource == null
+ && (publicId != null || literalSystemId != null || resourceIdentifier.getNamespace() !=null)
+ && (fUseCatalog && fCatalogFile != null)) {
if (fCatalogResolver == null) {
fCatalogFeatures = JdkXmlUtils.getCatalogFeatures(fDefer, fCatalogFile, fPrefer, fResolve);
fCatalogResolver = CatalogManager.catalogResolver(fCatalogFeatures);
@@ -1217,8 +1220,9 @@ public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) th
}
// Step 3: use the default JDK Catalog Resolver if Step 2's resolve is continue
- if ((publicId != null || literalSystemId != null)
- && xmlInputSource == null && JdkXmlUtils.isResolveContinue(fCatalogFeatures)) {
+ if (xmlInputSource == null
+ && (publicId != null || literalSystemId != null)
+ && JdkXmlUtils.isResolveContinue(fCatalogFeatures)) {
initJdkCatalogResolver();
// unlike a custom catalog, the JDK Catalog only contains entity references
xmlInputSource = resolveEntity(fDefCR, publicId, literalSystemId, baseSystemId);
@@ -1226,11 +1230,13 @@ public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) th
// Step 4: default resolution if not resolved by a resolver and the RESOLVE
// feature is set to 'continue'
- // Note if both publicId and systemId are null, the resolution process continues as usual
- if ((publicId == null && literalSystemId == null) ||
- ((xmlInputSource == null) && JdkXmlUtils.isResolveContinue(fCatalogFeatures) &&
- fSecurityManager.is(Limit.JDKCATALOG_RESOLVE, JdkConstants.CONTINUE))) {
- xmlInputSource = new XMLInputSource(publicId, literalSystemId, baseSystemId, false);
+ if (xmlInputSource == null) {
+ // Note if both publicId and systemId are null, the resolution process continues as usual
+ if ((publicId == null && literalSystemId == null) ||
+ (JdkXmlUtils.isResolveContinue(fCatalogFeatures) &&
+ fSecurityManager.is(Limit.JDKCATALOG_RESOLVE, JdkConstants.CONTINUE))) {
+ xmlInputSource = new XMLInputSource(publicId, literalSystemId, baseSystemId, false);
+ }
}
return xmlInputSource;
diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/catalog/NullIdTest.java b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/NullIdTest.java
new file mode 100644
index 00000000000..442f13f4927
--- /dev/null
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/NullIdTest.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2024, 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 common.catalog;
+
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.SAXException;
+
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.SchemaFactory;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.util.Objects.requireNonNull;
+import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
+import static javax.xml.catalog.CatalogManager.catalogResolver;
+import javax.xml.catalog.CatalogResolver;
+import javax.xml.validation.Validator;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8323571
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng common.catalog.NullIdTest
+ * @summary Verifies null values are handled properly in the source resolution
+ * process.
+ */
+public class NullIdTest {
+ private static final Map SCHEMAS;
+ // Source Level JDK 8
+ static {
+ Map map = new HashMap<>();
+ map.put("https://schemas.opentest4j.org/reporting/events/0.1.0", "events.xsd");
+ map.put("https://schemas.opentest4j.org/reporting/core/0.1.0", "core.xsd");
+ SCHEMAS = Collections.unmodifiableMap(map);
+ }
+
+ /*
+ * Verifies that the source resolution process recognizes the custom InputSource
+ * correctly even though the public and system IDs are null.
+ */
+ @Test
+ public void test() throws Exception {
+ String xml = "";
+ validate(new StreamSource(new StringReader(xml)));
+ System.out.println("Successfully validated");
+ }
+
+ private static void validate(Source source) throws SAXException, IOException {
+ SchemaFactory schemaFactory = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
+ Validator validator = schemaFactory.newSchema().newValidator();
+ validator.setResourceResolver(createResourceResolver());
+ validator.validate(source);
+ }
+
+ private static LSResourceResolver createResourceResolver() {
+ return (type, namespaceURI, publicId, systemId, baseURI) -> {
+ if (namespaceURI != null) {
+ if (SCHEMAS.containsKey(namespaceURI)) {
+ CustomLSInputImpl input = new CustomLSInputImpl();
+ input.setPublicId(publicId);
+ String schema = SCHEMAS.get(namespaceURI);
+ input.setSystemId(requireNonNull(NullIdTest.class.getResource(schema)).toExternalForm());
+ input.setBaseURI(baseURI);
+ InputStream stream = NullIdTest.class.getResourceAsStream(schema);
+ input.setCharacterStream(new InputStreamReader(requireNonNull(stream)));
+ return input;
+ }
+ }
+ if (systemId != null) {
+ CatalogFeatures features = CatalogFeatures.builder()
+ .with(CatalogFeatures.Feature.RESOLVE, "continue")
+ .build();
+ CatalogResolver catalogResolver = catalogResolver(features);
+ return catalogResolver.resolveResource(type, namespaceURI, publicId, systemId, baseURI);
+ }
+ return null;
+ };
+ }
+
+ static class CustomLSInputImpl implements LSInput {
+
+ private Reader characterStream;
+ private InputStream byteStream;
+ private String stringData;
+ private String systemId;
+ private String publicId;
+ private String baseURI;
+ private String encoding;
+ private boolean certifiedText;
+
+ @Override
+ public Reader getCharacterStream() {
+ return characterStream;
+ }
+
+ @Override
+ public void setCharacterStream(Reader characterStream) {
+ this.characterStream = characterStream;
+ }
+
+ @Override
+ public InputStream getByteStream() {
+ return byteStream;
+ }
+
+ @Override
+ public void setByteStream(InputStream byteStream) {
+ this.byteStream = byteStream;
+ }
+
+ @Override
+ public String getStringData() {
+ return stringData;
+ }
+
+ @Override
+ public void setStringData(String stringData) {
+ this.stringData = stringData;
+ }
+
+ @Override
+ public String getSystemId() {
+ return systemId;
+ }
+
+ @Override
+ public void setSystemId(String systemId) {
+ this.systemId = systemId;
+ }
+
+ @Override
+ public String getPublicId() {
+ return publicId;
+ }
+
+ @Override
+ public void setPublicId(String publicId) {
+ this.publicId = publicId;
+ }
+
+ @Override
+ public String getBaseURI() {
+ return baseURI;
+ }
+
+ @Override
+ public void setBaseURI(String baseURI) {
+ this.baseURI = baseURI;
+ }
+
+ @Override
+ public String getEncoding() {
+ return encoding;
+ }
+
+ @Override
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ @Override
+ public boolean getCertifiedText() {
+ return certifiedText;
+ }
+
+ @Override
+ public void setCertifiedText(boolean certifiedText) {
+ this.certifiedText = certifiedText;
+ }
+ }
+}
diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/catalog/core.xsd b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/core.xsd
new file mode 100644
index 00000000000..41b0de3425b
--- /dev/null
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/core.xsd
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/catalog/events.xsd b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/events.xsd
new file mode 100644
index 00000000000..56d5a431211
--- /dev/null
+++ b/test/jaxp/javax/xml/jaxp/unittest/common/catalog/events.xsd
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From 6022e73d7369bbdc145e2f9a427323286cf6e4d6 Mon Sep 17 00:00:00 2001
From: David Holmes
Date: Fri, 12 Jan 2024 02:14:16 +0000
Subject: [PATCH 31/66] 8322513: Build failure with minimal
Reviewed-by: bpb, jpai
Backport-of: 7db69e6a1292829b13da0c3c2b37c8758df94932
---
src/hotspot/share/runtime/handshake.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/hotspot/share/runtime/handshake.cpp b/src/hotspot/share/runtime/handshake.cpp
index a57076c021a..3919a89789c 100644
--- a/src/hotspot/share/runtime/handshake.cpp
+++ b/src/hotspot/share/runtime/handshake.cpp
@@ -487,10 +487,12 @@ HandshakeOperation* HandshakeState::get_op_for_self(bool allow_suspend, bool che
assert(_handshakee == Thread::current(), "Must be called by self");
assert(_lock.owned_by_self(), "Lock must be held");
assert(allow_suspend || !check_async_exception, "invalid case");
+#if INCLUDE_JVMTI
if (allow_suspend && _handshakee->is_disable_suspend()) {
// filter out suspend operations while JavaThread is in disable_suspend mode
allow_suspend = false;
}
+#endif
if (!allow_suspend) {
return _queue.peek(no_suspend_no_async_exception_filter);
} else if (check_async_exception && !_async_exceptions_blocked) {
From 749f749f0413452abdfc6501864a2a059b6de253 Mon Sep 17 00:00:00 2001
From: Thomas Schatzl
Date: Fri, 12 Jan 2024 09:09:05 +0000
Subject: [PATCH 32/66] 8323066: gc/g1/TestSkipRebuildRemsetPhase.java fails
with 'Skipping Remembered Set Rebuild.' missing
Reviewed-by: ayang
Backport-of: ee98d262181f5822609674c71c85ad4576ac1632
---
test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java b/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java
index 4c7190ada02..c2448416efa 100644
--- a/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java
+++ b/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java
@@ -45,7 +45,7 @@ public static void main(String[] args) throws Exception {
"-XX:+UnlockExperimentalVMOptions",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
- "-XX:G1MixedGCLiveThresholdPercent=20",
+ "-XX:G1MixedGCLiveThresholdPercent=0",
"-Xlog:gc+marking=debug,gc+phases=debug,gc+remset+tracking=trace",
"-Xms10M",
"-Xmx10M",
From 07a8911ce8d6c0e791544c0fd38e04d9a5ca2cd5 Mon Sep 17 00:00:00 2001
From: Jan Lahoda
Date: Fri, 12 Jan 2024 10:01:40 +0000
Subject: [PATCH 33/66] 8322003: JShell - Incorrect type inference in lists of
records implementing interfaces
Reviewed-by: vromero
Backport-of: 57a65fe436a3617d64bbf0b02d4c7f7c2551448f
---
.../sun/tools/javac/parser/JavacParser.java | 24 ++--
.../share/classes/jdk/jshell/TaskFactory.java | 107 ++++++++++++++----
test/langtools/jdk/jshell/VariablesTest.java | 13 ++-
3 files changed, 110 insertions(+), 34 deletions(-)
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
index d83fb85b7f2..c962862e4bf 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
@@ -967,6 +967,20 @@ public JCExpression parseType(boolean allowVar, List annotations)
return result;
}
+ protected JCExpression parseIntersectionType(int pos, JCExpression firstType) {
+ JCExpression t = firstType;
+ int pos1 = pos;
+ List targets = List.of(t);
+ while (token.kind == AMP) {
+ accept(AMP);
+ targets = targets.prepend(parseType());
+ }
+ if (targets.length() > 1) {
+ t = toP(F.at(pos1).TypeIntersection(targets.reverse()));
+ }
+ return t;
+ }
+
public JCExpression unannotatedType(boolean allowVar) {
return unannotatedType(allowVar, TYPE);
}
@@ -1337,15 +1351,7 @@ protected JCExpression term3() {
case CAST:
accept(LPAREN);
selectTypeMode();
- int pos1 = pos;
- List targets = List.of(t = parseType());
- while (token.kind == AMP) {
- accept(AMP);
- targets = targets.prepend(parseType());
- }
- if (targets.length() > 1) {
- t = toP(F.at(pos1).TypeIntersection(targets.reverse()));
- }
+ t = parseIntersectionType(pos, parseType());
accept(RPAREN);
selectExprMode();
JCExpression t1 = term3();
diff --git a/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java b/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java
index ac777435102..5360e0d517f 100644
--- a/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java
+++ b/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java
@@ -80,8 +80,13 @@
import com.sun.tools.javac.comp.Enter;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.comp.Resolve;
+import com.sun.tools.javac.parser.JavacParser;
+import com.sun.tools.javac.parser.Lexer;
import com.sun.tools.javac.parser.Parser;
import com.sun.tools.javac.parser.ParserFactory;
+import com.sun.tools.javac.parser.ScannerFactory;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.AMP;
+import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCTypeCast;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
@@ -363,7 +368,7 @@ private ParseTask(SourceHandler sh,
JavacTaskImpl task,
DiagnosticCollector diagnostics,
boolean forceExpression) {
- super(sh, task, diagnostics);
+ super(sh, task, diagnostics, false);
ReplParserFactory.preRegister(context, forceExpression);
cuts = parse();
units = Util.stream(cuts)
@@ -402,7 +407,7 @@ class AnalyzeTask extends BaseTask {
private AnalyzeTask(SourceHandler sh,
JavacTaskImpl task,
DiagnosticCollector diagnostics) {
- super(sh, task, diagnostics);
+ super(sh, task, diagnostics, true);
cuts = analyze();
}
@@ -440,7 +445,7 @@ class CompileTask extends BaseTask {
CompileTask(SourceHandlersh,
JavacTaskImpl jti,
DiagnosticCollector diagnostics) {
- super(sh, jti, diagnostics);
+ super(sh, jti, diagnostics, true);
}
boolean compile() {
@@ -504,11 +509,15 @@ abstract class BaseTask {
private BaseTask(SourceHandler sh,
JavacTaskImpl task,
- DiagnosticCollector diagnostics) {
+ DiagnosticCollector diagnostics,
+ boolean analyzeParserFactory) {
this.sourceHandler = sh;
this.task = task;
context = task.getContext();
this.diagnostics = diagnostics;
+ if (analyzeParserFactory) {
+ JShellAnalyzeParserFactory.preRegister(context);
+ }
}
abstract Iterable extends CompilationUnitTree> cuTrees();
@@ -693,7 +702,7 @@ private void setVariableType(VarSnippet s) {
Symtab syms = Symtab.instance(context);
Names names = Names.instance(context);
Log log = Log.instance(context);
- ParserFactory parserFactory = ParserFactory.instance(context);
+ JShellAnalyzeParserFactory parserFactory = (JShellAnalyzeParserFactory) ParserFactory.instance(context);
Attr attr = Attr.instance(context);
Enter enter = Enter.instance(context);
DisableAccessibilityResolve rs = (DisableAccessibilityResolve) Resolve.instance(context);
@@ -709,26 +718,28 @@ private void setVariableType(VarSnippet s) {
//ignore any errors:
JavaFileObject prev = log.useSource(null);
DiscardDiagnosticHandler h = new DiscardDiagnosticHandler(log);
- try {
- //parse the type as a cast, i.e. "() x". This is to support
- //intersection types:
- CharBuffer buf = CharBuffer.wrap(("(" + typeName +")x\u0000").toCharArray(), 0, typeName.length() + 3);
- Parser parser = parserFactory.newParser(buf, false, false, false);
- JCExpression expr = parser.parseExpression();
- if (expr.hasTag(Tag.TYPECAST)) {
- //if parsed OK, attribute and set the type:
- var2OriginalType.put(field, field.type);
-
- JCTypeCast tree = (JCTypeCast) expr;
- rs.runWithoutAccessChecks(() -> {
- field.type = attr.attribType(tree.clazz,
- enter.getEnvs().iterator().next().enclClass.sym);
- });
+ parserFactory.runPermitIntersectionTypes(() -> {
+ try {
+ //parse the type as a cast, i.e. "() x". This is to support
+ //intersection types:
+ CharBuffer buf = CharBuffer.wrap(("(" + typeName +")x\u0000").toCharArray(), 0, typeName.length() + 3);
+ Parser parser = parserFactory.newParser(buf, false, false, false);
+ JCExpression expr = parser.parseExpression();
+ if (expr.hasTag(Tag.TYPECAST)) {
+ //if parsed OK, attribute and set the type:
+ var2OriginalType.put(field, field.type);
+
+ JCTypeCast tree = (JCTypeCast) expr;
+ rs.runWithoutAccessChecks(() -> {
+ field.type = attr.attribType(tree.clazz,
+ enter.getEnvs().iterator().next().enclClass.sym);
+ });
+ }
+ } finally {
+ log.popDiagnosticHandler(h);
+ log.useSource(prev);
}
- } finally {
- log.popDiagnosticHandler(h);
- log.useSource(prev);
- }
+ });
}
}
}
@@ -777,4 +788,52 @@ public boolean isAccessible(Env env, Type site, Symbol sym, boolean
private static final class Marker {}
}
+ private static final class JShellAnalyzeParserFactory extends ParserFactory {
+ public static void preRegister(Context context) {
+ if (context.get(Marker.class) == null) {
+ context.put(parserFactoryKey, ((Factory) c -> new JShellAnalyzeParserFactory(c)));
+ context.put(Marker.class, new Marker());
+ }
+ }
+
+ private final ScannerFactory scannerFactory;
+ private boolean permitIntersectionTypes;
+
+ public JShellAnalyzeParserFactory(Context context) {
+ super(context);
+ this.scannerFactory = ScannerFactory.instance(context);
+ }
+
+ /**Run the given Runnable with intersection type permitted.
+ *
+ * @param r Runnnable to run
+ */
+ public void runPermitIntersectionTypes(Runnable r) {
+ boolean prevPermitIntersectionTypes = permitIntersectionTypes;
+ try {
+ permitIntersectionTypes = true;
+ r.run();
+ } finally {
+ permitIntersectionTypes = prevPermitIntersectionTypes;
+ }
+ }
+
+ @Override
+ public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap, boolean parseModuleInfo) {
+ com.sun.tools.javac.parser.Lexer lexer = scannerFactory.newScanner(input, keepDocComments);
+ return new JavacParser(this, lexer, keepDocComments, keepLineMap, keepEndPos, parseModuleInfo) {
+ @Override
+ public JCExpression parseType(boolean allowVar, com.sun.tools.javac.util.List annotations) {
+ int pos = token.pos;
+ JCExpression t = super.parseType(allowVar, annotations);
+ if (permitIntersectionTypes) {
+ t = parseIntersectionType(pos, t);
+ }
+ return t;
+ }
+ };
+ }
+
+ private static final class Marker {}
+ }
}
diff --git a/test/langtools/jdk/jshell/VariablesTest.java b/test/langtools/jdk/jshell/VariablesTest.java
index 56546955e08..98a543e77a9 100644
--- a/test/langtools/jdk/jshell/VariablesTest.java
+++ b/test/langtools/jdk/jshell/VariablesTest.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8144903 8177466 8191842 8211694 8213725 8239536 8257236 8252409 8294431 8322532
+ * @bug 8144903 8177466 8191842 8211694 8213725 8239536 8257236 8252409 8294431 8322003 8322532
* @summary Tests for EvaluationState.variables
* @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api
@@ -627,4 +627,15 @@ public void underscoreAsLambdaParameter() { //JDK-8322532
" int i;", true);
}
+ public void intersectionTypeAsTypeArgument() { //JDK-8322003
+ assertEval("interface Shape {}");
+ assertEval("record Square(int edge) implements Shape {}");
+ assertEval("record Circle(int radius) implements Shape {}");
+ assertEval("java.util.function.Consumer printShape = System.out::println;");
+ assertEval("Square square = new Square(1);");
+ assertEval("Circle circle = new Circle(1);");
+ assertEval("var shapes = java.util.List.of(square, circle);");
+ assertEval("shapes.forEach(printShape);");
+ }
+
}
From d3f18d0469d2eafbcfa527358c2817df24fde2c3 Mon Sep 17 00:00:00 2001
From: Serguei Spitsyn
Date: Fri, 12 Jan 2024 10:17:48 +0000
Subject: [PATCH 34/66] 8321685: Missing ResourceMark in code called from
JvmtiEnvBase::get_vthread_jvf
Reviewed-by: amenkov
Backport-of: 2806adee2d8cca6bc215f285888631799bd02eac
---
src/hotspot/share/prims/jvmtiEnvBase.cpp | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp
index 9d6296ee316..6a3ee718709 100644
--- a/src/hotspot/share/prims/jvmtiEnvBase.cpp
+++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, 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
@@ -2407,6 +2407,7 @@ UpdateForPopTopFrameClosure::doit(Thread *target, bool self) {
void
SetFramePopClosure::do_thread(Thread *target) {
Thread* current = Thread::current();
+ ResourceMark rm(current); // vframes are resource allocated
JavaThread* java_thread = JavaThread::cast(target);
if (java_thread->is_exiting()) {
@@ -2433,6 +2434,9 @@ SetFramePopClosure::do_thread(Thread *target) {
void
SetFramePopClosure::do_vthread(Handle target_h) {
+ Thread* current = Thread::current();
+ ResourceMark rm(current); // vframes are resource allocated
+
if (!_self && !JvmtiVTSuspender::is_vthread_suspended(target_h())) {
_result = JVMTI_ERROR_THREAD_NOT_SUSPENDED;
return;
From 71a05bf03f4789f04cdba205c4fd3dc6d2dd0a65 Mon Sep 17 00:00:00 2001
From: Serguei Spitsyn
Date: Fri, 12 Jan 2024 11:57:01 +0000
Subject: [PATCH 35/66] 8322538: remove fatal from JVM_VirtualThread functions
for !INCLUDE_JVMTI
Reviewed-by: dholmes
Backport-of: aff659aaf7c73ff8eb903fd3e426e1b42ea6d95a
---
src/hotspot/share/prims/jvm.cpp | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp
index bd6eda2d468..9a8a9a5bec0 100644
--- a/src/hotspot/share/prims/jvm.cpp
+++ b/src/hotspot/share/prims/jvm.cpp
@@ -3933,8 +3933,6 @@ JVM_ENTRY(void, JVM_VirtualThreadStart(JNIEnv* env, jobject vthread))
// set VTMS transition bit value in JavaThread and java.lang.VirtualThread object
JvmtiVTMSTransitionDisabler::set_is_in_VTMS_transition(thread, vthread, false);
}
-#else
- fatal("Should only be called with JVMTI enabled");
#endif
JVM_END
@@ -3950,8 +3948,6 @@ JVM_ENTRY(void, JVM_VirtualThreadEnd(JNIEnv* env, jobject vthread))
// set VTMS transition bit value in JavaThread and java.lang.VirtualThread object
JvmtiVTMSTransitionDisabler::set_is_in_VTMS_transition(thread, vthread, true);
}
-#else
- fatal("Should only be called with JVMTI enabled");
#endif
JVM_END
@@ -3969,8 +3965,6 @@ JVM_ENTRY(void, JVM_VirtualThreadMount(JNIEnv* env, jobject vthread, jboolean hi
// set VTMS transition bit value in JavaThread and java.lang.VirtualThread object
JvmtiVTMSTransitionDisabler::set_is_in_VTMS_transition(thread, vthread, hide);
}
-#else
- fatal("Should only be called with JVMTI enabled");
#endif
JVM_END
@@ -3988,8 +3982,6 @@ JVM_ENTRY(void, JVM_VirtualThreadUnmount(JNIEnv* env, jobject vthread, jboolean
// set VTMS transition bit value in JavaThread and java.lang.VirtualThread object
JvmtiVTMSTransitionDisabler::set_is_in_VTMS_transition(thread, vthread, hide);
}
-#else
- fatal("Should only be called with JVMTI enabled");
#endif
JVM_END
@@ -4003,8 +3995,6 @@ JVM_ENTRY(void, JVM_VirtualThreadHideFrames(JNIEnv* env, jobject vthread, jboole
assert(!thread->is_in_VTMS_transition(), "sanity check");
assert(thread->is_in_tmp_VTMS_transition() != (bool)hide, "sanity check");
thread->toggle_is_in_tmp_VTMS_transition();
-#else
- fatal("Should only be called with JVMTI enabled");
#endif
JVM_END
@@ -4019,8 +4009,6 @@ JVM_ENTRY(void, JVM_VirtualThreadDisableSuspend(JNIEnv* env, jobject vthread, jb
assert(thread->is_disable_suspend() != (bool)enter,
"nested or unbalanced monitor enter/exit is not allowed");
thread->toggle_is_disable_suspend();
-#else
- fatal("Should only be called with JVMTI enabled");
#endif
JVM_END
From d115295df8ccfec8670878ab5a7dc8d8661025d9 Mon Sep 17 00:00:00 2001
From: Tobias Hartmann
Date: Fri, 12 Jan 2024 12:42:36 +0000
Subject: [PATCH 36/66] 8323190: Segfault during deoptimization of C2-compiled
code
Reviewed-by: epeter
Backport-of: ed182223655feee5356d42a94dd74950e9595724
---
src/hotspot/share/opto/output.cpp | 30 ++++++++-
.../escapeAnalysis/TestInvalidLocation.java | 65 +++++++++++++++++++
2 files changed, 92 insertions(+), 3 deletions(-)
create mode 100644 test/hotspot/jtreg/compiler/escapeAnalysis/TestInvalidLocation.java
diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp
index 64d98f27ff6..9481b91ce39 100644
--- a/src/hotspot/share/opto/output.cpp
+++ b/src/hotspot/share/opto/output.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2024, 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
@@ -775,7 +775,7 @@ void PhaseOutput::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local,
SafePointScalarMergeNode* smerge = local->as_SafePointScalarMerge();
ObjectMergeValue* mv = (ObjectMergeValue*) sv_for_node_id(objs, smerge->_idx);
- if (mv == NULL) {
+ if (mv == nullptr) {
GrowableArray deps;
int merge_pointer_idx = smerge->merge_pointer_idx(sfpt->jvms());
@@ -783,7 +783,7 @@ void PhaseOutput::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local,
assert(deps.length() == 1, "missing value");
int selector_idx = smerge->selector_idx(sfpt->jvms());
- (void)FillLocArray(1, NULL, sfpt->in(selector_idx), &deps, NULL);
+ (void)FillLocArray(1, nullptr, sfpt->in(selector_idx), &deps, nullptr);
assert(deps.length() == 2, "missing value");
mv = new ObjectMergeValue(smerge->_idx, deps.at(0), deps.at(1));
@@ -1085,6 +1085,30 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) {
}
scval = sv;
}
+ } else if (obj_node->is_SafePointScalarMerge()) {
+ SafePointScalarMergeNode* smerge = obj_node->as_SafePointScalarMerge();
+ ObjectMergeValue* mv = (ObjectMergeValue*) sv_for_node_id(objs, smerge->_idx);
+
+ if (mv == nullptr) {
+ GrowableArray deps;
+
+ int merge_pointer_idx = smerge->merge_pointer_idx(youngest_jvms);
+ FillLocArray(0, sfn, sfn->in(merge_pointer_idx), &deps, objs);
+ assert(deps.length() == 1, "missing value");
+
+ int selector_idx = smerge->selector_idx(youngest_jvms);
+ FillLocArray(1, nullptr, sfn->in(selector_idx), &deps, nullptr);
+ assert(deps.length() == 2, "missing value");
+
+ mv = new ObjectMergeValue(smerge->_idx, deps.at(0), deps.at(1));
+ set_sv_for_object_node(objs, mv);
+
+ for (uint i = 1; i < smerge->req(); i++) {
+ Node* obj_node = smerge->in(i);
+ FillLocArray(mv->possible_objects()->length(), sfn, obj_node, mv->possible_objects(), objs);
+ }
+ }
+ scval = mv;
} else if (!obj_node->is_Con()) {
OptoReg::Name obj_reg = C->regalloc()->get_reg_first(obj_node);
if( obj_node->bottom_type()->base() == Type::NarrowOop ) {
diff --git a/test/hotspot/jtreg/compiler/escapeAnalysis/TestInvalidLocation.java b/test/hotspot/jtreg/compiler/escapeAnalysis/TestInvalidLocation.java
new file mode 100644
index 00000000000..f97532abfb1
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/escapeAnalysis/TestInvalidLocation.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2024, 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 8323190
+ * @summary C2 Segfaults during code generation because of unhandled SafePointScalarMerge monitor debug info.
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -Xcomp -XX:+ReduceAllocationMerges TestInvalidLocation
+ */
+
+public class TestInvalidLocation {
+ static boolean var2 = true;
+ static double[] var4 = new double[1];
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 10; i++) {
+ System.out.println(test());
+ }
+ }
+
+ static Class0 test() {
+ double[] var14;
+ double var3;
+ StringBuilder var1 = new StringBuilder();
+ Class0 var0 = Class1.Class1_sfield0;
+ synchronized (var2 ? new StringBuilder() : var1) {
+ var14 = var4;
+ for (int i0 = 0; i0 < var0.Class0_field0.length && i0 < var14.length; i0 = 1) {
+ var3 = var14[i0];
+ }
+ }
+ return var0;
+ }
+
+ static class Class0 {
+ double[] Class0_field0;
+ Class0() {
+ Class0_field0 = new double[] { 85.42200639495138 };
+ }
+ }
+
+ class Class1 {
+ static Class0 Class1_sfield0 = new Class0();
+ }
+}
From 3909d74af562006ff8c117a5cef99dbbbde4c24d Mon Sep 17 00:00:00 2001
From: Per Minborg
Date: Fri, 12 Jan 2024 14:41:43 +0000
Subject: [PATCH 37/66] 8321786: SegmentAllocator:allocateFrom(ValueLayout,
MemorySegment,ValueLayout,long,long) spec mismatch in exception scenario
Reviewed-by: mcimadamore
Backport-of: 7edd10e5fa71dafbbad23455553b7f5ff0a75ac9
---
.../java/lang/foreign/MemoryLayout.java | 2 +-
.../java/lang/foreign/MemorySegment.java | 42 +++++++++-
.../java/lang/foreign/SegmentAllocator.java | 6 +-
.../foreign/AbstractMemorySegmentImpl.java | 8 +-
.../classes/jdk/internal/foreign/Utils.java | 21 +++--
.../foreign/layout/AbstractLayout.java | 9 +--
.../foreign/layout/MemoryLayoutUtil.java | 7 --
test/jdk/java/foreign/TestLayouts.java | 4 +-
.../foreign/TestMemoryAccessInstance.java | 7 ++
.../java/foreign/TestScopedOperations.java | 3 +
.../java/foreign/TestSegmentAllocators.java | 77 +++++++++++++++++++
test/jdk/java/foreign/TestSegmentCopy.java | 60 +++++++++++++++
test/jdk/java/foreign/TestSegments.java | 11 ++-
13 files changed, 218 insertions(+), 39 deletions(-)
diff --git a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java
index 321d9b09bad..8a2b3b4df30 100644
--- a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java
+++ b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java
@@ -1016,7 +1016,7 @@ static PaddingLayout paddingLayout(long byteSize) {
* @throws IllegalArgumentException if {@code elementLayout.byteSize() % elementLayout.byteAlignment() != 0}
*/
static SequenceLayout sequenceLayout(long elementCount, MemoryLayout elementLayout) {
- MemoryLayoutUtil.requireNonNegative(elementCount);
+ Utils.checkNonNegativeArgument(elementCount, "elementCount");
Objects.requireNonNull(elementLayout);
Utils.checkElementAlignment(elementLayout,
"Element layout size is not multiple of alignment");
diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
index da255b9912b..faf28b01bf0 100644
--- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
+++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java
@@ -44,6 +44,7 @@
import jdk.internal.foreign.AbstractMemorySegmentImpl;
import jdk.internal.foreign.MemorySessionImpl;
import jdk.internal.foreign.SegmentFactories;
+import jdk.internal.foreign.Utils;
import jdk.internal.javac.Restricted;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.vm.annotation.ForceInline;
@@ -1591,6 +1592,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
*/
byte get(ValueLayout.OfByte layout, long offset);
@@ -1609,6 +1611,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
*/
@@ -1629,6 +1632,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
*/
boolean get(ValueLayout.OfBoolean layout, long offset);
@@ -1647,6 +1651,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
*/
@@ -1667,6 +1672,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
*/
char get(ValueLayout.OfChar layout, long offset);
@@ -1685,6 +1691,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
*/
@@ -1705,6 +1712,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
*/
short get(ValueLayout.OfShort layout, long offset);
@@ -1723,6 +1731,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
*/
@@ -1743,6 +1752,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
*/
int get(ValueLayout.OfInt layout, long offset);
@@ -1761,6 +1771,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
*/
@@ -1781,6 +1792,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
*/
float get(ValueLayout.OfFloat layout, long offset);
@@ -1799,6 +1811,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
*/
@@ -1819,6 +1832,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
*/
long get(ValueLayout.OfLong layout, long offset);
@@ -1837,6 +1851,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
*/
@@ -1857,6 +1872,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
*/
double get(ValueLayout.OfDouble layout, long offset);
@@ -1875,6 +1891,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
*/
@@ -1905,6 +1922,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in {@code T}
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
+ * or {@code offset < 0}
*/
MemorySegment get(AddressLayout layout, long offset);
@@ -1923,8 +1941,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* incompatible with the alignment constraint
* in the provided layout
* @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()}
- * @throws UnsupportedOperationException if this segment is
- * {@linkplain #isReadOnly() read-only}
+ * or {@code offset < 0}
* @throws IllegalArgumentException if {@code value} is not a
* {@linkplain #isNative() native} segment
* @throws IllegalArgumentException if this segment is
@@ -1951,6 +1968,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
*/
byte getAtIndex(ValueLayout.OfByte layout, long index);
@@ -1973,6 +1991,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
*/
boolean getAtIndex(ValueLayout.OfBoolean layout, long index);
@@ -1995,6 +2014,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
*/
char getAtIndex(ValueLayout.OfChar layout, long index);
@@ -2017,7 +2037,8 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
- * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
+ * or {@code index < 0}
+ * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/
void setAtIndex(ValueLayout.OfChar layout, long index, char value);
@@ -2040,6 +2061,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
*/
short getAtIndex(ValueLayout.OfShort layout, long index);
@@ -2061,6 +2083,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/
void setAtIndex(ValueLayout.OfByte layout, long index, byte value);
@@ -2084,6 +2107,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/
void setAtIndex(ValueLayout.OfBoolean layout, long index, boolean value);
@@ -2107,6 +2131,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/
void setAtIndex(ValueLayout.OfShort layout, long index, short value);
@@ -2130,6 +2155,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
*/
int getAtIndex(ValueLayout.OfInt layout, long index);
@@ -2152,6 +2178,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/
void setAtIndex(ValueLayout.OfInt layout, long index, int value);
@@ -2175,6 +2202,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
*/
float getAtIndex(ValueLayout.OfFloat layout, long index);
@@ -2197,6 +2225,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/
void setAtIndex(ValueLayout.OfFloat layout, long index, float value);
@@ -2220,6 +2249,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
*/
long getAtIndex(ValueLayout.OfLong layout, long index);
@@ -2242,6 +2272,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/
void setAtIndex(ValueLayout.OfLong layout, long index, long value);
@@ -2265,6 +2296,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
*/
double getAtIndex(ValueLayout.OfDouble layout, long index);
@@ -2287,6 +2319,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
* @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only}
*/
void setAtIndex(ValueLayout.OfDouble layout, long index, double value);
@@ -2319,6 +2352,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* in {@code T}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
+ * or {@code index < 0}
*/
MemorySegment getAtIndex(AddressLayout layout, long index);
@@ -2341,7 +2375,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr
* @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()}
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows
* @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()}
- * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}
+ * or {@code index < 0}
* @throws IllegalArgumentException if {@code value} is not a {@linkplain #isNative() native} segment
* @throws IllegalArgumentException if this segment is
* {@linkplain #isReadOnly() read-only}
diff --git a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java
index 6be9d949ea6..6c9cf51bee8 100644
--- a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java
+++ b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java
@@ -33,6 +33,7 @@
import jdk.internal.foreign.ArenaImpl;
import jdk.internal.foreign.SlicingAllocator;
import jdk.internal.foreign.StringSupport;
+import jdk.internal.foreign.Utils;
import jdk.internal.vm.annotation.ForceInline;
/**
@@ -390,9 +391,10 @@ default MemorySegment allocateFrom(AddressLayout layout, MemorySegment value) {
* with {@code source} is not {@linkplain MemorySegment.Scope#isAlive() alive}
* @throws WrongThreadException if this method is called from a thread {@code T},
* such that {@code source.isAccessibleBy(T) == false}
- * @throws IndexOutOfBoundsException if {@code elementCount * sourceElementLayout.byteSize()} overflows
+ * @throws IllegalArgumentException if {@code elementCount * sourceElementLayout.byteSize()} overflows
+ * @throws IllegalArgumentException if {@code elementCount < 0}
* @throws IndexOutOfBoundsException if {@code sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())}
- * @throws IndexOutOfBoundsException if either {@code sourceOffset} or {@code elementCount} are {@code < 0}
+ * @throws IndexOutOfBoundsException if {@code sourceOffset < 0}
*/
@ForceInline
default MemorySegment allocateFrom(ValueLayout elementLayout,
diff --git a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java
index 305594952d4..0efe62c1e4f 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java
@@ -153,9 +153,7 @@ public final MemorySegment reinterpret(Arena arena, Consumer clea
public MemorySegment reinterpretInternal(Class> callerClass, long newSize, Scope scope, Consumer cleanup) {
Reflection.ensureNativeAccess(callerClass, MemorySegment.class, "reinterpret");
- if (newSize < 0) {
- throw new IllegalArgumentException("newSize < 0");
- }
+ Utils.checkNonNegativeArgument(newSize, "newSize");
if (!isNative()) throw new UnsupportedOperationException("Not a native segment");
Runnable action = cleanup != null ?
() -> cleanup.accept(SegmentFactories.makeNativeSegmentUnchecked(address(), newSize)) :
@@ -594,6 +592,7 @@ public static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout,
MemorySegment dstSegment, ValueLayout dstElementLayout, long dstOffset,
long elementCount) {
+ Utils.checkNonNegativeIndex(elementCount, "elementCount");
AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment;
AbstractMemorySegmentImpl dstImpl = (AbstractMemorySegmentImpl)dstSegment;
if (srcElementLayout.byteSize() != dstElementLayout.byteSize()) {
@@ -625,7 +624,7 @@ public static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout,
public static void copy(MemorySegment srcSegment, ValueLayout srcLayout, long srcOffset,
Object dstArray, int dstIndex,
int elementCount) {
-
+ Utils.checkNonNegativeIndex(elementCount, "elementCount");
var dstInfo = Utils.BaseAndScale.of(dstArray);
if (dstArray.getClass().componentType() != srcLayout.carrier()) {
throw new IllegalArgumentException("Incompatible value layout: " + srcLayout);
@@ -652,7 +651,6 @@ public static void copy(MemorySegment srcSegment, ValueLayout srcLayout, long sr
public static void copy(Object srcArray, int srcIndex,
MemorySegment dstSegment, ValueLayout dstLayout, long dstOffset,
int elementCount) {
-
var srcInfo = Utils.BaseAndScale.of(srcArray);
if (srcArray.getClass().componentType() != dstLayout.carrier()) {
throw new IllegalArgumentException("Incompatible value layout: " + dstLayout);
diff --git a/src/java.base/share/classes/jdk/internal/foreign/Utils.java b/src/java.base/share/classes/jdk/internal/foreign/Utils.java
index d0d5c866f6b..6a081e23eac 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/Utils.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/Utils.java
@@ -200,11 +200,8 @@ public static long pointeeByteAlign(AddressLayout addressLayout) {
}
public static void checkAllocationSizeAndAlign(long byteSize, long byteAlignment) {
- // size should be >= 0
- if (byteSize < 0) {
- throw new IllegalArgumentException("Invalid allocation size : " + byteSize);
- }
-
+ // byteSize should be >= 0
+ Utils.checkNonNegativeArgument(byteSize, "allocation size");
checkAlign(byteAlignment);
}
@@ -216,6 +213,20 @@ public static void checkAlign(long byteAlignment) {
}
}
+ @ForceInline
+ public static void checkNonNegativeArgument(long value, String name) {
+ if (value < 0) {
+ throw new IllegalArgumentException("The provided " + name + " is negative: " + value);
+ }
+ }
+
+ @ForceInline
+ public static void checkNonNegativeIndex(long value, String name) {
+ if (value < 0) {
+ throw new IndexOutOfBoundsException("The provided " + name + " is negative: " + value);
+ }
+ }
+
private static long computePadding(long offset, long align) {
boolean isAligned = offset == 0 || offset % align == 0;
if (isAligned) {
diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java
index e4d931127af..3c0cf3902bb 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java
@@ -151,13 +151,8 @@ private static long requirePowerOfTwoAndGreaterOrEqualToOne(long value) {
}
public long scale(long offset, long index) {
- if (offset < 0) {
- throw new IllegalArgumentException("Negative offset: " + offset);
- }
- if (index < 0) {
- throw new IllegalArgumentException("Negative index: " + index);
- }
-
+ Utils.checkNonNegativeArgument(offset, "offset");
+ Utils.checkNonNegativeArgument(index, "index");
return Math.addExact(offset, Math.multiplyExact(byteSize(), index));
}
diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/MemoryLayoutUtil.java b/src/java.base/share/classes/jdk/internal/foreign/layout/MemoryLayoutUtil.java
index dce06141028..6b8e7738198 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/layout/MemoryLayoutUtil.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/layout/MemoryLayoutUtil.java
@@ -30,13 +30,6 @@ public final class MemoryLayoutUtil {
private MemoryLayoutUtil() {
}
- public static long requireNonNegative(long value) {
- if (value < 0) {
- throw new IllegalArgumentException("The provided value was negative: " + value);
- }
- return value;
- }
-
public static long requireByteSizeValid(long byteSize, boolean allowZero) {
if ((byteSize == 0 && !allowZero) || byteSize < 0) {
throw new IllegalArgumentException("Invalid byte size: " + byteSize);
diff --git a/test/jdk/java/foreign/TestLayouts.java b/test/jdk/java/foreign/TestLayouts.java
index f4048aaa68a..2aa398468cc 100644
--- a/test/jdk/java/foreign/TestLayouts.java
+++ b/test/jdk/java/foreign/TestLayouts.java
@@ -371,13 +371,13 @@ public void testVarHandleCaching() {
}
@Test(expectedExceptions=IllegalArgumentException.class,
- expectedExceptionsMessageRegExp=".*Negative offset.*")
+ expectedExceptionsMessageRegExp=".*offset is negative.*")
public void testScaleNegativeOffset() {
JAVA_INT.scale(-1, 0);
}
@Test(expectedExceptions=IllegalArgumentException.class,
- expectedExceptionsMessageRegExp=".*Negative index.*")
+ expectedExceptionsMessageRegExp=".*index is negative.*")
public void testScaleNegativeIndex() {
JAVA_INT.scale(0, -1);
}
diff --git a/test/jdk/java/foreign/TestMemoryAccessInstance.java b/test/jdk/java/foreign/TestMemoryAccessInstance.java
index d56f44388a4..b749c96ac54 100644
--- a/test/jdk/java/foreign/TestMemoryAccessInstance.java
+++ b/test/jdk/java/foreign/TestMemoryAccessInstance.java
@@ -164,6 +164,13 @@ public void badAccessOverflowInIndexedAccess(String t
}
}
+ @Test(dataProvider = "segmentAccessors")
+ public void negativeOffset(String testName, Accessor accessor) {
+ MemorySegment segment = MemorySegment.ofArray(new byte[100]);
+ assertThrows(IndexOutOfBoundsException.class, () -> accessor.get(segment, -ValueLayout.JAVA_LONG.byteSize()));
+ assertThrows(IndexOutOfBoundsException.class, () -> accessor.set(segment, -ValueLayout.JAVA_LONG.byteSize(), accessor.value));
+ }
+
static final ByteOrder NE = ByteOrder.nativeOrder();
@DataProvider(name = "segmentAccessors")
diff --git a/test/jdk/java/foreign/TestScopedOperations.java b/test/jdk/java/foreign/TestScopedOperations.java
index 70223c00c00..d680d234145 100644
--- a/test/jdk/java/foreign/TestScopedOperations.java
+++ b/test/jdk/java/foreign/TestScopedOperations.java
@@ -27,6 +27,7 @@
*/
import java.lang.foreign.Arena;
+import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
@@ -135,6 +136,8 @@ public void testOpOutsideConfinement(String name, ScopedOperation scopedO
ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_FLOAT, new float[]{0}), "Arena::allocateFrom/float");
ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_LONG, new long[]{0}), "Arena::allocateFrom/long");
ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_DOUBLE, new double[]{0}), "Arena::allocateFrom/double");
+ var source = MemorySegment.ofArray(new byte[]{});
+ ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_INT, source, JAVA_BYTE, 0, 1), "Arena::allocateFrom/5arg");
};
@DataProvider(name = "scopedOperations")
diff --git a/test/jdk/java/foreign/TestSegmentAllocators.java b/test/jdk/java/foreign/TestSegmentAllocators.java
index 0e0c49320da..87418f39d90 100644
--- a/test/jdk/java/foreign/TestSegmentAllocators.java
+++ b/test/jdk/java/foreign/TestSegmentAllocators.java
@@ -44,6 +44,8 @@
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
import java.util.function.Function;
@@ -189,6 +191,81 @@ public void testAllocatorAllocateFromHeapSegment() {
}
}
+ // Invariant checking tests for the SegmentAllocator method:
+ // MemorySegment allocateFrom(ValueLayout elementLayout,
+ // MemorySegment source,
+ // ValueLayout sourceElementLayout,
+ // long sourceOffset,
+ // long elementCount) {
+ @Test
+ public void testAllocatorAllocateFromArguments() {
+ try (Arena arena = Arena.ofConfined()) {
+ var sourceElements = 2;
+ var source = arena.allocate(ValueLayout.JAVA_LONG, sourceElements);
+ var elementLayout = ValueLayout.JAVA_INT;
+ var sourceElementLayout = ValueLayout.JAVA_INT;
+
+ // IllegalArgumentException if {@code elementLayout.byteSize() != sourceElementLayout.byteSize()}
+ assertThrows(IllegalArgumentException.class, () ->
+ arena.allocateFrom(elementLayout, source, ValueLayout.JAVA_BYTE, 0, 1)
+ );
+
+ // IllegalArgumentException if source segment/offset
+ // are incompatible with the alignment constraint
+ // in the source element layout
+ assertThrows(IllegalArgumentException.class, () ->
+ arena.allocateFrom(elementLayout, source.asSlice(1), sourceElementLayout, 0, 1)
+ );
+ assertThrows(IllegalArgumentException.class, () ->
+ arena.allocateFrom(elementLayout, source, sourceElementLayout, 1, 1)
+ );
+
+ // IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()}
+ assertThrows(IllegalArgumentException.class, () ->
+ arena.allocateFrom(elementLayout.withByteAlignment(elementLayout.byteAlignment() * 2), source, sourceElementLayout, 1, 1)
+ );
+
+ // IllegalStateException if the {@linkplain MemorySegment#scope() scope} associated
+ // with {@code source} is not {@linkplain MemorySegment.Scope#isAlive() alive}
+ // This is tested in TestScopedOperations
+
+ // WrongThreadException if this method is called from a thread {@code T},
+ // such that {@code source.isAccessibleBy(T) == false}
+ CompletableFuture future = CompletableFuture.supplyAsync(Arena::ofConfined);
+ try {
+ Arena otherThreadArena = future.get();
+ assertThrows(WrongThreadException.class, () ->
+ otherThreadArena.allocateFrom(elementLayout, source, sourceElementLayout, 0, 1)
+ );
+ } catch (ExecutionException | InterruptedException e) {
+ fail("Unable to create arena", e);
+ }
+
+ // IllegalArgumentException if {@code elementCount * sourceElementLayout.byteSize()} overflows
+ assertThrows(IllegalArgumentException.class, () ->
+ arena.allocateFrom(elementLayout, source, sourceElementLayout, 0, Long.MAX_VALUE)
+ );
+
+ // IndexOutOfBoundsException if {@code sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())}
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ arena.allocateFrom(elementLayout, source, sourceElementLayout, source.byteSize() - (1 * sourceElementLayout.byteAlignment()) + elementLayout.byteSize(), 1)
+ );
+
+ // IndexOutOfBoundsException if {@code sourceOffset < 0}
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ arena.allocateFrom(elementLayout, source, sourceElementLayout, -elementLayout.byteSize(), 1)
+ );
+
+ // IllegalArgumentException if {@code elementCount < 0}
+ assertThrows(IllegalArgumentException.class, () ->
+ arena.allocateFrom(elementLayout, source, sourceElementLayout, 0, -1)
+ );
+
+
+ }
+ }
+
+
@Test
public void testArrayAllocateDelegation() {
AtomicInteger calls = new AtomicInteger();
diff --git a/test/jdk/java/foreign/TestSegmentCopy.java b/test/jdk/java/foreign/TestSegmentCopy.java
index 414cd0a8451..88636bf5420 100644
--- a/test/jdk/java/foreign/TestSegmentCopy.java
+++ b/test/jdk/java/foreign/TestSegmentCopy.java
@@ -145,6 +145,66 @@ public void testHyperAlignedDst() {
MemorySegment.copy(segment, JAVA_BYTE.withByteAlignment(2), 0, segment, 0, 4);
}
+ @Test
+ public void testCopy5ArgWithNegativeValues() {
+ MemorySegment src = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
+ MemorySegment dst = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ MemorySegment.copy(src, -1, dst, 0, 4)
+ );
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ MemorySegment.copy(src, 0, dst, -1, 4)
+ );
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ MemorySegment.copy(src, 0, dst, 0, -1)
+ );
+ }
+
+ @Test
+ public void testCopy7ArgWithNegativeValues() {
+ MemorySegment src = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
+ MemorySegment dst = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ MemorySegment.copy(src, JAVA_BYTE, -1, dst, JAVA_BYTE, 0, 4)
+ );
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ MemorySegment.copy(src, JAVA_BYTE, 0, dst, JAVA_BYTE, -1, 4)
+ );
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ MemorySegment.copy(src, JAVA_BYTE, 0, dst, JAVA_BYTE, 0, -1)
+ );
+ }
+
+ @Test
+ public void testCopyFromArrayWithNegativeValues() {
+ MemorySegment src = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
+ byte[] dst = new byte[] {1, 2, 3, 4};
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ MemorySegment.copy(src, JAVA_BYTE, -1, dst, 0, 4)
+ );
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ MemorySegment.copy(src, JAVA_BYTE, 0, dst, -1, 4)
+ );
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ MemorySegment.copy(src, JAVA_BYTE, 0, dst, 0, -1)
+ );
+ }
+
+ @Test
+ public void testCopyToArrayWithNegativeValues() {
+ byte[] src = new byte[] {1, 2, 3, 4};
+ MemorySegment dst = MemorySegment.ofArray(new byte[] {1, 2, 3, 4});
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ MemorySegment.copy(src, -1, dst, JAVA_BYTE, 0, 4)
+ );
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ MemorySegment.copy(src, 0, dst, JAVA_BYTE, -1, 4)
+ );
+ assertThrows(IndexOutOfBoundsException.class, () ->
+ MemorySegment.copy(src, 0, dst, JAVA_BYTE, 0, -1)
+ );
+ }
+
enum Type {
// Byte
BYTE(byte.class, JAVA_BYTE, i -> (byte)i),
diff --git a/test/jdk/java/foreign/TestSegments.java b/test/jdk/java/foreign/TestSegments.java
index 94b49eb7e59..44ecd12ba5e 100644
--- a/test/jdk/java/foreign/TestSegments.java
+++ b/test/jdk/java/foreign/TestSegments.java
@@ -43,6 +43,7 @@
import java.util.function.Supplier;
import static java.lang.foreign.ValueLayout.JAVA_INT;
+import static java.lang.foreign.ValueLayout.JAVA_LONG;
import static org.testng.Assert.*;
public class TestSegments {
@@ -55,14 +56,13 @@ public void testBadAllocateAlign(long size, long align) {
@Test
public void testZeroLengthNativeSegment() {
try (Arena arena = Arena.ofConfined()) {
- Arena session = arena;
- var segment = session.allocate(0, 1);
+ var segment = arena.allocate(0, 1);
assertEquals(segment.byteSize(), 0);
MemoryLayout seq = MemoryLayout.sequenceLayout(0, JAVA_INT);
- segment = session.allocate(seq);
+ segment = arena.allocate(seq);
assertEquals(segment.byteSize(), 0);
assertEquals(segment.address() % seq.byteAlignment(), 0);
- segment = session.allocate(0, 4);
+ segment = arena.allocate(0, 4);
assertEquals(segment.byteSize(), 0);
assertEquals(segment.address() % 4, 0);
MemorySegment rawAddress = MemorySegment.ofAddress(segment.address());
@@ -133,8 +133,7 @@ public void testDerivedScopes(Supplier segmentSupplier) {
@Test
public void testEqualsOffHeap() {
try (Arena arena = Arena.ofConfined()) {
- Arena scope1 = arena;
- MemorySegment segment = scope1.allocate(100, 1);
+ MemorySegment segment = arena.allocate(100, 1);
assertEquals(segment, segment.asReadOnly());
assertEquals(segment, segment.asSlice(0, 100));
assertNotEquals(segment, segment.asSlice(10, 90));
From b0920c24cd83d85a846a60fe2d784a48dd8c9b52 Mon Sep 17 00:00:00 2001
From: Sandhya Viswanathan
Date: Fri, 12 Jan 2024 16:59:06 +0000
Subject: [PATCH 38/66] 8321712: C2: "failed: Multiple uses of register" in
C2_MacroAssembler::vminmax_fp
Reviewed-by: kvn, thartmann
Backport-of: e10d14004fa25998231ab1d2611b75aea9b5c67d
---
src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 6 ++++--
.../vectorization/runner/BasicDoubleOpTest.java | 12 ++++++++++++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
index 54e5f55fa2b..a197a8e3c7d 100644
--- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
@@ -1089,7 +1089,8 @@ void C2_MacroAssembler::vminmax_fp(int opcode, BasicType elem_bt,
assert(opcode == Op_MinV || opcode == Op_MinReductionV ||
opcode == Op_MaxV || opcode == Op_MaxReductionV, "sanity");
assert(elem_bt == T_FLOAT || elem_bt == T_DOUBLE, "sanity");
- assert_different_registers(a, b, tmp, atmp, btmp);
+ assert_different_registers(a, tmp, atmp, btmp);
+ assert_different_registers(b, tmp, atmp, btmp);
bool is_min = (opcode == Op_MinV || opcode == Op_MinReductionV);
bool is_double_word = is_double_word_type(elem_bt);
@@ -1176,7 +1177,8 @@ void C2_MacroAssembler::evminmax_fp(int opcode, BasicType elem_bt,
assert(opcode == Op_MinV || opcode == Op_MinReductionV ||
opcode == Op_MaxV || opcode == Op_MaxReductionV, "sanity");
assert(elem_bt == T_FLOAT || elem_bt == T_DOUBLE, "sanity");
- assert_different_registers(dst, a, b, atmp, btmp);
+ assert_different_registers(dst, a, atmp, btmp);
+ assert_different_registers(dst, b, atmp, btmp);
bool is_min = (opcode == Op_MinV || opcode == Op_MinReductionV);
bool is_double_word = is_double_word_type(elem_bt);
diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java
index 0f758be4ed0..a3fcdbaa9b0 100644
--- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java
+++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, 2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2024, 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
@@ -237,6 +238,17 @@ public double[] vectorMax() {
return res;
}
+ @Test
+ @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"},
+ counts = {IRNode.MAX_VD, ">0"})
+ public double[] vectorMax_8322090() {
+ double[] res = new double[SIZE];
+ for (int i = 0; i < SIZE; i++) {
+ res[i] = Math.max(d[i], d[i]);
+ }
+ return res;
+ }
+
@Test
@IR(applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"},
counts = {IRNode.MIN_VD, ">0"})
From 01f780fab21aceed5f40baeb6d4fa832bfee8251 Mon Sep 17 00:00:00 2001
From: Alan Bateman
Date: Sat, 13 Jan 2024 16:00:58 +0000
Subject: [PATCH 39/66] 8319757:
java/nio/channels/DatagramChannel/InterruptibleOrNot.java failed: wrong
exception thrown
Reviewed-by: jpai
Backport-of: ace010b38a83e0c9b43aeeb6bc5c92d0886dc53f
---
.../DatagramChannel/InterruptibleOrNot.java | 238 ++++++++++--------
1 file changed, 132 insertions(+), 106 deletions(-)
diff --git a/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java b/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java
index 7d369d7ddd9..794ede84a92 100644
--- a/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java
+++ b/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
* @test
* @bug 8236246
* @modules java.base/sun.nio.ch
- * @run testng InterruptibleOrNot
+ * @run junit InterruptibleOrNot
* @summary Test SelectorProviderImpl.openDatagramChannel(boolean) to create
* DatagramChannel objects that optionally support interrupt
*/
@@ -40,152 +40,178 @@
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.DatagramChannel;
import java.time.Duration;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
+import java.util.Arrays;
import sun.nio.ch.DefaultSelectorProvider;
-import org.testng.annotations.Test;
-import static org.testng.Assert.*;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.function.Executable;
+import static org.junit.jupiter.api.Assertions.*;
-@Test
public class InterruptibleOrNot {
+ // DatagramChannel implementation class
+ private static String dcImplClassName;
- public void testInterruptBeforeInterruptibleReceive() throws Exception {
- testInterruptBeforeReceive(true);
- }
-
- public void testInterruptDuringInterruptibleReceive() throws Exception {
- testInterruptDuringReceive(true);
- }
-
- public void testInterruptBeforeUninterruptibleReceive() throws Exception {
- testInterruptBeforeReceive(false);
- }
-
- public void testInterruptDuringUninterruptibleReceive() throws Exception {
- testInterruptDuringReceive(false);
- }
-
- public void testInterruptBeforeInterruptibleSend() throws Exception {
- testInterruptBeforeSend(true);
+ @BeforeAll
+ static void setup() throws Exception {
+ try (DatagramChannel dc = boundDatagramChannel(true)) {
+ dcImplClassName = dc.getClass().getName();
+ }
}
- public void testInterruptBeforeUninterruptibleSend() throws Exception {
- testInterruptBeforeSend(false);
+ /**
+ * Call DatagramChannel.receive with the interrupt status set, the DatagramChannel
+ * is interruptible.
+ */
+ @Test
+ public void testInterruptBeforeInterruptibleReceive() throws Exception {
+ try (DatagramChannel dc = boundDatagramChannel(true)) {
+ ByteBuffer buf = ByteBuffer.allocate(100);
+ Thread.currentThread().interrupt();
+ assertThrows(ClosedByInterruptException.class, () -> dc.receive(buf));
+ assertFalse(dc.isOpen());
+ } finally {
+ Thread.interrupted(); // clear interrupt status
+ }
}
/**
- * Test invoking DatagramChannel receive with interrupt status set
+ * Test interrupting a thread blocked in DatagramChannel.receive, the DatagramChannel
+ * is interruptible.
*/
- static void testInterruptBeforeReceive(boolean interruptible)
- throws Exception
- {
- try (DatagramChannel dc = openDatagramChannel(interruptible)) {
- dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
- Future> timeout = scheduleClose(dc, Duration.ofSeconds(2));
- try {
- ByteBuffer buf = ByteBuffer.allocate(100);
- Thread.currentThread().interrupt();
- assertThrows(expectedException(interruptible), () -> dc.receive(buf));
- } finally {
- timeout.cancel(false);
- }
+ @Test
+ public void testInterruptDuringInterruptibleReceive() throws Exception {
+ try (DatagramChannel dc = boundDatagramChannel(true)) {
+ ByteBuffer buf = ByteBuffer.allocate(100);
+ Thread thread = Thread.currentThread();
+ onReceive(thread::interrupt);
+ assertThrows(ClosedByInterruptException.class, () -> dc.receive(buf));
+ assertFalse(dc.isOpen());
} finally {
- Thread.interrupted(); // clear interrupt
+ Thread.interrupted(); // clear interrupt status
}
}
/**
- * Test Thread.interrupt when target thread is blocked in DatagramChannel receive
+ * Call DatagramChannel.receive with the interrupt status set, the DatagramChannel
+ * is not interruptible.
*/
- static void testInterruptDuringReceive(boolean interruptible)
- throws Exception
- {
- try (DatagramChannel dc = openDatagramChannel(interruptible)) {
- dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
- Future> timerTask = scheduleClose(dc, Duration.ofSeconds(5));
- Future> interruptTask = scheduleInterrupt(Thread.currentThread(), Duration.ofSeconds(1));
- try {
- ByteBuffer buf = ByteBuffer.allocate(100);
- assertThrows(expectedException(interruptible), () -> dc.receive(buf));
- } finally {
- timerTask.cancel(false);
- interruptTask.cancel(false);
- }
+ @Test
+ public void testInterruptBeforeUninterruptibleReceive() throws Exception {
+ try (DatagramChannel dc = boundDatagramChannel(false)) {
+ ByteBuffer buf = ByteBuffer.allocate(100);
+ onReceive(() -> {
+ // close the channel after a delay to ensure receive wakes up
+ Thread.sleep(1000);
+ dc.close();
+ });
+ Thread.currentThread().interrupt();
+ assertThrows(AsynchronousCloseException.class, () -> dc.receive(buf));
+ assertFalse(dc.isOpen());
} finally {
- Thread.interrupted(); // clear interrupt
+ Thread.interrupted(); // clear interrupt status
}
}
/**
- * Test invoking DatagramChannel send with interrupt status set
+ * Test interrupting a thread blocked in DatagramChannel.receive, the DatagramChannel
+ * is not interruptible.
*/
- static void testInterruptBeforeSend(boolean interruptible)
- throws Exception
- {
- try (DatagramChannel dc = openDatagramChannel(interruptible)) {
- dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
- Future> timeout = scheduleClose(dc, Duration.ofSeconds(2));
- try {
- ByteBuffer buf = ByteBuffer.allocate(100);
- SocketAddress target = dc.getLocalAddress();
- Thread.currentThread().interrupt();
- if (interruptible) {
- assertThrows(ClosedByInterruptException.class, () -> dc.send(buf, target));
- } else {
- int n = dc.send(buf, target);
- assertTrue(n == 100);
- }
- } finally {
- timeout.cancel(false);
- }
+ @Test
+ public void testInterruptDuringUninterruptibleReceive() throws Exception {
+ try (DatagramChannel dc = boundDatagramChannel(true)) {
+ ByteBuffer buf = ByteBuffer.allocate(100);
+
+ Thread thread = Thread.currentThread();
+ onReceive(() -> {
+ // interrupt should not cause the receive to wakeup
+ thread.interrupt();
+
+ // close the channel after a delay to ensure receive wakes up
+ Thread.sleep(1000);
+ dc.close();
+ });
+ assertThrows(AsynchronousCloseException.class, () -> dc.receive(buf));
+ assertFalse(dc.isOpen());
} finally {
- Thread.interrupted(); // clear interrupt
+ Thread.interrupted(); // clear interrupt status
}
}
/**
- * Creates a DatagramChannel that is interruptible or not.
+ * Call DatagramChannel.send with the interrupt status set, the DatagramChannel
+ * is interruptible.
*/
- static DatagramChannel openDatagramChannel(boolean interruptible) throws IOException {
- if (interruptible) {
- return DatagramChannel.open();
- } else {
- return DefaultSelectorProvider.get().openUninterruptibleDatagramChannel();
+ @Test
+ public void testInterruptBeforeInterruptibleSend() throws Exception {
+ try (DatagramChannel dc = boundDatagramChannel(true)) {
+ ByteBuffer buf = ByteBuffer.allocate(100);
+ SocketAddress target = dc.getLocalAddress();
+ Thread.currentThread().interrupt();
+ assertThrows(ClosedByInterruptException.class, () -> dc.send(buf, target));
+ assertFalse(dc.isOpen());
+ } finally {
+ Thread.interrupted(); // clear interrupt
}
}
/**
- * Expect ClosedByInterruptException if interruptible.
+ * Call DatagramChannel.send with the interrupt status set, the DatagramChannel
+ * is not interruptible.
*/
- static Class extends Exception> expectedException(boolean expectInterrupt) {
- if (expectInterrupt) {
- return ClosedByInterruptException.class;
- } else {
- return AsynchronousCloseException.class;
+ @Test
+ public void testInterruptBeforeUninterruptibleSend() throws Exception {
+ try (DatagramChannel dc = boundDatagramChannel(false)) {
+ ByteBuffer buf = ByteBuffer.allocate(100);
+ SocketAddress target = dc.getLocalAddress();
+ Thread.currentThread().interrupt();
+ int n = dc.send(buf, target);
+ assertEquals(100, n);
+ assertTrue(dc.isOpen());
+ } finally {
+ Thread.interrupted(); // clear interrupt status
}
}
/**
- * Schedule the given object to be closed.
+ * Creates a DatagramChannel that is interruptible or not, and bound to the loopback
+ * address.
*/
- static Future> scheduleClose(Closeable c, Duration timeout) {
- long nanos = TimeUnit.NANOSECONDS.convert(timeout);
- return STPE.schedule(() -> {
- c.close();
- return null;
- }, nanos, TimeUnit.NANOSECONDS);
+ static DatagramChannel boundDatagramChannel(boolean interruptible) throws IOException {
+ DatagramChannel dc;
+ if (interruptible) {
+ dc = DatagramChannel.open();
+ } else {
+ dc = DefaultSelectorProvider.get().openUninterruptibleDatagramChannel();
+ }
+ try {
+ dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+ } catch (IOException ioe) {
+ dc.close();
+ throw ioe;
+ }
+ return dc;
}
/**
- * Schedule the given thread to be interrupted.
+ * Runs the given action when the current thread is sampled in DatagramChannel.receive.
*/
- static Future> scheduleInterrupt(Thread t, Duration timeout) {
- long nanos = TimeUnit.NANOSECONDS.convert(timeout);
- return STPE.schedule(t::interrupt, nanos, TimeUnit.NANOSECONDS);
+ static void onReceive(Executable action) {
+ Thread target = Thread.currentThread();
+ Thread.ofPlatform().daemon().start(() -> {
+ try {
+ boolean found = false;
+ while (!found) {
+ Thread.sleep(20);
+ StackTraceElement[] stack = target.getStackTrace();
+ found = Arrays.stream(stack)
+ .anyMatch(e -> dcImplClassName.equals(e.getClassName())
+ && "receive".equals(e.getMethodName()));
+ }
+ action.execute();
+ } catch (Throwable ex) {
+ ex.printStackTrace();
+ }
+ });
}
-
- static final ScheduledExecutorService STPE = Executors.newScheduledThreadPool(0);
}
From ba9609412805f1896af3e92d4fa7d76738d0849c Mon Sep 17 00:00:00 2001
From: Thomas Schatzl
Date: Mon, 15 Jan 2024 12:05:33 +0000
Subject: [PATCH 40/66] 8323610: G1: HeapRegion pin count should be size_t to
avoid overflows
Reviewed-by: ayang
Backport-of: 8643cc21333c6b51242ed3b9295b25f372244755
---
src/hotspot/share/gc/g1/g1YoungCollector.cpp | 4 ++--
src/hotspot/share/gc/g1/heapRegion.cpp | 4 ++--
src/hotspot/share/gc/g1/heapRegion.hpp | 6 +++---
src/hotspot/share/gc/g1/heapRegion.inline.hpp | 6 +++---
src/hotspot/share/gc/g1/vmStructs_g1.hpp | 4 ++--
5 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp
index ec32f8b589b..b52bfdfbb08 100644
--- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp
+++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2024, 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
@@ -403,7 +403,7 @@ class G1PrepareEvacuationTask : public WorkerTask {
_g1h->register_region_with_region_attr(hr);
}
log_debug(gc, humongous)("Humongous region %u (object size %zu @ " PTR_FORMAT ") remset %zu code roots %zu "
- "marked %d pinned count %u reclaim candidate %d type array %d",
+ "marked %d pinned count %zu reclaim candidate %d type array %d",
index,
cast_to_oop(hr->bottom())->size() * HeapWordSize,
p2i(hr->bottom()),
diff --git a/src/hotspot/share/gc/g1/heapRegion.cpp b/src/hotspot/share/gc/g1/heapRegion.cpp
index 29fe5031a35..69040028d98 100644
--- a/src/hotspot/share/gc/g1/heapRegion.cpp
+++ b/src/hotspot/share/gc/g1/heapRegion.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2024, 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
@@ -424,7 +424,7 @@ void HeapRegion::print_on(outputStream* st) const {
st->print("|-");
}
}
- st->print("|%3u", Atomic::load(&_pinned_object_count));
+ st->print("|%3zu", Atomic::load(&_pinned_object_count));
st->print_cr("");
}
diff --git a/src/hotspot/share/gc/g1/heapRegion.hpp b/src/hotspot/share/gc/g1/heapRegion.hpp
index 2706b814000..725433215c4 100644
--- a/src/hotspot/share/gc/g1/heapRegion.hpp
+++ b/src/hotspot/share/gc/g1/heapRegion.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2024, 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
@@ -257,7 +257,7 @@ class HeapRegion : public CHeapObj {
uint _node_index;
// Number of objects in this region that are currently pinned.
- volatile uint _pinned_object_count;
+ volatile size_t _pinned_object_count;
void report_region_type_change(G1HeapRegionTraceType::Type to);
@@ -408,7 +408,7 @@ class HeapRegion : public CHeapObj {
bool is_old_or_humongous() const { return _type.is_old_or_humongous(); }
- uint pinned_count() const { return Atomic::load(&_pinned_object_count); }
+ size_t pinned_count() const { return Atomic::load(&_pinned_object_count); }
bool has_pinned_objects() const { return pinned_count() > 0; }
void set_free();
diff --git a/src/hotspot/share/gc/g1/heapRegion.inline.hpp b/src/hotspot/share/gc/g1/heapRegion.inline.hpp
index ec68407b546..4a42b922182 100644
--- a/src/hotspot/share/gc/g1/heapRegion.inline.hpp
+++ b/src/hotspot/share/gc/g1/heapRegion.inline.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2024, 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
@@ -554,11 +554,11 @@ inline void HeapRegion::record_surv_words_in_group(size_t words_survived) {
}
inline void HeapRegion::increment_pinned_object_count() {
- Atomic::add(&_pinned_object_count, 1u, memory_order_relaxed);
+ Atomic::add(&_pinned_object_count, (size_t)1, memory_order_relaxed);
}
inline void HeapRegion::decrement_pinned_object_count() {
- Atomic::sub(&_pinned_object_count, 1u, memory_order_relaxed);
+ Atomic::sub(&_pinned_object_count, (size_t)1, memory_order_relaxed);
}
#endif // SHARE_GC_G1_HEAPREGION_INLINE_HPP
diff --git a/src/hotspot/share/gc/g1/vmStructs_g1.hpp b/src/hotspot/share/gc/g1/vmStructs_g1.hpp
index 94ade0f387c..9ce61531989 100644
--- a/src/hotspot/share/gc/g1/vmStructs_g1.hpp
+++ b/src/hotspot/share/gc/g1/vmStructs_g1.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2024, 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
@@ -41,7 +41,7 @@
nonstatic_field(HeapRegion, _bottom, HeapWord* const) \
nonstatic_field(HeapRegion, _top, HeapWord* volatile) \
nonstatic_field(HeapRegion, _end, HeapWord* const) \
- nonstatic_field(HeapRegion, _pinned_object_count, volatile uint) \
+ volatile_nonstatic_field(HeapRegion, _pinned_object_count, size_t) \
\
nonstatic_field(HeapRegionType, _tag, HeapRegionType::Tag volatile) \
\
From 8db5d865c1066c217c5b4e87b9e0881bfb1f5beb Mon Sep 17 00:00:00 2001
From: Christoph Langer
Date: Mon, 15 Jan 2024 15:13:45 +0000
Subject: [PATCH 41/66] 8323008: filter out harmful -std* flags added by
autoconf from CXX
Reviewed-by: mdoerr
Backport-of: 68c4286026bc2c0ec0f594e0b96fe03fe5624d6d
---
make/autoconf/toolchain.m4 | 6 +++++-
make/autoconf/util.m4 | 6 +++---
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/make/autoconf/toolchain.m4 b/make/autoconf/toolchain.m4
index 289eec3356b..7a24815d163 100644
--- a/make/autoconf/toolchain.m4
+++ b/make/autoconf/toolchain.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2024, 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
@@ -389,6 +389,10 @@ AC_DEFUN_ONCE([TOOLCHAIN_POST_DETECTION],
# This is necessary since AC_PROG_CC defaults CFLAGS to "-g -O2"
CFLAGS="$ORG_CFLAGS"
CXXFLAGS="$ORG_CXXFLAGS"
+
+ # filter out some unwanted additions autoconf may add to CXX; we saw this on macOS with autoconf 2.72
+ UTIL_GET_NON_MATCHING_VALUES(cxx_filtered, $CXX, -std=c++11 -std=gnu++11)
+ CXX="$cxx_filtered"
])
# Check if a compiler is of the toolchain type we expect, and save the version
diff --git a/make/autoconf/util.m4 b/make/autoconf/util.m4
index 349a04a089e..3fae951224e 100644
--- a/make/autoconf/util.m4
+++ b/make/autoconf/util.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2024, 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
@@ -199,7 +199,7 @@ AC_DEFUN([UTIL_GET_NON_MATCHING_VALUES],
if test -z "$legal_values"; then
$1="$2"
else
- result=`$GREP -Fvx "$legal_values" <<< "$values_to_check" | $GREP -v '^$'`
+ result=`$GREP -Fvx -- "$legal_values" <<< "$values_to_check" | $GREP -v '^$'`
$1=${result//$'\n'/ }
fi
])
@@ -226,7 +226,7 @@ AC_DEFUN([UTIL_GET_MATCHING_VALUES],
if test -z "$illegal_values"; then
$1=""
else
- result=`$GREP -Fx "$illegal_values" <<< "$values_to_check" | $GREP -v '^$'`
+ result=`$GREP -Fx -- "$illegal_values" <<< "$values_to_check" | $GREP -v '^$'`
$1=${result//$'\n'/ }
fi
])
From 3017281956f3c8b50f064a75444c74a18d59e96d Mon Sep 17 00:00:00 2001
From: Alan Bateman
Date: Tue, 16 Jan 2024 08:19:22 +0000
Subject: [PATCH 42/66] 8322846: Running with -Djdk.tracePinnedThreads set can
hang
Reviewed-by: jpai
Backport-of: faa9c6909dda635eb008b9dada6e06fca47c17d6
---
.../java/lang/PinnedThreadPrinter.java | 65 ++++++++++-------
.../classes/java/lang/VirtualThread.java | 10 ++-
.../Thread/virtual/TracePinnedThreads.java | 69 +++++++++++++++++--
3 files changed, 116 insertions(+), 28 deletions(-)
diff --git a/src/java.base/share/classes/java/lang/PinnedThreadPrinter.java b/src/java.base/share/classes/java/lang/PinnedThreadPrinter.java
index 02e0683a1b9..a9b40d028f5 100644
--- a/src/java.base/share/classes/java/lang/PinnedThreadPrinter.java
+++ b/src/java.base/share/classes/java/lang/PinnedThreadPrinter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -34,6 +34,10 @@
import java.util.Set;
import java.util.stream.Collectors;
import static java.lang.StackWalker.Option.*;
+import jdk.internal.access.JavaIOPrintStreamAccess;
+import jdk.internal.access.SharedSecrets;
+import jdk.internal.misc.InternalLock;
+import jdk.internal.vm.Continuation;
/**
* Helper class to print the virtual thread stack trace when pinned.
@@ -42,7 +46,8 @@
* code in that Class. This is used to avoid printing the same stack trace many times.
*/
class PinnedThreadPrinter {
- static final StackWalker STACK_WALKER;
+ private static final JavaIOPrintStreamAccess JIOPSA = SharedSecrets.getJavaIOPrintStreamAccess();
+ private static final StackWalker STACK_WALKER;
static {
var options = Set.of(SHOW_REFLECT_FRAMES, RETAIN_CLASS_REFERENCE);
PrivilegedAction pa = () ->
@@ -86,45 +91,59 @@ private static int hash(List stack) {
}
/**
- * Prints the continuation stack trace.
+ * Returns true if the frame is native, a class initializer, or holds monitors.
+ */
+ private static boolean isInterestingFrame(LiveStackFrame f) {
+ return f.isNativeMethod()
+ || "".equals(f.getMethodName())
+ || (f.getMonitors().length > 0);
+ }
+
+ /**
+ * Prints the current thread's stack trace.
*
* @param printAll true to print all stack frames, false to only print the
* frames that are native or holding a monitor
*/
- static void printStackTrace(PrintStream out, boolean printAll) {
+ static void printStackTrace(PrintStream out, Continuation.Pinned reason, boolean printAll) {
List stack = STACK_WALKER.walk(s ->
s.map(f -> (LiveStackFrame) f)
.filter(f -> f.getDeclaringClass() != PinnedThreadPrinter.class)
.collect(Collectors.toList())
);
+ Object lockObj = JIOPSA.lock(out);
+ if (lockObj instanceof InternalLock lock && lock.tryLock()) {
+ try {
+ // find the closest frame that is causing the thread to be pinned
+ stack.stream()
+ .filter(f -> isInterestingFrame(f))
+ .map(LiveStackFrame::getDeclaringClass)
+ .findFirst()
+ .ifPresentOrElse(klass -> {
+ // print the stack trace if not already seen
+ int hash = hash(stack);
+ if (HASHES.get(klass).add(hash)) {
+ printStackTrace(out, reason, stack, printAll);
+ }
+ }, () -> printStackTrace(out, reason, stack, true)); // not found
- // find the closest frame that is causing the thread to be pinned
- stack.stream()
- .filter(f -> (f.isNativeMethod() || f.getMonitors().length > 0))
- .map(LiveStackFrame::getDeclaringClass)
- .findFirst()
- .ifPresentOrElse(klass -> {
- int hash = hash(stack);
- Hashes hashes = HASHES.get(klass);
- synchronized (hashes) {
- // print the stack trace if not already seen
- if (hashes.add(hash)) {
- printStackTrace(stack, out, printAll);
- }
- }
- }, () -> printStackTrace(stack, out, true)); // not found
+ } finally {
+ lock.unlock();
+ }
+ }
}
- private static void printStackTrace(List stack,
- PrintStream out,
+ private static void printStackTrace(PrintStream out,
+ Continuation.Pinned reason,
+ List