diff --git a/.jcheck/conf b/.jcheck/conf index 17552ee7361ab..617f3d95ed8e6 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -5,6 +5,7 @@ version=23 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists +warning=issuestitle [repository] tags=(?:jdk-(?:[1-9]([0-9]*)(?:\.(?:0|[1-9][0-9]*)){0,4})(?:\+(?:(?:[0-9]+))|(?:-ga)))|(?:jdk[4-9](?:u\d{1,3})?-(?:(?:b\d{2,3})|(?:ga)))|(?:hs\d\d(?:\.\d{1,2})?-b\d\d) diff --git a/make/Docs.gmk b/make/Docs.gmk index 2977f6f66f9e1..192843de9cdec 100644 --- a/make/Docs.gmk +++ b/make/Docs.gmk @@ -681,28 +681,25 @@ ifeq ($(ENABLE_PANDOC), true) $(TOPDIR)/make/jdk/src/classes/build/tools/pandocfilter) $(foreach m, $(ALL_MODULES), \ - $(eval MAN_$m := $(call FindModuleManDirs, $m)) \ - $(foreach d, $(MAN_$m), \ - $(foreach f, $(call ApplySpecFilter, $(filter %.md, $(call FindFiles, $d))), \ - $(eval $m_$f_NAME := MAN_TO_HTML_$m_$(strip $(call RelativePath, $f, $(TOPDIR)))) \ - $(eval $(call SetupProcessMarkdown, $($m_$f_NAME), \ - SRC := $d, \ - FILES := $f, \ - DEST := $(DOCS_OUTPUTDIR)/specs/man, \ - FILTER := $(PANDOC_HTML_MANPAGE_FILTER), \ - CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \ - REPLACEMENTS := \ - @@COPYRIGHT_YEAR@@ => $(COPYRIGHT_YEAR) ; \ - @@VERSION_SHORT@@ => $(VERSION_SHORT) ; \ - @@VERSION_SPECIFICATION@@ => $(VERSION_SPECIFICATION), \ - OPTIONS := --toc -V include-before='$(SPECS_TOP)' -V include-after='$(SPECS_BOTTOM_1)', \ - POST_PROCESS := $(TOOL_FIXUPPANDOC) --insert-nav --nav-right-info '$(HEADER_RIGHT_SIDE_INFO)' \ - --nav-subdirs 1 --nav-link-guides, \ - EXTRA_DEPS := $(PANDOC_HTML_MANPAGE_FILTER) \ - $(PANDOC_HTML_MANPAGE_FILTER_SOURCE), \ - )) \ - $(eval JDK_SPECS_TARGETS += $($($m_$f_NAME))) \ - ) \ + $(eval MAN_$m := $(call ApplySpecFilter, $(filter %.md, $(call FindFiles, \ + $(call FindModuleManDirs, $m))))) \ + $(if $(MAN_$m), \ + $(eval $(call SetupProcessMarkdown, MAN_TO_HTML_$m, \ + FILES := $(MAN_$m), \ + DEST := $(DOCS_OUTPUTDIR)/specs/man, \ + FILTER := $(PANDOC_HTML_MANPAGE_FILTER), \ + CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \ + REPLACEMENTS := \ + @@COPYRIGHT_YEAR@@ => $(COPYRIGHT_YEAR) ; \ + @@VERSION_SHORT@@ => $(VERSION_SHORT) ; \ + @@VERSION_SPECIFICATION@@ => $(VERSION_SPECIFICATION), \ + OPTIONS := --toc -V include-before='$(SPECS_TOP)' -V include-after='$(SPECS_BOTTOM_1)', \ + POST_PROCESS := $(TOOL_FIXUPPANDOC) --insert-nav --nav-right-info '$(HEADER_RIGHT_SIDE_INFO)' \ + --nav-subdirs 1 --nav-link-guides, \ + EXTRA_DEPS := $(PANDOC_HTML_MANPAGE_FILTER) \ + $(PANDOC_HTML_MANPAGE_FILTER_SOURCE), \ + )) \ + $(eval JDK_SPECS_TARGETS += $(MAN_TO_HTML_$m)) \ ) \ ) diff --git a/make/TestImage.gmk b/make/TestImage.gmk index b719d6824da30..f6d680fb69073 100644 --- a/make/TestImage.gmk +++ b/make/TestImage.gmk @@ -28,6 +28,9 @@ default: all include $(SPEC) include MakeBase.gmk +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, TestImage-pre.gmk)) + ############################################################################ BUILD_INFO_PROPERTIES := $(TEST_IMAGE_DIR)/build-info.properties diff --git a/make/autoconf/flags-ldflags.m4 b/make/autoconf/flags-ldflags.m4 index acb815515a24d..c4a75fb89c39d 100644 --- a/make/autoconf/flags-ldflags.m4 +++ b/make/autoconf/flags-ldflags.m4 @@ -118,7 +118,6 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER], # Setup LDFLAGS for linking executables if test "x$TOOLCHAIN_TYPE" = xgcc; then - EXECUTABLE_LDFLAGS="$EXECUTABLE_LDFLAGS -Wl,--allow-shlib-undefined" # Enabling pie on 32 bit builds prevents the JVM from allocating a continuous # java heap. if test "x$OPENJDK_TARGET_CPU_BITS" != "x32"; then diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 8c91a2ccd33eb..23f331e79b7f9 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -190,6 +190,17 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS], fi AC_SUBST(INCLUDE_SA) + # Setup default CDS alignment. On platforms where one build may run on machines with different + # page sizes, the JVM choses a compatible alignment to fit all possible page sizes. This slightly + # increases archive size. + # The only platform having this problem at the moment is Linux on aarch64, which may encounter + # three different page sizes: 4K, 64K, and if run on Mac m1 hardware, 16K. + COMPATIBLE_CDS_ALIGNMENT_DEFAULT=false + if test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xaarch64"; then + COMPATIBLE_CDS_ALIGNMENT_DEFAULT=true + fi + AC_SUBST(COMPATIBLE_CDS_ALIGNMENT_DEFAULT) + # Compress jars COMPRESS_JARS=false @@ -673,7 +684,7 @@ AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE], # AC_DEFUN([JDKOPT_ENABLE_DISABLE_COMPATIBLE_CDS_ALIGNMENT], [ - UTIL_ARG_ENABLE(NAME: compatible-cds-alignment, DEFAULT: false, + UTIL_ARG_ENABLE(NAME: compatible-cds-alignment, DEFAULT: $COMPATIBLE_CDS_ALIGNMENT_DEFAULT, RESULT: ENABLE_COMPATIBLE_CDS_ALIGNMENT, DESC: [enable use alternative compatible cds core region alignment], DEFAULT_DESC: [disabled], diff --git a/make/common/ProcessMarkdown.gmk b/make/common/ProcessMarkdown.gmk index e78c026a89c37..125892504f91a 100644 --- a/make/common/ProcessMarkdown.gmk +++ b/make/common/ProcessMarkdown.gmk @@ -38,48 +38,53 @@ define ProcessMarkdown $1_$2_INPUT_FILE := $3/$2 $1_$2_MARKER := $$(subst /,_,$1_$2) - ifneq ($$($1_REPLACEMENTS), ) - $1_$2_PANDOC_INPUT := $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_pre.tmp - - $$(eval $$(call SetupTextFileProcessing, $1_$2_PREPROCESSED, \ - SOURCE_FILES := $$($1_$2_INPUT_FILE), \ - OUTPUT_FILE := $$($1_$2_PANDOC_INPUT), \ - REPLACEMENTS := $$($1_REPLACEMENTS), \ - )) - else - $1_$2_PANDOC_INPUT := $$($1_$2_INPUT_FILE) - endif - - ifneq ($$($1_POST_PROCESS), ) - $1_$2_PANDOC_OUTPUT := $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_post.tmp - else - $1_$2_PANDOC_OUTPUT := $$($1_$2_OUTPUT_FILE) - endif + # Only continue if this target file hasn't been processed already. This lets + # the first found source file override any other with the same name. + ifeq ($$($1_$2_OUTPUT_FILE_PROCESSED), ) + $1_$2_OUTPUT_FILE_PROCESSED := true + + ifneq ($$($1_REPLACEMENTS), ) + $1_$2_PANDOC_INPUT := $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_pre.tmp + + $$(eval $$(call SetupTextFileProcessing, $1_$2_PREPROCESSED, \ + SOURCE_FILES := $$($1_$2_INPUT_FILE), \ + OUTPUT_FILE := $$($1_$2_PANDOC_INPUT), \ + REPLACEMENTS := $$($1_REPLACEMENTS), \ + )) + else + $1_$2_PANDOC_INPUT := $$($1_$2_INPUT_FILE) + endif - ifneq ($$($1_CSS), ) - ifneq ($$(findstring https:/, $$($1_CSS)), ) - $1_$2_CSS_OPTION := --css '$$($1_CSS)' + ifneq ($$($1_POST_PROCESS), ) + $1_$2_PANDOC_OUTPUT := $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_post.tmp else - $1_$2_CSS := $$(strip $$(call RelativePath, $$($1_CSS), $$($1_$2_TARGET_DIR))) - $1_$2_CSS_OPTION := --css '$$($1_$2_CSS)' + $1_$2_PANDOC_OUTPUT := $$($1_$2_OUTPUT_FILE) endif - endif - # This does not need to be included in VARDEPS since it's from the actual - # source file. Only run the shell if the recipe gets executed below. - $1_$2_OPTIONS_FROM_SRC = \ - $$(shell $$(GREP) _pandoc-options_: $3/$2 | $$(CUT) -d : -f 2-) + ifneq ($$($1_CSS), ) + ifneq ($$(findstring https:/, $$($1_CSS)), ) + $1_$2_CSS_OPTION := --css '$$($1_CSS)' + else + $1_$2_CSS := $$(strip $$(call RelativePath, $$($1_CSS), $$($1_$2_TARGET_DIR))) + $1_$2_CSS_OPTION := --css '$$($1_$2_CSS)' + endif + endif - ifneq ($$($1_FILTER), ) - $1_$2_OPTIONS := --filter $$($1_FILTER) - endif + # This does not need to be included in VARDEPS since it's from the actual + # source file. Only run the shell if the recipe gets executed below. + $1_$2_OPTIONS_FROM_SRC = \ + $$(shell $$(GREP) _pandoc-options_: $3/$2 | $$(CUT) -d : -f 2-) + + ifneq ($$($1_FILTER), ) + $1_$2_OPTIONS := --filter $$($1_FILTER) + endif - $1_$2_VARDEPS := $$($1_OPTIONS) $$($1_$2_OPTIONS) $$($1_CSS) \ - $$($1_REPLACEMENTS) $$($1_POST_PROCESS) - $1_$2_VARDEPS_FILE := $$(call DependOnVariable, $1_$2_VARDEPS, \ - $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER).vardeps) + $1_$2_VARDEPS := $$($1_OPTIONS) $$($1_$2_OPTIONS) $$($1_CSS) \ + $$($1_REPLACEMENTS) $$($1_POST_PROCESS) + $1_$2_VARDEPS_FILE := $$(call DependOnVariable, $1_$2_VARDEPS, \ + $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER).vardeps) - $$($1_$2_PANDOC_OUTPUT): $$($1_$2_PANDOC_INPUT) $$($1_$2_VARDEPS_FILE) $$($1_EXTRA_DEPS) + $$($1_$2_PANDOC_OUTPUT): $$($1_$2_PANDOC_INPUT) $$($1_$2_VARDEPS_FILE) $$($1_EXTRA_DEPS) $$(call LogInfo, Converting $2 to $$($1_FORMAT)) $$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$(dir $$($1_$2_PANDOC_OUTPUT))) $$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER), \ @@ -96,17 +101,18 @@ define ProcessMarkdown fi endif - # If we have no post processing, PANDOC_OUTPUT is set to OUTPUT_FILE. Otherwise - # PANDOC_OUTPUT is a temporary file, and we must now create the real OUTPUT_FILE. - ifneq ($$($1_POST_PROCESS), ) - $$($1_$2_OUTPUT_FILE): $$($1_$2_PANDOC_OUTPUT) + # If we have no post processing, PANDOC_OUTPUT is set to OUTPUT_FILE. Otherwise + # PANDOC_OUTPUT is a temporary file, and we must now create the real OUTPUT_FILE. + ifneq ($$($1_POST_PROCESS), ) + $$($1_$2_OUTPUT_FILE): $$($1_$2_PANDOC_OUTPUT) $$(call LogInfo, Post-processing markdown file $2) $$(call MakeDir, $$(SUPPORT_OUTPUTDIR)/markdown $$($1_$2_TARGET_DIR)) $$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/markdown/$$($1_$2_MARKER)_post, \ ( $$($1_POST_PROCESS) $$($1_$2_PANDOC_OUTPUT) > $$($1_$2_OUTPUT_FILE) ) ) - endif + endif - $1 += $$($1_$2_OUTPUT_FILE) + $1 += $$($1_$2_OUTPUT_FILE) + endif endef ################################################################################ diff --git a/make/conf/module-loader-map.conf b/make/conf/module-loader-map.conf index 5b72bf78aa013..e904031186dee 100644 --- a/make/conf/module-loader-map.conf +++ b/make/conf/module-loader-map.conf @@ -120,6 +120,7 @@ NATIVE_ACCESS_MODULES= \ jdk.dynalink \ jdk.httpserver \ jdk.incubator.vector \ + jdk.internal.le \ jdk.internal.vm.ci \ jdk.jfr \ jdk.jsobject \ diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java index 8d39ef4c1d55b..15251358a01a1 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java @@ -87,6 +87,7 @@ public class CLDRConverter { static final String ZONE_NAME_PREFIX = "timezone.displayname."; static final String METAZONE_ID_PREFIX = "metazone.id."; static final String PARENT_LOCALE_PREFIX = "parentLocale."; + static final String LIKELY_SCRIPT_PREFIX = "likelyScript."; static final String META_EMPTY_ZONE_NAME = "EMPTY_ZONE"; static final String[] EMPTY_ZONE = {"", "", "", "", "", ""}; static final String META_ETCUTC_ZONE_NAME = "ETC_UTC"; @@ -114,9 +115,13 @@ public class CLDRConverter { // "parentLocales" map private static final Map> parentLocalesMap = new HashMap<>(); + static boolean nonlikelyScript; private static final ResourceBundle.Control defCon = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT); + // "likelyScript" map + private static final Map> likelyScriptMap = new HashMap<>(); + private static Set AVAILABLE_TZIDS; static int copyrightYear; static String jdkHeaderTemplate; @@ -175,7 +180,7 @@ String getKeyword() { private static boolean verbose; private CLDRConverter() { - // no instantiation + // no instantiation } @SuppressWarnings("AssignmentToForLoopParameter") @@ -475,8 +480,8 @@ private static void parseSupplemental() throws Exception { parseLDMLFile(new File(SPPL_SOURCE_FILE), handlerSuppl); Map parentData = handlerSuppl.getData("root"); parentData.keySet().stream() - .filter(key -> key.startsWith(PARENT_LOCALE_PREFIX)) - .forEach(key -> { + .filter(key -> key.startsWith(PARENT_LOCALE_PREFIX)) + .forEach(key -> { parentLocalesMap.put(key, new TreeSet( Arrays.asList(((String)parentData.get(key)).split(" ")))); }); @@ -492,6 +497,16 @@ private static void parseSupplemental() throws Exception { // Parse likelySubtags handlerLikelySubtags = new LikelySubtagsParseHandler(); parseLDMLFile(new File(LIKELYSUBTAGS_SOURCE_FILE), handlerLikelySubtags); + handlerLikelySubtags.getData().forEach((from, to) -> { + if (!from.contains("-")) { // look for language-only tag + var script = to.split("-")[1]; + var key = LIKELY_SCRIPT_PREFIX + script; + var prev = likelyScriptMap.putIfAbsent(key, new TreeSet(Set.of(from))); + if (prev != null) { + prev.add(from); + } + } + }); // Parse supplementalMetadata // Currently interested in deprecated time zone ids and language aliases. @@ -561,6 +576,7 @@ private static void convertBundles(List bundles) throws Exception { // for now. if (isBaseModule) { metaInfo.putAll(parentLocalesMap); + metaInfo.putAll(likelyScriptMap); } for (Bundle bundle : bundles) { @@ -1135,7 +1151,7 @@ private static List applyParentLocales(String baseName, List can // check irregular parents for (int i = 0; i < candidates.size(); i++) { Locale l = candidates.get(i); - Locale p = childToParentLocaleMap.get(l); + Locale p = getParentLocale(l); if (!l.equals(Locale.ROOT) && Objects.nonNull(p) && !candidates.get(i+1).equals(p)) { @@ -1152,6 +1168,27 @@ private static List applyParentLocales(String baseName, List can return candidates; } + private static Locale getParentLocale(Locale child) { + Locale parent = childToParentLocaleMap.get(child); + + // check non-likely script for root + if (nonlikelyScript && parent == null && child.getCountry().isEmpty()) { + var lang = " " + child.getLanguage() + " "; + var script = child.getScript(); + + if (!script.isEmpty()) { + parent = likelyScriptMap.entrySet().stream() + .filter(e -> e.getValue().contains(lang)) + .findAny() + .map(Map.Entry::getKey) + .map(likely -> likely.equals(script) ? null : Locale.ROOT) + .orElse(null); + } + } + + return parent; + } + private static void generateZoneName() throws Exception { Files.createDirectories(Paths.get(DESTINATION_DIR, "java", "time", "format")); Files.write(Paths.get(DESTINATION_DIR, "java", "time", "format", "ZoneName.java"), diff --git a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java index 49c74544be66e..3953f38f653e6 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.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 @@ -38,6 +38,7 @@ import java.util.Objects; import java.util.Set; import java.util.SortedSet; +import java.util.stream.Collectors; class ResourceBundleGenerator implements BundleGenerator { // preferred timezones - keeping compatibility with JDK1.1 3 letter abbreviations @@ -306,81 +307,77 @@ public void generateMetaInfo(Map> metaInfo) throws IOE import sun.util.locale.provider.LocaleProviderAdapter; public class %s implements LocaleDataMetaInfo { - private static final Map resourceNameToLocales = HashMap.newHashMap(%d); - %s - static { - """, CLDRConverter.isBaseModule ? "cldr" : "resources.cldr.provider", - className, metaInfo.keySet().stream().filter(k -> k.equals("AvailableLocales")).count(), - CLDRConverter.isBaseModule ? - """ + """, + CLDRConverter.isBaseModule ? "cldr" : "resources.cldr.provider", + className); + + if (CLDRConverter.isBaseModule) { + out.printf(""" private static final Map parentLocalesMap = HashMap.newHashMap(%d); private static final Map languageAliasMap = HashMap.newHashMap(%d); + static final boolean nonlikelyScript = %s; // package access from CLDRLocaleProviderAdapter + + static { """.formatted( metaInfo.keySet().stream().filter(k -> k.startsWith(CLDRConverter.PARENT_LOCALE_PREFIX)).count(), - CLDRConverter.handlerSupplMeta.getLanguageAliasData().size()) : - ""); - - for (String key : metaInfo.keySet()) { - if (key.startsWith(CLDRConverter.PARENT_LOCALE_PREFIX)) { - String parentTag = key.substring(CLDRConverter.PARENT_LOCALE_PREFIX.length()); - if ("root".equals(parentTag)) { - out.printf(" parentLocalesMap.put(Locale.ROOT,\n"); - } else { - out.printf(" parentLocalesMap.put(Locale.forLanguageTag(\"%s\"),\n", - parentTag); - } - String[] children = toLocaleList(metaInfo.get(key), true).split(" "); - Arrays.sort(children); - out.printf(" new String[] {\n" + - " "); - int count = 0; - for (int i = 0; i < children.length; i++) { - String child = children[i]; - out.printf("\"%s\", ", child); - count += child.length() + 4; - if (i != children.length - 1 && count > 64) { - out.printf("\n "); - count = 0; + CLDRConverter.handlerSupplMeta.getLanguageAliasData().size(), + Boolean.valueOf(CLDRConverter.nonlikelyScript))); + + for (String key : metaInfo.keySet()) { + if (key.startsWith(CLDRConverter.PARENT_LOCALE_PREFIX)) { + String parentTag = key.substring(CLDRConverter.PARENT_LOCALE_PREFIX.length()); + if ("root".equals(parentTag)) { + out.printf(" parentLocalesMap.put(Locale.ROOT,\n"); + } else { + out.printf(" parentLocalesMap.put(Locale.forLanguageTag(\"%s\"),\n", + parentTag); } - } - out.printf("\n });\n"); - } else { - if ("AvailableLocales".equals(key)) { - out.printf(" resourceNameToLocales.put(\"%s\",\n", key); - out.printf(" \"%s\");\n", toLocaleList(applyLanguageAliases(metaInfo.get(key)), false)); + generateStringArray(metaInfo.get(key), out); } } - } - // for languageAliasMap - if (CLDRConverter.isBaseModule) { + out.println(); + + // for languageAliasMap CLDRConverter.handlerSupplMeta.getLanguageAliasData().forEach((key, value) -> { out.printf(" languageAliasMap.put(\"%s\", \"%s\");\n", key, value); }); - } + out.printf(" }\n\n"); - out.printf(" }\n\n"); + // end of static initializer block. - // end of static initializer block. - - // Canonical TZ names for delayed initialization - if (CLDRConverter.isBaseModule) { + // Delayed initialization section out.printf(""" - private static class TZCanonicalIDMapHolder { - static final Map tzCanonicalIDMap = HashMap.newHashMap(%d); + private static class CLDRMapHolder { + private static final Map tzCanonicalIDMap = HashMap.newHashMap(%d); + private static final Map likelyScriptMap = HashMap.newHashMap(%d); + static { - """, CLDRConverter.handlerTimeZone.getData().size()); + """, CLDRConverter.handlerTimeZone.getData().size(), + metaInfo.keySet().stream().filter(k -> k.startsWith(CLDRConverter.LIKELY_SCRIPT_PREFIX)).count()); CLDRConverter.handlerTimeZone.getData().entrySet().stream() .forEach(e -> { String[] ids = ((String)e.getValue()).split("\\s"); out.printf(" tzCanonicalIDMap.put(\"%s\", \"%s\");\n", e.getKey(), - ids[0]); + ids[0]); for (int i = 1; i < ids.length; i++) { out.printf(" tzCanonicalIDMap.put(\"%s\", \"%s\");\n", ids[i], ids[0]); } }); - out.printf(" }\n }\n\n"); + out.println(); + + // for likelyScript map + for (String key : metaInfo.keySet()) { + if (key.startsWith(CLDRConverter.LIKELY_SCRIPT_PREFIX)) { + // ensure spaces at the begin/end for delimiting purposes + out.printf(" likelyScriptMap.put(\"%s\", \"%s\");\n", + key.substring(CLDRConverter.LIKELY_SCRIPT_PREFIX.length()), + " " + metaInfo.get(key).stream().collect(Collectors.joining(" ")) + " "); + } + } + out.printf(" }\n }\n"); } + out.println(); out.printf(""" @Override @@ -390,12 +387,13 @@ public LocaleProviderAdapter.Type getType() { @Override public String availableLanguageTags(String category) { - return resourceNameToLocales.getOrDefault(category, ""); + return " %s"; } - %s - } """, - CLDRConverter.isBaseModule ? """ + toLocaleList(applyLanguageAliases(metaInfo.get("AvailableLocales")), false)); + + if(CLDRConverter.isBaseModule) { + out.printf(""" @Override public Map getLanguageAliasMap() { @@ -404,16 +402,41 @@ public Map getLanguageAliasMap() { @Override public Map tzCanonicalIDs() { - return TZCanonicalIDMapHolder.tzCanonicalIDMap; + return CLDRMapHolder.tzCanonicalIDMap; } public Map parentLocales() { return parentLocalesMap; } - """ : ""); + + // package access from CLDRLocaleProviderAdapter + Map likelyScriptMap() { + return CLDRMapHolder.likelyScriptMap; + } + """); + } + out.printf("}\n"); } } + private static void generateStringArray(SortedSet set, PrintWriter out) throws IOException { + String[] children = toLocaleList(set, true).split(" "); + Arrays.sort(children); + out.printf(" new String[] {\n" + + " "); + int count = 0; + for (int i = 0; i < children.length; i++) { + String child = children[i]; + out.printf("\"%s\", ", child); + count += child.length() + 4; + if (i != children.length - 1 && count > 64) { + out.printf("\n "); + count = 0; + } + } + out.printf("\n });\n"); + } + private static final Locale.Builder LOCALE_BUILDER = new Locale.Builder(); private static boolean isBaseLocale(String localeID) { localeID = localeID.replaceAll("-", "_"); @@ -433,7 +456,9 @@ private static String toLocaleList(SortedSet set, boolean all) { if (!all && CLDRConverter.isBaseModule ^ isBaseLocale(id)) { continue; } - sb.append(' '); + if (sb.length() > 0) { + sb.append(' '); + } sb.append(id); } } diff --git a/make/jdk/src/classes/build/tools/cldrconverter/SupplementalDataParseHandler.java b/make/jdk/src/classes/build/tools/cldrconverter/SupplementalDataParseHandler.java index f4d20160ffb3b..9ba4d64519949 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/SupplementalDataParseHandler.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/SupplementalDataParseHandler.java @@ -57,29 +57,22 @@ class SupplementalDataParseHandler extends AbstractLDMLHandler { // the weekData is listed using country code. // // weekData are generated per each country - private final Map firstDayMap; - private final Map minDaysMap; + private static final Map firstDayMap = new HashMap<>(); + private static final Map minDaysMap = new HashMap<>(); // Parent locales. These information will only be // generated towards the base meta info, with the format of // // parentLocale.=(" ")+ - private final Map parentLocalesMap; + private static final Map parentLocalesMap = new HashMap<>(); // Input Skeleton map for "preferred" and "allowed" // Map<"preferred"/"allowed", Map<"skeleton", SortedSet<"regions">>> - private final Map>> inputSkeletonMap; + private static final Map>> inputSkeletonMap = new HashMap<>(); // "component" specific to this parent locale chain private String currentParentLocaleComponent; - SupplementalDataParseHandler() { - firstDayMap = new HashMap<>(); - minDaysMap = new HashMap<>(); - parentLocalesMap = new HashMap<>(); - inputSkeletonMap = new HashMap<>(); - } - /** * It returns Map that contains the firstDay and minDays information for * the country. The Map is created in JRE format after obtaining the data @@ -158,9 +151,15 @@ public void startElement(String uri, String localName, String qName, Attributes // Ignore component for now, otherwise "zh-Hant" falling back to "zh" would happen // https://github.com/unicode-org/cldr/pull/2664 if (currentParentLocaleComponent == null) { + var parent = attributes.getValue("parent").replaceAll("_", "-"); + parentLocalesMap.put( - attributes.getValue("parent").replaceAll("_", "-"), + parent, attributes.getValue("locales").replaceAll("_", "-")); + + if ("root".equals(parent)) { + CLDRConverter.nonlikelyScript = "nonlikelyScript".equals(attributes.getValue("localeRules")); + } } } break; diff --git a/make/modules/jdk.httpserver/Java.gmk b/make/modules/jdk.httpserver/Java.gmk index d7b2b2f70ca21..799ff8695a74c 100644 --- a/make/modules/jdk.httpserver/Java.gmk +++ b/make/modules/jdk.httpserver/Java.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 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 @@ -24,3 +24,5 @@ # DISABLED_WARNINGS_java += missing-explicit-ctor this-escape + +COPY += .ico diff --git a/make/modules/jdk.internal.le/Lib.gmk b/make/modules/jdk.internal.le/Lib.gmk deleted file mode 100644 index e81137e0d5387..0000000000000 --- a/make/modules/jdk.internal.le/Lib.gmk +++ /dev/null @@ -1,45 +0,0 @@ -# -# 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 -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -include LibCommon.gmk - -ifeq ($(call isTargetOs, aix), false) - ############################################################################## - ## Build lible - ############################################################################## - - $(eval $(call SetupJdkLibrary, BUILD_LIBLE, \ - NAME := le, \ - LINK_TYPE := C++, \ - OPTIMIZATION := LOW, \ - EXTRA_HEADER_DIRS := \ - java.base:libjava \ - java.base:libjvm, \ - LD_SET_ORIGIN := false, \ - LIBS_windows := user32.lib, \ - )) - - TARGETS += $(BUILD_LIBLE) -endif diff --git a/src/hotspot/cpu/aarch64/gc/x/xGlobals_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/x/xGlobals_aarch64.cpp index 6204f21270374..a9c53da3d0186 100644 --- a/src/hotspot/cpu/aarch64/gc/x/xGlobals_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/x/xGlobals_aarch64.cpp @@ -142,9 +142,11 @@ // * 63-48 Fixed (16-bits, always zero) // -// Default value if probing is not implemented for a certain platform: 128TB -static const size_t DEFAULT_MAX_ADDRESS_BIT = 47; -// Minimum value returned, if probing fails: 64GB +// Default value if probing is not implemented for a certain platform +// Max address bit is restricted by implicit assumptions in the code, for instance +// the bit layout of XForwardingEntry or Partial array entry (see XMarkStackEntry) in mark stack +static const size_t DEFAULT_MAX_ADDRESS_BIT = 46; +// Minimum value returned, if probing fails static const size_t MINIMUM_MAX_ADDRESS_BIT = 36; static size_t probe_valid_max_address_bit() { diff --git a/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp index 6c3cea73d1a79..e140525bcbc5f 100644 --- a/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/z/zAddress_aarch64.cpp @@ -36,9 +36,11 @@ #include #endif // LINUX -// Default value if probing is not implemented for a certain platform: 128TB -static const size_t DEFAULT_MAX_ADDRESS_BIT = 47; -// Minimum value returned, if probing fails: 64GB +// Default value if probing is not implemented for a certain platform +// Max address bit is restricted by implicit assumptions in the code, for instance +// the bit layout of XForwardingEntry or Partial array entry (see XMarkStackEntry) in mark stack +static const size_t DEFAULT_MAX_ADDRESS_BIT = 46; +// Minimum value returned, if probing fail static const size_t MINIMUM_MAX_ADDRESS_BIT = 36; static size_t probe_valid_max_address_bit() { diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index b90b5862ee50e..faba321afc7f3 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -5535,12 +5535,22 @@ address MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3, Label DONE, SAME; Register tmp1 = rscratch1; Register tmp2 = rscratch2; - Register cnt2 = tmp2; // cnt2 only used in array length compare int elem_per_word = wordSize/elem_size; int log_elem_size = exact_log2(elem_size); + int klass_offset = arrayOopDesc::klass_offset_in_bytes(); int length_offset = arrayOopDesc::length_offset_in_bytes(); int base_offset = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); + // When the length offset is not aligned to 8 bytes, + // then we align it down. This is valid because the new + // offset will always be the klass which is the same + // for type arrays. + int start_offset = align_down(length_offset, BytesPerWord); + int extra_length = base_offset - start_offset; + assert(start_offset == length_offset || start_offset == klass_offset, + "start offset must be 8-byte-aligned or be the klass offset"); + assert(base_offset != start_offset, "must include the length field"); + extra_length = extra_length / elem_size; // We count in elements, not bytes. int stubBytesThreshold = 3 * 64 + (UseSIMDForArrayEquals ? 0 : 16); assert(elem_size == 1 || elem_size == 2, "must be char or byte"); @@ -5574,11 +5584,10 @@ address MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3, // return false; bind(A_IS_NOT_NULL); ldrw(cnt1, Address(a1, length_offset)); - ldrw(cnt2, Address(a2, length_offset)); - eorw(tmp5, cnt1, cnt2); - cbnzw(tmp5, DONE); - lea(a1, Address(a1, base_offset)); - lea(a2, Address(a2, base_offset)); + // Increase loop counter by diff between base- and actual start-offset. + addw(cnt1, cnt1, extra_length); + lea(a1, Address(a1, start_offset)); + lea(a2, Address(a2, start_offset)); // Check for short strings, i.e. smaller than wordSize. subs(cnt1, cnt1, elem_per_word); br(Assembler::LT, SHORT); @@ -5641,18 +5650,18 @@ address MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3, cbz(a1, DONE); ldrw(cnt1, Address(a1, length_offset)); cbz(a2, DONE); - ldrw(cnt2, Address(a2, length_offset)); + // Increase loop counter by diff between base- and actual start-offset. + addw(cnt1, cnt1, extra_length); + // on most CPUs a2 is still "locked"(surprisingly) in ldrw and it's // faster to perform another branch before comparing a1 and a2 cmp(cnt1, (u1)elem_per_word); br(LE, SHORT); // short or same - ldr(tmp3, Address(pre(a1, base_offset))); + ldr(tmp3, Address(pre(a1, start_offset))); subs(zr, cnt1, stubBytesThreshold); br(GE, STUB); - ldr(tmp4, Address(pre(a2, base_offset))); + ldr(tmp4, Address(pre(a2, start_offset))); sub(tmp5, zr, cnt1, LSL, 3 + log_elem_size); - cmp(cnt2, cnt1); - br(NE, DONE); // Main 16 byte comparison loop with 2 exits bind(NEXT_DWORD); { @@ -5684,9 +5693,7 @@ address MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3, b(LAST_CHECK); bind(STUB); - ldr(tmp4, Address(pre(a2, base_offset))); - cmp(cnt2, cnt1); - br(NE, DONE); + ldr(tmp4, Address(pre(a2, start_offset))); if (elem_size == 2) { // convert to byte counter lsl(cnt1, cnt1, 1); } @@ -5707,12 +5714,9 @@ address MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3, mov(result, a2); b(DONE); bind(SHORT); - cmp(cnt2, cnt1); - br(NE, DONE); - cbz(cnt1, SAME); sub(tmp5, zr, cnt1, LSL, 3 + log_elem_size); - ldr(tmp3, Address(a1, base_offset)); - ldr(tmp4, Address(a2, base_offset)); + ldr(tmp3, Address(a1, start_offset)); + ldr(tmp4, Address(a2, start_offset)); bind(LAST_CHECK); eor(tmp4, tmp3, tmp4); lslv(tmp5, tmp4, tmp5); diff --git a/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp b/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp index 5424f0d9c7572..332f24996930f 100644 --- a/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp @@ -32,7 +32,7 @@ #include "runtime/safepoint.hpp" -void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { +void Relocation::pd_set_data_value(address x, bool verify_only) { if (verify_only) return; diff --git a/src/hotspot/cpu/arm/relocInfo_arm.cpp b/src/hotspot/cpu/arm/relocInfo_arm.cpp index fc5b2981ce69c..fb112cdcfc0fa 100644 --- a/src/hotspot/cpu/arm/relocInfo_arm.cpp +++ b/src/hotspot/cpu/arm/relocInfo_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -30,13 +30,13 @@ #include "oops/oop.hpp" #include "runtime/safepoint.hpp" -void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { +void Relocation::pd_set_data_value(address x, bool verify_only) { NativeMovConstReg* ni = nativeMovConstReg_at(addr()); if (verify_only) { - guarantee(ni->data() == (intptr_t)(x + o), "instructions must match"); + guarantee(ni->data() == (intptr_t)x, "instructions must match"); } else { - ni->set_data((intptr_t)(x + o)); + ni->set_data((intptr_t)x); } } diff --git a/src/hotspot/cpu/ppc/relocInfo_ppc.cpp b/src/hotspot/cpu/ppc/relocInfo_ppc.cpp index 39e50465231ae..5d0d2785bf427 100644 --- a/src/hotspot/cpu/ppc/relocInfo_ppc.cpp +++ b/src/hotspot/cpu/ppc/relocInfo_ppc.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) 2012, 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -32,10 +32,7 @@ #include "oops/oop.hpp" #include "runtime/safepoint.hpp" -void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { - // Currently we don't support splitting of relocations. - assert(o == 0, "tried to split relocations"); - +void Relocation::pd_set_data_value(address x, bool verify_only) { if (!verify_only) { if (format() != 1) { nativeMovConstReg_at(addr())->set_data_plain(((intptr_t)x), code()); diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 388e7f9eb941f..2db57083ce5a6 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -1887,8 +1887,12 @@ enum Nf { } // Vector Bit-manipulation used in Cryptography (Zvkb) Extension - INSN(vbrev8_v, 0b1010111, 0b010, 0b01000, 0b010010); - INSN(vrev8_v, 0b1010111, 0b010, 0b01001, 0b010010); + INSN(vbrev_v, 0b1010111, 0b010, 0b01010, 0b010010); // reverse bits in every element + INSN(vbrev8_v, 0b1010111, 0b010, 0b01000, 0b010010); // reverse bits in every byte of element + INSN(vrev8_v, 0b1010111, 0b010, 0b01001, 0b010010); // reverse bytes in every elememt + + INSN(vclz_v, 0b1010111, 0b010, 0b01100, 0b010010); // count leading zeros + INSN(vctz_v, 0b1010111, 0b010, 0b01101, 0b010010); // count trailing zeros #undef INSN @@ -1904,6 +1908,16 @@ enum Nf { #undef INSN +#define INSN(NAME, op, funct3, Vs1, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2, VectorMask vm = unmasked) { \ + patch_VArith(op, Vd, funct3, Vs1, Vs2, vm, funct6); \ + } + + // Vector Basic Bit-manipulation (Zvbb) Extension + INSN(vcpop_v, 0b1010111, 0b010, 0b01110, 0b010010); + +#undef INSN + #undef patch_VArith // ==================================== diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp index e22456cacc603..c39b29f6ee4a7 100644 --- a/src/hotspot/cpu/riscv/globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -115,6 +115,7 @@ define_pd_global(intx, InlineSmallCode, 1000); product(bool, UseZtso, false, EXPERIMENTAL, "Assume Ztso memory model") \ product(bool, UseZihintpause, false, EXPERIMENTAL, \ "Use Zihintpause instructions") \ + product(bool, UseZvbb, false, EXPERIMENTAL, "Use Zvbb instructions") \ product(bool, UseZvfh, false, EXPERIMENTAL, "Use Zvfh instructions") \ product(bool, UseZvkn, false, EXPERIMENTAL, \ "Use Zvkn group extension, Zvkned, Zvknhb, Zvkb, Zvkt") \ diff --git a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp index 0e50d0b0796ca..b3cdb93a979d8 100644 --- a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp +++ b/src/hotspot/cpu/riscv/relocInfo_riscv.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. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -31,7 +31,7 @@ #include "oops/oop.inline.hpp" #include "runtime/safepoint.hpp" -void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { +void Relocation::pd_set_data_value(address x, bool verify_only) { if (verify_only) { return; } diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index 7869d6156e590..3d2cbbe5cf4dc 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -73,6 +73,12 @@ source %{ return false; } break; + case Op_CountTrailingZerosV: + case Op_CountLeadingZerosV: + case Op_ReverseBytesV: + case Op_PopCountVL: + case Op_PopCountVI: + return UseZvbb; case Op_LoadVectorGather: case Op_LoadVectorGatherMasked: if (is_subword_type(bt)) { @@ -3753,6 +3759,32 @@ instruct vsignum_reg(vReg dst, vReg zero, vReg one, vRegMask_V0 v0) %{ ins_pipe(pipe_slow); %} +// -------------------------------- Reverse Bytes Vector Operations ------------------------ + +instruct vreverse_bytes_masked(vReg dst_src, vRegMask_V0 v0) %{ + match(Set dst_src (ReverseBytesV dst_src v0)); + format %{ "vreverse_bytes_masked $dst_src, $dst_src, v0" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vrev8_v(as_VectorRegister($dst_src$$reg), as_VectorRegister($dst_src$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vreverse_bytes(vReg dst, vReg src) %{ + match(Set dst (ReverseBytesV src)); + format %{ "vreverse_bytes $dst, $src" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vrev8_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + // ---------------- Convert Half Floating to Floating Vector Operations ---------------- // half precision -> single @@ -3784,6 +3816,93 @@ instruct vconvF2HF(vReg dst, vReg src, vReg vtmp, vRegMask_V0 v0, iRegINoSp tmp) ins_pipe(pipe_slow); %} + +// ------------------------------ Popcount vector ------------------------------ + +instruct vpopcount_masked(vReg dst_src, vRegMask_V0 v0) %{ + match(Set dst_src (PopCountVI dst_src v0)); + match(Set dst_src (PopCountVL dst_src v0)); + ins_cost(VEC_COST); + format %{ "vcpop_v $dst_src, $dst_src, $v0\t# vcpop_v with mask" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vcpop_v(as_VectorRegister($dst_src$$reg), as_VectorRegister($dst_src$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vpopcount(vReg dst, vReg src) %{ + match(Set dst (PopCountVI src)); + match(Set dst (PopCountVL src)); + ins_cost(VEC_COST); + format %{ "vcpop_v $dst, $src\t# vcpop_v without mask" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vcpop_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// ------------------------------ CountLeadingZerosV -------------------------- + +instruct vcountLeadingZeros_masked(vReg dst_src, vRegMask_V0 v0) %{ + match(Set dst_src (CountLeadingZerosV dst_src v0)); + ins_cost(VEC_COST); + format %{ "vcount_leading_zeros_masked $dst_src, $dst_src, v0" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vclz_v(as_VectorRegister($dst_src$$reg), as_VectorRegister($dst_src$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vcountLeadingZeros(vReg dst, vReg src) %{ + match(Set dst (CountLeadingZerosV src)); + ins_cost(VEC_COST); + format %{ "vcount_leading_zeros $dst, $src" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vclz_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + +// ------------------------------ CountTrailingZerosV -------------------------- + +instruct vcountTrailingZeros_masked(vReg dst_src, vRegMask_V0 v0) %{ + match(Set dst_src (CountTrailingZerosV dst_src v0)); + ins_cost(VEC_COST); + format %{ "vcount_trailing_zeros_masked $dst_src, $dst_src, v0" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vctz_v(as_VectorRegister($dst_src$$reg), as_VectorRegister($dst_src$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vcountTrailingZeros(vReg dst, vReg src) %{ + match(Set dst (CountTrailingZerosV src)); + ins_cost(VEC_COST); + format %{ "vcount_trailing_zeros $dst, $src" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vctz_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + // ------------------------------ Vector Load Gather --------------------------- instruct gather_load(vReg dst, indirect mem, vReg idx) %{ diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 848ffe709d882..995e8b722485d 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -245,6 +245,12 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false); } + // UseZvbb (depends on RVV). + if (UseZvbb && !UseRVV) { + FLAG_SET_DEFAULT(UseZvbb, false); + warning("Cannot enable UseZvbb on cpu without RVV support."); + } + // SHA's if (FLAG_IS_DEFAULT(UseSHA)) { FLAG_SET_DEFAULT(UseSHA, true); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index d26b16941dbfe..f3a834b72379c 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -161,6 +161,7 @@ class VM_Version : public Abstract_VM_Version { decl(ext_Ztso , "Ztso" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \ decl(ext_Zihintpause , "Zihintpause" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \ decl(ext_Zacas , "Zacas" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \ + decl(ext_Zvbb , "Zvbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZvbb)) \ decl(ext_Zvfh , "Zvfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZvfh)) \ decl(ext_Zvkn , "Zvkn" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZvkn)) \ decl(mvendorid , "VendorId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ diff --git a/src/hotspot/cpu/s390/assembler_s390.hpp b/src/hotspot/cpu/s390/assembler_s390.hpp index 91cc7e611bfd1..cf80d164fafe6 100644 --- a/src/hotspot/cpu/s390/assembler_s390.hpp +++ b/src/hotspot/cpu/s390/assembler_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2023 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -352,10 +352,6 @@ class AddressLiteral { relocInfo::relocType rtype() const { return _rspec.type(); } const RelocationHolder& rspec() const { return _rspec; } - - RelocationHolder rspec(int offset) const { - return offset == 0 ? _rspec : _rspec.plus(offset); - } }; // Convenience classes diff --git a/src/hotspot/cpu/s390/relocInfo_s390.cpp b/src/hotspot/cpu/s390/relocInfo_s390.cpp index 747ae9c535d06..9e352be20a3a2 100644 --- a/src/hotspot/cpu/s390/relocInfo_s390.cpp +++ b/src/hotspot/cpu/s390/relocInfo_s390.cpp @@ -30,27 +30,25 @@ #include "oops/oop.inline.hpp" #include "runtime/safepoint.hpp" -void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { - // we don't support splitting of relocations, so o must be zero: - assert(o == 0, "tried to split relocations"); +void Relocation::pd_set_data_value(address x, bool verify_only) { if (!verify_only) { switch (format()) { case relocInfo::uncompressed_format: - nativeMovConstReg_at(addr())->set_data_plain(((intptr_t)x) + o, code()); + nativeMovConstReg_at(addr())->set_data_plain(((intptr_t)x), code()); break; case relocInfo::compressed_format: if (type() == relocInfo::metadata_type) - nativeMovConstReg_at(addr())->set_narrow_klass(((intptr_t)x) + o); + nativeMovConstReg_at(addr())->set_narrow_klass(((intptr_t)x)); else if (type() == relocInfo::oop_type) - nativeMovConstReg_at(addr())->set_narrow_oop(((intptr_t)x) + o); + nativeMovConstReg_at(addr())->set_narrow_oop(((intptr_t)x)); else guarantee(false, "bad relocInfo type for relocInfo::narrow_oop_format"); break; case relocInfo::pcrel_addr_format: // patch target location - nativeMovConstReg_at(addr())->set_pcrel_addr(((intptr_t)x) + o, code()); + nativeMovConstReg_at(addr())->set_pcrel_addr(((intptr_t)x), code()); break; case relocInfo::pcrel_data_format: // patch data at target location - nativeMovConstReg_at(addr())->set_pcrel_data(((intptr_t)x) + o, code()); + nativeMovConstReg_at(addr())->set_pcrel_data(((intptr_t)x), code()); break; default: assert(false, "not a valid relocInfo format"); diff --git a/src/hotspot/cpu/x86/relocInfo_x86.cpp b/src/hotspot/cpu/x86/relocInfo_x86.cpp index db806419b51d4..d7fddf838ac8e 100644 --- a/src/hotspot/cpu/x86/relocInfo_x86.cpp +++ b/src/hotspot/cpu/x86/relocInfo_x86.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 @@ -36,9 +36,8 @@ #include "utilities/checkedCast.hpp" -void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { +void Relocation::pd_set_data_value(address x, bool verify_only) { #ifdef AMD64 - x += o; typedef Assembler::WhichOperand WhichOperand; WhichOperand which = (WhichOperand) format(); // that is, disp32 or imm, call32, narrow oop assert(which == Assembler::disp32_operand || @@ -80,9 +79,9 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { } #else if (verify_only) { - guarantee(*pd_address_in_code() == (x + o), "instructions must match"); + guarantee(*pd_address_in_code() == x, "instructions must match"); } else { - *pd_address_in_code() = x + o; + *pd_address_in_code() = x; } #endif // AMD64 } diff --git a/src/hotspot/cpu/zero/relocInfo_zero.cpp b/src/hotspot/cpu/zero/relocInfo_zero.cpp index 1e9fdc1081d48..b926f20cfe7d8 100644 --- a/src/hotspot/cpu/zero/relocInfo_zero.cpp +++ b/src/hotspot/cpu/zero/relocInfo_zero.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. * Copyright 2007, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,7 +30,7 @@ #include "oops/oop.inline.hpp" #include "runtime/safepoint.hpp" -void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { +void Relocation::pd_set_data_value(address x, bool verify_only) { ShouldNotCallThis(); } diff --git a/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S b/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S index 54775cb7e8ede..a0f8577d8d199 100644 --- a/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S +++ b/src/hotspot/os_cpu/linux_x86/safefetch_linux_x86_32.S @@ -36,7 +36,7 @@ # 8(%esp) : default value # 4(%esp) : crash address # 0(%esp) : return pc - .type _SafeFetch32_impl,@function + .type SafeFetch32_impl,@function SafeFetch32_impl: movl 4(%esp),%ecx # load address from stack _SafeFetch32_fault: diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index 51399f03434f6..a98fd04ba6862 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -146,7 +146,7 @@ void ArchiveBuilder::SourceObjList::relocate(int i, ArchiveBuilder* builder) { } ArchiveBuilder::ArchiveBuilder() : - _current_dump_space(nullptr), + _current_dump_region(nullptr), _buffer_bottom(nullptr), _last_verified_top(nullptr), _num_dump_regions_used(0), @@ -341,10 +341,10 @@ address ArchiveBuilder::reserve_buffer() { _buffer_bottom = buffer_bottom; _last_verified_top = buffer_bottom; - _current_dump_space = &_rw_region; + _current_dump_region = &_rw_region; _num_dump_regions_used = 1; _other_region_used_bytes = 0; - _current_dump_space->init(&_shared_rs, &_shared_vs); + _current_dump_region->init(&_shared_rs, &_shared_vs); ArchivePtrMarker::initialize(&_ptrmap, &_shared_vs); @@ -560,21 +560,21 @@ ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref } } -void ArchiveBuilder::start_dump_space(DumpRegion* next) { +void ArchiveBuilder::start_dump_region(DumpRegion* next) { address bottom = _last_verified_top; - address top = (address)(current_dump_space()->top()); + address top = (address)(current_dump_region()->top()); _other_region_used_bytes += size_t(top - bottom); - current_dump_space()->pack(next); - _current_dump_space = next; + current_dump_region()->pack(next); + _current_dump_region = next; _num_dump_regions_used ++; - _last_verified_top = (address)(current_dump_space()->top()); + _last_verified_top = (address)(current_dump_region()->top()); } void ArchiveBuilder::verify_estimate_size(size_t estimate, const char* which) { address bottom = _last_verified_top; - address top = (address)(current_dump_space()->top()); + address top = (address)(current_dump_region()->top()); size_t used = size_t(top - bottom) + _other_region_used_bytes; int diff = int(estimate) - int(used); @@ -630,7 +630,7 @@ void ArchiveBuilder::dump_ro_metadata() { ResourceMark rm; log_info(cds)("Allocating RO objects ... "); - start_dump_space(&_ro_region); + start_dump_region(&_ro_region); make_shallow_copies(&_ro_region, &_ro_src_objs); #if INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/archiveBuilder.hpp b/src/hotspot/share/cds/archiveBuilder.hpp index dab369265b0b4..cbde5a7e02cbc 100644 --- a/src/hotspot/share/cds/archiveBuilder.hpp +++ b/src/hotspot/share/cds/archiveBuilder.hpp @@ -91,7 +91,7 @@ const int SharedSpaceObjectAlignment = KlassAlignmentInBytes; // class ArchiveBuilder : public StackObj { protected: - DumpRegion* _current_dump_space; + DumpRegion* _current_dump_region; address _buffer_bottom; // for writing the contents of rw/ro regions address _last_verified_top; int _num_dump_regions_used; @@ -114,7 +114,7 @@ class ArchiveBuilder : public StackObj { intx _buffer_to_requested_delta; - DumpRegion* current_dump_space() const { return _current_dump_space; } + DumpRegion* current_dump_region() const { return _current_dump_region; } public: enum FollowMode { @@ -278,17 +278,17 @@ class ArchiveBuilder : public StackObj { size_t estimate_archive_size(); - void start_dump_space(DumpRegion* next); + void start_dump_region(DumpRegion* next); void verify_estimate_size(size_t estimate, const char* which); public: address reserve_buffer(); - address buffer_bottom() const { return _buffer_bottom; } - address buffer_top() const { return (address)current_dump_space()->top(); } - address requested_static_archive_bottom() const { return _requested_static_archive_bottom; } - address mapped_static_archive_bottom() const { return _mapped_static_archive_bottom; } - intx buffer_to_requested_delta() const { return _buffer_to_requested_delta; } + address buffer_bottom() const { return _buffer_bottom; } + address buffer_top() const { return (address)current_dump_region()->top(); } + address requested_static_archive_bottom() const { return _requested_static_archive_bottom; } + address mapped_static_archive_bottom() const { return _mapped_static_archive_bottom; } + intx buffer_to_requested_delta() const { return _buffer_to_requested_delta; } bool is_in_buffer_space(address p) const { return (buffer_bottom() <= p && p < buffer_top()); diff --git a/src/hotspot/share/cds/archiveHeapWriter.cpp b/src/hotspot/share/cds/archiveHeapWriter.cpp index a86996d3b1fd8..d526a961b7f7b 100644 --- a/src/hotspot/share/cds/archiveHeapWriter.cpp +++ b/src/hotspot/share/cds/archiveHeapWriter.cpp @@ -67,8 +67,10 @@ ArchiveHeapWriter::BufferOffsetToSourceObjectTable* ArchiveHeapWriter::_buffer_offset_to_source_obj_table = nullptr; -typedef ResourceHashtable FillersTable; static FillersTable* _fillers; @@ -361,12 +363,12 @@ void ArchiveHeapWriter::maybe_fill_gc_region_gap(size_t required_byte_size) { array_length, fill_bytes, _buffer_used); HeapWord* filler = init_filler_array_at_buffer_top(array_length, fill_bytes); _buffer_used = filler_end; - _fillers->put((address)filler, fill_bytes); + _fillers->put(buffered_address_to_offset((address)filler), fill_bytes); } } size_t ArchiveHeapWriter::get_filler_size_at(address buffered_addr) { - size_t* p = _fillers->get(buffered_addr); + size_t* p = _fillers->get(buffered_address_to_offset(buffered_addr)); if (p != nullptr) { assert(*p > 0, "filler must be larger than zero bytes"); return *p; @@ -530,10 +532,8 @@ void ArchiveHeapWriter::update_header_for_requested_obj(oop requested_obj, oop s fake_oop->set_narrow_klass(nk); // We need to retain the identity_hash, because it may have been used by some hashtables - // in the shared heap. This also has the side effect of pre-initializing the - // identity_hash for all shared objects, so they are less likely to be written - // into during run time, increasing the potential of memory sharing. - if (src_obj != nullptr) { + // in the shared heap. + if (src_obj != nullptr && !src_obj->fast_no_hash_check()) { intptr_t src_hash = src_obj->identity_hash(); fake_oop->set_mark(markWord::prototype().copy_set_hash(src_hash)); assert(fake_oop->mark().is_unlocked(), "sanity"); diff --git a/src/hotspot/share/cds/archiveUtils.cpp b/src/hotspot/share/cds/archiveUtils.cpp index 5ba36960c55b1..8fd20e2026700 100644 --- a/src/hotspot/share/cds/archiveUtils.cpp +++ b/src/hotspot/share/cds/archiveUtils.cpp @@ -310,18 +310,11 @@ void WriteClosure::do_ptr(void** p) { if (ptr != nullptr && !ArchiveBuilder::current()->is_in_buffer_space(ptr)) { ptr = ArchiveBuilder::current()->get_buffered_addr(ptr); } - _dump_region->append_intptr_t((intptr_t)ptr, true); -} - -void WriteClosure::do_region(u_char* start, size_t size) { - assert((intptr_t)start % sizeof(intptr_t) == 0, "bad alignment"); - assert(size % sizeof(intptr_t) == 0, "bad size"); - do_tag((int)size); - while (size > 0) { - do_ptr((void**)start); - start += sizeof(intptr_t); - size -= sizeof(intptr_t); + // null pointers do not need to be converted to offsets + if (ptr != nullptr) { + ptr = (address)ArchiveBuilder::current()->buffer_to_offset(ptr); } + _dump_region->append_intptr_t((intptr_t)ptr, false); } void ReadClosure::do_ptr(void** p) { @@ -329,7 +322,7 @@ void ReadClosure::do_ptr(void** p) { intptr_t obj = nextPtr(); assert((intptr_t)obj >= 0 || (intptr_t)obj < -100, "hit tag while initializing ptrs."); - *p = (void*)obj; + *p = (void*)obj != nullptr ? (void*)(SharedBaseAddress + obj) : (void*)obj; } void ReadClosure::do_u4(u4* p) { @@ -355,17 +348,6 @@ void ReadClosure::do_tag(int tag) { FileMapInfo::assert_mark(tag == old_tag); } -void ReadClosure::do_region(u_char* start, size_t size) { - assert((intptr_t)start % sizeof(intptr_t) == 0, "bad alignment"); - assert(size % sizeof(intptr_t) == 0, "bad size"); - do_tag((int)size); - while (size > 0) { - *(intptr_t*)start = nextPtr(); - start += sizeof(intptr_t); - size -= sizeof(intptr_t); - } -} - void ArchiveUtils::log_to_classlist(BootstrapInfo* bootstrap_specifier, TRAPS) { if (ClassListWriter::is_enabled()) { if (SystemDictionaryShared::is_supported_invokedynamic(bootstrap_specifier)) { diff --git a/src/hotspot/share/cds/archiveUtils.hpp b/src/hotspot/share/cds/archiveUtils.hpp index efe5a468b93b4..32cef97886f06 100644 --- a/src/hotspot/share/cds/archiveUtils.hpp +++ b/src/hotspot/share/cds/archiveUtils.hpp @@ -215,7 +215,10 @@ class WriteClosure : public SerializeClosure { _dump_region->append_intptr_t((intptr_t)tag); } - void do_region(u_char* start, size_t size); + char* region_top() { + return _dump_region->top(); + } + bool reading() const { return false; } }; @@ -238,8 +241,8 @@ class ReadClosure : public SerializeClosure { void do_int(int* p); void do_bool(bool *p); void do_tag(int tag); - void do_region(u_char* start, size_t size); bool reading() const { return true; } + char* region_top() { return nullptr; } }; class ArchiveUtils { diff --git a/src/hotspot/share/cds/classListParser.cpp b/src/hotspot/share/cds/classListParser.cpp index b17da725deb3f..4e49cd3d881c8 100644 --- a/src/hotspot/share/cds/classListParser.cpp +++ b/src/hotspot/share/cds/classListParser.cpp @@ -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 @@ -50,30 +50,24 @@ #include "runtime/javaCalls.hpp" #include "utilities/defaultStream.hpp" #include "utilities/macros.hpp" +#include "utilities/utf8.hpp" volatile Thread* ClassListParser::_parsing_thread = nullptr; ClassListParser* ClassListParser::_instance = nullptr; -ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) : _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE) { +ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) : + _classlist_file(file), + _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE), + _file_input(do_open(file), /* need_close=*/true), + _input_stream(&_file_input) { log_info(cds)("Parsing %s%s", file, (parse_mode == _parse_lambda_forms_invokers_only) ? " (lambda form invokers only)" : ""); - _classlist_file = file; - _file = nullptr; - // Use os::open() because neither fopen() nor os::fopen() - // can handle long path name on Windows. - int fd = os::open(file, O_RDONLY, S_IREAD); - if (fd != -1) { - // Obtain a File* from the file descriptor so that fgets() - // can be used in parse_one_line() - _file = os::fdopen(fd, "r"); - } - if (_file == nullptr) { + if (!_file_input.is_open()) { char errmsg[JVM_MAXPATHLEN]; os::lasterror(errmsg, JVM_MAXPATHLEN); vm_exit_during_initialization("Loading classlist failed", errmsg); } - _line_no = 0; - _token = _line; + _token = _line = nullptr; _interfaces = new (mtClass) GrowableArray(10, mtClass); _indy_items = new (mtClass) GrowableArray(9, mtClass); _parse_mode = parse_mode; @@ -84,14 +78,24 @@ ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) : _id2k Atomic::store(&_parsing_thread, Thread::current()); } +FILE* ClassListParser::do_open(const char* file) { + // Use os::open() because neither fopen() nor os::fopen() + // can handle long path name on Windows. (See JDK-8216184) + int fd = os::open(file, O_RDONLY, S_IREAD); + FILE* fp = nullptr; + if (fd != -1) { + // Obtain a FILE* from the file descriptor so that _input_stream + // can be used in ClassListParser::parse() + fp = os::fdopen(fd, "r"); + } + return fp; +} + bool ClassListParser::is_parsing_thread() { return Atomic::load(&_parsing_thread) == Thread::current(); } ClassListParser::~ClassListParser() { - if (_file != nullptr) { - fclose(_file); - } Atomic::store(&_parsing_thread, (Thread*)nullptr); delete _indy_items; delete _interfaces; @@ -101,7 +105,15 @@ ClassListParser::~ClassListParser() { int ClassListParser::parse(TRAPS) { int class_count = 0; - while (parse_one_line()) { + for (; !_input_stream.done(); _input_stream.next()) { + _line = _input_stream.current_line(); + if (*_line == '#') { // comment + continue; + } + if (!parse_one_line()) { + break; + } + if (lambda_form_line()) { // The current line is "@lambda-form-invoker ...". It has been recorded in LambdaFormInvokers, // and will be processed later. @@ -112,6 +124,7 @@ int ClassListParser::parse(TRAPS) { continue; } + check_class_name(_class_name); TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name); if (_indy_items->length() > 0) { // The current line is "@lambda-proxy class_name". Load the proxy class. @@ -165,43 +178,26 @@ int ClassListParser::parse(TRAPS) { } bool ClassListParser::parse_one_line() { - for (;;) { - if (fgets(_line, sizeof(_line), _file) == nullptr) { - return false; - } - ++ _line_no; - _line_len = (int)strlen(_line); - if (_line_len > _max_allowed_line_len) { - error("input line too long (must be no longer than %d chars)", _max_allowed_line_len); - } - if (*_line == '#') { // comment - continue; - } - - { - int len = (int)strlen(_line); - int i; - // Replace \t\r\n\f with ' ' - for (i=0; i 0) { - if (_line[len-1] == ' ') { - _line[len-1] = '\0'; - len --; - } else { - break; - } + // Remove trailing newline/space + while (len > 0) { + if (_line[len-1] == ' ') { + _line[len-1] = '\0'; + len --; + } else { + break; } - _line_len = len; } - - // valid line - break; + _line_len = len; } _class_name = _line; @@ -286,7 +282,7 @@ int ClassListParser::split_at_tag_from_line() { _token = _line; char* ptr; if ((ptr = strchr(_line, ' ')) == nullptr) { - error("Too few items following the @ tag \"%s\" line #%d", _line, _line_no); + error("Too few items following the @ tag \"%s\" line #%zu", _line, lineno()); return 0; } *ptr++ = '\0'; @@ -304,7 +300,7 @@ bool ClassListParser::parse_at_tags() { if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) { split_tokens_by_whitespace(offset); if (_indy_items->length() < 2) { - error("Line with @ tag has too few items \"%s\" line #%d", _token, _line_no); + error("Line with @ tag has too few items \"%s\" line #%zu", _token, lineno()); return false; } // set the class name @@ -315,7 +311,7 @@ bool ClassListParser::parse_at_tags() { _lambda_form_line = true; return true; } else { - error("Invalid @ tag at the beginning of line \"%s\" line #%d", _token, _line_no); + error("Invalid @ tag at the beginning of line \"%s\" line #%zu", _token, lineno()); return false; } } @@ -423,8 +419,8 @@ void ClassListParser::error(const char* msg, ...) { } jio_fprintf(defaultStream::error_stream(), - "An error has occurred while processing class list file %s %d:%d.\n", - _classlist_file, _line_no, (error_index + 1)); + "An error has occurred while processing class list file %s %zu:%d.\n", + _classlist_file, lineno(), (error_index + 1)); jio_vfprintf(defaultStream::error_stream(), msg, ap); if (_line_len <= 0) { @@ -450,6 +446,25 @@ void ClassListParser::error(const char* msg, ...) { va_end(ap); } +void ClassListParser::check_class_name(const char* class_name) { + const char* err = nullptr; + size_t len = strlen(class_name); + if (len > (size_t)Symbol::max_length()) { + err = "class name too long"; + } else { + assert(Symbol::max_length() < INT_MAX && len < INT_MAX, "must be"); + if (!UTF8::is_legal_utf8((const unsigned char*)class_name, (int)len, /*version_leq_47*/false)) { + err = "class name is not valid UTF8"; + } + } + if (err != nullptr) { + jio_fprintf(defaultStream::error_stream(), + "An error has occurred while processing class list file %s:%zu %s\n", + _classlist_file, lineno(), err); + vm_exit_during_initialization("class list format error.", nullptr); + } +} + // This function is used for loading classes for customized class loaders // during archive dumping. InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) { diff --git a/src/hotspot/share/cds/classListParser.hpp b/src/hotspot/share/cds/classListParser.hpp index 74a2ff10515f8..a383e04d8e6fe 100644 --- a/src/hotspot/share/cds/classListParser.hpp +++ b/src/hotspot/share/cds/classListParser.hpp @@ -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 @@ -28,6 +28,7 @@ #include "utilities/exceptions.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/growableArray.hpp" +#include "utilities/istream.hpp" #include "utilities/resizeableResourceHash.hpp" #define LAMBDA_PROXY_TAG "@lambda-proxy" @@ -80,14 +81,6 @@ class ClassListParser : public StackObj { enum { _unspecified = -999, - - // Max number of bytes allowed per line in the classlist. - // Theoretically Java class names could be 65535 bytes in length. Also, an input line - // could have a very long path name up to JVM_MAXPATHLEN bytes in length. In reality, - // 4K bytes is more than enough. - _max_allowed_line_len = 4096, - _line_buf_extra = 10, // for detecting input too long - _line_buf_size = _max_allowed_line_len + _line_buf_extra }; // Use a small initial size in debug build to test resizing logic @@ -96,16 +89,14 @@ class ClassListParser : public StackObj { static volatile Thread* _parsing_thread; // the thread that created _instance static ClassListParser* _instance; // the singleton. const char* _classlist_file; - FILE* _file; ID2KlassTable _id2klass_table; - // The following field contains information from the *current* line being - // parsed. - char _line[_line_buf_size]; // The buffer that holds the current line. Some characters in + FileInput _file_input; + inputStream _input_stream; + char* _line; // The buffer that holds the current line. Some characters in // the buffer may be overwritten by '\0' during parsing. int _line_len; // Original length of the input line. - int _line_no; // Line number for current line being parsed const char* _class_name; GrowableArray* _indy_items; // items related to invoke dynamic for archiving lambda proxy classes int _id; @@ -132,6 +123,8 @@ class ClassListParser : public StackObj { bool parse_one_line(); Klass* load_current_class(Symbol* class_name_symbol, TRAPS); + size_t lineno() { return _input_stream.lineno(); } + FILE* do_open(const char* file); ClassListParser(const char* file, ParseMode _parse_mode); ~ClassListParser(); @@ -183,6 +176,7 @@ class ClassListParser : public StackObj { error("%s id %d is not yet loaded", which, id); } } + void check_class_name(const char* class_name); const char* current_class_name() { return _class_name; diff --git a/src/hotspot/share/cds/cppVtables.cpp b/src/hotspot/share/cds/cppVtables.cpp index c339ce9c0deaa..f17d94a82fdb5 100644 --- a/src/hotspot/share/cds/cppVtables.cpp +++ b/src/hotspot/share/cds/cppVtables.cpp @@ -213,23 +213,30 @@ void CppVtableCloner::init_orig_cpp_vtptr(int kind) { // the following holds true: // _index[ConstantPool_Kind]->cloned_vtable() == ((intptr_t**)cp)[0] // _index[InstanceKlass_Kind]->cloned_vtable() == ((intptr_t**)ik)[0] -CppVtableInfo** CppVtables::_index = nullptr; +static CppVtableInfo* _index[_num_cloned_vtable_kinds]; -char* CppVtables::dumptime_init(ArchiveBuilder* builder) { +// Vtables are all fixed offsets from ArchiveBuilder::current()->mapped_base() +// E.g. ConstantPool is at offset 0x58. We can archive these offsets in the +// RO region and use them to alculate their location at runtime without storing +// the pointers in the RW region +char* CppVtables::_vtables_serialized_base = nullptr; + +void CppVtables::dumptime_init(ArchiveBuilder* builder) { assert(CDSConfig::is_dumping_static_archive(), "cpp tables are only dumped into static archive"); - size_t vtptrs_bytes = _num_cloned_vtable_kinds * sizeof(CppVtableInfo*); - _index = (CppVtableInfo**)builder->rw_region()->allocate(vtptrs_bytes); CPP_VTABLE_TYPES_DO(ALLOCATE_AND_INITIALIZE_VTABLE); size_t cpp_tables_size = builder->rw_region()->top() - builder->rw_region()->base(); builder->alloc_stats()->record_cpp_vtables((int)cpp_tables_size); - - return (char*)_index; } void CppVtables::serialize(SerializeClosure* soc) { - soc->do_ptr(&_index); + if (!soc->reading()) { + _vtables_serialized_base = (char*)ArchiveBuilder::current()->buffer_top(); + } + for (int i = 0; i < _num_cloned_vtable_kinds; i++) { + soc->do_ptr(&_index[i]); + } if (soc->reading()) { CPP_VTABLE_TYPES_DO(INITIALIZE_VTABLE); } diff --git a/src/hotspot/share/cds/cppVtables.hpp b/src/hotspot/share/cds/cppVtables.hpp index 5318a9de2ba95..973502909ddf4 100644 --- a/src/hotspot/share/cds/cppVtables.hpp +++ b/src/hotspot/share/cds/cppVtables.hpp @@ -36,13 +36,14 @@ class CppVtableInfo; // Support for C++ vtables in CDS archive. class CppVtables : AllStatic { - static CppVtableInfo** _index; + static char* _vtables_serialized_base; public: - static char* dumptime_init(ArchiveBuilder* builder); + static void dumptime_init(ArchiveBuilder* builder); static void zero_archived_vtables(); static intptr_t* get_archived_vtable(MetaspaceObj::Type msotype, address obj); static void serialize(SerializeClosure* sc); static bool is_valid_shared_method(const Method* m) NOT_CDS_RETURN_(false); + static char* vtables_serialized_base() { return _vtables_serialized_base; } }; #endif // SHARE_CDS_CPPVTABLES_HPP diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index cd5dd88b09939..f255b337d148f 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -137,7 +137,7 @@ class DynamicArchiveBuilder : public ArchiveBuilder { // Note that these tables still point to the *original* objects, so // they would need to call DynamicArchive::original_to_target() to // get the correct addresses. - assert(current_dump_space() == ro_region(), "Must be RO space"); + assert(current_dump_region() == ro_region(), "Must be RO space"); SymbolTable::write_to_archive(symbols()); ArchiveBuilder::OtherROAllocMark mark; diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 202042e622e0b..b9f5d963c85ac 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -278,12 +278,6 @@ bool HeapShared::archive_object(oop obj) { } else { count_allocation(obj->size()); ArchiveHeapWriter::add_source_obj(obj); - - // The archived objects are discovered in a predictable order. Compute - // their identity_hash() as soon as we see them. This ensures that the - // the identity_hash in the object header will have a predictable value, - // making the archive reproducible. - obj->identity_hash(); CachedOopInfo info = make_cached_oop_info(obj); archived_object_cache()->put_when_absent(obj, info); archived_object_cache()->maybe_grow(); diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index c7d14f83d036a..93c5c1a1e3b00 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -511,7 +511,7 @@ void VM_PopulateDumpSharedSpace::doit() { builder.gather_source_objs(); builder.reserve_buffer(); - char* cloned_vtables = CppVtables::dumptime_init(&builder); + CppVtables::dumptime_init(&builder); builder.sort_metadata_objs(); builder.dump_rw_metadata(); @@ -542,7 +542,7 @@ void VM_PopulateDumpSharedSpace::doit() { FileMapInfo* mapinfo = new FileMapInfo(static_archive, true); mapinfo->populate_header(MetaspaceShared::core_region_alignment()); mapinfo->set_serialized_data(serialized_data); - mapinfo->set_cloned_vtables(cloned_vtables); + mapinfo->set_cloned_vtables(CppVtables::vtables_serialized_base()); mapinfo->open_for_write(); builder.write_archive(mapinfo, &_heap_info); diff --git a/src/hotspot/share/cds/serializeClosure.hpp b/src/hotspot/share/cds/serializeClosure.hpp index 275009286cb81..3d401407f37a1 100644 --- a/src/hotspot/share/cds/serializeClosure.hpp +++ b/src/hotspot/share/cds/serializeClosure.hpp @@ -48,8 +48,20 @@ class SerializeClosure : public StackObj { // Read/write the bool pointed to by p. virtual void do_bool(bool* p) = 0; - // Read/write the region specified. - virtual void do_region(u_char* start, size_t size) = 0; + // Iterate on the pointers from p[0] through p[num_pointers-1] + void do_ptrs(void** p, size_t size) { + assert((intptr_t)p % sizeof(intptr_t) == 0, "bad alignment"); + assert(size % sizeof(intptr_t) == 0, "bad size"); + do_tag((int)size); + while (size > 0) { + do_ptr(p); + p++; + size -= sizeof(intptr_t); + } + } + + // Address of the first element being written (write only) + virtual char* region_top() = 0; // Check/write the tag. If reading, then compare the tag against // the passed in value and fail is they don't match. This allows diff --git a/src/hotspot/share/classfile/vmSymbols.cpp b/src/hotspot/share/classfile/vmSymbols.cpp index 05cd4767e9a6d..172d074255b38 100644 --- a/src/hotspot/share/classfile/vmSymbols.cpp +++ b/src/hotspot/share/classfile/vmSymbols.cpp @@ -205,9 +205,9 @@ void vmSymbols::metaspace_pointers_do(MetaspaceClosure *closure) { } void vmSymbols::serialize(SerializeClosure* soc) { - soc->do_region((u_char*)&Symbol::_vm_symbols[FIRST_SID], + soc->do_ptrs((void**)&Symbol::_vm_symbols[FIRST_SID], (SID_LIMIT - FIRST_SID) * sizeof(Symbol::_vm_symbols[0])); - soc->do_region((u_char*)_type_signatures, sizeof(_type_signatures)); + soc->do_ptrs((void**)_type_signatures, sizeof(_type_signatures)); } #ifndef PRODUCT diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp index 69ff4bc78d639..d0f732edac486 100644 --- a/src/hotspot/share/code/relocInfo.cpp +++ b/src/hotspot/share/code/relocInfo.cpp @@ -277,30 +277,6 @@ DEFINE_COPY_INTO_AUX(Relocation) #undef DEFINE_COPY_INTO_AUX #undef DEFINE_COPY_INTO -//////// Methods for RelocationHolder - -RelocationHolder RelocationHolder::plus(int offset) const { - if (offset != 0) { - switch (type()) { - case relocInfo::none: - break; - case relocInfo::oop_type: - { - oop_Relocation* r = (oop_Relocation*)reloc(); - return oop_Relocation::spec(r->oop_index(), r->offset() + offset); - } - case relocInfo::metadata_type: - { - metadata_Relocation* r = (metadata_Relocation*)reloc(); - return metadata_Relocation::spec(r->metadata_index(), r->offset() + offset); - } - default: - ShouldNotReachHere(); - } - } - return (*this); -} - //////// Methods for flyweight Relocation types // some relocations can compute their own values @@ -402,24 +378,24 @@ void CallRelocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer void oop_Relocation::pack_data_to(CodeSection* dest) { short* p = (short*) dest->locs_end(); - p = pack_2_ints_to(p, _oop_index, _offset); + p = pack_1_int_to(p, _oop_index); dest->set_locs_end((relocInfo*) p); } void oop_Relocation::unpack_data() { - unpack_2_ints(_oop_index, _offset); + _oop_index = unpack_1_int(); } void metadata_Relocation::pack_data_to(CodeSection* dest) { short* p = (short*) dest->locs_end(); - p = pack_2_ints_to(p, _metadata_index, _offset); + p = pack_1_int_to(p, _metadata_index); dest->set_locs_end((relocInfo*) p); } void metadata_Relocation::unpack_data() { - unpack_2_ints(_metadata_index, _offset); + _metadata_index = unpack_1_int(); } @@ -855,8 +831,8 @@ void RelocIterator::print_current() { raw_oop = *oop_addr; oop_value = r->oop_value(); } - tty->print(" | [oop_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]", - p2i(oop_addr), p2i(raw_oop), r->offset()); + tty->print(" | [oop_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT "]", + p2i(oop_addr), p2i(raw_oop)); // Do not print the oop by default--we want this routine to // work even during GC or other inconvenient times. if (WizardMode && oop_value != nullptr) { @@ -878,8 +854,8 @@ void RelocIterator::print_current() { raw_metadata = *metadata_addr; metadata_value = r->metadata_value(); } - tty->print(" | [metadata_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT " offset=%d]", - p2i(metadata_addr), p2i(raw_metadata), r->offset()); + tty->print(" | [metadata_addr=" INTPTR_FORMAT " *=" INTPTR_FORMAT "]", + p2i(metadata_addr), p2i(raw_metadata)); if (metadata_value != nullptr) { tty->print("metadata_value=" INTPTR_FORMAT ": ", p2i(metadata_value)); metadata_value->print_value_on(tty); diff --git a/src/hotspot/share/code/relocInfo.hpp b/src/hotspot/share/code/relocInfo.hpp index 9f1db9f4684e3..6d0907d97dedc 100644 --- a/src/hotspot/share/code/relocInfo.hpp +++ b/src/hotspot/share/code/relocInfo.hpp @@ -129,12 +129,7 @@ class nmethod; // Value: an oop, or else the address (handle) of an oop // Instruction types: memory (load), set (load address) // Data: [] an oop stored in 4 bytes of instruction -// [n] n is the index of an oop in the CodeBlob's oop pool -// [[N]n l] and l is a byte offset to be applied to the oop -// [Nn Ll] both index and offset may be 32 bits if necessary -// Here is a special hack, used only by the old compiler: -// [[N]n 00] the value is the __address__ of the nth oop in the pool -// (Note that the offset allows optimal references to class variables.) +// [[N]n] the index of an oop in the CodeBlob's oop pool // // relocInfo::internal_word_type -- an address within the same CodeBlob // relocInfo::section_word_type -- same, but can refer to another section @@ -515,9 +510,6 @@ class RelocationHolder { Relocation* reloc() const { return (Relocation*)_relocbuf; } inline relocInfo::relocType type() const; - // Add a constant offset to a relocation. Helper for class Address. - RelocationHolder plus(int offset) const; - // Return a holder containing a relocation of type Reloc, constructed using args. template static RelocationHolder construct(const Args&... args) { @@ -788,8 +780,8 @@ class Relocation { void const_set_data_value (address x); void const_verify_data_value (address x); // platform-dependent utilities for decoding and patching instructions - void pd_set_data_value (address x, intptr_t off, bool verify_only = false); // a set or mem-ref - void pd_verify_data_value (address x, intptr_t off) { pd_set_data_value(x, off, true); } + void pd_set_data_value (address x, bool verify_only = false); // a set or mem-ref + void pd_verify_data_value (address x) { pd_set_data_value(x, true); } address pd_call_destination (address orig_addr = nullptr); void pd_set_call_destination (address x); @@ -895,41 +887,28 @@ relocInfo::relocType RelocationHolder::type() const { // A DataRelocation always points at a memory or load-constant instruction.. // It is absolute on most machines, and the constant is split on RISCs. // The specific subtypes are oop, external_word, and internal_word. -// By convention, the "value" does not include a separately reckoned "offset". class DataRelocation : public Relocation { public: DataRelocation(relocInfo::relocType type) : Relocation(type) {} - bool is_data() override { return true; } + bool is_data() override { return true; } - // both target and offset must be computed somehow from relocation data - virtual int offset() { return 0; } - address value() override = 0; - void set_value(address x) override { set_value(x, offset()); } - void set_value(address x, intptr_t o) { - if (addr_in_const()) + // target must be computed somehow from relocation data + address value() override = 0; + void set_value(address x) override { + if (addr_in_const()) { const_set_data_value(x); - else - pd_set_data_value(x, o); + } else { + pd_set_data_value(x); + } } - void verify_value(address x) { - if (addr_in_const()) + void verify_value(address x) { + if (addr_in_const()) { const_verify_data_value(x); - else - pd_verify_data_value(x, offset()); + } else { + pd_verify_data_value(x); + } } - - // The "o" (displacement) argument is relevant only to split relocations - // on RISC machines. In some CPUs (SPARC), the set-hi and set-lo ins'ns - // can encode more than 32 bits between them. This allows compilers to - // share set-hi instructions between addresses that differ by a small - // offset (e.g., different static variables in the same class). - // On such machines, the "x" argument to set_value on all set-lo - // instructions must be the same as the "x" argument for the - // corresponding set-hi instructions. The "o" arguments for the - // set-hi instructions are ignored, and must not affect the high-half - // immediate constant. The "o" arguments for the set-lo instructions are - // added into the low-half immediate constant, and must not overflow it. }; class post_call_nop_Relocation : public Relocation { @@ -976,40 +955,36 @@ class CallRelocation : public Relocation { class oop_Relocation : public DataRelocation { public: - // encode in one of these formats: [] [n] [n l] [Nn l] [Nn Ll] - // an oop in the CodeBlob's oop pool - static RelocationHolder spec(int oop_index, int offset = 0) { + // an oop in the CodeBlob's oop pool; encoded as [n] or [Nn] + static RelocationHolder spec(int oop_index) { assert(oop_index > 0, "must be a pool-resident oop"); - return RelocationHolder::construct(oop_index, offset); + return RelocationHolder::construct(oop_index); } - // an oop in the instruction stream + // an oop in the instruction stream; encoded as [] static RelocationHolder spec_for_immediate() { // If no immediate oops are generated, we can skip some walks over nmethods. // Assert that they don't get generated accidentally! assert(relocInfo::mustIterateImmediateOopsInCode(), "Must return true so we will search for oops as roots etc. in the code."); const int oop_index = 0; - const int offset = 0; // if you want an offset, use the oop pool - return RelocationHolder::construct(oop_index, offset); + return RelocationHolder::construct(oop_index); } void copy_into(RelocationHolder& holder) const override; private: jint _oop_index; // if > 0, index into CodeBlob::oop_at - jint _offset; // byte offset to apply to the oop itself - oop_Relocation(int oop_index, int offset) - : DataRelocation(relocInfo::oop_type), _oop_index(oop_index), _offset(offset) { } + oop_Relocation(int oop_index) + : DataRelocation(relocInfo::oop_type), _oop_index(oop_index) { } friend class RelocationHolder; oop_Relocation() : DataRelocation(relocInfo::oop_type) {} public: int oop_index() { return _oop_index; } - int offset() override { return _offset; } - // data is packed in "2_ints" format: [i o] or [Ii Oo] + // oop_index is packed in "1_int" format: [n] or [Nn] void pack_data_to(CodeSection* dest) override; void unpack_data() override; @@ -1031,27 +1006,24 @@ class oop_Relocation : public DataRelocation { class metadata_Relocation : public DataRelocation { public: - // encode in one of these formats: [] [n] [n l] [Nn l] [Nn Ll] - // an metadata in the CodeBlob's metadata pool - static RelocationHolder spec(int metadata_index, int offset = 0) { + // an metadata in the CodeBlob's metadata pool; encoded as [n] or [Nn] + static RelocationHolder spec(int metadata_index) { assert(metadata_index > 0, "must be a pool-resident metadata"); - return RelocationHolder::construct(metadata_index, offset); + return RelocationHolder::construct(metadata_index); } - // an metadata in the instruction stream + // an metadata in the instruction stream; encoded as [] static RelocationHolder spec_for_immediate() { const int metadata_index = 0; - const int offset = 0; // if you want an offset, use the metadata pool - return RelocationHolder::construct(metadata_index, offset); + return RelocationHolder::construct(metadata_index); } void copy_into(RelocationHolder& holder) const override; private: jint _metadata_index; // if > 0, index into nmethod::metadata_at - jint _offset; // byte offset to apply to the metadata itself - metadata_Relocation(int metadata_index, int offset) - : DataRelocation(relocInfo::metadata_type), _metadata_index(metadata_index), _offset(offset) { } + metadata_Relocation(int metadata_index) + : DataRelocation(relocInfo::metadata_type), _metadata_index(metadata_index) { } friend class RelocationHolder; metadata_Relocation() : DataRelocation(relocInfo::metadata_type) { } @@ -1063,9 +1035,8 @@ class metadata_Relocation : public DataRelocation { public: int metadata_index() { return _metadata_index; } - int offset() override { return _offset; } - // data is packed in "2_ints" format: [i o] or [Ii Oo] + // metadata_index is packed in "1_int" format: [n] or [Nn] void pack_data_to(CodeSection* dest) override; void unpack_data() override; diff --git a/src/hotspot/share/compiler/compilationMemoryStatistic.cpp b/src/hotspot/share/compiler/compilationMemoryStatistic.cpp index 585d55febb8e7..196a11fd06537 100644 --- a/src/hotspot/share/compiler/compilationMemoryStatistic.cpp +++ b/src/hotspot/share/compiler/compilationMemoryStatistic.cpp @@ -181,10 +181,16 @@ class MemStatEntry : public CHeapObj { int _num_recomp; // Compiling thread. Only for diagnostic purposes. Thread may not be alive anymore. const Thread* _thread; + // active limit for this compilation, if any + size_t _limit; + // peak usage, bytes, over all arenas size_t _total; + // usage in node arena when total peaked size_t _na_at_peak; + // usage in resource area when total peaked size_t _ra_at_peak; + // number of nodes (c2 only) when total peaked unsigned _live_nodes_at_peak; const char* _result; @@ -192,7 +198,7 @@ class MemStatEntry : public CHeapObj { MemStatEntry(FullMethodName method) : _method(method), _comptype(compiler_c1), - _time(0), _num_recomp(0), _thread(nullptr), + _time(0), _num_recomp(0), _thread(nullptr), _limit(0), _total(0), _na_at_peak(0), _ra_at_peak(0), _live_nodes_at_peak(0), _result(nullptr) { } @@ -200,6 +206,7 @@ class MemStatEntry : public CHeapObj { void set_comptype(CompilerType comptype) { _comptype = comptype; } void set_current_time() { _time = os::elapsedTime(); } void set_current_thread() { _thread = Thread::current(); } + void set_limit(size_t limit) { _limit = limit; } void inc_recompilation() { _num_recomp++; } void set_total(size_t n) { _total = n; } @@ -218,6 +225,7 @@ class MemStatEntry : public CHeapObj { st->print_cr(" RA : ...how much in resource areas"); st->print_cr(" result : Result: 'ok' finished successfully, 'oom' hit memory limit, 'err' compilation failed"); st->print_cr(" #nodes : ...how many nodes (c2 only)"); + st->print_cr(" limit : memory limit, if set"); st->print_cr(" time : time of last compilation (sec)"); st->print_cr(" type : compiler type"); st->print_cr(" #rc : how often recompiled"); @@ -225,7 +233,7 @@ class MemStatEntry : public CHeapObj { } static void print_header(outputStream* st) { - st->print_cr("total NA RA result #nodes time type #rc thread method"); + st->print_cr("total NA RA result #nodes limit time type #rc thread method"); } void print_on(outputStream* st, bool human_readable) const { @@ -260,7 +268,19 @@ class MemStatEntry : public CHeapObj { col += 8; st->fill_to(col); // Number of Nodes when memory peaked - st->print("%u ", _live_nodes_at_peak); + if (_live_nodes_at_peak > 0) { + st->print("%u ", _live_nodes_at_peak); + } else { + st->print("-"); + } + col += 8; st->fill_to(col); + + // Limit + if (_limit > 0) { + st->print(PROPERFMT " ", PROPERFMTARGS(_limit)); + } else { + st->print("-"); + } col += 8; st->fill_to(col); // TimeStamp @@ -322,7 +342,7 @@ class MemStatTable : void add(const FullMethodName& fmn, CompilerType comptype, size_t total, size_t na_at_peak, size_t ra_at_peak, - unsigned live_nodes_at_peak, const char* result) { + unsigned live_nodes_at_peak, size_t limit, const char* result) { assert_lock_strong(NMTCompilationCostHistory_lock); MemStatTableKey key(fmn, comptype); MemStatEntry** pe = get(key); @@ -343,6 +363,7 @@ class MemStatTable : e->set_na_at_peak(na_at_peak); e->set_ra_at_peak(ra_at_peak); e->set_live_nodes_at_peak(live_nodes_at_peak); + e->set_limit(limit); e->set_result(result); } @@ -430,6 +451,7 @@ void CompilationMemoryStatistic::on_end_compilation() { arena_stat->na_at_peak(), arena_stat->ra_at_peak(), arena_stat->live_nodes_at_peak(), + arena_stat->limit(), result); } if (print) { @@ -521,8 +543,8 @@ void CompilationMemoryStatistic::on_arena_change(ssize_t diff, const Arena* aren if (ct != compiler_none && name[0] != '\0') { ss.print("%s %s: ", compilertype2name(ct), name); } - ss.print("Hit MemLimit %s (limit: %zu now: %zu)", - (hit_limit_before ? "again" : ""), + ss.print("Hit MemLimit %s(limit: %zu now: %zu)", + (hit_limit_before ? "again " : ""), arena_stat->limit(), arena_stat->peak_since_start()); } diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 0935ea6a8e132..ddd5b2f0eb7e9 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -38,6 +38,7 @@ #include "compiler/compilerEvent.hpp" #include "compiler/compilerOracle.hpp" #include "compiler/directivesParser.hpp" +#include "gc/shared/memAllocator.hpp" #include "interpreter/linkResolver.hpp" #include "jvm.h" #include "jfr/jfrEvents.hpp" @@ -1396,6 +1397,7 @@ nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, assert(!HAS_PENDING_EXCEPTION, "No exception should be present"); // some prerequisites that are compiler specific if (comp->is_c2() || comp->is_jvmci()) { + InternalOOMEMark iom(THREAD); method->constants()->resolve_string_constants(CHECK_AND_CLEAR_NONASYNC_NULL); // Resolve all classes seen in the signature of the method // we are compiling. diff --git a/src/hotspot/share/compiler/compilerOracle.cpp b/src/hotspot/share/compiler/compilerOracle.cpp index ea09e3ebb7f75..a81d60c9fc422 100644 --- a/src/hotspot/share/compiler/compilerOracle.cpp +++ b/src/hotspot/share/compiler/compilerOracle.cpp @@ -40,8 +40,26 @@ #include "runtime/handles.inline.hpp" #include "runtime/jniHandles.hpp" #include "runtime/os.hpp" +#include "utilities/istream.hpp" #include "utilities/parseInteger.hpp" +// Default compile commands, if defined, are parsed before any of the +// explicitly defined compile commands. Thus, explicitly defined compile +// commands take precedence over default compile commands. The effect is +// as if the default compile commands had been specified at the start of +// the command line. +static const char* const default_compile_commands[] = { +#ifdef ASSERT + // In debug builds, impose a (generous) per-compilation memory limit + // to catch pathological compilations during testing. The suboption + // "crash" will cause the JVM to assert. + // + // Note: to disable the default limit at the command line, + // set a limit of 0 (e.g. -XX:CompileCommand=MemLimit,*.*,0). + "MemLimit,*.*,1G~crash", +#endif + nullptr }; + static const char* optiontype_names[] = { #define enum_of_types(type, name) name, OPTION_TYPES(enum_of_types) @@ -905,6 +923,14 @@ class LineCopy : StackObj { } }; +bool CompilerOracle::parse_from_line_quietly(char* line) { + const bool quiet0 = _quiet; + _quiet = true; + const bool result = parse_from_line(line); + _quiet = quiet0; + return result; +} + bool CompilerOracle::parse_from_line(char* line) { if ((line[0] == '\0') || (line[0] == '#')) { return true; @@ -1056,57 +1082,39 @@ bool CompilerOracle::parse_from_file() { return true; } - char token[1024]; - int pos = 0; - int c = getc(stream); - bool success = true; - while(c != EOF && pos < (int)(sizeof(token)-1)) { - if (c == '\n') { - token[pos++] = '\0'; - if (!parse_from_line(token)) { - success = false; - } - pos = 0; - } else { - token[pos++] = c; - } - c = getc(stream); - } - token[pos++] = '\0'; - if (!parse_from_line(token)) { - success = false; - } - fclose(stream); - return success; + FileInput input(stream, /*need_close=*/ true); + return parse_from_input(&input, parse_from_line); } -bool CompilerOracle::parse_from_string(const char* str, bool (*parse_line)(char*)) { - char token[1024]; - int pos = 0; - const char* sp = str; - int c = *sp++; +bool CompilerOracle::parse_from_input(inputStream::Input* input, + CompilerOracle:: + parse_from_line_fn_t* parse_from_line) { bool success = true; - while (c != '\0' && pos < (int)(sizeof(token)-1)) { - if (c == '\n') { - token[pos++] = '\0'; - if (!parse_line(token)) { - success = false; - } - pos = 0; - } else { - token[pos++] = c; + for (inputStream in(input); !in.done(); in.next()) { + if (!parse_from_line(in.current_line())) { + success = false; } - c = *sp++; - } - token[pos++] = '\0'; - if (!parse_line(token)) { - success = false; } return success; } +bool CompilerOracle::parse_from_string(const char* str, + CompilerOracle:: + parse_from_line_fn_t* parse_from_line) { + MemoryInput input(str, strlen(str)); + return parse_from_input(&input, parse_from_line); +} + bool compilerOracle_init() { bool success = true; + // Register default compile commands first - any commands specified via CompileCommand will + // supersede these default commands. + for (int i = 0; default_compile_commands[i] != nullptr; i ++) { + char* s = os::strdup(default_compile_commands[i]); + success = CompilerOracle::parse_from_line_quietly(s); + os::free(s); + assert(success, "default compile command \"%s\" failed to parse", default_compile_commands[i]); + } if (!CompilerOracle::parse_from_string(CompileCommand, CompilerOracle::parse_from_line)) { success = false; } diff --git a/src/hotspot/share/compiler/compilerOracle.hpp b/src/hotspot/share/compiler/compilerOracle.hpp index 43a30b30facec..1a85e0629f93e 100644 --- a/src/hotspot/share/compiler/compilerOracle.hpp +++ b/src/hotspot/share/compiler/compilerOracle.hpp @@ -27,6 +27,7 @@ #include "memory/allStatic.hpp" #include "oops/oopsHierarchy.hpp" +#include "utilities/istream.hpp" class methodHandle; @@ -120,11 +121,18 @@ enum class MemStatAction { }; class CompilerOracle : AllStatic { + public: + typedef bool parse_from_line_fn_t(char*); + private: static bool _quiet; static void print_parse_error(char* error_msg, char* original_line); static void print_command(CompileCommandEnum option, const char* name, enum OptionType type); + // The core parser. + static bool parse_from_input(inputStream::Input* input, + parse_from_line_fn_t* parse_from_line); + public: // True if the command file has been specified or is implicit static bool has_command_file(); @@ -177,8 +185,10 @@ class CompilerOracle : AllStatic { static bool option_matches_type(CompileCommandEnum option, T& value); // Reads from string instead of file - static bool parse_from_string(const char* option_string, bool (*parser)(char*)); + static bool parse_from_string(const char* option_string, + parse_from_line_fn_t* parser); static bool parse_from_line(char* line); + static bool parse_from_line_quietly(char* line); static bool parse_compile_only(char* line); // Fast check if there is any option set that compile control needs to know about diff --git a/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp b/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp index dd38d33b5d39e..531559545d797 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp +++ b/src/hotspot/share/gc/g1/g1CollectionSetCandidates.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, 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 @@ -26,7 +26,6 @@ #define SHARE_GC_G1_G1COLLECTIONSETCANDIDATES_HPP #include "gc/g1/g1CollectionSetCandidates.hpp" -#include "gc/g1/g1_globals.hpp" #include "gc/shared/gc_globals.hpp" #include "gc/shared/workerThread.hpp" #include "memory/allocation.hpp" diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp index a176b847eab69..ba309c97ca5a3 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp @@ -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 @@ -30,7 +30,7 @@ #include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp" #include "gc/g1/g1HeapRegion.inline.hpp" #include "gc/g1/g1HeapRegionManager.inline.hpp" -#include "gc/g1/g1_globals.hpp" +#include "gc/shared/gc_globals.hpp" #include "gc/shared/suspendibleThreadSet.hpp" #include "gc/shared/workerThread.hpp" #include "logging/log.hpp" diff --git a/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp b/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp index 337acfe24058d..59a1afe6f3408 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, 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 @@ -29,9 +29,8 @@ #include "gc/g1/g1HeapRegionRemSet.hpp" #include "gc/g1/g1MonotonicArenaFreeMemoryTask.hpp" #include "gc/g1/g1MonotonicArenaFreePool.hpp" -#include "gc/g1/g1_globals.hpp" -#include "gc/shared/gc_globals.hpp" #include "gc/shared/gcTraceTime.inline.hpp" +#include "gc/shared/gc_globals.hpp" #include "gc/shared/suspendibleThreadSet.hpp" #include "runtime/os.hpp" diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp index 72f7a0b84e7d9..3f8f8e22a9965 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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,9 +29,9 @@ #include "gc/g1/g1RedirtyCardsQueue.hpp" #include "gc/g1/g1OopClosures.hpp" #include "gc/g1/g1YoungGCAllocationFailureInjector.hpp" -#include "gc/g1/g1_globals.hpp" #include "gc/shared/ageTable.hpp" #include "gc/shared/copyFailedInfo.hpp" +#include "gc/shared/gc_globals.hpp" #include "gc/shared/partialArrayTaskStepper.hpp" #include "gc/shared/preservedMarks.hpp" #include "gc/shared/stringdedup/stringDedup.hpp" diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp index a47fd379a7038..63f48a15e8d4c 100644 --- a/src/hotspot/share/gc/g1/g1RemSet.cpp +++ b/src/hotspot/share/gc/g1/g1RemSet.cpp @@ -42,10 +42,10 @@ #include "gc/g1/g1Policy.hpp" #include "gc/g1/g1RootClosures.hpp" #include "gc/g1/g1RemSet.hpp" -#include "gc/g1/g1_globals.hpp" #include "gc/shared/bufferNode.hpp" #include "gc/shared/bufferNodeList.hpp" #include "gc/shared/gcTraceTime.inline.hpp" +#include "gc/shared/gc_globals.hpp" #include "jfr/jfrEvents.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index bf1c8b738f8a0..720cf3a362916 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -49,10 +49,10 @@ #include "gc/g1/g1YoungGCAllocationFailureInjector.hpp" #include "gc/g1/g1YoungGCPostEvacuateTasks.hpp" #include "gc/g1/g1YoungGCPreEvacuateTasks.hpp" -#include "gc/g1/g1_globals.hpp" #include "gc/shared/concurrentGCBreakpoints.hpp" #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/gcTimer.hpp" +#include "gc/shared/gc_globals.hpp" #include "gc/shared/preservedMarks.hpp" #include "gc/shared/referenceProcessor.hpp" #include "gc/shared/weakProcessor.inline.hpp" diff --git a/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.cpp b/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.cpp index 60b7e0872f2ef..9bbb6bddb316a 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.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 @@ -26,7 +26,7 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1YoungGCAllocationFailureInjector.inline.hpp" -#include "gc/g1/g1_globals.hpp" +#include "gc/shared/gc_globals.hpp" #if ALLOCATION_FAILURE_INJECTOR diff --git a/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.hpp b/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.hpp index fb7e8cd3ad3bb..44677fe4710bb 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.hpp +++ b/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.hpp @@ -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 @@ -25,7 +25,7 @@ #ifndef SHARE_GC_G1_G1YOUNGGCALLOCATIONFAILUREINJECTOR_HPP #define SHARE_GC_G1_G1YOUNGGCALLOCATIONFAILUREINJECTOR_HPP -#include "gc/g1/g1_globals.hpp" +#include "gc/shared/gc_globals.hpp" #include "memory/allStatic.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.inline.hpp b/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.inline.hpp index 7c71eb14d52bc..cfa047ea0ce28 100644 --- a/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.inline.hpp +++ b/src/hotspot/share/gc/g1/g1YoungGCAllocationFailureInjector.inline.hpp @@ -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 @@ -27,8 +27,8 @@ #include "gc/g1/g1YoungGCAllocationFailureInjector.hpp" -#include "gc/g1/g1_globals.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/shared/gc_globals.hpp" #if ALLOCATION_FAILURE_INJECTOR diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp index 2a39ce7b4700d..b4ea195518201 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp @@ -79,10 +79,7 @@ void MutableNUMASpace::mangle_unused_area() { // This method should do nothing. // It can be called on a numa space during a full compaction. } -void MutableNUMASpace::mangle_unused_area_complete() { - // This method should do nothing. - // It can be called on a numa space during a full compaction. -} + void MutableNUMASpace::mangle_region(MemRegion mr) { // This method should do nothing because numa spaces are not mangled. } diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp index 18271fabd050d..9a6cf420c0d24 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp @@ -173,7 +173,7 @@ class MutableNUMASpace : public MutableSpace { virtual void clear(bool mangle_space); virtual void mangle_unused_area() PRODUCT_RETURN; - virtual void mangle_unused_area_complete() PRODUCT_RETURN; + virtual void mangle_region(MemRegion mr) PRODUCT_RETURN; virtual void check_mangled_unused_area(HeapWord* limit) PRODUCT_RETURN; virtual void check_mangled_unused_area_complete() PRODUCT_RETURN; diff --git a/src/hotspot/share/gc/parallel/mutableSpace.cpp b/src/hotspot/share/gc/parallel/mutableSpace.cpp index 4641b4ce5c611..7d881f73dbf3e 100644 --- a/src/hotspot/share/gc/parallel/mutableSpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableSpace.cpp @@ -167,10 +167,6 @@ void MutableSpace::mangle_unused_area() { mangler()->mangle_unused_area(); } -void MutableSpace::mangle_unused_area_complete() { - mangler()->mangle_unused_area_complete(); -} - void MutableSpace::mangle_region(MemRegion mr) { SpaceMangler::mangle_region(mr); } diff --git a/src/hotspot/share/gc/parallel/mutableSpace.hpp b/src/hotspot/share/gc/parallel/mutableSpace.hpp index b77c1d80332e7..1cf0d306dc02e 100644 --- a/src/hotspot/share/gc/parallel/mutableSpace.hpp +++ b/src/hotspot/share/gc/parallel/mutableSpace.hpp @@ -109,7 +109,7 @@ class MutableSpace: public CHeapObj { // Methods used in mangling. See descriptions under SpaceMangler. virtual void mangle_unused_area() PRODUCT_RETURN; - virtual void mangle_unused_area_complete() PRODUCT_RETURN; + virtual void check_mangled_unused_area(HeapWord* limit) PRODUCT_RETURN; virtual void check_mangled_unused_area_complete() PRODUCT_RETURN; virtual void set_top_for_allocations(HeapWord* v) PRODUCT_RETURN; diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 43c8be36148cf..ff65a6dd45033 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -226,6 +226,7 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs, size_t max_size, const char* policy) : Generation(rs, initial_size), + _promotion_failed(false), _preserved_marks_set(false /* in_c_heap */), _promo_failure_drain_in_progress(false), _should_allocate_from_space(false), diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 6fbe6d708972b..b413e3dfb438c 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -91,9 +91,7 @@ class CollectedHeap : public CHeapObj { friend class VMStructs; friend class JVMCIVMStructs; friend class IsSTWGCActiveMark; // Block structured external access to _is_stw_gc_active - friend class DisableIsSTWGCActiveMark; // Disable current IsSTWGCActiveMark friend class MemAllocator; - friend class ParallelObjectIterator; private: GCHeapLog* _gc_heap_log; @@ -401,12 +399,10 @@ class CollectedHeap : public CHeapObj { // Iterate over all objects, calling "cl.do_object" on each. virtual void object_iterate(ObjectClosure* cl) = 0; - protected: virtual ParallelObjectIteratorImpl* parallel_object_iterator(uint thread_num) { return nullptr; } - public: // Keep alive an object that was loaded with AS_NO_KEEPALIVE. virtual void keep_alive(oop obj) {} diff --git a/src/hotspot/share/gc/shared/isGCActiveMark.cpp b/src/hotspot/share/gc/shared/isGCActiveMark.cpp index add6acaa01a22..7c400f2acc082 100644 --- a/src/hotspot/share/gc/shared/isGCActiveMark.cpp +++ b/src/hotspot/share/gc/shared/isGCActiveMark.cpp @@ -42,15 +42,3 @@ IsSTWGCActiveMark::~IsSTWGCActiveMark() { assert(heap->is_stw_gc_active(), "Sanity"); heap->_is_stw_gc_active = false; } - -DisableIsSTWGCActiveMark::DisableIsSTWGCActiveMark() { - CollectedHeap* heap = Universe::heap(); - assert(heap->is_stw_gc_active(), "Not reentrant"); - heap->_is_stw_gc_active = false; -} - -DisableIsSTWGCActiveMark::~DisableIsSTWGCActiveMark() { - CollectedHeap* heap = Universe::heap(); - assert(!heap->is_stw_gc_active(), "Sanity"); - heap->_is_stw_gc_active = true; -} diff --git a/src/hotspot/share/gc/shared/isGCActiveMark.hpp b/src/hotspot/share/gc/shared/isGCActiveMark.hpp index c65c7ebe56a68..e523c600ace5c 100644 --- a/src/hotspot/share/gc/shared/isGCActiveMark.hpp +++ b/src/hotspot/share/gc/shared/isGCActiveMark.hpp @@ -36,10 +36,4 @@ class IsSTWGCActiveMark : public StackObj { ~IsSTWGCActiveMark(); }; -class DisableIsSTWGCActiveMark : public StackObj { - public: - DisableIsSTWGCActiveMark(); - ~DisableIsSTWGCActiveMark(); -}; - #endif // SHARE_GC_SHARED_ISGCACTIVEMARK_HPP diff --git a/src/hotspot/share/gc/shared/memAllocator.cpp b/src/hotspot/share/gc/shared/memAllocator.cpp index ddd33d8f43adb..156b55c104621 100644 --- a/src/hotspot/share/gc/shared/memAllocator.cpp +++ b/src/hotspot/share/gc/shared/memAllocator.cpp @@ -123,21 +123,21 @@ bool MemAllocator::Allocation::check_out_of_memory() { } const char* message = _overhead_limit_exceeded ? "GC overhead limit exceeded" : "Java heap space"; - if (!_thread->in_retryable_allocation()) { + if (!_thread->is_in_internal_oome_mark()) { // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support report_java_out_of_memory(message); - if (JvmtiExport::should_post_resource_exhausted()) { JvmtiExport::post_resource_exhausted( JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP, message); } + oop exception = _overhead_limit_exceeded ? Universe::out_of_memory_error_gc_overhead_limit() : Universe::out_of_memory_error_java_heap(); THROW_OOP_(exception, true); } else { - THROW_OOP_(Universe::out_of_memory_error_retry(), true); + THROW_OOP_(Universe::out_of_memory_error_java_heap_without_backtrace(), true); } } diff --git a/src/hotspot/share/gc/shared/memAllocator.hpp b/src/hotspot/share/gc/shared/memAllocator.hpp index 5d3f892ca14fd..f299dd633e510 100644 --- a/src/hotspot/share/gc/shared/memAllocator.hpp +++ b/src/hotspot/share/gc/shared/memAllocator.hpp @@ -114,4 +114,37 @@ class ClassAllocator: public MemAllocator { virtual oop initialize(HeapWord* mem) const; }; +// Manages a scope where a failed heap allocation results in +// suppression of JVMTI "resource exhausted" events and +// throwing a shared, backtrace-less OOME instance. +// Used for OOMEs that will not be propagated to user code. +class InternalOOMEMark: public StackObj { + private: + bool _outer; + JavaThread* _thread; + + public: + explicit InternalOOMEMark(JavaThread* thread) { + if (thread != nullptr) { + _outer = thread->is_in_internal_oome_mark(); + thread->set_is_in_internal_oome_mark(true); + _thread = thread; + } else { + _outer = false; + _thread = nullptr; + } + } + + ~InternalOOMEMark() { + if (_thread != nullptr) { + // Check that only InternalOOMEMark sets + // JavaThread::_is_in_internal_oome_mark + assert(_thread->is_in_internal_oome_mark(), "must be"); + _thread->set_is_in_internal_oome_mark(_outer); + } + } + + JavaThread* thread() const { return _thread; } +}; + #endif // SHARE_GC_SHARED_MEMALLOCATOR_HPP diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 2a831ddad89bc..8dcd954dcf479 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -73,8 +73,11 @@ class ContiguousSpace: public CHeapObj { // Accessors HeapWord* bottom() const { return _bottom; } HeapWord* end() const { return _end; } + HeapWord* top() const { return _top; } + void set_bottom(HeapWord* value) { _bottom = value; } void set_end(HeapWord* value) { _end = value; } + void set_top(HeapWord* value) { _top = value; } // Testers bool is_empty() const { return used() == 0; } @@ -112,10 +115,6 @@ class ContiguousSpace: public CHeapObj { // had allocation performed in it, but is now to be considered empty. void clear(bool mangle_space); - // Accessors - HeapWord* top() const { return _top; } - void set_top(HeapWord* value) { _top = value; } - // Used to save the space's current top for later use during mangling. void set_top_for_allocations() PRODUCT_RETURN; @@ -139,9 +138,9 @@ class ContiguousSpace: public CHeapObj { // Allocation (return null if full). Assumes the caller has established // mutually exclusive access to the space. - virtual HeapWord* allocate(size_t word_size); + HeapWord* allocate(size_t word_size); // Allocation (return null if full). Enforces mutual exclusion internally. - virtual HeapWord* par_allocate(size_t word_size); + HeapWord* par_allocate(size_t word_size); // Iteration void object_iterate(ObjectClosure* blk); diff --git a/src/hotspot/share/gc/z/zArray.inline.hpp b/src/hotspot/share/gc/z/zArray.inline.hpp index e4de7a37040da..2ec87a761564e 100644 --- a/src/hotspot/share/gc/z/zArray.inline.hpp +++ b/src/hotspot/share/gc/z/zArray.inline.hpp @@ -96,7 +96,7 @@ ZActivatedArray::ZActivatedArray(bool locked) _array() {} template -ZActivatedArray::~ZActivatedArray() { +ZActivatedArray::~ZActivatedArray() { FreeHeap(_lock); } diff --git a/src/hotspot/share/gc/z/zVerify.cpp b/src/hotspot/share/gc/z/zVerify.cpp index d8f78eb26e211..fba8adfb3c16f 100644 --- a/src/hotspot/share/gc/z/zVerify.cpp +++ b/src/hotspot/share/gc/z/zVerify.cpp @@ -483,9 +483,6 @@ void ZVerify::after_mark() { roots_strong(true /* verify_after_old_mark */); } if (ZVerifyObjects) { - // Workaround OopMapCacheAlloc_lock reordering with the StackWatermark_lock - DisableIsSTWGCActiveMark mark; - objects(false /* verify_weaks */); guarantee(zverify_broken_object == zaddress::null, "Verification failed"); } diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp index 9627259e26473..57b29a09d016f 100644 --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -248,12 +248,6 @@ bool ReferenceToThreadRootClosure::do_thread_stack_detailed(JavaThread* jt) { ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_stack_variable, jt); if (jt->has_last_Java_frame()) { - // Traverse the monitor chunks - MonitorChunk* chunk = jt->monitor_chunks(); - for (; chunk != nullptr; chunk = chunk->next()) { - chunk->oops_do(&rcl); - } - if (rcl.complete()) { return true; } diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index fc4bb5a6a0674..99f427ee1688d 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -28,6 +28,7 @@ #include "classfile/vmClasses.hpp" #include "compiler/compileBroker.hpp" #include "gc/shared/collectedHeap.hpp" +#include "gc/shared/memAllocator.hpp" #include "gc/shared/oopStorage.inline.hpp" #include "jvmci/jniAccessMark.inline.hpp" #include "jvmci/jvmciCompilerToVM.hpp" @@ -92,39 +93,25 @@ static void deopt_caller() { } // Manages a scope for a JVMCI runtime call that attempts a heap allocation. -// If there is a pending nonasync exception upon closing the scope and the runtime +// If there is a pending OutOfMemoryError upon closing the scope and the runtime // call is of the variety where allocation failure returns null without an // exception, the following action is taken: -// 1. The pending nonasync exception is cleared +// 1. The pending OutOfMemoryError is cleared // 2. null is written to JavaThread::_vm_result -// 3. Checks that an OutOfMemoryError is Universe::out_of_memory_error_retry(). -class RetryableAllocationMark: public StackObj { +class RetryableAllocationMark { private: - JavaThread* _thread; + InternalOOMEMark _iom; public: - RetryableAllocationMark(JavaThread* thread, bool activate) { - if (activate) { - assert(!thread->in_retryable_allocation(), "retryable allocation scope is non-reentrant"); - _thread = thread; - _thread->set_in_retryable_allocation(true); - } else { - _thread = nullptr; - } - } + RetryableAllocationMark(JavaThread* thread, bool activate) : _iom(activate ? thread : nullptr) {} ~RetryableAllocationMark() { - if (_thread != nullptr) { - _thread->set_in_retryable_allocation(false); - JavaThread* THREAD = _thread; // For exception macros. + JavaThread* THREAD = _iom.thread(); // For exception macros. + if (THREAD != nullptr) { if (HAS_PENDING_EXCEPTION) { oop ex = PENDING_EXCEPTION; - // Do not clear probable async exceptions. - CLEAR_PENDING_NONASYNC_EXCEPTION; - oop retry_oome = Universe::out_of_memory_error_retry(); - if (ex->is_a(retry_oome->klass()) && retry_oome != ex) { - ResourceMark rm; - fatal("Unexpected exception in scope of retryable allocation: " INTPTR_FORMAT " of type %s", p2i(ex), ex->klass()->external_name()); + THREAD->set_vm_result(nullptr); + if (ex->is_a(vmClasses::OutOfMemoryError_klass())) { + CLEAR_PENDING_EXCEPTION; } - _thread->set_vm_result(nullptr); } } } diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 187bdf25af85a..4a16b3d89a878 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -135,7 +135,6 @@ enum OutOfMemoryInstance { _oom_java_heap, _oom_array_size, _oom_gc_overhead_limit, _oom_realloc_objects, - _oom_retry, _oom_count }; OopHandle Universe::_out_of_memory_errors; @@ -655,6 +654,10 @@ oop Universe::out_of_memory_error_java_heap() { return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_java_heap)); } +oop Universe::out_of_memory_error_java_heap_without_backtrace() { + return out_of_memory_errors()->obj_at(_oom_java_heap); +} + oop Universe::out_of_memory_error_c_heap() { return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_c_heap)); } @@ -679,9 +682,6 @@ oop Universe::out_of_memory_error_realloc_objects() { return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_realloc_objects)); } -// Throw default _out_of_memory_error_retry object as it will never propagate out of the VM -oop Universe::out_of_memory_error_retry() { return out_of_memory_errors()->obj_at(_oom_retry); } - oop Universe::class_init_out_of_memory_error() { return out_of_memory_errors()->obj_at(_oom_java_heap); } oop Universe::class_init_stack_overflow_error() { return _class_init_stack_overflow_error.resolve(); } oop Universe::delayed_stack_overflow_error_message() { return _delayed_stack_overflow_error_message.resolve(); } @@ -785,9 +785,6 @@ void Universe::create_preallocated_out_of_memory_errors(TRAPS) { msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK); java_lang_Throwable::set_message(oom_array->obj_at(_oom_realloc_objects), msg()); - msg = java_lang_String::create_from_str("Java heap space: failed retryable allocation", CHECK); - java_lang_Throwable::set_message(oom_array->obj_at(_oom_retry), msg()); - // Setup the array of errors that have preallocated backtrace int len = (StackTraceInThrowable) ? (int)PreallocatedOutOfMemoryErrorCount : 0; objArrayOop instance = oopFactory::new_objArray(ik, len, CHECK); diff --git a/src/hotspot/share/memory/universe.hpp b/src/hotspot/share/memory/universe.hpp index d5a38658e482f..c7bdb8f233970 100644 --- a/src/hotspot/share/memory/universe.hpp +++ b/src/hotspot/share/memory/universe.hpp @@ -272,6 +272,7 @@ class Universe: AllStatic { // may or may not have a backtrace. If error has a backtrace then the stack trace is already // filled in. static oop out_of_memory_error_java_heap(); + static oop out_of_memory_error_java_heap_without_backtrace(); static oop out_of_memory_error_c_heap(); static oop out_of_memory_error_metaspace(); static oop out_of_memory_error_class_metaspace(); @@ -279,8 +280,6 @@ class Universe: AllStatic { static oop out_of_memory_error_gc_overhead_limit(); static oop out_of_memory_error_realloc_objects(); - // Throw default _out_of_memory_error_retry object as it will never propagate out of the VM - static oop out_of_memory_error_retry(); static oop delayed_stack_overflow_error_message(); // Saved StackOverflowError and OutOfMemoryError for use when diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 23a6770251a3d..ea3b5e756d082 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -873,12 +873,12 @@ void Klass::set_archived_java_mirror(int mirror_index) { void Klass::check_array_allocation_length(int length, int max_length, TRAPS) { if (length > max_length) { - if (!THREAD->in_retryable_allocation()) { + if (!THREAD->is_in_internal_oome_mark()) { report_java_out_of_memory("Requested array size exceeds VM limit"); JvmtiExport::post_array_size_exhausted(); THROW_OOP(Universe::out_of_memory_error_array_size()); } else { - THROW_OOP(Universe::out_of_memory_error_retry()); + THROW_OOP(Universe::out_of_memory_error_java_heap_without_backtrace()); } } else if (length < 0) { THROW_MSG(vmSymbols::java_lang_NegativeArraySizeException(), err_msg("%d", length)); diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index d5ed95187a893..25c7ced8aebfe 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -844,19 +844,9 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci, if (failing()) return; NOT_PRODUCT( verify_graph_edges(); ) - // If any phase is randomized for stress testing, seed random number - // generation and log the seed for repeatability. if (StressLCM || StressGCM || StressIGVN || StressCCP || StressIncrementalInlining || StressMacroExpansion) { - if (FLAG_IS_DEFAULT(StressSeed) || (FLAG_IS_ERGO(StressSeed) && directive->RepeatCompilationOption)) { - _stress_seed = static_cast(Ticks::now().nanoseconds()); - FLAG_SET_ERGO(StressSeed, _stress_seed); - } else { - _stress_seed = StressSeed; - } - if (_log != nullptr) { - _log->elem("stress_test seed='%u'", _stress_seed); - } + initialize_stress_seed(directive); } // Now optimize @@ -983,6 +973,11 @@ Compile::Compile( ciEnv* ci_env, _igvn_worklist = new (comp_arena()) Unique_Node_List(comp_arena()); _types = new (comp_arena()) Type_Array(comp_arena()); _node_hash = new (comp_arena()) NodeHash(comp_arena(), 255); + + if (StressLCM || StressGCM) { + initialize_stress_seed(directive); + } + { PhaseGVN gvn; set_initial_gvn(&gvn); // not significant, but GraphKit guys use it pervasively @@ -5068,6 +5063,18 @@ void Compile::remove_speculative_types(PhaseIterGVN &igvn) { // Auxiliary methods to support randomized stressing/fuzzing. +void Compile::initialize_stress_seed(const DirectiveSet* directive) { + if (FLAG_IS_DEFAULT(StressSeed) || (FLAG_IS_ERGO(StressSeed) && directive->RepeatCompilationOption)) { + _stress_seed = static_cast(Ticks::now().nanoseconds()); + FLAG_SET_ERGO(StressSeed, _stress_seed); + } else { + _stress_seed = StressSeed; + } + if (_log != nullptr) { + _log->elem("stress_test seed='%u'", _stress_seed); + } +} + int Compile::random() { _stress_seed = os::next_random(_stress_seed); return static_cast(_stress_seed); diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index df93b388daa8d..e1d9b61f7f8d1 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -1278,6 +1278,9 @@ class Compile : public Phase { int random(); bool randomized_select(int count); + // seed random number generation and log the seed for repeatability. + void initialize_stress_seed(const DirectiveSet* directive); + // supporting clone_map CloneMap& clone_map(); void set_clone_map(Dict* d); diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index c82eaad50e1ba..71051ee7bd10a 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -2184,7 +2184,8 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { strcmp(call->as_CallLeaf()->_name, "vectorizedMismatch") == 0 || strcmp(call->as_CallLeaf()->_name, "arraysort_stub") == 0 || strcmp(call->as_CallLeaf()->_name, "array_partition_stub") == 0 || - strcmp(call->as_CallLeaf()->_name, "get_class_id_intrinsic") == 0) + strcmp(call->as_CallLeaf()->_name, "get_class_id_intrinsic") == 0 || + strcmp(call->as_CallLeaf()->_name, "unsafe_setmemory") == 0) ))) { call->dump(); fatal("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name); diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index bb58c2ff8cee6..04631dcbae237 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -1569,8 +1569,8 @@ Node* Node::last_out(DUIterator_Last& i) const { class SimpleDUIterator : public StackObj { private: Node* node; - DUIterator_Fast i; DUIterator_Fast imax; + DUIterator_Fast i; public: SimpleDUIterator(Node* n): node(n), i(n->fast_outs(imax)) {} bool has_next() { return i < imax; } diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index 4d623144a8407..3f48567c09363 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -1280,7 +1280,6 @@ void PhaseOutput::estimate_buffer_size(int& const_req) { } // Compute prolog code size - _method_size = 0; _frame_slots = OptoReg::reg2stack(C->matcher()->_old_SP) + C->regalloc()->_framesize; assert(_frame_slots >= 0 && _frame_slots < 1000000, "sanity check"); diff --git a/src/hotspot/share/opto/output.hpp b/src/hotspot/share/opto/output.hpp index b58b97e77455e..1717955360256 100644 --- a/src/hotspot/share/opto/output.hpp +++ b/src/hotspot/share/opto/output.hpp @@ -77,7 +77,6 @@ class BufferSizingData { class PhaseOutput : public Phase { private: // Instruction bits passed off to the VM - int _method_size; // Size of nmethod code segment in bytes CodeBuffer _code_buffer; // Where the code is assembled int _first_block_size; // Size of unvalidated entry point code / OSR poison code ExceptionHandlerTable _handler_table; // Table of native-code exception handlers @@ -166,7 +165,6 @@ class PhaseOutput : public Phase { void install(); // Instruction bits passed off to the VM - int code_size() { return _method_size; } CodeBuffer* code_buffer() { return &_code_buffer; } int first_block_size() { return _first_block_size; } void set_frame_complete(int off) { if (!in_scratch_emit_size()) { _code_offsets.set_value(CodeOffsets::Frame_Complete, off); } } diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index cd9b76eb44db9..f41e8a7b8b354 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -45,12 +45,13 @@ SuperWord::SuperWord(const VLoopAnalyzer &vloop_analyzer) : _arena(mtCompiler), _node_info(arena(), _vloop.estimated_body_length(), 0, SWNodeInfo::initial), // info needed per node _clone_map(phase()->C->clone_map()), // map of nodes created in cloning - _align_to_ref(nullptr), // memory reference to align vectors to _pairset(&_arena, _vloop_analyzer), _packset(&_arena, _vloop_analyzer NOT_PRODUCT(COMMA is_trace_superword_packset()) NOT_PRODUCT(COMMA is_trace_superword_rejections()) ), + _mem_ref_for_main_loop_alignment(nullptr), + _aw_for_main_loop_alignment(0), _do_vector_loop(phase()->C->do_vector_loop()), // whether to do vectorization/simd style _num_work_vecs(0), // amount of vector work we have _num_reductions(0) // amount of reduction work we have @@ -516,22 +517,12 @@ void SuperWord::find_adjacent_refs() { int max_idx; - // Take the first mem_ref as the reference to align to. The pre-loop trip count is - // modified to align this reference to a vector-aligned address. If strict alignment - // is required, we may change the reference later (see filter_packs_for_alignment()). - MemNode* align_to_mem_ref = nullptr; - while (memops.size() != 0) { // Find a memory reference to align to. MemNode* mem_ref = find_align_to_ref(memops, max_idx); if (mem_ref == nullptr) break; int iv_adjustment = get_iv_adjustment(mem_ref); - if (align_to_mem_ref == nullptr) { - align_to_mem_ref = mem_ref; - set_align_to_ref(align_to_mem_ref); - } - const VPointer& align_to_ref_p = vpointer(mem_ref); // Set alignment relative to "align_to_ref" for all related memory operations. for (int i = memops.size() - 1; i >= 0; i--) { @@ -573,9 +564,6 @@ void SuperWord::find_adjacent_refs() { } } // while (memops.size() != 0) - assert(_pairset.is_empty() || align_to_mem_ref != nullptr, - "pairset empty or we find the alignment reference"); - #ifndef PRODUCT if (is_trace_superword_packset()) { tty->print_cr("\nAfter Superword::find_adjacent_refs"); @@ -1723,7 +1711,11 @@ void SuperWord::filter_packs_for_alignment() { if (current->is_constrained()) { // Solution is constrained (not trivial) // -> must change pre-limit to achieve alignment - set_align_to_ref(current->as_constrained()->mem_ref()); + MemNode const* mem = current->as_constrained()->mem_ref(); + Node_List* pack = get_pack(mem); + assert(pack != nullptr, "memop of final solution must still be packed"); + _mem_ref_for_main_loop_alignment = mem; + _aw_for_main_loop_alignment = pack->size() * mem->memory_size(); } } @@ -3397,6 +3389,32 @@ LoadNode::ControlDependency SuperWord::control_dependency(Node_List* p) { return dep; } +// Find the memop pack with the maximum vector width, unless they were already +// determined by SuperWord::filter_packs_for_alignment(). +void SuperWord::determine_mem_ref_and_aw_for_main_loop_alignment() { + if (_mem_ref_for_main_loop_alignment != nullptr) { + assert(vectors_should_be_aligned(), "mem_ref only set if filtered for alignment"); + return; + } + + MemNode const* mem_ref = nullptr; + int max_aw = 0; + for (int i = 0; i < _packset.length(); i++) { + Node_List* pack = _packset.at(i); + MemNode* first = pack->at(0)->isa_Mem(); + if (first == nullptr) { continue; } + + int vw = first->memory_size() * pack->size(); + if (vw > max_aw) { + max_aw = vw; + mem_ref = first; + } + } + assert(mem_ref != nullptr && max_aw > 0, "found mem_ref and aw"); + _mem_ref_for_main_loop_alignment = mem_ref; + _aw_for_main_loop_alignment = max_aw; +} + #define TRACE_ALIGN_VECTOR_NODE(node) { \ DEBUG_ONLY( \ if (is_trace_align_vector()) { \ @@ -3407,11 +3425,14 @@ LoadNode::ControlDependency SuperWord::control_dependency(Node_List* p) { } \ // Ensure that the main loop vectors are aligned by adjusting the pre loop limit. We memory-align -// the address of "align_to_ref" to the maximal possible vector width. We adjust the pre-loop -// iteration count by adjusting the pre-loop limit. +// the address of "_mem_ref_for_main_loop_alignment" to "_aw_for_main_loop_alignment", which is a +// sufficiently large alignment width. We adjust the pre-loop iteration count by adjusting the +// pre-loop limit. void SuperWord::adjust_pre_loop_limit_to_align_main_loop_vectors() { - const MemNode* align_to_ref = _align_to_ref; - assert(align_to_ref != nullptr, "align_to_ref must be set"); + determine_mem_ref_and_aw_for_main_loop_alignment(); + const MemNode* align_to_ref = _mem_ref_for_main_loop_alignment; + const int aw = _aw_for_main_loop_alignment; + assert(align_to_ref != nullptr && aw > 0, "must have alignment reference and aw"); assert(cl()->is_main_loop(), "can only do alignment for main loop"); // The opaque node for the limit, where we adjust the input @@ -3556,10 +3577,7 @@ void SuperWord::adjust_pre_loop_limit_to_align_main_loop_vectors() { // = MIN(new_limit, orig_limit) (15a, stride > 0) // constrained_limit = MAX(old_limit - adjust_pre_iter, orig_limit) // = MAX(new_limit, orig_limit) (15a, stride < 0) - - // We chose an aw that is the maximal possible vector width for the type of - // align_to_ref. - const int aw = vector_width_in_bytes(align_to_ref); + // const int stride = iv_stride(); const int scale = align_to_ref_p.scale_in_bytes(); const int offset = align_to_ref_p.offset_in_bytes(); diff --git a/src/hotspot/share/opto/superword.hpp b/src/hotspot/share/opto/superword.hpp index 7d1ba1131f322..159032d94b909 100644 --- a/src/hotspot/share/opto/superword.hpp +++ b/src/hotspot/share/opto/superword.hpp @@ -411,11 +411,15 @@ class SuperWord : public ResourceObj { GrowableArray _node_info; // Info needed per node CloneMap& _clone_map; // map of nodes created in cloning - MemNode const* _align_to_ref; // Memory reference that pre-loop will align to PairSet _pairset; PackSet _packset; + // Memory reference, and the alignment width (aw) for which we align the main-loop, + // by adjusting the pre-loop limit. + MemNode const* _mem_ref_for_main_loop_alignment; + int _aw_for_main_loop_alignment; + public: SuperWord(const VLoopAnalyzer &vloop_analyzer); @@ -563,8 +567,6 @@ class SuperWord : public ResourceObj { Arena* arena() { return &_arena; } int get_vw_bytes_special(MemNode* s); - const MemNode* align_to_ref() const { return _align_to_ref; } - void set_align_to_ref(const MemNode* m) { _align_to_ref = m; } // Ensure node_info contains element "i" void grow_node_info(int i) { if (i >= _node_info.length()) _node_info.at_put_grow(i, SWNodeInfo::initial); } @@ -670,6 +672,7 @@ class SuperWord : public ResourceObj { // Alignment within a vector memory reference int memory_alignment(MemNode* s, int iv_adjust); // Ensure that the main loop vectors are aligned by adjusting the pre loop limit. + void determine_mem_ref_and_aw_for_main_loop_alignment(); void adjust_pre_loop_limit_to_align_main_loop_vectors(); }; diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index 2039e9c27be74..807912327e6d1 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.cpp @@ -59,6 +59,17 @@ static bool check_vbox(const TypeInstPtr* vbox_type) { } #endif +#define log_if_needed(...) \ + if (C->print_intrinsics()) { \ + tty->print_cr(__VA_ARGS__); \ + } + +#ifndef PRODUCT +#define non_product_log_if_needed(...) log_if_needed(__VA_ARGS__) +#else +#define non_product_log_if_needed(...) +#endif + static bool is_vector_mask(ciKlass* klass) { return klass->is_subclass_of(ciEnv::current()->vector_VectorMask_klass()); } @@ -85,12 +96,8 @@ bool LibraryCallKit::arch_supports_vector_rotate(int opc, int num_elem, BasicTyp if ((mask_use_type & VecMaskUseLoad) != 0) { if (!Matcher::match_rule_supported_vector(Op_VectorLoadMask, num_elem, elem_bt) || !Matcher::match_rule_supported_vector(Op_LoadVector, num_elem, T_BOOLEAN)) { - #ifndef PRODUCT - if (C->print_intrinsics()) { - tty->print_cr(" ** Rejected vector mask loading (%s,%s,%d) because architecture does not support it", - NodeClassNames[Op_VectorLoadMask], type2name(elem_bt), num_elem); - } - #endif + non_product_log_if_needed(" ** Rejected vector mask loading (%s,%s,%d) because architecture does not support it", + NodeClassNames[Op_VectorLoadMask], type2name(elem_bt), num_elem); return false; } } @@ -98,12 +105,8 @@ bool LibraryCallKit::arch_supports_vector_rotate(int opc, int num_elem, BasicTyp if ((mask_use_type & VecMaskUsePred) != 0) { if (!Matcher::has_predicated_vectors() || !Matcher::match_rule_supported_vector_masked(opc, num_elem, elem_bt)) { - #ifndef PRODUCT - if (C->print_intrinsics()) { - tty->print_cr("Rejected vector mask predicate using (%s,%s,%d) because architecture does not support it", - NodeClassNames[opc], type2name(elem_bt), num_elem); - } - #endif + non_product_log_if_needed("Rejected vector mask predicate using (%s,%s,%d) because architecture does not support it", + NodeClassNames[opc], type2name(elem_bt), num_elem); return false; } } @@ -185,43 +188,27 @@ Node* GraphKit::vector_shift_count(Node* cnt, int shift_op, BasicType bt, int nu bool LibraryCallKit::arch_supports_vector(int sopc, int num_elem, BasicType type, VectorMaskUseType mask_use_type, bool has_scalar_args) { // Check that the operation is valid. if (sopc <= 0) { -#ifndef PRODUCT - if (C->print_intrinsics()) { - tty->print_cr(" ** Rejected intrinsification because no valid vector op could be extracted"); - } -#endif + non_product_log_if_needed(" ** Rejected intrinsification because no valid vector op could be extracted"); return false; } if (VectorNode::is_vector_rotate(sopc)) { if(!arch_supports_vector_rotate(sopc, num_elem, type, mask_use_type, has_scalar_args)) { -#ifndef PRODUCT - if (C->print_intrinsics()) { - tty->print_cr(" ** Rejected vector op (%s,%s,%d) because architecture does not support variable vector shifts", - NodeClassNames[sopc], type2name(type), num_elem); - } -#endif + non_product_log_if_needed(" ** Rejected vector op (%s,%s,%d) because architecture does not support variable vector shifts", + NodeClassNames[sopc], type2name(type), num_elem); return false; } } else if (VectorNode::is_vector_integral_negate(sopc)) { if (!VectorNode::is_vector_integral_negate_supported(sopc, num_elem, type, false)) { -#ifndef PRODUCT - if (C->print_intrinsics()) { - tty->print_cr(" ** Rejected vector op (%s,%s,%d) because architecture does not support integral vector negate", - NodeClassNames[sopc], type2name(type), num_elem); - } -#endif + non_product_log_if_needed(" ** Rejected vector op (%s,%s,%d) because architecture does not support integral vector negate", + NodeClassNames[sopc], type2name(type), num_elem); return false; } } else { // Check that architecture supports this op-size-type combination. if (!Matcher::match_rule_supported_vector(sopc, num_elem, type)) { -#ifndef PRODUCT - if (C->print_intrinsics()) { - tty->print_cr(" ** Rejected vector op (%s,%s,%d) because architecture does not support it", - NodeClassNames[sopc], type2name(type), num_elem); - } -#endif + non_product_log_if_needed(" ** Rejected vector op (%s,%s,%d) because architecture does not support it", + NodeClassNames[sopc], type2name(type), num_elem); return false; } else { assert(Matcher::match_rule_supported(sopc), "must be supported"); @@ -230,23 +217,15 @@ bool LibraryCallKit::arch_supports_vector(int sopc, int num_elem, BasicType type if (num_elem == 1) { if (mask_use_type != VecMaskNotUsed) { -#ifndef PRODUCT - if (C->print_intrinsics()) { - tty->print_cr(" ** Rejected vector mask op (%s,%s,%d) because architecture does not support it", - NodeClassNames[sopc], type2name(type), num_elem); - } -#endif + non_product_log_if_needed(" ** Rejected vector mask op (%s,%s,%d) because architecture does not support it", + NodeClassNames[sopc], type2name(type), num_elem); return false; } if (sopc != 0) { if (sopc != Op_LoadVector && sopc != Op_StoreVector) { -#ifndef PRODUCT - if (C->print_intrinsics()) { - tty->print_cr(" ** Not a svml call or load/store vector op (%s,%s,%d)", - NodeClassNames[sopc], type2name(type), num_elem); - } -#endif + non_product_log_if_needed(" ** Not a svml call or load/store vector op (%s,%s,%d)", + NodeClassNames[sopc], type2name(type), num_elem); return false; } } @@ -254,10 +233,8 @@ bool LibraryCallKit::arch_supports_vector(int sopc, int num_elem, BasicType type if (!has_scalar_args && VectorNode::is_vector_shift(sopc) && Matcher::supports_vector_variable_shifts() == false) { - if (C->print_intrinsics()) { - tty->print_cr(" ** Rejected vector op (%s,%s,%d) because architecture does not support variable vector shifts", - NodeClassNames[sopc], type2name(type), num_elem); - } + log_if_needed(" ** Rejected vector op (%s,%s,%d) because architecture does not support variable vector shifts", + NodeClassNames[sopc], type2name(type), num_elem); return false; } @@ -267,12 +244,8 @@ bool LibraryCallKit::arch_supports_vector(int sopc, int num_elem, BasicType type if ((mask_use_type & VecMaskUseLoad) != 0) { if (!Matcher::match_rule_supported_vector(Op_VectorLoadMask, num_elem, type) || !Matcher::match_rule_supported_vector(Op_LoadVector, num_elem, T_BOOLEAN)) { - #ifndef PRODUCT - if (C->print_intrinsics()) { - tty->print_cr(" ** Rejected vector mask loading (%s,%s,%d) because architecture does not support it", - NodeClassNames[Op_VectorLoadMask], type2name(type), num_elem); - } - #endif + non_product_log_if_needed(" ** Rejected vector mask loading (%s,%s,%d) because architecture does not support it", + NodeClassNames[Op_VectorLoadMask], type2name(type), num_elem); return false; } } @@ -283,12 +256,8 @@ bool LibraryCallKit::arch_supports_vector(int sopc, int num_elem, BasicType type if ((mask_use_type & VecMaskUseStore) != 0) { if (!Matcher::match_rule_supported_vector(Op_VectorStoreMask, num_elem, type) || !Matcher::match_rule_supported_vector(Op_StoreVector, num_elem, T_BOOLEAN)) { - #ifndef PRODUCT - if (C->print_intrinsics()) { - tty->print_cr("Rejected vector mask storing (%s,%s,%d) because architecture does not support it", - NodeClassNames[Op_VectorStoreMask], type2name(type), num_elem); - } - #endif + non_product_log_if_needed("Rejected vector mask storing (%s,%s,%d) because architecture does not support it", + NodeClassNames[Op_VectorStoreMask], type2name(type), num_elem); return false; } } @@ -305,12 +274,8 @@ bool LibraryCallKit::arch_supports_vector(int sopc, int num_elem, BasicType type is_supported |= Matcher::supports_vector_predicate_op_emulation(sopc, num_elem, type); if (!is_supported) { - #ifndef PRODUCT - if (C->print_intrinsics()) { - tty->print_cr("Rejected vector mask predicate using (%s,%s,%d) because architecture does not support it", - NodeClassNames[sopc], type2name(type), num_elem); - } - #endif + non_product_log_if_needed("Rejected vector mask predicate using (%s,%s,%d) because architecture does not support it", + NodeClassNames[sopc], type2name(type), num_elem); return false; } } @@ -360,27 +325,21 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) { if (opr == nullptr || vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr || !opr->is_con() || vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: opr=%s vclass=%s etype=%s vlen=%s", + log_if_needed(" ** missing constant: opr=%s vclass=%s etype=%s vlen=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(3)->Opcode()], NodeClassNames[argument(4)->Opcode()]); - } return false; // not enough info for intrinsification } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } if (!is_klass_initialized(vector_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } @@ -390,23 +349,17 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) { bool is_masked_op = vmask_type != TypePtr::NULL_PTR; if (is_masked_op) { if (mask_klass == nullptr || mask_klass->const_oop() == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: maskclass=%s", NodeClassNames[argument(2)->Opcode()]); - } + log_if_needed(" ** missing constant: maskclass=%s", NodeClassNames[argument(2)->Opcode()]); return false; // not enough info for intrinsification } if (!is_klass_initialized(mask_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** mask klass argument not initialized"); - } + log_if_needed(" ** mask klass argument not initialized"); return false; } if (vmask_type->maybe_null()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** null mask values are not allowed for masked op"); - } + log_if_needed(" ** null mask values are not allowed for masked op"); return false; } } @@ -416,17 +369,13 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) { int opc = VectorSupport::vop2ideal(opr->get_con(), elem_bt); int sopc = VectorNode::opcode(opc, elem_bt); if ((opc != Op_CallLeafVector) && (sopc == 0)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** operation not supported: opc=%s bt=%s", NodeClassNames[opc], type2name(elem_bt)); - } + log_if_needed(" ** operation not supported: opc=%s bt=%s", NodeClassNames[opc], type2name(elem_bt)); return false; // operation not supported } if (num_elem == 1) { if (opc != Op_CallLeafVector || elem_bt != T_DOUBLE) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a svml call: arity=%d opc=%d vlen=%d etype=%s", + log_if_needed(" ** not a svml call: arity=%d opc=%d vlen=%d etype=%s", n, opc, num_elem, type2name(elem_bt)); - } return false; } } @@ -439,22 +388,16 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) { if (opc == Op_CallLeafVector) { if (!UseVectorStubs) { - if (C->print_intrinsics()) { - tty->print_cr(" ** vector stubs support is disabled"); - } + log_if_needed(" ** vector stubs support is disabled"); return false; } if (!Matcher::supports_vector_calling_convention()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** no vector calling conventions supported"); - } + log_if_needed(" ** no vector calling conventions supported"); return false; } if (!Matcher::vector_size_supported(elem_bt, num_elem)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** vector size (vlen=%d, etype=%s) is not supported", + log_if_needed(" ** vector size (vlen=%d, etype=%s) is not supported", num_elem, type2name(elem_bt)); - } return false; } } @@ -463,21 +406,17 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) { VectorMaskUseType mask_use_type = is_vector_mask(vbox_klass) ? VecMaskUseAll : is_masked_op ? VecMaskUseLoad : VecMaskNotUsed; if ((sopc != 0) && !arch_supports_vector(sopc, num_elem, elem_bt, mask_use_type)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d opc=%d vlen=%d etype=%s ismask=%d is_masked_op=%d", + log_if_needed(" ** not supported: arity=%d opc=%d vlen=%d etype=%s ismask=%d is_masked_op=%d", n, sopc, num_elem, type2name(elem_bt), is_vector_mask(vbox_klass) ? 1 : 0, is_masked_op ? 1 : 0); - } return false; // not supported } // Return true if current platform has implemented the masked operation with predicate feature. bool use_predicate = is_masked_op && sopc != 0 && arch_supports_vector(sopc, num_elem, elem_bt, VecMaskUsePred); if (is_masked_op && !use_predicate && !arch_supports_vector(Op_VectorBlend, num_elem, elem_bt, VecMaskUseLoad)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d opc=%d vlen=%d etype=%s ismask=0 is_masked_op=1", + log_if_needed(" ** not supported: arity=%d opc=%d vlen=%d etype=%s ismask=0 is_masked_op=1", n, sopc, num_elem, type2name(elem_bt)); - } return false; } @@ -486,10 +425,8 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) { case 3: { opd3 = unbox_vector(argument(7), vbox_type, elem_bt, num_elem); if (opd3 == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed v3=%s", + log_if_needed(" ** unbox failed v3=%s", NodeClassNames[argument(7)->Opcode()]); - } return false; } // fall-through @@ -497,10 +434,8 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) { case 2: { opd2 = unbox_vector(argument(6), vbox_type, elem_bt, num_elem); if (opd2 == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed v2=%s", + log_if_needed(" ** unbox failed v2=%s", NodeClassNames[argument(6)->Opcode()]); - } return false; } // fall-through @@ -508,10 +443,8 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) { case 1: { opd1 = unbox_vector(argument(5), vbox_type, elem_bt, num_elem); if (opd1 == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed v1=%s", + log_if_needed(" ** unbox failed v1=%s", NodeClassNames[argument(5)->Opcode()]); - } return false; } break; @@ -526,10 +459,8 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) { const TypeInstPtr* mbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, mbox_klass); mask = unbox_vector(argument(n + 5), mbox_type, elem_bt, num_elem); if (mask == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed mask=%s", + log_if_needed(" ** unbox failed mask=%s", NodeClassNames[argument(n + 5)->Opcode()]); - } return false; } } @@ -539,12 +470,10 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) { assert(UseVectorStubs, "sanity"); operation = gen_call_to_svml(opr->get_con(), elem_bt, num_elem, opd1, opd2); if (operation == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** svml call failed for %s_%s_%d", + log_if_needed(" ** svml call failed for %s_%s_%d", (elem_bt == T_FLOAT)?"float":"double", VectorSupport::svmlname[opr->get_con() - VectorSupport::VECTOR_OP_SVML_START], num_elem * type2aelembytes(elem_bt)); - } return false; } } else { @@ -599,9 +528,7 @@ bool LibraryCallKit::inline_vector_shuffle_iota() { } if (!is_klass_initialized(shuffle_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } @@ -708,9 +635,7 @@ bool LibraryCallKit::inline_vector_mask_operation() { } if (!is_klass_initialized(mask_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } @@ -720,10 +645,8 @@ bool LibraryCallKit::inline_vector_mask_operation() { int mopc = VectorSupport::vop2ideal(oper->get_con(), elem_bt); if (!arch_supports_vector(mopc, num_elem, elem_bt, VecMaskUseLoad)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=1 op=cast#%d/3 vlen2=%d etype2=%s", + log_if_needed(" ** not supported: arity=1 op=cast#%d/3 vlen2=%d etype2=%s", mopc, num_elem, type2name(elem_bt)); - } return false; // not supported } @@ -732,10 +655,8 @@ bool LibraryCallKit::inline_vector_mask_operation() { const TypeInstPtr* mask_box_type = TypeInstPtr::make_exact(TypePtr::NotNull, mbox_klass); Node* mask_vec = unbox_vector(mask, mask_box_type, elem_bt, num_elem, true); if (mask_vec == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed mask=%s", + log_if_needed(" ** unbox failed mask=%s", NodeClassNames[argument(4)->Opcode()]); - } return false; } @@ -774,9 +695,7 @@ bool LibraryCallKit::inline_vector_shuffle_to_vector() { return false; // not enough info for intrinsification } if (!is_klass_initialized(shuffle_klass) || !is_klass_initialized(vector_klass) ) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } @@ -791,10 +710,8 @@ bool LibraryCallKit::inline_vector_shuffle_to_vector() { int cast_vopc = VectorCastNode::opcode(-1, T_BYTE); // from shuffle of type T_BYTE // Make sure that cast is implemented to particular type/size combination. if (!arch_supports_vector(cast_vopc, num_elem, elem_bt, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=1 op=cast#%d/3 vlen2=%d etype2=%s", + log_if_needed(" ** not supported: arity=1 op=cast#%d/3 vlen2=%d etype2=%s", cast_vopc, num_elem, type2name(elem_bt)); - } return false; } @@ -838,27 +755,21 @@ bool LibraryCallKit::inline_vector_frombits_coerced() { if (vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr || mode == nullptr || bits_type == nullptr || vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con() || !mode->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: vclass=%s etype=%s vlen=%s bitwise=%s", + log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s bitwise=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(2)->Opcode()], NodeClassNames[argument(5)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } BasicType elem_bt = elem_type->basic_type(); @@ -872,12 +783,10 @@ bool LibraryCallKit::inline_vector_frombits_coerced() { int opc = bcast_mode == VectorSupport::MODE_BITS_COERCED_LONG_TO_MASK ? Op_VectorLongToMask : Op_Replicate; if (!arch_supports_vector(opc, num_elem, elem_bt, checkFlags, true /*has_scalar_args*/)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=0 op=broadcast vlen=%d etype=%s ismask=%d bcast_mode=%d", + log_if_needed(" ** not supported: arity=0 op=broadcast vlen=%d etype=%s ismask=%d bcast_mode=%d", num_elem, type2name(elem_bt), is_mask ? 1 : 0, bcast_mode); - } return false; // not supported } @@ -973,27 +882,21 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { if (vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr || !from_ms->is_con() || vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: vclass=%s etype=%s vlen=%s from_ms=%s", + log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s from_ms=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(2)->Opcode()], NodeClassNames[argument(6)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } BasicType elem_bt = elem_type->basic_type(); @@ -1001,11 +904,9 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { // TODO When mask usage is supported, VecMaskNotUsed needs to be VecMaskUseLoad. if (!arch_supports_vector(is_store ? Op_StoreVector : Op_LoadVector, num_elem, elem_bt, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d op=%s vlen=%d etype=%s ismask=no", + log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s ismask=no", is_store, is_store ? "store" : "load", num_elem, type2name(elem_bt)); - } return false; // not supported } @@ -1046,18 +947,14 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { arr_type->elem()->array_element_basic_type() != elem_bt); BasicType mem_elem_bt = mismatched_ms ? arr_type->elem()->array_element_basic_type() : elem_bt; if (!is_java_primitive(mem_elem_bt)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** non-primitive array element type"); - } + log_if_needed(" ** non-primitive array element type"); return false; } int mem_num_elem = mismatched_ms ? (num_elem * type2aelembytes(elem_bt)) / type2aelembytes(mem_elem_bt) : num_elem; if (arr_type != nullptr && !is_mask && !elem_consistent_with_arr(elem_bt, arr_type, mismatched_ms)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d op=%s vlen=%d etype=%s atype=%s ismask=no", + log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s atype=%s ismask=no", is_store, is_store ? "store" : "load", num_elem, type2name(elem_bt), type2name(arr_type->elem()->array_element_basic_type())); - } set_map(old_map); set_sp(old_sp); return false; @@ -1068,11 +965,9 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { if (is_store) { if (!arch_supports_vector(Op_StoreVector, num_elem, elem_bt, VecMaskNotUsed) || !arch_supports_vector(Op_VectorReinterpret, mem_num_elem, mem_elem_bt, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d op=%s vlen=%d*8 etype=%s/8 ismask=no", + log_if_needed(" ** not supported: arity=%d op=%s vlen=%d*8 etype=%s/8 ismask=no", is_store, "store", num_elem, type2name(elem_bt)); - } set_map(old_map); set_sp(old_sp); return false; // not supported @@ -1080,11 +975,9 @@ bool LibraryCallKit::inline_vector_mem_operation(bool is_store) { } else { if (!arch_supports_vector(Op_LoadVector, mem_num_elem, mem_elem_bt, VecMaskNotUsed) || !arch_supports_vector(Op_VectorReinterpret, num_elem, elem_bt, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d op=%s vlen=%d*8 etype=%s/8 ismask=no", + log_if_needed(" ** not supported: arity=%d op=%s vlen=%d*8 etype=%s/8 ismask=no", is_store, "load", mem_num_elem, type2name(mem_elem_bt)); - } set_map(old_map); set_sp(old_sp); return false; // not supported @@ -1198,35 +1091,27 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { if (vector_klass == nullptr || mask_klass == nullptr || elem_klass == nullptr || vlen == nullptr || vector_klass->const_oop() == nullptr || mask_klass->const_oop() == nullptr || from_ms == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con() || !from_ms->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: vclass=%s mclass=%s etype=%s vlen=%s from_ms=%s", + log_if_needed(" ** missing constant: vclass=%s mclass=%s etype=%s vlen=%s from_ms=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(2)->Opcode()], NodeClassNames[argument(3)->Opcode()], NodeClassNames[argument(7)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } if (!is_klass_initialized(mask_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** mask klass argument not initialized"); - } + log_if_needed(" ** mask klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } @@ -1248,11 +1133,9 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { BIG_ENDIAN_ONLY(if (mismatched_ms) return false;) // If there is no consistency between array and vector element types, it must be special byte array case if (arr_type != nullptr && !elem_consistent_with_arr(elem_bt, arr_type, mismatched_ms)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d op=%s vlen=%d etype=%s atype=%s", + log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s atype=%s", is_store, is_store ? "storeMasked" : "loadMasked", num_elem, type2name(elem_bt), type2name(arr_type->elem()->array_element_basic_type())); - } set_map(old_map); set_sp(old_sp); return false; @@ -1274,10 +1157,8 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { // Masked vector load with IOOBE always uses the predicated load. const TypeInt* offset_in_range = gvn().type(argument(9))->isa_int(); if (!offset_in_range->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: offsetInRange=%s", + log_if_needed(" ** missing constant: offsetInRange=%s", NodeClassNames[argument(8)->Opcode()]); - } set_map(old_map); set_sp(old_sp); return false; @@ -1286,11 +1167,9 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { } if (needs_predicate) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: op=%s vlen=%d etype=%s mismatched_ms=%d", + log_if_needed(" ** not supported: op=%s vlen=%d etype=%s mismatched_ms=%d", is_store ? "storeMasked" : "loadMasked", num_elem, type2name(elem_bt), mismatched_ms ? 1 : 0); - } set_map(old_map); set_sp(old_sp); return false; @@ -1301,10 +1180,8 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { // the normal vector load and blend operations are supported by backend. if (!supports_predicate && (!arch_supports_vector(Op_LoadVector, mem_num_elem, mem_elem_bt, VecMaskNotUsed) || !arch_supports_vector(Op_VectorBlend, mem_num_elem, mem_elem_bt, VecMaskUseLoad))) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: op=loadMasked vlen=%d etype=%s mismatched_ms=%d", + log_if_needed(" ** not supported: op=loadMasked vlen=%d etype=%s mismatched_ms=%d", num_elem, type2name(elem_bt), mismatched_ms ? 1 : 0); - } set_map(old_map); set_sp(old_sp); return false; @@ -1314,11 +1191,9 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { // with byte type is supported by backend. if (mismatched_ms) { if (!arch_supports_vector(Op_VectorReinterpret, mem_num_elem, T_BYTE, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d op=%s vlen=%d etype=%s mismatched_ms=1", + log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s mismatched_ms=1", is_store, is_store ? "storeMasked" : "loadMasked", num_elem, type2name(elem_bt)); - } set_map(old_map); set_sp(old_sp); return false; @@ -1328,11 +1203,9 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { // Since it needs to unbox the mask, we need to double check that the related load operations // for mask are supported by backend. if (!arch_supports_vector(Op_LoadVector, num_elem, elem_bt, VecMaskUseLoad)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d op=%s vlen=%d etype=%s", + log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s", is_store, is_store ? "storeMasked" : "loadMasked", num_elem, type2name(elem_bt)); - } set_map(old_map); set_sp(old_sp); return false; @@ -1352,11 +1225,9 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { Node* mask = unbox_vector(is_store ? argument(9) : argument(8), mbox_type, elem_bt, num_elem); if (mask == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed mask=%s", + log_if_needed(" ** unbox failed mask=%s", is_store ? NodeClassNames[argument(9)->Opcode()] : NodeClassNames[argument(8)->Opcode()]); - } set_map(old_map); set_sp(old_sp); return false; @@ -1365,10 +1236,8 @@ bool LibraryCallKit::inline_vector_mem_masked_operation(bool is_store) { if (is_store) { Node* val = unbox_vector(argument(8), vbox_type, elem_bt, num_elem); if (val == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed vector=%s", + log_if_needed(" ** unbox failed vector=%s", NodeClassNames[argument(8)->Opcode()]); - } set_map(old_map); set_sp(old_sp); return false; // operand unboxing failed @@ -1460,28 +1329,22 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { if (vector_klass == nullptr || elem_klass == nullptr || vector_idx_klass == nullptr || vlen == nullptr || vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || vector_idx_klass->const_oop() == nullptr || !vlen->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: vclass=%s etype=%s vlen=%s viclass=%s", + log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s viclass=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(2)->Opcode()], NodeClassNames[argument(3)->Opcode()], NodeClassNames[argument(4)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass) || !is_klass_initialized(vector_idx_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } @@ -1492,44 +1355,34 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { bool is_masked_op = vmask_type != TypePtr::NULL_PTR; if (is_masked_op) { if (mask_klass == nullptr || mask_klass->const_oop() == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: maskclass=%s", NodeClassNames[argument(1)->Opcode()]); - } + log_if_needed(" ** missing constant: maskclass=%s", NodeClassNames[argument(1)->Opcode()]); return false; // not enough info for intrinsification } if (!is_klass_initialized(mask_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** mask klass argument not initialized"); - } + log_if_needed(" ** mask klass argument not initialized"); return false; } if (vmask_type->maybe_null()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** null mask values are not allowed for masked op"); - } + log_if_needed(" ** null mask values are not allowed for masked op"); return false; } // Check whether the predicated gather/scatter node is supported by architecture. VectorMaskUseType mask = (VectorMaskUseType) (VecMaskUseLoad | VecMaskUsePred); if (!arch_supports_vector(is_scatter ? Op_StoreVectorScatterMasked : Op_LoadVectorGatherMasked, num_elem, elem_bt, mask)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d op=%s vlen=%d etype=%s is_masked_op=1", + log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s is_masked_op=1", is_scatter, is_scatter ? "scatterMasked" : "gatherMasked", num_elem, type2name(elem_bt)); - } return false; // not supported } } else { // Check whether the normal gather/scatter node is supported for non-masked operation. if (!arch_supports_vector(is_scatter ? Op_StoreVectorScatter : Op_LoadVectorGather, num_elem, elem_bt, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d op=%s vlen=%d etype=%s is_masked_op=0", + log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s is_masked_op=0", is_scatter, is_scatter ? "scatter" : "gather", num_elem, type2name(elem_bt)); - } return false; // not supported } } @@ -1537,11 +1390,9 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { // Check that the vector holding indices is supported by architecture // For sub-word gathers expander receive index array. if (!is_subword_type(elem_bt) && !arch_supports_vector(Op_LoadVector, num_elem, T_INT, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d op=%s/loadindex vlen=%d etype=int is_masked_op=%d", + log_if_needed(" ** not supported: arity=%d op=%s/loadindex vlen=%d etype=int is_masked_op=%d", is_scatter, is_scatter ? "scatter" : "gather", num_elem, is_masked_op ? 1 : 0); - } return false; // not supported } @@ -1559,11 +1410,9 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { // The array must be consistent with vector type if (arr_type == nullptr || (arr_type != nullptr && !elem_consistent_with_arr(elem_bt, arr_type, false))) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=%d op=%s vlen=%d etype=%s atype=%s ismask=no", + log_if_needed(" ** not supported: arity=%d op=%s vlen=%d etype=%s atype=%s ismask=no", is_scatter, is_scatter ? "scatter" : "gather", num_elem, type2name(elem_bt), type2name(arr_type->elem()->array_element_basic_type())); - } set_map(old_map); set_sp(old_sp); return false; @@ -1595,11 +1444,9 @@ bool LibraryCallKit::inline_vector_gather_scatter(bool is_scatter) { const TypeInstPtr* mbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, mbox_klass); mask = unbox_vector(is_scatter ? argument(10) : argument(9), mbox_type, elem_bt, num_elem); if (mask == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed mask=%s", + log_if_needed(" ** unbox failed mask=%s", is_scatter ? NodeClassNames[argument(10)->Opcode()] : NodeClassNames[argument(9)->Opcode()]); - } set_map(old_map); set_sp(old_sp); return false; @@ -1669,26 +1516,20 @@ bool LibraryCallKit::inline_vector_reduction() { if (opr == nullptr || vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr || !opr->is_con() || vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: opr=%s vclass=%s etype=%s vlen=%s", + log_if_needed(" ** missing constant: opr=%s vclass=%s etype=%s vlen=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(3)->Opcode()], NodeClassNames[argument(4)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } @@ -1696,23 +1537,17 @@ bool LibraryCallKit::inline_vector_reduction() { bool is_masked_op = vmask_type != TypePtr::NULL_PTR; if (is_masked_op) { if (mask_klass == nullptr || mask_klass->const_oop() == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: maskclass=%s", NodeClassNames[argument(2)->Opcode()]); - } + log_if_needed(" ** missing constant: maskclass=%s", NodeClassNames[argument(2)->Opcode()]); return false; // not enough info for intrinsification } if (!is_klass_initialized(mask_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** mask klass argument not initialized"); - } + log_if_needed(" ** mask klass argument not initialized"); return false; } if (vmask_type->maybe_null()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** null mask values are not allowed for masked op"); - } + log_if_needed(" ** null mask values are not allowed for masked op"); return false; } } @@ -1724,20 +1559,16 @@ bool LibraryCallKit::inline_vector_reduction() { // When using mask, mask use type needs to be VecMaskUseLoad. if (!arch_supports_vector(sopc, num_elem, elem_bt, is_masked_op ? VecMaskUseLoad : VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=1 op=%d/reduce vlen=%d etype=%s is_masked_op=%d", + log_if_needed(" ** not supported: arity=1 op=%d/reduce vlen=%d etype=%s is_masked_op=%d", sopc, num_elem, type2name(elem_bt), is_masked_op ? 1 : 0); - } return false; } // Return true if current platform has implemented the masked operation with predicate feature. bool use_predicate = is_masked_op && arch_supports_vector(sopc, num_elem, elem_bt, VecMaskUsePred); if (is_masked_op && !use_predicate && !arch_supports_vector(Op_VectorBlend, num_elem, elem_bt, VecMaskUseLoad)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=1 op=%d/reduce vlen=%d etype=%s is_masked_op=1", + log_if_needed(" ** not supported: arity=1 op=%d/reduce vlen=%d etype=%s is_masked_op=1", sopc, num_elem, type2name(elem_bt)); - } return false; } @@ -1756,10 +1587,8 @@ bool LibraryCallKit::inline_vector_reduction() { const TypeInstPtr* mbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, mbox_klass); mask = unbox_vector(argument(6), mbox_type, elem_bt, num_elem); if (mask == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed mask=%s", + log_if_needed(" ** unbox failed mask=%s", NodeClassNames[argument(6)->Opcode()]); - } return false; } } @@ -1822,26 +1651,20 @@ bool LibraryCallKit::inline_vector_test() { if (cond == nullptr || vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr || !cond->is_con() || vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: cond=%s vclass=%s etype=%s vlen=%s", + log_if_needed(" ** missing constant: cond=%s vclass=%s etype=%s vlen=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(2)->Opcode()], NodeClassNames[argument(3)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } BasicType elem_bt = elem_type->basic_type(); @@ -1851,11 +1674,9 @@ bool LibraryCallKit::inline_vector_test() { const TypeInstPtr* vbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, vbox_klass); if (!arch_supports_vector(Op_VectorTest, num_elem, elem_bt, is_vector_mask(vbox_klass) ? VecMaskUseLoad : VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=2 op=test/%d vlen=%d etype=%s ismask=%d", + log_if_needed(" ** not supported: arity=2 op=test/%d vlen=%d etype=%s ismask=%d", cond->get_con(), num_elem, type2name(elem_bt), is_vector_mask(vbox_klass)); - } return false; } @@ -1900,26 +1721,20 @@ bool LibraryCallKit::inline_vector_blend() { } if (mask_klass->const_oop() == nullptr || vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: vclass=%s mclass=%s etype=%s vlen=%s", + log_if_needed(" ** missing constant: vclass=%s mclass=%s etype=%s vlen=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(2)->Opcode()], NodeClassNames[argument(3)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass) || !is_klass_initialized(mask_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } BasicType elem_bt = elem_type->basic_type(); @@ -1927,10 +1742,8 @@ bool LibraryCallKit::inline_vector_blend() { int num_elem = vlen->get_con(); if (!arch_supports_vector(Op_VectorBlend, num_elem, elem_bt, VecMaskUseLoad)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=2 op=blend vlen=%d etype=%s ismask=useload", + log_if_needed(" ** not supported: arity=2 op=blend vlen=%d etype=%s ismask=useload", num_elem, type2name(elem_bt)); - } return false; // not supported } ciKlass* vbox_klass = vector_klass->const_oop()->as_instance()->java_lang_Class_klass(); @@ -1974,27 +1787,21 @@ bool LibraryCallKit::inline_vector_compare() { } if (!cond->is_con() || vector_klass->const_oop() == nullptr || mask_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: cond=%s vclass=%s mclass=%s etype=%s vlen=%s", + log_if_needed(" ** missing constant: cond=%s vclass=%s mclass=%s etype=%s vlen=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(2)->Opcode()], NodeClassNames[argument(3)->Opcode()], NodeClassNames[argument(4)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass) || !is_klass_initialized(mask_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } @@ -2004,19 +1811,15 @@ bool LibraryCallKit::inline_vector_compare() { if ((cond->get_con() & BoolTest::unsigned_compare) != 0) { if (!Matcher::supports_vector_comparison_unsigned(num_elem, elem_bt)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: unsigned comparison op=comp/%d vlen=%d etype=%s ismask=usestore", + log_if_needed(" ** not supported: unsigned comparison op=comp/%d vlen=%d etype=%s ismask=usestore", cond->get_con() & (BoolTest::unsigned_compare - 1), num_elem, type2name(elem_bt)); - } return false; } } if (!arch_supports_vector(Op_VectorMaskCmp, num_elem, elem_bt, VecMaskUseStore)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=2 op=comp/%d vlen=%d etype=%s ismask=usestore", + log_if_needed(" ** not supported: arity=2 op=comp/%d vlen=%d etype=%s ismask=usestore", cond->get_con(), num_elem, type2name(elem_bt)); - } return false; } @@ -2032,19 +1835,15 @@ bool LibraryCallKit::inline_vector_compare() { bool is_masked_op = argument(7)->bottom_type() != TypePtr::NULL_PTR; Node* mask = is_masked_op ? unbox_vector(argument(7), mbox_type, elem_bt, num_elem) : nullptr; if (is_masked_op && mask == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: mask = null arity=2 op=comp/%d vlen=%d etype=%s ismask=usestore is_masked_op=1", + log_if_needed(" ** not supported: mask = null arity=2 op=comp/%d vlen=%d etype=%s ismask=usestore is_masked_op=1", cond->get_con(), num_elem, type2name(elem_bt)); - } return false; } bool use_predicate = is_masked_op && arch_supports_vector(Op_VectorMaskCmp, num_elem, elem_bt, VecMaskUsePred); if (is_masked_op && !use_predicate && !arch_supports_vector(Op_AndV, num_elem, elem_bt, VecMaskUseLoad)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=2 op=comp/%d vlen=%d etype=%s ismask=usestore is_masked_op=1", + log_if_needed(" ** not supported: arity=2 op=comp/%d vlen=%d etype=%s ismask=usestore is_masked_op=1", cond->get_con(), num_elem, type2name(elem_bt)); - } return false; } @@ -2097,27 +1896,21 @@ bool LibraryCallKit::inline_vector_rearrange() { vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: vclass=%s sclass=%s etype=%s vlen=%s", + log_if_needed(" ** missing constant: vclass=%s sclass=%s etype=%s vlen=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(3)->Opcode()], NodeClassNames[argument(4)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass) || !is_klass_initialized(shuffle_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } BasicType elem_bt = elem_type->basic_type(); @@ -2125,10 +1918,8 @@ bool LibraryCallKit::inline_vector_rearrange() { int num_elem = vlen->get_con(); if (!arch_supports_vector(Op_VectorLoadShuffle, num_elem, elem_bt, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=0 op=load/shuffle vlen=%d etype=%s ismask=no", + log_if_needed(" ** not supported: arity=0 op=load/shuffle vlen=%d etype=%s ismask=no", num_elem, type2name(elem_bt)); - } return false; // not supported } @@ -2138,9 +1929,7 @@ bool LibraryCallKit::inline_vector_rearrange() { (mask_klass == nullptr || mask_klass->const_oop() == nullptr || !is_klass_initialized(mask_klass))) { - if (C->print_intrinsics()) { - tty->print_cr(" ** mask_klass argument not initialized"); - } + log_if_needed(" ** mask_klass argument not initialized"); } VectorMaskUseType checkFlags = (VectorMaskUseType)(is_masked_op ? (VecMaskUseLoad | VecMaskUsePred) : VecMaskNotUsed); if (!arch_supports_vector(Op_VectorRearrange, num_elem, elem_bt, checkFlags)) { @@ -2149,10 +1938,8 @@ bool LibraryCallKit::inline_vector_rearrange() { (!arch_supports_vector(Op_VectorRearrange, num_elem, elem_bt, VecMaskNotUsed) || !arch_supports_vector(Op_VectorBlend, num_elem, elem_bt, VecMaskUseLoad) || !arch_supports_vector(Op_Replicate, num_elem, elem_bt, VecMaskNotUsed))) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=2 op=shuffle/rearrange vlen=%d etype=%s ismask=no", + log_if_needed(" ** not supported: arity=2 op=shuffle/rearrange vlen=%d etype=%s ismask=no", num_elem, type2name(elem_bt)); - } return false; // not supported } } @@ -2175,10 +1962,8 @@ bool LibraryCallKit::inline_vector_rearrange() { const TypeInstPtr* mbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, mbox_klass); mask = unbox_vector(argument(7), mbox_type, elem_bt, num_elem); if (mask == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=3 op=shuffle/rearrange vlen=%d etype=%s ismask=useload is_masked_op=1", + log_if_needed(" ** not supported: arity=3 op=shuffle/rearrange vlen=%d etype=%s ismask=useload is_masked_op=1", num_elem, type2name(elem_bt)); - } return false; } } @@ -2280,19 +2065,15 @@ bool LibraryCallKit::inline_vector_broadcast_int() { return false; // dead code } if (!opr->is_con() || vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: opr=%s vclass=%s etype=%s vlen=%s", + log_if_needed(" ** missing constant: opr=%s vclass=%s etype=%s vlen=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(3)->Opcode()], NodeClassNames[argument(4)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } @@ -2300,32 +2081,24 @@ bool LibraryCallKit::inline_vector_broadcast_int() { bool is_masked_op = vmask_type != TypePtr::NULL_PTR; if (is_masked_op) { if (mask_klass == nullptr || mask_klass->const_oop() == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: maskclass=%s", NodeClassNames[argument(2)->Opcode()]); - } + log_if_needed(" ** missing constant: maskclass=%s", NodeClassNames[argument(2)->Opcode()]); return false; // not enough info for intrinsification } if (!is_klass_initialized(mask_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** mask klass argument not initialized"); - } + log_if_needed(" ** mask klass argument not initialized"); return false; } if (vmask_type->maybe_null()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** null mask values are not allowed for masked op"); - } + log_if_needed(" ** null mask values are not allowed for masked op"); return false; } } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } @@ -2337,17 +2110,13 @@ bool LibraryCallKit::inline_vector_broadcast_int() { bool is_rotate = VectorNode::is_rotate_opcode(opc); if (opc == 0 || (!is_shift && !is_rotate)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** operation not supported: op=%d bt=%s", opr->get_con(), type2name(elem_bt)); - } + log_if_needed(" ** operation not supported: op=%d bt=%s", opr->get_con(), type2name(elem_bt)); return false; // operation not supported } int sopc = VectorNode::opcode(opc, elem_bt); if (sopc == 0) { - if (C->print_intrinsics()) { - tty->print_cr(" ** operation not supported: opc=%s bt=%s", NodeClassNames[opc], type2name(elem_bt)); - } + log_if_needed(" ** operation not supported: opc=%s bt=%s", NodeClassNames[opc], type2name(elem_bt)); return false; // operation not supported } @@ -2370,10 +2139,8 @@ bool LibraryCallKit::inline_vector_broadcast_int() { (!arch_supports_vector(sopc, num_elem, elem_bt, VecMaskNotUsed, has_scalar_args) || !arch_supports_vector(Op_VectorBlend, num_elem, elem_bt, VecMaskUseLoad))) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=0 op=int/%d vlen=%d etype=%s is_masked_op=%d", + log_if_needed(" ** not supported: arity=0 op=int/%d vlen=%d etype=%s is_masked_op=%d", sopc, num_elem, type2name(elem_bt), is_masked_op ? 1 : 0); - } return false; // not supported } } @@ -2404,9 +2171,7 @@ bool LibraryCallKit::inline_vector_broadcast_int() { const TypeInstPtr* mbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, mbox_klass); mask = unbox_vector(argument(7), mbox_type, elem_bt, num_elem); if (mask == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed mask=%s", NodeClassNames[argument(7)->Opcode()]); - } + log_if_needed(" ** unbox failed mask=%s", NodeClassNames[argument(7)->Opcode()]); return false; } } @@ -2456,8 +2221,7 @@ bool LibraryCallKit::inline_vector_convert() { if (!opr->is_con() || vector_klass_from->const_oop() == nullptr || elem_klass_from->const_oop() == nullptr || !vlen_from->is_con() || vector_klass_to->const_oop() == nullptr || elem_klass_to->const_oop() == nullptr || !vlen_to->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: opr=%s vclass_from=%s etype_from=%s vlen_from=%s vclass_to=%s etype_to=%s vlen_to=%s", + log_if_needed(" ** missing constant: opr=%s vclass_from=%s etype_from=%s vlen_from=%s vclass_to=%s etype_to=%s vlen_to=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(2)->Opcode()], @@ -2465,13 +2229,10 @@ bool LibraryCallKit::inline_vector_convert() { NodeClassNames[argument(4)->Opcode()], NodeClassNames[argument(5)->Opcode()], NodeClassNames[argument(6)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass_from) || !is_klass_initialized(vector_klass_to)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } @@ -2508,11 +2269,9 @@ bool LibraryCallKit::inline_vector_convert() { num_elem_from, elem_bt_from, is_mask ? VecMaskUseAll : VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=1 op=%s/1 vlen1=%d etype1=%s ismask=%d", + log_if_needed(" ** not supported: arity=1 op=%s/1 vlen1=%d etype1=%s ismask=%d", is_cast ? "cast" : "reinterpret", num_elem_from, type2name(elem_bt_from), is_mask); - } return false; } @@ -2521,11 +2280,9 @@ bool LibraryCallKit::inline_vector_convert() { num_elem_to, elem_bt_to, is_mask ? VecMaskUseAll : VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=1 op=%s/2 vlen2=%d etype2=%s ismask=%d", + log_if_needed(" ** not supported: arity=1 op=%s/2 vlen2=%d etype2=%s ismask=%d", is_cast ? "cast" : "reinterpret", num_elem_to, type2name(elem_bt_to), is_mask); - } return false; } @@ -2565,10 +2322,8 @@ bool LibraryCallKit::inline_vector_convert() { // Make sure that vector cast is implemented to particular type/size combination if it is // not a mask casting. if (!is_mask && !arch_supports_vector(cast_vopc, num_elem_to, elem_bt_to, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=1 op=cast#%d/3 vlen2=%d etype2=%s ismask=%d", + log_if_needed(" ** not supported: arity=1 op=cast#%d/3 vlen2=%d etype2=%s ismask=%d", cast_vopc, num_elem_to, type2name(elem_bt_to), is_mask); - } return false; } @@ -2580,11 +2335,9 @@ bool LibraryCallKit::inline_vector_convert() { // It is possible that arch does not support this intermediate vector size // TODO More complex logic required here to handle this corner case for the sizes. if (!arch_supports_vector(cast_vopc, num_elem_for_cast, elem_bt_to, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=1 op=cast#%d/4 vlen1=%d etype2=%s ismask=%d", + log_if_needed(" ** not supported: arity=1 op=cast#%d/4 vlen1=%d etype2=%s ismask=%d", cast_vopc, num_elem_for_cast, type2name(elem_bt_to), is_mask); - } return false; } @@ -2602,10 +2355,8 @@ bool LibraryCallKit::inline_vector_convert() { num_elem_for_resize, elem_bt_from, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=1 op=cast/5 vlen2=%d etype1=%s ismask=%d", + log_if_needed(" ** not supported: arity=1 op=cast/5 vlen2=%d etype1=%s ismask=%d", num_elem_for_resize, type2name(elem_bt_from), is_mask); - } return false; } @@ -2616,10 +2367,8 @@ bool LibraryCallKit::inline_vector_convert() { if (is_mask) { // Make sure that cast for vector mask is implemented to particular type/size combination. if (!arch_supports_vector(Op_VectorMaskCast, num_elem_to, elem_bt_to, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=1 op=maskcast vlen2=%d etype2=%s ismask=%d", + log_if_needed(" ** not supported: arity=1 op=maskcast vlen2=%d etype2=%s ismask=%d", num_elem_to, type2name(elem_bt_to), is_mask); - } return false; } op = gvn().transform(new VectorMaskCastNode(op, dst_type)); @@ -2657,35 +2406,27 @@ bool LibraryCallKit::inline_vector_insert() { return false; // dead code } if (vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con() || !idx->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: vclass=%s etype=%s vlen=%s idx=%s", + log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s idx=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(2)->Opcode()], NodeClassNames[argument(4)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } BasicType elem_bt = elem_type->basic_type(); int num_elem = vlen->get_con(); if (!arch_supports_vector(Op_VectorInsert, num_elem, elem_bt, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=1 op=insert vlen=%d etype=%s ismask=no", + log_if_needed(" ** not supported: arity=1 op=insert vlen=%d etype=%s ismask=no", num_elem, type2name(elem_bt)); - } return false; // not supported } @@ -2751,25 +2492,19 @@ bool LibraryCallKit::inline_vector_extract() { return false; // dead code } if (vector_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: vclass=%s etype=%s vlen=%s", + log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(2)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } BasicType elem_bt = elem_type->basic_type(); @@ -2807,26 +2542,20 @@ bool LibraryCallKit::inline_vector_extract() { opd = gvn().transform(new URShiftLNode(opd, pos)); opd = gvn().transform(new AndLNode(opd, gvn().makecon(TypeLong::ONE))); } else { - if (C->print_intrinsics()) { - tty->print_cr(" ** Rejected mask extraction because architecture does not support it"); - } + log_if_needed(" ** Rejected mask extraction because architecture does not support it"); return false; // not supported } } else { // vbox_klass is vector. This is used for Vector.lane(int). if (!idx->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: idx=%s", NodeClassNames[argument(4)->Opcode()]); - } + log_if_needed(" ** missing constant: idx=%s", NodeClassNames[argument(4)->Opcode()]); return false; // not enough info for intrinsification } int vopc = ExtractNode::opcode(elem_bt); if (!arch_supports_vector(vopc, num_elem, elem_bt, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: arity=1 op=extract vlen=%d etype=%s ismask=no", + log_if_needed(" ** not supported: arity=1 op=extract vlen=%d etype=%s ismask=no", num_elem, type2name(elem_bt)); - } return false; // not supported } @@ -2882,29 +2611,23 @@ bool LibraryCallKit::inline_vector_compress_expand() { if (vector_klass == nullptr || elem_klass == nullptr || mask_klass == nullptr || vlen == nullptr || vector_klass->const_oop() == nullptr || mask_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con() || !opr->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: opr=%s vclass=%s mclass=%s etype=%s vlen=%s", + log_if_needed(" ** missing constant: opr=%s vclass=%s mclass=%s etype=%s vlen=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(2)->Opcode()], NodeClassNames[argument(3)->Opcode()], NodeClassNames[argument(4)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass) || !is_klass_initialized(mask_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } @@ -2913,10 +2636,8 @@ bool LibraryCallKit::inline_vector_compress_expand() { int opc = VectorSupport::vop2ideal(opr->get_con(), elem_bt); if (!arch_supports_vector(opc, num_elem, elem_bt, VecMaskUseLoad)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: opc=%d vlen=%d etype=%s ismask=useload", + log_if_needed(" ** not supported: opc=%d vlen=%d etype=%s ismask=useload", opc, num_elem, type2name(elem_bt)); - } return false; // not supported } @@ -2927,10 +2648,8 @@ bool LibraryCallKit::inline_vector_compress_expand() { vbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, vbox_klass); opd1 = unbox_vector(argument(5), vbox_type, elem_bt, num_elem); if (opd1 == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed vector=%s", + log_if_needed(" ** unbox failed vector=%s", NodeClassNames[argument(5)->Opcode()]); - } return false; } } @@ -2941,10 +2660,8 @@ bool LibraryCallKit::inline_vector_compress_expand() { Node* mask = unbox_vector(argument(6), mbox_type, elem_bt, num_elem); if (mask == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed mask=%s", + log_if_needed(" ** unbox failed mask=%s", NodeClassNames[argument(6)->Opcode()]); - } return false; } @@ -2975,27 +2692,21 @@ bool LibraryCallKit::inline_index_vector() { if (vector_klass == nullptr || elem_klass == nullptr || vlen == nullptr || vector_klass->const_oop() == nullptr || !vlen->is_con() || elem_klass->const_oop() == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: vclass=%s etype=%s vlen=%s", + log_if_needed(" ** missing constant: vclass=%s etype=%s vlen=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(2)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(vector_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } @@ -3004,9 +2715,7 @@ bool LibraryCallKit::inline_index_vector() { // Check whether the iota index generation op is supported by the current hardware if (!arch_supports_vector(Op_VectorLoadConst, num_elem, elem_bt, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: vlen=%d etype=%s", num_elem, type2name(elem_bt)); - } + log_if_needed(" ** not supported: vlen=%d etype=%s", num_elem, type2name(elem_bt)); return false; // not supported } @@ -3021,9 +2730,7 @@ bool LibraryCallKit::inline_index_vector() { } else { // Check whether the vector multiply op is supported by the current hardware if (!arch_supports_vector(vmul_op, num_elem, elem_bt, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: vlen=%d etype=%s", num_elem, type2name(elem_bt)); - } + log_if_needed(" ** not supported: vlen=%d etype=%s", num_elem, type2name(elem_bt)); return false; // not supported } @@ -3032,10 +2739,8 @@ bool LibraryCallKit::inline_index_vector() { int cast_op = elem_bt == T_LONG ? Op_ConvI2L : elem_bt == T_FLOAT? Op_ConvI2F : Op_ConvI2D; if (!Matcher::match_rule_supported(cast_op)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** Rejected op (%s) because architecture does not support it", + log_if_needed(" ** Rejected op (%s) because architecture does not support it", NodeClassNames[cast_op]); - } return false; // not supported } } @@ -3045,10 +2750,8 @@ bool LibraryCallKit::inline_index_vector() { const TypeInstPtr* vbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, vbox_klass); Node* opd = unbox_vector(argument(3), vbox_type, elem_bt, num_elem); if (opd == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** unbox failed vector=%s", + log_if_needed(" ** unbox failed vector=%s", NodeClassNames[argument(3)->Opcode()]); - } return false; } @@ -3061,9 +2764,7 @@ bool LibraryCallKit::inline_index_vector() { } else { // Check whether the vector addition op is supported by the current hardware if (!arch_supports_vector(vadd_op, num_elem, elem_bt, VecMaskNotUsed)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: vlen=%d etype=%s", num_elem, type2name(elem_bt)); - } + log_if_needed(" ** not supported: vlen=%d etype=%s", num_elem, type2name(elem_bt)); return false; // not supported } } @@ -3124,27 +2825,21 @@ bool LibraryCallKit::inline_index_partially_in_upper_range() { if (mask_klass == nullptr || elem_klass == nullptr || vlen == nullptr || mask_klass->const_oop() == nullptr || elem_klass->const_oop() == nullptr || !vlen->is_con()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** missing constant: mclass=%s etype=%s vlen=%s", + log_if_needed(" ** missing constant: mclass=%s etype=%s vlen=%s", NodeClassNames[argument(0)->Opcode()], NodeClassNames[argument(1)->Opcode()], NodeClassNames[argument(2)->Opcode()]); - } return false; // not enough info for intrinsification } if (!is_klass_initialized(mask_klass)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** klass argument not initialized"); - } + log_if_needed(" ** klass argument not initialized"); return false; } ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type(); if (!elem_type->is_primitive_type()) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not a primitive bt=%d", elem_type->basic_type()); - } + log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type()); return false; // should be primitive type } @@ -3157,9 +2852,7 @@ bool LibraryCallKit::inline_index_partially_in_upper_range() { if (!arch_supports_vector(Op_VectorLoadConst, num_elem, elem_bt, VecMaskNotUsed) || !arch_supports_vector(Op_Replicate, num_elem, elem_bt, VecMaskNotUsed) || !arch_supports_vector(Op_VectorMaskCmp, num_elem, elem_bt, VecMaskUseStore)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** not supported: vlen=%d etype=%s", num_elem, type2name(elem_bt)); - } + log_if_needed(" ** not supported: vlen=%d etype=%s", num_elem, type2name(elem_bt)); return false; // not supported } @@ -3168,10 +2861,8 @@ bool LibraryCallKit::inline_index_partially_in_upper_range() { int cast_op = is_integral_type(elem_bt) ? Op_ConvL2I : (elem_bt == T_FLOAT ? Op_ConvL2F : Op_ConvL2D); if (!Matcher::match_rule_supported(cast_op)) { - if (C->print_intrinsics()) { - tty->print_cr(" ** Rejected op (%s) because architecture does not support it", + log_if_needed(" ** Rejected op (%s) because architecture does not support it", NodeClassNames[cast_op]); - } return false; // not supported } } @@ -3180,9 +2871,7 @@ bool LibraryCallKit::inline_index_partially_in_upper_range() { Node* offset = argument(3); Node* limit = argument(5); if (offset == nullptr || limit == nullptr) { - if (C->print_intrinsics()) { - tty->print_cr(" ** offset or limit argument is null"); - } + log_if_needed(" ** offset or limit argument is null"); return false; // not supported } @@ -3238,3 +2927,6 @@ bool LibraryCallKit::inline_index_partially_in_upper_range() { C->set_max_vector_size(MAX2(C->max_vector_size(), (uint)(num_elem * type2aelembytes(elem_bt)))); return true; } + +#undef non_product_log_if_needed +#undef log_if_needed diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index 5a87e16c855b2..c2b6d27986b94 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -929,7 +929,9 @@ class JvmtiClassFileLoadHookPoster : public StackObj { _cached_class_file_ptr = cache_ptr; _has_been_modified = false; - assert(!_thread->is_in_any_VTMS_transition(), "CFLH events are not allowed in any VTMS transition"); + if (_thread->is_in_any_VTMS_transition()) { + return; // no events should be posted if thread is in any VTMS transition + } _state = JvmtiExport::get_jvmti_thread_state(_thread); if (_state != nullptr) { _class_being_redefined = _state->get_class_being_redefined(); @@ -1366,10 +1368,9 @@ void JvmtiExport::post_class_load(JavaThread *thread, Klass* klass) { if (state == nullptr) { return; } - if (thread->is_in_tmp_VTMS_transition()) { - return; // skip ClassLoad events in tmp VTMS transition + if (thread->is_in_any_VTMS_transition()) { + return; // no events should be posted if thread is in any VTMS transition } - assert(!thread->is_in_any_VTMS_transition(), "class load events are not allowed in any VTMS transition"); EVT_TRIG_TRACE(JVMTI_EVENT_CLASS_LOAD, ("[%s] Trg Class Load triggered", JvmtiTrace::safe_get_thread_name(thread))); @@ -1404,10 +1405,9 @@ void JvmtiExport::post_class_prepare(JavaThread *thread, Klass* klass) { if (state == nullptr) { return; } - if (thread->is_in_tmp_VTMS_transition()) { - return; // skip ClassPrepare events in tmp VTMS transition + if (thread->is_in_any_VTMS_transition()) { + return; // no events should be posted if thread is in any VTMS transition } - assert(!thread->is_in_any_VTMS_transition(), "class prepare events are not allowed in any VTMS transition"); EVT_TRIG_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("[%s] Trg Class Prepare triggered", JvmtiTrace::safe_get_thread_name(thread))); diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 7a4a59a855315..53a0f2e9c3b51 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -35,6 +35,7 @@ #include "compiler/compilationPolicy.hpp" #include "compiler/compilerDefinitions.inline.hpp" #include "gc/shared/collectedHeap.hpp" +#include "gc/shared/memAllocator.hpp" #include "interpreter/bytecode.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/interpreter.hpp" @@ -535,7 +536,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread #if COMPILER2_OR_JVMCI if ((jvmci_enabled COMPILER2_PRESENT( || ((DoEscapeAnalysis || EliminateNestedLocks) && EliminateLocks) )) && !EscapeBarrier::objs_are_deoptimized(current, deoptee.id())) { - bool unused; + bool unused = false; restore_eliminated_locks(current, chunk, realloc_failures, deoptee, exec_mode, unused); } #endif // COMPILER2_OR_JVMCI @@ -1237,6 +1238,7 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap* InstanceKlass* ik = InstanceKlass::cast(k); if (obj == nullptr && !cache_init_error) { + InternalOOMEMark iom(THREAD); #if COMPILER2_OR_JVMCI if (EnableVectorSupport && VectorSupport::is_vector(ik)) { obj = VectorSupport::allocate_vector(ik, fr, reg_map, sv, THREAD); @@ -1251,9 +1253,11 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap* TypeArrayKlass* ak = TypeArrayKlass::cast(k); assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length"); int len = sv->field_size() / type2size[ak->element_type()]; + InternalOOMEMark iom(THREAD); obj = ak->allocate(len, THREAD); } else if (k->is_objArray_klass()) { ObjArrayKlass* ak = ObjArrayKlass::cast(k); + InternalOOMEMark iom(THREAD); obj = ak->allocate(sv->field_size(), THREAD); } @@ -1732,7 +1736,7 @@ void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* ObjectSynchronizer::exit(src->obj(), src->lock(), thread); } } - array->element(i)->free_monitors(thread); + array->element(i)->free_monitors(); #ifdef ASSERT array->element(i)->set_removed_monitors(); #endif diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 2e40c99455c9d..97be533341364 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -430,8 +430,6 @@ JavaThread::JavaThread() : _active_handles(nullptr), _free_handle_block(nullptr), - _monitor_chunks(nullptr), - _suspend_flags(0), _thread_state(_thread_new), @@ -456,11 +454,11 @@ JavaThread::JavaThread() : #endif #endif _jni_attach_state(_not_attaching_via_jni), + _is_in_internal_oome_mark(false), #if INCLUDE_JVMCI _pending_deoptimization(-1), _pending_monitorenter(false), _pending_transfer_to_interpreter(false), - _in_retryable_allocation(false), _pending_failed_speculation(0), _jvmci{nullptr}, _libjvmci_runtime(nullptr), @@ -1050,13 +1048,7 @@ JavaThread* JavaThread::active() { bool JavaThread::is_lock_owned(address adr) const { assert(LockingMode != LM_LIGHTWEIGHT, "should not be called with new lightweight locking"); - if (Thread::is_lock_owned(adr)) return true; - - for (MonitorChunk* chunk = monitor_chunks(); chunk != nullptr; chunk = chunk->next()) { - if (chunk->contains(adr)) return true; - } - - return false; + return is_in_full_stack(adr); } oop JavaThread::exception_oop() const { @@ -1067,22 +1059,6 @@ void JavaThread::set_exception_oop(oop o) { Atomic::store(&_exception_oop, o); } -void JavaThread::add_monitor_chunk(MonitorChunk* chunk) { - chunk->set_next(monitor_chunks()); - set_monitor_chunks(chunk); -} - -void JavaThread::remove_monitor_chunk(MonitorChunk* chunk) { - guarantee(monitor_chunks() != nullptr, "must be non empty"); - if (monitor_chunks() == chunk) { - set_monitor_chunks(chunk->next()); - } else { - MonitorChunk* prev = monitor_chunks(); - while (prev->next() != chunk) prev = prev->next(); - prev->set_next(chunk->next()); - } -} - void JavaThread::handle_special_runtime_exit_condition() { if (is_obj_deopt_suspend()) { frame_anchor()->make_walkable(); @@ -1408,13 +1384,6 @@ void JavaThread::oops_do_no_frames(OopClosure* f, NMethodClosure* cf) { DEBUG_ONLY(verify_frame_info();) - if (has_last_Java_frame()) { - // Traverse the monitor chunks - for (MonitorChunk* chunk = monitor_chunks(); chunk != nullptr; chunk = chunk->next()) { - chunk->oops_do(f); - } - } - assert(vframe_array_head() == nullptr, "deopt in progress at a safepoint!"); // If we have deferred set_locals there might be oops waiting to be // written diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index 6b6c9139b78eb..2541aaded00a3 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -52,6 +52,7 @@ class AsyncExceptionHandshake; class ContinuationEntry; class DeoptResourceMark; +class InternalOOMEMark; class JNIHandleBlock; class JVMCIRuntime; @@ -192,10 +193,6 @@ class JavaThread: public Thread { void pop_jni_handle_block(); private: - MonitorChunk* _monitor_chunks; // Contains the off stack monitors - // allocated during deoptimization - // and by JNI_MonitorEnter/Exit - enum SuspendFlags { // NOTE: avoid using the sign-bit as cc generates different test code // when the sign-bit is used, and sometimes incorrectly - see CR 6398077 @@ -335,6 +332,8 @@ class JavaThread: public Thread { // of _attaching_via_jni and transitions to _attached_via_jni. volatile JNIAttachStates _jni_attach_state; + // In scope of an InternalOOMEMark? + bool _is_in_internal_oome_mark; #if INCLUDE_JVMCI // The _pending_* fields below are used to communicate extra information @@ -350,10 +349,6 @@ class JavaThread: public Thread { // Specifies if the DeoptReason for the last uncommon trap was Reason_transfer_to_interpreter bool _pending_transfer_to_interpreter; - // True if in a runtime call from compiled code that will deoptimize - // and re-execute a failed heap allocation in the interpreter. - bool _in_retryable_allocation; - // An id of a speculation that JVMCI compiled code can use to further describe and // uniquely identify the speculative optimization guarded by an uncommon trap. // See JVMCINMethodData::SPECULATION_LENGTH_BITS for further details. @@ -680,7 +675,7 @@ class JavaThread: public Thread { return (_suspend_flags & (_obj_deopt JFR_ONLY(| _trace_flag))) != 0; } - // Fast-locking support + // Stack-locking support (not for LM_LIGHTWEIGHT) bool is_lock_owned(address adr) const; // Accessors for vframe array top @@ -718,6 +713,10 @@ class JavaThread: public Thread { MemRegion deferred_card_mark() const { return _deferred_card_mark; } void set_deferred_card_mark(MemRegion mr) { _deferred_card_mark = mr; } + // Is thread in scope of an InternalOOMEMark? + bool is_in_internal_oome_mark() const { return _is_in_internal_oome_mark; } + void set_is_in_internal_oome_mark(bool b) { _is_in_internal_oome_mark = b; } + #if INCLUDE_JVMCI jlong pending_failed_speculation() const { return _pending_failed_speculation; } void set_pending_monitorenter(bool b) { _pending_monitorenter = b; } @@ -727,9 +726,6 @@ class JavaThread: public Thread { void set_jvmci_alternate_call_target(address a) { assert(_jvmci._alternate_call_target == nullptr, "must be"); _jvmci._alternate_call_target = a; } void set_jvmci_implicit_exception_pc(address a) { assert(_jvmci._implicit_exception_pc == nullptr, "must be"); _jvmci._implicit_exception_pc = a; } - virtual bool in_retryable_allocation() const { return _in_retryable_allocation; } - void set_in_retryable_allocation(bool b) { _in_retryable_allocation = b; } - JVMCIRuntime* libjvmci_runtime() const { return _libjvmci_runtime; } void set_libjvmci_runtime(JVMCIRuntime* rt) { assert((_libjvmci_runtime == nullptr && rt != nullptr) || (_libjvmci_runtime != nullptr && rt == nullptr), "must be"); @@ -881,13 +877,7 @@ class JavaThread: public Thread { int depth_first_number() { return _depth_first_number; } void set_depth_first_number(int dfn) { _depth_first_number = dfn; } - private: - void set_monitor_chunks(MonitorChunk* monitor_chunks) { _monitor_chunks = monitor_chunks; } - public: - MonitorChunk* monitor_chunks() const { return _monitor_chunks; } - void add_monitor_chunk(MonitorChunk* chunk); - void remove_monitor_chunk(MonitorChunk* chunk); bool in_deopt_handler() const { return _in_deopt_handler > 0; } void inc_in_deopt_handler() { _in_deopt_handler++; } void dec_in_deopt_handler() { diff --git a/src/hotspot/share/runtime/monitorChunk.cpp b/src/hotspot/share/runtime/monitorChunk.cpp index c54ad685cdbbb..d18fc21d78d93 100644 --- a/src/hotspot/share/runtime/monitorChunk.cpp +++ b/src/hotspot/share/runtime/monitorChunk.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -30,7 +30,6 @@ MonitorChunk::MonitorChunk(int number_on_monitors) { _number_of_monitors = number_on_monitors; _monitors = NEW_C_HEAP_ARRAY(BasicObjectLock, number_on_monitors, mtSynchronizer); - _next = nullptr; } diff --git a/src/hotspot/share/runtime/monitorChunk.hpp b/src/hotspot/share/runtime/monitorChunk.hpp index f16aa46fa6411..5c804b5c595ef 100644 --- a/src/hotspot/share/runtime/monitorChunk.hpp +++ b/src/hotspot/share/runtime/monitorChunk.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -38,23 +38,17 @@ class MonitorChunk: public CHeapObj { int _number_of_monitors; BasicObjectLock* _monitors; BasicObjectLock* monitors() const { return _monitors; } - MonitorChunk* _next; public: // Constructor MonitorChunk(int number_on_monitors); ~MonitorChunk(); - // link operations - MonitorChunk* next() const { return _next; } - void set_next(MonitorChunk* next) { _next = next; } - // Returns the number of monitors int number_of_monitors() const { return _number_of_monitors; } // Returns the index'th monitor BasicObjectLock* at(int index) { assert(index >= 0 && index < number_of_monitors(), "out of bounds check"); return &monitors()[index]; } - // Memory management void oops_do(OopClosure* f); diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index f8d4b32315665..27b4163238aa9 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1056,7 +1056,9 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) { } // Fall thru so we only have one place that installs the hash in // the ObjectMonitor. - } else if (LockingMode == LM_LEGACY && mark.has_locker() && current->is_lock_owned((address)mark.locker())) { + } else if (LockingMode == LM_LEGACY && mark.has_locker() + && current->is_Java_thread() + && JavaThread::cast(current)->is_lock_owned((address)mark.locker())) { // This is a stack-lock owned by the calling thread so fetch the // displaced markWord from the BasicLock on the stack. temp = mark.displaced_mark_helper(); diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 396f349a8856b..d98fcf6f664a2 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -24,6 +24,7 @@ */ #include "precompiled.hpp" +#include "cds/cdsConfig.hpp" #include "classfile/javaClasses.hpp" #include "classfile/javaThreadStatus.hpp" #include "gc/shared/barrierSet.hpp" @@ -103,7 +104,10 @@ Thread::Thread() { _vm_error_callbacks = nullptr; // thread-specific hashCode stream generator state - Marsaglia shift-xor form - _hashStateX = os::random(); + // If we are dumping, keep ihashes constant. Note that during dumping we only + // ever run one java thread, and no other thread should generate ihashes either, + // so using a constant seed should work fine. + _hashStateX = CDSConfig::is_dumping_static_archive() ? 0x12345678 : os::random(); _hashStateY = 842502087; _hashStateZ = 0x8767; // (int)(3579807591LL & 0xffff) ; _hashStateW = 273326509; @@ -527,16 +531,6 @@ void Thread::print_owned_locks_on(outputStream* st) const { } #endif // ASSERT -// We had to move these methods here, because vm threads get into ObjectSynchronizer::enter -// However, there is a note in JavaThread::is_lock_owned() about the VM threads not being -// used for compilation in the future. If that change is made, the need for these methods -// should be revisited, and they should be removed if possible. - -bool Thread::is_lock_owned(address adr) const { - assert(LockingMode != LM_LIGHTWEIGHT, "should not be called with new lightweight locking"); - return is_in_full_stack(adr); -} - bool Thread::set_as_starting_thread() { assert(_starting_thread == nullptr, "already initialized: " "_starting_thread=" INTPTR_FORMAT, p2i(_starting_thread)); diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index a3d6e091d28fa..d0749b8101d85 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -210,14 +210,6 @@ class Thread: public ThreadShadow { DEBUG_ONLY(bool _indirectly_safepoint_thread;) public: - // Determines if a heap allocation failure will be retried - // (e.g., by deoptimizing and re-executing in the interpreter). - // In this case, the failed allocation must raise - // Universe::out_of_memory_error_retry() and omit side effects - // such as JVMTI events and handling -XX:+HeapDumpOnOutOfMemoryError - // and -XX:OnOutOfMemoryError. - virtual bool in_retryable_allocation() const { return false; } - #ifdef ASSERT void set_suspendible_thread() { _suspendible_thread = true; } void clear_suspendible_thread() { _suspendible_thread = false; } @@ -483,9 +475,6 @@ class Thread: public ThreadShadow { } public: - // Used by fast lock support - virtual bool is_lock_owned(address adr) const; - // Check if address is within the given range of this thread's // stack: stack_base() > adr >= limit bool is_in_stack_range_incl(address adr, address limit) const { diff --git a/src/hotspot/share/runtime/vframeArray.cpp b/src/hotspot/share/runtime/vframeArray.cpp index cf7b087887fbd..d3bbbc283992a 100644 --- a/src/hotspot/share/runtime/vframeArray.cpp +++ b/src/hotspot/share/runtime/vframeArray.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -37,6 +37,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/monitorChunk.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/synchronizer.hpp" #include "runtime/vframe.hpp" #include "runtime/vframeArray.hpp" #include "runtime/vframe_hp.hpp" @@ -48,11 +49,10 @@ int vframeArrayElement:: bci(void) const { return (_bci == SynchronizationEntryBCI ? 0 : _bci); } -void vframeArrayElement::free_monitors(JavaThread* jt) { +void vframeArrayElement::free_monitors() { if (_monitors != nullptr) { MonitorChunk* chunk = _monitors; _monitors = nullptr; - jt->remove_monitor_chunk(chunk); delete chunk; } } @@ -72,7 +72,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) { int index; { - Thread* current_thread = Thread::current(); + JavaThread* current_thread = JavaThread::current(); ResourceMark rm(current_thread); HandleMark hm(current_thread); @@ -85,7 +85,6 @@ void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) { // Allocate monitor chunk _monitors = new MonitorChunk(list->length()); - vf->thread()->add_monitor_chunk(_monitors); // Migrate the BasicLocks from the stack to the monitor chunk for (index = 0; index < list->length(); index++) { @@ -95,9 +94,16 @@ void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) { if (monitor->owner_is_scalar_replaced()) { dest->set_obj(nullptr); } else { - assert(monitor->owner() == nullptr || !monitor->owner()->is_unlocked(), "object must be null or locked"); + assert(monitor->owner() != nullptr, "monitor owner must not be null"); + assert(!monitor->owner()->is_unlocked(), "monitor must be locked"); dest->set_obj(monitor->owner()); + assert(ObjectSynchronizer::current_thread_holds_lock(current_thread, Handle(current_thread, dest->obj())), + "should be held, before move_to"); + monitor->lock()->move_to(monitor->owner(), dest->lock()); + + assert(ObjectSynchronizer::current_thread_holds_lock(current_thread, Handle(current_thread, dest->obj())), + "should be held, after move_to"); } } } @@ -308,7 +314,11 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, top = iframe()->previous_monitor_in_interpreter_frame(top); BasicObjectLock* src = _monitors->at(index); top->set_obj(src->obj()); + assert(src->obj() != nullptr || ObjectSynchronizer::current_thread_holds_lock(thread, Handle(thread, src->obj())), + "should be held, before move_to"); src->lock()->move_to(src->obj(), top->lock()); + assert(src->obj() != nullptr || ObjectSynchronizer::current_thread_holds_lock(thread, Handle(thread, src->obj())), + "should be held, after move_to"); } if (ProfileInterpreter) { iframe()->interpreter_frame_set_mdp(0); // clear out the mdp. @@ -649,9 +659,8 @@ void vframeArray::unpack_to_stack(frame &unpack_frame, int exec_mode, int caller } void vframeArray::deallocate_monitor_chunks() { - JavaThread* jt = JavaThread::current(); for (int index = 0; index < frames(); index++ ) { - element(index)->free_monitors(jt); + element(index)->free_monitors(); } } diff --git a/src/hotspot/share/runtime/vframeArray.hpp b/src/hotspot/share/runtime/vframeArray.hpp index 734703a94ae6f..b270046252dba 100644 --- a/src/hotspot/share/runtime/vframeArray.hpp +++ b/src/hotspot/share/runtime/vframeArray.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -77,7 +77,7 @@ class vframeArrayElement { MonitorChunk* monitors(void) const { return _monitors; } - void free_monitors(JavaThread* jt); + void free_monitors(); StackValueCollection* locals(void) const { return _locals; } diff --git a/src/hotspot/share/utilities/chunkedList.hpp b/src/hotspot/share/utilities/chunkedList.hpp index 81898ac53b268..9a600e4ce1b50 100644 --- a/src/hotspot/share/utilities/chunkedList.hpp +++ b/src/hotspot/share/utilities/chunkedList.hpp @@ -44,7 +44,7 @@ template class ChunkedList : public CHeapObj { } public: - ChunkedList() : _top(_values), _next_used(nullptr), _next_free(nullptr) {} + ChunkedList() : _top(_values), _next_used(nullptr), _next_free(nullptr) {} bool is_full() const { return _top == end(); diff --git a/src/hotspot/share/utilities/events.hpp b/src/hotspot/share/utilities/events.hpp index 0aefbbefd2bb1..4470002a1e367 100644 --- a/src/hotspot/share/utilities/events.hpp +++ b/src/hotspot/share/utilities/events.hpp @@ -99,7 +99,7 @@ template class EventLogBase : public EventLog { EventRecord* _records; public: - EventLogBase(const char* name, const char* handle, int length = LogEventsBufferEntries): + EventLogBase(const char* name, const char* handle, int length = LogEventsBufferEntries): _mutex(Mutex::event, name), _name(name), _handle(handle), diff --git a/src/hotspot/share/utilities/istream.cpp b/src/hotspot/share/utilities/istream.cpp new file mode 100644 index 0000000000000..cb082128c62ca --- /dev/null +++ b/src/hotspot/share/utilities/istream.cpp @@ -0,0 +1,368 @@ +/* + * 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. + * + */ + +#include "precompiled.hpp" +#include "memory/allocation.inline.hpp" +#include "runtime/orderAccess.hpp" +#include "utilities/istream.hpp" +#include "utilities/ostream.hpp" +#include "utilities/xmlstream.hpp" + +#ifndef ASSERT +#define COV(casen) {} +#else //ASSERT +// Support for coverage testing. Used by the gtest. +/* $ sed < istream.cpp '/^.* COV(\([A-Z][^)]*\)).*$/!d;s//COV_FN(\1)/' | + tr '\12' ' ' | fold -sw72 | sed 's| $||;s|.*| & \\|' + */ +#define DO_COV_CASES(COV_FN) \ + COV_FN(NXT_L) COV_FN(NXT_N) COV_FN(FIB_P) COV_FN(FIB_E) COV_FN(FIB_N) \ + COV_FN(FIB_L) COV_FN(PFB_C) COV_FN(PFB_P) COV_FN(PFB_A) \ + COV_FN(PFB_G) COV_FN(PFB_H) COV_FN(SBC_C) COV_FN(SBC_B) COV_FN(SBC_N) \ + COV_FN(SBC_L) COV_FN(EXB_R) COV_FN(EXB_A) + /**/ +#define COV_COUNT(casename) coverage_case_##casename +#define DECLARE_COV_CASE(casename) static int COV_COUNT(casename); +DO_COV_CASES(DECLARE_COV_CASE) +#undef DECLARE_COV_CASE + +static int current_coverage_mode = 0; +#define COV(casename) { \ + if (current_coverage_mode != 0) { \ + COV_COUNT(casename)++; \ + } } +#endif //ASSERT + +bool inputStream::next() { + // We have to look at the current line first, just in case nobody + // actually called current_line() or done(). + preload(); + if (definitely_done()) { + return false; // OK to call this->next() after done is true + } + // current line is at buffer[beg..end]; now skip past its '\0' + assert(have_current_line(), ""); + + set_buffer_content(_next, _content_end); + if (!need_to_read()) { // any next line was already in the buffer + COV(NXT_L); + assert(have_current_line(), ""); + return true; + } else { // go back to the source for more + COV(NXT_N); + return fill_buffer(); + } +} + +void inputStream::set_done() { + size_t end = _beg = _end = _content_end; + _next = end + NEXT_PHANTOM; + _line_ending = 0; + assert(definitely_done(), ""); +} + +void inputStream::set_error(bool error_condition) { + if (error_condition) { + set_done(); + _input_state = IState::ERR_STATE; + assert(error(), ""); + } else if (error()) { + _input_state = definitely_done() ? IState::EOF_STATE : IState::NTR_STATE; + } +} + +void inputStream::clear_buffer() { + _content_end = _beg = _end = _next = 0; + _line_ending = 0; +} + +const char* inputStream::next_content(size_t& next_content_length) const { + assert(is_sane(), ""); + size_t len = buffered_content_length(false); + next_content_length = len; + return len == 0 ? "" : &_buffer[_next]; +} + +void inputStream::set_input(inputStream::Input* input) { + clear_buffer(); + _input = input; + _input_state = IState::NTR_STATE; +} + +bool inputStream::fill_buffer() { + size_t fill_offset, fill_length; + assert(!definitely_done(), ""); // caller responsibility + while (need_to_read()) { + prepare_to_fill_buffer(fill_offset, fill_length); + if (error()) return false; + assert(fill_length > 0, ""); + assert(fill_offset < _buffer_size, ""); + assert(fill_offset + fill_length <= _buffer_size, ""); + size_t nr = 0; + if (_input != nullptr && _input_state == IState::NTR_STATE) { + nr = _input->read(&_buffer[fill_offset], fill_length); + if (nr == 0) _input_state = IState::EOF_STATE; // do not get EOF twice + } + bool last_partial = false; + if (nr > 0) { + fill_offset += nr; + } else if (_beg == _end) { // no partial line, so end it now + // we hit the end of the file (or there was never anything there) + COV(FIB_P); + assert(!definitely_done(), ""); + set_done(); + assert(definitely_done(), ""); + return false; + } else { + // pretend to read a newline, to complete the last partial line + COV(FIB_E); + _buffer[fill_offset++] = '\n'; // insert phantom newline + last_partial = true; + } + set_buffer_content(_beg, fill_offset); + assert(!definitely_done(), ""); + if (need_to_read()) { COV(FIB_N); } + else { COV(FIB_L); } + if (last_partial) { + assert(have_current_line(), ""); + _line_ending = 0; + _content_end -= 1; // reverse insertion of phantom newline + assert(_next == _content_end + NEXT_PHANTOM, ""); + assert(have_current_line(), ""); + } + } + return true; +} + +// Find some space in the buffer for reading. If there is already a +// partial line in the buffer, new space must follow it immediately. +// The partial line is between _beg and _end, and no other parts of +// the buffer are in use. +void inputStream::prepare_to_fill_buffer(size_t& fill_offset, + size_t& fill_length) { + assert(need_to_read(), ""); // _next pointer out of the way + size_t end = _content_end; + if (_beg == end) { // if no partial line present... + COV(PFB_C); + clear_buffer(); + fill_offset = 0; + fill_length = _buffer_size; + return; // use the whole buffer + } + // at this point we have a pending line that needs more input + if (_beg > 0 && (_input != nullptr || end == _buffer_size)) { + COV(PFB_P); + // compact the buffer by overwriting characters from previous lines + size_t shift_left = _beg; + ::memmove(_buffer, _buffer + shift_left, _content_end - _beg); + _beg -= shift_left; + _end -= shift_left; + _next -= shift_left; + _content_end -= shift_left; + end = _content_end; + } + if (end < _buffer_size) { + COV(PFB_A); + fill_offset = end; + fill_length = _buffer_size - end; + return; // use the whole buffer except partial line at the beginning + } + // the whole buffer contains a partial line, which means we must expand + COV(PFB_G); + size_t new_size = (_buffer_size < BIG_SIZE ? BIG_SIZE + : _buffer_size + _buffer_size / 2); + assert(new_size > _buffer_size, ""); + if (expand_buffer(new_size)) { + COV(PFB_H); + fill_offset = end; + fill_length = _buffer_size - end; + return; // use the expanded buffer, except the partial line + } + // no recovery from failed allocation; just set the error state and bail + set_error(); +} + +// The only buffer content is between the given offsets. +// Set _beg, _end, _next, and _content_end appropriately. +void inputStream::set_buffer_content(size_t content_start, + size_t content_end) { + assert(content_end <= _buffer_size, ""); + assert(content_start <= content_end + NEXT_PHANTOM, ""); + if (content_start >= content_end) { // empty content; clear buffer + COV(SBC_C); + clear_buffer(); + return; + } + COV(SBC_B); + size_t content_len = content_end - content_start; + _beg = content_start; + _content_end = content_end; + + // this is where we scan for newlines + char* nl = (char*) memchr(&_buffer[content_start], '\n', content_len); + if (nl == nullptr) { + COV(SBC_N); + _next = _end = content_end; + _line_ending = 0; + assert(need_to_read(), ""); + } else { + COV(SBC_L); + *nl = '\0'; // so that this->current_line() will work + ++_line_count; + size_t end = nl - &_buffer[0]; + _next = end + 1; + assert(_next != _content_end + NEXT_PHANTOM, ""); + if (end > content_start && nl[-1] == '\r') { // yuck + // again, for this->current_line(), remove '\r' before '\n' + nl[-1] = '\0'; + --end; + // Note: we could treat '\r' alone as a line ending on some + // platforms, but that is way too much work. Newline '\n' is + // supported everywhere, and some tools insist on accompanying + // it with return as well, so we remove that. But return '\r' + // by itself is an obsolete format, and also inconsistent with + // outputStream, which standarizes on '\n' and never emits '\r'. + // Postel's law suggests that we write '\n' only and grudgingly + // accept '\r' before '\n'. + } + _end = end; // now this->current_line() points to buf[beg..end] + _line_ending = (int)(_next - end); + assert(have_current_line(), ""); + assert(current_line() == &_buffer[_beg], ""); + assert(current_line_length() == _end - _beg, ""); + } +} + +// Return true iff we expanded the buffer to the given length. +bool inputStream::expand_buffer(size_t new_length) { + assert(new_length > _buffer_size, ""); + char* new_buf = nullptr; + assert(new_length > sizeof(_small_buffer), ""); + if (_buffer == &_small_buffer[0]) { + // fresh alloc from c-heap + COV(EXB_A); + new_buf = NEW_C_HEAP_ARRAY(char, new_length, mtInternal); + assert(new_buf != nullptr, "would have exited VM if OOM"); + if (_content_end > 0) { + assert(_content_end <= _buffer_size, ""); + ::memcpy(new_buf, _buffer, _content_end); // copy only the active content + } + } else { + // realloc + COV(EXB_R); + new_buf = REALLOC_C_HEAP_ARRAY(char, _buffer, new_length, mtInternal); + assert(new_buf != nullptr, "would have exited VM if OOM"); + } + + if (new_buf == nullptr) { + return false; // do not further update _buffer etc. + } + _buffer = new_buf; + _buffer_size = new_length; + return true; +} + +inputStream::~inputStream() { + if (has_c_heap_buffer()) { + FreeHeap(_buffer); + DEBUG_ONLY(_buffer = (char*)((uintptr_t)0xdeadbeef)); // sanity + } +} + +#ifdef ASSERT +void inputStream::dump(const char* what) { + int diff = (int)(_end - _beg); + if (!_buffer || _beg > _buffer_size || _end > _buffer_size) + diff = 0; + + bool ntr = (_next == _end), + hcl = (_beg < _content_end && _end < _next), + ddn = (_beg == _content_end && _next > _content_end); + tty->print_cr("%s%sistream %s%s%s%s%s [%d<%.*s>%d/%d..%d] LE=%d," + " B=%llx%s[%d], LN=%d, CH=%d", + what ? what : "", what ? ": " : "", + _buffer == nullptr ? "U" : "", + ntr ? "R" : "", + hcl ? "L" : "", + ddn ? "D" : "", + (_next < _content_end ? "" : + _next == _content_end ? "N" : "P"), + (int)_beg, + diff < 0 ? 0 : diff > 10 ? 10 : diff, + _buffer ? &_buffer[_beg] : "", + (int)_end, (int)_next, (int)_content_end, + _line_ending, + (unsigned long long)(intptr_t)_buffer, + _buffer == _small_buffer ? "(SB)" : "", + (int)_buffer_size, + (int)_line_count, + has_c_heap_buffer()); + assert(is_sane(), ""); +} +#endif + +#ifdef ASSERT +// More support for coverage testing. +int inputStream::coverage_mode(int start, + int& cases, int& total, int& zeroes) { + int old_mode = current_coverage_mode; + current_coverage_mode = start; + int num_cases = 0, zero_count = 0, case_count = 0; +#define COUNT_COV_CASE(casename) { \ + int tem = COV_COUNT(casename); \ + case_count += tem; \ + if (tem == 0) ++zero_count; \ + num_cases++; \ + } + DO_COV_CASES(COUNT_COV_CASE) +#undef COUNT_COV_CASE + if (start < 0) { + tty->print("istream coverage:"); + #define PRINT_COV_CASE(casename) \ + tty->print(" %s:%d", #casename, COV_COUNT(casename)); + DO_COV_CASES(PRINT_COV_CASE) + tty->cr(); + #undef PRINT_COV_CASE + if (zero_count != 0) { + case_count = -case_count; + #define ZERO_COV_CASE(casename) \ + if (COV_COUNT(casename) == 0) \ + tty->print_cr("%s: no coverage for %s", \ + __FILE__, #casename); \ + DO_COV_CASES(ZERO_COV_CASE) + #undef ZERO_COV_CASE + } + } + if (start >= 2 || start < 0) { + #define CLEAR_COV_CASE(casename) \ + COV_COUNT(casename) = 0; + DO_COV_CASES(CLEAR_COV_CASE) + #undef CLEAR_COV_CASE + } + cases = num_cases; + total = case_count; + zeroes = zero_count; + return old_mode; +} +#endif //ASSERT diff --git a/src/hotspot/share/utilities/istream.hpp b/src/hotspot/share/utilities/istream.hpp new file mode 100644 index 0000000000000..b6a58055b937c --- /dev/null +++ b/src/hotspot/share/utilities/istream.hpp @@ -0,0 +1,386 @@ +/* + * 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. + * + */ + +#ifndef SHARE_UTILITIES_ISTREAM_HPP +#define SHARE_UTILITIES_ISTREAM_HPP + +#include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" +#include "utilities/ostream.hpp" + +// Input streams for reading line-oriented textual data. These streams +// treat newline '\n' very differently from all other bytes. Carriage +// return '\r' is just another bit of whitespace, although it is +// removed just before newline. +// +// Null '\0' is just a data byte, although it also terminates C +// strings; the `current_line` function adds a null after removing any +// line terminator but does not specially process any nulls embedded +// in the line. +// +// There are sizing access functions which allow lines to contain +// null, but the simpler function assumes null termination, and thus +// lines containing null will "look" shorter when viewed as C strings. +// Use the sizing access functions if you care about this. +// +// Formatting guidelines: +// +// Configuration data should be line-oriented. It should be readable +// by humans (though perhaps with difficulty). It should be easily +// processed by text editors and by widely available text processing +// tools such as grep, sed, and awk. +// +// Configuration data should not require "compilers" to generate, if +// possible. It should be editable by hand, if possible. In cases +// where binary data is strongly required, pick a binary format +// already native to Hotspot, such as classfile, jar, or jmod. +// +// Each line should be separately parseable; the parsing can be ad +// hoc. For constructs inherently larger than single lines (such as +// complex method configuration information), try to use a structuring +// principle that allows "leaf" data to be line-oriented, and delimits +// that data with markup lines of some sort. Try to pick a +// line-friendly version of a standard format like XML or Markdown. +// JSON is somewhat problematic because there is no line-friendly leaf +// syntax: everything at the leaves must be a quoted string in JSON. +// +// Use simple parsing via scanf-like formats for simple applications. +// But, keep in mind that these formats may lose data when applied to +// unusual strings, such as class names that contain spaces, or method +// names that contain punctuation. For more robust transmission of +// potentially unusual names, consider wrapping them in XML-flavored +// lines like . +// +// Note: Input streams are never MT-safe. + +class inputStream : public CHeapObjBase { + public: + class Input; + + private: + NONCOPYABLE(inputStream); + + static constexpr size_t SMALL_SIZE = 240 DEBUG_ONLY(*0 + 10); + static constexpr size_t BIG_SIZE = 2048 DEBUG_ONLY(*0 + 20); + + protected: + // Values for _input_state, to distinguish some phases of history: + // Do we need to read more input (NTR)? Did we see EOF already? + // Was there an error getting input or allocating buffer space? + enum class IState : int { NTR_STATE, EOF_STATE, ERR_STATE }; + + // Named offset for _next relative to _content_end, of phantom '\n'. + static const int NEXT_PHANTOM = 1; + + Input* _input; // where the input comes from or else nullptr + IState _input_state; // one of {NTR,EOF,ERR}_STATE + char _line_ending; // one of {0,1,2} for "", "\n", "\r\n" + char* _buffer; // scratch buffer holding at least the current line + size_t _buffer_size; // allocated size of buffer + size_t _content_end; // offset to end of valid contents of buffer + size_t _beg; // offset in buffer to start of current line + size_t _end; // offset to end of known current line (else content_end) + size_t _next; // offset to known start of next line (else =end) + size_t _line_count; // increasing non-resettable count of lines read + char _small_buffer[SMALL_SIZE]; // stack-allocated buffer for holding lines; + // will switch to C_HEAP allocation when necessary. + + bool has_c_heap_buffer() { + return _buffer != &_small_buffer[0]; + } + + // Buffer states + // + // The current line (less any line ending) is always [beg..end). + // It is always the case that 0 <= beg <= end <= con_end <= buffer_size. + // When there is a current line buffered, end < next <= 1+con_end. + // In that case, the value of next is end + max(1, strlen(lend)), + // where lend is "\n", "\r\n", or (for a last partial line) "". + // But if next == end, we need to read more input, or observe an EOF. + // + // beg ==end ==next == con_end => nothing buffered, we need to read + // beg <=end < next <= con_end => have current line, with terminator + // beg < end < next ==1+con_end => have partial current line (saw EOF) + // beg < end ==next == con_end => partial line, we need to read + // beg ==end < next ==1+con_end => definitely done; no more I/O + // + // These states are in three mutually exclusive groups: + // need_to_read() <= nothing or partial line in buffer + // have_current_line() <= beg/end point to valid line (partial only if EOF) + // definitely_done() <= consumed all lines && (hit EOF || hit error) + // These states are internal; the user can only look at next/done/error. + // + // Relative to these states, everything already read from the input + // before the first byte of the current line is logically present + // (but not accessible) before _beg, while everything not yet read + // from the input is after _content_end. The difference between + // these two pointers is constant, except when characters change + // from being in the current line to being (logically) before it, + // when next is called. + + bool is_sane() const { + assert(_buffer != nullptr, ""); + assert(_content_end <= _buffer_size, ""); + assert(_beg <= _end && _end <= _content_end, ""); + assert(_end <= _next && _next <= _content_end + NEXT_PHANTOM, ""); + assert(_buffer_size == 0 || _next <= _buffer_size, ""); + return true; + } + + bool need_to_read() const { + assert(is_sane(), ""); + return _next == _end; + } + bool have_current_line() const { + assert(is_sane(), ""); + // _beg < _content_end because there is an \0 (was \n) at _end, + // or else it is a non-empty partial line and the \0 is at + // _content_end. In either case, if _end == _next we are + // still searching for more input. + return (_beg < _content_end && _end < _next); + } + bool definitely_done() const { + assert(is_sane(), ""); + // If _beg < _content_end we still have a line of some sort. + // Otherwise, if _next > _content_end, we have seen EOF or error. + return (_beg == _content_end && _next > _content_end); + } + + // Reset indexes within the buffer to point to no content. + void clear_buffer(); + + // Reset indexes within the buffer to point to the given content. + // This is where we scan for newlines as well. + void set_buffer_content(size_t content_start, size_t content_end); + + // Try to make the buffer bigger. This may be necessary in order to + // buffer a very long line. Returns false if there was an + // allocation failure. + // + // On allocation failure, just make do with whatever buffer there + // was to start with; the caller must check for this condition and + // avoid buffering more data in the non-expanded buffer. However, + // the buffer will always be non-null, so at least one line can be + // buffered, if it is of normal size. + bool expand_buffer(size_t new_length); + + // Make sure there is at least one line in the buffer, and set + // _beg/_end to indicate where it is. Any content before _beg can + // be overwritten to make more room in the buffer. If there is no + // more input, set the state up to indicate we are done. + bool fill_buffer(); + + // Find some room in the buffer so we can call read on it. + // This might call expand_buffer but will try not to. + // The assumption is that read already buffers slow I/O calls. + // The purpose for the small buffer managed here is to store whole lines, + // and perhaps edit them in-place. + void prepare_to_fill_buffer(size_t& fill_offset, size_t& fill_length); + + // Quick check for an initially incomplete buffer... + void preload() const { + if (need_to_read()) { + const_cast(this)->fill_buffer(); + } + } + + // How much content is buffered (if any) after the current line? + size_t buffered_content_length(bool include_current) const { + return (include_current ? _content_end - _beg : + _content_end >= _next ? _content_end - _next : 0); + } + + // Returns a pointer and count to characters buffered after the + // current line, but not yet read from my input source. Only useful + // if you are trying to stack input streams on top of each other + // somehow. You can also ask the input source if it thinks it has + // more bytes. + const char* next_content(size_t& next_content_length) const; + + public: + // Create an empty input stream. + // Call push_back_input or set_input to configure. + inputStream() : + _input(nullptr), + _input_state(IState::NTR_STATE), + _line_ending(0), + _buffer(&_small_buffer[0]), + _buffer_size(sizeof(_small_buffer)), + _content_end(0), + _beg(0), + _end(0), + _next(0), + _line_count(0) {} + + // Take input from the given source. Buffer only a modest amount. + inputStream(Input* input) + : inputStream() + { + set_input(input); + } + + virtual ~inputStream(); + + // Discards any previous input and sets the given input source. + void set_input(Input* input); + + // Returns a pointer to a null terminated mutable copy of the current line. + // Note that embedded nulls may make the line appear shorter than it really is. + // This may trigger input activity if there is not enough data buffered. + // If there are no more lines, return an empty line, statically allocated. + char* current_line() const { + preload(); + if (definitely_done()) + return (char*)""; + return &_buffer[_beg]; + } + + // Return the size of the current line, exclusive of any line terminator. + // If no lines have been read yet, or there are none remaining, return zero. + size_t current_line_length() const { + preload(); + return _end - _beg; + } + + // Reports my current input source, if any, else a null pointer. + Input* input() const { return _input; } + + // Discards the current line, gets ready to report the next line. + // Returns true if there is one, which is always the opposite of done(). + // Fetches input if necessary. + bool next(); + + // Reports if there are no more lines. Fetches input if necessary. + bool done() const { + preload(); + return definitely_done(); + } + + // Discard pending input and do not read any more. + // Takes no action if already done, whether in an error state or not. + void set_done(); + + // Reports if this stream has had an error was reported on it. + bool error() const { + return _input_state == IState::ERR_STATE; + } + + // Set this stream done with an error, if the argument is true. + // If it is false but there is an error condition, clear the error. + // Otherwise do nothing. + void set_error(bool error_condition = true); + + // lineno is the 1-based ordinal of the current line; it starts at one + size_t lineno() const { preload(); return _line_count; } + + // Copy the current line to the given output stream. + void print_on(outputStream* out); + + // Copy the current line to the given output stream, and also call cr(). + void print_cr_on(outputStream* out) { + print_on(out); out->cr(); + } + +#ifdef ASSERT + void dump(const char* what = nullptr); + static int coverage_mode(int mode, int& cases, int& total, int& zeroes); +#else + void dump(const char* what = nullptr) { } +#endif + + + // Block-oriented input, which treats all bytes equally. + class Input : public CHeapObjBase { + public: + // Read some characters from an external source into the line buffer. + // If there are no more, return zero, otherwise return non-zero. + // It must be OK to call read even after it returns zero. + virtual size_t read(char* buf, size_t size) = 0; + // Example: read(b,s) { return fread(b, 1, s, _my_fp); } + // Example: read(b,s) { return 0; } // never more than the initial buffer + }; +}; + +// for reading lines from files +class FileInput : public inputStream::Input { + NONCOPYABLE(FileInput); + + protected: + fileStream& _fs; + fileStream _private_fs; + + // it does not seem likely there are such file streams around + FileInput(fileStream& fs) + : _fs(fs) + { } + + public: + // just forward all the constructor arguments to the wrapped line-input class + template + FileInput(Arg... arg) + : _fs(_private_fs), _private_fs(arg...) + { } + + FileInput(const char* file_name) + : FileInput(file_name, "rt") + { } + + bool is_open() const { return _fs.is_open(); } + + protected: + size_t read(char* buf, size_t size) override { + return _fs.read(buf, size); + } +}; + +class MemoryInput : public inputStream::Input { + const void* _base; + const size_t _limit; + size_t _offset; + + public: + MemoryInput(const void* base, size_t size, + size_t offset = 0) + : _base(base), _limit(size), _offset(offset) {} + + MemoryInput(const char* start) + : MemoryInput(start, 0, strlen(start)) + { } + + protected: + size_t read(char* buf, size_t size) override { + size_t nr = size; + if (nr > _limit - _offset) { + nr = _limit - _offset; + } + if (nr > 0) { + ::memcpy(buf, (char*)_base + _offset, nr); + _offset += nr; + } + return nr; + } +}; + +#endif // SHARE_UTILITIES_ISTREAM_HPP diff --git a/src/hotspot/share/utilities/linkedlist.hpp b/src/hotspot/share/utilities/linkedlist.hpp index 5b8e258d53914..eec7ea1e48d90 100644 --- a/src/hotspot/share/utilities/linkedlist.hpp +++ b/src/hotspot/share/utilities/linkedlist.hpp @@ -82,7 +82,7 @@ template class LinkedListNode : public AnyObj { template class LinkedList : public AnyObj { protected: LinkedListNode* _head; - NONCOPYABLE(LinkedList); + NONCOPYABLE(LinkedList); public: LinkedList() : _head(nullptr) { } diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp index a1575b3d2c6c8..89335f9cf4c62 100644 --- a/src/hotspot/share/utilities/ostream.cpp +++ b/src/hotspot/share/utilities/ostream.cpp @@ -397,7 +397,7 @@ char* stringStream::as_string(bool c_heap) const { char* copy = c_heap ? NEW_C_HEAP_ARRAY(char, _written + 1, mtInternal) : NEW_RESOURCE_ARRAY(char, _written + 1); ::memcpy(copy, _buffer, _written); - copy[_written] = 0; // terminating null + copy[_written] = '\0'; // terminating null if (c_heap) { // Need to ensure our content is written to memory before we return // the pointer to it. @@ -590,23 +590,10 @@ long fileStream::fileSize() { return size; } -char* fileStream::readln(char *data, int count ) { - char * ret = nullptr; - if (_file != nullptr) { - ret = ::fgets(data, count, _file); - // Get rid of annoying \n char only if it is present. - size_t len = ::strlen(data); - if (len > 0 && data[len - 1] == '\n') { - data[len - 1] = '\0'; - } - } - return ret; -} - fileStream::~fileStream() { if (_file != nullptr) { - if (_need_close) fclose(_file); - _file = nullptr; + close(); + _file = nullptr; } } diff --git a/src/hotspot/share/utilities/ostream.hpp b/src/hotspot/share/utilities/ostream.hpp index 72cf804ed646d..d39fca29ba4c0 100644 --- a/src/hotspot/share/utilities/ostream.hpp +++ b/src/hotspot/share/utilities/ostream.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -242,11 +242,20 @@ class fileStream : public outputStream { ~fileStream(); bool is_open() const { return _file != nullptr; } virtual void write(const char* c, size_t len); - size_t read(void *data, size_t size, size_t count) { return _file != nullptr ? ::fread(data, size, count, _file) : 0; } - char* readln(char *data, int count); - int eof() { return _file != nullptr ? feof(_file) : -1; } + // unlike other classes in this file, fileStream can perform input as well as output + size_t read(void* data, size_t size) { + if (_file == nullptr) return 0; + return ::fread(data, 1, size, _file); + } + size_t read(void *data, size_t size, size_t count) { + return read(data, size * count); + } + void close() { + if (_file == nullptr || !_need_close) return; + fclose(_file); + _need_close = false; + } long fileSize(); - void rewind() { if (_file != nullptr) ::rewind(_file); } void flush(); }; diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index ae1c65b9f935d..5e28b9ce95b7c 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -191,8 +191,9 @@ private System() { */ public static final PrintStream err = null; - // Holder for the initial value of `in`, set within `initPhase1()`. - private static InputStream initialIn; + // Initial values of System.in and System.err, set in initPhase1(). + private static @Stable InputStream initialIn; + private static @Stable PrintStream initialErr; // indicates if a security manager is possible private static final int NEVER = 1; @@ -355,9 +356,6 @@ private static class CallersHolder { = Collections.synchronizedMap(new WeakHashMap<>()); } - // Remember initial System.err. setSecurityManager() warning goes here - private static volatile @Stable PrintStream initialErrStream; - private static URL codeSource(Class clazz) { PrivilegedAction pa = clazz::getProtectionDomain; @SuppressWarnings("removal") @@ -417,7 +415,7 @@ public static void setSecurityManager(@SuppressWarnings("removal") SecurityManag } else { source = callerClass.getName() + " (" + url + ")"; } - initialErrStream.printf(""" + initialErr.printf(""" WARNING: A terminally deprecated method in java.lang.System has been called WARNING: System::setSecurityManager has been called by %s WARNING: Please consider reporting this to the maintainers of %s @@ -2200,7 +2198,8 @@ private static void initPhase1() { // thus they are equivalent to Console.charset(), otherwise the encodings // of those properties default to native.encoding setOut0(newPrintStream(fdOut, props.getProperty("stdout.encoding"))); - setErr0(newPrintStream(fdErr, props.getProperty("stderr.encoding"))); + initialErr = newPrintStream(fdErr, props.getProperty("stderr.encoding")); + setErr0(initialErr); // Setup Java signal handlers for HUP, TERM, and INT (where available). Terminator.setup(); @@ -2406,8 +2405,6 @@ private static void initPhase3() { notSupportedJnuEncoding); } - initialErrStream = System.err; - // initializing the system class loader VM.initLevel(3); @@ -2598,6 +2595,10 @@ public InputStream initialSystemIn() { return initialIn; } + public PrintStream initialSystemErr() { + return initialErr; + } + public void setCause(Throwable t, Throwable cause) { t.setCause(cause); } diff --git a/src/java.base/share/classes/java/lang/classfile/TypeKind.java b/src/java.base/share/classes/java/lang/classfile/TypeKind.java index bf2435f43ef0e..5ba566b3d0672 100644 --- a/src/java.base/share/classes/java/lang/classfile/TypeKind.java +++ b/src/java.base/share/classes/java/lang/classfile/TypeKind.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 @@ -58,7 +58,7 @@ public enum TypeKind { private final String name; private final String descriptor; - private final int newarraycode; + private final int newarrayCode; /** {@return the human-readable name corresponding to this type} */ public String typeName() { return name; } @@ -66,9 +66,12 @@ public enum TypeKind { /** {@return the field descriptor character corresponding to this type} */ public String descriptor() { return descriptor; } - /** {@return the code used by the {@code newarray} opcode corresponding to this type} */ - public int newarraycode() { - return newarraycode; + /** + * {@return the code used by the {@code newarray} opcode corresponding to this type} + * @since 23 + */ + public int newarrayCode() { + return newarrayCode; } /** @@ -94,19 +97,21 @@ public TypeKind asLoadable() { }; } - TypeKind(String name, String descriptor, int newarraycode) { + TypeKind(String name, String descriptor, int newarrayCode) { this.name = name; this.descriptor = descriptor; - this.newarraycode = newarraycode; + this.newarrayCode = newarrayCode; } /** * {@return the type kind associated with the array type described by the * array code used as an operand to {@code newarray}} - * @param newarraycode the operand of the {@code newarray} instruction + * @param newarrayCode the operand of the {@code newarray} instruction + * @throws IllegalArgumentException if the code is invalid + * @since 23 */ - public static TypeKind fromNewArrayCode(int newarraycode) { - return switch (newarraycode) { + public static TypeKind fromNewarrayCode(int newarrayCode) { + return switch (newarrayCode) { case 4 -> TypeKind.BooleanType; case 5 -> TypeKind.CharType; case 6 -> TypeKind.FloatType; @@ -115,15 +120,19 @@ public static TypeKind fromNewArrayCode(int newarraycode) { case 9 -> TypeKind.ShortType; case 10 -> TypeKind.IntType; case 11 -> TypeKind.LongType; - default -> throw new IllegalArgumentException("Bad new array code: " + newarraycode); + default -> throw new IllegalArgumentException("Bad newarray code: " + newarrayCode); }; } /** * {@return the type kind associated with the specified field descriptor} * @param s the field descriptor + * @throws IllegalArgumentException only if the descriptor is not valid */ public static TypeKind fromDescriptor(CharSequence s) { + if (s.isEmpty()) { // implicit null check + throw new IllegalArgumentException("Empty descriptor"); + } return switch (s.charAt(0)) { case '[', 'L' -> TypeKind.ReferenceType; case 'B' -> TypeKind.ByteType; @@ -144,6 +153,8 @@ public static TypeKind fromDescriptor(CharSequence s) { * @param descriptor the field descriptor */ public static TypeKind from(TypeDescriptor.OfField descriptor) { - return fromDescriptor(descriptor.descriptorString()); + return descriptor.isPrimitive() // implicit null check + ? fromDescriptor(descriptor.descriptorString()) + : TypeKind.ReferenceType; } } diff --git a/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java b/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java index a67a0f21c0883..ae3f465402d0f 100644 --- a/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java +++ b/src/java.base/share/classes/java/lang/classfile/instruction/NewPrimitiveArrayInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 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 @@ -56,7 +56,7 @@ public sealed interface NewPrimitiveArrayInstruction extends Instruction */ static NewPrimitiveArrayInstruction of(TypeKind typeKind) { // Implicit null-check: - if (typeKind.newarraycode() < 0) { + if (typeKind.newarrayCode() < 0) { throw new IllegalArgumentException("Illegal component type: " + typeKind.typeName()); } return new AbstractInstruction.UnboundNewPrimitiveArrayInstruction(typeKind); diff --git a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java index 19a193a924a0a..46eeb67de54c5 100644 --- a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java +++ b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java @@ -28,7 +28,6 @@ import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; import sun.invoke.util.Wrapper; -import sun.util.logging.PlatformLogger; import java.util.ArrayList; import java.util.HashSet; @@ -73,6 +72,7 @@ static class HolderClassBuilder { private final TreeSet speciesTypes = new TreeSet<>(); private final TreeSet invokerTypes = new TreeSet<>(); + private final TreeSet linkerTypes = new TreeSet<>(); private final TreeSet callSiteTypes = new TreeSet<>(); private final Map> dmhMethods = new TreeMap<>(); @@ -87,6 +87,12 @@ HolderClassBuilder addInvokerType(String methodType) { return this; } + HolderClassBuilder addLinkerType(String methodType) { + validateMethodType(methodType); + linkerTypes.add(methodType); + return this; + } + HolderClassBuilder addCallSiteType(String csType) { validateMethodType(csType); callSiteTypes.add(csType); @@ -130,19 +136,33 @@ Map build() { } } - // The invoker type to ask for is retrieved by removing the first + // The linker type to ask for is retrieved by removing the first // and the last argument, which needs to be of Object.class + MethodType[] linkerMethodTypes = new MethodType[linkerTypes.size()]; + index = 0; + for (String linkerType : linkerTypes) { + MethodType mt = asMethodType(linkerType); + final int lastParam = mt.parameterCount() - 1; + if (!checkLinkerTypeParams(mt)) { + throw new RuntimeException( + "Linker type parameter must start and end with Object: " + linkerType); + } + mt = mt.dropParameterTypes(lastParam, lastParam + 1); + linkerMethodTypes[index] = mt.dropParameterTypes(0, 1); + index++; + } + + // The invoker type to ask for is retrieved by removing the first + // argument, which needs to be of Object.class MethodType[] invokerMethodTypes = new MethodType[invokerTypes.size()]; index = 0; for (String invokerType : invokerTypes) { MethodType mt = asMethodType(invokerType); - final int lastParam = mt.parameterCount() - 1; if (!checkInvokerTypeParams(mt)) { throw new RuntimeException( - "Invoker type parameter must start and end with Object: " + invokerType); + "Invoker type parameter must start with 2 Objects: " + invokerType); } - mt = mt.dropParameterTypes(lastParam, lastParam + 1); - invokerMethodTypes[index] = mt.dropParameterTypes(0, 1); + invokerMethodTypes[index] = mt.dropParameterTypes(0, 2); index++; } @@ -171,7 +191,7 @@ Map build() { DELEGATING_HOLDER, directMethodTypes)); result.put(INVOKERS_HOLDER, generateInvokersHolderClassBytes(INVOKERS_HOLDER, - invokerMethodTypes, callSiteMethodTypes)); + linkerMethodTypes, invokerMethodTypes, callSiteMethodTypes)); result.put(BASIC_FORMS_HOLDER, generateBasicFormsClassBytes(BASIC_FORMS_HOLDER)); @@ -207,6 +227,12 @@ public static MethodType asMethodType(String basicSignatureString) { } public static boolean checkInvokerTypeParams(MethodType mt) { + return (mt.parameterCount() >= 2 && + mt.parameterType(0) == Object.class && + mt.parameterType(1) == Object.class); + } + + public static boolean checkLinkerTypeParams(MethodType mt) { final int lastParam = mt.parameterCount() - 1; return (mt.parameterCount() >= 2 && mt.parameterType(0) == Object.class && @@ -320,15 +346,11 @@ static Map generateHolderClasses(Stream traces) { if ("linkToTargetMethod".equals(parts[2]) || "linkToCallSite".equals(parts[2])) { builder.addCallSiteType(methodType); + } else if (parts[2].endsWith("nvoker")) { + // MH.exactInvoker exactInvoker MH.invoker invoker + builder.addInvokerType(methodType); } else { - MethodType mt = HolderClassBuilder.asMethodType(methodType); - // Work around JDK-8327499 - if (HolderClassBuilder.checkInvokerTypeParams(mt)) { - builder.addInvokerType(methodType); - } else { - PlatformLogger.getLogger("java.lang.invoke") - .warning("Invalid LF_RESOLVE " + parts[1] + " " + parts[2] + " " + parts[3]); - } + builder.addLinkerType(methodType); } } else if (parts[1].contains("DirectMethodHandle")) { String dmh = parts[2]; @@ -465,27 +487,27 @@ static byte[] generateDelegatingMethodHandleHolderClassBytes(String className, /** * Returns a {@code byte[]} representation of a class implementing - * the invoker forms for the set of supplied {@code invokerMethodTypes} - * and {@code callSiteMethodTypes}. + * the invoker forms for the set of supplied {@code linkerMethodTypes} + * {@code invokerMethodTypes}, and {@code callSiteMethodTypes}. */ static byte[] generateInvokersHolderClassBytes(String className, - MethodType[] invokerMethodTypes, MethodType[] callSiteMethodTypes) { + MethodType[] linkerMethodTypes, MethodType[] invokerMethodTypes, + MethodType[] callSiteMethodTypes) { HashSet dedupSet = new HashSet<>(); ArrayList forms = new ArrayList<>(); ArrayList names = new ArrayList<>(); - int[] types = { - MethodTypeForm.LF_EX_LINKER, + + int[] invokerTypes = { MethodTypeForm.LF_EX_INVOKER, - MethodTypeForm.LF_GEN_LINKER, - MethodTypeForm.LF_GEN_INVOKER + MethodTypeForm.LF_GEN_INVOKER, }; - for (int i = 0; i < invokerMethodTypes.length; i++) { + for (MethodType methodType : invokerMethodTypes) { // generate methods representing invokers of the specified type - if (dedupSet.add(invokerMethodTypes[i])) { - for (int type : types) { - LambdaForm invokerForm = Invokers.invokeHandleForm(invokerMethodTypes[i], + if (dedupSet.add(methodType)) { + for (int type : invokerTypes) { + LambdaForm invokerForm = Invokers.invokeHandleForm(methodType, /*customized*/false, type); forms.add(invokerForm); names.add(invokerForm.kind.defaultLambdaName); @@ -493,6 +515,24 @@ static byte[] generateInvokersHolderClassBytes(String className, } } + int[] linkerTypes = { + MethodTypeForm.LF_EX_LINKER, + MethodTypeForm.LF_GEN_LINKER, + }; + + dedupSet = new HashSet<>(); + for (MethodType methodType : linkerMethodTypes) { + // generate methods representing linkers of the specified type + if (dedupSet.add(methodType)) { + for (int type : linkerTypes) { + LambdaForm linkerForm = Invokers.invokeHandleForm(methodType, + /*customized*/false, type); + forms.add(linkerForm); + names.add(linkerForm.kind.defaultLambdaName); + } + } + } + dedupSet = new HashSet<>(); for (int i = 0; i < callSiteMethodTypes.length; i++) { // generate methods representing invokers of the specified type diff --git a/src/java.base/share/classes/java/util/Locale.java b/src/java.base/share/classes/java/util/Locale.java index 0f8474ec12d48..ae6c4af5ec56c 100644 --- a/src/java.base/share/classes/java/util/Locale.java +++ b/src/java.base/share/classes/java/util/Locale.java @@ -48,6 +48,7 @@ import java.text.DateFormat; import java.text.MessageFormat; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import java.util.spi.LocaleNameProvider; import java.util.stream.Stream; @@ -980,29 +981,36 @@ static Locale getInstance(String language, String script, String country, return getInstance(baseloc, extensions); } + static Locale getInstance(BaseLocale baseloc, LocaleExtensions extensions) { if (extensions == null) { Locale locale = CONSTANT_LOCALES.get(baseloc); if (locale != null) { return locale; } - return LOCALE_CACHE.computeIfAbsent(baseloc, Locale::createLocale); + return LOCALE_CACHE.computeIfAbsent(baseloc, LOCALE_CREATOR); } else { LocaleKey key = new LocaleKey(baseloc, extensions); - return LOCALE_CACHE.computeIfAbsent(key, Locale::createLocale); + return LOCALE_CACHE.computeIfAbsent(key, LOCALE_CREATOR); } } - private static final ReferencedKeyMap LOCALE_CACHE = ReferencedKeyMap.create(true, ConcurrentHashMap::new); - private static Locale createLocale(Object key) { - if (key instanceof BaseLocale base) { - return new Locale(base, null); + private static final ReferencedKeyMap LOCALE_CACHE + = ReferencedKeyMap.create(true, ReferencedKeyMap.concurrentHashMapSupplier()); + + private static final Function LOCALE_CREATOR = new Function<>() { + @Override + public Locale apply(Object key) { + if (key instanceof BaseLocale base) { + return new Locale(base, null); + } + LocaleKey lk = (LocaleKey)key; + return new Locale(lk.base, lk.exts); } - LocaleKey lk = (LocaleKey)key; - return new Locale(lk.base, lk.exts); - } + }; private static final class LocaleKey { + private final BaseLocale base; private final LocaleExtensions exts; private final int hash; diff --git a/src/java.base/share/classes/java/util/concurrent/locks/Lock.java b/src/java.base/share/classes/java/util/concurrent/locks/Lock.java index 84100e64a13dd..bd6ce2eb6f919 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/Lock.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/Lock.java @@ -80,11 +80,11 @@ * *
 {@code
  * Lock l = ...;
- * l.lock();
+ * l.lock(); // lock() as the last statement before the try block
  * try {
  *   // access the resource protected by this lock
  * } finally {
- *   l.unlock();
+ *   l.unlock(); // unlock() as the first statement in the finally block
  * }}
* * When locking and unlocking occur in different scopes, care must be diff --git a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java index c58925b086e6d..3378ce3983aa1 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java @@ -71,8 +71,9 @@ * is available even if other threads are waiting. * *

It is recommended practice to always immediately - * follow a call to {@code lock} with a {@code try} block, most - * typically in a before/after construction such as: + * follow a call to {@code lock} with a {@code try} block, and + * to always immediately call {@code unlock} as the + * first statement in the finally block, as follows: * *

 {@code
  * class X {
@@ -80,11 +81,11 @@
  *   // ...
  *
  *   public void m() {
- *     lock.lock();  // block until condition holds
+ *     lock.lock();  // lock() as the last statement before the try block
  *     try {
  *       // ... method body
  *     } finally {
- *       lock.unlock();
+ *       lock.unlock(); // unlock() as the first statement in the finally block
  *     }
  *   }
  * }}
diff --git a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java index c73bd41cea87a..517708e70f3f2 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java @@ -141,6 +141,7 @@ * * void processCachedData() { * rwl.readLock().lock(); + * // Code between the lock() above, and the unlock() below must not throw * if (!cacheValid) { * // Must release read lock before acquiring write lock * rwl.readLock().unlock(); @@ -158,7 +159,7 @@ * rwl.writeLock().unlock(); // Unlock write, still hold read * } * } - * + * // Make sure that code that could throw is executed inside the try block * try { * use(data); * } finally { diff --git a/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java b/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java index 7b7339e2772a8..a7c063713684b 100644 --- a/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java +++ b/src/java.base/share/classes/java/util/random/RandomGeneratorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2022, 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 @@ -142,8 +142,9 @@ private static class FactoryMapHolder { * @return Map of RandomGeneratorFactory classes. */ private static Map> createFactoryMap() { + FactoryMapHolder.class.getModule().addUses(RandomGenerator.class); return ServiceLoader - .load(RandomGenerator.class) + .load(RandomGenerator.class, ClassLoader.getPlatformClassLoader()) .stream() .filter(p -> !p.type().isInterface()) .collect(Collectors.toMap(p -> p.type().getSimpleName(), Function.identity())); @@ -341,9 +342,6 @@ private void ensureConstructors() { * {@link RandomGenerator} that utilize the {@code name} * algorithm. * - * @implSpec Availability is determined by RandomGeneratorFactory using the - * service provider API to locate implementations of the RandomGenerator interface. - * * @param name Name of random number generator * algorithm * @param Sub-interface of {@link RandomGenerator} to produce @@ -376,12 +374,9 @@ public static RandomGeneratorFactory getDefault() { /** * Returns a non-empty stream of available {@link RandomGeneratorFactory RandomGeneratorFactory(s)}. - * + *

* RandomGenerators that are marked as deprecated are not included in the result. * - * @implSpec Availability is determined by RandomGeneratorFactory using the service provider API - * to locate implementations of the RandomGenerator interface. - * * @return a non-empty stream of all available {@link RandomGeneratorFactory RandomGeneratorFactory(s)}. */ public static Stream> all() { @@ -615,5 +610,3 @@ public T create(byte[] seed) { } } - - diff --git a/src/java.base/share/classes/java/util/random/package-info.java b/src/java.base/share/classes/java/util/random/package-info.java index b4dfe28f796c4..2e16b319f44bb 100644 --- a/src/java.base/share/classes/java/util/random/package-info.java +++ b/src/java.base/share/classes/java/util/random/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, 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 @@ -50,9 +50,7 @@ *

The principal supporting class is {@link RandomGeneratorFactory}. This * can be used to generate multiple random number generators for a specific * algorithm. {@link RandomGeneratorFactory} also provides methods for - * selecting random number generator algorithms. RandomGeneratorFactory - * registers implementations of {@link RandomGenerator} interface using the - * service provider API. + * selecting random number generator algorithms. * *

An important subsidiary interface is * {@link RandomGenerator.StreamableGenerator}, which provides methods for @@ -636,4 +634,3 @@ * @since 17 */ package java.util.random; - diff --git a/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java b/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java index 2bf0c711cfece..6ec8b2a149a81 100644 --- a/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java +++ b/src/java.base/share/classes/java/util/spi/LocaleServiceProvider.java @@ -152,6 +152,11 @@ * supported by the Java runtime environment. The following table lists the * version of CLDR used in each JDK release. Unless otherwise specified, all * update releases in a given JDK release family use the same CLDR version. + * Note that the CLDR locale data are subject to change. Users should not assume + * that the locale data remain the same across CLDR versions. Otherwise, unexpected + * incompatible behaviors may occur, such as an exception on parsing a date. + * Refer to CLDR Releases + * for the deltas between their releases. * * * @@ -264,7 +269,7 @@ public boolean isSupportedLocale(Locale locale) { for (Locale available : getAvailableLocales()) { if (locale.equals(available.stripExtensions())) { return true; -} + } } return false; } diff --git a/src/java.base/share/classes/java/util/stream/StreamSpliterators.java b/src/java.base/share/classes/java/util/stream/StreamSpliterators.java index a098bb2f2acab..196cd76c8f821 100644 --- a/src/java.base/share/classes/java/util/stream/StreamSpliterators.java +++ b/src/java.base/share/classes/java/util/stream/StreamSpliterators.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 @@ -248,6 +248,11 @@ public final int characteristics() { c |= (spliterator.characteristics() & (Spliterator.SIZED | Spliterator.SUBSIZED)); } + // It's not allowed for a Spliterator to report SORTED if not also ORDERED + if ((c & Spliterator.SORTED) != 0 && (c & Spliterator.ORDERED) == 0) { + c &= ~(Spliterator.SORTED); + } + return c; } diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java index af7ff2e4aa255..c31e745cd89a6 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java @@ -26,6 +26,7 @@ package jdk.internal.access; import java.io.InputStream; +import java.io.PrintStream; import java.lang.annotation.Annotation; import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; @@ -401,6 +402,11 @@ public interface JavaLangAccess { */ InputStream initialSystemIn(); + /** + * Returns the initial value of System.err. + */ + PrintStream initialSystemErr(); + /** * Encodes ASCII codepoints as possible from the source array into * the destination byte array, assuming that the encoding is ASCII diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java index 4e9a55c77ac2c..e1598db154560 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java @@ -557,7 +557,7 @@ public BoundNewPrimitiveArrayInstruction(Opcode op, CodeImpl code, int pos) { @Override public TypeKind typeKind() { - return TypeKind.fromNewArrayCode(code.classReader.readU1(pos + 1)); + return TypeKind.fromNewarrayCode(code.classReader.readU1(pos + 1)); } @Override @@ -1149,7 +1149,7 @@ public TypeKind typeKind() { @Override public void writeTo(DirectCodeBuilder writer) { - writer.writeNewPrimitiveArray(typeKind.newarraycode()); + writer.writeNewPrimitiveArray(typeKind.newarrayCode()); } @Override diff --git a/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java b/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java index 5eee17573eed9..390ad1b2f97da 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java +++ b/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java @@ -26,6 +26,7 @@ package jdk.internal.foreign; import jdk.internal.vm.annotation.ForceInline; + import java.lang.foreign.AddressLayout; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; @@ -204,10 +205,7 @@ public VarHandle dereferenceHandle(boolean adapt) { String.format("Path does not select a value layout: %s", breadcrumbs())); } - // If we have an enclosing layout, drop the alignment check for the accessed element, - // we check the root layout instead - ValueLayout accessedLayout = enclosing != null ? valueLayout.withByteAlignment(1) : valueLayout; - VarHandle handle = accessedLayout.varHandle(); + VarHandle handle = valueLayout.varHandle(); handle = MethodHandles.collectCoordinates(handle, 1, offsetHandle()); // we only have to check the alignment of the root layout for the first dereference we do, diff --git a/src/java.base/share/classes/jdk/internal/misc/VM.java b/src/java.base/share/classes/jdk/internal/misc/VM.java index 9b51cfad458a8..de6f011fe8ffd 100644 --- a/src/java.base/share/classes/jdk/internal/misc/VM.java +++ b/src/java.base/share/classes/jdk/internal/misc/VM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -27,6 +27,7 @@ import static java.lang.Thread.State.*; +import java.io.PrintStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -496,4 +497,11 @@ private static class BufferPoolsHolder { public static List getBufferPools() { return BufferPoolsHolder.BUFFER_POOLS; } + + /** + * Return the initial value of System.err that was set during VM initialization. + */ + public static PrintStream initialErr() { + return SharedSecrets.getJavaLangAccess().initialSystemErr(); + } } diff --git a/src/jdk.random/share/classes/jdk/random/L128X1024MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L128X1024MixRandom.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/L128X1024MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L128X1024MixRandom.java index 46f8a642d54ad..e6f4f896dc0bf 100644 --- a/src/jdk.random/share/classes/jdk/random/L128X1024MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L128X1024MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 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 @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L128X128MixRandom.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L128X128MixRandom.java index ac12b96b4d227..d03fcfc086485 100644 --- a/src/jdk.random/share/classes/jdk/random/L128X128MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L128X128MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 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 @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L128X256MixRandom.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L128X256MixRandom.java index f34956e40a1e8..81440d7316a50 100644 --- a/src/jdk.random/share/classes/jdk/random/L128X256MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L128X256MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, 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 @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L32X64MixRandom.java similarity index 98% rename from src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L32X64MixRandom.java index 1b64a4b28cd92..0f6beea7bc796 100644 --- a/src/jdk.random/share/classes/jdk/random/L32X64MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L32X64MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 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 @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L64X1024MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L64X1024MixRandom.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/L64X1024MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L64X1024MixRandom.java index 9ec81997bde05..e4eb82d450ef2 100644 --- a/src/jdk.random/share/classes/jdk/random/L64X1024MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L64X1024MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 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 @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L64X128MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L64X128MixRandom.java similarity index 98% rename from src/jdk.random/share/classes/jdk/random/L64X128MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L64X128MixRandom.java index 4188e85e89f31..7dd757f312b1e 100644 --- a/src/jdk.random/share/classes/jdk/random/L64X128MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L64X128MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 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 @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L64X128StarStarRandom.java b/src/java.base/share/classes/jdk/internal/random/L64X128StarStarRandom.java similarity index 98% rename from src/jdk.random/share/classes/jdk/random/L64X128StarStarRandom.java rename to src/java.base/share/classes/jdk/internal/random/L64X128StarStarRandom.java index 139b27223b678..15b9bc312da3a 100644 --- a/src/jdk.random/share/classes/jdk/random/L64X128StarStarRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L64X128StarStarRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 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 @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/L64X256MixRandom.java b/src/java.base/share/classes/jdk/internal/random/L64X256MixRandom.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/L64X256MixRandom.java rename to src/java.base/share/classes/jdk/internal/random/L64X256MixRandom.java index 0c0cbb43687d8..bb605df5fdc87 100644 --- a/src/jdk.random/share/classes/jdk/random/L64X256MixRandom.java +++ b/src/java.base/share/classes/jdk/internal/random/L64X256MixRandom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 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 @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/Xoroshiro128PlusPlus.java b/src/java.base/share/classes/jdk/internal/random/Xoroshiro128PlusPlus.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/Xoroshiro128PlusPlus.java rename to src/java.base/share/classes/jdk/internal/random/Xoroshiro128PlusPlus.java index ba8daaf724661..d20b3cf9e6afa 100644 --- a/src/jdk.random/share/classes/jdk/random/Xoroshiro128PlusPlus.java +++ b/src/java.base/share/classes/jdk/internal/random/Xoroshiro128PlusPlus.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 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 @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/jdk.random/share/classes/jdk/random/Xoshiro256PlusPlus.java b/src/java.base/share/classes/jdk/internal/random/Xoshiro256PlusPlus.java similarity index 99% rename from src/jdk.random/share/classes/jdk/random/Xoshiro256PlusPlus.java rename to src/java.base/share/classes/jdk/internal/random/Xoshiro256PlusPlus.java index 5c9cc606597b1..fdefe02dd035d 100644 --- a/src/jdk.random/share/classes/jdk/random/Xoshiro256PlusPlus.java +++ b/src/java.base/share/classes/jdk/internal/random/Xoshiro256PlusPlus.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 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 @@ -23,7 +23,7 @@ * questions. */ -package jdk.random; +package jdk.internal.random; import java.util.concurrent.atomic.AtomicLong; import java.util.random.RandomGenerator; diff --git a/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java b/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java index be392c3ae2ddf..9c364cd781350 100644 --- a/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java +++ b/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java @@ -99,6 +99,21 @@ public final class ReferencedKeyMap implements Map { */ private final ReferenceQueue stale; + /** + * @return a supplier to create a {@code ConcurrentHashMap} appropriate for use in the + * create methods. + * @param the type of keys maintained by the new map + * @param the type of mapped values + */ + public static Supplier, V>> concurrentHashMapSupplier() { + return new Supplier<>() { + @Override + public Map, V> get() { + return new ConcurrentHashMap<>(); + } + }; + } + /** * Private constructor. * diff --git a/src/java.base/share/classes/jdk/internal/util/ReferencedKeySet.java b/src/java.base/share/classes/jdk/internal/util/ReferencedKeySet.java index 21b940439e00c..73ad6f326409d 100644 --- a/src/java.base/share/classes/jdk/internal/util/ReferencedKeySet.java +++ b/src/java.base/share/classes/jdk/internal/util/ReferencedKeySet.java @@ -75,6 +75,15 @@ public final class ReferencedKeySet extends AbstractSet { */ final ReferencedKeyMap> map; + /** + * @return a supplier to create a {@code ConcurrentHashMap} appropriate for use in the + * create methods. + * @param the type of elements maintained by this set + */ + public static Supplier, ReferenceKey>> concurrentHashMapSupplier() { + return ReferencedKeyMap.concurrentHashMapSupplier(); + } + /** * Private constructor. * diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 17a66b856a1e4..edbbad78c9da9 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -268,8 +268,6 @@ jdk.jfr; exports jdk.internal.util.xml.impl to jdk.jfr; - exports jdk.internal.util.random to - jdk.random; exports jdk.internal.util to java.desktop, java.prefs, @@ -396,7 +394,6 @@ uses java.time.chrono.AbstractChronology; uses java.time.chrono.Chronology; uses java.time.zone.ZoneRulesProvider; - uses java.util.random.RandomGenerator; uses java.util.spi.CalendarDataProvider; uses java.util.spi.CalendarNameProvider; uses java.util.spi.CurrencyNameProvider; @@ -425,6 +422,16 @@ provides java.util.random.RandomGenerator with java.security.SecureRandom, java.util.Random, - java.util.SplittableRandom; + java.util.SplittableRandom, + jdk.internal.random.L32X64MixRandom, + jdk.internal.random.L64X128MixRandom, + jdk.internal.random.L64X128StarStarRandom, + jdk.internal.random.L64X256MixRandom, + jdk.internal.random.L64X1024MixRandom, + jdk.internal.random.L128X128MixRandom, + jdk.internal.random.L128X256MixRandom, + jdk.internal.random.L128X1024MixRandom, + jdk.internal.random.Xoroshiro128PlusPlus, + jdk.internal.random.Xoshiro256PlusPlus; } diff --git a/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java b/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java index 9f65e32fa27cd..0ce080c20547f 100644 --- a/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java +++ b/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.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 @@ -259,6 +259,24 @@ private static Locale getParentLocale(Locale locale) { break; } } + + if (parent == null) { + // check nonlikelyScript locales + if (CLDRBaseLocaleDataMetaInfo.nonlikelyScript && locale.getCountry().isEmpty()) { + var lang = " " + locale.getLanguage() + " "; + var script= locale.getScript(); + if (!script.isEmpty()) { + parent = baseMetaInfo.likelyScriptMap().entrySet().stream() + .filter(e -> e.getValue().contains(lang)) + .findAny() + .map(Map.Entry::getKey) + .map(likely -> likely.equals(script) ? null : Locale.ROOT) + .orElse(null); + } + } + } + + // no parent found if (parent == null) { parent = locale; // non existent marker } diff --git a/src/java.base/share/classes/sun/util/locale/BaseLocale.java b/src/java.base/share/classes/sun/util/locale/BaseLocale.java index 7e0fc9a2d3477..ec2a6a49183ca 100644 --- a/src/java.base/share/classes/sun/util/locale/BaseLocale.java +++ b/src/java.base/share/classes/sun/util/locale/BaseLocale.java @@ -38,7 +38,7 @@ import jdk.internal.vm.annotation.Stable; import java.util.StringJoiner; -import java.util.concurrent.ConcurrentHashMap; +import java.util.function.UnaryOperator; public final class BaseLocale { @@ -93,7 +93,7 @@ public final class BaseLocale { // Interned BaseLocale cache private static final ReferencedKeySet CACHE = - ReferencedKeySet.create(true, ConcurrentHashMap::new); + ReferencedKeySet.create(true, ReferencedKeySet.concurrentHashMapSupplier()); public static final String SEP = "_"; @@ -164,13 +164,21 @@ public static BaseLocale getInstance(String language, String script, // "interned" instance can subsequently be used by the Locale // instance which guarantees the locale components are properly cased/interned. return CACHE.intern(new BaseLocale(language, script, region, variant), - (b) -> new BaseLocale( - LocaleUtils.toLowerString(b.language).intern(), - LocaleUtils.toTitleString(b.script).intern(), - LocaleUtils.toUpperString(b.region).intern(), - b.variant.intern())); + // Avoid lambdas since this may be on the bootstrap path in many locales + INTERNER); } + public static final UnaryOperator INTERNER = new UnaryOperator<>() { + @Override + public BaseLocale apply(BaseLocale b) { + return new BaseLocale( + LocaleUtils.toLowerString(b.language).intern(), + LocaleUtils.toTitleString(b.script).intern(), + LocaleUtils.toUpperString(b.region).intern(), + b.variant.intern()); + } + }; + public static String convertOldISOCodes(String language) { return switch (language) { case "he", "iw" -> OLD_ISO_CODES ? "iw" : "he"; diff --git a/src/java.base/share/data/publicsuffixlist/VERSION b/src/java.base/share/data/publicsuffixlist/VERSION index f86d2df03ca38..24f4407cc89ab 100644 --- a/src/java.base/share/data/publicsuffixlist/VERSION +++ b/src/java.base/share/data/publicsuffixlist/VERSION @@ -1,2 +1,2 @@ -Github: https://raw.githubusercontent.com/publicsuffix/list/b5bf572c52988dbe9d865b8f090ea819024a9936/public_suffix_list.dat -Date: 2023-11-09 +Github: https://raw.githubusercontent.com/publicsuffix/list/1cbd6e71a9b83620b1d0b11e49d3d9ff48c27e22/public_suffix_list.dat +Date: 2024-05-07 diff --git a/src/java.base/share/data/publicsuffixlist/public_suffix_list.dat b/src/java.base/share/data/publicsuffixlist/public_suffix_list.dat index fff6e9a494d64..34733674ea00f 100644 --- a/src/java.base/share/data/publicsuffixlist/public_suffix_list.dat +++ b/src/java.base/share/data/publicsuffixlist/public_suffix_list.dat @@ -6710,7 +6710,7 @@ org.zw // newGTLDs -// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2023-11-03T15:13:18Z +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2024-05-04T15:12:50Z // This list is auto-generated, don't edit it manually. // aaa : American Automobile Association, Inc. // https://www.iana.org/domains/root/db/aaa.html @@ -6896,7 +6896,7 @@ anquan // https://www.iana.org/domains/root/db/anz.html anz -// aol : Oath Inc. +// aol : Yahoo Inc. // https://www.iana.org/domains/root/db/aol.html aol @@ -6988,10 +6988,6 @@ auto // https://www.iana.org/domains/root/db/autos.html autos -// avianca : Avianca Inc. -// https://www.iana.org/domains/root/db/avianca.html -avianca - // aws : AWS Registry LLC // https://www.iana.org/domains/root/db/aws.html aws @@ -7016,10 +7012,6 @@ baidu // https://www.iana.org/domains/root/db/banamex.html banamex -// bananarepublic : The Gap, Inc. -// https://www.iana.org/domains/root/db/bananarepublic.html -bananarepublic - // band : Dog Beach, LLC // https://www.iana.org/domains/root/db/band.html band @@ -7544,10 +7536,6 @@ college // https://www.iana.org/domains/root/db/cologne.html cologne -// comcast : Comcast IP Holdings I, LLC -// https://www.iana.org/domains/root/db/comcast.html -comcast - // commbank : COMMONWEALTH BANK OF AUSTRALIA // https://www.iana.org/domains/root/db/commbank.html commbank @@ -7752,6 +7740,10 @@ dental // https://www.iana.org/domains/root/db/dentist.html dentist +// desi +// https://www.iana.org/domains/root/db/desi.html +desi + // design : Registry Services, LLC // https://www.iana.org/domains/root/db/design.html design @@ -7796,7 +7788,7 @@ discover // https://www.iana.org/domains/root/db/dish.html dish -// diy : Lifestyle Domain Holdings, Inc. +// diy : Internet Naming Company LLC // https://www.iana.org/domains/root/db/diy.html diy @@ -7928,10 +7920,6 @@ esq // https://www.iana.org/domains/root/db/estate.html estate -// etisalat : Emirates Telecommunications Corporation (trading as Etisalat) -// https://www.iana.org/domains/root/db/etisalat.html -etisalat - // eurovision : European Broadcasting Union (EBU) // https://www.iana.org/domains/root/db/eurovision.html eurovision @@ -8104,7 +8092,7 @@ fly // https://www.iana.org/domains/root/db/foo.html foo -// food : Lifestyle Domain Holdings, Inc. +// food : Internet Naming Company LLC // https://www.iana.org/domains/root/db/food.html food @@ -8164,7 +8152,7 @@ ftr // https://www.iana.org/domains/root/db/fujitsu.html fujitsu -// fun : Radix FZC DMCC +// fun : Radix Technologies Inc. // https://www.iana.org/domains/root/db/fun.html fun @@ -8312,7 +8300,7 @@ goldpoint // https://www.iana.org/domains/root/db/golf.html golf -// goo : NTT Resonant Inc. +// goo : NTT DOCOMO, INC. // https://www.iana.org/domains/root/db/goo.html goo @@ -8364,10 +8352,6 @@ grocery // https://www.iana.org/domains/root/db/group.html group -// guardian : The Guardian Life Insurance Company of America -// https://www.iana.org/domains/root/db/guardian.html -guardian - // gucci : Guccio Gucci S.p.a. // https://www.iana.org/domains/root/db/gucci.html gucci @@ -8500,7 +8484,7 @@ horse // https://www.iana.org/domains/root/db/hospital.html hospital -// host : Radix FZC DMCC +// host : Radix Technologies Inc. // https://www.iana.org/domains/root/db/host.html host @@ -8720,7 +8704,7 @@ jpmorgan // https://www.iana.org/domains/root/db/jprs.html jprs -// juegos : Internet Naming Company LLC +// juegos : Dog Beach, LLC // https://www.iana.org/domains/root/db/juegos.html juegos @@ -8908,7 +8892,7 @@ life // https://www.iana.org/domains/root/db/lifeinsurance.html lifeinsurance -// lifestyle : Lifestyle Domain Holdings, Inc. +// lifestyle : Internet Naming Company LLC // https://www.iana.org/domains/root/db/lifestyle.html lifestyle @@ -8948,7 +8932,7 @@ lipsy // https://www.iana.org/domains/root/db/live.html live -// living : Lifestyle Domain Holdings, Inc. +// living : Internet Naming Company LLC // https://www.iana.org/domains/root/db/living.html living @@ -9392,10 +9376,6 @@ olayan // https://www.iana.org/domains/root/db/olayangroup.html olayangroup -// oldnavy : The Gap, Inc. -// https://www.iana.org/domains/root/db/oldnavy.html -oldnavy - // ollo : Dish DBS Corporation // https://www.iana.org/domains/root/db/ollo.html ollo @@ -9416,7 +9396,7 @@ ong // https://www.iana.org/domains/root/db/onl.html onl -// online : Radix FZC DMCC +// online : Radix Technologies Inc. // https://www.iana.org/domains/root/db/online.html online @@ -9620,7 +9600,7 @@ pramerica // https://www.iana.org/domains/root/db/praxi.html praxi -// press : Radix FZC DMCC +// press : Radix Technologies Inc. // https://www.iana.org/domains/root/db/press.html press @@ -9928,10 +9908,6 @@ sbi // https://www.iana.org/domains/root/db/sbs.html sbs -// sca : SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ) -// https://www.iana.org/domains/root/db/sca.html -sca - // scb : The Siam Commercial Bank Public Company Limited ("SCB") // https://www.iana.org/domains/root/db/scb.html scb @@ -10076,7 +10052,7 @@ sina // https://www.iana.org/domains/root/db/singles.html singles -// site : Radix FZC DMCC +// site : Radix Technologies Inc. // https://www.iana.org/domains/root/db/site.html site @@ -10156,7 +10132,7 @@ soy // https://www.iana.org/domains/root/db/spa.html spa -// space : Radix FZC DMCC +// space : Radix Technologies Inc. // https://www.iana.org/domains/root/db/space.html space @@ -10208,7 +10184,7 @@ stockholm // https://www.iana.org/domains/root/db/storage.html storage -// store : Radix FZC DMCC +// store : Radix Technologies Inc. // https://www.iana.org/domains/root/db/store.html store @@ -10324,7 +10300,7 @@ tdk // https://www.iana.org/domains/root/db/team.html team -// tech : Radix FZC DMCC +// tech : Radix Technologies Inc. // https://www.iana.org/domains/root/db/tech.html tech @@ -10508,7 +10484,7 @@ unicom // https://www.iana.org/domains/root/db/university.html university -// uno : Radix FZC DMCC +// uno : Radix Technologies Inc. // https://www.iana.org/domains/root/db/uno.html uno @@ -10524,7 +10500,7 @@ ups // https://www.iana.org/domains/root/db/vacations.html vacations -// vana : Lifestyle Domain Holdings, Inc. +// vana : Internet Naming Company LLC // https://www.iana.org/domains/root/db/vana.html vana @@ -10608,10 +10584,6 @@ vlaanderen // https://www.iana.org/domains/root/db/vodka.html vodka -// volkswagen : Volkswagen Group of America Inc. -// https://www.iana.org/domains/root/db/volkswagen.html -volkswagen - // volvo : Volvo Holding Sverige Aktiebolag // https://www.iana.org/domains/root/db/volvo.html volvo @@ -10676,10 +10648,14 @@ webcam // https://www.iana.org/domains/root/db/weber.html weber -// website : Radix FZC DMCC +// website : Radix Technologies Inc. // https://www.iana.org/domains/root/db/website.html website +// wed +// https://www.iana.org/domains/root/db/wed.html +wed + // wedding : Registry Services, LLC // https://www.iana.org/domains/root/db/wedding.html wedding @@ -10768,10 +10744,6 @@ xbox // https://www.iana.org/domains/root/db/xerox.html xerox -// xfinity : Comcast IP Holdings I, LLC -// https://www.iana.org/domains/root/db/xfinity.html -xfinity - // xihuan : Beijing Qihu Keji Co., Ltd. // https://www.iana.org/domains/root/db/xihuan.html xihuan @@ -11012,10 +10984,6 @@ xin // https://www.iana.org/domains/root/db/xn--mgba7c0bbn0a.html العليان -// xn--mgbaakc7dvf : Emirates Telecommunications Corporation (trading as Etisalat) -// https://www.iana.org/domains/root/db/xn--mgbaakc7dvf.html -اتصالات - // xn--mgbab2bd : CORE Association // https://www.iana.org/domains/root/db/xn--mgbab2bd.html بازار @@ -11152,7 +11120,7 @@ xyz // https://www.iana.org/domains/root/db/yachts.html yachts -// yahoo : Oath Inc. +// yahoo : Yahoo Inc. // https://www.iana.org/domains/root/db/yahoo.html yahoo @@ -11217,6 +11185,12 @@ zuerich // ===BEGIN PRIVATE DOMAINS=== // (Note: these are in alphabetical order by company name) +// 12CHARS: https://12chars.com +// Submitted by Kenny Niehage +12chars.dev +12chars.it +12chars.pro + // 1GB LLC : https://www.1gb.ua/ // Submitted by 1GB LLC cc.ua @@ -11226,6 +11200,15 @@ ltd.ua // 611coin : https://611project.org/ 611.to +// AAA workspace : https://aaa.vodka +// Submitted by Kirill Rezraf +aaa.vodka + +// A2 Hosting +// Submitted by Tyler Hall +a2hosted.com +cpserver.com + // Aaron Marais' Gitlab pages: https://lab.aaronleem.co.za // Submitted by Aaron Marais graphox.us @@ -11242,12 +11225,18 @@ graphox.us // Submitted by Ofer Kalaora activetrail.biz +// Adaptable.io : https://adaptable.io +// Submitted by Mark Terrel +adaptable.app + // Adobe : https://www.adobe.com/ // Submitted by Ian Boston and Lars Trieloff adobeaemcloud.com *.dev.adobeaemcloud.com +aem.live hlx.live adobeaemcloud.net +aem.page hlx.page hlx3.page @@ -11319,7 +11308,7 @@ myamaze.net // Amazon API Gateway // Submitted by AWS Security -// Reference: 4d863337-ff98-4501-a6f2-361eba8445d6 +// Reference: 9e37648f-a66c-4655-9ab1-5981f8737197 execute-api.cn-north-1.amazonaws.com.cn execute-api.cn-northwest-1.amazonaws.com.cn execute-api.af-south-1.amazonaws.com @@ -11334,6 +11323,7 @@ execute-api.ap-southeast-2.amazonaws.com execute-api.ap-southeast-3.amazonaws.com execute-api.ap-southeast-4.amazonaws.com execute-api.ca-central-1.amazonaws.com +execute-api.ca-west-1.amazonaws.com execute-api.eu-central-1.amazonaws.com execute-api.eu-central-2.amazonaws.com execute-api.eu-north-1.amazonaws.com @@ -11360,23 +11350,28 @@ cloudfront.net // Amazon Cognito // Submitted by AWS Security -// Reference: 7bee1013-f456-47df-bfe8-03c78d946d61 +// Reference: 09588633-91fe-49d8-b4e7-ec36496d11f3 auth.af-south-1.amazoncognito.com auth.ap-northeast-1.amazoncognito.com auth.ap-northeast-2.amazoncognito.com auth.ap-northeast-3.amazoncognito.com auth.ap-south-1.amazoncognito.com +auth.ap-south-2.amazoncognito.com auth.ap-southeast-1.amazoncognito.com auth.ap-southeast-2.amazoncognito.com auth.ap-southeast-3.amazoncognito.com +auth.ap-southeast-4.amazoncognito.com auth.ca-central-1.amazoncognito.com auth.eu-central-1.amazoncognito.com +auth.eu-central-2.amazoncognito.com auth.eu-north-1.amazoncognito.com auth.eu-south-1.amazoncognito.com +auth.eu-south-2.amazoncognito.com auth.eu-west-1.amazoncognito.com auth.eu-west-2.amazoncognito.com auth.eu-west-3.amazoncognito.com auth.il-central-1.amazoncognito.com +auth.me-central-1.amazoncognito.com auth.me-south-1.amazoncognito.com auth.sa-east-1.amazoncognito.com auth.us-east-1.amazoncognito.com @@ -11399,7 +11394,7 @@ us-east-1.amazonaws.com // Amazon EMR // Submitted by AWS Security -// Reference: 597f3f8e-9283-4e48-8e32-7ee25a1ff6ab +// Reference: 82f43f9f-bbb8-400e-8349-854f5a62f20d emrappui-prod.cn-north-1.amazonaws.com.cn emrnotebooks-prod.cn-north-1.amazonaws.com.cn emrstudio-prod.cn-north-1.amazonaws.com.cn @@ -11424,6 +11419,9 @@ emrstudio-prod.ap-northeast-3.amazonaws.com emrappui-prod.ap-south-1.amazonaws.com emrnotebooks-prod.ap-south-1.amazonaws.com emrstudio-prod.ap-south-1.amazonaws.com +emrappui-prod.ap-south-2.amazonaws.com +emrnotebooks-prod.ap-south-2.amazonaws.com +emrstudio-prod.ap-south-2.amazonaws.com emrappui-prod.ap-southeast-1.amazonaws.com emrnotebooks-prod.ap-southeast-1.amazonaws.com emrstudio-prod.ap-southeast-1.amazonaws.com @@ -11433,18 +11431,30 @@ emrstudio-prod.ap-southeast-2.amazonaws.com emrappui-prod.ap-southeast-3.amazonaws.com emrnotebooks-prod.ap-southeast-3.amazonaws.com emrstudio-prod.ap-southeast-3.amazonaws.com +emrappui-prod.ap-southeast-4.amazonaws.com +emrnotebooks-prod.ap-southeast-4.amazonaws.com +emrstudio-prod.ap-southeast-4.amazonaws.com emrappui-prod.ca-central-1.amazonaws.com emrnotebooks-prod.ca-central-1.amazonaws.com emrstudio-prod.ca-central-1.amazonaws.com +emrappui-prod.ca-west-1.amazonaws.com +emrnotebooks-prod.ca-west-1.amazonaws.com +emrstudio-prod.ca-west-1.amazonaws.com emrappui-prod.eu-central-1.amazonaws.com emrnotebooks-prod.eu-central-1.amazonaws.com emrstudio-prod.eu-central-1.amazonaws.com +emrappui-prod.eu-central-2.amazonaws.com +emrnotebooks-prod.eu-central-2.amazonaws.com +emrstudio-prod.eu-central-2.amazonaws.com emrappui-prod.eu-north-1.amazonaws.com emrnotebooks-prod.eu-north-1.amazonaws.com emrstudio-prod.eu-north-1.amazonaws.com emrappui-prod.eu-south-1.amazonaws.com emrnotebooks-prod.eu-south-1.amazonaws.com emrstudio-prod.eu-south-1.amazonaws.com +emrappui-prod.eu-south-2.amazonaws.com +emrnotebooks-prod.eu-south-2.amazonaws.com +emrstudio-prod.eu-south-2.amazonaws.com emrappui-prod.eu-west-1.amazonaws.com emrnotebooks-prod.eu-west-1.amazonaws.com emrstudio-prod.eu-west-1.amazonaws.com @@ -11454,6 +11464,9 @@ emrstudio-prod.eu-west-2.amazonaws.com emrappui-prod.eu-west-3.amazonaws.com emrnotebooks-prod.eu-west-3.amazonaws.com emrstudio-prod.eu-west-3.amazonaws.com +emrappui-prod.il-central-1.amazonaws.com +emrnotebooks-prod.il-central-1.amazonaws.com +emrstudio-prod.il-central-1.amazonaws.com emrappui-prod.me-central-1.amazonaws.com emrnotebooks-prod.me-central-1.amazonaws.com emrstudio-prod.me-central-1.amazonaws.com @@ -11484,9 +11497,11 @@ emrstudio-prod.us-west-2.amazonaws.com // Amazon Managed Workflows for Apache Airflow // Submitted by AWS Security -// Reference: 4ab55e6f-90c0-4a8d-b6a0-52ca5dbb1c2e +// Reference: 87f24ece-a77e-40e8-bb4a-f6b74fe9f975 *.cn-north-1.airflow.amazonaws.com.cn *.cn-northwest-1.airflow.amazonaws.com.cn +*.af-south-1.airflow.amazonaws.com +*.ap-east-1.airflow.amazonaws.com *.ap-northeast-1.airflow.amazonaws.com *.ap-northeast-2.airflow.amazonaws.com *.ap-south-1.airflow.amazonaws.com @@ -11495,17 +11510,20 @@ emrstudio-prod.us-west-2.amazonaws.com *.ca-central-1.airflow.amazonaws.com *.eu-central-1.airflow.amazonaws.com *.eu-north-1.airflow.amazonaws.com +*.eu-south-1.airflow.amazonaws.com *.eu-west-1.airflow.amazonaws.com *.eu-west-2.airflow.amazonaws.com *.eu-west-3.airflow.amazonaws.com +*.me-south-1.airflow.amazonaws.com *.sa-east-1.airflow.amazonaws.com *.us-east-1.airflow.amazonaws.com *.us-east-2.airflow.amazonaws.com +*.us-west-1.airflow.amazonaws.com *.us-west-2.airflow.amazonaws.com // Amazon S3 // Submitted by AWS Security -// Reference: 0e801048-08f2-4064-9cb8-e7373e0b57f4 +// Reference: cd5c8b3a-67b7-4b40-9236-c87ce81a3d10 s3.dualstack.cn-north-1.amazonaws.com.cn s3-accesspoint.dualstack.cn-north-1.amazonaws.com.cn s3-website.dualstack.cn-north-1.amazonaws.com.cn @@ -11604,6 +11622,16 @@ s3-accesspoint-fips.ca-central-1.amazonaws.com s3-fips.ca-central-1.amazonaws.com s3-object-lambda.ca-central-1.amazonaws.com s3-website.ca-central-1.amazonaws.com +s3.dualstack.ca-west-1.amazonaws.com +s3-accesspoint.dualstack.ca-west-1.amazonaws.com +s3-accesspoint-fips.dualstack.ca-west-1.amazonaws.com +s3-fips.dualstack.ca-west-1.amazonaws.com +s3-website.dualstack.ca-west-1.amazonaws.com +s3.ca-west-1.amazonaws.com +s3-accesspoint.ca-west-1.amazonaws.com +s3-accesspoint-fips.ca-west-1.amazonaws.com +s3-fips.ca-west-1.amazonaws.com +s3-website.ca-west-1.amazonaws.com s3.dualstack.eu-central-1.amazonaws.com s3-accesspoint.dualstack.eu-central-1.amazonaws.com s3-website.dualstack.eu-central-1.amazonaws.com @@ -11784,9 +11812,25 @@ s3-fips.us-west-2.amazonaws.com s3-object-lambda.us-west-2.amazonaws.com s3-website.us-west-2.amazonaws.com +// Amazon SageMaker Ground Truth +// Submitted by AWS Security +// Reference: 98dbfde4-7802-48c3-8751-b60f204e0d9c +labeling.ap-northeast-1.sagemaker.aws +labeling.ap-northeast-2.sagemaker.aws +labeling.ap-south-1.sagemaker.aws +labeling.ap-southeast-1.sagemaker.aws +labeling.ap-southeast-2.sagemaker.aws +labeling.ca-central-1.sagemaker.aws +labeling.eu-central-1.sagemaker.aws +labeling.eu-west-1.sagemaker.aws +labeling.eu-west-2.sagemaker.aws +labeling.us-east-1.sagemaker.aws +labeling.us-east-2.sagemaker.aws +labeling.us-west-2.sagemaker.aws + // Amazon SageMaker Notebook Instances // Submitted by AWS Security -// Reference: fe8c9e94-5a22-486d-8750-991a3a9b13c6 +// Reference: b5ea56df-669e-43cc-9537-14aa172f5dfc notebook.af-south-1.sagemaker.aws notebook.ap-east-1.sagemaker.aws notebook.ap-northeast-1.sagemaker.aws @@ -11799,6 +11843,9 @@ notebook.ap-southeast-2.sagemaker.aws notebook.ap-southeast-3.sagemaker.aws notebook.ap-southeast-4.sagemaker.aws notebook.ca-central-1.sagemaker.aws +notebook-fips.ca-central-1.sagemaker.aws +notebook.ca-west-1.sagemaker.aws +notebook-fips.ca-west-1.sagemaker.aws notebook.eu-central-1.sagemaker.aws notebook.eu-central-2.sagemaker.aws notebook.eu-north-1.sagemaker.aws @@ -11820,6 +11867,7 @@ notebook-fips.us-gov-east-1.sagemaker.aws notebook.us-gov-west-1.sagemaker.aws notebook-fips.us-gov-west-1.sagemaker.aws notebook.us-west-1.sagemaker.aws +notebook-fips.us-west-1.sagemaker.aws notebook.us-west-2.sagemaker.aws notebook-fips.us-west-2.sagemaker.aws notebook.cn-north-1.sagemaker.com.cn @@ -11827,7 +11875,7 @@ notebook.cn-northwest-1.sagemaker.com.cn // Amazon SageMaker Studio // Submitted by AWS Security -// Reference: 057ee397-6bf8-4f20-b807-d7bc145ac980 +// Reference: 69c723d9-6e1a-4bff-a203-48eecd203183 studio.af-south-1.sagemaker.aws studio.ap-east-1.sagemaker.aws studio.ap-northeast-1.sagemaker.aws @@ -11841,6 +11889,7 @@ studio.ca-central-1.sagemaker.aws studio.eu-central-1.sagemaker.aws studio.eu-north-1.sagemaker.aws studio.eu-south-1.sagemaker.aws +studio.eu-south-2.sagemaker.aws studio.eu-west-1.sagemaker.aws studio.eu-west-2.sagemaker.aws studio.eu-west-3.sagemaker.aws @@ -11885,7 +11934,7 @@ analytics-gateway.us-west-2.amazonaws.com // AWS Cloud9 // Submitted by: AWS Security -// Reference: 05c44955-977c-4b57-938a-f2af92733f9f +// Reference: 30717f72-4007-4f0f-8ed4-864c6f2efec9 webview-assets.aws-cloud9.af-south-1.amazonaws.com vfs.cloud9.af-south-1.amazonaws.com webview-assets.cloud9.af-south-1.amazonaws.com @@ -11931,6 +11980,8 @@ webview-assets.cloud9.eu-west-2.amazonaws.com webview-assets.aws-cloud9.eu-west-3.amazonaws.com vfs.cloud9.eu-west-3.amazonaws.com webview-assets.cloud9.eu-west-3.amazonaws.com +webview-assets.aws-cloud9.il-central-1.amazonaws.com +vfs.cloud9.il-central-1.amazonaws.com webview-assets.aws-cloud9.me-south-1.amazonaws.com vfs.cloud9.me-south-1.amazonaws.com webview-assets.cloud9.me-south-1.amazonaws.com @@ -11950,6 +12001,11 @@ webview-assets.aws-cloud9.us-west-2.amazonaws.com vfs.cloud9.us-west-2.amazonaws.com webview-assets.cloud9.us-west-2.amazonaws.com +// AWS Directory Service +// Submitted by AWS Security +// Reference: a13203e8-42dc-4045-a0d2-2ee67bed1068 +awsapps.com + // AWS Elastic Beanstalk // Submitted by AWS Security // Reference: bb5a965c-dec3-4967-aa22-e306ad064797 @@ -11993,6 +12049,11 @@ us-west-2.elasticbeanstalk.com // Reference: d916759d-a08b-4241-b536-4db887383a6a awsglobalaccelerator.com +// AWS re:Post Private +// Submitted by AWS Security +// Reference: 83385945-225f-416e-9aa0-ad0632bfdcee +*.private.repost.aws + // eero // Submitted by Yue Kang // Reference: 264afe70-f62c-4c02-8ab9-b5281ed24461 @@ -12010,6 +12071,10 @@ tele.amune.org // Submitted by Apigee Security Team apigee.io +// Apis Networks: https://apisnetworks.com +// Submitted by Matt Saladna +panel.dev + // Apphud : https://apphud.com // Submitted by Alexander Selivanov siiites.com @@ -12027,6 +12092,10 @@ appudo.net // Submitted by Thomas Orozco on-aptible.com +// Aquapal : https://aquapal.net/ +// Submitted by Aki Ueno +f5.si + // ASEINet : https://www.aseinet.com/ // Submitted by Asei SEKIGUCHI user.aseinet.ne.jp @@ -12062,6 +12131,7 @@ autocode.dev // AVM : https://avm.de // Submitted by Andreas Weise +myfritz.link myfritz.net // AVStack Pte. Ltd. : https://avstack.io @@ -12121,10 +12191,18 @@ beagleboard.io // Submitted by Lev Nekrasov *.beget.app +// Besties : https://besties.house +// Submitted by Hazel Cora +pages.gay + // BetaInABox // Submitted by Adrian betainabox.com +// University of Bielsko-Biala regional domain: http://dns.bielsko.pl/ +// Submitted by Marcin +bielsko.pl + // BinaryLane : http://www.binarylane.com // Submitted by Nathan O'Sullivan bnr.la @@ -12166,8 +12244,13 @@ square7.de bplaced.net square7.net +// Brave : https://brave.com +// Submitted by Andrea Brancaleoni +*.s.brave.io + // Brendly : https://brendly.rs -// Submitted by Dusan Radovanovic +// Submitted by Dusan Radovanovic +shop.brendly.hr shop.brendly.rs // BrowserSafetyMark @@ -12191,7 +12274,9 @@ mycd.eu // Canva Pty Ltd : https://canva.com/ // Submitted by Joel Aquilina canva-apps.cn +*.my.canvasite.cn canva-apps.com +*.my.canva.site // Carrd : https://carrd.co // Submitted by AJ @@ -12329,6 +12414,12 @@ pages.dev r2.dev workers.dev +// cloudscale.ch AG : https://www.cloudscale.ch/ +// Submitted by Gaudenz Steinlin +cust.cloudscale.ch +objects.lpg.cloudscale.ch +objects.rma.cloudscale.ch + // Clovyr : https://clovyr.io // Submitted by Patrick Nielsen wnext.app @@ -12346,22 +12437,33 @@ co.cz // CDN77.com : http://www.cdn77.com // Submitted by Jan Krpes -c.cdn77.org +cdn77-storage.com +rsc.contentproxy9.cz cdn77-ssl.net r.cdn77.net -rsc.cdn77.org ssl.origin.cdn77-secure.org +c.cdn77.org +rsc.cdn77.org // Cloud DNS Ltd : http://www.cloudns.net -// Submitted by Aleksander Hristov +// Submitted by Aleksander Hristov & Boyan Peychev cloudns.asia +cloudns.be cloudns.biz -cloudns.club cloudns.cc +cloudns.ch +cloudns.cl +cloudns.club +dnsabr.com +cloudns.cx cloudns.eu cloudns.in cloudns.info +dns-cloud.net +dns-dynamic.net +cloudns.nz cloudns.org +cloudns.ph cloudns.pro cloudns.pw cloudns.us @@ -12374,6 +12476,11 @@ cnpy.gdn // Submitted by Moritz Marquardt codeberg.page +// CodeSandbox B.V. : https://codesandbox.io +// Submitted by Ives van Hoorne +csb.app +preview.csb.app + // CoDNS B.V. co.nl co.no @@ -12383,6 +12490,10 @@ co.no webhosting.be hosting-cluster.nl +// Convex : https://convex.dev/ +// Submitted by James Cowling +convex.site + // Coordination Center for TLD RU and XN--P1AI : https://cctld.ru/en/domains/domens_ru/reserved/ // Submitted by George Georgievsky ac.ru @@ -12404,10 +12515,18 @@ feste-ip.net knx-server.net static-access.net +// cPanel L.L.C. : https://www.cpanel.net/ +// Submitted by Dustin Scherer +*.cprapid.com + // Craynic, s.r.o. : http://www.craynic.com/ // Submitted by Ales Krajnik realm.cz +// Crisp IM SAS : https://crisp.chat/ +// Submitted by Baptiste Jamin +on.crisp.email + // Cryptonomic : https://cryptonomic.net/ // Submitted by Andrew Cady *.cryptonomic.net @@ -12428,6 +12547,13 @@ curv.dev *.ocp.customer-oci.com *.ocs.customer-oci.com +// Cyclic Software : https://www.cyclic.sh +// Submitted by Kam Lasater +cyclic.app +cyclic.cloud +cyclic-app.com +cyclic.co.in + // cyon GmbH : https://www.cyon.ch/ // Submitted by Dominic Luechinger cyon.link @@ -12473,6 +12599,7 @@ dyndns.dappnode.io // Dark, Inc. : https://darklang.com // Submitted by Paul Biggar builtwithdark.com +darklang.io // DataDetect, LLC. : https://datadetect.com // Submitted by Andrew Banchich @@ -12871,6 +12998,10 @@ ondigitalocean.app // Submitted by Robin H. Johnson *.digitaloceanspaces.com +// DigitalPlat : https://www.digitalplat.org/ +// Submitted by Edward Hsing +us.kg + // dnstrace.pro : https://dnstrace.pro/ // Submitted by Chris Partridge bci.dnstrace.pro @@ -12908,6 +13039,18 @@ e4.cz easypanel.app easypanel.host +// EasyWP : https://www.easywp.com +// Submitted by +*.ewp.live + +// Electromagnetic Field : https://www.emfcamp.org +// Submitted by +at.emf.camp + +// Elefunc, Inc. : https://elefunc.com +// Submitted by Cetin Sert +rt.ht + // Elementor : Elementor Ltd. // Submitted by Anton Barkan elementor.cloud @@ -13022,10 +13165,6 @@ url.tw // Submitted by Eric Jiang onfabrica.com -// Facebook, Inc. -// Submitted by Peter Ruibal -apps.fbsbx.com - // FAITID : https://faitid.org/ // Submitted by Maxim Alzoba // https://www.flexireg.net/stat_info @@ -13183,6 +13322,10 @@ flap.id onflashdrive.app fldrv.com +// FlutterFlow : https://flutterflow.io +// Submitted by Anton Emelyanov +flutterflow.app + // fly.io: https://fly.io // Submitted by Kurt Mackey fly.dev @@ -13193,13 +13336,14 @@ shw.io // Submitted by Jonathan Rudenberg flynnhosting.net -// Forgerock : https://www.forgerock.com +// Forgerock : https://www.forgerock.com // Submitted by Roderick Parr forgeblocks.com id.forgerock.io // Framer : https://www.framer.com -// Submitted by Koen Rouwhorst +// Submitted by Koen Rouwhorst +framer.ai framer.app framercanvas.com framer.media @@ -13240,6 +13384,24 @@ freemyip.com // Submitted by Daniel A. Maierhofer wien.funkfeuer.at +// Future Versatile Group. :https://www.fvg-on.net/ +// T.Kabu +daemon.asia +dix.asia +mydns.bz +0am.jp +0g0.jp +0j0.jp +0t0.jp +mydns.jp +pgw.jp +wjg.jp +keyword-on.net +live-on.net +server-on.net +mydns.tw +mydns.vc + // Futureweb GmbH : https://www.futureweb.at // Submitted by Andreas Schnederle-Wagner *.futurecms.at @@ -13251,6 +13413,10 @@ futuremailing.at *.kunden.ortsinfo.at *.statics.cloud +// GCom Internet : https://www.gcom.net.au +// Submitted by Leo Julius +aliases121.com + // GDS : https://www.gov.uk/service-manual/technology/managing-domain-names // Submitted by Stephen Ford independent-commission.uk @@ -13279,9 +13445,11 @@ gentlentapis.com lab.ms cdn-edges.net -// Ghost Foundation : https://ghost.org -// Submitted by Matt Hanley -ghost.io +// Getlocalcert: https://www.getlocalcert.net +// Submitted by Robert Alexander +localcert.net +localhostcert.net +corpnet.work // GignoSystemJapan: http://gsj.bz // Submitted by GignoSystemJapan @@ -13425,6 +13593,10 @@ whitesnow.jp zombie.jp heteml.net +// GoDaddy Registry : https://registry.godaddy +// Submitted by Rohan Durrant +graphic.design + // GOV.UK Platform as a Service : https://www.cloud.service.gov.uk/ // Submitted by Tom Whitwell cloudapps.digital @@ -13434,10 +13606,6 @@ london.cloudapps.digital // Submitted by Richard Baker pymnt.uk -// UKHomeOffice : https://www.gov.uk/government/organisations/home-office -// Submitted by Jon Shanks -homeoffice.gov.uk - // GlobeHosting, Inc. // Submitted by Zoltan Egresi ro.im @@ -13448,8 +13616,7 @@ goip.de // Google, Inc. // Submitted by Eduardo Vela -run.app -a.run.app +*.run.app web.app *.0emm.com appspot.com @@ -13549,6 +13716,10 @@ goupile.fr // Submitted by gov.nl +// GrayJay Web Solutions Inc. : https://grayjaysports.ca +// Submitted by Matt Yamkowy +grayjayleagues.com + // Group 53, LLC : https://www.group53.com // Submitted by Tyler Todd awsmppl.com @@ -13583,6 +13754,11 @@ hasura-app.io // Submitted by Richard Zowalla pages.it.hs-heilbronn.de +// Helio Networks : https://heliohost.org +// Submitted by Ben Frede +helioho.st +heliohost.us + // Hepforge : https://www.hepforge.org // Submitted by David Grellscheid hepforge.org @@ -13596,7 +13772,6 @@ herokussl.com // Submitted by Oren Eini ravendb.cloud ravendb.community -ravendb.me development.run ravendb.run @@ -13604,6 +13779,12 @@ ravendb.run // Submitted by Krzysztof Wolski homesklep.pl +// Homebase : https://homebase.id/ +// Submitted by Jason Babo +*.kin.one +*.id.pub +*.kin.pub + // Hong Kong Productivity Council: https://www.hkpc.org/ // Submitted by SECaaS Team secaas.hk @@ -13681,7 +13862,7 @@ biz.at info.at // info.cx : http://info.cx -// Submitted by Jacob Slater +// Submitted by June Slater info.cx // Interlegis : http://www.interlegis.leg.br @@ -13730,6 +13911,14 @@ iopsys.se // Submitted by Matthew Hardeman ipifony.net +// is-a.dev : https://www.is-a.dev +// Submitted by William Harrison +is-a.dev + +// ir.md : https://nic.ir.md +// Submitted by Ali Soizi +ir.md + // IServ GmbH : https://iserv.de // Submitted by Mario Hoberg iservschule.de @@ -13838,6 +14027,11 @@ myjino.ru // Submitted by Daniel Fariña jotelulu.cloud +// JouwWeb B.V. : https://www.jouwweb.nl +// Submitted by Camilo Sperberg +jouwweb.site +webadorsite.com + // Joyent : https://www.joyent.com/ // Submitted by Brian Bennett *.triton.zone @@ -13911,6 +14105,10 @@ lpusercontent.com // Submitted by Lelux Admin lelux.site +// Libre IT Ltd : https://libre.nz +// Submitted by Tomas Maggio +runcontainers.dev + // Lifetime Hosting : https://Lifetime.Hosting/ // Submitted by Mike Fillator co.business @@ -13921,10 +14119,6 @@ co.network co.place co.technology -// Lightmaker Property Manager, Inc. : https://app.lmpm.com/ -// Submitted by Greg Holland -app.lmpm.com - // linkyard ldt: https://www.linkyard.ch/ // Submitted by Mario Siegenthaler linkyard.cloud @@ -14057,6 +14251,11 @@ memset.net // Submitted by Ruben Schmidmeister messerli.app +// Meta Platforms, Inc. : https://meta.com/ +// Submitted by Jacob Cordero +atmeta.com +apps.fbsbx.com + // MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ // Submitted by Zdeněk Šustr *.cloud.metacentrum.cz @@ -14077,10 +14276,14 @@ co.pl // Microsoft Corporation : http://microsoft.com // Submitted by Public Suffix List Admin +// Managed by Corporate Domains +// Microsoft Azure : https://home.azure *.azurecontainer.io +azure-api.net +azureedge.net +azurefd.net azurewebsites.net azure-mobile.net -cloudapp.net azurestaticapps.net 1.azurestaticapps.net 2.azurestaticapps.net @@ -14094,6 +14297,10 @@ eastasia.azurestaticapps.net eastus2.azurestaticapps.net westeurope.azurestaticapps.net westus2.azurestaticapps.net +cloudapp.net +trafficmanager.net +blob.core.windows.net +servicebus.windows.net // minion.systems : http://minion.systems // Submitted by Robert Böttinger @@ -14107,6 +14314,10 @@ mintere.site // Submitted by Grayson Martin forte.id +// MODX Systems LLC : https://modx.com +// Submitted by Elizabeth Southwell +modx.dev + // Mozilla Corporation : https://mozilla.com // Submitted by Ben Francis mozilla-iot.org @@ -14153,6 +14364,10 @@ netlify.app // Submitted by Trung Tran 4u.com +// NGO.US Registry : https://nic.ngo.us +// Submitted by Alstra Solutions Ltd. Networking Team +ngo.us + // ngrok : https://ngrok.com/ // Submitted by Alan Shreve ngrok.app @@ -14168,18 +14383,24 @@ jp.ngrok.io sa.ngrok.io us.ngrok.io ngrok.pizza +ngrok.pro // Nicolaus Copernicus University in Torun - MSK TORMAN (https://www.man.torun.pl) torun.pl // Nimbus Hosting Ltd. : https://www.nimbushosting.co.uk/ -// Submitted by Nicholas Ford +// Submitted by Nicholas Ford nh-serv.co.uk +nimsite.uk // NFSN, Inc. : https://www.NearlyFreeSpeech.NET/ // Submitted by Jeff Wheelhouse nfshost.com +// NFT.Storage : https://nft.storage/ +// Submitted by Vasco Santos or +ipfs.nftstorage.link + // Noop : https://noop.app // Submitted by Nathaniel Schweinberg *.developer.app @@ -14330,6 +14551,10 @@ pcloud.host // Submitted by Matthew Brown nyc.mn +// O3O.Foundation : https://o3o.foundation/ +// Submitted by the prvcy.page Registry Team +prvcy.page + // Observable, Inc. : https://observablehq.com // Submitted by Mike Bostock static.observableusercontent.com @@ -14359,7 +14584,6 @@ omniwe.site 123minsida.se 123miweb.es 123paginaweb.pt -123sait.ru 123siteweb.fr 123webseite.at 123webseite.de @@ -14377,6 +14601,13 @@ simplesite.pl // Submitted by Eddie Jones nid.io +// Open Domains : https://open-domains.net +// Submitted by William Harrison +is-cool.dev +is-not-a.dev +localplayer.dev +is-local.org + // Open Social : https://www.getopensocial.com/ // Submitted by Alexander Varwijk opensocial.site @@ -14397,6 +14628,11 @@ operaunite.com // Submitted by Alexandre Linte tech.orange +// OsSav Technology Ltd. : https://ossav.com/ +// TLD Nic: http://nic.can.re - TLD Whois Server: whois.can.re +// Submitted by OsSav Technology Ltd. +can.re + // Oursky Limited : https://authgear.com/, https://skygear.io/ // Submitted by Authgear Team , Skygear Developer authgear-staging.com @@ -14447,10 +14683,11 @@ pagexl.com // pcarrier.ca Software Inc: https://pcarrier.ca/ // Submitted by Pierre Carrier -bar0.net -bar1.net -bar2.net -rdv.to +*.xmit.co +xmit.dev +srv.us +gh.srv.us +gl.srv.us // .pl domains (grandfathered) art.pl @@ -14483,7 +14720,8 @@ on-web.fr // Platform.sh : https://platform.sh // Submitted by Nikola Kotur -bc.platform.sh +*.upsun.app +upsunapp.com ent.platform.sh eu.platform.sh us.platform.sh @@ -14502,6 +14740,10 @@ pdns.page plesk.page pleskns.com +// Pley AB : https://www.pley.com/ +// Submitted by Henning Pohl +pley.games + // Port53 : https://port53.io/ // Submitted by Maximilian Schieder dyn53.io @@ -14533,10 +14775,6 @@ xen.prgmr.com // Submitted by registry priv.at -// privacytools.io : https://www.privacytools.io/ -// Submitted by Jonah Aragon -prvcy.page - // Protocol Labs : https://protocol.ai/ // Submitted by Michael Burns *.dweb.link @@ -14578,6 +14816,8 @@ qbuser.com // Rad Web Hosting: https://radwebhosting.com // Submitted by Scott Claeys cloudsite.builders +myradweb.net +servername.us // Redgate Software: https://red-gate.com // Submitted by Andrew Farries @@ -14601,9 +14841,12 @@ qcx.io *.sys.qcx.io // QNAP System Inc : https://www.qnap.com -// Submitted by Nick Chang -dev-myqnapcloud.com +// Submitted by Nick Chang +myqnapcloud.cn alpha-myqnapcloud.com +dev-myqnapcloud.com +mycloudnas.com +mynascloud.com myqnapcloud.com // Quip : https://quip.com @@ -14644,11 +14887,40 @@ app.render.com onrender.com // Repl.it : https://repl.it -// Submitted by Lincoln Bergeson +// Submitted by Lincoln Bergeson +replit.app +id.replit.app firewalledreplit.co id.firewalledreplit.co repl.co id.repl.co +replit.dev +archer.replit.dev +bones.replit.dev +canary.replit.dev +global.replit.dev +hacker.replit.dev +id.replit.dev +janeway.replit.dev +kim.replit.dev +kira.replit.dev +kirk.replit.dev +odo.replit.dev +paris.replit.dev +picard.replit.dev +pike.replit.dev +prerelease.replit.dev +reed.replit.dev +riker.replit.dev +sisko.replit.dev +spock.replit.dev +staging.replit.dev +sulu.replit.dev +tarpit.replit.dev +teams.replit.dev +tucker.replit.dev +wesley.replit.dev +worf.replit.dev repl.run // Resin.io : https://resin.io @@ -14745,10 +15017,11 @@ from.tv sakura.tv // Salesforce.com, Inc. https://salesforce.com/ -// Submitted by Michael Biven +// Submitted by Michael Biven and Aaron Romeo *.builder.code.com *.dev-builder.code.com *.stg-builder.code.com +*.001.test.code-builder-stg.platform.salesforce.com // Sandstorm Development Group, Inc. : https://sandcats.io/ // Submitted by Asheesh Laroia @@ -14764,6 +15037,7 @@ logoip.com fr-par-1.baremetal.scw.cloud fr-par-2.baremetal.scw.cloud nl-ams-1.baremetal.scw.cloud +cockpit.fr-par.scw.cloud fnc.fr-par.scw.cloud functions.fnc.fr-par.scw.cloud k8s.fr-par.scw.cloud @@ -14774,11 +15048,13 @@ whm.fr-par.scw.cloud priv.instances.scw.cloud pub.instances.scw.cloud k8s.scw.cloud +cockpit.nl-ams.scw.cloud k8s.nl-ams.scw.cloud nodes.k8s.nl-ams.scw.cloud s3.nl-ams.scw.cloud s3-website.nl-ams.scw.cloud whm.nl-ams.scw.cloud +cockpit.pl-waw.scw.cloud k8s.pl-waw.scw.cloud nodes.k8s.pl-waw.scw.cloud s3.pl-waw.scw.cloud @@ -14800,6 +15076,10 @@ service.gov.scot // Submitted by Shante Adam scrysec.com +// Scrypted : https://scrypted.app +// Submitted by Koushik Dutta +client.scrypted.io + // Securepoint GmbH : https://www.securepoint.de // Submitted by Erik Anders firewall-gateway.com @@ -14839,6 +15119,10 @@ biz.ua co.ua pp.ua +// Sheezy.Art : https://sheezy.art +// Submitted by Nyoom +sheezy.games + // Shift Crypto AG : https://shiftcrypto.ch // Submitted by alex shiftcrypto.dev @@ -14887,7 +15171,7 @@ alpha.bounty-full.com beta.bounty-full.com // Smallregistry by Promopixel SARL: https://www.smallregistry.net -// Former AFNIC's SLDs +// Former AFNIC's SLDs // Submitted by Jérôme Lipowicz aeroport.fr avocat.fr @@ -14909,9 +15193,9 @@ small-web.org vp4.me // Snowflake Inc : https://www.snowflake.com/ -// Submitted by Faith Olapade -snowflake.app -privatelink.snowflake.app +// Submitted by Sam Haar +*.snowflake.app +*.privatelink.snowflake.app streamlit.app streamlitapp.com @@ -14923,10 +15207,24 @@ try-snowplow.com // Submitted by Drew DeVault srht.site +// StackBlitz : https://stackblitz.com +// Submitted by Dominic Elm +w-corp-staticblitz.com +w-credentialless-staticblitz.com +w-staticblitz.com + // Stackhero : https://www.stackhero.io // Submitted by Adrien Gillon stackhero-network.com +// STACKIT : https://www.stackit.de/en/ +// Submitted by STACKIT-DNS Team (Simon Stier) +runs.onstackit.cloud +stackit.gg +stackit.rocks +stackit.run +stackit.zone + // Staclar : https://staclar.com // Submitted by Q Misell musician.io @@ -14993,6 +15291,19 @@ myspreadshop.co.uk // Submitted by Jacob Lee api.stdlib.com +// stereosense GmbH : https://www.involve.me +// Submitted by Florian Burmann +feedback.ac +forms.ac +assessments.cx +calculators.cx +funnels.cx +paynow.cx +quizzes.cx +researched.cx +tests.cx +surveys.so + // Storipress : https://storipress.com // Submitted by Benno Liu storipress.app @@ -15001,6 +15312,12 @@ storipress.app // Submitted by Philip Hutchins storj.farm +// Streak : https://streak.com +// Submitted by Blake Kadatz +streak-link.com +streaklinks.com +streakusercontent.com + // Studenten Net Twente : http://www.snt.utwente.nl/ // Submitted by Silke Hofstra utwente.io @@ -15063,6 +15380,7 @@ taifun-dns.de // Submitted by David Anderson beta.tailscale.net ts.net +*.c.ts.net // TASK geographical domains (www.task.gda.pl/uslugi/dns) gda.pl @@ -15196,6 +15514,10 @@ inc.hk // Submitted by ITComdomains it.com +// Unison Computing, PBC : https://unison.cloud +// Submitted by Simon Højberg +unison-services.cloud + // UNIVERSAL DOMAIN REGISTRY : https://www.udr.org.yt/ // see also: whois -h whois.udr.org.yt help // Submitted by Atanunu Igbunuroghene @@ -15245,48 +15567,6 @@ v-info.info // Submitted by Nathan van Bakel voorloper.cloud -// Voxel.sh DNS : https://voxel.sh/dns/ -// Submitted by Mia Rehlinger -neko.am -nyaa.am -be.ax -cat.ax -es.ax -eu.ax -gg.ax -mc.ax -us.ax -xy.ax -nl.ci -xx.gl -app.gp -blog.gt -de.gt -to.gt -be.gy -cc.hn -blog.kg -io.kg -jp.kg -tv.kg -uk.kg -us.kg -de.ls -at.md -de.md -jp.md -to.md -indie.porn -vxl.sh -ch.tc -me.tc -we.tc -nyan.to -at.vg -blog.vu -dev.vu -me.vu - // V.UA Domain Administrator : https://domain.v.ua/ // Submitted by Serhii Rostilo v.ua @@ -15299,6 +15579,11 @@ v.ua // Submitted by Masayuki Note wafflecell.com +// Webflow, Inc. : https://www.webflow.com +// Submitted by Webflow Security Team +webflow.io +webflowtest.io + // WebHare bv: https://www.webhare.com/ // Submitted by Arnold Hendriks *.webhare.dev @@ -15310,6 +15595,10 @@ reserve-online.com bookonline.app hotelwithflight.com +// WebWaddle Ltd: https://webwaddle.com/ +// Submitted by Merlin Glander +*.wadl.top + // WeDeploy by Liferay, Inc. : https://www.wedeploy.com // Submitted by Henrique Vicente wedeploy.io @@ -15418,6 +15707,10 @@ noho.st za.net za.org +// ZAP-Hosting GmbH & Co. KG : https://zap-hosting.com +// Submitted by Julian Alker +zap.cloud + // Zine EOOD : https://zine.bg/ // Submitted by Martin Angelov bss.design diff --git a/src/java.base/share/legal/public_suffix.md b/src/java.base/share/legal/public_suffix.md index 493f3b1680dfb..02481558af654 100644 --- a/src/java.base/share/legal/public_suffix.md +++ b/src/java.base/share/legal/public_suffix.md @@ -11,7 +11,7 @@ If you do not wish to use the Public Suffix List, you may remove the The Source Code of this file is available under the Mozilla Public License, v. 2.0 and is located at -https://raw.githubusercontent.com/publicsuffix/list/b5bf572c52988dbe9d865b8f090ea819024a9936/public_suffix_list.dat. +https://raw.githubusercontent.com/publicsuffix/list/1cbd6e71a9b83620b1d0b11e49d3d9ff48c27e22/public_suffix_list.dat. If a copy of the MPL was not distributed with this file, you can obtain one at https://mozilla.org/MPL/2.0/. diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java index 72b8c759e30b5..65f29ea8384fe 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -348,6 +348,8 @@ protected void initComponentDefaults(UIDefaults table) { Double defaultCaretAspectRatio = Double.valueOf(0.025); Color caretColor = table.getColor("caretColor"); Color controlText = table.getColor("controlText"); + Color tabbedPaneBg = new ColorUIResource(238, 238, 238); + Color unselectedTabColor = new ColorUIResource(255, 255, 255); Object fieldInputMap = new UIDefaults.LazyInputMap(new Object[] { "ctrl C", DefaultEditorKit.copyAction, @@ -1020,6 +1022,11 @@ public Object createValue(UIDefaults table) { "TabbedPane.selectedLabelShift", 3, "TabbedPane.font", new FontLazyValue(Region.TABBED_PANE), "TabbedPane.selectedTabPadInsets", new InsetsUIResource(2, 2, 0, 1), + "TabbedPane.selected", tabbedPaneBg, + "TabbedPane.contentOpaque", Boolean.TRUE, + "TabbedPane.tabsOpaque", Boolean.TRUE, + "TabbedPane.contentAreaColor", tabbedPaneBg, + "TabbedPane.unselectedBackground", unselectedTabColor, "Table.scrollPaneBorder", zeroBorder, "Table.background", tableBg, diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java index 1635ff66f89c1..e643d3d28ff3d 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -972,6 +972,9 @@ public void paintTabbedPaneTabBackground(SynthContext context, JTabbedPane pane = (JTabbedPane)context.getComponent(); int placement = pane.getTabPlacement(); + // Fill the tab rect area + g.fillRect(x, y, w, h); + synchronized (UNIXToolkit.GTK_LOCK) { if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, placement, tabIndex)) { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf index 38e8530983aad..1d486f9fe0644 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf +++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/skin.laf @@ -1,7 +1,7 @@
JDK releases and supported CLDR versions