diff --git a/.hgtags b/.hgtags index 388dda57f39..87ac6618472 100644 --- a/.hgtags +++ b/.hgtags @@ -598,3 +598,4 @@ c16ac7a2eba4e73cb4f7ee9294dd647860eebff0 jdk-14+21 15936b142f86731afa4b1a2c0fe4a01e806c4944 jdk-14+23 438337c846fb071900ddb6922bddf8b3e895a514 jdk-14+24 17d242844fc9e7d18b3eac97426490a9c246119e jdk-14+25 +288777cf0702914e5266bc1e5d380eed9032ca41 jdk-14+26 diff --git a/doc/testing.html b/doc/testing.html index 0587be1b237..5b8dde5cecf 100644 --- a/doc/testing.html +++ b/doc/testing.html @@ -168,6 +168,8 @@ TEST FAILURE

Additional VM options to JTReg (-vmoption).

AOT_MODULES

Generate AOT modules before testing for the specified module, or set of modules. If multiple modules are specified, they should be separated by space (or, to help avoid quoting issues, the special value %20).

+

RETRY_COUNT

+

Retry failed tests up to a set number of times. Defaults to 0.

Gtest keywords

REPEAT

The number of times to repeat the tests (--gtest_repeat).

diff --git a/doc/testing.md b/doc/testing.md index 308dcf57daf..ed1c786a00e 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -332,6 +332,10 @@ Generate AOT modules before testing for the specified module, or set of modules. If multiple modules are specified, they should be separated by space (or, to help avoid quoting issues, the special value `%20`). +#### RETRY_COUNT + +Retry failed tests up to a set number of times. Defaults to 0. + ### Gtest keywords #### REPEAT diff --git a/make/CompileInterimLangtools.gmk b/make/CompileInterimLangtools.gmk index 736dfd70280..a0854914862 100644 --- a/make/CompileInterimLangtools.gmk +++ b/make/CompileInterimLangtools.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -80,6 +80,7 @@ define SetupInterimModule ADD_JAVAC_FLAGS := --module-path $(BUILDTOOLS_OUTPUTDIR)/interim_langtools_modules \ $$(INTERIM_LANGTOOLS_ADD_EXPORTS) \ --patch-module java.base=$(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim \ + --add-exports java.base/jdk.internal=java.compiler.interim \ --add-exports java.base/jdk.internal=jdk.compiler.interim \ -Xlint:-module, \ )) diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index 12623377546..15477c1b693 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -380,6 +380,13 @@ endif ################################################################################ +jdk.incubator.jpackage_COPY += .gif .png .txt .spec .script .prerm .preinst .postrm .postinst .list .sh \ + .desktop .copyright .control .plist .template .icns .scpt .entitlements .wxs .wxl .wxi .ico .bmp + +jdk.incubator.jpackage_CLEAN += .properties + +################################################################################ + jdk.jconsole_COPY += .gif .png jdk.jconsole_CLEAN_FILES += $(wildcard \ diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 916dde0f3cb..92bbe782502 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -300,7 +300,8 @@ $(eval $(call SetTestOpt,FAILURE_HANDLER_TIMEOUT,JTREG)) $(eval $(call ParseKeywordVariable, JTREG, \ SINGLE_KEYWORDS := JOBS TIMEOUT_FACTOR FAILURE_HANDLER_TIMEOUT \ - TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM RUN_PROBLEM_LISTS, \ + TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM RUN_PROBLEM_LISTS \ + RETRY_COUNT, \ STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS KEYWORDS \ EXTRA_PROBLEM_LISTS AOT_MODULES, \ )) @@ -851,6 +852,7 @@ define SetupRunJtregTestBody JTREG_VERBOSE ?= fail,error,summary JTREG_RETAIN ?= fail,error JTREG_RUN_PROBLEM_LISTS ?= false + JTREG_RETRY_COUNT ?= 0 ifneq ($$($1_JTREG_MAX_MEM), 0) $1_JTREG_BASIC_OPTIONS += -vmoption:-Xmx$$($1_JTREG_MAX_MEM) @@ -942,25 +944,43 @@ define SetupRunJtregTestBody clean-workdir-$1: $$(RM) -r $$($1_TEST_SUPPORT_DIR) + $1_COMMAND_LINE := \ + $$(JAVA) $$($1_JTREG_LAUNCHER_OPTIONS) \ + -Dprogram=jtreg -jar $$(JT_HOME)/lib/jtreg.jar \ + $$($1_JTREG_BASIC_OPTIONS) \ + -testjdk:$$(JDK_UNDER_TEST) \ + -dir:$$(JTREG_TOPDIR) \ + -reportDir:$$($1_TEST_RESULTS_DIR) \ + -workDir:$$($1_TEST_SUPPORT_DIR) \ + -status:$$$${JTREG_STATUS} \ + $$(JTREG_OPTIONS) \ + $$(JTREG_FAILURE_HANDLER_OPTIONS) \ + $$(JTREG_COV_OPTIONS) \ + $$($1_TEST_NAME) \ + && $$(ECHO) $$$$? > $$($1_EXITCODE) \ + || $$(ECHO) $$$$? > $$($1_EXITCODE) + + + ifneq ($$(JTREG_RETRY_COUNT), 0) + $1_COMMAND_LINE := \ + for i in {0..$$(JTREG_RETRY_COUNT)}; do \ + if [ "$$$$i" != 0 ]; then \ + $$(PRINTF) "\nRetrying Jtreg run. Attempt: $$$$i\n"; \ + fi; \ + $$($1_COMMAND_LINE); \ + if [ "`$$(CAT) $$($1_EXITCODE)`" = "0" ]; then \ + break; \ + fi; \ + export JTREG_STATUS="-status:error,fail"; \ + done + endif + run-test-$1: pre-run-test clean-workdir-$1 $$($1_AOT_TARGETS) $$(call LogWarn) $$(call LogWarn, Running test '$$($1_TEST)') $$(call MakeDir, $$($1_TEST_RESULTS_DIR) $$($1_TEST_SUPPORT_DIR)) $$(call ExecuteWithLog, $$($1_TEST_SUPPORT_DIR)/jtreg, ( \ - $$(COV_ENVIRONMENT) \ - $$(JAVA) $$($1_JTREG_LAUNCHER_OPTIONS) \ - -Dprogram=jtreg -jar $$(JT_HOME)/lib/jtreg.jar \ - $$($1_JTREG_BASIC_OPTIONS) \ - -testjdk:$$(JDK_UNDER_TEST) \ - -dir:$$(JTREG_TOPDIR) \ - -reportDir:$$($1_TEST_RESULTS_DIR) \ - -workDir:$$($1_TEST_SUPPORT_DIR) \ - $$(JTREG_OPTIONS) \ - $$(JTREG_FAILURE_HANDLER_OPTIONS) \ - $$(JTREG_COV_OPTIONS) \ - $$($1_TEST_NAME) \ - && $$(ECHO) $$$$? > $$($1_EXITCODE) \ - || $$(ECHO) $$$$? > $$($1_EXITCODE) \ + $$(COV_ENVIRONMENT) $$($1_COMMAND_LINE) \ )) $1_RESULT_FILE := $$($1_TEST_RESULTS_DIR)/text/stats.txt diff --git a/make/autoconf/boot-jdk.m4 b/make/autoconf/boot-jdk.m4 index cbfaeaadfbe..8aa2547f429 100644 --- a/make/autoconf/boot-jdk.m4 +++ b/make/autoconf/boot-jdk.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -345,7 +345,7 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK], # When compiling code to be executed by the Boot JDK, force compatibility with the # oldest supported bootjdk. - BOOT_JDK_SOURCETARGET="-source 9 -target 9" + BOOT_JDK_SOURCETARGET="-source 13 -target 13" AC_SUBST(BOOT_JDK_SOURCETARGET) AC_SUBST(JAVAC_FLAGS) diff --git a/make/autoconf/hotspot.m4 b/make/autoconf/hotspot.m4 index f340faebd39..649e48cb675 100644 --- a/make/autoconf/hotspot.m4 +++ b/make/autoconf/hotspot.m4 @@ -347,7 +347,8 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES], # Only enable ZGC on supported platforms AC_MSG_CHECKING([if zgc can be built]) if (test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xx86_64") || \ - (test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xaarch64") || + (test "x$OPENJDK_TARGET_OS" = "xlinux" && test "x$OPENJDK_TARGET_CPU" = "xaarch64") || \ + (test "x$OPENJDK_TARGET_OS" = "xwindows" && test "x$OPENJDK_TARGET_CPU" = "xx86_64") || \ (test "x$OPENJDK_TARGET_OS" = "xmacosx" && test "x$OPENJDK_TARGET_CPU" = "xx86_64"); then AC_MSG_RESULT([yes]) else diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk index 8587d48ef63..5833b6c8233 100644 --- a/make/common/Modules.gmk +++ b/make/common/Modules.gmk @@ -128,6 +128,7 @@ endif JRE_TOOL_MODULES += \ jdk.jdwp.agent \ + jdk.incubator.jpackage \ jdk.pack \ jdk.scripting.nashorn.shell \ # @@ -149,6 +150,7 @@ DOCS_MODULES += \ jdk.editpad \ jdk.hotspot.agent \ jdk.httpserver \ + jdk.incubator.jpackage \ jdk.jartool \ jdk.javadoc \ jdk.jcmd \ @@ -242,6 +244,13 @@ ifeq ($(ENABLE_AOT), false) MODULES_FILTER += jdk.aot endif +################################################################################ +# jpackage is only on windows, macosx, and linux + +ifeq ($(call isTargetOs, windows macosx linux), false) + MODULES_FILTER += jdk.incubator.jpackage +endif + ################################################################################ # Module list macros diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index 56f771f5f44..6bad327bc99 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -397,6 +397,7 @@ endef # ARFLAGS the archiver flags to be used # OBJECT_DIR the directory where we store the object files # OUTPUT_DIR the directory where the resulting binary is put +# SYMBOLS_DIR the directory where the debug symbols are put, defaults to OUTPUT_DIR # INCLUDES only pick source from these directories # EXCLUDES do not pick source from these directories # INCLUDE_FILES only compile exactly these files! @@ -533,8 +534,6 @@ define SetupNativeCompilationBody $$(call SetIfEmpty, $1_SYSROOT_CFLAGS, $$($$($1_TOOLCHAIN)_SYSROOT_CFLAGS)) $$(call SetIfEmpty, $1_SYSROOT_LDFLAGS, $$($$($1_TOOLCHAIN)_SYSROOT_LDFLAGS)) - # Make sure the dirs exist. - $$(call MakeDir, $$($1_OBJECT_DIR) $$($1_OUTPUT_DIR)) $$(foreach d, $$($1_SRC), $$(if $$(wildcard $$d), , \ $$(error SRC specified to SetupNativeCompilation $1 contains missing directory $$d))) @@ -911,30 +910,31 @@ define SetupNativeCompilationBody ifeq ($$($1_COPY_DEBUG_SYMBOLS), true) ifneq ($$($1_DEBUG_SYMBOLS), false) + $$(call SetIfEmpty, $1_SYMBOLS_DIR, $$($1_OUTPUT_DIR)) # Only copy debug symbols for dynamic libraries and programs. ifneq ($$($1_TYPE), STATIC_LIBRARY) # Generate debuginfo files. ifeq ($(call isTargetOs, windows), true) - $1_EXTRA_LDFLAGS += -debug "-pdb:$$($1_OUTPUT_DIR)/$$($1_NOSUFFIX).pdb" \ - "-map:$$($1_OUTPUT_DIR)/$$($1_NOSUFFIX).map" - $1_DEBUGINFO_FILES := $$($1_OUTPUT_DIR)/$$($1_NOSUFFIX).pdb \ - $$($1_OUTPUT_DIR)/$$($1_NOSUFFIX).map + $1_EXTRA_LDFLAGS += -debug "-pdb:$$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).pdb" \ + "-map:$$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).map" + $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).pdb \ + $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).map else ifeq ($(call isTargetOs, linux solaris), true) - $1_DEBUGINFO_FILES := $$($1_OUTPUT_DIR)/$$($1_NOSUFFIX).debuginfo + $1_DEBUGINFO_FILES := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).debuginfo # Setup the command line creating debuginfo files, to be run after linking. # It cannot be run separately since it updates the original target file $1_CREATE_DEBUGINFO_CMDS := \ $$($1_OBJCOPY) --only-keep-debug $$($1_TARGET) $$($1_DEBUGINFO_FILES) $$(NEWLINE) \ - $(CD) $$($1_OUTPUT_DIR) && \ + $(CD) $$($1_SYMBOLS_DIR) && \ $$($1_OBJCOPY) --add-gnu-debuglink=$$($1_DEBUGINFO_FILES) $$($1_TARGET) else ifeq ($(call isTargetOs, macosx), true) $1_DEBUGINFO_FILES := \ - $$($1_OUTPUT_DIR)/$$($1_BASENAME).dSYM/Contents/Info.plist \ - $$($1_OUTPUT_DIR)/$$($1_BASENAME).dSYM/Contents/Resources/DWARF/$$($1_BASENAME) + $$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM/Contents/Info.plist \ + $$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM/Contents/Resources/DWARF/$$($1_BASENAME) $1_CREATE_DEBUGINFO_CMDS := \ - $(DSYMUTIL) --out $$($1_OUTPUT_DIR)/$$($1_BASENAME).dSYM $$($1_TARGET) + $(DSYMUTIL) --out $$($1_SYMBOLS_DIR)/$$($1_BASENAME).dSYM $$($1_TARGET) endif # Since the link rule creates more than one file that we want to track, @@ -956,14 +956,14 @@ define SetupNativeCompilationBody $1 += $$($1_DEBUGINFO_FILES) ifeq ($$($1_ZIP_EXTERNAL_DEBUG_SYMBOLS), true) - $1_DEBUGINFO_ZIP := $$($1_OUTPUT_DIR)/$$($1_NOSUFFIX).diz + $1_DEBUGINFO_ZIP := $$($1_SYMBOLS_DIR)/$$($1_NOSUFFIX).diz $1 += $$($1_DEBUGINFO_ZIP) # The dependency on TARGET is needed for debuginfo files # to be rebuilt properly. $$($1_DEBUGINFO_ZIP): $$($1_DEBUGINFO_FILES) $$($1_TARGET) - $(CD) $$($1_OUTPUT_DIR) && \ - $(ZIPEXE) -q -r $$@ $$(subst $$($1_OUTPUT_DIR)/,, $$($1_DEBUGINFO_FILES)) + $(CD) $$($1_SYMBOLS_DIR) && \ + $(ZIPEXE) -q -r $$@ $$(subst $$($1_SYMBOLS_DIR)/,, $$($1_DEBUGINFO_FILES)) endif endif # !STATIC_LIBRARY @@ -999,6 +999,7 @@ define SetupNativeCompilationBody $$($1_TARGET): $$($1_TARGET_DEPS) $$(call LogInfo, Building static library $$($1_BASENAME)) + $$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR)) $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \ $$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_ALL_OBJS) \ $$($1_RES)) @@ -1100,7 +1101,9 @@ define SetupNativeCompilationBody # Keep as much as possible on one execution line for best performance # on Windows $$(call LogInfo, Linking $$($1_BASENAME)) + $$(call MakeDir, $$($1_OUTPUT_DIR) $$($1_SYMBOLS_DIR)) ifeq ($(call isTargetOs, windows), true) + $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \ $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \ $(LD_OUT_OPTION)$$($1_TARGET) $$($1_LD_OBJ_ARG) $$($1_RES) $$(GLOBAL_LIBS) \ diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index b8b1a39d738..08dc9aac8dd 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1043,7 +1043,7 @@ var getJibProfilesDependencies = function (input, common) { jtreg: { server: "javare", revision: "4.2", - build_number: "b14", + build_number: "b16", checksum_file: "MD5_VALUES", file: "jtreg_bin-4.2.zip", environment_name: "JT_HOME", diff --git a/make/data/jdwp/jdwp.spec b/make/data/jdwp/jdwp.spec index 2cf53f7c7e3..258493edf97 100644 --- a/make/data/jdwp/jdwp.spec +++ b/make/data/jdwp/jdwp.spec @@ -468,7 +468,7 @@ JDWP "Java(tm) Debug Wire Protocol" "
  • deleting a method
  • " "
  • changing class modifiers
  • " "
  • changing method modifiers
  • " - "
  • changing the NestHost or NestMembers class attributes
  • " + "
  • changing the NestHost, NestMembers, or Record class attributes
  • " "" "

    " "Requires canRedefineClasses capability - see " @@ -3167,8 +3167,8 @@ JDWP "Java(tm) Debug Wire Protocol" "than its counterpart in the old class version and " "canUnrestrictedlyRedefineClasses is false.") (Constant CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED - =72 "The new class version has different NestHost or " - "NestMembers class attribute and " + =72 "The new class version has a different NestHost, " + "NestMembers, or Record class attribute and " "canUnrestrictedlyRedefineClasses is false.") (Constant NOT_IMPLEMENTED =99 "The functionality is not implemented in " "this virtual machine.") diff --git a/make/hotspot/symbols/symbols-unix b/make/hotspot/symbols/symbols-unix index 825be6aaac5..29efcc5b55f 100644 --- a/make/hotspot/symbols/symbols-unix +++ b/make/hotspot/symbols/symbols-unix @@ -122,6 +122,7 @@ JVM_GetNestMembers JVM_GetPrimitiveArrayElement JVM_GetProperties JVM_GetProtectionDomain +JVM_GetRecordComponents JVM_GetSimpleBinaryName JVM_GetStackAccessControlContext JVM_GetSystemPackage @@ -143,6 +144,7 @@ JVM_IsArrayClass JVM_IsConstructorIx JVM_IsInterface JVM_IsPrimitiveClass +JVM_IsRecord JVM_IsSameClassPackage JVM_IsSupportedJNIVersion JVM_IsThreadAlive diff --git a/make/jdk/src/classes/build/tools/cldrconverter/AbstractLDMLHandler.java b/make/jdk/src/classes/build/tools/cldrconverter/AbstractLDMLHandler.java index 2197a279682..66f146a610a 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/AbstractLDMLHandler.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/AbstractLDMLHandler.java @@ -157,9 +157,9 @@ abstract class AbstractLDMLHandler extends DefaultHandler { } } - void pushStringListElement(String qName, Attributes attributes, int index) { + void pushStringListElement(String qName, Attributes attributes, int index, String count) { if (!pushIfIgnored(qName, attributes)) { - currentContainer = new StringListElement(qName, currentContainer, index); + currentContainer = new StringListElement(qName, currentContainer, index, count); } } diff --git a/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java b/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java index 87ccdc61085..f4789fab916 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java @@ -242,14 +242,14 @@ class Bundle { if (i < size) { pattern = patterns.get(i); if (!pattern.isEmpty()) { - return pattern; + return "{" + pattern + "}"; } } // if not found, try parent if (i < psize) { pattern = pList.get(i); if (!pattern.isEmpty()) { - return pattern; + return "{" + pattern + "}"; } } // bail out with empty string diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java index a61785961a9..ad30b3297c1 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java @@ -70,6 +70,7 @@ public class CLDRConverter { private static String LIKELYSUBTAGS_SOURCE_FILE; private static String TIMEZONE_SOURCE_FILE; private static String WINZONES_SOURCE_FILE; + private static String PLURALS_SOURCE_FILE; static String DESTINATION_DIR = "build/gensrc"; static final String LOCALE_NAME_PREFIX = "locale.displayname."; @@ -93,6 +94,7 @@ public class CLDRConverter { private static SupplementDataParseHandler handlerSuppl; private static LikelySubtagsParseHandler handlerLikelySubtags; private static WinZonesParseHandler handlerWinZones; + static PluralsParseHandler handlerPlurals; static SupplementalMetadataParseHandler handlerSupplMeta; static NumberingSystemsParseHandler handlerNumbering; static MetaZonesParseHandler handlerMetaZones; @@ -244,6 +246,7 @@ public class CLDRConverter { TIMEZONE_SOURCE_FILE = CLDR_BASE + "/bcp47/timezone.xml"; SPPL_META_SOURCE_FILE = CLDR_BASE + "/supplemental/supplementalMetadata.xml"; WINZONES_SOURCE_FILE = CLDR_BASE + "/supplemental/windowsZones.xml"; + PLURALS_SOURCE_FILE = CLDR_BASE + "/supplemental/plurals.xml"; if (BASE_LOCALES.isEmpty()) { setupBaseLocales("en-US"); @@ -264,6 +267,9 @@ public class CLDRConverter { // Generate Windows tzmappings generateWindowsTZMappings(); + + // Generate Plural rules + generatePluralRules(); } } @@ -451,6 +457,10 @@ public class CLDRConverter { // Parse windowsZones handlerWinZones = new WinZonesParseHandler(); parseLDMLFile(new File(WINZONES_SOURCE_FILE), handlerWinZones); + + // Parse plurals + handlerPlurals = new PluralsParseHandler(); + parseLDMLFile(new File(PLURALS_SOURCE_FILE), handlerPlurals); } // Parsers for data in "bcp47" directory @@ -1161,6 +1171,52 @@ public class CLDRConverter { StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); } + /** + * Generate ResourceBundle source file for plural rules. The generated + * class is {@code sun.text.resources.PluralRules} which has one public + * two dimensional array {@code rulesArray}. Each array element consists + * of two elements that designate the locale and the locale's plural rules + * string. The latter has the syntax from Unicode Consortium's + * + * Plural rules syntax. {@code samples} and {@code "other"} are being ommited. + * + * @throws Exception + */ + private static void generatePluralRules() throws Exception { + Files.createDirectories(Paths.get(DESTINATION_DIR, "sun", "text", "resources")); + Files.write(Paths.get(DESTINATION_DIR, "sun", "text", "resources", "PluralRules.java"), + Stream.concat( + Stream.concat( + Stream.of( + "package sun.text.resources;", + "public final class PluralRules {", + " public static final String[][] rulesArray = {" + ), + pluralRulesStream().sorted() + ), + Stream.of( + " };", + "}" + ) + ) + .collect(Collectors.toList()), + StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); + } + + private static Stream pluralRulesStream() { + return handlerPlurals.getData().entrySet().stream() + .filter(e -> !((Map)e.getValue()).isEmpty()) + .map(e -> { + String loc = e.getKey(); + Map rules = (Map)e.getValue(); + return " {\"" + loc + "\", \"" + + rules.entrySet().stream() + .map(rule -> rule.getKey() + ":" + rule.getValue().replaceFirst("@.*", "")) + .map(String::trim) + .collect(Collectors.joining(";")) + "\"},"; + }); + } + // for debug static void dumpMap(Map map) { map.entrySet().stream() @@ -1179,3 +1235,4 @@ public class CLDRConverter { .forEach(System.out::println); } } + diff --git a/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java b/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java index a4a7301b088..cf5baf4c378 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java @@ -54,7 +54,6 @@ class LDMLParseHandler extends AbstractLDMLHandler { private String currentContext = ""; // "format"/"stand-alone" private String currentWidth = ""; // "wide"/"narrow"/"abbreviated" private String currentStyle = ""; // short, long for decimalFormat - private String compactCount = ""; // one or other for decimalFormat LDMLParseHandler(String id) { this.id = id; @@ -577,32 +576,12 @@ class LDMLParseHandler extends AbstractLDMLHandler { if (currentStyle == null) { pushContainer(qName, attributes); } else { - // The compact number patterns parsing assumes that the order - // of patterns are always in the increasing order of their - // type attribute i.e. type = 1000... - // Between the inflectional forms for a type (e.g. - // count = "one" and count = "other" for type = 1000), it is - // assumed that the count = "one" always appears before - // count = "other" switch (currentStyle) { case "short": case "long": - String count = attributes.getValue("count"); - // first pattern of count = "one" or count = "other" - if ((count.equals("one") || count.equals("other")) - && compactCount.equals("")) { - compactCount = count; - pushStringListElement(qName, attributes, - (int) Math.log10(Double.parseDouble(attributes.getValue("type")))); - } else if ((count.equals("one") || count.equals("other")) - && compactCount.equals(count)) { - // extract patterns with similar "count" - // attribute value - pushStringListElement(qName, attributes, - (int) Math.log10(Double.parseDouble(attributes.getValue("type")))); - } else { - pushIgnoredContainer(qName); - } + pushStringListElement(qName, attributes, + (int) Math.log10(Double.parseDouble(attributes.getValue("type"))), + attributes.getValue("count")); break; default: pushIgnoredContainer(qName); @@ -1051,7 +1030,6 @@ class LDMLParseHandler extends AbstractLDMLHandler { break; case "decimalFormatLength": currentStyle = ""; - compactCount = ""; putIfEntry(); break; case "currencyFormats": diff --git a/make/jdk/src/classes/build/tools/cldrconverter/PluralsParseHandler.java b/make/jdk/src/classes/build/tools/cldrconverter/PluralsParseHandler.java new file mode 100644 index 00000000000..4a904786e07 --- /dev/null +++ b/make/jdk/src/classes/build/tools/cldrconverter/PluralsParseHandler.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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. + */ + +package build.tools.cldrconverter; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * Handles parsing of files in Locale Data Markup Language for + * plurals.xml + */ + +class PluralsParseHandler extends AbstractLDMLHandler { + @Override + public InputSource resolveEntity(String publicID, String systemID) throws IOException, SAXException { + // avoid HTTP traffic to unicode.org + if (systemID.startsWith(CLDRConverter.SPPL_LDML_DTD_SYSTEM_ID)) { + return new InputSource((new File(CLDRConverter.LOCAL_SPPL_LDML_DTD)).toURI().toString()); + } + return null; + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + switch (qName) { + case "plurals": + // Only deal with "cardinal" type for now. + if (attributes.getValue("type").equals("cardinal")) { + pushContainer(qName, attributes); + } else { + // ignore + pushIgnoredContainer(qName); + } + break; + case "pluralRules": + // key: locales + pushKeyContainer(qName, attributes, attributes.getValue("locales")); + break; + case "pluralRule": + pushStringEntry(qName, attributes, attributes.getValue("count")); + break; + default: + // treat anything else as a container + pushContainer(qName, attributes); + break; + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + assert qName.equals(currentContainer.getqName()) : "current=" + currentContainer.getqName() + ", param=" + qName; + switch (qName) { + case "pluralRule": + assert !(currentContainer instanceof Entry); + Entry entry = (Entry)currentContainer; + final String count = entry.getKey(); + final String rule = (String)entry.getValue(); + String locales = ((KeyContainer)(currentContainer.getParent())).getKey(); + Arrays.stream(locales.split("\\s")) + .forEach(loc -> { + Map rules = (Map)get(loc); + if (rules == null) { + rules = new HashMap<>(); + put(loc, rules); + } + if (!count.equals("other")) { + rules.put(count, rule); + } + }); + break; + } + + currentContainer = currentContainer.getParent(); + } +} diff --git a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java index 240552a7e65..285f33610d1 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java @@ -309,7 +309,7 @@ class ResourceBundleGenerator implements BundleGenerator { // for languageAliasMap if (CLDRConverter.isBaseModule) { CLDRConverter.handlerSupplMeta.getLanguageAliasData().forEach((key, value) -> { - out.printf(" languageAliasMap.put(\"%s\", \"%s\");\n", key, value); + out.printf(" languageAliasMap.put(\"%s\", \"%s\");\n", key, value); }); } diff --git a/make/jdk/src/classes/build/tools/cldrconverter/StringListElement.java b/make/jdk/src/classes/build/tools/cldrconverter/StringListElement.java index 4529efb015f..8c2a7830c00 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/StringListElement.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/StringListElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,20 +28,22 @@ package build.tools.cldrconverter; class StringListElement extends Container { StringListEntry list; + String count; int index; - StringListElement(String qName, Container parent, int index) { + StringListElement(String qName, Container parent, int index, String count) { super(qName, parent); while (!(parent instanceof StringListEntry)) { parent = parent.getParent(); } list = (StringListEntry) parent; this.index = index; + this.count = count; } @Override void addCharacters(char[] characters, int start, int length) { - list.addCharacters(index, characters, start, length); + list.addCharacters(index, count, characters, start, length); } } diff --git a/make/jdk/src/classes/build/tools/cldrconverter/StringListEntry.java b/make/jdk/src/classes/build/tools/cldrconverter/StringListEntry.java index a0e55007f66..6b1f5a2647d 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/StringListEntry.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/StringListEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,13 +38,22 @@ class StringListEntry extends Entry> { value = new ArrayList<>(); } - void addCharacters(int index, char[] characters, int start, int length) { - // fill with empty strings when the patterns start from index > 0 - if (value.size() < index) { - IntStream.range(0, index).forEach(i -> value.add(i, "")); - value.add(index, new String(characters, start, length)); + void addCharacters(int index, String count, char[] characters, int start, int length) { + int size = value.size(); + String elem = count + ":" + new String(characters, start, length); + + // quote embedded spaces, if any + elem = elem.replaceAll(" ", "' '"); + + if (size < index) { + // fill with empty strings when the patterns start from index > size + IntStream.range(size, index).forEach(i -> value.add(i, "")); + value.add(index, elem); + } else if (size == index) { + value.add(index, elem); } else { - value.add(index, new String(characters, start, length)); + // concatenate the pattern with the delimiter ' ' + value.set(index, value.get(index) + " " + elem); } } diff --git a/make/jdk/src/classes/build/tools/fixuppandoc/Main.java b/make/jdk/src/classes/build/tools/fixuppandoc/Main.java index c790f0f16a3..7978477b6d8 100644 --- a/make/jdk/src/classes/build/tools/fixuppandoc/Main.java +++ b/make/jdk/src/classes/build/tools/fixuppandoc/Main.java @@ -46,6 +46,7 @@ import java.util.Objects; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static java.nio.charset.StandardCharsets.UTF_8; /** * Fixup HTML generated by pandoc. @@ -98,6 +99,10 @@ public class Main { * If no output file is specified, the program will write to standard output. * Any error messages will be written to the standard error stream. * + * Consistent with the + * pandoc tool, + * input and output text is encoded as UTF-8. + * * @param args the command-line arguments */ public static void main(String... args) { @@ -184,7 +189,7 @@ public class Main { if (inFile != null) { read(inFile); } else { - read(new BufferedReader(new InputStreamReader(System.in))); + read(new BufferedReader(new InputStreamReader(System.in, UTF_8))); } } } @@ -198,9 +203,9 @@ public class Main { */ private Writer openWriter(Path file) throws IOException { if (file != null) { - return Files.newBufferedWriter(file); + return Files.newBufferedWriter(file, UTF_8); } else { - return new BufferedWriter(new OutputStreamWriter(System.out) { + return new BufferedWriter(new OutputStreamWriter(System.out, UTF_8) { @Override public void close() throws IOException { flush(); @@ -615,7 +620,7 @@ public class Main { * @param file the file */ void read(Path file) { - try (Reader r = Files.newBufferedReader(file)) { + try (Reader r = Files.newBufferedReader(file, UTF_8)) { this.file = file; read(r); } catch (IOException e) { diff --git a/make/launcher/Launcher-jdk.incubator.jpackage.gmk b/make/launcher/Launcher-jdk.incubator.jpackage.gmk new file mode 100644 index 00000000000..7a25dae733c --- /dev/null +++ b/make/launcher/Launcher-jdk.incubator.jpackage.gmk @@ -0,0 +1,30 @@ +# +# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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 LauncherCommon.gmk + +$(eval $(call SetupBuildLauncher, jpackage, \ + MAIN_CLASS := jdk.incubator.jpackage.main.Main, \ +)) diff --git a/make/launcher/Launcher-jdk.jconsole.gmk b/make/launcher/Launcher-jdk.jconsole.gmk index 7ef2e577b76..9b19dcdc0e5 100644 --- a/make/launcher/Launcher-jdk.jconsole.gmk +++ b/make/launcher/Launcher-jdk.jconsole.gmk @@ -29,6 +29,7 @@ $(eval $(call SetupBuildLauncher, jconsole, \ MAIN_CLASS := sun.tools.jconsole.JConsole, \ JAVA_ARGS := --add-opens java.base/java.io=jdk.jconsole \ --add-modules ALL-DEFAULT \ - -Djconsole.showOutputViewer, \ + -Djconsole.showOutputViewer \ + -Djdk.attach.allowAttachSelf=true, \ CFLAGS_windows := -DJAVAW, \ )) diff --git a/make/lib/Lib-jdk.incubator.jpackage.gmk b/make/lib/Lib-jdk.incubator.jpackage.gmk new file mode 100644 index 00000000000..f9e407d341a --- /dev/null +++ b/make/lib/Lib-jdk.incubator.jpackage.gmk @@ -0,0 +1,140 @@ +# +# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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 + +################################################################################ + +# Output app launcher library in resources dir, and symbols in the object dir +$(eval $(call SetupJdkLibrary, BUILD_LIB_APPLAUNCHER, \ + NAME := applauncher, \ + OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \ + SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libapplauncher, \ + TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ + OPTIMIZATION := LOW, \ + CFLAGS := $(CXXFLAGS_JDKLIB), \ + CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \ + LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ + $(call SET_SHARED_LIBRARY_ORIGIN), \ + LIBS := $(LIBCXX), \ + LIBS_windows := user32.lib shell32.lib advapi32.lib ole32.lib, \ + LIBS_linux := -ldl -lpthread, \ + LIBS_macosx := -ldl -framework Cocoa, \ +)) + +$(BUILD_LIB_APPLAUNCHER): $(call FindLib, java.base, java) + +TARGETS += $(BUILD_LIB_APPLAUNCHER) + +JPACKAGE_APPLAUNCHER_SRC := \ + $(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/jpackageapplauncher + +# Output app launcher executable in resources dir, and symbols in the object dir +$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \ + NAME := jpackageapplauncher, \ + OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \ + SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncher, \ + SRC := $(JPACKAGE_APPLAUNCHER_SRC), \ + TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ + OPTIMIZATION := LOW, \ + CFLAGS := $(CXXFLAGS_JDKEXE), \ + CFLAGS_windows := -EHsc -DLAUNCHERC -DUNICODE -D_UNICODE, \ + LDFLAGS := $(LDFLAGS_JDKEXE), \ + LIBS_macosx := -framework Cocoa, \ + LIBS := $(LIBCXX), \ + LIBS_linux := -ldl, \ + LIBS_windows := user32.lib shell32.lib advapi32.lib, \ +)) + +TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE) + +################################################################################ + +ifeq ($(call isTargetOs, windows), true) + + $(eval $(call SetupJdkLibrary, BUILD_LIB_JPACKAGE, \ + NAME := jpackage, \ + OPTIMIZATION := LOW, \ + CFLAGS := $(CXXFLAGS_JDKLIB), \ + CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \ + LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ + $(call SET_SHARED_LIBRARY_ORIGIN), \ + LIBS := $(LIBCXX), \ + LIBS_windows := user32.lib shell32.lib advapi32.lib ole32.lib, \ + )) + + TARGETS += $(BUILD_LIB_JPACKAGE) + + # Build Wix custom action helper + # Output library in resources dir, and symbols in the object dir + $(eval $(call SetupJdkLibrary, BUILD_LIB_WIXHELPER, \ + NAME := wixhelper, \ + OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \ + SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libwixhelper, \ + OPTIMIZATION := LOW, \ + CFLAGS := $(CXXFLAGS_JDKLIB), \ + CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE -MT, \ + LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK), \ + LIBS := $(LIBCXX), \ + LIBS_windows := msi.lib Shlwapi.lib User32.lib, \ + )) + + TARGETS += $(BUILD_LIB_WIXHELPER) + + # Build exe installer wrapper for msi installer + $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_MSIWRAPPER, \ + NAME := msiwrapper, \ + OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \ + SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/msiwrapper, \ + SRC := $(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/msiwrapper, \ + EXTRA_FILES := $(addprefix $(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/libjpackage/, \ + FileUtils.cpp Log.cpp WinSysInfo.cpp tstrings.cpp WinErrorHandling.cpp ErrorHandling.cpp), \ + CFLAGS := $(CXXFLAGS_JDKEXE) -MT \ + $(addprefix -I$(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/, msiwrapper libjpackage), \ + CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \ + LDFLAGS := $(LDFLAGS_JDKEXE), \ + LIBS := $(LIBCXX), \ + )) + + TARGETS += $(BUILD_JPACKAGE_MSIWRAPPER) + + # Build non-console version of launcher + $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHERWEXE, \ + NAME := jpackageapplauncherw, \ + OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \ + SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \ + SRC := $(JPACKAGE_APPLAUNCHER_SRC), \ + TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ + OPTIMIZATION := LOW, \ + CFLAGS := $(CXXFLAGS_JDKEXE), \ + CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \ + LDFLAGS := $(LDFLAGS_JDKEXE), \ + LIBS := $(LIBCXX), \ + LIBS_windows := user32.lib shell32.lib advapi32.lib, \ + )) + + TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE) + +endif diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 568e7faecdd..c146a0cb78c 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -1857,13 +1857,14 @@ static enum RC rc_class(OptoReg::Name reg) { // we have 30 int registers * 2 halves // (rscratch1 and rscratch2 are omitted) + int slots_of_int_registers = RegisterImpl::max_slots_per_register * (RegisterImpl::number_of_registers - 2); - if (reg < 60) { + if (reg < slots_of_int_registers) { return rc_int; } - // we have 32 float register * 2 halves - if (reg < 60 + 128) { + // we have 32 float register * 4 halves + if (reg < slots_of_int_registers + FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers) { return rc_float; } @@ -2293,6 +2294,24 @@ const bool Matcher::require_postalloc_expand = false; // the cpu only look at the lower 5/6 bits anyway? const bool Matcher::need_masked_shift_count = false; +// No support for generic vector operands. +const bool Matcher::supports_generic_vector_operands = false; + +MachOper* Matcher::specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg) { + ShouldNotReachHere(); // generic vector operands not supported + return NULL; +} + +bool Matcher::is_generic_reg2reg_move(MachNode* m) { + ShouldNotReachHere(); // generic vector operands not supported + return false; +} + +bool Matcher::is_generic_vector(MachOper* opnd) { + ShouldNotReachHere(); // generic vector operands not supported + return false; +} + // This affects two different things: // - how Decode nodes are matched // - how ImplicitNullCheck opportunities are recognized diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index cc1ef1405e2..ba670a1930c 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -604,7 +604,9 @@ class InternalAddress: public Address { InternalAddress(address target) : Address(target, relocInfo::internal_word_type) {} }; -const int FPUStateSizeInWords = 32 * 2; +const int FPUStateSizeInWords = FloatRegisterImpl::number_of_registers * + FloatRegisterImpl::save_slots_per_register; + typedef enum { PLDL1KEEP = 0b00000, PLDL1STRM, PLDL2KEEP, PLDL2STRM, PLDL3KEEP, PLDL3STRM, PSTL1KEEP = 0b10000, PSTL1STRM, PSTL2KEEP, PSTL2STRM, PSTL3KEEP, PSTL3STRM, diff --git a/src/hotspot/cpu/aarch64/gc/z/zGlobals_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/z/zGlobals_aarch64.cpp index 785a8cb630e..4c17e54828e 100644 --- a/src/hotspot/cpu/aarch64/gc/z/zGlobals_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/z/zGlobals_aarch64.cpp @@ -23,9 +23,9 @@ #include "precompiled.hpp" #include "gc/z/zGlobals.hpp" -#include "gc/z/zUtils.inline.hpp" #include "runtime/globals.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" // // The heap can have three different layouts, depending on the max heap size. @@ -142,7 +142,7 @@ uintptr_t ZPlatformAddressBase() { size_t ZPlatformAddressOffsetBits() { const size_t min_address_offset_bits = 42; // 4TB const size_t max_address_offset_bits = 44; // 16TB - const size_t address_offset = ZUtils::round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); + const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); const size_t address_offset_bits = log2_intptr(address_offset); return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits); } diff --git a/src/hotspot/cpu/aarch64/register_aarch64.cpp b/src/hotspot/cpu/aarch64/register_aarch64.cpp index 30924e8a5e6..36cbe3fee34 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.cpp @@ -26,10 +26,12 @@ #include "precompiled.hpp" #include "register_aarch64.hpp" -const int ConcreteRegisterImpl::max_gpr = RegisterImpl::number_of_registers << 1; +const int ConcreteRegisterImpl::max_gpr = RegisterImpl::number_of_registers * + RegisterImpl::max_slots_per_register; const int ConcreteRegisterImpl::max_fpr - = ConcreteRegisterImpl::max_gpr + (FloatRegisterImpl::number_of_registers << 1); + = ConcreteRegisterImpl::max_gpr + + FloatRegisterImpl::number_of_registers * FloatRegisterImpl::max_slots_per_register; const char* RegisterImpl::name() const { const char* names[number_of_registers] = { diff --git a/src/hotspot/cpu/aarch64/register_aarch64.hpp b/src/hotspot/cpu/aarch64/register_aarch64.hpp index a95a7fb093f..e968baad6e1 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.hpp @@ -44,7 +44,8 @@ class RegisterImpl: public AbstractRegisterImpl { enum { number_of_registers = 32, number_of_byte_registers = 32, - number_of_registers_for_jvmci = 34 // Including SP and ZR. + number_of_registers_for_jvmci = 34, // Including SP and ZR. + max_slots_per_register = 2 }; // derived registers, offsets, and addresses @@ -127,7 +128,10 @@ inline FloatRegister as_FloatRegister(int encoding) { class FloatRegisterImpl: public AbstractRegisterImpl { public: enum { - number_of_registers = 32 + number_of_registers = 32, + max_slots_per_register = 4, + save_slots_per_register = 2, + extra_save_slots_per_register = max_slots_per_register - save_slots_per_register }; // construction @@ -193,8 +197,8 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl { // There is no requirement that any ordering here matches any ordering c2 gives // it's optoregs. - number_of_registers = (2 * RegisterImpl::number_of_registers + - 4 * FloatRegisterImpl::number_of_registers + + number_of_registers = (RegisterImpl::max_slots_per_register * RegisterImpl::number_of_registers + + FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers + 1) // flags }; diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 63dcc21d533..be3505abbe3 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -33,6 +33,7 @@ #include "interpreter/interp_masm.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" +#include "nativeInst_aarch64.hpp" #include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "runtime/safepointMechanism.hpp" @@ -99,15 +100,15 @@ class RegisterSaver { // Capture info about frame layout enum layout { fpu_state_off = 0, - fpu_state_end = fpu_state_off+FPUStateSizeInWords-1, + fpu_state_end = fpu_state_off + FPUStateSizeInWords - 1, // The frame sender code expects that rfp will be in // the "natural" place and will override any oopMap // setting for it. We must therefore force the layout // so that it agrees with the frame sender code. - r0_off = fpu_state_off+FPUStateSizeInWords, - rfp_off = r0_off + 30 * 2, - return_off = rfp_off + 2, // slot for return address - reg_save_size = return_off + 2}; + r0_off = fpu_state_off + FPUStateSizeInWords, + rfp_off = r0_off + (RegisterImpl::number_of_registers - 2) * RegisterImpl::max_slots_per_register, + return_off = rfp_off + RegisterImpl::max_slots_per_register, // slot for return address + reg_save_size = return_off + RegisterImpl::max_slots_per_register}; }; @@ -115,19 +116,20 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ #if COMPILER2_OR_JVMCI if (save_vectors) { // Save upper half of vector registers - int vect_words = 32 * 8 / wordSize; + int vect_words = FloatRegisterImpl::number_of_registers * FloatRegisterImpl::extra_save_slots_per_register / + VMRegImpl::slots_per_word; additional_frame_words += vect_words; } #else assert(!save_vectors, "vectors are generated only by C2 and JVMCI"); #endif - int frame_size_in_bytes = align_up(additional_frame_words*wordSize + - reg_save_size*BytesPerInt, 16); + int frame_size_in_bytes = align_up(additional_frame_words * wordSize + + reg_save_size * BytesPerInt, 16); // OopMap frame size is in compiler stack slots (jint's) not bytes or words int frame_size_in_slots = frame_size_in_bytes / BytesPerInt; // The caller will allocate additional_frame_words - int additional_frame_slots = additional_frame_words*wordSize / BytesPerInt; + int additional_frame_slots = additional_frame_words * wordSize / BytesPerInt; // CodeBlob frame size is in words. int frame_size_in_words = frame_size_in_bytes / wordSize; *total_frame_words = frame_size_in_words; @@ -147,10 +149,10 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ for (int i = 0; i < RegisterImpl::number_of_registers; i++) { Register r = as_Register(i); if (r < rheapbase && r != rscratch1 && r != rscratch2) { - int sp_offset = 2 * (i + 32); // SP offsets are in 4-byte words, - // register slots are 8 bytes - // wide, 32 floating-point - // registers + // SP offsets are in 4-byte words. + // Register slots are 8 bytes wide, 32 floating-point registers. + int sp_offset = RegisterImpl::max_slots_per_register * i + + FloatRegisterImpl::save_slots_per_register * FloatRegisterImpl::number_of_registers; oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset + additional_frame_slots), r->as_VMReg()); } @@ -158,7 +160,8 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ for (int i = 0; i < FloatRegisterImpl::number_of_registers; i++) { FloatRegister r = as_FloatRegister(i); - int sp_offset = save_vectors ? (4 * i) : (2 * i); + int sp_offset = save_vectors ? (FloatRegisterImpl::max_slots_per_register * i) : + (FloatRegisterImpl::save_slots_per_register * i); oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset), r->as_VMReg()); } diff --git a/src/hotspot/cpu/aarch64/vmreg_aarch64.cpp b/src/hotspot/cpu/aarch64/vmreg_aarch64.cpp index 9fd20be0f54..35d0adf5b9f 100644 --- a/src/hotspot/cpu/aarch64/vmreg_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vmreg_aarch64.cpp @@ -33,15 +33,17 @@ void VMRegImpl::set_regName() { Register reg = ::as_Register(0); int i; for (i = 0; i < ConcreteRegisterImpl::max_gpr ; ) { - regName[i++] = reg->name(); - regName[i++] = reg->name(); + for (int j = 0 ; j < RegisterImpl::max_slots_per_register ; j++) { + regName[i++] = reg->name(); + } reg = reg->successor(); } FloatRegister freg = ::as_FloatRegister(0); for ( ; i < ConcreteRegisterImpl::max_fpr ; ) { - regName[i++] = freg->name(); - regName[i++] = freg->name(); + for (int j = 0 ; j < FloatRegisterImpl::max_slots_per_register ; j++) { + regName[i++] = freg->name(); + } freg = freg->successor(); } diff --git a/src/hotspot/cpu/aarch64/vmreg_aarch64.hpp b/src/hotspot/cpu/aarch64/vmreg_aarch64.hpp index 07ad197fae8..12fab035e0c 100644 --- a/src/hotspot/cpu/aarch64/vmreg_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vmreg_aarch64.hpp @@ -38,13 +38,14 @@ inline Register as_Register() { assert( is_Register(), "must be"); // Yuk - return ::as_Register(value() >> 1); + return ::as_Register(value() / RegisterImpl::max_slots_per_register); } inline FloatRegister as_FloatRegister() { assert( is_FloatRegister() && is_even(value()), "must be" ); // Yuk - return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) >> 1); + return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) / + FloatRegisterImpl::max_slots_per_register); } inline bool is_concrete() { diff --git a/src/hotspot/cpu/aarch64/vmreg_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/vmreg_aarch64.inline.hpp index 5173a299b78..9d54448a364 100644 --- a/src/hotspot/cpu/aarch64/vmreg_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/vmreg_aarch64.inline.hpp @@ -28,11 +28,12 @@ inline VMReg RegisterImpl::as_VMReg() { if( this==noreg ) return VMRegImpl::Bad(); - return VMRegImpl::as_VMReg(encoding() << 1 ); + return VMRegImpl::as_VMReg(encoding() * RegisterImpl::max_slots_per_register); } inline VMReg FloatRegisterImpl::as_VMReg() { - return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_gpr); + return VMRegImpl::as_VMReg((encoding() * FloatRegisterImpl::max_slots_per_register) + + ConcreteRegisterImpl::max_gpr); } #endif // CPU_AARCH64_VMREG_AARCH64_INLINE_HPP diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index 18b556e1aed..ec8aba26903 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -1077,6 +1077,24 @@ const bool Matcher::need_masked_shift_count = true; const bool Matcher::convi2l_type_required = true; +// No support for generic vector operands. +const bool Matcher::supports_generic_vector_operands = false; + +MachOper* Matcher::specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg) { + ShouldNotReachHere(); // generic vector operands not supported + return NULL; +} + +bool Matcher::is_generic_reg2reg_move(MachNode* m) { + ShouldNotReachHere(); // generic vector operands not supported + return false; +} + +bool Matcher::is_generic_vector(MachOper* opnd) { + ShouldNotReachHere(); // generic vector operands not supported + return false; +} + // Should the Matcher clone shifts on addressing modes, expecting them // to be subsumed into complex addressing expressions or compute them // into registers? diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index c95a82df1a6..8768a1c6882 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -2426,6 +2426,24 @@ const bool Matcher::require_postalloc_expand = true; // PowerPC requires masked shift counts. const bool Matcher::need_masked_shift_count = true; +// No support for generic vector operands. +const bool Matcher::supports_generic_vector_operands = false; + +MachOper* Matcher::specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg) { + ShouldNotReachHere(); // generic vector operands not supported + return NULL; +} + +bool Matcher::is_generic_reg2reg_move(MachNode* m) { + ShouldNotReachHere(); // generic vector operands not supported + return false; +} + +bool Matcher::is_generic_vector(MachOper* opnd) { + ShouldNotReachHere(); // generic vector operands not supported + return false; +} + // This affects two different things: // - how Decode nodes are matched // - how ImplicitNullCheck opportunities are recognized diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 417a80e9919..2cb18cb978e 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -1658,6 +1658,24 @@ const bool Matcher::require_postalloc_expand = false; // Constant shift counts are handled in Ideal phase. const bool Matcher::need_masked_shift_count = false; +// No support for generic vector operands. +const bool Matcher::supports_generic_vector_operands = false; + +MachOper* Matcher::specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg) { + ShouldNotReachHere(); // generic vector operands not supported + return NULL; +} + +bool Matcher::is_generic_reg2reg_move(MachNode* m) { + ShouldNotReachHere(); // generic vector operands not supported + return false; +} + +bool Matcher::is_generic_vector(MachOper* opnd) { + ShouldNotReachHere(); // generic vector operands not supported + return false; +} + // Set this as clone_shift_expressions. bool Matcher::narrow_oop_use_complex_address() { if (CompressedOops::base() == NULL && CompressedOops::shift() == 0) return true; diff --git a/src/hotspot/cpu/sparc/sparc.ad b/src/hotspot/cpu/sparc/sparc.ad index c7965f6eebc..96f62c3c2be 100644 --- a/src/hotspot/cpu/sparc/sparc.ad +++ b/src/hotspot/cpu/sparc/sparc.ad @@ -1815,6 +1815,24 @@ const bool Matcher::require_postalloc_expand = false; // the cpu only look at the lower 5/6 bits anyway? const bool Matcher::need_masked_shift_count = false; +// No support for generic vector operands. +const bool Matcher::supports_generic_vector_operands = false; + +MachOper* Matcher::specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg) { + ShouldNotReachHere(); // generic vector operands not supported + return NULL; +} + +bool Matcher::is_generic_reg2reg_move(MachNode* m) { + ShouldNotReachHere(); // generic vector operands not supported + return false; +} + +bool Matcher::is_generic_vector(MachOper* opnd) { + ShouldNotReachHere(); // generic vector operands not supported + return false; +} + bool Matcher::narrow_oop_use_complex_address() { assert(UseCompressedOops, "only for compressed oops code"); return false; diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp index 34f3ceaeee6..13883f18d82 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp @@ -517,8 +517,11 @@ private: // Sort by size, largest first _xmm_registers.sort(xmm_compare_register_size); + // On Windows, the caller reserves stack space for spilling register arguments + const int arg_spill_size = frame::arg_reg_save_area_bytes; + // Stack pointer must be 16 bytes aligned for the call - _spill_offset = _spill_size = align_up(xmm_spill_size + gp_spill_size, 16); + _spill_offset = _spill_size = align_up(xmm_spill_size + gp_spill_size + arg_spill_size, 16); } public: diff --git a/src/hotspot/cpu/x86/gc/z/zGlobals_x86.cpp b/src/hotspot/cpu/x86/gc/z/zGlobals_x86.cpp index 785a8cb630e..4c17e54828e 100644 --- a/src/hotspot/cpu/x86/gc/z/zGlobals_x86.cpp +++ b/src/hotspot/cpu/x86/gc/z/zGlobals_x86.cpp @@ -23,9 +23,9 @@ #include "precompiled.hpp" #include "gc/z/zGlobals.hpp" -#include "gc/z/zUtils.inline.hpp" #include "runtime/globals.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" // // The heap can have three different layouts, depending on the max heap size. @@ -142,7 +142,7 @@ uintptr_t ZPlatformAddressBase() { size_t ZPlatformAddressOffsetBits() { const size_t min_address_offset_bits = 42; // 4TB const size_t max_address_offset_bits = 44; // 16TB - const size_t address_offset = ZUtils::round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); + const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); const size_t address_offset_bits = log2_intptr(address_offset); return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits); } diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 2546561589e..ffe92bfbb88 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1356,7 +1356,7 @@ public: void vpxor(XMMRegister dst, Address src) { Assembler::vpxor(dst, dst, src, true); } void vinserti128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { - if (UseAVX > 2) { + if (UseAVX > 2 && VM_Version::supports_avx512novl()) { Assembler::vinserti32x4(dst, dst, src, imm8); } else if (UseAVX > 1) { // vinserti128 is available only in AVX2 @@ -1367,7 +1367,7 @@ public: } void vinserti128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) { - if (UseAVX > 2) { + if (UseAVX > 2 && VM_Version::supports_avx512novl()) { Assembler::vinserti32x4(dst, dst, src, imm8); } else if (UseAVX > 1) { // vinserti128 is available only in AVX2 @@ -1378,7 +1378,7 @@ public: } void vextracti128(XMMRegister dst, XMMRegister src, uint8_t imm8) { - if (UseAVX > 2) { + if (UseAVX > 2 && VM_Version::supports_avx512novl()) { Assembler::vextracti32x4(dst, src, imm8); } else if (UseAVX > 1) { // vextracti128 is available only in AVX2 @@ -1389,7 +1389,7 @@ public: } void vextracti128(Address dst, XMMRegister src, uint8_t imm8) { - if (UseAVX > 2) { + if (UseAVX > 2 && VM_Version::supports_avx512novl()) { Assembler::vextracti32x4(dst, src, imm8); } else if (UseAVX > 1) { // vextracti128 is available only in AVX2 @@ -1414,7 +1414,7 @@ public: } void vinsertf128_high(XMMRegister dst, XMMRegister src) { - if (UseAVX > 2) { + if (UseAVX > 2 && VM_Version::supports_avx512novl()) { Assembler::vinsertf32x4(dst, dst, src, 1); } else { Assembler::vinsertf128(dst, dst, src, 1); @@ -1422,7 +1422,7 @@ public: } void vinsertf128_high(XMMRegister dst, Address src) { - if (UseAVX > 2) { + if (UseAVX > 2 && VM_Version::supports_avx512novl()) { Assembler::vinsertf32x4(dst, dst, src, 1); } else { Assembler::vinsertf128(dst, dst, src, 1); @@ -1430,7 +1430,7 @@ public: } void vextractf128_high(XMMRegister dst, XMMRegister src) { - if (UseAVX > 2) { + if (UseAVX > 2 && VM_Version::supports_avx512novl()) { Assembler::vextractf32x4(dst, src, 1); } else { Assembler::vextractf128(dst, src, 1); @@ -1438,7 +1438,7 @@ public: } void vextractf128_high(Address dst, XMMRegister src) { - if (UseAVX > 2) { + if (UseAVX > 2 && VM_Version::supports_avx512novl()) { Assembler::vextractf32x4(dst, src, 1); } else { Assembler::vextractf128(dst, src, 1); @@ -1480,7 +1480,7 @@ public: } void vinsertf128_low(XMMRegister dst, XMMRegister src) { - if (UseAVX > 2) { + if (UseAVX > 2 && VM_Version::supports_avx512novl()) { Assembler::vinsertf32x4(dst, dst, src, 0); } else { Assembler::vinsertf128(dst, dst, src, 0); @@ -1488,7 +1488,7 @@ public: } void vinsertf128_low(XMMRegister dst, Address src) { - if (UseAVX > 2) { + if (UseAVX > 2 && VM_Version::supports_avx512novl()) { Assembler::vinsertf32x4(dst, dst, src, 0); } else { Assembler::vinsertf128(dst, dst, src, 0); @@ -1496,7 +1496,7 @@ public: } void vextractf128_low(XMMRegister dst, XMMRegister src) { - if (UseAVX > 2) { + if (UseAVX > 2 && VM_Version::supports_avx512novl()) { Assembler::vextractf32x4(dst, src, 0); } else { Assembler::vextractf128(dst, src, 0); @@ -1504,7 +1504,7 @@ public: } void vextractf128_low(Address dst, XMMRegister src) { - if (UseAVX > 2) { + if (UseAVX > 2 && VM_Version::supports_avx512novl()) { Assembler::vextractf32x4(dst, src, 0); } else { Assembler::vextractf128(dst, src, 0); diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 910a5d05f83..a0f741091aa 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1094,7 +1094,7 @@ reg_class vectorz_reg_legacy(XMM0, XMM0b, XMM0c, XMM0d, XMM0e, XMM0f, XMM0 #endif ); -reg_class_dynamic vectorz_reg(vectorz_reg_evex, vectorz_reg_legacy, %{ VM_Version::supports_evex() %} ); +reg_class_dynamic vectorz_reg (vectorz_reg_evex, vectorz_reg_legacy, %{ VM_Version::supports_evex() %} ); reg_class_dynamic vectorz_reg_vl(vectorz_reg_evex, vectorz_reg_legacy, %{ VM_Version::supports_evex() && VM_Version::supports_avx512vl() %} ); %} @@ -1388,7 +1388,7 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen) { case Op_LShiftVB: case Op_RShiftVB: case Op_URShiftVB: - if ((vlen == 32 && UseAVX < 2) || + if ((vlen == 32 && UseAVX < 2) || ((vlen == 64) && (VM_Version::supports_avx512bw() == false))) ret_value = false; break; @@ -1418,6 +1418,55 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen) { return ret_value; // Per default match rules are supported. } +// x86 supports generic vector operands: vec and legVec. +const bool Matcher::supports_generic_vector_operands = true; + +MachOper* Matcher::specialize_generic_vector_operand(MachOper* generic_opnd, uint ideal_reg) { + assert(Matcher::is_generic_vector(generic_opnd), "not generic"); + bool legacy = (generic_opnd->opcode() == LEGVEC); + if (legacy) { + switch (ideal_reg) { + case Op_VecS: return new legVecSOper(); + case Op_VecD: return new legVecDOper(); + case Op_VecX: return new legVecXOper(); + case Op_VecY: return new legVecYOper(); + case Op_VecZ: return new legVecZOper(); + } + } else { + switch (ideal_reg) { + case Op_VecS: return new vecSOper(); + case Op_VecD: return new vecDOper(); + case Op_VecX: return new vecXOper(); + case Op_VecY: return new vecYOper(); + case Op_VecZ: return new vecZOper(); + } + } + ShouldNotReachHere(); + return NULL; +} + +bool Matcher::is_generic_reg2reg_move(MachNode* m) { + switch (m->rule()) { + case MoveVec2Leg_rule: + case MoveLeg2Vec_rule: + return true; + default: + return false; + } +} + +bool Matcher::is_generic_vector(MachOper* opnd) { + switch (opnd->opcode()) { + case VEC: + case LEGVEC: + return true; + default: + return false; + } +} + +//------------------------------------------------------------------------ + const bool Matcher::has_predicated_vectors(void) { bool ret_value = false; if (UseAVX > 2) { @@ -1926,6 +1975,111 @@ encode %{ // in the ADLC because operands constitute user defined types which are used in // instruction definitions. +// Vectors + +// Dummy generic vector class. Should be used for all vector operands. +// Replaced with vec[SDXYZ] during post-selection pass. +operand vec() %{ + constraint(ALLOC_IN_RC(dynamic)); + match(VecX); + match(VecY); + match(VecZ); + match(VecS); + match(VecD); + + format %{ %} + interface(REG_INTER); +%} + +// Dummy generic legacy vector class. Should be used for all legacy vector operands. +// Replaced with legVec[SDXYZ] during post-selection cleanup. +// Note: legacy register class is used to avoid extra (unneeded in 32-bit VM) +// runtime code generation via reg_class_dynamic. +operand legVec() %{ + constraint(ALLOC_IN_RC(dynamic)); + match(VecX); + match(VecY); + match(VecZ); + match(VecS); + match(VecD); + + format %{ %} + interface(REG_INTER); +%} + +// Replaces vec during post-selection cleanup. See above. +operand vecS() %{ + constraint(ALLOC_IN_RC(vectors_reg_vlbwdq)); + match(VecS); + + format %{ %} + interface(REG_INTER); +%} + +// Replaces legVec during post-selection cleanup. See above. +operand legVecS() %{ + constraint(ALLOC_IN_RC(vectors_reg_legacy)); + match(VecS); + + format %{ %} + interface(REG_INTER); +%} + +// Replaces vec during post-selection cleanup. See above. +operand vecD() %{ + constraint(ALLOC_IN_RC(vectord_reg_vlbwdq)); + match(VecD); + + format %{ %} + interface(REG_INTER); +%} + +// Replaces legVec during post-selection cleanup. See above. +operand legVecD() %{ + constraint(ALLOC_IN_RC(vectord_reg_legacy)); + match(VecD); + + format %{ %} + interface(REG_INTER); +%} + +// Replaces vec during post-selection cleanup. See above. +operand vecX() %{ + constraint(ALLOC_IN_RC(vectorx_reg_vlbwdq)); + match(VecX); + + format %{ %} + interface(REG_INTER); +%} + +// Replaces legVec during post-selection cleanup. See above. +operand legVecX() %{ + constraint(ALLOC_IN_RC(vectorx_reg_legacy)); + match(VecX); + + format %{ %} + interface(REG_INTER); +%} + +// Replaces vec during post-selection cleanup. See above. +operand vecY() %{ + constraint(ALLOC_IN_RC(vectory_reg_vlbwdq)); + match(VecY); + + format %{ %} + interface(REG_INTER); +%} + +// Replaces legVec during post-selection cleanup. See above. +operand legVecY() %{ + constraint(ALLOC_IN_RC(vectory_reg_legacy)); + match(VecY); + + format %{ %} + interface(REG_INTER); +%} + +// Replaces vec during post-selection cleanup. See above. operand vecZ() %{ constraint(ALLOC_IN_RC(vectorz_reg)); match(VecZ); @@ -1934,6 +2088,7 @@ operand vecZ() %{ interface(REG_INTER); %} +// Replaces legVec during post-selection cleanup. See above. operand legVecZ() %{ constraint(ALLOC_IN_RC(vectorz_reg_vl)); match(VecZ); @@ -2766,7 +2921,7 @@ instruct roundD_imm(legRegD dst, immD con, immU8 rmode, rRegI scratch_reg) %{ ins_pipe(pipe_slow); %} -instruct vround2D_reg(legVecX dst, legVecX src, immU8 rmode) %{ +instruct vround2D_reg(legVec dst, legVec src, immU8 rmode) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (RoundDoubleModeV src rmode)); format %{ "vroundpd $dst, $src, $rmode\t! round packed2D" %} @@ -2777,7 +2932,7 @@ instruct vround2D_reg(legVecX dst, legVecX src, immU8 rmode) %{ ins_pipe( pipe_slow ); %} -instruct vround2D_mem(legVecX dst, memory mem, immU8 rmode) %{ +instruct vround2D_mem(legVec dst, memory mem, immU8 rmode) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (RoundDoubleModeV (LoadVector mem) rmode)); format %{ "vroundpd $dst, $mem, $rmode\t! round packed2D" %} @@ -2788,7 +2943,7 @@ instruct vround2D_mem(legVecX dst, memory mem, immU8 rmode) %{ ins_pipe( pipe_slow ); %} -instruct vround4D_reg(legVecY dst, legVecY src, legVecY rmode) %{ +instruct vround4D_reg(legVec dst, legVec src, legVec rmode) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (RoundDoubleModeV src rmode)); format %{ "vroundpd $dst, $src, $rmode\t! round packed4D" %} @@ -2799,7 +2954,7 @@ instruct vround4D_reg(legVecY dst, legVecY src, legVecY rmode) %{ ins_pipe( pipe_slow ); %} -instruct vround4D_mem(legVecY dst, memory mem, immU8 rmode) %{ +instruct vround4D_mem(legVec dst, memory mem, immU8 rmode) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (RoundDoubleModeV (LoadVector mem) rmode)); format %{ "vroundpd $dst, $mem, $rmode\t! round packed4D" %} @@ -2811,7 +2966,7 @@ instruct vround4D_mem(legVecY dst, memory mem, immU8 rmode) %{ %} -instruct vround8D_reg(vecZ dst, vecZ src, immU8 rmode) %{ +instruct vround8D_reg(vec dst, vec src, immU8 rmode) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (RoundDoubleModeV src rmode)); format %{ "vrndscalepd $dst, $src, $rmode\t! round packed8D" %} @@ -2822,7 +2977,7 @@ instruct vround8D_reg(vecZ dst, vecZ src, immU8 rmode) %{ ins_pipe( pipe_slow ); %} -instruct vround8D_mem(vecZ dst, memory mem, immU8 rmode) %{ +instruct vround8D_mem(vec dst, memory mem, immU8 rmode) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (RoundDoubleModeV (LoadVector mem) rmode)); format %{ "vrndscalepd $dst, $mem, $rmode\t! round packed8D" %} @@ -2874,9 +3029,27 @@ instruct fmaF_reg(regF a, regF b, regF c) %{ // ====================VECTOR INSTRUCTIONS===================================== +// Dummy reg-to-reg vector moves. Removed during post-selection cleanup. +instruct MoveVec2Leg(legVec dst, vec src) %{ + match(Set dst src); + format %{ "" %} + ins_encode %{ + ShouldNotReachHere(); + %} + ins_pipe( fpu_reg_reg ); +%} + +instruct MoveLeg2Vec(vec dst, legVec src) %{ + match(Set dst src); + format %{ "" %} + ins_encode %{ + ShouldNotReachHere(); + %} + ins_pipe( fpu_reg_reg ); +%} // Load vectors (4 bytes long) -instruct loadV4(vecS dst, memory mem) %{ +instruct loadV4(vec dst, memory mem) %{ predicate(n->as_LoadVector()->memory_size() == 4); match(Set dst (LoadVector mem)); ins_cost(125); @@ -2887,28 +3060,8 @@ instruct loadV4(vecS dst, memory mem) %{ ins_pipe( pipe_slow ); %} -// Load vectors (4 bytes long) -instruct MoveVecS2Leg(legVecS dst, vecS src) %{ - match(Set dst src); - format %{ "movss $dst,$src\t! load vector (4 bytes)" %} - ins_encode %{ - __ movflt($dst$$XMMRegister, $src$$XMMRegister); - %} - ins_pipe( fpu_reg_reg ); -%} - -// Load vectors (4 bytes long) -instruct MoveLeg2VecS(vecS dst, legVecS src) %{ - match(Set dst src); - format %{ "movss $dst,$src\t! load vector (4 bytes)" %} - ins_encode %{ - __ movflt($dst$$XMMRegister, $src$$XMMRegister); - %} - ins_pipe( fpu_reg_reg ); -%} - // Load vectors (8 bytes long) -instruct loadV8(vecD dst, memory mem) %{ +instruct loadV8(vec dst, memory mem) %{ predicate(n->as_LoadVector()->memory_size() == 8); match(Set dst (LoadVector mem)); ins_cost(125); @@ -2919,28 +3072,8 @@ instruct loadV8(vecD dst, memory mem) %{ ins_pipe( pipe_slow ); %} -// Load vectors (8 bytes long) -instruct MoveVecD2Leg(legVecD dst, vecD src) %{ - match(Set dst src); - format %{ "movsd $dst,$src\t! load vector (8 bytes)" %} - ins_encode %{ - __ movdbl($dst$$XMMRegister, $src$$XMMRegister); - %} - ins_pipe( fpu_reg_reg ); -%} - -// Load vectors (8 bytes long) -instruct MoveLeg2VecD(vecD dst, legVecD src) %{ - match(Set dst src); - format %{ "movsd $dst,$src\t! load vector (8 bytes)" %} - ins_encode %{ - __ movdbl($dst$$XMMRegister, $src$$XMMRegister); - %} - ins_pipe( fpu_reg_reg ); -%} - // Load vectors (16 bytes long) -instruct loadV16(vecX dst, memory mem) %{ +instruct loadV16(vec dst, memory mem) %{ predicate(n->as_LoadVector()->memory_size() == 16); match(Set dst (LoadVector mem)); ins_cost(125); @@ -2951,38 +3084,8 @@ instruct loadV16(vecX dst, memory mem) %{ ins_pipe( pipe_slow ); %} -// Load vectors (16 bytes long) -instruct MoveVecX2Leg(legVecX dst, vecX src) %{ - match(Set dst src); - format %{ "movdqu $dst,$src\t! load vector (16 bytes)" %} - ins_encode %{ - if (UseAVX > 2 && !VM_Version::supports_avx512vl()) { - int vector_len = 2; - __ evmovdquq($dst$$XMMRegister, $src$$XMMRegister, vector_len); - } else { - __ movdqu($dst$$XMMRegister, $src$$XMMRegister); - } - %} - ins_pipe( fpu_reg_reg ); -%} - -// Load vectors (16 bytes long) -instruct MoveLeg2VecX(vecX dst, legVecX src) %{ - match(Set dst src); - format %{ "movdqu $dst,$src\t! load vector (16 bytes)" %} - ins_encode %{ - if (UseAVX > 2 && !VM_Version::supports_avx512vl()) { - int vector_len = 2; - __ evmovdquq($dst$$XMMRegister, $src$$XMMRegister, vector_len); - } else { - __ movdqu($dst$$XMMRegister, $src$$XMMRegister); - } - %} - ins_pipe( fpu_reg_reg ); -%} - // Load vectors (32 bytes long) -instruct loadV32(vecY dst, memory mem) %{ +instruct loadV32(vec dst, memory mem) %{ predicate(n->as_LoadVector()->memory_size() == 32); match(Set dst (LoadVector mem)); ins_cost(125); @@ -2993,38 +3096,8 @@ instruct loadV32(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -// Load vectors (32 bytes long) -instruct MoveVecY2Leg(legVecY dst, vecY src) %{ - match(Set dst src); - format %{ "vmovdqu $dst,$src\t! load vector (32 bytes)" %} - ins_encode %{ - if (UseAVX > 2 && !VM_Version::supports_avx512vl()) { - int vector_len = 2; - __ evmovdquq($dst$$XMMRegister, $src$$XMMRegister, vector_len); - } else { - __ vmovdqu($dst$$XMMRegister, $src$$XMMRegister); - } - %} - ins_pipe( fpu_reg_reg ); -%} - -// Load vectors (32 bytes long) -instruct MoveLeg2VecY(vecY dst, legVecY src) %{ - match(Set dst src); - format %{ "vmovdqu $dst,$src\t! load vector (32 bytes)" %} - ins_encode %{ - if (UseAVX > 2 && !VM_Version::supports_avx512vl()) { - int vector_len = 2; - __ evmovdquq($dst$$XMMRegister, $src$$XMMRegister, vector_len); - } else { - __ vmovdqu($dst$$XMMRegister, $src$$XMMRegister); - } - %} - ins_pipe( fpu_reg_reg ); -%} - // Load vectors (64 bytes long) -instruct loadV64_dword(vecZ dst, memory mem) %{ +instruct loadV64_dword(vec dst, memory mem) %{ predicate(n->as_LoadVector()->memory_size() == 64 && n->as_LoadVector()->element_size() <= 4); match(Set dst (LoadVector mem)); ins_cost(125); @@ -3037,7 +3110,7 @@ instruct loadV64_dword(vecZ dst, memory mem) %{ %} // Load vectors (64 bytes long) -instruct loadV64_qword(vecZ dst, memory mem) %{ +instruct loadV64_qword(vec dst, memory mem) %{ predicate(n->as_LoadVector()->memory_size() == 64 && n->as_LoadVector()->element_size() > 4); match(Set dst (LoadVector mem)); ins_cost(125); @@ -3049,28 +3122,8 @@ instruct loadV64_qword(vecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct MoveVecZ2Leg(legVecZ dst, vecZ src) %{ - match(Set dst src); - format %{ "vmovdquq $dst k0,$src\t! Move vector (64 bytes)" %} - ins_encode %{ - int vector_len = 2; - __ evmovdquq($dst$$XMMRegister, $src$$XMMRegister, vector_len); - %} - ins_pipe( fpu_reg_reg ); -%} - -instruct MoveLeg2VecZ(vecZ dst, legVecZ src) %{ - match(Set dst src); - format %{ "vmovdquq $dst k0,$src\t! Move vector (64 bytes)" %} - ins_encode %{ - int vector_len = 2; - __ evmovdquq($dst$$XMMRegister, $src$$XMMRegister, vector_len); - %} - ins_pipe( fpu_reg_reg ); -%} - // Store vectors -instruct storeV4(memory mem, vecS src) %{ +instruct storeV4(memory mem, vec src) %{ predicate(n->as_StoreVector()->memory_size() == 4); match(Set mem (StoreVector mem src)); ins_cost(145); @@ -3081,7 +3134,7 @@ instruct storeV4(memory mem, vecS src) %{ ins_pipe( pipe_slow ); %} -instruct storeV8(memory mem, vecD src) %{ +instruct storeV8(memory mem, vec src) %{ predicate(n->as_StoreVector()->memory_size() == 8); match(Set mem (StoreVector mem src)); ins_cost(145); @@ -3092,7 +3145,7 @@ instruct storeV8(memory mem, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct storeV16(memory mem, vecX src) %{ +instruct storeV16(memory mem, vec src) %{ predicate(n->as_StoreVector()->memory_size() == 16); match(Set mem (StoreVector mem src)); ins_cost(145); @@ -3103,7 +3156,7 @@ instruct storeV16(memory mem, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct storeV32(memory mem, vecY src) %{ +instruct storeV32(memory mem, vec src) %{ predicate(n->as_StoreVector()->memory_size() == 32); match(Set mem (StoreVector mem src)); ins_cost(145); @@ -3114,7 +3167,7 @@ instruct storeV32(memory mem, vecY src) %{ ins_pipe( pipe_slow ); %} -instruct storeV64_dword(memory mem, vecZ src) %{ +instruct storeV64_dword(memory mem, vec src) %{ predicate(n->as_StoreVector()->memory_size() == 64 && n->as_StoreVector()->element_size() <= 4); match(Set mem (StoreVector mem src)); ins_cost(145); @@ -3126,7 +3179,7 @@ instruct storeV64_dword(memory mem, vecZ src) %{ ins_pipe( pipe_slow ); %} -instruct storeV64_qword(memory mem, vecZ src) %{ +instruct storeV64_qword(memory mem, vec src) %{ predicate(n->as_StoreVector()->memory_size() == 64 && n->as_StoreVector()->element_size() > 4); match(Set mem (StoreVector mem src)); ins_cost(145); @@ -3140,7 +3193,7 @@ instruct storeV64_qword(memory mem, vecZ src) %{ // ====================LEGACY REPLICATE======================================= -instruct Repl16B(vecX dst, rRegI src) %{ +instruct Repl16B(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB src)); format %{ "movd $dst,$src\n\t" @@ -3156,7 +3209,7 @@ instruct Repl16B(vecX dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl32B(vecY dst, rRegI src) %{ +instruct Repl32B(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 32 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB src)); format %{ "movd $dst,$src\n\t" @@ -3174,7 +3227,7 @@ instruct Repl32B(vecY dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl64B(legVecZ dst, rRegI src) %{ +instruct Repl64B(legVec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 64 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB src)); format %{ "movd $dst,$src\n\t" @@ -3194,7 +3247,7 @@ instruct Repl64B(legVecZ dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl16B_imm(vecX dst, immI con) %{ +instruct Repl16B_imm(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -3206,7 +3259,7 @@ instruct Repl16B_imm(vecX dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl32B_imm(vecY dst, immI con) %{ +instruct Repl32B_imm(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 32 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -3220,7 +3273,7 @@ instruct Repl32B_imm(vecY dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl64B_imm(legVecZ dst, immI con) %{ +instruct Repl64B_imm(legVec dst, immI con) %{ predicate(n->as_Vector()->length() == 64 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -3236,7 +3289,7 @@ instruct Repl64B_imm(legVecZ dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl4S(vecD dst, rRegI src) %{ +instruct Repl4S(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS src)); format %{ "movd $dst,$src\n\t" @@ -3248,7 +3301,7 @@ instruct Repl4S(vecD dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl4S_mem(vecD dst, memory mem) %{ +instruct Repl4S_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 0 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS (LoadS mem))); format %{ "pshuflw $dst,$mem,0x00\t! replicate4S" %} @@ -3258,7 +3311,7 @@ instruct Repl4S_mem(vecD dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8S(vecX dst, rRegI src) %{ +instruct Repl8S(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS src)); format %{ "movd $dst,$src\n\t" @@ -3272,7 +3325,7 @@ instruct Repl8S(vecX dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl8S_mem(vecX dst, memory mem) %{ +instruct Repl8S_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 0 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS (LoadS mem))); format %{ "pshuflw $dst,$mem,0x00\n\t" @@ -3284,7 +3337,7 @@ instruct Repl8S_mem(vecX dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8S_imm(vecX dst, immI con) %{ +instruct Repl8S_imm(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -3296,7 +3349,7 @@ instruct Repl8S_imm(vecX dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl16S(vecY dst, rRegI src) %{ +instruct Repl16S(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS src)); format %{ "movd $dst,$src\n\t" @@ -3312,7 +3365,7 @@ instruct Repl16S(vecY dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl16S_mem(vecY dst, memory mem) %{ +instruct Repl16S_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS (LoadS mem))); format %{ "pshuflw $dst,$mem,0x00\n\t" @@ -3326,7 +3379,7 @@ instruct Repl16S_mem(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl16S_imm(vecY dst, immI con) %{ +instruct Repl16S_imm(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -3340,7 +3393,7 @@ instruct Repl16S_imm(vecY dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl32S(legVecZ dst, rRegI src) %{ +instruct Repl32S(legVec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 32 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS src)); format %{ "movd $dst,$src\n\t" @@ -3358,7 +3411,7 @@ instruct Repl32S(legVecZ dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl32S_mem(legVecZ dst, memory mem) %{ +instruct Repl32S_mem(legVec dst, memory mem) %{ predicate(n->as_Vector()->length() == 32 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS (LoadS mem))); format %{ "pshuflw $dst,$mem,0x00\n\t" @@ -3374,7 +3427,7 @@ instruct Repl32S_mem(legVecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl32S_imm(legVecZ dst, immI con) %{ +instruct Repl32S_imm(legVec dst, immI con) %{ predicate(n->as_Vector()->length() == 32 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -3390,7 +3443,7 @@ instruct Repl32S_imm(legVecZ dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl4I(vecX dst, rRegI src) %{ +instruct Repl4I(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateI src)); format %{ "movd $dst,$src\n\t" @@ -3402,7 +3455,7 @@ instruct Repl4I(vecX dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl4I_mem(vecX dst, memory mem) %{ +instruct Repl4I_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 0 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateI (LoadI mem))); format %{ "pshufd $dst,$mem,0x00\t! replicate4I" %} @@ -3412,7 +3465,7 @@ instruct Repl4I_mem(vecX dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8I(vecY dst, rRegI src) %{ +instruct Repl8I(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateI src)); format %{ "movd $dst,$src\n\t" @@ -3426,7 +3479,7 @@ instruct Repl8I(vecY dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl8I_mem(vecY dst, memory mem) %{ +instruct Repl8I_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateI (LoadI mem))); format %{ "pshufd $dst,$mem,0x00\n\t" @@ -3438,7 +3491,7 @@ instruct Repl8I_mem(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl16I(legVecZ dst, rRegI src) %{ +instruct Repl16I(legVec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateI src)); format %{ "movd $dst,$src\n\t" @@ -3454,7 +3507,7 @@ instruct Repl16I(legVecZ dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl16I_mem(legVecZ dst, memory mem) %{ +instruct Repl16I_mem(legVec dst, memory mem) %{ predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateI (LoadI mem))); format %{ "pshufd $dst,$mem,0x00\n\t" @@ -3468,7 +3521,7 @@ instruct Repl16I_mem(legVecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl4I_imm(vecX dst, immI con) %{ +instruct Repl4I_imm(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateI con)); format %{ "movq $dst,[$constantaddress]\t! replicate4I($con)\n\t" @@ -3480,7 +3533,7 @@ instruct Repl4I_imm(vecX dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl8I_imm(vecY dst, immI con) %{ +instruct Repl8I_imm(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateI con)); format %{ "movq $dst,[$constantaddress]\t! replicate8I($con)\n\t" @@ -3494,7 +3547,7 @@ instruct Repl8I_imm(vecY dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl16I_imm(legVecZ dst, immI con) %{ +instruct Repl16I_imm(legVec dst, immI con) %{ predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateI con)); format %{ "movq $dst,[$constantaddress]\t" @@ -3511,7 +3564,7 @@ instruct Repl16I_imm(legVecZ dst, immI con) %{ %} // Long could be loaded into xmm register directly from memory. -instruct Repl2L_mem(vecX dst, memory mem) %{ +instruct Repl2L_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 2 && !VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateL (LoadL mem))); format %{ "movq $dst,$mem\n\t" @@ -3525,7 +3578,7 @@ instruct Repl2L_mem(vecX dst, memory mem) %{ // Replicate long (8 byte) scalar to be vector #ifdef _LP64 -instruct Repl4L(vecY dst, rRegL src) %{ +instruct Repl4L(vec dst, rRegL src) %{ predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateL src)); format %{ "movdq $dst,$src\n\t" @@ -3539,7 +3592,7 @@ instruct Repl4L(vecY dst, rRegL src) %{ ins_pipe( pipe_slow ); %} -instruct Repl8L(legVecZ dst, rRegL src) %{ +instruct Repl8L(legVec dst, rRegL src) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateL src)); format %{ "movdq $dst,$src\n\t" @@ -3555,7 +3608,7 @@ instruct Repl8L(legVecZ dst, rRegL src) %{ ins_pipe( pipe_slow ); %} #else // _LP64 -instruct Repl4L(vecY dst, eRegL src, vecY tmp) %{ +instruct Repl4L(vec dst, eRegL src, vec tmp) %{ predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateL src)); effect(TEMP dst, USE src, TEMP tmp); @@ -3574,7 +3627,7 @@ instruct Repl4L(vecY dst, eRegL src, vecY tmp) %{ ins_pipe( pipe_slow ); %} -instruct Repl8L(legVecZ dst, eRegL src, legVecZ tmp) %{ +instruct Repl8L(legVec dst, eRegL src, legVec tmp) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateL src)); effect(TEMP dst, USE src, TEMP tmp); @@ -3596,7 +3649,7 @@ instruct Repl8L(legVecZ dst, eRegL src, legVecZ tmp) %{ %} #endif // _LP64 -instruct Repl4L_imm(vecY dst, immL con) %{ +instruct Repl4L_imm(vec dst, immL con) %{ predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateL con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -3610,7 +3663,7 @@ instruct Repl4L_imm(vecY dst, immL con) %{ ins_pipe( pipe_slow ); %} -instruct Repl8L_imm(legVecZ dst, immL con) %{ +instruct Repl8L_imm(legVec dst, immL con) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateL con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -3626,7 +3679,7 @@ instruct Repl8L_imm(legVecZ dst, immL con) %{ ins_pipe( pipe_slow ); %} -instruct Repl4L_mem(vecY dst, memory mem) %{ +instruct Repl4L_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateL (LoadL mem))); format %{ "movq $dst,$mem\n\t" @@ -3640,7 +3693,7 @@ instruct Repl4L_mem(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8L_mem(legVecZ dst, memory mem) %{ +instruct Repl8L_mem(legVec dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateL (LoadL mem))); format %{ "movq $dst,$mem\n\t" @@ -3656,7 +3709,7 @@ instruct Repl8L_mem(legVecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl2F_mem(vecD dst, memory mem) %{ +instruct Repl2F_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 2 && UseAVX > 0 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateF (LoadF mem))); format %{ "pshufd $dst,$mem,0x00\t! replicate2F" %} @@ -3666,7 +3719,7 @@ instruct Repl2F_mem(vecD dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl4F_mem(vecX dst, memory mem) %{ +instruct Repl4F_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 0 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateF (LoadF mem))); format %{ "pshufd $dst,$mem,0x00\t! replicate4F" %} @@ -3676,7 +3729,7 @@ instruct Repl4F_mem(vecX dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8F(vecY dst, vlRegF src) %{ +instruct Repl8F(vec dst, vlRegF src) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 0 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateF src)); format %{ "pshufd $dst,$src,0x00\n\t" @@ -3688,7 +3741,7 @@ instruct Repl8F(vecY dst, vlRegF src) %{ ins_pipe( pipe_slow ); %} -instruct Repl8F_mem(vecY dst, memory mem) %{ +instruct Repl8F_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateF (LoadF mem))); format %{ "pshufd $dst,$mem,0x00\n\t" @@ -3700,7 +3753,7 @@ instruct Repl8F_mem(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl16F(legVecZ dst, vlRegF src) %{ +instruct Repl16F(legVec dst, vlRegF src) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 0 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateF src)); format %{ "pshufd $dst,$src,0x00\n\t" @@ -3714,7 +3767,7 @@ instruct Repl16F(legVecZ dst, vlRegF src) %{ ins_pipe( pipe_slow ); %} -instruct Repl16F_mem(legVecZ dst, memory mem) %{ +instruct Repl16F_mem(legVec dst, memory mem) %{ predicate(n->as_Vector()->length() == 16 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateF (LoadF mem))); format %{ "pshufd $dst,$mem,0x00\n\t" @@ -3728,7 +3781,7 @@ instruct Repl16F_mem(legVecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl2F_zero(vecD dst, immF0 zero) %{ +instruct Repl2F_zero(vec dst, immF0 zero) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateF zero)); format %{ "xorps $dst,$dst\t! replicate2F zero" %} @@ -3738,7 +3791,7 @@ instruct Repl2F_zero(vecD dst, immF0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl4F_zero(vecX dst, immF0 zero) %{ +instruct Repl4F_zero(vec dst, immF0 zero) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateF zero)); format %{ "xorps $dst,$dst\t! replicate4F zero" %} @@ -3748,7 +3801,7 @@ instruct Repl4F_zero(vecX dst, immF0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl8F_zero(vecY dst, immF0 zero) %{ +instruct Repl8F_zero(vec dst, immF0 zero) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 0); match(Set dst (ReplicateF zero)); format %{ "vxorps $dst,$dst,$dst\t! replicate8F zero" %} @@ -3759,7 +3812,7 @@ instruct Repl8F_zero(vecY dst, immF0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl2D_mem(vecX dst, memory mem) %{ +instruct Repl2D_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 2 && UseAVX > 0 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateD (LoadD mem))); format %{ "pshufd $dst,$mem,0x44\t! replicate2D" %} @@ -3769,7 +3822,7 @@ instruct Repl2D_mem(vecX dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl4D(vecY dst, vlRegD src) %{ +instruct Repl4D(vec dst, vlRegD src) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 0 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateD src)); format %{ "pshufd $dst,$src,0x44\n\t" @@ -3781,7 +3834,7 @@ instruct Repl4D(vecY dst, vlRegD src) %{ ins_pipe( pipe_slow ); %} -instruct Repl4D_mem(vecY dst, memory mem) %{ +instruct Repl4D_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateD (LoadD mem))); format %{ "pshufd $dst,$mem,0x44\n\t" @@ -3793,7 +3846,7 @@ instruct Repl4D_mem(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8D(legVecZ dst, vlRegD src) %{ +instruct Repl8D(legVec dst, vlRegD src) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 0 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateD src)); format %{ "pshufd $dst,$src,0x44\n\t" @@ -3807,7 +3860,7 @@ instruct Repl8D(legVecZ dst, vlRegD src) %{ ins_pipe( pipe_slow ); %} -instruct Repl8D_mem(legVecZ dst, memory mem) %{ +instruct Repl8D_mem(legVec dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateD (LoadD mem))); format %{ "pshufd $dst,$mem,0x44\n\t" @@ -3822,7 +3875,7 @@ instruct Repl8D_mem(legVecZ dst, memory mem) %{ %} // Replicate double (8 byte) scalar zero to be vector -instruct Repl2D_zero(vecX dst, immD0 zero) %{ +instruct Repl2D_zero(vec dst, immD0 zero) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateD zero)); format %{ "xorpd $dst,$dst\t! replicate2D zero" %} @@ -3832,7 +3885,7 @@ instruct Repl2D_zero(vecX dst, immD0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl4D_zero(vecY dst, immD0 zero) %{ +instruct Repl4D_zero(vec dst, immD0 zero) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 0); match(Set dst (ReplicateD zero)); format %{ "vxorpd $dst,$dst,$dst,vect256\t! replicate4D zero" %} @@ -3846,7 +3899,7 @@ instruct Repl4D_zero(vecY dst, immD0 zero) %{ // ====================GENERIC REPLICATE========================================== // Replicate byte scalar to be vector -instruct Repl4B(vecS dst, rRegI src) %{ +instruct Repl4B(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateB src)); format %{ "movd $dst,$src\n\t" @@ -3860,7 +3913,7 @@ instruct Repl4B(vecS dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl8B(vecD dst, rRegI src) %{ +instruct Repl8B(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateB src)); format %{ "movd $dst,$src\n\t" @@ -3875,7 +3928,7 @@ instruct Repl8B(vecD dst, rRegI src) %{ %} // Replicate byte scalar immediate to be vector by loading from const table. -instruct Repl4B_imm(vecS dst, immI con) %{ +instruct Repl4B_imm(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateB con)); format %{ "movdl $dst,[$constantaddress]\t! replicate4B($con)" %} @@ -3885,7 +3938,7 @@ instruct Repl4B_imm(vecS dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl8B_imm(vecD dst, immI con) %{ +instruct Repl8B_imm(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateB con)); format %{ "movq $dst,[$constantaddress]\t! replicate8B($con)" %} @@ -3896,7 +3949,7 @@ instruct Repl8B_imm(vecD dst, immI con) %{ %} // Replicate byte scalar zero to be vector -instruct Repl4B_zero(vecS dst, immI0 zero) %{ +instruct Repl4B_zero(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateB zero)); format %{ "pxor $dst,$dst\t! replicate4B zero" %} @@ -3906,7 +3959,7 @@ instruct Repl4B_zero(vecS dst, immI0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl8B_zero(vecD dst, immI0 zero) %{ +instruct Repl8B_zero(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateB zero)); format %{ "pxor $dst,$dst\t! replicate8B zero" %} @@ -3916,7 +3969,7 @@ instruct Repl8B_zero(vecD dst, immI0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl16B_zero(vecX dst, immI0 zero) %{ +instruct Repl16B_zero(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 16); match(Set dst (ReplicateB zero)); format %{ "pxor $dst,$dst\t! replicate16B zero" %} @@ -3926,7 +3979,7 @@ instruct Repl16B_zero(vecX dst, immI0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl32B_zero(vecY dst, immI0 zero) %{ +instruct Repl32B_zero(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 32); match(Set dst (ReplicateB zero)); format %{ "vpxor $dst,$dst,$dst\t! replicate32B zero" %} @@ -3939,7 +3992,7 @@ instruct Repl32B_zero(vecY dst, immI0 zero) %{ %} // Replicate char/short (2 byte) scalar to be vector -instruct Repl2S(vecS dst, rRegI src) %{ +instruct Repl2S(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateS src)); format %{ "movd $dst,$src\n\t" @@ -3952,7 +4005,7 @@ instruct Repl2S(vecS dst, rRegI src) %{ %} // Replicate char/short (2 byte) scalar immediate to be vector by loading from const table. -instruct Repl2S_imm(vecS dst, immI con) %{ +instruct Repl2S_imm(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateS con)); format %{ "movdl $dst,[$constantaddress]\t! replicate2S($con)" %} @@ -3962,7 +4015,7 @@ instruct Repl2S_imm(vecS dst, immI con) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl4S_imm(vecD dst, immI con) %{ +instruct Repl4S_imm(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateS con)); format %{ "movq $dst,[$constantaddress]\t! replicate4S($con)" %} @@ -3973,7 +4026,7 @@ instruct Repl4S_imm(vecD dst, immI con) %{ %} // Replicate char/short (2 byte) scalar zero to be vector -instruct Repl2S_zero(vecS dst, immI0 zero) %{ +instruct Repl2S_zero(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateS zero)); format %{ "pxor $dst,$dst\t! replicate2S zero" %} @@ -3983,7 +4036,7 @@ instruct Repl2S_zero(vecS dst, immI0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl4S_zero(vecD dst, immI0 zero) %{ +instruct Repl4S_zero(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateS zero)); format %{ "pxor $dst,$dst\t! replicate4S zero" %} @@ -3993,7 +4046,7 @@ instruct Repl4S_zero(vecD dst, immI0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl8S_zero(vecX dst, immI0 zero) %{ +instruct Repl8S_zero(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateS zero)); format %{ "pxor $dst,$dst\t! replicate8S zero" %} @@ -4003,7 +4056,7 @@ instruct Repl8S_zero(vecX dst, immI0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl16S_zero(vecY dst, immI0 zero) %{ +instruct Repl16S_zero(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 16); match(Set dst (ReplicateS zero)); format %{ "vpxor $dst,$dst,$dst\t! replicate16S zero" %} @@ -4016,7 +4069,7 @@ instruct Repl16S_zero(vecY dst, immI0 zero) %{ %} // Replicate integer (4 byte) scalar to be vector -instruct Repl2I(vecD dst, rRegI src) %{ +instruct Repl2I(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateI src)); format %{ "movd $dst,$src\n\t" @@ -4029,7 +4082,7 @@ instruct Repl2I(vecD dst, rRegI src) %{ %} // Integer could be loaded into xmm register directly from memory. -instruct Repl2I_mem(vecD dst, memory mem) %{ +instruct Repl2I_mem(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateI (LoadI mem))); format %{ "movd $dst,$mem\n\t" @@ -4042,7 +4095,7 @@ instruct Repl2I_mem(vecD dst, memory mem) %{ %} // Replicate integer (4 byte) scalar immediate to be vector by loading from const table. -instruct Repl2I_imm(vecD dst, immI con) %{ +instruct Repl2I_imm(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateI con)); format %{ "movq $dst,[$constantaddress]\t! replicate2I($con)" %} @@ -4053,7 +4106,7 @@ instruct Repl2I_imm(vecD dst, immI con) %{ %} // Replicate integer (4 byte) scalar zero to be vector -instruct Repl2I_zero(vecD dst, immI0 zero) %{ +instruct Repl2I_zero(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateI zero)); format %{ "pxor $dst,$dst\t! replicate2I" %} @@ -4063,7 +4116,7 @@ instruct Repl2I_zero(vecD dst, immI0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl4I_zero(vecX dst, immI0 zero) %{ +instruct Repl4I_zero(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateI zero)); format %{ "pxor $dst,$dst\t! replicate4I zero)" %} @@ -4073,7 +4126,7 @@ instruct Repl4I_zero(vecX dst, immI0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl8I_zero(vecY dst, immI0 zero) %{ +instruct Repl8I_zero(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (ReplicateI zero)); format %{ "vpxor $dst,$dst,$dst\t! replicate8I zero" %} @@ -4087,7 +4140,7 @@ instruct Repl8I_zero(vecY dst, immI0 zero) %{ // Replicate long (8 byte) scalar to be vector #ifdef _LP64 -instruct Repl2L(vecX dst, rRegL src) %{ +instruct Repl2L(vec dst, rRegL src) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateL src)); format %{ "movdq $dst,$src\n\t" @@ -4099,7 +4152,7 @@ instruct Repl2L(vecX dst, rRegL src) %{ ins_pipe( pipe_slow ); %} #else // _LP64 -instruct Repl2L(vecX dst, eRegL src, vecX tmp) %{ +instruct Repl2L(vec dst, eRegL src, vec tmp) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateL src)); effect(TEMP dst, USE src, TEMP tmp); @@ -4118,7 +4171,7 @@ instruct Repl2L(vecX dst, eRegL src, vecX tmp) %{ #endif // _LP64 // Replicate long (8 byte) scalar immediate to be vector by loading from const table. -instruct Repl2L_imm(vecX dst, immL con) %{ +instruct Repl2L_imm(vec dst, immL con) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateL con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -4131,7 +4184,7 @@ instruct Repl2L_imm(vecX dst, immL con) %{ %} // Replicate long (8 byte) scalar zero to be vector -instruct Repl2L_zero(vecX dst, immL0 zero) %{ +instruct Repl2L_zero(vec dst, immL0 zero) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateL zero)); format %{ "pxor $dst,$dst\t! replicate2L zero" %} @@ -4141,7 +4194,7 @@ instruct Repl2L_zero(vecX dst, immL0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl4L_zero(vecY dst, immL0 zero) %{ +instruct Repl4L_zero(vec dst, immL0 zero) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateL zero)); format %{ "vpxor $dst,$dst,$dst\t! replicate4L zero" %} @@ -4154,7 +4207,7 @@ instruct Repl4L_zero(vecY dst, immL0 zero) %{ %} // Replicate float (4 byte) scalar to be vector -instruct Repl2F(vecD dst, vlRegF src) %{ +instruct Repl2F(vec dst, vlRegF src) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateF src)); format %{ "pshufd $dst,$dst,0x00\t! replicate2F" %} @@ -4164,7 +4217,7 @@ instruct Repl2F(vecD dst, vlRegF src) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl4F(vecX dst, vlRegF src) %{ +instruct Repl4F(vec dst, vlRegF src) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (ReplicateF src)); format %{ "pshufd $dst,$dst,0x00\t! replicate4F" %} @@ -4175,7 +4228,7 @@ instruct Repl4F(vecX dst, vlRegF src) %{ %} // Replicate double (8 bytes) scalar to be vector -instruct Repl2D(vecX dst, vlRegD src) %{ +instruct Repl2D(vec dst, vlRegD src) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (ReplicateD src)); format %{ "pshufd $dst,$src,0x44\t! replicate2D" %} @@ -4187,7 +4240,7 @@ instruct Repl2D(vecX dst, vlRegD src) %{ // ====================EVEX REPLICATE============================================= -instruct Repl4B_mem_evex(vecS dst, memory mem) %{ +instruct Repl4B_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB (LoadB mem))); format %{ "vpbroadcastb $dst,$mem\t! replicate4B" %} @@ -4198,7 +4251,7 @@ instruct Repl4B_mem_evex(vecS dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8B_mem_evex(vecD dst, memory mem) %{ +instruct Repl8B_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB (LoadB mem))); format %{ "vpbroadcastb $dst,$mem\t! replicate8B" %} @@ -4209,7 +4262,7 @@ instruct Repl8B_mem_evex(vecD dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl16B_evex(vecX dst, rRegI src) %{ +instruct Repl16B_evex(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB src)); format %{ "evpbroadcastb $dst,$src\t! replicate16B" %} @@ -4220,7 +4273,7 @@ instruct Repl16B_evex(vecX dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl16B_mem_evex(vecX dst, memory mem) %{ +instruct Repl16B_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB (LoadB mem))); format %{ "vpbroadcastb $dst,$mem\t! replicate16B" %} @@ -4231,7 +4284,7 @@ instruct Repl16B_mem_evex(vecX dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl32B_evex(vecY dst, rRegI src) %{ +instruct Repl32B_evex(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 32 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB src)); format %{ "evpbroadcastb $dst,$src\t! replicate32B" %} @@ -4242,7 +4295,7 @@ instruct Repl32B_evex(vecY dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl32B_mem_evex(vecY dst, memory mem) %{ +instruct Repl32B_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 32 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB (LoadB mem))); format %{ "vpbroadcastb $dst,$mem\t! replicate32B" %} @@ -4253,7 +4306,7 @@ instruct Repl32B_mem_evex(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl64B_evex(vecZ dst, rRegI src) %{ +instruct Repl64B_evex(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 64 && UseAVX > 2 && VM_Version::supports_avx512bw()); match(Set dst (ReplicateB src)); format %{ "evpbroadcastb $dst,$src\t! upper replicate64B" %} @@ -4264,7 +4317,7 @@ instruct Repl64B_evex(vecZ dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl64B_mem_evex(vecZ dst, memory mem) %{ +instruct Repl64B_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 64 && UseAVX > 2 && VM_Version::supports_avx512bw()); match(Set dst (ReplicateB (LoadB mem))); format %{ "vpbroadcastb $dst,$mem\t! replicate64B" %} @@ -4275,7 +4328,7 @@ instruct Repl64B_mem_evex(vecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl16B_imm_evex(vecX dst, immI con) %{ +instruct Repl16B_imm_evex(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -4288,7 +4341,7 @@ instruct Repl16B_imm_evex(vecX dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl32B_imm_evex(vecY dst, immI con) %{ +instruct Repl32B_imm_evex(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 32 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateB con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -4301,7 +4354,7 @@ instruct Repl32B_imm_evex(vecY dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl64B_imm_evex(vecZ dst, immI con) %{ +instruct Repl64B_imm_evex(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 64 && UseAVX > 2 && VM_Version::supports_avx512bw()); match(Set dst (ReplicateB con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -4314,7 +4367,7 @@ instruct Repl64B_imm_evex(vecZ dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl64B_zero_evex(vecZ dst, immI0 zero) %{ +instruct Repl64B_zero_evex(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 64 && UseAVX > 2); match(Set dst (ReplicateB zero)); format %{ "vpxor $dst k0,$dst,$dst\t! replicate64B zero" %} @@ -4326,7 +4379,7 @@ instruct Repl64B_zero_evex(vecZ dst, immI0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl4S_evex(vecD dst, rRegI src) %{ +instruct Repl4S_evex(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS src)); format %{ "evpbroadcastw $dst,$src\t! replicate4S" %} @@ -4337,7 +4390,7 @@ instruct Repl4S_evex(vecD dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl4S_mem_evex(vecD dst, memory mem) %{ +instruct Repl4S_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS (LoadS mem))); format %{ "vpbroadcastw $dst,$mem\t! replicate4S" %} @@ -4348,7 +4401,7 @@ instruct Repl4S_mem_evex(vecD dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8S_evex(vecX dst, rRegI src) %{ +instruct Repl8S_evex(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS src)); format %{ "evpbroadcastw $dst,$src\t! replicate8S" %} @@ -4359,7 +4412,7 @@ instruct Repl8S_evex(vecX dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl8S_mem_evex(vecX dst, memory mem) %{ +instruct Repl8S_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS (LoadS mem))); format %{ "vpbroadcastw $dst,$mem\t! replicate8S" %} @@ -4370,7 +4423,7 @@ instruct Repl8S_mem_evex(vecX dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl16S_evex(vecY dst, rRegI src) %{ +instruct Repl16S_evex(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS src)); format %{ "evpbroadcastw $dst,$src\t! replicate16S" %} @@ -4381,7 +4434,7 @@ instruct Repl16S_evex(vecY dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl16S_mem_evex(vecY dst, memory mem) %{ +instruct Repl16S_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS (LoadS mem))); format %{ "vpbroadcastw $dst,$mem\t! replicate16S" %} @@ -4392,7 +4445,7 @@ instruct Repl16S_mem_evex(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl32S_evex(vecZ dst, rRegI src) %{ +instruct Repl32S_evex(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 32 && UseAVX > 2 && VM_Version::supports_avx512bw()); match(Set dst (ReplicateS src)); format %{ "evpbroadcastw $dst,$src\t! replicate32S" %} @@ -4403,7 +4456,7 @@ instruct Repl32S_evex(vecZ dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl32S_mem_evex(vecZ dst, memory mem) %{ +instruct Repl32S_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 32 && UseAVX > 2 && VM_Version::supports_avx512bw()); match(Set dst (ReplicateS (LoadS mem))); format %{ "vpbroadcastw $dst,$mem\t! replicate32S" %} @@ -4414,7 +4467,7 @@ instruct Repl32S_mem_evex(vecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8S_imm_evex(vecX dst, immI con) %{ +instruct Repl8S_imm_evex(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -4427,7 +4480,7 @@ instruct Repl8S_imm_evex(vecX dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl16S_imm_evex(vecY dst, immI con) %{ +instruct Repl16S_imm_evex(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2 && VM_Version::supports_avx512vlbw()); match(Set dst (ReplicateS con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -4440,7 +4493,7 @@ instruct Repl16S_imm_evex(vecY dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl32S_imm_evex(vecZ dst, immI con) %{ +instruct Repl32S_imm_evex(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 32 && UseAVX > 2 && VM_Version::supports_avx512bw()); match(Set dst (ReplicateS con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -4453,7 +4506,7 @@ instruct Repl32S_imm_evex(vecZ dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl32S_zero_evex(vecZ dst, immI0 zero) %{ +instruct Repl32S_zero_evex(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 32 && UseAVX > 2); match(Set dst (ReplicateS zero)); format %{ "vpxor $dst k0,$dst,$dst\t! replicate32S zero" %} @@ -4465,7 +4518,7 @@ instruct Repl32S_zero_evex(vecZ dst, immI0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl4I_evex(vecX dst, rRegI src) %{ +instruct Repl4I_evex(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateI src)); format %{ "evpbroadcastd $dst,$src\t! replicate4I" %} @@ -4476,7 +4529,7 @@ instruct Repl4I_evex(vecX dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl4I_mem_evex(vecX dst, memory mem) %{ +instruct Repl4I_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateI (LoadI mem))); format %{ "vpbroadcastd $dst,$mem\t! replicate4I" %} @@ -4487,7 +4540,7 @@ instruct Repl4I_mem_evex(vecX dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8I_evex(vecY dst, rRegI src) %{ +instruct Repl8I_evex(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateI src)); format %{ "evpbroadcastd $dst,$src\t! replicate8I" %} @@ -4498,7 +4551,7 @@ instruct Repl8I_evex(vecY dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl8I_mem_evex(vecY dst, memory mem) %{ +instruct Repl8I_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateI (LoadI mem))); format %{ "vpbroadcastd $dst,$mem\t! replicate8I" %} @@ -4509,7 +4562,7 @@ instruct Repl8I_mem_evex(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl16I_evex(vecZ dst, rRegI src) %{ +instruct Repl16I_evex(vec dst, rRegI src) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2); match(Set dst (ReplicateI src)); format %{ "evpbroadcastd $dst,$src\t! replicate16I" %} @@ -4520,7 +4573,7 @@ instruct Repl16I_evex(vecZ dst, rRegI src) %{ ins_pipe( pipe_slow ); %} -instruct Repl16I_mem_evex(vecZ dst, memory mem) %{ +instruct Repl16I_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2); match(Set dst (ReplicateI (LoadI mem))); format %{ "vpbroadcastd $dst,$mem\t! replicate16I" %} @@ -4531,7 +4584,7 @@ instruct Repl16I_mem_evex(vecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl4I_imm_evex(vecX dst, immI con) %{ +instruct Repl4I_imm_evex(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateI con)); format %{ "movq $dst,[$constantaddress]\t! replicate8I($con)\n\t" @@ -4544,7 +4597,7 @@ instruct Repl4I_imm_evex(vecX dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl8I_imm_evex(vecY dst, immI con) %{ +instruct Repl8I_imm_evex(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateI con)); format %{ "movq $dst,[$constantaddress]\t! replicate8I($con)\n\t" @@ -4557,7 +4610,7 @@ instruct Repl8I_imm_evex(vecY dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl16I_imm_evex(vecZ dst, immI con) %{ +instruct Repl16I_imm_evex(vec dst, immI con) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2); match(Set dst (ReplicateI con)); format %{ "movq $dst,[$constantaddress]\t! replicate16I($con)\n\t" @@ -4570,7 +4623,7 @@ instruct Repl16I_imm_evex(vecZ dst, immI con) %{ ins_pipe( pipe_slow ); %} -instruct Repl16I_zero_evex(vecZ dst, immI0 zero) %{ +instruct Repl16I_zero_evex(vec dst, immI0 zero) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2); match(Set dst (ReplicateI zero)); format %{ "vpxor $dst k0,$dst,$dst\t! replicate16I zero" %} @@ -4584,7 +4637,7 @@ instruct Repl16I_zero_evex(vecZ dst, immI0 zero) %{ // Replicate long (8 byte) scalar to be vector #ifdef _LP64 -instruct Repl4L_evex(vecY dst, rRegL src) %{ +instruct Repl4L_evex(vec dst, rRegL src) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateL src)); format %{ "evpbroadcastq $dst,$src\t! replicate4L" %} @@ -4595,7 +4648,7 @@ instruct Repl4L_evex(vecY dst, rRegL src) %{ ins_pipe( pipe_slow ); %} -instruct Repl8L_evex(vecZ dst, rRegL src) %{ +instruct Repl8L_evex(vec dst, rRegL src) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2); match(Set dst (ReplicateL src)); format %{ "evpbroadcastq $dst,$src\t! replicate8L" %} @@ -4606,7 +4659,7 @@ instruct Repl8L_evex(vecZ dst, rRegL src) %{ ins_pipe( pipe_slow ); %} #else // _LP64 -instruct Repl4L_evex(vecY dst, eRegL src, regD tmp) %{ +instruct Repl4L_evex(vec dst, eRegL src, regD tmp) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateL src)); effect(TEMP dst, USE src, TEMP tmp); @@ -4624,7 +4677,7 @@ instruct Repl4L_evex(vecY dst, eRegL src, regD tmp) %{ ins_pipe( pipe_slow ); %} -instruct Repl8L_evex(legVecZ dst, eRegL src, legVecZ tmp) %{ +instruct Repl8L_evex(legVec dst, eRegL src, legVec tmp) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2); match(Set dst (ReplicateL src)); effect(TEMP dst, USE src, TEMP tmp); @@ -4643,7 +4696,7 @@ instruct Repl8L_evex(legVecZ dst, eRegL src, legVecZ tmp) %{ %} #endif // _LP64 -instruct Repl4L_imm_evex(vecY dst, immL con) %{ +instruct Repl4L_imm_evex(vec dst, immL con) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateL con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -4656,7 +4709,7 @@ instruct Repl4L_imm_evex(vecY dst, immL con) %{ ins_pipe( pipe_slow ); %} -instruct Repl8L_imm_evex(vecZ dst, immL con) %{ +instruct Repl8L_imm_evex(vec dst, immL con) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2); match(Set dst (ReplicateL con)); format %{ "movq $dst,[$constantaddress]\n\t" @@ -4669,7 +4722,7 @@ instruct Repl8L_imm_evex(vecZ dst, immL con) %{ ins_pipe( pipe_slow ); %} -instruct Repl2L_mem_evex(vecX dst, memory mem) %{ +instruct Repl2L_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 2 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateL (LoadL mem))); format %{ "vpbroadcastd $dst,$mem\t! replicate2L" %} @@ -4680,7 +4733,7 @@ instruct Repl2L_mem_evex(vecX dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl4L_mem_evex(vecY dst, memory mem) %{ +instruct Repl4L_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateL (LoadL mem))); format %{ "vpbroadcastd $dst,$mem\t! replicate4L" %} @@ -4691,7 +4744,7 @@ instruct Repl4L_mem_evex(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8L_mem_evex(vecZ dst, memory mem) %{ +instruct Repl8L_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2); match(Set dst (ReplicateL (LoadL mem))); format %{ "vpbroadcastd $dst,$mem\t! replicate8L" %} @@ -4702,7 +4755,7 @@ instruct Repl8L_mem_evex(vecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8L_zero_evex(vecZ dst, immL0 zero) %{ +instruct Repl8L_zero_evex(vec dst, immL0 zero) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2); match(Set dst (ReplicateL zero)); format %{ "vpxor $dst k0,$dst,$dst\t! replicate8L zero" %} @@ -4714,7 +4767,7 @@ instruct Repl8L_zero_evex(vecZ dst, immL0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl8F_evex(vecY dst, regF src) %{ +instruct Repl8F_evex(vec dst, regF src) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateF src)); format %{ "vpbroadcastss $dst,$src\t! replicate8F" %} @@ -4725,7 +4778,7 @@ instruct Repl8F_evex(vecY dst, regF src) %{ ins_pipe( pipe_slow ); %} -instruct Repl8F_mem_evex(vecY dst, memory mem) %{ +instruct Repl8F_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateF (LoadF mem))); format %{ "vbroadcastss $dst,$mem\t! replicate8F" %} @@ -4736,7 +4789,7 @@ instruct Repl8F_mem_evex(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl16F_evex(vecZ dst, regF src) %{ +instruct Repl16F_evex(vec dst, regF src) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2); match(Set dst (ReplicateF src)); format %{ "vpbroadcastss $dst,$src\t! replicate16F" %} @@ -4747,7 +4800,7 @@ instruct Repl16F_evex(vecZ dst, regF src) %{ ins_pipe( pipe_slow ); %} -instruct Repl16F_mem_evex(vecZ dst, memory mem) %{ +instruct Repl16F_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2); match(Set dst (ReplicateF (LoadF mem))); format %{ "vbroadcastss $dst,$mem\t! replicate16F" %} @@ -4758,7 +4811,7 @@ instruct Repl16F_mem_evex(vecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl16F_zero_evex(vecZ dst, immF0 zero) %{ +instruct Repl16F_zero_evex(vec dst, immF0 zero) %{ predicate(n->as_Vector()->length() == 16 && UseAVX > 2); match(Set dst (ReplicateF zero)); format %{ "vpxor $dst k0,$dst,$dst\t! replicate16F zero" %} @@ -4770,7 +4823,7 @@ instruct Repl16F_zero_evex(vecZ dst, immF0 zero) %{ ins_pipe( fpu_reg_reg ); %} -instruct Repl4D_evex(vecY dst, regD src) %{ +instruct Repl4D_evex(vec dst, regD src) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateD src)); format %{ "vpbroadcastsd $dst,$src\t! replicate4D" %} @@ -4781,7 +4834,7 @@ instruct Repl4D_evex(vecY dst, regD src) %{ ins_pipe( pipe_slow ); %} -instruct Repl4D_mem_evex(vecY dst, memory mem) %{ +instruct Repl4D_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 4 && UseAVX > 2 && VM_Version::supports_avx512vl()); match(Set dst (ReplicateD (LoadD mem))); format %{ "vbroadcastsd $dst,$mem\t! replicate4D" %} @@ -4792,7 +4845,7 @@ instruct Repl4D_mem_evex(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8D_evex(vecZ dst, regD src) %{ +instruct Repl8D_evex(vec dst, regD src) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2); match(Set dst (ReplicateD src)); format %{ "vpbroadcastsd $dst,$src\t! replicate8D" %} @@ -4803,7 +4856,7 @@ instruct Repl8D_evex(vecZ dst, regD src) %{ ins_pipe( pipe_slow ); %} -instruct Repl8D_mem_evex(vecZ dst, memory mem) %{ +instruct Repl8D_mem_evex(vec dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2); match(Set dst (ReplicateD (LoadD mem))); format %{ "vbroadcastsd $dst,$mem\t! replicate8D" %} @@ -4814,7 +4867,7 @@ instruct Repl8D_mem_evex(vecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct Repl8D_zero_evex(vecZ dst, immD0 zero) %{ +instruct Repl8D_zero_evex(vec dst, immD0 zero) %{ predicate(n->as_Vector()->length() == 8 && UseAVX > 2); match(Set dst (ReplicateD zero)); format %{ "vpxor $dst k0,$dst,$dst,vect512\t! replicate8D zero" %} @@ -4828,8 +4881,8 @@ instruct Repl8D_zero_evex(vecZ dst, immD0 zero) %{ // ====================REDUCTION ARITHMETIC======================================= -instruct rsadd2I_reduction_reg(rRegI dst, rRegI src1, vecD src2, vecD tmp, vecD tmp2) %{ - predicate(UseSSE > 2 && UseAVX == 0); +instruct rsadd2I_reduction_reg(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseSSE > 2 && UseAVX == 0 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp2, TEMP tmp); format %{ "movdqu $tmp2,$src2\n\t" @@ -4847,8 +4900,8 @@ instruct rsadd2I_reduction_reg(rRegI dst, rRegI src1, vecD src2, vecD tmp, vecD ins_pipe( pipe_slow ); %} -instruct rvadd2I_reduction_reg(rRegI dst, rRegI src1, vecD src2, vecD tmp, vecD tmp2) %{ - predicate(VM_Version::supports_avxonly()); +instruct rvadd2I_reduction_reg(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 0 && VM_Version::supports_avxonly() && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "vphaddd $tmp,$src2,$src2\n\t" @@ -4865,8 +4918,8 @@ instruct rvadd2I_reduction_reg(rRegI dst, rRegI src1, vecD src2, vecD tmp, vecD ins_pipe( pipe_slow ); %} -instruct rvadd2I_reduction_reg_evex(rRegI dst, rRegI src1, vecD src2, vecD tmp, vecD tmp2) %{ - predicate(UseAVX > 2); +instruct rvadd2I_reduction_reg_evex(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 2 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "pshufd $tmp2,$src2,0x1\n\t" @@ -4885,8 +4938,8 @@ instruct rvadd2I_reduction_reg_evex(rRegI dst, rRegI src1, vecD src2, vecD tmp, ins_pipe( pipe_slow ); %} -instruct rsadd4I_reduction_reg(rRegI dst, rRegI src1, vecX src2, vecX tmp, vecX tmp2) %{ - predicate(UseSSE > 2 && UseAVX == 0); +instruct rsadd4I_reduction_reg(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseSSE > 2 && UseAVX == 0 && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "movdqu $tmp,$src2\n\t" @@ -4906,8 +4959,8 @@ instruct rsadd4I_reduction_reg(rRegI dst, rRegI src1, vecX src2, vecX tmp, vecX ins_pipe( pipe_slow ); %} -instruct rvadd4I_reduction_reg(rRegI dst, rRegI src1, vecX src2, vecX tmp, vecX tmp2) %{ - predicate(VM_Version::supports_avxonly()); +instruct rvadd4I_reduction_reg(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 0 && VM_Version::supports_avxonly() && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "vphaddd $tmp,$src2,$src2\n\t" @@ -4926,8 +4979,8 @@ instruct rvadd4I_reduction_reg(rRegI dst, rRegI src1, vecX src2, vecX tmp, vecX ins_pipe( pipe_slow ); %} -instruct rvadd4I_reduction_reg_evex(rRegI dst, rRegI src1, vecX src2, vecX tmp, vecX tmp2) %{ - predicate(UseAVX > 2); +instruct rvadd4I_reduction_reg_evex(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 2 && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "pshufd $tmp2,$src2,0xE\n\t" @@ -4950,8 +5003,8 @@ instruct rvadd4I_reduction_reg_evex(rRegI dst, rRegI src1, vecX src2, vecX tmp, ins_pipe( pipe_slow ); %} -instruct rvadd8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, vecY tmp, vecY tmp2) %{ - predicate(VM_Version::supports_avxonly()); +instruct rvadd8I_reduction_reg(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 0 && VM_Version::supports_avxonly() && n->in(2)->bottom_type()->is_vect()->length() == 8); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "vphaddd $tmp,$src2,$src2\n\t" @@ -4974,8 +5027,8 @@ instruct rvadd8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, vecY tmp, vecY ins_pipe( pipe_slow ); %} -instruct rvadd8I_reduction_reg_evex(rRegI dst, rRegI src1, vecY src2, vecY tmp, vecY tmp2) %{ - predicate(UseAVX > 2); +instruct rvadd8I_reduction_reg_evex(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 2 && n->in(2)->bottom_type()->is_vect()->length() == 8); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "vextracti128_high $tmp,$src2\n\t" @@ -5002,8 +5055,8 @@ instruct rvadd8I_reduction_reg_evex(rRegI dst, rRegI src1, vecY src2, vecY tmp, ins_pipe( pipe_slow ); %} -instruct rvadd16I_reduction_reg_evex(rRegI dst, rRegI src1, legVecZ src2, legVecZ tmp, legVecZ tmp2, legVecZ tmp3) %{ - predicate(UseAVX > 2); +instruct rvadd16I_reduction_reg_evex(rRegI dst, rRegI src1, legVec src2, legVec tmp, legVec tmp2, legVec tmp3) %{ + predicate(UseAVX > 2 && n->in(2)->bottom_type()->is_vect()->length() == 16); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2, TEMP tmp3); format %{ "vextracti64x4_high $tmp3,$src2\n\t" @@ -5034,8 +5087,8 @@ instruct rvadd16I_reduction_reg_evex(rRegI dst, rRegI src1, legVecZ src2, legVec %} #ifdef _LP64 -instruct rvadd2L_reduction_reg(rRegL dst, rRegL src1, vecX src2, vecX tmp, vecX tmp2) %{ - predicate(UseAVX > 2); +instruct rvadd2L_reduction_reg(rRegL dst, rRegL src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 2 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (AddReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "pshufd $tmp2,$src2,0xE\n\t" @@ -5053,8 +5106,8 @@ instruct rvadd2L_reduction_reg(rRegL dst, rRegL src1, vecX src2, vecX tmp, vecX ins_pipe( pipe_slow ); %} -instruct rvadd4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, vecY tmp, vecY tmp2) %{ - predicate(UseAVX > 2); +instruct rvadd4L_reduction_reg(rRegL dst, rRegL src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 2 && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (AddReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "vextracti128_high $tmp,$src2\n\t" @@ -5076,8 +5129,8 @@ instruct rvadd4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, vecY tmp, vecY ins_pipe( pipe_slow ); %} -instruct rvadd8L_reduction_reg(rRegL dst, rRegL src1, legVecZ src2, legVecZ tmp, legVecZ tmp2) %{ - predicate(UseAVX > 2); +instruct rvadd8L_reduction_reg(rRegL dst, rRegL src1, legVec src2, legVec tmp, legVec tmp2) %{ + predicate(UseAVX > 2 && n->in(2)->bottom_type()->is_vect()->length() == 8); match(Set dst (AddReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "vextracti64x4_high $tmp2,$src2\n\t" @@ -5104,8 +5157,8 @@ instruct rvadd8L_reduction_reg(rRegL dst, rRegL src1, legVecZ src2, legVecZ tmp, %} #endif -instruct rsadd2F_reduction_reg(regF dst, vecD src2, vecD tmp) %{ - predicate(UseSSE >= 1 && UseAVX == 0); +instruct rsadd2F_reduction_reg(regF dst, vec src2, vec tmp) %{ + predicate(UseSSE >= 1 && UseAVX == 0 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (AddReductionVF dst src2)); effect(TEMP dst, TEMP tmp); format %{ "addss $dst,$src2\n\t" @@ -5119,8 +5172,8 @@ instruct rsadd2F_reduction_reg(regF dst, vecD src2, vecD tmp) %{ ins_pipe( pipe_slow ); %} -instruct rvadd2F_reduction_reg(regF dst, vecD src2, vecD tmp) %{ - predicate(UseAVX > 0); +instruct rvadd2F_reduction_reg(regF dst, vec src2, vec tmp) %{ + predicate(UseAVX > 0 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (AddReductionVF dst src2)); effect(TEMP dst, TEMP tmp); format %{ "vaddss $dst,$dst,$src2\n\t" @@ -5134,8 +5187,8 @@ instruct rvadd2F_reduction_reg(regF dst, vecD src2, vecD tmp) %{ ins_pipe( pipe_slow ); %} -instruct rsadd4F_reduction_reg(regF dst, vecX src2, vecX tmp) %{ - predicate(UseSSE >= 1 && UseAVX == 0); +instruct rsadd4F_reduction_reg(regF dst, vec src2, vec tmp) %{ + predicate(UseSSE >= 1 && UseAVX == 0 && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (AddReductionVF dst src2)); effect(TEMP dst, TEMP tmp); format %{ "addss $dst,$src2\n\t" @@ -5157,8 +5210,8 @@ instruct rsadd4F_reduction_reg(regF dst, vecX src2, vecX tmp) %{ ins_pipe( pipe_slow ); %} -instruct rvadd4F_reduction_reg(regF dst, vecX src2, vecX tmp) %{ - predicate(UseAVX > 0); +instruct rvadd4F_reduction_reg(regF dst, vec src2, vec tmp) %{ + predicate(UseAVX > 0 && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (AddReductionVF dst src2)); effect(TEMP tmp, TEMP dst); format %{ "vaddss $dst,dst,$src2\n\t" @@ -5180,8 +5233,8 @@ instruct rvadd4F_reduction_reg(regF dst, vecX src2, vecX tmp) %{ ins_pipe( pipe_slow ); %} -instruct radd8F_reduction_reg(regF dst, vecY src2, vecY tmp, vecY tmp2) %{ - predicate(UseAVX > 0); +instruct radd8F_reduction_reg(regF dst, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 0 && n->in(2)->bottom_type()->is_vect()->length() == 8); match(Set dst (AddReductionVF dst src2)); effect(TEMP tmp, TEMP dst, TEMP tmp2); format %{ "vaddss $dst,$dst,$src2\n\t" @@ -5219,8 +5272,8 @@ instruct radd8F_reduction_reg(regF dst, vecY src2, vecY tmp, vecY tmp2) %{ ins_pipe( pipe_slow ); %} -instruct radd16F_reduction_reg(regF dst, legVecZ src2, legVecZ tmp, legVecZ tmp2) %{ - predicate(UseAVX > 2); +instruct radd16F_reduction_reg(regF dst, legVec src2, legVec tmp, legVec tmp2) %{ + predicate(UseAVX > 2 && n->in(2)->bottom_type()->is_vect()->length() == 16); match(Set dst (AddReductionVF dst src2)); effect(TEMP tmp, TEMP dst, TEMP tmp2); format %{ "vaddss $dst,$dst,$src2\n\t" @@ -5290,8 +5343,8 @@ instruct radd16F_reduction_reg(regF dst, legVecZ src2, legVecZ tmp, legVecZ tmp2 ins_pipe( pipe_slow ); %} -instruct rsadd2D_reduction_reg(regD dst, vecX src2, vecX tmp) %{ - predicate(UseSSE >= 1 && UseAVX == 0); +instruct rsadd2D_reduction_reg(regD dst, vec src2, vec tmp) %{ + predicate(UseSSE >= 1 && UseAVX == 0 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (AddReductionVD dst src2)); effect(TEMP tmp, TEMP dst); format %{ "addsd $dst,$src2\n\t" @@ -5305,8 +5358,8 @@ instruct rsadd2D_reduction_reg(regD dst, vecX src2, vecX tmp) %{ ins_pipe( pipe_slow ); %} -instruct rvadd2D_reduction_reg(regD dst, vecX src2, vecX tmp) %{ - predicate(UseAVX > 0); +instruct rvadd2D_reduction_reg(regD dst, vec src2, vec tmp) %{ + predicate(UseAVX > 0 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (AddReductionVD dst src2)); effect(TEMP tmp, TEMP dst); format %{ "vaddsd $dst,$dst,$src2\n\t" @@ -5320,8 +5373,8 @@ instruct rvadd2D_reduction_reg(regD dst, vecX src2, vecX tmp) %{ ins_pipe( pipe_slow ); %} -instruct rvadd4D_reduction_reg(regD dst, vecY src2, vecX tmp, vecX tmp2) %{ - predicate(UseAVX > 0); +instruct rvadd4D_reduction_reg(regD dst, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 0 && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (AddReductionVD dst src2)); effect(TEMP tmp, TEMP dst, TEMP tmp2); format %{ "vaddsd $dst,$dst,$src2\n\t" @@ -5343,8 +5396,8 @@ instruct rvadd4D_reduction_reg(regD dst, vecY src2, vecX tmp, vecX tmp2) %{ ins_pipe( pipe_slow ); %} -instruct rvadd8D_reduction_reg(regD dst, legVecZ src2, legVecZ tmp, legVecZ tmp2) %{ - predicate(UseAVX > 2); +instruct rvadd8D_reduction_reg(regD dst, legVec src2, legVec tmp, legVec tmp2) %{ + predicate(UseAVX > 2 && n->in(2)->bottom_type()->is_vect()->length() == 8); match(Set dst (AddReductionVD dst src2)); effect(TEMP tmp, TEMP dst, TEMP tmp2); format %{ "vaddsd $dst,$dst,$src2\n\t" @@ -5382,8 +5435,8 @@ instruct rvadd8D_reduction_reg(regD dst, legVecZ src2, legVecZ tmp, legVecZ tmp2 ins_pipe( pipe_slow ); %} -instruct rsmul2I_reduction_reg(rRegI dst, rRegI src1, vecD src2, vecD tmp, vecD tmp2) %{ - predicate(UseSSE > 3 && UseAVX == 0); +instruct rsmul2I_reduction_reg(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseSSE > 3 && UseAVX == 0 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (MulReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "pshufd $tmp2,$src2,0x1\n\t" @@ -5401,8 +5454,8 @@ instruct rsmul2I_reduction_reg(rRegI dst, rRegI src1, vecD src2, vecD tmp, vecD ins_pipe( pipe_slow ); %} -instruct rvmul2I_reduction_reg(rRegI dst, rRegI src1, vecD src2, vecD tmp, vecD tmp2) %{ - predicate(UseAVX > 0); +instruct rvmul2I_reduction_reg(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 0 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (MulReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "pshufd $tmp2,$src2,0x1\n\t" @@ -5421,8 +5474,8 @@ instruct rvmul2I_reduction_reg(rRegI dst, rRegI src1, vecD src2, vecD tmp, vecD ins_pipe( pipe_slow ); %} -instruct rsmul4I_reduction_reg(rRegI dst, rRegI src1, vecX src2, vecX tmp, vecX tmp2) %{ - predicate(UseSSE > 3 && UseAVX == 0); +instruct rsmul4I_reduction_reg(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseSSE > 3 && UseAVX == 0 && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (MulReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "pshufd $tmp2,$src2,0xE\n\t" @@ -5444,8 +5497,8 @@ instruct rsmul4I_reduction_reg(rRegI dst, rRegI src1, vecX src2, vecX tmp, vecX ins_pipe( pipe_slow ); %} -instruct rvmul4I_reduction_reg(rRegI dst, rRegI src1, vecX src2, vecX tmp, vecX tmp2) %{ - predicate(UseAVX > 0); +instruct rvmul4I_reduction_reg(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 0 && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (MulReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "pshufd $tmp2,$src2,0xE\n\t" @@ -5468,8 +5521,8 @@ instruct rvmul4I_reduction_reg(rRegI dst, rRegI src1, vecX src2, vecX tmp, vecX ins_pipe( pipe_slow ); %} -instruct rvmul8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, vecY tmp, vecY tmp2) %{ - predicate(UseAVX > 1); +instruct rvmul8I_reduction_reg(rRegI dst, rRegI src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 1 && n->in(2)->bottom_type()->is_vect()->length() == 8); match(Set dst (MulReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "vextracti128_high $tmp,$src2\n\t" @@ -5496,8 +5549,8 @@ instruct rvmul8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, vecY tmp, vecY ins_pipe( pipe_slow ); %} -instruct rvmul16I_reduction_reg(rRegI dst, rRegI src1, legVecZ src2, legVecZ tmp, legVecZ tmp2, legVecZ tmp3) %{ - predicate(UseAVX > 2); +instruct rvmul16I_reduction_reg(rRegI dst, rRegI src1, legVec src2, legVec tmp, legVec tmp2, legVec tmp3) %{ + predicate(UseAVX > 2 && n->in(2)->bottom_type()->is_vect()->length() == 16); match(Set dst (MulReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2, TEMP tmp3); format %{ "vextracti64x4_high $tmp3,$src2\n\t" @@ -5528,8 +5581,8 @@ instruct rvmul16I_reduction_reg(rRegI dst, rRegI src1, legVecZ src2, legVecZ tmp %} #ifdef _LP64 -instruct rvmul2L_reduction_reg(rRegL dst, rRegL src1, vecX src2, vecX tmp, vecX tmp2) %{ - predicate(UseAVX > 2 && VM_Version::supports_avx512dq()); +instruct rvmul2L_reduction_reg(rRegL dst, rRegL src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 2 && VM_Version::supports_avx512dq() && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (MulReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "pshufd $tmp2,$src2,0xE\n\t" @@ -5547,8 +5600,8 @@ instruct rvmul2L_reduction_reg(rRegL dst, rRegL src1, vecX src2, vecX tmp, vecX ins_pipe( pipe_slow ); %} -instruct rvmul4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, vecY tmp, vecY tmp2) %{ - predicate(UseAVX > 2 && VM_Version::supports_avx512dq()); +instruct rvmul4L_reduction_reg(rRegL dst, rRegL src1, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 2 && VM_Version::supports_avx512dq() && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (MulReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "vextracti128_high $tmp,$src2\n\t" @@ -5570,8 +5623,8 @@ instruct rvmul4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, vecY tmp, vecY ins_pipe( pipe_slow ); %} -instruct rvmul8L_reduction_reg(rRegL dst, rRegL src1, legVecZ src2, legVecZ tmp, legVecZ tmp2) %{ - predicate(UseAVX > 2 && VM_Version::supports_avx512dq()); +instruct rvmul8L_reduction_reg(rRegL dst, rRegL src1, legVec src2, legVec tmp, legVec tmp2) %{ + predicate(UseAVX > 2 && VM_Version::supports_avx512dq() && n->in(2)->bottom_type()->is_vect()->length() == 8); match(Set dst (MulReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); format %{ "vextracti64x4_high $tmp2,$src2\n\t" @@ -5598,8 +5651,8 @@ instruct rvmul8L_reduction_reg(rRegL dst, rRegL src1, legVecZ src2, legVecZ tmp, %} #endif -instruct rsmul2F_reduction(regF dst, vecD src2, vecD tmp) %{ - predicate(UseSSE >= 1 && UseAVX == 0); +instruct rsmul2F_reduction(regF dst, vec src2, vec tmp) %{ + predicate(UseSSE >= 1 && UseAVX == 0 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (MulReductionVF dst src2)); effect(TEMP dst, TEMP tmp); format %{ "mulss $dst,$src2\n\t" @@ -5613,8 +5666,8 @@ instruct rsmul2F_reduction(regF dst, vecD src2, vecD tmp) %{ ins_pipe( pipe_slow ); %} -instruct rvmul2F_reduction_reg(regF dst, vecD src2, vecD tmp) %{ - predicate(UseAVX > 0); +instruct rvmul2F_reduction_reg(regF dst, vec src2, vec tmp) %{ + predicate(UseAVX > 0 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (MulReductionVF dst src2)); effect(TEMP tmp, TEMP dst); format %{ "vmulss $dst,$dst,$src2\n\t" @@ -5628,8 +5681,8 @@ instruct rvmul2F_reduction_reg(regF dst, vecD src2, vecD tmp) %{ ins_pipe( pipe_slow ); %} -instruct rsmul4F_reduction_reg(regF dst, vecX src2, vecX tmp) %{ - predicate(UseSSE >= 1 && UseAVX == 0); +instruct rsmul4F_reduction_reg(regF dst, vec src2, vec tmp) %{ + predicate(UseSSE >= 1 && UseAVX == 0 && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (MulReductionVF dst src2)); effect(TEMP dst, TEMP tmp); format %{ "mulss $dst,$src2\n\t" @@ -5651,8 +5704,8 @@ instruct rsmul4F_reduction_reg(regF dst, vecX src2, vecX tmp) %{ ins_pipe( pipe_slow ); %} -instruct rvmul4F_reduction_reg(regF dst, vecX src2, vecX tmp) %{ - predicate(UseAVX > 0); +instruct rvmul4F_reduction_reg(regF dst, vec src2, vec tmp) %{ + predicate(UseAVX > 0 && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (MulReductionVF dst src2)); effect(TEMP tmp, TEMP dst); format %{ "vmulss $dst,$dst,$src2\n\t" @@ -5674,8 +5727,8 @@ instruct rvmul4F_reduction_reg(regF dst, vecX src2, vecX tmp) %{ ins_pipe( pipe_slow ); %} -instruct rvmul8F_reduction_reg(regF dst, vecY src2, vecY tmp, vecY tmp2) %{ - predicate(UseAVX > 0); +instruct rvmul8F_reduction_reg(regF dst, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 0 && n->in(2)->bottom_type()->is_vect()->length() == 8); match(Set dst (MulReductionVF dst src2)); effect(TEMP tmp, TEMP dst, TEMP tmp2); format %{ "vmulss $dst,$dst,$src2\n\t" @@ -5713,8 +5766,8 @@ instruct rvmul8F_reduction_reg(regF dst, vecY src2, vecY tmp, vecY tmp2) %{ ins_pipe( pipe_slow ); %} -instruct rvmul16F_reduction_reg(regF dst, legVecZ src2, legVecZ tmp, legVecZ tmp2) %{ - predicate(UseAVX > 2); +instruct rvmul16F_reduction_reg(regF dst, legVec src2, legVec tmp, legVec tmp2) %{ + predicate(UseAVX > 2 && n->in(2)->bottom_type()->is_vect()->length() == 16); match(Set dst (MulReductionVF dst src2)); effect(TEMP tmp, TEMP dst, TEMP tmp2); format %{ "vmulss $dst,$dst,$src2\n\t" @@ -5784,8 +5837,8 @@ instruct rvmul16F_reduction_reg(regF dst, legVecZ src2, legVecZ tmp, legVecZ tmp ins_pipe( pipe_slow ); %} -instruct rsmul2D_reduction_reg(regD dst, vecX src2, vecX tmp) %{ - predicate(UseSSE >= 1 && UseAVX == 0); +instruct rsmul2D_reduction_reg(regD dst, vec src2, vec tmp) %{ + predicate(UseSSE >= 1 && UseAVX == 0 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (MulReductionVD dst src2)); effect(TEMP dst, TEMP tmp); format %{ "mulsd $dst,$src2\n\t" @@ -5799,8 +5852,8 @@ instruct rsmul2D_reduction_reg(regD dst, vecX src2, vecX tmp) %{ ins_pipe( pipe_slow ); %} -instruct rvmul2D_reduction_reg(regD dst, vecX src2, vecX tmp) %{ - predicate(UseAVX > 0); +instruct rvmul2D_reduction_reg(regD dst, vec src2, vec tmp) %{ + predicate(UseAVX > 0 && n->in(2)->bottom_type()->is_vect()->length() == 2); match(Set dst (MulReductionVD dst src2)); effect(TEMP tmp, TEMP dst); format %{ "vmulsd $dst,$dst,$src2\n\t" @@ -5814,8 +5867,8 @@ instruct rvmul2D_reduction_reg(regD dst, vecX src2, vecX tmp) %{ ins_pipe( pipe_slow ); %} -instruct rvmul4D_reduction_reg(regD dst, vecY src2, vecY tmp, vecY tmp2) %{ - predicate(UseAVX > 0); +instruct rvmul4D_reduction_reg(regD dst, vec src2, vec tmp, vec tmp2) %{ + predicate(UseAVX > 0 && n->in(2)->bottom_type()->is_vect()->length() == 4); match(Set dst (MulReductionVD dst src2)); effect(TEMP tmp, TEMP dst, TEMP tmp2); format %{ "vmulsd $dst,$dst,$src2\n\t" @@ -5837,8 +5890,8 @@ instruct rvmul4D_reduction_reg(regD dst, vecY src2, vecY tmp, vecY tmp2) %{ ins_pipe( pipe_slow ); %} -instruct rvmul8D_reduction_reg(regD dst, legVecZ src2, legVecZ tmp, legVecZ tmp2) %{ - predicate(UseAVX > 2); +instruct rvmul8D_reduction_reg(regD dst, legVec src2, legVec tmp, legVec tmp2) %{ + predicate(UseAVX > 2 && n->in(2)->bottom_type()->is_vect()->length() == 8); match(Set dst (MulReductionVD dst src2)); effect(TEMP tmp, TEMP dst, TEMP tmp2); format %{ "vmulsd $dst,$dst,$src2\n\t" @@ -5881,7 +5934,7 @@ instruct rvmul8D_reduction_reg(regD dst, legVecZ src2, legVecZ tmp, legVecZ tmp2 // --------------------------------- ADD -------------------------------------- // Bytes vector add -instruct vadd4B(vecS dst, vecS src) %{ +instruct vadd4B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 4); match(Set dst (AddVB dst src)); format %{ "paddb $dst,$src\t! add packed4B" %} @@ -5891,7 +5944,7 @@ instruct vadd4B(vecS dst, vecS src) %{ ins_pipe( pipe_slow ); %} -instruct vadd4B_reg(vecS dst, vecS src1, vecS src2) %{ +instruct vadd4B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (AddVB src1 src2)); format %{ "vpaddb $dst,$src1,$src2\t! add packed4B" %} @@ -5903,7 +5956,7 @@ instruct vadd4B_reg(vecS dst, vecS src1, vecS src2) %{ %} -instruct vadd4B_mem(vecS dst, vecS src, memory mem) %{ +instruct vadd4B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (AddVB src (LoadVector mem))); format %{ "vpaddb $dst,$src,$mem\t! add packed4B" %} @@ -5914,7 +5967,7 @@ instruct vadd4B_mem(vecS dst, vecS src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd8B(vecD dst, vecD src) %{ +instruct vadd8B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 8); match(Set dst (AddVB dst src)); format %{ "paddb $dst,$src\t! add packed8B" %} @@ -5924,7 +5977,7 @@ instruct vadd8B(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vadd8B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (AddVB src1 src2)); format %{ "vpaddb $dst,$src1,$src2\t! add packed8B" %} @@ -5936,7 +5989,7 @@ instruct vadd8B_reg(vecD dst, vecD src1, vecD src2) %{ %} -instruct vadd8B_mem(vecD dst, vecD src, memory mem) %{ +instruct vadd8B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (AddVB src (LoadVector mem))); format %{ "vpaddb $dst,$src,$mem\t! add packed8B" %} @@ -5947,7 +6000,7 @@ instruct vadd8B_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd16B(vecX dst, vecX src) %{ +instruct vadd16B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 16); match(Set dst (AddVB dst src)); format %{ "paddb $dst,$src\t! add packed16B" %} @@ -5957,7 +6010,7 @@ instruct vadd16B(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vadd16B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 16); match(Set dst (AddVB src1 src2)); format %{ "vpaddb $dst,$src1,$src2\t! add packed16B" %} @@ -5968,7 +6021,7 @@ instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd16B_mem(vecX dst, vecX src, memory mem) %{ +instruct vadd16B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 16); match(Set dst (AddVB src (LoadVector mem))); format %{ "vpaddb $dst,$src,$mem\t! add packed16B" %} @@ -5979,7 +6032,7 @@ instruct vadd16B_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd32B_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vadd32B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 32); match(Set dst (AddVB src1 src2)); format %{ "vpaddb $dst,$src1,$src2\t! add packed32B" %} @@ -5990,7 +6043,7 @@ instruct vadd32B_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd32B_mem(vecY dst, vecY src, memory mem) %{ +instruct vadd32B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 32); match(Set dst (AddVB src (LoadVector mem))); format %{ "vpaddb $dst,$src,$mem\t! add packed32B" %} @@ -6001,7 +6054,7 @@ instruct vadd32B_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd64B_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vadd64B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 64); match(Set dst (AddVB src1 src2)); format %{ "vpaddb $dst,$src1,$src2\t! add packed64B" %} @@ -6012,7 +6065,7 @@ instruct vadd64B_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd64B_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vadd64B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 64); match(Set dst (AddVB src (LoadVector mem))); format %{ "vpaddb $dst,$src,$mem\t! add packed64B" %} @@ -6024,7 +6077,7 @@ instruct vadd64B_mem(vecZ dst, vecZ src, memory mem) %{ %} // Shorts/Chars vector add -instruct vadd2S(vecS dst, vecS src) %{ +instruct vadd2S(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (AddVS dst src)); format %{ "paddw $dst,$src\t! add packed2S" %} @@ -6034,7 +6087,7 @@ instruct vadd2S(vecS dst, vecS src) %{ ins_pipe( pipe_slow ); %} -instruct vadd2S_reg(vecS dst, vecS src1, vecS src2) %{ +instruct vadd2S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (AddVS src1 src2)); format %{ "vpaddw $dst,$src1,$src2\t! add packed2S" %} @@ -6045,7 +6098,7 @@ instruct vadd2S_reg(vecS dst, vecS src1, vecS src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd2S_mem(vecS dst, vecS src, memory mem) %{ +instruct vadd2S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (AddVS src (LoadVector mem))); format %{ "vpaddw $dst,$src,$mem\t! add packed2S" %} @@ -6056,7 +6109,7 @@ instruct vadd2S_mem(vecS dst, vecS src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd4S(vecD dst, vecD src) %{ +instruct vadd4S(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 4); match(Set dst (AddVS dst src)); format %{ "paddw $dst,$src\t! add packed4S" %} @@ -6066,7 +6119,7 @@ instruct vadd4S(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vadd4S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (AddVS src1 src2)); format %{ "vpaddw $dst,$src1,$src2\t! add packed4S" %} @@ -6077,7 +6130,7 @@ instruct vadd4S_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd4S_mem(vecD dst, vecD src, memory mem) %{ +instruct vadd4S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (AddVS src (LoadVector mem))); format %{ "vpaddw $dst,$src,$mem\t! add packed4S" %} @@ -6088,7 +6141,7 @@ instruct vadd4S_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd8S(vecX dst, vecX src) %{ +instruct vadd8S(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 8); match(Set dst (AddVS dst src)); format %{ "paddw $dst,$src\t! add packed8S" %} @@ -6098,7 +6151,7 @@ instruct vadd8S(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vadd8S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (AddVS src1 src2)); format %{ "vpaddw $dst,$src1,$src2\t! add packed8S" %} @@ -6109,7 +6162,7 @@ instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd8S_mem(vecX dst, vecX src, memory mem) %{ +instruct vadd8S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (AddVS src (LoadVector mem))); format %{ "vpaddw $dst,$src,$mem\t! add packed8S" %} @@ -6120,7 +6173,7 @@ instruct vadd8S_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd16S_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vadd16S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 16); match(Set dst (AddVS src1 src2)); format %{ "vpaddw $dst,$src1,$src2\t! add packed16S" %} @@ -6131,7 +6184,7 @@ instruct vadd16S_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd16S_mem(vecY dst, vecY src, memory mem) %{ +instruct vadd16S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 16); match(Set dst (AddVS src (LoadVector mem))); format %{ "vpaddw $dst,$src,$mem\t! add packed16S" %} @@ -6142,7 +6195,7 @@ instruct vadd16S_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd32S_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vadd32S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); match(Set dst (AddVS src1 src2)); format %{ "vpaddw $dst,$src1,$src2\t! add packed32S" %} @@ -6153,7 +6206,7 @@ instruct vadd32S_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd32S_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vadd32S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); match(Set dst (AddVS src (LoadVector mem))); format %{ "vpaddw $dst,$src,$mem\t! add packed32S" %} @@ -6165,7 +6218,7 @@ instruct vadd32S_mem(vecZ dst, vecZ src, memory mem) %{ %} // Integers vector add -instruct vadd2I(vecD dst, vecD src) %{ +instruct vadd2I(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (AddVI dst src)); format %{ "paddd $dst,$src\t! add packed2I" %} @@ -6175,7 +6228,7 @@ instruct vadd2I(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vadd2I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (AddVI src1 src2)); format %{ "vpaddd $dst,$src1,$src2\t! add packed2I" %} @@ -6186,7 +6239,7 @@ instruct vadd2I_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd2I_mem(vecD dst, vecD src, memory mem) %{ +instruct vadd2I_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (AddVI src (LoadVector mem))); format %{ "vpaddd $dst,$src,$mem\t! add packed2I" %} @@ -6197,7 +6250,7 @@ instruct vadd2I_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd4I(vecX dst, vecX src) %{ +instruct vadd4I(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 4); match(Set dst (AddVI dst src)); format %{ "paddd $dst,$src\t! add packed4I" %} @@ -6207,7 +6260,7 @@ instruct vadd4I(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vadd4I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (AddVI src1 src2)); format %{ "vpaddd $dst,$src1,$src2\t! add packed4I" %} @@ -6218,7 +6271,7 @@ instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd4I_mem(vecX dst, vecX src, memory mem) %{ +instruct vadd4I_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (AddVI src (LoadVector mem))); format %{ "vpaddd $dst,$src,$mem\t! add packed4I" %} @@ -6229,7 +6282,7 @@ instruct vadd4I_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd8I_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vadd8I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 8); match(Set dst (AddVI src1 src2)); format %{ "vpaddd $dst,$src1,$src2\t! add packed8I" %} @@ -6240,7 +6293,7 @@ instruct vadd8I_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd8I_mem(vecY dst, vecY src, memory mem) %{ +instruct vadd8I_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 8); match(Set dst (AddVI src (LoadVector mem))); format %{ "vpaddd $dst,$src,$mem\t! add packed8I" %} @@ -6251,7 +6304,7 @@ instruct vadd8I_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd16I_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vadd16I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (AddVI src1 src2)); format %{ "vpaddd $dst,$src1,$src2\t! add packed16I" %} @@ -6262,7 +6315,7 @@ instruct vadd16I_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd16I_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vadd16I_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (AddVI src (LoadVector mem))); format %{ "vpaddd $dst,$src,$mem\t! add packed16I" %} @@ -6274,7 +6327,7 @@ instruct vadd16I_mem(vecZ dst, vecZ src, memory mem) %{ %} // Longs vector add -instruct vadd2L(vecX dst, vecX src) %{ +instruct vadd2L(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (AddVL dst src)); format %{ "paddq $dst,$src\t! add packed2L" %} @@ -6284,7 +6337,7 @@ instruct vadd2L(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vadd2L_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (AddVL src1 src2)); format %{ "vpaddq $dst,$src1,$src2\t! add packed2L" %} @@ -6295,7 +6348,7 @@ instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd2L_mem(vecX dst, vecX src, memory mem) %{ +instruct vadd2L_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (AddVL src (LoadVector mem))); format %{ "vpaddq $dst,$src,$mem\t! add packed2L" %} @@ -6306,7 +6359,7 @@ instruct vadd2L_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd4L_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vadd4L_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 4); match(Set dst (AddVL src1 src2)); format %{ "vpaddq $dst,$src1,$src2\t! add packed4L" %} @@ -6317,7 +6370,7 @@ instruct vadd4L_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd4L_mem(vecY dst, vecY src, memory mem) %{ +instruct vadd4L_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 4); match(Set dst (AddVL src (LoadVector mem))); format %{ "vpaddq $dst,$src,$mem\t! add packed4L" %} @@ -6328,7 +6381,7 @@ instruct vadd4L_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd8L_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vadd8L_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (AddVL src1 src2)); format %{ "vpaddq $dst,$src1,$src2\t! add packed8L" %} @@ -6339,7 +6392,7 @@ instruct vadd8L_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd8L_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vadd8L_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (AddVL src (LoadVector mem))); format %{ "vpaddq $dst,$src,$mem\t! add packed8L" %} @@ -6351,7 +6404,7 @@ instruct vadd8L_mem(vecZ dst, vecZ src, memory mem) %{ %} // Floats vector add -instruct vadd2F(vecD dst, vecD src) %{ +instruct vadd2F(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (AddVF dst src)); format %{ "addps $dst,$src\t! add packed2F" %} @@ -6361,7 +6414,7 @@ instruct vadd2F(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vadd2F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (AddVF src1 src2)); format %{ "vaddps $dst,$src1,$src2\t! add packed2F" %} @@ -6372,7 +6425,7 @@ instruct vadd2F_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd2F_mem(vecD dst, vecD src, memory mem) %{ +instruct vadd2F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (AddVF src (LoadVector mem))); format %{ "vaddps $dst,$src,$mem\t! add packed2F" %} @@ -6383,7 +6436,7 @@ instruct vadd2F_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd4F(vecX dst, vecX src) %{ +instruct vadd4F(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 4); match(Set dst (AddVF dst src)); format %{ "addps $dst,$src\t! add packed4F" %} @@ -6393,7 +6446,7 @@ instruct vadd4F(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vadd4F_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vadd4F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (AddVF src1 src2)); format %{ "vaddps $dst,$src1,$src2\t! add packed4F" %} @@ -6404,7 +6457,7 @@ instruct vadd4F_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd4F_mem(vecX dst, vecX src, memory mem) %{ +instruct vadd4F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (AddVF src (LoadVector mem))); format %{ "vaddps $dst,$src,$mem\t! add packed4F" %} @@ -6415,7 +6468,7 @@ instruct vadd4F_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd8F_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vadd8F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (AddVF src1 src2)); format %{ "vaddps $dst,$src1,$src2\t! add packed8F" %} @@ -6426,7 +6479,7 @@ instruct vadd8F_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd8F_mem(vecY dst, vecY src, memory mem) %{ +instruct vadd8F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (AddVF src (LoadVector mem))); format %{ "vaddps $dst,$src,$mem\t! add packed8F" %} @@ -6437,7 +6490,7 @@ instruct vadd8F_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd16F_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vadd16F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (AddVF src1 src2)); format %{ "vaddps $dst,$src1,$src2\t! add packed16F" %} @@ -6448,7 +6501,7 @@ instruct vadd16F_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd16F_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vadd16F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (AddVF src (LoadVector mem))); format %{ "vaddps $dst,$src,$mem\t! add packed16F" %} @@ -6460,7 +6513,7 @@ instruct vadd16F_mem(vecZ dst, vecZ src, memory mem) %{ %} // Doubles vector add -instruct vadd2D(vecX dst, vecX src) %{ +instruct vadd2D(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (AddVD dst src)); format %{ "addpd $dst,$src\t! add packed2D" %} @@ -6470,7 +6523,7 @@ instruct vadd2D(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vadd2D_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vadd2D_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (AddVD src1 src2)); format %{ "vaddpd $dst,$src1,$src2\t! add packed2D" %} @@ -6481,7 +6534,7 @@ instruct vadd2D_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd2D_mem(vecX dst, vecX src, memory mem) %{ +instruct vadd2D_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (AddVD src (LoadVector mem))); format %{ "vaddpd $dst,$src,$mem\t! add packed2D" %} @@ -6492,7 +6545,7 @@ instruct vadd2D_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd4D_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vadd4D_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (AddVD src1 src2)); format %{ "vaddpd $dst,$src1,$src2\t! add packed4D" %} @@ -6503,7 +6556,7 @@ instruct vadd4D_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd4D_mem(vecY dst, vecY src, memory mem) %{ +instruct vadd4D_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (AddVD src (LoadVector mem))); format %{ "vaddpd $dst,$src,$mem\t! add packed4D" %} @@ -6514,7 +6567,7 @@ instruct vadd4D_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vadd8D_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vadd8D_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (AddVD src1 src2)); format %{ "vaddpd $dst,$src1,$src2\t! add packed8D" %} @@ -6525,7 +6578,7 @@ instruct vadd8D_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vadd8D_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vadd8D_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (AddVD src (LoadVector mem))); format %{ "vaddpd $dst,$src,$mem\t! add packed8D" %} @@ -6539,7 +6592,7 @@ instruct vadd8D_mem(vecZ dst, vecZ src, memory mem) %{ // --------------------------------- SUB -------------------------------------- // Bytes vector sub -instruct vsub4B(vecS dst, vecS src) %{ +instruct vsub4B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 4); match(Set dst (SubVB dst src)); format %{ "psubb $dst,$src\t! sub packed4B" %} @@ -6549,7 +6602,7 @@ instruct vsub4B(vecS dst, vecS src) %{ ins_pipe( pipe_slow ); %} -instruct vsub4B_reg(vecS dst, vecS src1, vecS src2) %{ +instruct vsub4B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SubVB src1 src2)); format %{ "vpsubb $dst,$src1,$src2\t! sub packed4B" %} @@ -6560,7 +6613,7 @@ instruct vsub4B_reg(vecS dst, vecS src1, vecS src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub4B_mem(vecS dst, vecS src, memory mem) %{ +instruct vsub4B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SubVB src (LoadVector mem))); format %{ "vpsubb $dst,$src,$mem\t! sub packed4B" %} @@ -6571,7 +6624,7 @@ instruct vsub4B_mem(vecS dst, vecS src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub8B(vecD dst, vecD src) %{ +instruct vsub8B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 8); match(Set dst (SubVB dst src)); format %{ "psubb $dst,$src\t! sub packed8B" %} @@ -6581,7 +6634,7 @@ instruct vsub8B(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vsub8B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (SubVB src1 src2)); format %{ "vpsubb $dst,$src1,$src2\t! sub packed8B" %} @@ -6592,7 +6645,7 @@ instruct vsub8B_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub8B_mem(vecD dst, vecD src, memory mem) %{ +instruct vsub8B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (SubVB src (LoadVector mem))); format %{ "vpsubb $dst,$src,$mem\t! sub packed8B" %} @@ -6603,7 +6656,7 @@ instruct vsub8B_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub16B(vecX dst, vecX src) %{ +instruct vsub16B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 16); match(Set dst (SubVB dst src)); format %{ "psubb $dst,$src\t! sub packed16B" %} @@ -6613,7 +6666,7 @@ instruct vsub16B(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vsub16B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 16); match(Set dst (SubVB src1 src2)); format %{ "vpsubb $dst,$src1,$src2\t! sub packed16B" %} @@ -6624,7 +6677,7 @@ instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub16B_mem(vecX dst, vecX src, memory mem) %{ +instruct vsub16B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 16); match(Set dst (SubVB src (LoadVector mem))); format %{ "vpsubb $dst,$src,$mem\t! sub packed16B" %} @@ -6635,7 +6688,7 @@ instruct vsub16B_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub32B_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vsub32B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 32); match(Set dst (SubVB src1 src2)); format %{ "vpsubb $dst,$src1,$src2\t! sub packed32B" %} @@ -6646,7 +6699,7 @@ instruct vsub32B_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub32B_mem(vecY dst, vecY src, memory mem) %{ +instruct vsub32B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 32); match(Set dst (SubVB src (LoadVector mem))); format %{ "vpsubb $dst,$src,$mem\t! sub packed32B" %} @@ -6657,7 +6710,7 @@ instruct vsub32B_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub64B_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vsub64B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 64); match(Set dst (SubVB src1 src2)); format %{ "vpsubb $dst,$src1,$src2\t! sub packed64B" %} @@ -6668,7 +6721,7 @@ instruct vsub64B_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub64B_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vsub64B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 64); match(Set dst (SubVB src (LoadVector mem))); format %{ "vpsubb $dst,$src,$mem\t! sub packed64B" %} @@ -6680,7 +6733,7 @@ instruct vsub64B_mem(vecZ dst, vecZ src, memory mem) %{ %} // Shorts/Chars vector sub -instruct vsub2S(vecS dst, vecS src) %{ +instruct vsub2S(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (SubVS dst src)); format %{ "psubw $dst,$src\t! sub packed2S" %} @@ -6690,7 +6743,7 @@ instruct vsub2S(vecS dst, vecS src) %{ ins_pipe( pipe_slow ); %} -instruct vsub2S_reg(vecS dst, vecS src1, vecS src2) %{ +instruct vsub2S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SubVS src1 src2)); format %{ "vpsubw $dst,$src1,$src2\t! sub packed2S" %} @@ -6701,7 +6754,7 @@ instruct vsub2S_reg(vecS dst, vecS src1, vecS src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub2S_mem(vecS dst, vecS src, memory mem) %{ +instruct vsub2S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SubVS src (LoadVector mem))); format %{ "vpsubw $dst,$src,$mem\t! sub packed2S" %} @@ -6712,7 +6765,7 @@ instruct vsub2S_mem(vecS dst, vecS src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub4S(vecD dst, vecD src) %{ +instruct vsub4S(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 4); match(Set dst (SubVS dst src)); format %{ "psubw $dst,$src\t! sub packed4S" %} @@ -6722,7 +6775,7 @@ instruct vsub4S(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vsub4S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SubVS src1 src2)); format %{ "vpsubw $dst,$src1,$src2\t! sub packed4S" %} @@ -6733,7 +6786,7 @@ instruct vsub4S_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub4S_mem(vecD dst, vecD src, memory mem) %{ +instruct vsub4S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SubVS src (LoadVector mem))); format %{ "vpsubw $dst,$src,$mem\t! sub packed4S" %} @@ -6744,7 +6797,7 @@ instruct vsub4S_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub8S(vecX dst, vecX src) %{ +instruct vsub8S(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 8); match(Set dst (SubVS dst src)); format %{ "psubw $dst,$src\t! sub packed8S" %} @@ -6754,7 +6807,7 @@ instruct vsub8S(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vsub8S_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vsub8S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (SubVS src1 src2)); format %{ "vpsubw $dst,$src1,$src2\t! sub packed8S" %} @@ -6765,7 +6818,7 @@ instruct vsub8S_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub8S_mem(vecX dst, vecX src, memory mem) %{ +instruct vsub8S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (SubVS src (LoadVector mem))); format %{ "vpsubw $dst,$src,$mem\t! sub packed8S" %} @@ -6776,7 +6829,7 @@ instruct vsub8S_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub16S_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vsub16S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 16); match(Set dst (SubVS src1 src2)); format %{ "vpsubw $dst,$src1,$src2\t! sub packed16S" %} @@ -6787,7 +6840,7 @@ instruct vsub16S_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub16S_mem(vecY dst, vecY src, memory mem) %{ +instruct vsub16S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 16); match(Set dst (SubVS src (LoadVector mem))); format %{ "vpsubw $dst,$src,$mem\t! sub packed16S" %} @@ -6798,7 +6851,7 @@ instruct vsub16S_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub32S_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vsub32S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); match(Set dst (SubVS src1 src2)); format %{ "vpsubw $dst,$src1,$src2\t! sub packed32S" %} @@ -6809,7 +6862,7 @@ instruct vsub32S_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub32S_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vsub32S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); match(Set dst (SubVS src (LoadVector mem))); format %{ "vpsubw $dst,$src,$mem\t! sub packed32S" %} @@ -6821,7 +6874,7 @@ instruct vsub32S_mem(vecZ dst, vecZ src, memory mem) %{ %} // Integers vector sub -instruct vsub2I(vecD dst, vecD src) %{ +instruct vsub2I(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (SubVI dst src)); format %{ "psubd $dst,$src\t! sub packed2I" %} @@ -6831,7 +6884,7 @@ instruct vsub2I(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vsub2I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SubVI src1 src2)); format %{ "vpsubd $dst,$src1,$src2\t! sub packed2I" %} @@ -6842,7 +6895,7 @@ instruct vsub2I_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub2I_mem(vecD dst, vecD src, memory mem) %{ +instruct vsub2I_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SubVI src (LoadVector mem))); format %{ "vpsubd $dst,$src,$mem\t! sub packed2I" %} @@ -6853,7 +6906,7 @@ instruct vsub2I_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub4I(vecX dst, vecX src) %{ +instruct vsub4I(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 4); match(Set dst (SubVI dst src)); format %{ "psubd $dst,$src\t! sub packed4I" %} @@ -6863,7 +6916,7 @@ instruct vsub4I(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vsub4I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SubVI src1 src2)); format %{ "vpsubd $dst,$src1,$src2\t! sub packed4I" %} @@ -6874,7 +6927,7 @@ instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub4I_mem(vecX dst, vecX src, memory mem) %{ +instruct vsub4I_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SubVI src (LoadVector mem))); format %{ "vpsubd $dst,$src,$mem\t! sub packed4I" %} @@ -6885,7 +6938,7 @@ instruct vsub4I_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub8I_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vsub8I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 8); match(Set dst (SubVI src1 src2)); format %{ "vpsubd $dst,$src1,$src2\t! sub packed8I" %} @@ -6896,7 +6949,7 @@ instruct vsub8I_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub8I_mem(vecY dst, vecY src, memory mem) %{ +instruct vsub8I_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 8); match(Set dst (SubVI src (LoadVector mem))); format %{ "vpsubd $dst,$src,$mem\t! sub packed8I" %} @@ -6907,7 +6960,7 @@ instruct vsub8I_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub16I_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vsub16I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (SubVI src1 src2)); format %{ "vpsubd $dst,$src1,$src2\t! sub packed16I" %} @@ -6918,7 +6971,7 @@ instruct vsub16I_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub16I_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vsub16I_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (SubVI src (LoadVector mem))); format %{ "vpsubd $dst,$src,$mem\t! sub packed16I" %} @@ -6930,7 +6983,7 @@ instruct vsub16I_mem(vecZ dst, vecZ src, memory mem) %{ %} // Longs vector sub -instruct vsub2L(vecX dst, vecX src) %{ +instruct vsub2L(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (SubVL dst src)); format %{ "psubq $dst,$src\t! sub packed2L" %} @@ -6940,7 +6993,7 @@ instruct vsub2L(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vsub2L_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SubVL src1 src2)); format %{ "vpsubq $dst,$src1,$src2\t! sub packed2L" %} @@ -6951,7 +7004,7 @@ instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub2L_mem(vecX dst, vecX src, memory mem) %{ +instruct vsub2L_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SubVL src (LoadVector mem))); format %{ "vpsubq $dst,$src,$mem\t! sub packed2L" %} @@ -6962,7 +7015,7 @@ instruct vsub2L_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub4L_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vsub4L_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 4); match(Set dst (SubVL src1 src2)); format %{ "vpsubq $dst,$src1,$src2\t! sub packed4L" %} @@ -6973,7 +7026,7 @@ instruct vsub4L_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub4L_mem(vecY dst, vecY src, memory mem) %{ +instruct vsub4L_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 4); match(Set dst (SubVL src (LoadVector mem))); format %{ "vpsubq $dst,$src,$mem\t! sub packed4L" %} @@ -6984,7 +7037,7 @@ instruct vsub4L_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub8L_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vsub8L_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (SubVL src1 src2)); format %{ "vpsubq $dst,$src1,$src2\t! sub packed8L" %} @@ -6995,7 +7048,7 @@ instruct vsub8L_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub8L_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vsub8L_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (SubVL src (LoadVector mem))); format %{ "vpsubq $dst,$src,$mem\t! sub packed8L" %} @@ -7007,7 +7060,7 @@ instruct vsub8L_mem(vecZ dst, vecZ src, memory mem) %{ %} // Floats vector sub -instruct vsub2F(vecD dst, vecD src) %{ +instruct vsub2F(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (SubVF dst src)); format %{ "subps $dst,$src\t! sub packed2F" %} @@ -7017,7 +7070,7 @@ instruct vsub2F(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vsub2F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SubVF src1 src2)); format %{ "vsubps $dst,$src1,$src2\t! sub packed2F" %} @@ -7028,7 +7081,7 @@ instruct vsub2F_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub2F_mem(vecD dst, vecD src, memory mem) %{ +instruct vsub2F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SubVF src (LoadVector mem))); format %{ "vsubps $dst,$src,$mem\t! sub packed2F" %} @@ -7039,7 +7092,7 @@ instruct vsub2F_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub4F(vecX dst, vecX src) %{ +instruct vsub4F(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 4); match(Set dst (SubVF dst src)); format %{ "subps $dst,$src\t! sub packed4F" %} @@ -7049,7 +7102,7 @@ instruct vsub4F(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vsub4F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SubVF src1 src2)); format %{ "vsubps $dst,$src1,$src2\t! sub packed4F" %} @@ -7060,7 +7113,7 @@ instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub4F_mem(vecX dst, vecX src, memory mem) %{ +instruct vsub4F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SubVF src (LoadVector mem))); format %{ "vsubps $dst,$src,$mem\t! sub packed4F" %} @@ -7071,7 +7124,7 @@ instruct vsub4F_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub8F_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vsub8F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (SubVF src1 src2)); format %{ "vsubps $dst,$src1,$src2\t! sub packed8F" %} @@ -7082,7 +7135,7 @@ instruct vsub8F_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub8F_mem(vecY dst, vecY src, memory mem) %{ +instruct vsub8F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (SubVF src (LoadVector mem))); format %{ "vsubps $dst,$src,$mem\t! sub packed8F" %} @@ -7093,7 +7146,7 @@ instruct vsub8F_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub16F_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vsub16F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (SubVF src1 src2)); format %{ "vsubps $dst,$src1,$src2\t! sub packed16F" %} @@ -7104,7 +7157,7 @@ instruct vsub16F_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub16F_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vsub16F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (SubVF src (LoadVector mem))); format %{ "vsubps $dst,$src,$mem\t! sub packed16F" %} @@ -7116,7 +7169,7 @@ instruct vsub16F_mem(vecZ dst, vecZ src, memory mem) %{ %} // Doubles vector sub -instruct vsub2D(vecX dst, vecX src) %{ +instruct vsub2D(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (SubVD dst src)); format %{ "subpd $dst,$src\t! sub packed2D" %} @@ -7126,7 +7179,7 @@ instruct vsub2D(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vsub2D_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vsub2D_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SubVD src1 src2)); format %{ "vsubpd $dst,$src1,$src2\t! sub packed2D" %} @@ -7137,7 +7190,7 @@ instruct vsub2D_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub2D_mem(vecX dst, vecX src, memory mem) %{ +instruct vsub2D_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SubVD src (LoadVector mem))); format %{ "vsubpd $dst,$src,$mem\t! sub packed2D" %} @@ -7148,7 +7201,7 @@ instruct vsub2D_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub4D_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vsub4D_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SubVD src1 src2)); format %{ "vsubpd $dst,$src1,$src2\t! sub packed4D" %} @@ -7159,7 +7212,7 @@ instruct vsub4D_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub4D_mem(vecY dst, vecY src, memory mem) %{ +instruct vsub4D_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SubVD src (LoadVector mem))); format %{ "vsubpd $dst,$src,$mem\t! sub packed4D" %} @@ -7170,7 +7223,7 @@ instruct vsub4D_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsub8D_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vsub8D_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (SubVD src1 src2)); format %{ "vsubpd $dst,$src1,$src2\t! sub packed8D" %} @@ -7181,7 +7234,7 @@ instruct vsub8D_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vsub8D_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vsub8D_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (SubVD src (LoadVector mem))); format %{ "vsubpd $dst,$src,$mem\t! sub packed8D" %} @@ -7195,7 +7248,7 @@ instruct vsub8D_mem(vecZ dst, vecZ src, memory mem) %{ // --------------------------------- MUL -------------------------------------- // Byte vector mul -instruct mul4B_reg(vecS dst, vecS src1, vecS src2, vecS tmp, rRegI scratch) %{ +instruct mul4B_reg(vec dst, vec src1, vec src2, vec tmp, rRegI scratch) %{ predicate(UseSSE > 3 && n->as_Vector()->length() == 4); match(Set dst (MulVB src1 src2)); effect(TEMP dst, TEMP tmp, TEMP scratch); @@ -7216,7 +7269,7 @@ instruct mul4B_reg(vecS dst, vecS src1, vecS src2, vecS tmp, rRegI scratch) %{ ins_pipe( pipe_slow ); %} -instruct mul8B_reg(vecD dst, vecD src1, vecD src2, vecD tmp, rRegI scratch) %{ +instruct mul8B_reg(vec dst, vec src1, vec src2, vec tmp, rRegI scratch) %{ predicate(UseSSE > 3 && n->as_Vector()->length() == 8); match(Set dst (MulVB src1 src2)); effect(TEMP dst, TEMP tmp, TEMP scratch); @@ -7237,7 +7290,7 @@ instruct mul8B_reg(vecD dst, vecD src1, vecD src2, vecD tmp, rRegI scratch) %{ ins_pipe( pipe_slow ); %} -instruct mul16B_reg(vecX dst, vecX src1, vecX src2, vecX tmp1, vecX tmp2, rRegI scratch) %{ +instruct mul16B_reg(vec dst, vec src1, vec src2, vec tmp1, vec tmp2, rRegI scratch) %{ predicate(UseSSE > 3 && n->as_Vector()->length() == 16); match(Set dst (MulVB src1 src2)); effect(TEMP dst, TEMP tmp1, TEMP tmp2, TEMP scratch); @@ -7270,7 +7323,7 @@ instruct mul16B_reg(vecX dst, vecX src1, vecX src2, vecX tmp1, vecX tmp2, rRegI ins_pipe( pipe_slow ); %} -instruct vmul16B_reg_avx(vecX dst, vecX src1, vecX src2, vecX tmp, rRegI scratch) %{ +instruct vmul16B_reg_avx(vec dst, vec src1, vec src2, vec tmp, rRegI scratch) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 16); match(Set dst (MulVB src1 src2)); effect(TEMP dst, TEMP tmp, TEMP scratch); @@ -7294,7 +7347,7 @@ instruct vmul16B_reg_avx(vecX dst, vecX src1, vecX src2, vecX tmp, rRegI scratch ins_pipe( pipe_slow ); %} -instruct vmul32B_reg_avx(vecY dst, vecY src1, vecY src2, vecY tmp1, vecY tmp2, rRegI scratch) %{ +instruct vmul32B_reg_avx(vec dst, vec src1, vec src2, vec tmp1, vec tmp2, rRegI scratch) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 32); match(Set dst (MulVB src1 src2)); effect(TEMP dst, TEMP tmp1, TEMP tmp2, TEMP scratch); @@ -7332,7 +7385,7 @@ instruct vmul32B_reg_avx(vecY dst, vecY src1, vecY src2, vecY tmp1, vecY tmp2, r ins_pipe( pipe_slow ); %} -instruct vmul64B_reg_avx(vecZ dst, vecZ src1, vecZ src2, vecZ tmp1, vecZ tmp2, rRegI scratch) %{ +instruct vmul64B_reg_avx(vec dst, vec src1, vec src2, vec tmp1, vec tmp2, rRegI scratch) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 64); match(Set dst (MulVB src1 src2)); effect(TEMP dst, TEMP tmp1, TEMP tmp2, TEMP scratch); @@ -7375,7 +7428,7 @@ instruct vmul64B_reg_avx(vecZ dst, vecZ src1, vecZ src2, vecZ tmp1, vecZ tmp2, r %} // Shorts/Chars vector mul -instruct vmul2S(vecS dst, vecS src) %{ +instruct vmul2S(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (MulVS dst src)); format %{ "pmullw $dst,$src\t! mul packed2S" %} @@ -7385,7 +7438,7 @@ instruct vmul2S(vecS dst, vecS src) %{ ins_pipe( pipe_slow ); %} -instruct vmul2S_reg(vecS dst, vecS src1, vecS src2) %{ +instruct vmul2S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (MulVS src1 src2)); format %{ "vpmullw $dst,$src1,$src2\t! mul packed2S" %} @@ -7396,7 +7449,7 @@ instruct vmul2S_reg(vecS dst, vecS src1, vecS src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul2S_mem(vecS dst, vecS src, memory mem) %{ +instruct vmul2S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (MulVS src (LoadVector mem))); format %{ "vpmullw $dst,$src,$mem\t! mul packed2S" %} @@ -7407,7 +7460,7 @@ instruct vmul2S_mem(vecS dst, vecS src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul4S(vecD dst, vecD src) %{ +instruct vmul4S(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 4); match(Set dst (MulVS dst src)); format %{ "pmullw $dst,$src\t! mul packed4S" %} @@ -7417,7 +7470,7 @@ instruct vmul4S(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vmul4S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (MulVS src1 src2)); format %{ "vpmullw $dst,$src1,$src2\t! mul packed4S" %} @@ -7428,7 +7481,7 @@ instruct vmul4S_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul4S_mem(vecD dst, vecD src, memory mem) %{ +instruct vmul4S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (MulVS src (LoadVector mem))); format %{ "vpmullw $dst,$src,$mem\t! mul packed4S" %} @@ -7439,7 +7492,7 @@ instruct vmul4S_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul8S(vecX dst, vecX src) %{ +instruct vmul8S(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 8); match(Set dst (MulVS dst src)); format %{ "pmullw $dst,$src\t! mul packed8S" %} @@ -7449,7 +7502,7 @@ instruct vmul8S(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vmul8S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (MulVS src1 src2)); format %{ "vpmullw $dst,$src1,$src2\t! mul packed8S" %} @@ -7460,7 +7513,7 @@ instruct vmul8S_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul8S_mem(vecX dst, vecX src, memory mem) %{ +instruct vmul8S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (MulVS src (LoadVector mem))); format %{ "vpmullw $dst,$src,$mem\t! mul packed8S" %} @@ -7471,7 +7524,7 @@ instruct vmul8S_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul16S_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vmul16S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 16); match(Set dst (MulVS src1 src2)); format %{ "vpmullw $dst,$src1,$src2\t! mul packed16S" %} @@ -7482,7 +7535,7 @@ instruct vmul16S_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul16S_mem(vecY dst, vecY src, memory mem) %{ +instruct vmul16S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 16); match(Set dst (MulVS src (LoadVector mem))); format %{ "vpmullw $dst,$src,$mem\t! mul packed16S" %} @@ -7493,7 +7546,7 @@ instruct vmul16S_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul32S_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vmul32S_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); match(Set dst (MulVS src1 src2)); format %{ "vpmullw $dst,$src1,$src2\t! mul packed32S" %} @@ -7504,7 +7557,7 @@ instruct vmul32S_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul32S_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vmul32S_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); match(Set dst (MulVS src (LoadVector mem))); format %{ "vpmullw $dst,$src,$mem\t! mul packed32S" %} @@ -7516,7 +7569,7 @@ instruct vmul32S_mem(vecZ dst, vecZ src, memory mem) %{ %} // Integers vector mul (sse4_1) -instruct vmul2I(vecD dst, vecD src) %{ +instruct vmul2I(vec dst, vec src) %{ predicate(UseSSE > 3 && n->as_Vector()->length() == 2); match(Set dst (MulVI dst src)); format %{ "pmulld $dst,$src\t! mul packed2I" %} @@ -7526,7 +7579,7 @@ instruct vmul2I(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vmul2I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (MulVI src1 src2)); format %{ "vpmulld $dst,$src1,$src2\t! mul packed2I" %} @@ -7537,7 +7590,7 @@ instruct vmul2I_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul2I_mem(vecD dst, vecD src, memory mem) %{ +instruct vmul2I_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (MulVI src (LoadVector mem))); format %{ "vpmulld $dst,$src,$mem\t! mul packed2I" %} @@ -7548,7 +7601,7 @@ instruct vmul2I_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul4I(vecX dst, vecX src) %{ +instruct vmul4I(vec dst, vec src) %{ predicate(UseSSE > 3 && n->as_Vector()->length() == 4); match(Set dst (MulVI dst src)); format %{ "pmulld $dst,$src\t! mul packed4I" %} @@ -7558,7 +7611,7 @@ instruct vmul4I(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vmul4I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (MulVI src1 src2)); format %{ "vpmulld $dst,$src1,$src2\t! mul packed4I" %} @@ -7569,7 +7622,7 @@ instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul4I_mem(vecX dst, vecX src, memory mem) %{ +instruct vmul4I_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (MulVI src (LoadVector mem))); format %{ "vpmulld $dst,$src,$mem\t! mul packed4I" %} @@ -7580,7 +7633,7 @@ instruct vmul4I_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul2L_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vmul2L_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 2 && VM_Version::supports_avx512dq()); match(Set dst (MulVL src1 src2)); format %{ "vpmullq $dst,$src1,$src2\t! mul packed2L" %} @@ -7591,7 +7644,7 @@ instruct vmul2L_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul2L_mem(vecX dst, vecX src, memory mem) %{ +instruct vmul2L_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 2 && VM_Version::supports_avx512dq()); match(Set dst (MulVL src (LoadVector mem))); format %{ "vpmullq $dst,$src,$mem\t! mul packed2L" %} @@ -7602,7 +7655,7 @@ instruct vmul2L_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul4L_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vmul4L_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 4 && VM_Version::supports_avx512dq()); match(Set dst (MulVL src1 src2)); format %{ "vpmullq $dst,$src1,$src2\t! mul packed4L" %} @@ -7613,7 +7666,7 @@ instruct vmul4L_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul4L_mem(vecY dst, vecY src, memory mem) %{ +instruct vmul4L_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 4 && VM_Version::supports_avx512dq()); match(Set dst (MulVL src (LoadVector mem))); format %{ "vpmullq $dst,$src,$mem\t! mul packed4L" %} @@ -7624,7 +7677,7 @@ instruct vmul4L_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul8L_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vmul8L_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8 && VM_Version::supports_avx512dq()); match(Set dst (MulVL src1 src2)); format %{ "vpmullq $dst,$src1,$src2\t! mul packed8L" %} @@ -7635,7 +7688,7 @@ instruct vmul8L_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul8L_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vmul8L_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8 && VM_Version::supports_avx512dq()); match(Set dst (MulVL src (LoadVector mem))); format %{ "vpmullq $dst,$src,$mem\t! mul packed8L" %} @@ -7646,7 +7699,7 @@ instruct vmul8L_mem(vecZ dst, vecZ src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul8I_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vmul8I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 8); match(Set dst (MulVI src1 src2)); format %{ "vpmulld $dst,$src1,$src2\t! mul packed8I" %} @@ -7657,7 +7710,7 @@ instruct vmul8I_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul8I_mem(vecY dst, vecY src, memory mem) %{ +instruct vmul8I_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 8); match(Set dst (MulVI src (LoadVector mem))); format %{ "vpmulld $dst,$src,$mem\t! mul packed8I" %} @@ -7668,7 +7721,7 @@ instruct vmul8I_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul16I_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vmul16I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (MulVI src1 src2)); format %{ "vpmulld $dst,$src1,$src2\t! mul packed16I" %} @@ -7679,7 +7732,7 @@ instruct vmul16I_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul16I_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vmul16I_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (MulVI src (LoadVector mem))); format %{ "vpmulld $dst,$src,$mem\t! mul packed16I" %} @@ -7691,7 +7744,7 @@ instruct vmul16I_mem(vecZ dst, vecZ src, memory mem) %{ %} // Floats vector mul -instruct vmul2F(vecD dst, vecD src) %{ +instruct vmul2F(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (MulVF dst src)); format %{ "mulps $dst,$src\t! mul packed2F" %} @@ -7701,7 +7754,7 @@ instruct vmul2F(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vmul2F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (MulVF src1 src2)); format %{ "vmulps $dst,$src1,$src2\t! mul packed2F" %} @@ -7712,7 +7765,7 @@ instruct vmul2F_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul2F_mem(vecD dst, vecD src, memory mem) %{ +instruct vmul2F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (MulVF src (LoadVector mem))); format %{ "vmulps $dst,$src,$mem\t! mul packed2F" %} @@ -7723,7 +7776,7 @@ instruct vmul2F_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul4F(vecX dst, vecX src) %{ +instruct vmul4F(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 4); match(Set dst (MulVF dst src)); format %{ "mulps $dst,$src\t! mul packed4F" %} @@ -7733,7 +7786,7 @@ instruct vmul4F(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vmul4F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (MulVF src1 src2)); format %{ "vmulps $dst,$src1,$src2\t! mul packed4F" %} @@ -7744,7 +7797,7 @@ instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul4F_mem(vecX dst, vecX src, memory mem) %{ +instruct vmul4F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (MulVF src (LoadVector mem))); format %{ "vmulps $dst,$src,$mem\t! mul packed4F" %} @@ -7755,7 +7808,7 @@ instruct vmul4F_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul8F_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vmul8F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (MulVF src1 src2)); format %{ "vmulps $dst,$src1,$src2\t! mul packed8F" %} @@ -7766,7 +7819,7 @@ instruct vmul8F_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul8F_mem(vecY dst, vecY src, memory mem) %{ +instruct vmul8F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (MulVF src (LoadVector mem))); format %{ "vmulps $dst,$src,$mem\t! mul packed8F" %} @@ -7777,7 +7830,7 @@ instruct vmul8F_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul16F_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vmul16F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (MulVF src1 src2)); format %{ "vmulps $dst,$src1,$src2\t! mul packed16F" %} @@ -7788,7 +7841,7 @@ instruct vmul16F_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul16F_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vmul16F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (MulVF src (LoadVector mem))); format %{ "vmulps $dst,$src,$mem\t! mul packed16F" %} @@ -7800,7 +7853,7 @@ instruct vmul16F_mem(vecZ dst, vecZ src, memory mem) %{ %} // Doubles vector mul -instruct vmul2D(vecX dst, vecX src) %{ +instruct vmul2D(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (MulVD dst src)); format %{ "mulpd $dst,$src\t! mul packed2D" %} @@ -7810,7 +7863,7 @@ instruct vmul2D(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vmul2D_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vmul2D_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (MulVD src1 src2)); format %{ "vmulpd $dst,$src1,$src2\t! mul packed2D" %} @@ -7821,7 +7874,7 @@ instruct vmul2D_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul2D_mem(vecX dst, vecX src, memory mem) %{ +instruct vmul2D_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (MulVD src (LoadVector mem))); format %{ "vmulpd $dst,$src,$mem\t! mul packed2D" %} @@ -7832,7 +7885,7 @@ instruct vmul2D_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul4D_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vmul4D_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (MulVD src1 src2)); format %{ "vmulpd $dst,$src1,$src2\t! mul packed4D" %} @@ -7843,7 +7896,7 @@ instruct vmul4D_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul4D_mem(vecY dst, vecY src, memory mem) %{ +instruct vmul4D_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (MulVD src (LoadVector mem))); format %{ "vmulpd $dst,$src,$mem\t! mul packed4D" %} @@ -7854,7 +7907,7 @@ instruct vmul4D_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vmul8D_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vmul8D_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (MulVD src1 src2)); format %{ "vmulpd $dst k0,$src1,$src2\t! mul packed8D" %} @@ -7865,7 +7918,7 @@ instruct vmul8D_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vmul8D_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vmul8D_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (MulVD src (LoadVector mem))); format %{ "vmulpd $dst k0,$src,$mem\t! mul packed8D" %} @@ -7876,7 +7929,7 @@ instruct vmul8D_mem(vecZ dst, vecZ src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vcmov8F_reg(legVecY dst, legVecY src1, legVecY src2, immI8 cop, cmpOp_vcmppd copnd) %{ +instruct vcmov8F_reg(legVec dst, legVec src1, legVec src2, immI8 cop, cmpOp_vcmppd copnd) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (CMoveVF (Binary copnd cop) (Binary src1 src2))); effect(TEMP dst, USE src1, USE src2); @@ -7892,7 +7945,7 @@ instruct vcmov8F_reg(legVecY dst, legVecY src1, legVecY src2, immI8 cop, cmpOp_v ins_pipe( pipe_slow ); %} -instruct vcmov4D_reg(legVecY dst, legVecY src1, legVecY src2, immI8 cop, cmpOp_vcmppd copnd) %{ +instruct vcmov4D_reg(legVec dst, legVec src1, legVec src2, immI8 cop, cmpOp_vcmppd copnd) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (CMoveVD (Binary copnd cop) (Binary src1 src2))); effect(TEMP dst, USE src1, USE src2); @@ -7911,7 +7964,7 @@ instruct vcmov4D_reg(legVecY dst, legVecY src1, legVecY src2, immI8 cop, cmpOp_v // --------------------------------- DIV -------------------------------------- // Floats vector div -instruct vdiv2F(vecD dst, vecD src) %{ +instruct vdiv2F(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (DivVF dst src)); format %{ "divps $dst,$src\t! div packed2F" %} @@ -7921,7 +7974,7 @@ instruct vdiv2F(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vdiv2F_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vdiv2F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (DivVF src1 src2)); format %{ "vdivps $dst,$src1,$src2\t! div packed2F" %} @@ -7932,7 +7985,7 @@ instruct vdiv2F_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vdiv2F_mem(vecD dst, vecD src, memory mem) %{ +instruct vdiv2F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (DivVF src (LoadVector mem))); format %{ "vdivps $dst,$src,$mem\t! div packed2F" %} @@ -7943,7 +7996,7 @@ instruct vdiv2F_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vdiv4F(vecX dst, vecX src) %{ +instruct vdiv4F(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 4); match(Set dst (DivVF dst src)); format %{ "divps $dst,$src\t! div packed4F" %} @@ -7953,7 +8006,7 @@ instruct vdiv4F(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vdiv4F_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vdiv4F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (DivVF src1 src2)); format %{ "vdivps $dst,$src1,$src2\t! div packed4F" %} @@ -7964,7 +8017,7 @@ instruct vdiv4F_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vdiv4F_mem(vecX dst, vecX src, memory mem) %{ +instruct vdiv4F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (DivVF src (LoadVector mem))); format %{ "vdivps $dst,$src,$mem\t! div packed4F" %} @@ -7975,7 +8028,7 @@ instruct vdiv4F_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vdiv8F_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vdiv8F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (DivVF src1 src2)); format %{ "vdivps $dst,$src1,$src2\t! div packed8F" %} @@ -7986,7 +8039,7 @@ instruct vdiv8F_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vdiv8F_mem(vecY dst, vecY src, memory mem) %{ +instruct vdiv8F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (DivVF src (LoadVector mem))); format %{ "vdivps $dst,$src,$mem\t! div packed8F" %} @@ -7997,7 +8050,7 @@ instruct vdiv8F_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vdiv16F_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vdiv16F_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 16); match(Set dst (DivVF src1 src2)); format %{ "vdivps $dst,$src1,$src2\t! div packed16F" %} @@ -8008,7 +8061,7 @@ instruct vdiv16F_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vdiv16F_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vdiv16F_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 16); match(Set dst (DivVF src (LoadVector mem))); format %{ "vdivps $dst,$src,$mem\t! div packed16F" %} @@ -8020,7 +8073,7 @@ instruct vdiv16F_mem(vecZ dst, vecZ src, memory mem) %{ %} // Doubles vector div -instruct vdiv2D(vecX dst, vecX src) %{ +instruct vdiv2D(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (DivVD dst src)); format %{ "divpd $dst,$src\t! div packed2D" %} @@ -8030,7 +8083,7 @@ instruct vdiv2D(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vdiv2D_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vdiv2D_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (DivVD src1 src2)); format %{ "vdivpd $dst,$src1,$src2\t! div packed2D" %} @@ -8041,7 +8094,7 @@ instruct vdiv2D_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vdiv2D_mem(vecX dst, vecX src, memory mem) %{ +instruct vdiv2D_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (DivVD src (LoadVector mem))); format %{ "vdivpd $dst,$src,$mem\t! div packed2D" %} @@ -8052,7 +8105,7 @@ instruct vdiv2D_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vdiv4D_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vdiv4D_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (DivVD src1 src2)); format %{ "vdivpd $dst,$src1,$src2\t! div packed4D" %} @@ -8063,7 +8116,7 @@ instruct vdiv4D_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vdiv4D_mem(vecY dst, vecY src, memory mem) %{ +instruct vdiv4D_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (DivVD src (LoadVector mem))); format %{ "vdivpd $dst,$src,$mem\t! div packed4D" %} @@ -8074,7 +8127,7 @@ instruct vdiv4D_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vdiv8D_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vdiv8D_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (DivVD src1 src2)); format %{ "vdivpd $dst,$src1,$src2\t! div packed8D" %} @@ -8085,7 +8138,7 @@ instruct vdiv8D_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vdiv8D_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vdiv8D_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (DivVD src (LoadVector mem))); format %{ "vdivpd $dst,$src,$mem\t! div packed8D" %} @@ -8099,7 +8152,7 @@ instruct vdiv8D_mem(vecZ dst, vecZ src, memory mem) %{ // --------------------------------- Sqrt -------------------------------------- // Floating point vector sqrt -instruct vsqrt2D_reg(vecX dst, vecX src) %{ +instruct vsqrt2D_reg(vec dst, vec src) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SqrtVD src)); format %{ "vsqrtpd $dst,$src\t! sqrt packed2D" %} @@ -8110,7 +8163,7 @@ instruct vsqrt2D_reg(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt2D_mem(vecX dst, memory mem) %{ +instruct vsqrt2D_mem(vec dst, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SqrtVD (LoadVector mem))); format %{ "vsqrtpd $dst,$mem\t! sqrt packed2D" %} @@ -8121,7 +8174,7 @@ instruct vsqrt2D_mem(vecX dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt4D_reg(vecY dst, vecY src) %{ +instruct vsqrt4D_reg(vec dst, vec src) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SqrtVD src)); format %{ "vsqrtpd $dst,$src\t! sqrt packed4D" %} @@ -8132,7 +8185,7 @@ instruct vsqrt4D_reg(vecY dst, vecY src) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt4D_mem(vecY dst, memory mem) %{ +instruct vsqrt4D_mem(vec dst, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SqrtVD (LoadVector mem))); format %{ "vsqrtpd $dst,$mem\t! sqrt packed4D" %} @@ -8143,7 +8196,7 @@ instruct vsqrt4D_mem(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt8D_reg(vecZ dst, vecZ src) %{ +instruct vsqrt8D_reg(vec dst, vec src) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (SqrtVD src)); format %{ "vsqrtpd $dst,$src\t! sqrt packed8D" %} @@ -8154,7 +8207,7 @@ instruct vsqrt8D_reg(vecZ dst, vecZ src) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt8D_mem(vecZ dst, memory mem) %{ +instruct vsqrt8D_mem(vec dst, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (SqrtVD (LoadVector mem))); format %{ "vsqrtpd $dst,$mem\t! sqrt packed8D" %} @@ -8165,7 +8218,7 @@ instruct vsqrt8D_mem(vecZ dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt2F_reg(vecD dst, vecD src) %{ +instruct vsqrt2F_reg(vec dst, vec src) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SqrtVF src)); format %{ "vsqrtps $dst,$src\t! sqrt packed2F" %} @@ -8176,7 +8229,7 @@ instruct vsqrt2F_reg(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt2F_mem(vecD dst, memory mem) %{ +instruct vsqrt2F_mem(vec dst, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (SqrtVF (LoadVector mem))); format %{ "vsqrtps $dst,$mem\t! sqrt packed2F" %} @@ -8187,7 +8240,7 @@ instruct vsqrt2F_mem(vecD dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt4F_reg(vecX dst, vecX src) %{ +instruct vsqrt4F_reg(vec dst, vec src) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SqrtVF src)); format %{ "vsqrtps $dst,$src\t! sqrt packed4F" %} @@ -8198,7 +8251,7 @@ instruct vsqrt4F_reg(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt4F_mem(vecX dst, memory mem) %{ +instruct vsqrt4F_mem(vec dst, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (SqrtVF (LoadVector mem))); format %{ "vsqrtps $dst,$mem\t! sqrt packed4F" %} @@ -8209,7 +8262,7 @@ instruct vsqrt4F_mem(vecX dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt8F_reg(vecY dst, vecY src) %{ +instruct vsqrt8F_reg(vec dst, vec src) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (SqrtVF src)); format %{ "vsqrtps $dst,$src\t! sqrt packed8F" %} @@ -8220,7 +8273,7 @@ instruct vsqrt8F_reg(vecY dst, vecY src) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt8F_mem(vecY dst, memory mem) %{ +instruct vsqrt8F_mem(vec dst, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (SqrtVF (LoadVector mem))); format %{ "vsqrtps $dst,$mem\t! sqrt packed8F" %} @@ -8231,7 +8284,7 @@ instruct vsqrt8F_mem(vecY dst, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt16F_reg(vecZ dst, vecZ src) %{ +instruct vsqrt16F_reg(vec dst, vec src) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (SqrtVF src)); format %{ "vsqrtps $dst,$src\t! sqrt packed16F" %} @@ -8242,7 +8295,7 @@ instruct vsqrt16F_reg(vecZ dst, vecZ src) %{ ins_pipe( pipe_slow ); %} -instruct vsqrt16F_mem(vecZ dst, memory mem) %{ +instruct vsqrt16F_mem(vec dst, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (SqrtVF (LoadVector mem))); format %{ "vsqrtps $dst,$mem\t! sqrt packed16F" %} @@ -8257,7 +8310,7 @@ instruct vsqrt16F_mem(vecZ dst, memory mem) %{ // Left and right shift count vectors are the same on x86 // (only lowest bits of xmm reg are used for count). -instruct vshiftcnt(vecS dst, rRegI cnt) %{ +instruct vshiftcnt(vec dst, rRegI cnt) %{ match(Set dst (LShiftCntV cnt)); match(Set dst (RShiftCntV cnt)); format %{ "movdl $dst,$cnt\t! load shift count" %} @@ -8267,7 +8320,7 @@ instruct vshiftcnt(vecS dst, rRegI cnt) %{ ins_pipe( pipe_slow ); %} -instruct vshiftcntimm(vecS dst, immI8 cnt, rRegI tmp) %{ +instruct vshiftcntimm(vec dst, immI8 cnt, rRegI tmp) %{ match(Set dst cnt); effect(TEMP tmp); format %{ "movl $tmp,$cnt\t" @@ -8280,7 +8333,7 @@ instruct vshiftcntimm(vecS dst, immI8 cnt, rRegI tmp) %{ %} // Byte vector shift -instruct vshift4B(vecS dst, vecS src, vecS shift, vecS tmp, rRegI scratch) %{ +instruct vshift4B(vec dst, vec src, vec shift, vec tmp, rRegI scratch) %{ predicate(UseSSE > 3 && n->as_Vector()->length() == 4); match(Set dst (LShiftVB src shift)); match(Set dst (RShiftVB src shift)); @@ -8296,14 +8349,14 @@ instruct vshift4B(vecS dst, vecS src, vecS shift, vecS tmp, rRegI scratch) %{ __ vextendbw(opcode, $tmp$$XMMRegister, $src$$XMMRegister); __ vshiftw(opcode, $tmp$$XMMRegister, $shift$$XMMRegister); - __ movdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); + __ movdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); __ pand($dst$$XMMRegister, $tmp$$XMMRegister); __ packuswb($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} -instruct vshift8B(vecD dst, vecD src, vecS shift, vecD tmp, rRegI scratch) %{ +instruct vshift8B(vec dst, vec src, vec shift, vec tmp, rRegI scratch) %{ predicate(UseSSE > 3 && n->as_Vector()->length() == 8); match(Set dst (LShiftVB src shift)); match(Set dst (RShiftVB src shift)); @@ -8319,14 +8372,14 @@ instruct vshift8B(vecD dst, vecD src, vecS shift, vecD tmp, rRegI scratch) %{ __ vextendbw(opcode, $tmp$$XMMRegister, $src$$XMMRegister); __ vshiftw(opcode, $tmp$$XMMRegister, $shift$$XMMRegister); - __ movdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); + __ movdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); __ pand($dst$$XMMRegister, $tmp$$XMMRegister); __ packuswb($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} -instruct vshift16B(vecX dst, vecX src, vecS shift, vecX tmp1, vecX tmp2, rRegI scratch) %{ +instruct vshift16B(vec dst, vec src, vec shift, vec tmp1, vec tmp2, rRegI scratch) %{ predicate(UseSSE > 3 && UseAVX <= 1 && n->as_Vector()->length() == 16); match(Set dst (LShiftVB src shift)); match(Set dst (RShiftVB src shift)); @@ -8357,7 +8410,7 @@ instruct vshift16B(vecX dst, vecX src, vecS shift, vecX tmp1, vecX tmp2, rRegI s ins_pipe( pipe_slow ); %} -instruct vshift16B_avx(vecX dst, vecX src, vecS shift, vecX tmp, rRegI scratch) %{ +instruct vshift16B_avx(vec dst, vec src, vec shift, vec tmp, rRegI scratch) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 16); match(Set dst (LShiftVB src shift)); match(Set dst (RShiftVB src shift)); @@ -8381,7 +8434,7 @@ instruct vshift16B_avx(vecX dst, vecX src, vecS shift, vecX tmp, rRegI scratch) ins_pipe( pipe_slow ); %} -instruct vshift32B_avx(vecY dst, vecY src, vecS shift, vecY tmp, rRegI scratch) %{ +instruct vshift32B_avx(vec dst, vec src, vec shift, vec tmp, rRegI scratch) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 32); match(Set dst (LShiftVB src shift)); match(Set dst (RShiftVB src shift)); @@ -8413,7 +8466,7 @@ instruct vshift32B_avx(vecY dst, vecY src, vecS shift, vecY tmp, rRegI scratch) ins_pipe( pipe_slow ); %} -instruct vshift64B_avx(vecZ dst, vecZ src, vecS shift, vecZ tmp1, vecZ tmp2, rRegI scratch) %{ +instruct vshift64B_avx(vec dst, vec src, vec shift, vec tmp1, vec tmp2, rRegI scratch) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 64); match(Set dst (LShiftVB src shift)); match(Set dst (RShiftVB src shift)); @@ -8456,7 +8509,7 @@ instruct vshift64B_avx(vecZ dst, vecZ src, vecS shift, vecZ tmp1, vecZ tmp2, rRe // sign extension before a shift. But char vectors are fine since chars are // unsigned values. // Shorts/Chars vector left shift -instruct vshist2S(vecS dst, vecS src, vecS shift) %{ +instruct vshist2S(vec dst, vec src, vec shift) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (LShiftVS src shift)); match(Set dst (RShiftVS src shift)); @@ -8465,7 +8518,7 @@ instruct vshist2S(vecS dst, vecS src, vecS shift) %{ format %{ "vshiftw $dst,$src,$shift\t! shift packed2S" %} ins_encode %{ int opcode = this->as_Mach()->ideal_Opcode(); - if (UseAVX == 0) { + if (UseAVX == 0) { if ($dst$$XMMRegister != $src$$XMMRegister) __ movflt($dst$$XMMRegister, $src$$XMMRegister); __ vshiftw(opcode, $dst$$XMMRegister, $shift$$XMMRegister); @@ -8477,7 +8530,7 @@ instruct vshist2S(vecS dst, vecS src, vecS shift) %{ ins_pipe( pipe_slow ); %} -instruct vshift4S(vecD dst, vecD src, vecS shift) %{ +instruct vshift4S(vec dst, vec src, vec shift) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (LShiftVS src shift)); match(Set dst (RShiftVS src shift)); @@ -8486,11 +8539,11 @@ instruct vshift4S(vecD dst, vecD src, vecS shift) %{ format %{ "vshiftw $dst,$src,$shift\t! shift packed4S" %} ins_encode %{ int opcode = this->as_Mach()->ideal_Opcode(); - if (UseAVX == 0) { + if (UseAVX == 0) { if ($dst$$XMMRegister != $src$$XMMRegister) __ movdbl($dst$$XMMRegister, $src$$XMMRegister); __ vshiftw(opcode, $dst$$XMMRegister, $shift$$XMMRegister); - + } else { int vector_len = 0; __ vshiftw(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); @@ -8499,7 +8552,7 @@ instruct vshift4S(vecD dst, vecD src, vecS shift) %{ ins_pipe( pipe_slow ); %} -instruct vshift8S(vecX dst, vecX src, vecS shift) %{ +instruct vshift8S(vec dst, vec src, vec shift) %{ predicate(n->as_Vector()->length() == 8); match(Set dst (LShiftVS src shift)); match(Set dst (RShiftVS src shift)); @@ -8508,7 +8561,7 @@ instruct vshift8S(vecX dst, vecX src, vecS shift) %{ format %{ "vshiftw $dst,$src,$shift\t! shift packed8S" %} ins_encode %{ int opcode = this->as_Mach()->ideal_Opcode(); - if (UseAVX == 0) { + if (UseAVX == 0) { if ($dst$$XMMRegister != $src$$XMMRegister) __ movdqu($dst$$XMMRegister, $src$$XMMRegister); __ vshiftw(opcode, $dst$$XMMRegister, $shift$$XMMRegister); @@ -8520,7 +8573,7 @@ instruct vshift8S(vecX dst, vecX src, vecS shift) %{ ins_pipe( pipe_slow ); %} -instruct vshift16S(vecY dst, vecY src, vecS shift) %{ +instruct vshift16S(vec dst, vec src, vec shift) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 16); match(Set dst (LShiftVS src shift)); match(Set dst (RShiftVS src shift)); @@ -8535,7 +8588,7 @@ instruct vshift16S(vecY dst, vecY src, vecS shift) %{ ins_pipe( pipe_slow ); %} -instruct vshift32S(vecZ dst, vecZ src, vecS shift) %{ +instruct vshift32S(vec dst, vec src, vec shift) %{ predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); match(Set dst (LShiftVS src shift)); match(Set dst (RShiftVS src shift)); @@ -8551,7 +8604,7 @@ instruct vshift32S(vecZ dst, vecZ src, vecS shift) %{ %} // Integers vector left shift -instruct vshift2I(vecD dst, vecD src, vecS shift) %{ +instruct vshift2I(vec dst, vec src, vec shift) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (LShiftVI src shift)); match(Set dst (RShiftVI src shift)); @@ -8560,7 +8613,7 @@ instruct vshift2I(vecD dst, vecD src, vecS shift) %{ format %{ "vshiftd $dst,$src,$shift\t! shift packed2I" %} ins_encode %{ int opcode = this->as_Mach()->ideal_Opcode(); - if (UseAVX == 0) { + if (UseAVX == 0) { if ($dst$$XMMRegister != $src$$XMMRegister) __ movdbl($dst$$XMMRegister, $src$$XMMRegister); __ vshiftd(opcode, $dst$$XMMRegister, $shift$$XMMRegister); @@ -8572,7 +8625,7 @@ instruct vshift2I(vecD dst, vecD src, vecS shift) %{ ins_pipe( pipe_slow ); %} -instruct vshift4I(vecX dst, vecX src, vecS shift) %{ +instruct vshift4I(vec dst, vec src, vec shift) %{ predicate(n->as_Vector()->length() == 4); match(Set dst (LShiftVI src shift)); match(Set dst (RShiftVI src shift)); @@ -8581,7 +8634,7 @@ instruct vshift4I(vecX dst, vecX src, vecS shift) %{ format %{ "vshiftd $dst,$src,$shift\t! shift packed4I" %} ins_encode %{ int opcode = this->as_Mach()->ideal_Opcode(); - if (UseAVX == 0) { + if (UseAVX == 0) { if ($dst$$XMMRegister != $src$$XMMRegister) __ movdqu($dst$$XMMRegister, $src$$XMMRegister); __ vshiftd(opcode, $dst$$XMMRegister, $shift$$XMMRegister); @@ -8593,7 +8646,7 @@ instruct vshift4I(vecX dst, vecX src, vecS shift) %{ ins_pipe( pipe_slow ); %} -instruct vshift8I(vecY dst, vecY src, vecS shift) %{ +instruct vshift8I(vec dst, vec src, vec shift) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 8); match(Set dst (LShiftVI src shift)); match(Set dst (RShiftVI src shift)); @@ -8608,7 +8661,7 @@ instruct vshift8I(vecY dst, vecY src, vecS shift) %{ ins_pipe( pipe_slow ); %} -instruct vshift16I(vecZ dst, vecZ src, vecS shift) %{ +instruct vshift16I(vec dst, vec src, vec shift) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (LShiftVI src shift)); match(Set dst (RShiftVI src shift)); @@ -8624,7 +8677,7 @@ instruct vshift16I(vecZ dst, vecZ src, vecS shift) %{ %} // Longs vector shift -instruct vshift2L(vecX dst, vecX src, vecS shift) %{ +instruct vshift2L(vec dst, vec src, vec shift) %{ predicate(n->as_Vector()->length() == 2); match(Set dst (LShiftVL src shift)); match(Set dst (URShiftVL src shift)); @@ -8632,7 +8685,7 @@ instruct vshift2L(vecX dst, vecX src, vecS shift) %{ format %{ "vshiftq $dst,$src,$shift\t! shift packed2L" %} ins_encode %{ int opcode = this->as_Mach()->ideal_Opcode(); - if (UseAVX == 0) { + if (UseAVX == 0) { if ($dst$$XMMRegister != $src$$XMMRegister) __ movdqu($dst$$XMMRegister, $src$$XMMRegister); __ vshiftq(opcode, $dst$$XMMRegister, $shift$$XMMRegister); @@ -8644,7 +8697,7 @@ instruct vshift2L(vecX dst, vecX src, vecS shift) %{ ins_pipe( pipe_slow ); %} -instruct vshift4L(vecY dst, vecY src, vecS shift) %{ +instruct vshift4L(vec dst, vec src, vec shift) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 4); match(Set dst (LShiftVL src shift)); match(Set dst (URShiftVL src shift)); @@ -8658,7 +8711,7 @@ instruct vshift4L(vecY dst, vecY src, vecS shift) %{ ins_pipe( pipe_slow ); %} -instruct vshift8L(vecZ dst, vecZ src, vecS shift) %{ +instruct vshift8L(vec dst, vec src, vec shift) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (LShiftVL src shift)); match(Set dst (RShiftVL src shift)); @@ -8675,7 +8728,7 @@ instruct vshift8L(vecZ dst, vecZ src, vecS shift) %{ // -------------------ArithmeticRightShift ----------------------------------- // Long vector arithmetic right shift -instruct vsra2L_reg(vecX dst, vecX src, vecS shift, vecX tmp, rRegI scratch) %{ +instruct vsra2L_reg(vec dst, vec src, vec shift, vec tmp, rRegI scratch) %{ predicate(UseSSE >= 2 && n->as_Vector()->length() == 2); match(Set dst (RShiftVL src shift)); effect(TEMP dst, TEMP tmp, TEMP scratch); @@ -8696,7 +8749,7 @@ instruct vsra2L_reg(vecX dst, vecX src, vecS shift, vecX tmp, rRegI scratch) %{ ins_pipe( pipe_slow ); %} -instruct vsra2L_reg_evex(vecX dst, vecX src, vecS shift) %{ +instruct vsra2L_reg_evex(vec dst, vec src, vec shift) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 2); match(Set dst (RShiftVL src shift)); format %{ "evpsraq $dst,$src,$shift\t! arithmetic right shift packed2L" %} @@ -8707,7 +8760,7 @@ instruct vsra2L_reg_evex(vecX dst, vecX src, vecS shift) %{ ins_pipe( pipe_slow ); %} -instruct vsra4L_reg(vecY dst, vecY src, vecS shift, vecY tmp, rRegI scratch) %{ +instruct vsra4L_reg(vec dst, vec src, vec shift, vec tmp, rRegI scratch) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 4); match(Set dst (RShiftVL src shift)); effect(TEMP dst, TEMP tmp, TEMP scratch); @@ -8727,7 +8780,7 @@ instruct vsra4L_reg(vecY dst, vecY src, vecS shift, vecY tmp, rRegI scratch) %{ ins_pipe( pipe_slow ); %} -instruct vsra4L_reg_evex(vecY dst, vecY src, vecS shift) %{ +instruct vsra4L_reg_evex(vec dst, vec src, vec shift) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 4); match(Set dst (RShiftVL src shift)); format %{ "evpsraq $dst,$src,$shift\t! arithmetic right shift packed4L" %} @@ -8740,7 +8793,7 @@ instruct vsra4L_reg_evex(vecY dst, vecY src, vecS shift) %{ // --------------------------------- AND -------------------------------------- -instruct vand4B(vecS dst, vecS src) %{ +instruct vand4B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length_in_bytes() == 4); match(Set dst (AndV dst src)); format %{ "pand $dst,$src\t! and vectors (4 bytes)" %} @@ -8750,7 +8803,7 @@ instruct vand4B(vecS dst, vecS src) %{ ins_pipe( pipe_slow ); %} -instruct vand4B_reg(vecS dst, vecS src1, vecS src2) %{ +instruct vand4B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 4); match(Set dst (AndV src1 src2)); format %{ "vpand $dst,$src1,$src2\t! and vectors (4 bytes)" %} @@ -8761,7 +8814,7 @@ instruct vand4B_reg(vecS dst, vecS src1, vecS src2) %{ ins_pipe( pipe_slow ); %} -instruct vand4B_mem(vecS dst, vecS src, memory mem) %{ +instruct vand4B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 4); match(Set dst (AndV src (LoadVector mem))); format %{ "vpand $dst,$src,$mem\t! and vectors (4 bytes)" %} @@ -8772,7 +8825,7 @@ instruct vand4B_mem(vecS dst, vecS src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vand8B(vecD dst, vecD src) %{ +instruct vand8B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length_in_bytes() == 8); match(Set dst (AndV dst src)); format %{ "pand $dst,$src\t! and vectors (8 bytes)" %} @@ -8782,7 +8835,7 @@ instruct vand8B(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vand8B_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vand8B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 8); match(Set dst (AndV src1 src2)); format %{ "vpand $dst,$src1,$src2\t! and vectors (8 bytes)" %} @@ -8793,7 +8846,7 @@ instruct vand8B_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vand8B_mem(vecD dst, vecD src, memory mem) %{ +instruct vand8B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 8); match(Set dst (AndV src (LoadVector mem))); format %{ "vpand $dst,$src,$mem\t! and vectors (8 bytes)" %} @@ -8804,7 +8857,7 @@ instruct vand8B_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vand16B(vecX dst, vecX src) %{ +instruct vand16B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length_in_bytes() == 16); match(Set dst (AndV dst src)); format %{ "pand $dst,$src\t! and vectors (16 bytes)" %} @@ -8814,7 +8867,7 @@ instruct vand16B(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vand16B_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vand16B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 16); match(Set dst (AndV src1 src2)); format %{ "vpand $dst,$src1,$src2\t! and vectors (16 bytes)" %} @@ -8825,7 +8878,7 @@ instruct vand16B_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vand16B_mem(vecX dst, vecX src, memory mem) %{ +instruct vand16B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 16); match(Set dst (AndV src (LoadVector mem))); format %{ "vpand $dst,$src,$mem\t! and vectors (16 bytes)" %} @@ -8836,7 +8889,7 @@ instruct vand16B_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vand32B_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vand32B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length_in_bytes() == 32); match(Set dst (AndV src1 src2)); format %{ "vpand $dst,$src1,$src2\t! and vectors (32 bytes)" %} @@ -8847,7 +8900,7 @@ instruct vand32B_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vand32B_mem(vecY dst, vecY src, memory mem) %{ +instruct vand32B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length_in_bytes() == 32); match(Set dst (AndV src (LoadVector mem))); format %{ "vpand $dst,$src,$mem\t! and vectors (32 bytes)" %} @@ -8858,7 +8911,7 @@ instruct vand32B_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vand64B_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vand64B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length_in_bytes() == 64); match(Set dst (AndV src1 src2)); format %{ "vpand $dst,$src1,$src2\t! and vectors (64 bytes)" %} @@ -8869,7 +8922,7 @@ instruct vand64B_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vand64B_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vand64B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length_in_bytes() == 64); match(Set dst (AndV src (LoadVector mem))); format %{ "vpand $dst,$src,$mem\t! and vectors (64 bytes)" %} @@ -8882,7 +8935,7 @@ instruct vand64B_mem(vecZ dst, vecZ src, memory mem) %{ // --------------------------------- OR --------------------------------------- -instruct vor4B(vecS dst, vecS src) %{ +instruct vor4B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length_in_bytes() == 4); match(Set dst (OrV dst src)); format %{ "por $dst,$src\t! or vectors (4 bytes)" %} @@ -8892,7 +8945,7 @@ instruct vor4B(vecS dst, vecS src) %{ ins_pipe( pipe_slow ); %} -instruct vor4B_reg(vecS dst, vecS src1, vecS src2) %{ +instruct vor4B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 4); match(Set dst (OrV src1 src2)); format %{ "vpor $dst,$src1,$src2\t! or vectors (4 bytes)" %} @@ -8903,7 +8956,7 @@ instruct vor4B_reg(vecS dst, vecS src1, vecS src2) %{ ins_pipe( pipe_slow ); %} -instruct vor4B_mem(vecS dst, vecS src, memory mem) %{ +instruct vor4B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 4); match(Set dst (OrV src (LoadVector mem))); format %{ "vpor $dst,$src,$mem\t! or vectors (4 bytes)" %} @@ -8914,7 +8967,7 @@ instruct vor4B_mem(vecS dst, vecS src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vor8B(vecD dst, vecD src) %{ +instruct vor8B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length_in_bytes() == 8); match(Set dst (OrV dst src)); format %{ "por $dst,$src\t! or vectors (8 bytes)" %} @@ -8924,7 +8977,7 @@ instruct vor8B(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vor8B_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vor8B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 8); match(Set dst (OrV src1 src2)); format %{ "vpor $dst,$src1,$src2\t! or vectors (8 bytes)" %} @@ -8935,7 +8988,7 @@ instruct vor8B_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vor8B_mem(vecD dst, vecD src, memory mem) %{ +instruct vor8B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 4); match(Set dst (OrV src (LoadVector mem))); format %{ "vpor $dst,$src,$mem\t! or vectors (8 bytes)" %} @@ -8946,7 +8999,7 @@ instruct vor8B_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vor16B(vecX dst, vecX src) %{ +instruct vor16B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length_in_bytes() == 16); match(Set dst (OrV dst src)); format %{ "por $dst,$src\t! or vectors (16 bytes)" %} @@ -8956,7 +9009,7 @@ instruct vor16B(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vor16B_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vor16B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 16); match(Set dst (OrV src1 src2)); format %{ "vpor $dst,$src1,$src2\t! or vectors (16 bytes)" %} @@ -8967,7 +9020,7 @@ instruct vor16B_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vor16B_mem(vecX dst, vecX src, memory mem) %{ +instruct vor16B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 16); match(Set dst (OrV src (LoadVector mem))); format %{ "vpor $dst,$src,$mem\t! or vectors (16 bytes)" %} @@ -8978,7 +9031,7 @@ instruct vor16B_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vor32B_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vor32B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length_in_bytes() == 32); match(Set dst (OrV src1 src2)); format %{ "vpor $dst,$src1,$src2\t! or vectors (32 bytes)" %} @@ -8989,7 +9042,7 @@ instruct vor32B_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vor32B_mem(vecY dst, vecY src, memory mem) %{ +instruct vor32B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length_in_bytes() == 32); match(Set dst (OrV src (LoadVector mem))); format %{ "vpor $dst,$src,$mem\t! or vectors (32 bytes)" %} @@ -9000,7 +9053,7 @@ instruct vor32B_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vor64B_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vor64B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length_in_bytes() == 64); match(Set dst (OrV src1 src2)); format %{ "vpor $dst,$src1,$src2\t! or vectors (64 bytes)" %} @@ -9011,7 +9064,7 @@ instruct vor64B_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vor64B_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vor64B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length_in_bytes() == 64); match(Set dst (OrV src (LoadVector mem))); format %{ "vpor $dst,$src,$mem\t! or vectors (64 bytes)" %} @@ -9024,7 +9077,7 @@ instruct vor64B_mem(vecZ dst, vecZ src, memory mem) %{ // --------------------------------- XOR -------------------------------------- -instruct vxor4B(vecS dst, vecS src) %{ +instruct vxor4B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length_in_bytes() == 4); match(Set dst (XorV dst src)); format %{ "pxor $dst,$src\t! xor vectors (4 bytes)" %} @@ -9034,7 +9087,7 @@ instruct vxor4B(vecS dst, vecS src) %{ ins_pipe( pipe_slow ); %} -instruct vxor4B_reg(vecS dst, vecS src1, vecS src2) %{ +instruct vxor4B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 4); match(Set dst (XorV src1 src2)); format %{ "vpxor $dst,$src1,$src2\t! xor vectors (4 bytes)" %} @@ -9045,7 +9098,7 @@ instruct vxor4B_reg(vecS dst, vecS src1, vecS src2) %{ ins_pipe( pipe_slow ); %} -instruct vxor4B_mem(vecS dst, vecS src, memory mem) %{ +instruct vxor4B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 4); match(Set dst (XorV src (LoadVector mem))); format %{ "vpxor $dst,$src,$mem\t! xor vectors (4 bytes)" %} @@ -9056,7 +9109,7 @@ instruct vxor4B_mem(vecS dst, vecS src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vxor8B(vecD dst, vecD src) %{ +instruct vxor8B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length_in_bytes() == 8); match(Set dst (XorV dst src)); format %{ "pxor $dst,$src\t! xor vectors (8 bytes)" %} @@ -9066,7 +9119,7 @@ instruct vxor8B(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vxor8B_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vxor8B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 8); match(Set dst (XorV src1 src2)); format %{ "vpxor $dst,$src1,$src2\t! xor vectors (8 bytes)" %} @@ -9077,7 +9130,7 @@ instruct vxor8B_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct vxor8B_mem(vecD dst, vecD src, memory mem) %{ +instruct vxor8B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 8); match(Set dst (XorV src (LoadVector mem))); format %{ "vpxor $dst,$src,$mem\t! xor vectors (8 bytes)" %} @@ -9088,7 +9141,7 @@ instruct vxor8B_mem(vecD dst, vecD src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vxor16B(vecX dst, vecX src) %{ +instruct vxor16B(vec dst, vec src) %{ predicate(UseAVX == 0 && n->as_Vector()->length_in_bytes() == 16); match(Set dst (XorV dst src)); format %{ "pxor $dst,$src\t! xor vectors (16 bytes)" %} @@ -9098,7 +9151,7 @@ instruct vxor16B(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vxor16B_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vxor16B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 16); match(Set dst (XorV src1 src2)); format %{ "vpxor $dst,$src1,$src2\t! xor vectors (16 bytes)" %} @@ -9109,7 +9162,7 @@ instruct vxor16B_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vxor16B_mem(vecX dst, vecX src, memory mem) %{ +instruct vxor16B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 0 && n->as_Vector()->length_in_bytes() == 16); match(Set dst (XorV src (LoadVector mem))); format %{ "vpxor $dst,$src,$mem\t! xor vectors (16 bytes)" %} @@ -9120,7 +9173,7 @@ instruct vxor16B_mem(vecX dst, vecX src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vxor32B_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vxor32B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length_in_bytes() == 32); match(Set dst (XorV src1 src2)); format %{ "vpxor $dst,$src1,$src2\t! xor vectors (32 bytes)" %} @@ -9131,7 +9184,7 @@ instruct vxor32B_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vxor32B_mem(vecY dst, vecY src, memory mem) %{ +instruct vxor32B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 1 && n->as_Vector()->length_in_bytes() == 32); match(Set dst (XorV src (LoadVector mem))); format %{ "vpxor $dst,$src,$mem\t! xor vectors (32 bytes)" %} @@ -9142,7 +9195,7 @@ instruct vxor32B_mem(vecY dst, vecY src, memory mem) %{ ins_pipe( pipe_slow ); %} -instruct vxor64B_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vxor64B_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length_in_bytes() == 64); match(Set dst (XorV src1 src2)); format %{ "vpxor $dst,$src1,$src2\t! xor vectors (64 bytes)" %} @@ -9153,7 +9206,7 @@ instruct vxor64B_reg(vecZ dst, vecZ src1, vecZ src2) %{ ins_pipe( pipe_slow ); %} -instruct vxor64B_mem(vecZ dst, vecZ src, memory mem) %{ +instruct vxor64B_mem(vec dst, vec src, memory mem) %{ predicate(UseAVX > 2 && n->as_Vector()->length_in_bytes() == 64); match(Set dst (XorV src (LoadVector mem))); format %{ "vpxor $dst,$src,$mem\t! xor vectors (64 bytes)" %} @@ -9166,7 +9219,7 @@ instruct vxor64B_mem(vecZ dst, vecZ src, memory mem) %{ // --------------------------------- ABS -------------------------------------- // a = |a| -instruct vabs4B_reg(vecS dst, vecS src) %{ +instruct vabs4B_reg(vec dst, vec src) %{ predicate(UseSSE > 2 && n->as_Vector()->length() == 4); match(Set dst (AbsVB src)); format %{ "pabsb $dst,$src\t# $dst = |$src| abs packed4B" %} @@ -9176,7 +9229,7 @@ instruct vabs4B_reg(vecS dst, vecS src) %{ ins_pipe( pipe_slow ); %} -instruct vabs8B_reg(vecD dst, vecD src) %{ +instruct vabs8B_reg(vec dst, vec src) %{ predicate(UseSSE > 2 && n->as_Vector()->length() == 8); match(Set dst (AbsVB src)); format %{ "pabsb $dst,$src\t# $dst = |$src| abs packed8B" %} @@ -9186,7 +9239,7 @@ instruct vabs8B_reg(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vabs16B_reg(vecX dst, vecX src) %{ +instruct vabs16B_reg(vec dst, vec src) %{ predicate(UseSSE > 2 && n->as_Vector()->length() == 16); match(Set dst (AbsVB src)); format %{ "pabsb $dst,$src\t# $dst = |$src| abs packed16B" %} @@ -9196,7 +9249,7 @@ instruct vabs16B_reg(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vabs32B_reg(vecY dst, vecY src) %{ +instruct vabs32B_reg(vec dst, vec src) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 32); match(Set dst (AbsVB src)); format %{ "vpabsb $dst,$src\t# $dst = |$src| abs packed32B" %} @@ -9207,7 +9260,7 @@ instruct vabs32B_reg(vecY dst, vecY src) %{ ins_pipe( pipe_slow ); %} -instruct vabs64B_reg(vecZ dst, vecZ src) %{ +instruct vabs64B_reg(vec dst, vec src) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 64); match(Set dst (AbsVB src)); format %{ "vpabsb $dst,$src\t# $dst = |$src| abs packed64B" %} @@ -9218,7 +9271,7 @@ instruct vabs64B_reg(vecZ dst, vecZ src) %{ ins_pipe( pipe_slow ); %} -instruct vabs2S_reg(vecD dst, vecD src) %{ +instruct vabs2S_reg(vec dst, vec src) %{ predicate(UseSSE > 2 && n->as_Vector()->length() == 2); match(Set dst (AbsVS src)); format %{ "pabsw $dst,$src\t# $dst = |$src| abs packed2S" %} @@ -9228,7 +9281,7 @@ instruct vabs2S_reg(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vabs4S_reg(vecD dst, vecD src) %{ +instruct vabs4S_reg(vec dst, vec src) %{ predicate(UseSSE > 2 && n->as_Vector()->length() == 4); match(Set dst (AbsVS src)); format %{ "pabsw $dst,$src\t# $dst = |$src| abs packed4S" %} @@ -9238,7 +9291,7 @@ instruct vabs4S_reg(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vabs8S_reg(vecX dst, vecX src) %{ +instruct vabs8S_reg(vec dst, vec src) %{ predicate(UseSSE > 2 && n->as_Vector()->length() == 8); match(Set dst (AbsVS src)); format %{ "pabsw $dst,$src\t# $dst = |$src| abs packed8S" %} @@ -9248,7 +9301,7 @@ instruct vabs8S_reg(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vabs16S_reg(vecY dst, vecY src) %{ +instruct vabs16S_reg(vec dst, vec src) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 16); match(Set dst (AbsVS src)); format %{ "vpabsw $dst,$src\t# $dst = |$src| abs packed16S" %} @@ -9259,7 +9312,7 @@ instruct vabs16S_reg(vecY dst, vecY src) %{ ins_pipe( pipe_slow ); %} -instruct vabs32S_reg(vecZ dst, vecZ src) %{ +instruct vabs32S_reg(vec dst, vec src) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 32); match(Set dst (AbsVS src)); format %{ "vpabsw $dst,$src\t# $dst = |$src| abs packed32S" %} @@ -9270,7 +9323,7 @@ instruct vabs32S_reg(vecZ dst, vecZ src) %{ ins_pipe( pipe_slow ); %} -instruct vabs2I_reg(vecD dst, vecD src) %{ +instruct vabs2I_reg(vec dst, vec src) %{ predicate(UseSSE > 2 && n->as_Vector()->length() == 2); match(Set dst (AbsVI src)); format %{ "pabsd $dst,$src\t# $dst = |$src| abs packed2I" %} @@ -9280,7 +9333,7 @@ instruct vabs2I_reg(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vabs4I_reg(vecX dst, vecX src) %{ +instruct vabs4I_reg(vec dst, vec src) %{ predicate(UseSSE > 2 && n->as_Vector()->length() == 4); match(Set dst (AbsVI src)); format %{ "pabsd $dst,$src\t# $dst = |$src| abs packed4I" %} @@ -9290,7 +9343,7 @@ instruct vabs4I_reg(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vabs8I_reg(vecY dst, vecY src) %{ +instruct vabs8I_reg(vec dst, vec src) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (AbsVI src)); format %{ "vpabsd $dst,$src\t# $dst = |$src| abs packed8I" %} @@ -9301,7 +9354,7 @@ instruct vabs8I_reg(vecY dst, vecY src) %{ ins_pipe( pipe_slow ); %} -instruct vabs16I_reg(vecZ dst, vecZ src) %{ +instruct vabs16I_reg(vec dst, vec src) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (AbsVI src)); format %{ "vpabsd $dst,$src\t# $dst = |$src| abs packed16I" %} @@ -9312,7 +9365,7 @@ instruct vabs16I_reg(vecZ dst, vecZ src) %{ ins_pipe( pipe_slow ); %} -instruct vabs2L_reg(vecX dst, vecX src) %{ +instruct vabs2L_reg(vec dst, vec src) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 2); match(Set dst (AbsVL src)); format %{ "evpabsq $dst,$src\t# $dst = |$src| abs packed2L" %} @@ -9323,7 +9376,7 @@ instruct vabs2L_reg(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vabs4L_reg(vecY dst, vecY src) %{ +instruct vabs4L_reg(vec dst, vec src) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 4); match(Set dst (AbsVL src)); format %{ "evpabsq $dst,$src\t# $dst = |$src| abs packed4L" %} @@ -9334,7 +9387,7 @@ instruct vabs4L_reg(vecY dst, vecY src) %{ ins_pipe( pipe_slow ); %} -instruct vabs8L_reg(vecZ dst, vecZ src) %{ +instruct vabs8L_reg(vec dst, vec src) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (AbsVL src)); format %{ "evpabsq $dst,$src\t# $dst = |$src| abs packed8L" %} @@ -9347,7 +9400,7 @@ instruct vabs8L_reg(vecZ dst, vecZ src) %{ // --------------------------------- ABSNEG -------------------------------------- -instruct vabsneg2D(vecX dst, vecX src, rRegI scratch) %{ +instruct vabsneg2D(vec dst, vec src, rRegI scratch) %{ predicate(UseSSE >= 2 && n->as_Vector()->length() == 2); match(Set dst (AbsVD src)); match(Set dst (NegVD src)); @@ -9362,7 +9415,7 @@ instruct vabsneg2D(vecX dst, vecX src, rRegI scratch) %{ ins_pipe( pipe_slow ); %} -instruct vabsneg4D(vecY dst, vecY src, rRegI scratch) %{ +instruct vabsneg4D(vec dst, vec src, rRegI scratch) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (AbsVD src)); match(Set dst (NegVD src)); @@ -9376,7 +9429,7 @@ instruct vabsneg4D(vecY dst, vecY src, rRegI scratch) %{ ins_pipe( pipe_slow ); %} -instruct vabsneg8D(vecZ dst, vecZ src, rRegI scratch) %{ +instruct vabsneg8D(vec dst, vec src, rRegI scratch) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (AbsVD src)); match(Set dst (NegVD src)); @@ -9390,7 +9443,7 @@ instruct vabsneg8D(vecZ dst, vecZ src, rRegI scratch) %{ ins_pipe( pipe_slow ); %} -instruct vabsneg2F(vecD dst, vecD src, rRegI scratch) %{ +instruct vabsneg2F(vec dst, vec src, rRegI scratch) %{ predicate(UseSSE > 0 && n->as_Vector()->length() == 2); match(Set dst (AbsVF src)); match(Set dst (NegVF src)); @@ -9405,7 +9458,7 @@ instruct vabsneg2F(vecD dst, vecD src, rRegI scratch) %{ ins_pipe( pipe_slow ); %} -instruct vabsneg4F(vecX dst, rRegI scratch) %{ +instruct vabsneg4F(vec dst, rRegI scratch) %{ predicate(UseSSE > 0 && n->as_Vector()->length() == 4); match(Set dst (AbsVF dst)); match(Set dst (NegVF dst)); @@ -9419,7 +9472,7 @@ instruct vabsneg4F(vecX dst, rRegI scratch) %{ ins_pipe( pipe_slow ); %} -instruct vabsneg8F(vecY dst, vecY src, rRegI scratch) %{ +instruct vabsneg8F(vec dst, vec src, rRegI scratch) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 8); match(Set dst (AbsVF src)); match(Set dst (NegVF src)); @@ -9434,7 +9487,7 @@ instruct vabsneg8F(vecY dst, vecY src, rRegI scratch) %{ ins_pipe( pipe_slow ); %} -instruct vabsneg16F(vecZ dst, vecZ src, rRegI scratch) %{ +instruct vabsneg16F(vec dst, vec src, rRegI scratch) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (AbsVF src)); match(Set dst (NegVF src)); @@ -9452,7 +9505,7 @@ instruct vabsneg16F(vecZ dst, vecZ src, rRegI scratch) %{ // --------------------------------- FMA -------------------------------------- // a * b + c -instruct vfma2D_reg(vecX a, vecX b, vecX c) %{ +instruct vfma2D_reg(vec a, vec b, vec c) %{ predicate(UseFMA && n->as_Vector()->length() == 2); match(Set c (FmaVD c (Binary a b))); format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed2D" %} @@ -9465,7 +9518,7 @@ instruct vfma2D_reg(vecX a, vecX b, vecX c) %{ %} // a * b + c -instruct vfma2D_mem(vecX a, memory b, vecX c) %{ +instruct vfma2D_mem(vec a, memory b, vec c) %{ predicate(UseFMA && n->as_Vector()->length() == 2); match(Set c (FmaVD c (Binary a (LoadVector b)))); format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed2D" %} @@ -9479,7 +9532,7 @@ instruct vfma2D_mem(vecX a, memory b, vecX c) %{ // a * b + c -instruct vfma4D_reg(vecY a, vecY b, vecY c) %{ +instruct vfma4D_reg(vec a, vec b, vec c) %{ predicate(UseFMA && n->as_Vector()->length() == 4); match(Set c (FmaVD c (Binary a b))); format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed4D" %} @@ -9492,7 +9545,7 @@ instruct vfma4D_reg(vecY a, vecY b, vecY c) %{ %} // a * b + c -instruct vfma4D_mem(vecY a, memory b, vecY c) %{ +instruct vfma4D_mem(vec a, memory b, vec c) %{ predicate(UseFMA && n->as_Vector()->length() == 4); match(Set c (FmaVD c (Binary a (LoadVector b)))); format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed4D" %} @@ -9505,7 +9558,7 @@ instruct vfma4D_mem(vecY a, memory b, vecY c) %{ %} // a * b + c -instruct vfma8D_reg(vecZ a, vecZ b, vecZ c) %{ +instruct vfma8D_reg(vec a, vec b, vec c) %{ predicate(UseFMA && n->as_Vector()->length() == 8); match(Set c (FmaVD c (Binary a b))); format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed8D" %} @@ -9518,7 +9571,7 @@ instruct vfma8D_reg(vecZ a, vecZ b, vecZ c) %{ %} // a * b + c -instruct vfma8D_mem(vecZ a, memory b, vecZ c) %{ +instruct vfma8D_mem(vec a, memory b, vec c) %{ predicate(UseFMA && n->as_Vector()->length() == 8); match(Set c (FmaVD c (Binary a (LoadVector b)))); format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed8D" %} @@ -9531,7 +9584,7 @@ instruct vfma8D_mem(vecZ a, memory b, vecZ c) %{ %} // a * b + c -instruct vfma4F_reg(vecX a, vecX b, vecX c) %{ +instruct vfma4F_reg(vec a, vec b, vec c) %{ predicate(UseFMA && n->as_Vector()->length() == 4); match(Set c (FmaVF c (Binary a b))); format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed4F" %} @@ -9544,7 +9597,7 @@ instruct vfma4F_reg(vecX a, vecX b, vecX c) %{ %} // a * b + c -instruct vfma4F_mem(vecX a, memory b, vecX c) %{ +instruct vfma4F_mem(vec a, memory b, vec c) %{ predicate(UseFMA && n->as_Vector()->length() == 4); match(Set c (FmaVF c (Binary a (LoadVector b)))); format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed4F" %} @@ -9557,7 +9610,7 @@ instruct vfma4F_mem(vecX a, memory b, vecX c) %{ %} // a * b + c -instruct vfma8F_reg(vecY a, vecY b, vecY c) %{ +instruct vfma8F_reg(vec a, vec b, vec c) %{ predicate(UseFMA && n->as_Vector()->length() == 8); match(Set c (FmaVF c (Binary a b))); format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed8F" %} @@ -9570,7 +9623,7 @@ instruct vfma8F_reg(vecY a, vecY b, vecY c) %{ %} // a * b + c -instruct vfma8F_mem(vecY a, memory b, vecY c) %{ +instruct vfma8F_mem(vec a, memory b, vec c) %{ predicate(UseFMA && n->as_Vector()->length() == 8); match(Set c (FmaVF c (Binary a (LoadVector b)))); format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed8F" %} @@ -9583,7 +9636,7 @@ instruct vfma8F_mem(vecY a, memory b, vecY c) %{ %} // a * b + c -instruct vfma16F_reg(vecZ a, vecZ b, vecZ c) %{ +instruct vfma16F_reg(vec a, vec b, vec c) %{ predicate(UseFMA && n->as_Vector()->length() == 16); match(Set c (FmaVF c (Binary a b))); format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed16F" %} @@ -9596,7 +9649,7 @@ instruct vfma16F_reg(vecZ a, vecZ b, vecZ c) %{ %} // a * b + c -instruct vfma16F_mem(vecZ a, memory b, vecZ c) %{ +instruct vfma16F_mem(vec a, memory b, vec c) %{ predicate(UseFMA && n->as_Vector()->length() == 16); match(Set c (FmaVF c (Binary a (LoadVector b)))); format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed16F" %} @@ -9610,7 +9663,7 @@ instruct vfma16F_mem(vecZ a, memory b, vecZ c) %{ // --------------------------------- Vector Multiply Add -------------------------------------- -instruct smuladd4S2I_reg(vecD dst, vecD src1) %{ +instruct smuladd4S2I_reg(vec dst, vec src1) %{ predicate(UseSSE >= 2 && UseAVX == 0 && n->as_Vector()->length() == 2); match(Set dst (MulAddVS2VI dst src1)); format %{ "pmaddwd $dst,$dst,$src1\t! muladd packed4Sto2I" %} @@ -9620,7 +9673,7 @@ instruct smuladd4S2I_reg(vecD dst, vecD src1) %{ ins_pipe( pipe_slow ); %} -instruct vmuladd4S2I_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vmuladd4S2I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 2); match(Set dst (MulAddVS2VI src1 src2)); format %{ "vpmaddwd $dst,$src1,$src2\t! muladd packed4Sto2I" %} @@ -9631,7 +9684,7 @@ instruct vmuladd4S2I_reg(vecD dst, vecD src1, vecD src2) %{ ins_pipe( pipe_slow ); %} -instruct smuladd8S4I_reg(vecX dst, vecX src1) %{ +instruct smuladd8S4I_reg(vec dst, vec src1) %{ predicate(UseSSE >= 2 && UseAVX == 0 && n->as_Vector()->length() == 4); match(Set dst (MulAddVS2VI dst src1)); format %{ "pmaddwd $dst,$dst,$src1\t! muladd packed8Sto4I" %} @@ -9641,7 +9694,7 @@ instruct smuladd8S4I_reg(vecX dst, vecX src1) %{ ins_pipe( pipe_slow ); %} -instruct vmuladd8S4I_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vmuladd8S4I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 0 && n->as_Vector()->length() == 4); match(Set dst (MulAddVS2VI src1 src2)); format %{ "vpmaddwd $dst,$src1,$src2\t! muladd packed8Sto4I" %} @@ -9652,7 +9705,7 @@ instruct vmuladd8S4I_reg(vecX dst, vecX src1, vecX src2) %{ ins_pipe( pipe_slow ); %} -instruct vmuladd16S8I_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vmuladd16S8I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 8); match(Set dst (MulAddVS2VI src1 src2)); format %{ "vpmaddwd $dst,$src1,$src2\t! muladd packed16Sto8I" %} @@ -9663,7 +9716,7 @@ instruct vmuladd16S8I_reg(vecY dst, vecY src1, vecY src2) %{ ins_pipe( pipe_slow ); %} -instruct vmuladd32S16I_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vmuladd32S16I_reg(vec dst, vec src1, vec src2) %{ predicate(UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (MulAddVS2VI src1 src2)); format %{ "vpmaddwd $dst,$src1,$src2\t! muladd packed32Sto16I" %} @@ -9676,7 +9729,7 @@ instruct vmuladd32S16I_reg(vecZ dst, vecZ src1, vecZ src2) %{ // --------------------------------- Vector Multiply Add Add ---------------------------------- -instruct vmuladdadd4S2I_reg(vecD dst, vecD src1, vecD src2) %{ +instruct vmuladdadd4S2I_reg(vec dst, vec src1, vec src2) %{ predicate(VM_Version::supports_vnni() && UseAVX > 2 && n->as_Vector()->length() == 2); match(Set dst (AddVI (MulAddVS2VI src1 src2) dst)); format %{ "evpdpwssd $dst,$src1,$src2\t! muladdadd packed4Sto2I" %} @@ -9688,7 +9741,7 @@ instruct vmuladdadd4S2I_reg(vecD dst, vecD src1, vecD src2) %{ ins_cost(10); %} -instruct vmuladdadd8S4I_reg(vecX dst, vecX src1, vecX src2) %{ +instruct vmuladdadd8S4I_reg(vec dst, vec src1, vec src2) %{ predicate(VM_Version::supports_vnni() && UseAVX > 2 && n->as_Vector()->length() == 4); match(Set dst (AddVI (MulAddVS2VI src1 src2) dst)); format %{ "evpdpwssd $dst,$src1,$src2\t! muladdadd packed8Sto4I" %} @@ -9700,7 +9753,7 @@ instruct vmuladdadd8S4I_reg(vecX dst, vecX src1, vecX src2) %{ ins_cost(10); %} -instruct vmuladdadd16S8I_reg(vecY dst, vecY src1, vecY src2) %{ +instruct vmuladdadd16S8I_reg(vec dst, vec src1, vec src2) %{ predicate(VM_Version::supports_vnni() && UseAVX > 2 && n->as_Vector()->length() == 8); match(Set dst (AddVI (MulAddVS2VI src1 src2) dst)); format %{ "evpdpwssd $dst,$src1,$src2\t! muladdadd packed16Sto8I" %} @@ -9712,7 +9765,7 @@ instruct vmuladdadd16S8I_reg(vecY dst, vecY src1, vecY src2) %{ ins_cost(10); %} -instruct vmuladdadd32S16I_reg(vecZ dst, vecZ src1, vecZ src2) %{ +instruct vmuladdadd32S16I_reg(vec dst, vec src1, vec src2) %{ predicate(VM_Version::supports_vnni() && UseAVX > 2 && n->as_Vector()->length() == 16); match(Set dst (AddVI (MulAddVS2VI src1 src2) dst)); format %{ "evpdpwssd $dst,$src1,$src2\t! muladdadd packed32Sto16I" %} @@ -9726,7 +9779,7 @@ instruct vmuladdadd32S16I_reg(vecZ dst, vecZ src1, vecZ src2) %{ // --------------------------------- PopCount -------------------------------------- -instruct vpopcount2I(vecD dst, vecD src) %{ +instruct vpopcount2I(vec dst, vec src) %{ predicate(VM_Version::supports_vpopcntdq() && UsePopCountInstruction && n->as_Vector()->length() == 2); match(Set dst (PopCountVI src)); format %{ "vpopcntd $dst,$src\t! vector popcount packed2I" %} @@ -9737,7 +9790,7 @@ instruct vpopcount2I(vecD dst, vecD src) %{ ins_pipe( pipe_slow ); %} -instruct vpopcount4I(vecX dst, vecX src) %{ +instruct vpopcount4I(vec dst, vec src) %{ predicate(VM_Version::supports_vpopcntdq() && UsePopCountInstruction && n->as_Vector()->length() == 4); match(Set dst (PopCountVI src)); format %{ "vpopcntd $dst,$src\t! vector popcount packed4I" %} @@ -9748,7 +9801,7 @@ instruct vpopcount4I(vecX dst, vecX src) %{ ins_pipe( pipe_slow ); %} -instruct vpopcount8I(vecY dst, vecY src) %{ +instruct vpopcount8I(vec dst, vec src) %{ predicate(VM_Version::supports_vpopcntdq() && UsePopCountInstruction && n->as_Vector()->length() == 8); match(Set dst (PopCountVI src)); format %{ "vpopcntd $dst,$src\t! vector popcount packed8I" %} @@ -9759,7 +9812,7 @@ instruct vpopcount8I(vecY dst, vecY src) %{ ins_pipe( pipe_slow ); %} -instruct vpopcount16I(vecZ dst, vecZ src) %{ +instruct vpopcount16I(vec dst, vec src) %{ predicate(VM_Version::supports_vpopcntdq() && UsePopCountInstruction && n->as_Vector()->length() == 16); match(Set dst (PopCountVI src)); format %{ "vpopcntd $dst,$src\t! vector popcount packed16I" %} diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index b1b7611d717..44d0567e87b 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -4130,72 +4130,6 @@ operand vlRegD() %{ interface(REG_INTER); %} -// Vectors : note, we use legacy registers to avoid extra (unneeded in 32-bit VM) -// runtime code generation via reg_class_dynamic. -operand vecS() %{ - constraint(ALLOC_IN_RC(vectors_reg_legacy)); - match(VecS); - - format %{ %} - interface(REG_INTER); -%} - -operand legVecS() %{ - constraint(ALLOC_IN_RC(vectors_reg_legacy)); - match(VecS); - - format %{ %} - interface(REG_INTER); -%} - -operand vecD() %{ - constraint(ALLOC_IN_RC(vectord_reg_legacy)); - match(VecD); - - format %{ %} - interface(REG_INTER); -%} - -operand legVecD() %{ - constraint(ALLOC_IN_RC(vectord_reg_legacy)); - match(VecD); - - format %{ %} - interface(REG_INTER); -%} - -operand vecX() %{ - constraint(ALLOC_IN_RC(vectorx_reg_legacy)); - match(VecX); - - format %{ %} - interface(REG_INTER); -%} - -operand legVecX() %{ - constraint(ALLOC_IN_RC(vectorx_reg_legacy)); - match(VecX); - - format %{ %} - interface(REG_INTER); -%} - -operand vecY() %{ - constraint(ALLOC_IN_RC(vectory_reg_legacy)); - match(VecY); - - format %{ %} - interface(REG_INTER); -%} - -operand legVecY() %{ - constraint(ALLOC_IN_RC(vectory_reg_legacy)); - match(VecY); - - format %{ %} - interface(REG_INTER); -%} - //----------Memory Operands---------------------------------------------------- // Direct Memory Operand operand direct(immP addr) %{ @@ -11795,12 +11729,12 @@ instruct string_equals(eDIRegP str1, eSIRegP str2, eCXRegI cnt, eAXRegI result, // fast search of substring with known size. instruct string_indexof_conL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2, - eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{ + eBXRegI result, regD vec1, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{ predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); - effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); + effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); - format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec1, $cnt1, $cnt2, $tmp" %} ins_encode %{ int icnt2 = (int)$int_cnt2$$constant; if (icnt2 >= 16) { @@ -11809,13 +11743,13 @@ instruct string_indexof_conL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_ __ string_indexofC8($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); + $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); } else { // Small strings are loaded through stack if they cross page boundary. __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); + $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); } %} ins_pipe( pipe_slow ); @@ -11823,12 +11757,12 @@ instruct string_indexof_conL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_ // fast search of substring with known size. instruct string_indexof_conU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2, - eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{ + eBXRegI result, regD vec1, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{ predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); - effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); + effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); - format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec1, $cnt1, $cnt2, $tmp" %} ins_encode %{ int icnt2 = (int)$int_cnt2$$constant; if (icnt2 >= 8) { @@ -11837,13 +11771,13 @@ instruct string_indexof_conU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_ __ string_indexofC8($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); + $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); } else { // Small strings are loaded through stack if they cross page boundary. __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); + $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); } %} ins_pipe( pipe_slow ); @@ -11851,12 +11785,12 @@ instruct string_indexof_conU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_ // fast search of substring with known size. instruct string_indexof_conUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2, - eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{ + eBXRegI result, regD vec1, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{ predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); - effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); + effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); - format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec1, $cnt1, $cnt2, $tmp" %} ins_encode %{ int icnt2 = (int)$int_cnt2$$constant; if (icnt2 >= 8) { @@ -11865,62 +11799,62 @@ instruct string_indexof_conUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int __ string_indexofC8($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); + $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); } else { // Small strings are loaded through stack if they cross page boundary. __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); + $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); } %} ins_pipe( pipe_slow ); %} instruct string_indexofL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2, - eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{ + eBXRegI result, regD vec1, eCXRegI tmp, eFlagsReg cr) %{ predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); - effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); + effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, (-1), $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); + $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); %} ins_pipe( pipe_slow ); %} instruct string_indexofU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2, - eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{ + eBXRegI result, regD vec1, eCXRegI tmp, eFlagsReg cr) %{ predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); - effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); + effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, (-1), $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); + $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); %} ins_pipe( pipe_slow ); %} instruct string_indexofUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2, - eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{ + eBXRegI result, regD vec1, eCXRegI tmp, eFlagsReg cr) %{ predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); - effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); + effect(TEMP vec1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, (-1), $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); + $vec1$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); %} ins_pipe( pipe_slow ); %} diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 805b9e4a0fb..b00bc77977d 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -3720,72 +3720,6 @@ operand vlRegD() %{ interface(REG_INTER); %} -// Vectors -operand vecS() %{ - constraint(ALLOC_IN_RC(vectors_reg_vlbwdq)); - match(VecS); - - format %{ %} - interface(REG_INTER); -%} - -// Vectors -operand legVecS() %{ - constraint(ALLOC_IN_RC(vectors_reg_legacy)); - match(VecS); - - format %{ %} - interface(REG_INTER); -%} - -operand vecD() %{ - constraint(ALLOC_IN_RC(vectord_reg_vlbwdq)); - match(VecD); - - format %{ %} - interface(REG_INTER); -%} - -operand legVecD() %{ - constraint(ALLOC_IN_RC(vectord_reg_legacy)); - match(VecD); - - format %{ %} - interface(REG_INTER); -%} - -operand vecX() %{ - constraint(ALLOC_IN_RC(vectorx_reg_vlbwdq)); - match(VecX); - - format %{ %} - interface(REG_INTER); -%} - -operand legVecX() %{ - constraint(ALLOC_IN_RC(vectorx_reg_legacy)); - match(VecX); - - format %{ %} - interface(REG_INTER); -%} - -operand vecY() %{ - constraint(ALLOC_IN_RC(vectory_reg_vlbwdq)); - match(VecY); - - format %{ %} - interface(REG_INTER); -%} - -operand legVecY() %{ - constraint(ALLOC_IN_RC(vectory_reg_legacy)); - match(VecY); - - format %{ %} - interface(REG_INTER); -%} - //----------Memory Operands---------------------------------------------------- // Direct Memory Operand // operand direct(immP addr) @@ -11224,7 +11158,7 @@ instruct rep_stos_large(rcx_RegL cnt, rdi_RegP base, regD tmp, rax_RegI zero, %} instruct string_compareL(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2, - rax_RegI result, legVecS tmp1, rFlagsReg cr) + rax_RegI result, legRegD tmp1, rFlagsReg cr) %{ predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL); match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); @@ -11240,7 +11174,7 @@ instruct string_compareL(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI c %} instruct string_compareU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2, - rax_RegI result, legVecS tmp1, rFlagsReg cr) + rax_RegI result, legRegD tmp1, rFlagsReg cr) %{ predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU); match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); @@ -11256,7 +11190,7 @@ instruct string_compareU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI c %} instruct string_compareLU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2, - rax_RegI result, legVecS tmp1, rFlagsReg cr) + rax_RegI result, legRegD tmp1, rFlagsReg cr) %{ predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU); match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); @@ -11272,7 +11206,7 @@ instruct string_compareLU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI %} instruct string_compareUL(rsi_RegP str1, rdx_RegI cnt1, rdi_RegP str2, rcx_RegI cnt2, - rax_RegI result, legVecS tmp1, rFlagsReg cr) + rax_RegI result, legRegD tmp1, rFlagsReg cr) %{ predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL); match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); @@ -11289,13 +11223,13 @@ instruct string_compareUL(rsi_RegP str1, rdx_RegI cnt1, rdi_RegP str2, rcx_RegI // fast search of substring with known size. instruct string_indexof_conL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2, - rbx_RegI result, legVecS vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr) + rbx_RegI result, legRegD tmp_vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr) %{ predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); - effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); + effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); - format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $tmp_vec, $cnt1, $cnt2, $tmp" %} ins_encode %{ int icnt2 = (int)$int_cnt2$$constant; if (icnt2 >= 16) { @@ -11304,13 +11238,13 @@ instruct string_indexof_conL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI i __ string_indexofC8($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); + $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); } else { // Small strings are loaded through stack if they cross page boundary. __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); + $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); } %} ins_pipe( pipe_slow ); @@ -11318,13 +11252,13 @@ instruct string_indexof_conL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI i // fast search of substring with known size. instruct string_indexof_conU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2, - rbx_RegI result, legVecS vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr) + rbx_RegI result, legRegD tmp_vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr) %{ predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); - effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); + effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); - format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $tmp_vec, $cnt1, $cnt2, $tmp" %} ins_encode %{ int icnt2 = (int)$int_cnt2$$constant; if (icnt2 >= 8) { @@ -11333,13 +11267,13 @@ instruct string_indexof_conU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI i __ string_indexofC8($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); + $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); } else { // Small strings are loaded through stack if they cross page boundary. __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); + $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); } %} ins_pipe( pipe_slow ); @@ -11347,13 +11281,13 @@ instruct string_indexof_conU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI i // fast search of substring with known size. instruct string_indexof_conUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2, - rbx_RegI result, legVecS vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr) + rbx_RegI result, legRegD tmp_vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr) %{ predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); - effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); + effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); - format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $tmp_vec, $cnt1, $cnt2, $tmp" %} ins_encode %{ int icnt2 = (int)$int_cnt2$$constant; if (icnt2 >= 8) { @@ -11362,86 +11296,86 @@ instruct string_indexof_conUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI __ string_indexofC8($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); + $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); } else { // Small strings are loaded through stack if they cross page boundary. __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, icnt2, $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); + $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); } %} ins_pipe( pipe_slow ); %} instruct string_indexofL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2, - rbx_RegI result, legVecS vec, rcx_RegI tmp, rFlagsReg cr) + rbx_RegI result, legRegD tmp_vec, rcx_RegI tmp, rFlagsReg cr) %{ predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); - effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); + effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, (-1), $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); + $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL); %} ins_pipe( pipe_slow ); %} instruct string_indexofU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2, - rbx_RegI result, legVecS vec, rcx_RegI tmp, rFlagsReg cr) + rbx_RegI result, legRegD tmp_vec, rcx_RegI tmp, rFlagsReg cr) %{ predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); - effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); + effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, (-1), $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); + $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU); %} ins_pipe( pipe_slow ); %} instruct string_indexofUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2, - rbx_RegI result, legVecS vec, rcx_RegI tmp, rFlagsReg cr) + rbx_RegI result, legRegD tmp_vec, rcx_RegI tmp, rFlagsReg cr) %{ predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL)); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); - effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); + effect(TEMP tmp_vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, $cnt1$$Register, $cnt2$$Register, (-1), $result$$Register, - $vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); + $tmp_vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL); %} ins_pipe( pipe_slow ); %} instruct string_indexofU_char(rdi_RegP str1, rdx_RegI cnt1, rax_RegI ch, - rbx_RegI result, legVecS vec1, legVecS vec2, legVecS vec3, rcx_RegI tmp, rFlagsReg cr) + rbx_RegI result, legRegD tmp_vec1, legRegD tmp_vec2, legRegD tmp_vec3, rcx_RegI tmp, rFlagsReg cr) %{ predicate(UseSSE42Intrinsics); match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); - effect(TEMP vec1, TEMP vec2, TEMP vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr); + effect(TEMP tmp_vec1, TEMP tmp_vec2, TEMP tmp_vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr); format %{ "String IndexOf char[] $str1,$cnt1,$ch -> $result // KILL all" %} ins_encode %{ __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register, - $vec1$$XMMRegister, $vec2$$XMMRegister, $vec3$$XMMRegister, $tmp$$Register); + $tmp_vec1$$XMMRegister, $tmp_vec2$$XMMRegister, $tmp_vec3$$XMMRegister, $tmp$$Register); %} ins_pipe( pipe_slow ); %} // fast string equals instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI result, - legVecS tmp1, legVecS tmp2, rbx_RegI tmp3, rFlagsReg cr) + legRegD tmp1, legRegD tmp2, rbx_RegI tmp3, rFlagsReg cr) %{ match(Set result (StrEquals (Binary str1 str2) cnt)); effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr); @@ -11457,7 +11391,7 @@ instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI resu // fast array equals instruct array_equalsB(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result, - legVecS tmp1, legVecS tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr) + legRegD tmp1, legRegD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr) %{ predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); match(Set result (AryEq ary1 ary2)); @@ -11473,7 +11407,7 @@ instruct array_equalsB(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result, %} instruct array_equalsC(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result, - legVecS tmp1, legVecS tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr) + legRegD tmp1, legRegD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr) %{ predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); match(Set result (AryEq ary1 ary2)); @@ -11489,7 +11423,7 @@ instruct array_equalsC(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result, %} instruct has_negatives(rsi_RegP ary1, rcx_RegI len, rax_RegI result, - legVecS tmp1, legVecS tmp2, rbx_RegI tmp3, rFlagsReg cr) + legRegD tmp1, legRegD tmp2, rbx_RegI tmp3, rFlagsReg cr) %{ match(Set result (HasNegatives ary1 len)); effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr); @@ -11504,7 +11438,7 @@ instruct has_negatives(rsi_RegP ary1, rcx_RegI len, rax_RegI result, %} // fast char[] to byte[] compression -instruct string_compress(rsi_RegP src, rdi_RegP dst, rdx_RegI len, legVecS tmp1, legVecS tmp2, legVecS tmp3, legVecS tmp4, +instruct string_compress(rsi_RegP src, rdi_RegP dst, rdx_RegI len, legRegD tmp1, legRegD tmp2, legRegD tmp3, legRegD tmp4, rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{ match(Set result (StrCompressedCopy src (Binary dst len))); effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr); @@ -11520,7 +11454,7 @@ instruct string_compress(rsi_RegP src, rdi_RegP dst, rdx_RegI len, legVecS tmp1, // fast byte[] to char[] inflation instruct string_inflate(Universe dummy, rsi_RegP src, rdi_RegP dst, rdx_RegI len, - legVecS tmp1, rcx_RegI tmp2, rFlagsReg cr) %{ + legRegD tmp1, rcx_RegI tmp2, rFlagsReg cr) %{ match(Set dummy (StrInflatedCopy src (Binary dst len))); effect(TEMP tmp1, TEMP tmp2, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr); @@ -11534,7 +11468,7 @@ instruct string_inflate(Universe dummy, rsi_RegP src, rdi_RegP dst, rdx_RegI len // encode char[] to byte[] in ISO_8859_1 instruct encode_iso_array(rsi_RegP src, rdi_RegP dst, rdx_RegI len, - legVecS tmp1, legVecS tmp2, legVecS tmp3, legVecS tmp4, + legRegD tmp1, legRegD tmp2, legRegD tmp3, legRegD tmp4, rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{ match(Set result (EncodeISOArray src (Binary dst len))); effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr); diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 928d467657b..47f0ba29901 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -1384,6 +1384,8 @@ void os::print_os_info(outputStream* st) { st->print_cr("AIX kernel version %u.%u.%u.%u", (ver >> 24) & 0xFF, (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF); + os::Posix::print_uptime_info(st); + os::Posix::print_rlimit_info(st); os::Posix::print_load_average(st); diff --git a/src/hotspot/os/aix/os_perf_aix.cpp b/src/hotspot/os/aix/os_perf_aix.cpp index deed59e742b..f66c60d1e61 100644 --- a/src/hotspot/os/aix/os_perf_aix.cpp +++ b/src/hotspot/os/aix/os_perf_aix.cpp @@ -28,6 +28,7 @@ #include "os_aix.inline.hpp" #include "runtime/os.hpp" #include "runtime/os_perf.hpp" +#include "utilities/globalDefinitions.hpp" #include CPU_HEADER(vm_version_ext) @@ -884,8 +885,7 @@ class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj= 0) { + time_t bootsec = boottime.tv_sec; + time_t currsec = time(NULL); + os::print_dhm(st, "OS uptime:", (long) difftime(currsec, bootsec)); + } +} + julong os::physical_memory() { return Bsd::physical_memory(); } @@ -1569,6 +1585,8 @@ void os::print_os_info(outputStream* st) { os::Posix::print_uname_info(st); + os::Bsd::print_uptime_info(st); + os::Posix::print_rlimit_info(st); os::Posix::print_load_average(st); @@ -3763,11 +3781,30 @@ int os::fork_and_exec(char* cmd, bool use_vfork_if_available) { } } -// Get the default path to the core file +// Get the kern.corefile setting, or otherwise the default path to the core file // Returns the length of the string int os::get_core_path(char* buffer, size_t bufferSize) { - int n = jio_snprintf(buffer, bufferSize, "/cores/core.%d", current_process_id()); + int n = 0; +#ifdef __APPLE__ + char coreinfo[MAX_PATH]; + size_t sz = sizeof(coreinfo); + int ret = sysctlbyname("kern.corefile", coreinfo, &sz, NULL, 0); + if (ret == 0) { + char *pid_pos = strstr(coreinfo, "%P"); + // skip over the "%P" to preserve any optional custom user pattern + const char* tail = (pid_pos != NULL) ? (pid_pos + 2) : ""; + if (pid_pos != NULL) { + *pid_pos = '\0'; + n = jio_snprintf(buffer, bufferSize, "%s%d%s", coreinfo, os::current_process_id(), tail); + } else { + n = jio_snprintf(buffer, bufferSize, "%s", coreinfo); + } + } else +#endif + { + n = jio_snprintf(buffer, bufferSize, "/cores/core.%d", os::current_process_id()); + } // Truncate if theoretical string was longer than bufferSize n = MIN2(n, (int)bufferSize); diff --git a/src/hotspot/os/bsd/os_bsd.hpp b/src/hotspot/os/bsd/os_bsd.hpp index 590f7423321..c9afcdad10f 100644 --- a/src/hotspot/os/bsd/os_bsd.hpp +++ b/src/hotspot/os/bsd/os_bsd.hpp @@ -155,6 +155,8 @@ class Bsd { } } static int get_node_by_cpu(int cpu_id); + + static void print_uptime_info(outputStream* st); }; #endif // OS_BSD_OS_BSD_HPP diff --git a/src/hotspot/os/bsd/os_perf_bsd.cpp b/src/hotspot/os/bsd/os_perf_bsd.cpp index b0abca58ab1..70abd502d01 100644 --- a/src/hotspot/os/bsd/os_perf_bsd.cpp +++ b/src/hotspot/os/bsd/os_perf_bsd.cpp @@ -26,6 +26,7 @@ #include "memory/resourceArea.hpp" #include "runtime/os.hpp" #include "runtime/os_perf.hpp" +#include "utilities/globalDefinitions.hpp" #include CPU_HEADER(vm_version_ext) #ifdef __APPLE__ @@ -72,8 +73,8 @@ class CPUPerformanceInterface::CPUPerformance : public CHeapObj { int cpu_load_total_process(double* cpu_load); int cpu_loads_process(double* pjvmUserLoad, double* pjvmKernelLoad, double* psystemTotalLoad); - CPUPerformance(const CPUPerformance& rhs); // no impl - CPUPerformance& operator=(const CPUPerformance& rhs); // no impl + NONCOPYABLE(CPUPerformance); + public: CPUPerformance(); bool initialize(); @@ -264,8 +265,7 @@ class SystemProcessInterface::SystemProcesses : public CHeapObj { private: SystemProcesses(); bool initialize(); - SystemProcesses(const SystemProcesses& rhs); // no impl - SystemProcesses& operator=(const SystemProcesses& rhs); // no impl + NONCOPYABLE(SystemProcesses); ~SystemProcesses(); //information about system processes @@ -407,8 +407,7 @@ class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj{ semaphore_t _semaphore; - // Prevent copying and assignment. - OSXSemaphore(const OSXSemaphore&); - OSXSemaphore& operator=(const OSXSemaphore&); + NONCOPYABLE(OSXSemaphore); public: OSXSemaphore(uint value = 0); diff --git a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp index 7268f927ea3..6d0470ffc2b 100644 --- a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp +++ b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp @@ -249,7 +249,7 @@ void ZPhysicalMemoryBacking::pretouch_view(uintptr_t addr, size_t size) const { os::pretouch_memory((void*)addr, (void*)(addr + size), page_size); } -void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const { +void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr) const { const size_t nsegments = pmem.nsegments(); size_t size = 0; @@ -273,11 +273,6 @@ void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t add // NUMA interleave memory before touching it ZNUMA::memory_interleave(addr, size); - - // Pre-touch memory - if (pretouch) { - pretouch_view(addr, size); - } } void ZPhysicalMemoryBacking::unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const { @@ -296,15 +291,27 @@ uintptr_t ZPhysicalMemoryBacking::nmt_address(uintptr_t offset) const { return ZAddress::marked0(offset); } +void ZPhysicalMemoryBacking::pretouch(uintptr_t offset, size_t size) const { + if (ZVerifyViews) { + // Pre-touch good view + pretouch_view(ZAddress::good(offset), size); + } else { + // Pre-touch all views + pretouch_view(ZAddress::marked0(offset), size); + pretouch_view(ZAddress::marked1(offset), size); + pretouch_view(ZAddress::remapped(offset), size); + } +} + void ZPhysicalMemoryBacking::map(const ZPhysicalMemory& pmem, uintptr_t offset) const { if (ZVerifyViews) { // Map good view - map_view(pmem, ZAddress::good(offset), AlwaysPreTouch); + map_view(pmem, ZAddress::good(offset)); } else { // Map all views - map_view(pmem, ZAddress::marked0(offset), AlwaysPreTouch); - map_view(pmem, ZAddress::marked1(offset), AlwaysPreTouch); - map_view(pmem, ZAddress::remapped(offset), AlwaysPreTouch); + map_view(pmem, ZAddress::marked0(offset)); + map_view(pmem, ZAddress::marked1(offset)); + map_view(pmem, ZAddress::remapped(offset)); } } @@ -323,7 +330,7 @@ void ZPhysicalMemoryBacking::unmap(const ZPhysicalMemory& pmem, uintptr_t offset void ZPhysicalMemoryBacking::debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const { // Map good view assert(ZVerifyViews, "Should be enabled"); - map_view(pmem, ZAddress::good(offset), false /* pretouch */); + map_view(pmem, ZAddress::good(offset)); } void ZPhysicalMemoryBacking::debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const { diff --git a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.hpp b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.hpp index 6847d9ac1e0..8fa785aa336 100644 --- a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.hpp +++ b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.hpp @@ -43,7 +43,7 @@ private: void advise_view(uintptr_t addr, size_t size, int advice) const; void pretouch_view(uintptr_t addr, size_t size) const; - void map_view(const ZPhysicalMemory& pmem, uintptr_t addr, bool pretouch) const; + void map_view(const ZPhysicalMemory& pmem, uintptr_t addr) const; void unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const; public: @@ -60,6 +60,8 @@ public: uintptr_t nmt_address(uintptr_t offset) const; + void pretouch(uintptr_t offset, size_t size) const; + void map(const ZPhysicalMemory& pmem, uintptr_t offset) const; void unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const; diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 3ca7497539b..56941bbf1ce 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2119,6 +2119,8 @@ void os::print_os_info(outputStream* st) { os::Posix::print_uname_info(st); + os::Linux::print_uptime_info(st); + // Print warning if unsafe chroot environment detected if (unsafe_chroot_detected) { st->print("WARNING!! "); @@ -2304,6 +2306,15 @@ void os::Linux::print_ld_preload_file(outputStream* st) { st->cr(); } +void os::Linux::print_uptime_info(outputStream* st) { + struct sysinfo sinfo; + int ret = sysinfo(&sinfo); + if (ret == 0) { + os::print_dhm(st, "OS uptime:", (long) sinfo.uptime); + } +} + + void os::Linux::print_container_info(outputStream* st) { if (!OSContainer::is_containerized()) { return; diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp index 20d3ef331a6..798755d6e8d 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -103,6 +103,7 @@ class Linux { static void print_libversion_info(outputStream* st); static void print_proc_sys_info(outputStream* st); static void print_ld_preload_file(outputStream* st); + static void print_uptime_info(outputStream* st); public: struct CPUPerfTicks { diff --git a/src/hotspot/os/linux/os_perf_linux.cpp b/src/hotspot/os/linux/os_perf_linux.cpp index f7e5eef084a..28273615a7c 100644 --- a/src/hotspot/os/linux/os_perf_linux.cpp +++ b/src/hotspot/os/linux/os_perf_linux.cpp @@ -28,6 +28,7 @@ #include "os_linux.inline.hpp" #include "runtime/os.hpp" #include "runtime/os_perf.hpp" +#include "utilities/globalDefinitions.hpp" #include CPU_HEADER(vm_version_ext) @@ -948,8 +949,7 @@ class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj { volatile int _futex_barrier; - // Prevent copying and assignment of LinuxWaitBarrier instances. - LinuxWaitBarrier(const LinuxWaitBarrier&); - LinuxWaitBarrier& operator=(const LinuxWaitBarrier&); + NONCOPYABLE(LinuxWaitBarrier); public: LinuxWaitBarrier() : _futex_barrier(0) {}; diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 4a1f207ef8d..811a9cd2b39 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -49,6 +49,7 @@ #include #include #include +#include // Todo: provide a os::get_max_process_id() or similar. Number of processes // may have been configured, can be read more accurately from proc fs etc. @@ -379,6 +380,27 @@ void os::Posix::print_load_average(outputStream* st) { st->cr(); } +// boot/uptime information; +// unfortunately it does not work on macOS and Linux because the utx chain has no entry +// for reboot at least on my test machines +void os::Posix::print_uptime_info(outputStream* st) { + int bootsec = -1; + int currsec = time(NULL); + struct utmpx* ent; + setutxent(); + while ((ent = getutxent())) { + if (!strcmp("system boot", ent->ut_line)) { + bootsec = ent->ut_tv.tv_sec; + break; + } + } + + if (bootsec != -1) { + os::print_dhm(st, "OS uptime:", (long) (currsec-bootsec)); + } +} + + void os::Posix::print_rlimit_info(outputStream* st) { st->print("rlimit:"); struct rlimit rlim; diff --git a/src/hotspot/os/posix/os_posix.hpp b/src/hotspot/os/posix/os_posix.hpp index d9950765532..e036c98d27c 100644 --- a/src/hotspot/os/posix/os_posix.hpp +++ b/src/hotspot/os/posix/os_posix.hpp @@ -41,6 +41,7 @@ protected: static void print_uname_info(outputStream* st); static void print_libversion_info(outputStream* st); static void print_load_average(outputStream* st); + static void print_uptime_info(outputStream* st); // Minimum stack size a thread can be created with (allowing // the VM to completely create the thread and enter user code). @@ -285,10 +286,8 @@ class PlatformMutex : public CHeapObj { #endif // PLATFORM_MONITOR_IMPL_INDIRECT -private: - // Disable copying - PlatformMutex(const PlatformMutex&); - PlatformMutex& operator=(const PlatformMutex&); + private: + NONCOPYABLE(PlatformMutex); public: void lock(); @@ -329,9 +328,7 @@ class PlatformMonitor : public PlatformMutex { #endif // PLATFORM_MONITOR_IMPL_INDIRECT private: - // Disable copying - PlatformMonitor(const PlatformMonitor&); - PlatformMonitor& operator=(const PlatformMonitor&); + NONCOPYABLE(PlatformMonitor); public: int wait(jlong millis); diff --git a/src/hotspot/os/posix/semaphore_posix.hpp b/src/hotspot/os/posix/semaphore_posix.hpp index 2e408f7a111..1a267e9d0f6 100644 --- a/src/hotspot/os/posix/semaphore_posix.hpp +++ b/src/hotspot/os/posix/semaphore_posix.hpp @@ -26,15 +26,14 @@ #define OS_POSIX_SEMAPHORE_POSIX_HPP #include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" #include class PosixSemaphore : public CHeapObj { sem_t _semaphore; - // Prevent copying and assignment. - PosixSemaphore(const PosixSemaphore&); - PosixSemaphore& operator=(const PosixSemaphore&); + NONCOPYABLE(PosixSemaphore); public: PosixSemaphore(uint value = 0); diff --git a/src/hotspot/os/solaris/os_perf_solaris.cpp b/src/hotspot/os/solaris/os_perf_solaris.cpp index 80b37c2312e..bd33979a335 100644 --- a/src/hotspot/os/solaris/os_perf_solaris.cpp +++ b/src/hotspot/os/solaris/os_perf_solaris.cpp @@ -28,6 +28,7 @@ #include "runtime/os.hpp" #include "runtime/os_perf.hpp" #include "os_solaris.inline.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" #include CPU_HEADER(vm_version_ext) @@ -737,8 +738,7 @@ class NetworkPerformanceInterface::NetworkPerformance : public CHeapObj { // Platform specific implementations that underpin VM Mutex/Monitor classes class PlatformMutex : public CHeapObj { - // Disable copying - PlatformMutex(const PlatformMutex&); - PlatformMutex& operator=(const PlatformMutex&); + NONCOPYABLE(PlatformMutex); protected: mutex_t _mutex; // Native mutex for locking @@ -352,9 +350,8 @@ class PlatformMutex : public CHeapObj { class PlatformMonitor : public PlatformMutex { private: cond_t _cond; // Native condition variable for blocking - // Disable copying - PlatformMonitor(const PlatformMonitor&); - PlatformMonitor& operator=(const PlatformMonitor&); + + NONCOPYABLE(PlatformMonitor); public: PlatformMonitor(); diff --git a/src/hotspot/os/windows/gc/z/zBackingFile_windows.cpp b/src/hotspot/os/windows/gc/z/zBackingFile_windows.cpp new file mode 100644 index 00000000000..899c190bb5a --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zBackingFile_windows.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/z/zBackingFile_windows.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zGranuleMap.inline.hpp" +#include "gc/z/zMapper_windows.hpp" +#include "logging/log.hpp" +#include "runtime/globals.hpp" +#include "utilities/debug.hpp" + +// The backing file commits and uncommits physical memory, that can be +// multi-mapped into the virtual address space. To support fine-graned +// committing and uncommitting, each ZGranuleSize chunked is mapped to +// a separate paging file mapping. + +ZBackingFile::ZBackingFile() : + _handles(MaxHeapSize), + _size(0) {} + +size_t ZBackingFile::size() const { + return _size; +} + +HANDLE ZBackingFile::get_handle(uintptr_t offset) const { + HANDLE const handle = _handles.get(offset); + assert(handle != 0, "Should be set"); + return handle; +} + +void ZBackingFile::put_handle(uintptr_t offset, HANDLE handle) { + assert(handle != INVALID_HANDLE_VALUE, "Invalid handle"); + assert(_handles.get(offset) == 0, "Should be cleared"); + _handles.put(offset, handle); +} + +void ZBackingFile::clear_handle(uintptr_t offset) { + assert(_handles.get(offset) != 0, "Should be set"); + _handles.put(offset, 0); +} + +size_t ZBackingFile::commit_from_paging_file(size_t offset, size_t size) { + for (size_t i = 0; i < size; i += ZGranuleSize) { + HANDLE const handle = ZMapper::create_and_commit_paging_file_mapping(ZGranuleSize); + if (handle == 0) { + return i; + } + + put_handle(offset + i, handle); + } + + return size; +} + +size_t ZBackingFile::uncommit_from_paging_file(size_t offset, size_t size) { + for (size_t i = 0; i < size; i += ZGranuleSize) { + HANDLE const handle = get_handle(offset + i); + clear_handle(offset + i); + ZMapper::close_paging_file_mapping(handle); + } + + return size; +} + +size_t ZBackingFile::commit(size_t offset, size_t length) { + log_trace(gc, heap)("Committing memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)", + offset / M, (offset + length) / M, length / M); + + const size_t committed = commit_from_paging_file(offset, length); + + const size_t end = offset + committed; + if (end > _size) { + // Update size + _size = end; + } + + return committed; +} + +size_t ZBackingFile::uncommit(size_t offset, size_t length) { + log_trace(gc, heap)("Uncommitting memory: " SIZE_FORMAT "M-" SIZE_FORMAT "M (" SIZE_FORMAT "M)", + offset / M, (offset + length) / M, length / M); + + return uncommit_from_paging_file(offset, length); +} + +void ZBackingFile::map(uintptr_t addr, size_t size, size_t offset) const { + assert(is_aligned(offset, ZGranuleSize), "Misaligned"); + assert(is_aligned(addr, ZGranuleSize), "Misaligned"); + assert(is_aligned(size, ZGranuleSize), "Misaligned"); + + for (size_t i = 0; i < size; i += ZGranuleSize) { + HANDLE const handle = get_handle(offset + i); + ZMapper::map_view_replace_placeholder(handle, 0 /* offset */, addr + i, ZGranuleSize); + } +} + +void ZBackingFile::unmap(uintptr_t addr, size_t size) const { + assert(is_aligned(addr, ZGranuleSize), "Misaligned"); + assert(is_aligned(size, ZGranuleSize), "Misaligned"); + + for (size_t i = 0; i < size; i += ZGranuleSize) { + ZMapper::unmap_view_preserve_placeholder(addr + i, ZGranuleSize); + } +} diff --git a/src/hotspot/os/windows/gc/z/zBackingFile_windows.hpp b/src/hotspot/os/windows/gc/z/zBackingFile_windows.hpp new file mode 100644 index 00000000000..514a3f97f44 --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zBackingFile_windows.hpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef OS_WINDOWS_GC_Z_ZBACKINGFILE_WINDOWS_HPP +#define OS_WINDOWS_GC_Z_ZBACKINGFILE_WINDOWS_HPP + +#include "gc/z/zGranuleMap.hpp" +#include "memory/allocation.hpp" + +#include + +class ZBackingFile { +private: + ZGranuleMap _handles; + size_t _size; + + HANDLE get_handle(uintptr_t offset) const; + void put_handle(uintptr_t offset, HANDLE handle); + void clear_handle(uintptr_t offset); + + size_t commit_from_paging_file(size_t offset, size_t size); + size_t uncommit_from_paging_file(size_t offset, size_t size); + +public: + ZBackingFile(); + + size_t size() const; + + size_t commit(size_t offset, size_t length); + size_t uncommit(size_t offset, size_t length); + + void map(uintptr_t addr, size_t size, size_t offset) const; + void unmap(uintptr_t addr, size_t size) const; +}; + +#endif // OS_WINDOWS_GC_Z_ZBACKINGFILE_WINDOWS_HPP diff --git a/src/hotspot/os/windows/gc/z/zInitialize_windows.cpp b/src/hotspot/os/windows/gc/z/zInitialize_windows.cpp new file mode 100644 index 00000000000..c584f79fde4 --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zInitialize_windows.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/z/zInitialize.hpp" +#include "gc/z/zSyscall_windows.hpp" + +void ZInitialize::initialize_os() { + ZSyscall::initialize(); +} diff --git a/src/hotspot/os/windows/gc/z/zLargePages_windows.cpp b/src/hotspot/os/windows/gc/z/zLargePages_windows.cpp new file mode 100644 index 00000000000..231c817952b --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zLargePages_windows.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/z/zLargePages.hpp" + +void ZLargePages::initialize_platform() { + _state = Disabled; +} diff --git a/src/hotspot/os/windows/gc/z/zMapper_windows.cpp b/src/hotspot/os/windows/gc/z/zMapper_windows.cpp new file mode 100644 index 00000000000..d859d4c42c3 --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zMapper_windows.cpp @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/z/zMapper_windows.hpp" +#include "gc/z/zSyscall_windows.hpp" +#include "logging/log.hpp" +#include "utilities/debug.hpp" + +#include + +// Memory reservation, commit, views, and placeholders. +// +// To be able to up-front reserve address space for the heap views, and later +// multi-map the heap views to the same physical memory, without ever losing the +// reservation of the reserved address space, we use "placeholders". +// +// These placeholders block out the address space from being used by other parts +// of the process. To commit memory in this address space, the placeholder must +// be replaced by anonymous memory, or replaced by mapping a view against a +// paging file mapping. We use the later to support multi-mapping. +// +// We want to be able to dynamically commit and uncommit the physical memory of +// the heap (and also unmap ZPages), in granules of ZGranuleSize bytes. There is +// no way to grow and shrink the committed memory of a paging file mapping. +// Therefore, we create multiple granule-sized page file mappings. The memory is +// committed by creating a page file mapping, map a view against it, commit the +// memory, unmap the view. The memory will stay committed until all views are +// unmapped, and the paging file mapping handle is closed. +// +// When replacing a placeholder address space reservation with a mapped view +// against a paging file mapping, the virtual address space must exactly match +// an existing placeholder's address and size. Therefore we only deal with +// granule-sized placeholders at this layer. Higher layers that keep track of +// reserved available address space can (and will) coalesce placeholders, but +// they will be split before being used. + +#define fatal_error(msg, addr, size) \ + fatal(msg ": " PTR_FORMAT " " SIZE_FORMAT "M (%d)", \ + (addr), (size) / M, GetLastError()) + +uintptr_t ZMapper::reserve(uintptr_t addr, size_t size) { + void* const res = ZSyscall::VirtualAlloc2( + GetCurrentProcess(), // Process + (void*)addr, // BaseAddress + size, // Size + MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, // AllocationType + PAGE_NOACCESS, // PageProtection + NULL, // ExtendedParameters + 0 // ParameterCount + ); + + // Caller responsible for error handling + return (uintptr_t)res; +} + +void ZMapper::unreserve(uintptr_t addr, size_t size) { + const bool res = ZSyscall::VirtualFreeEx( + GetCurrentProcess(), // hProcess + (void*)addr, // lpAddress + size, // dwSize + MEM_RELEASE // dwFreeType + ); + + if (!res) { + fatal_error("Failed to unreserve memory", addr, size); + } +} + +HANDLE ZMapper::create_paging_file_mapping(size_t size) { + // Create mapping with SEC_RESERVE instead of SEC_COMMIT. + // + // We use MapViewOfFile3 for two different reasons: + // 1) When commiting memory for the created paging file + // 2) When mapping a view of the memory created in (2) + // + // The non-platform code is only setup to deal with out-of-memory + // errors in (1). By using SEC_RESERVE, we prevent MapViewOfFile3 + // from failing because of "commit limit" checks. To actually commit + // memory in (1), a call to VirtualAlloc2 is done. + + HANDLE const res = ZSyscall::CreateFileMappingW( + INVALID_HANDLE_VALUE, // hFile + NULL, // lpFileMappingAttribute + PAGE_READWRITE | SEC_RESERVE, // flProtect + size >> 32, // dwMaximumSizeHigh + size & 0xFFFFFFFF, // dwMaximumSizeLow + NULL // lpName + ); + + // Caller responsible for error handling + return res; +} + +bool ZMapper::commit_paging_file_mapping(HANDLE file_handle, uintptr_t file_offset, size_t size) { + const uintptr_t addr = map_view_no_placeholder(file_handle, file_offset, size); + if (addr == 0) { + log_error(gc)("Failed to map view of paging file mapping (%d)", GetLastError()); + return false; + } + + const uintptr_t res = commit(addr, size); + if (res != addr) { + log_error(gc)("Failed to commit memory (%d)", GetLastError()); + } + + unmap_view_no_placeholder(addr, size); + + return res == addr; +} + +uintptr_t ZMapper::map_view_no_placeholder(HANDLE file_handle, uintptr_t file_offset, size_t size) { + void* const res = ZSyscall::MapViewOfFile3( + file_handle, // FileMapping + GetCurrentProcess(), // ProcessHandle + NULL, // BaseAddress + file_offset, // Offset + size, // ViewSize + 0, // AllocationType + PAGE_NOACCESS, // PageProtection + NULL, // ExtendedParameters + 0 // ParameterCount + ); + + // Caller responsible for error handling + return (uintptr_t)res; +} + +void ZMapper::unmap_view_no_placeholder(uintptr_t addr, size_t size) { + const bool res = ZSyscall::UnmapViewOfFile2( + GetCurrentProcess(), // ProcessHandle + (void*)addr, // BaseAddress + 0 // UnmapFlags + ); + + if (!res) { + fatal_error("Failed to unmap memory", addr, size); + } +} + +uintptr_t ZMapper::commit(uintptr_t addr, size_t size) { + void* const res = ZSyscall::VirtualAlloc2( + GetCurrentProcess(), // Process + (void*)addr, // BaseAddress + size, // Size + MEM_COMMIT, // AllocationType + PAGE_NOACCESS, // PageProtection + NULL, // ExtendedParameters + 0 // ParameterCount + ); + + // Caller responsible for error handling + return (uintptr_t)res; +} + +HANDLE ZMapper::create_and_commit_paging_file_mapping(size_t size) { + HANDLE const file_handle = create_paging_file_mapping(size); + if (file_handle == 0) { + log_error(gc)("Failed to create paging file mapping (%d)", GetLastError()); + return 0; + } + + const bool res = commit_paging_file_mapping(file_handle, 0 /* file_offset */, size); + if (!res) { + close_paging_file_mapping(file_handle); + return 0; + } + + return file_handle; +} + +void ZMapper::close_paging_file_mapping(HANDLE file_handle) { + const bool res = CloseHandle( + file_handle // hObject + ); + + if (!res) { + fatal("Failed to close paging file handle (%d)", GetLastError()); + } +} + +void ZMapper::split_placeholder(uintptr_t addr, size_t size) { + const bool res = VirtualFree( + (void*)addr, // lpAddress + size, // dwSize + MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER // dwFreeType + ); + + if (!res) { + fatal_error("Failed to split placeholder", addr, size); + } +} + +void ZMapper::coalesce_placeholders(uintptr_t addr, size_t size) { + const bool res = VirtualFree( + (void*)addr, // lpAddress + size, // dwSize + MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS // dwFreeType + ); + + if (!res) { + fatal_error("Failed to coalesce placeholders", addr, size); + } +} + +void ZMapper::map_view_replace_placeholder(HANDLE file_handle, uintptr_t file_offset, uintptr_t addr, size_t size) { + void* const res = ZSyscall::MapViewOfFile3( + file_handle, // FileMapping + GetCurrentProcess(), // ProcessHandle + (void*)addr, // BaseAddress + file_offset, // Offset + size, // ViewSize + MEM_REPLACE_PLACEHOLDER, // AllocationType + PAGE_READWRITE, // PageProtection + NULL, // ExtendedParameters + 0 // ParameterCount + ); + + if (res == NULL) { + fatal_error("Failed to map memory", addr, size); + } +} + +void ZMapper::unmap_view_preserve_placeholder(uintptr_t addr, size_t size) { + const bool res = ZSyscall::UnmapViewOfFile2( + GetCurrentProcess(), // ProcessHandle + (void*)addr, // BaseAddress + MEM_PRESERVE_PLACEHOLDER // UnmapFlags + ); + + if (!res) { + fatal_error("Failed to unmap memory", addr, size); + } +} diff --git a/src/hotspot/os/windows/gc/z/zMapper_windows.hpp b/src/hotspot/os/windows/gc/z/zMapper_windows.hpp new file mode 100644 index 00000000000..005263ad9f4 --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zMapper_windows.hpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef OS_WINDOWS_GC_Z_ZMAPPER_WINDOWS_HPP +#define OS_WINDOWS_GC_Z_ZMAPPER_WINDOWS_HPP + +#include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" + +#include + +class ZMapper : public AllStatic { +private: + // Create paging file mapping + static HANDLE create_paging_file_mapping(size_t size); + + // Commit paging file mapping + static bool commit_paging_file_mapping(HANDLE file_handle, uintptr_t file_offset, size_t size); + + // Map a view anywhere without a placeholder + static uintptr_t map_view_no_placeholder(HANDLE file_handle, uintptr_t file_offset, size_t size); + + // Unmap a view without preserving a placeholder + static void unmap_view_no_placeholder(uintptr_t addr, size_t size); + + // Commit memory covering the given virtual address range + static uintptr_t commit(uintptr_t addr, size_t size); + +public: + // Reserve memory with a placeholder + static uintptr_t reserve(uintptr_t addr, size_t size); + + // Unreserve memory + static void unreserve(uintptr_t addr, size_t size); + + // Create and commit paging file mapping + static HANDLE create_and_commit_paging_file_mapping(size_t size); + + // Close paging file mapping + static void close_paging_file_mapping(HANDLE file_handle); + + // Split a placeholder + // + // A view can only replace an entire placeholder, so placeholders need to be + // split and coalesced to be the exact size of the new views. + // [addr, addr + size) needs to be a proper sub-placeholder of an existing + // placeholder. + static void split_placeholder(uintptr_t addr, size_t size); + + // Coalesce a placeholder + // + // [addr, addr + size) is the new placeholder. A sub-placeholder needs to + // exist within that range. + static void coalesce_placeholders(uintptr_t addr, size_t size); + + // Map a view of the file handle and replace the placeholder covering the + // given virtual address range + static void map_view_replace_placeholder(HANDLE file_handle, uintptr_t file_offset, uintptr_t addr, size_t size); + + // Unmap the view and reinstate a placeholder covering the given virtual + // address range + static void unmap_view_preserve_placeholder(uintptr_t addr, size_t size); +}; + +#endif // OS_WINDOWS_GC_Z_ZMAPPER_WINDOWS_HPP diff --git a/src/hotspot/os/windows/gc/z/zNUMA_windows.cpp b/src/hotspot/os/windows/gc/z/zNUMA_windows.cpp new file mode 100644 index 00000000000..966ef9b997f --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zNUMA_windows.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/z/zNUMA.hpp" + +void ZNUMA::initialize_platform() { + _enabled = false; +} + +uint32_t ZNUMA::count() { + return 1; +} + +uint32_t ZNUMA::id() { + return 0; +} + +uint32_t ZNUMA::memory_id(uintptr_t addr) { + // NUMA support not enabled, assume everything belongs to node zero + return 0; +} diff --git a/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.cpp b/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.cpp new file mode 100644 index 00000000000..b03bce0324e --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.cpp @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/z/zAddress.inline.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zLargePages.inline.hpp" +#include "gc/z/zMapper_windows.hpp" +#include "gc/z/zPhysicalMemory.inline.hpp" +#include "gc/z/zPhysicalMemoryBacking_windows.hpp" +#include "runtime/globals.hpp" +#include "runtime/init.hpp" +#include "runtime/os.hpp" +#include "utilities/align.hpp" +#include "utilities/debug.hpp" + +bool ZPhysicalMemoryBacking::is_initialized() const { + return true; +} + +void ZPhysicalMemoryBacking::warn_commit_limits(size_t max) const { + // Does nothing +} + +bool ZPhysicalMemoryBacking::supports_uncommit() { + assert(!is_init_completed(), "Invalid state"); + assert(_file.size() >= ZGranuleSize, "Invalid size"); + + // Test if uncommit is supported by uncommitting and then re-committing a granule + return commit(uncommit(ZGranuleSize)) == ZGranuleSize; +} + +size_t ZPhysicalMemoryBacking::commit(size_t size) { + size_t committed = 0; + + // Fill holes in the backing file + while (committed < size) { + size_t allocated = 0; + const size_t remaining = size - committed; + const uintptr_t start = _uncommitted.alloc_from_front_at_most(remaining, &allocated); + if (start == UINTPTR_MAX) { + // No holes to commit + break; + } + + // Try commit hole + const size_t filled = _file.commit(start, allocated); + if (filled > 0) { + // Successful or partialy successful + _committed.free(start, filled); + committed += filled; + } + if (filled < allocated) { + // Failed or partialy failed + _uncommitted.free(start + filled, allocated - filled); + return committed; + } + } + + // Expand backing file + if (committed < size) { + const size_t remaining = size - committed; + const uintptr_t start = _file.size(); + const size_t expanded = _file.commit(start, remaining); + if (expanded > 0) { + // Successful or partialy successful + _committed.free(start, expanded); + committed += expanded; + } + } + + return committed; +} + +size_t ZPhysicalMemoryBacking::uncommit(size_t size) { + size_t uncommitted = 0; + + // Punch holes in backing file + while (uncommitted < size) { + size_t allocated = 0; + const size_t remaining = size - uncommitted; + const uintptr_t start = _committed.alloc_from_back_at_most(remaining, &allocated); + assert(start != UINTPTR_MAX, "Allocation should never fail"); + + // Try punch hole + const size_t punched = _file.uncommit(start, allocated); + if (punched > 0) { + // Successful or partialy successful + _uncommitted.free(start, punched); + uncommitted += punched; + } + if (punched < allocated) { + // Failed or partialy failed + _committed.free(start + punched, allocated - punched); + return uncommitted; + } + } + + return uncommitted; +} + +ZPhysicalMemory ZPhysicalMemoryBacking::alloc(size_t size) { + assert(is_aligned(size, ZGranuleSize), "Invalid size"); + + ZPhysicalMemory pmem; + + // Allocate segments + for (size_t allocated = 0; allocated < size; allocated += ZGranuleSize) { + const uintptr_t start = _committed.alloc_from_front(ZGranuleSize); + assert(start != UINTPTR_MAX, "Allocation should never fail"); + pmem.add_segment(ZPhysicalMemorySegment(start, ZGranuleSize)); + } + + return pmem; +} + +void ZPhysicalMemoryBacking::free(const ZPhysicalMemory& pmem) { + const size_t nsegments = pmem.nsegments(); + + // Free segments + for (size_t i = 0; i < nsegments; i++) { + const ZPhysicalMemorySegment& segment = pmem.segment(i); + _committed.free(segment.start(), segment.size()); + } +} + +void ZPhysicalMemoryBacking::pretouch_view(uintptr_t addr, size_t size) const { + const size_t page_size = ZLargePages::is_explicit() ? os::large_page_size() : os::vm_page_size(); + os::pretouch_memory((void*)addr, (void*)(addr + size), page_size); +} + +void ZPhysicalMemoryBacking::map_view(const ZPhysicalMemory& pmem, uintptr_t addr) const { + const size_t nsegments = pmem.nsegments(); + size_t size = 0; + + // Map segments + for (size_t i = 0; i < nsegments; i++) { + const ZPhysicalMemorySegment& segment = pmem.segment(i); + _file.map(addr + size, segment.size(), segment.start()); + size += segment.size(); + } +} + +void ZPhysicalMemoryBacking::unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const { + _file.unmap(addr, pmem.size()); +} + +uintptr_t ZPhysicalMemoryBacking::nmt_address(uintptr_t offset) const { + // From an NMT point of view we treat the first heap view (marked0) as committed + return ZAddress::marked0(offset); +} + +void ZPhysicalMemoryBacking::pretouch(uintptr_t offset, size_t size) const { + if (ZVerifyViews) { + // Pre-touch good view + pretouch_view(ZAddress::good(offset), size); + } else { + // Pre-touch all views + pretouch_view(ZAddress::marked0(offset), size); + pretouch_view(ZAddress::marked1(offset), size); + pretouch_view(ZAddress::remapped(offset), size); + } +} + +void ZPhysicalMemoryBacking::map(const ZPhysicalMemory& pmem, uintptr_t offset) const { + if (ZVerifyViews) { + // Map good view + map_view(pmem, ZAddress::good(offset)); + } else { + // Map all views + map_view(pmem, ZAddress::marked0(offset)); + map_view(pmem, ZAddress::marked1(offset)); + map_view(pmem, ZAddress::remapped(offset)); + } +} + +void ZPhysicalMemoryBacking::unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const { + if (ZVerifyViews) { + // Unmap good view + unmap_view(pmem, ZAddress::good(offset)); + } else { + // Unmap all views + unmap_view(pmem, ZAddress::marked0(offset)); + unmap_view(pmem, ZAddress::marked1(offset)); + unmap_view(pmem, ZAddress::remapped(offset)); + } +} + +void ZPhysicalMemoryBacking::debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const { + // Map good view + assert(ZVerifyViews, "Should be enabled"); + map_view(pmem, ZAddress::good(offset)); +} + +void ZPhysicalMemoryBacking::debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const { + // Unmap good view + assert(ZVerifyViews, "Should be enabled"); + unmap_view(pmem, ZAddress::good(offset)); +} diff --git a/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.hpp b/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.hpp new file mode 100644 index 00000000000..bc7af9caee9 --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zPhysicalMemoryBacking_windows.hpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef OS_WINDOWS_GC_Z_ZPHYSICALMEMORYBACKING_WINDOWS_HPP +#define OS_WINDOWS_GC_Z_ZPHYSICALMEMORYBACKING_WINDOWS_HPP + +#include "gc/z/zBackingFile_windows.hpp" +#include "gc/z/zMemory.hpp" + +class ZPhysicalMemory; + +class ZPhysicalMemoryBacking { +private: + ZBackingFile _file; + ZMemoryManager _committed; + ZMemoryManager _uncommitted; + + void pretouch_view(uintptr_t addr, size_t size) const; + void map_view(const ZPhysicalMemory& pmem, uintptr_t addr) const; + void unmap_view(const ZPhysicalMemory& pmem, uintptr_t addr) const; + +public: + bool is_initialized() const; + + void warn_commit_limits(size_t max) const; + bool supports_uncommit(); + + size_t commit(size_t size); + size_t uncommit(size_t size); + + ZPhysicalMemory alloc(size_t size); + void free(const ZPhysicalMemory& pmem); + + uintptr_t nmt_address(uintptr_t offset) const; + + void pretouch(uintptr_t offset, size_t size) const; + + void map(const ZPhysicalMemory& pmem, uintptr_t offset) const; + void unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const; + + void debug_map(const ZPhysicalMemory& pmem, uintptr_t offset) const; + void debug_unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const; +}; + +#endif // OS_WINDOWS_GC_Z_ZPHYSICALMEMORYBACKING_WINDOWS_HPP diff --git a/src/hotspot/os/windows/gc/z/zSyscall_windows.cpp b/src/hotspot/os/windows/gc/z/zSyscall_windows.cpp new file mode 100644 index 00000000000..b00e45fb962 --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zSyscall_windows.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/z/zSyscall_windows.hpp" +#include "logging/log.hpp" +#include "runtime/java.hpp" +#include "runtime/os.hpp" + +ZSyscall::CreateFileMappingWFn ZSyscall::CreateFileMappingW; +ZSyscall::VirtualAlloc2Fn ZSyscall::VirtualAlloc2; +ZSyscall::VirtualFreeExFn ZSyscall::VirtualFreeEx; +ZSyscall::MapViewOfFile3Fn ZSyscall::MapViewOfFile3; +ZSyscall::UnmapViewOfFile2Fn ZSyscall::UnmapViewOfFile2; + +template +static void lookup_symbol(Fn*& fn, const char* library, const char* symbol) { + char ebuf[1024]; + void* const handle = os::dll_load(library, ebuf, sizeof(ebuf)); + if (handle == NULL) { + log_error(gc)("Failed to load library: %s", library); + vm_exit_during_initialization("ZGC requires Windows version 1803 or later"); + } + + fn = reinterpret_cast(os::dll_lookup(handle, symbol)); + if (fn == NULL) { + log_error(gc)("Failed to lookup symbol: %s", symbol); + vm_exit_during_initialization("ZGC requires Windows version 1803 or later"); + } +} + +void ZSyscall::initialize() { + lookup_symbol(CreateFileMappingW, "KernelBase", "CreateFileMappingW"); + lookup_symbol(VirtualAlloc2, "KernelBase", "VirtualAlloc2"); + lookup_symbol(VirtualFreeEx, "KernelBase", "VirtualFreeEx"); + lookup_symbol(MapViewOfFile3, "KernelBase", "MapViewOfFile3"); + lookup_symbol(UnmapViewOfFile2, "KernelBase", "UnmapViewOfFile2"); +} diff --git a/src/hotspot/os/windows/gc/z/zSyscall_windows.hpp b/src/hotspot/os/windows/gc/z/zSyscall_windows.hpp new file mode 100644 index 00000000000..1fc4f678271 --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zSyscall_windows.hpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef OS_WINDOWS_GC_Z_ZSYSCALL_WINDOWS_HPP +#define OS_WINDOWS_GC_Z_ZSYSCALL_WINDOWS_HPP + +#include "utilities/globalDefinitions.hpp" + +#include +#include + +class ZSyscall { +private: + typedef HANDLE (*CreateFileMappingWFn)(HANDLE, LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD, LPCWSTR); + typedef PVOID (*VirtualAlloc2Fn)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, MEM_EXTENDED_PARAMETER*, ULONG); + typedef BOOL (*VirtualFreeExFn)(HANDLE, LPVOID, SIZE_T, DWORD); + typedef PVOID (*MapViewOfFile3Fn)(HANDLE, HANDLE, PVOID, ULONG64, SIZE_T, ULONG, ULONG, MEM_EXTENDED_PARAMETER*, ULONG); + typedef BOOL (*UnmapViewOfFile2Fn)(HANDLE, PVOID, ULONG); + +public: + static CreateFileMappingWFn CreateFileMappingW; + static VirtualAlloc2Fn VirtualAlloc2; + static VirtualFreeExFn VirtualFreeEx; + static MapViewOfFile3Fn MapViewOfFile3; + static UnmapViewOfFile2Fn UnmapViewOfFile2; + + static void initialize(); +}; + +#endif // OS_WINDOWS_GC_Z_ZSYSCALL_WINDOWS_HPP diff --git a/src/hotspot/os/windows/gc/z/zUtils_windows.cpp b/src/hotspot/os/windows/gc/z/zUtils_windows.cpp new file mode 100644 index 00000000000..633727b6f73 --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zUtils_windows.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/z/zUtils.hpp" +#include "utilities/debug.hpp" + +#include + +uintptr_t ZUtils::alloc_aligned(size_t alignment, size_t size) { + void* const res = _aligned_malloc(size, alignment); + + if (res == NULL) { + fatal("_aligned_malloc failed"); + } + + memset(res, 0, size); + + return (uintptr_t)res; +} diff --git a/src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp b/src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp new file mode 100644 index 00000000000..e54c2ce5373 --- /dev/null +++ b/src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/z/zAddress.inline.hpp" +#include "gc/z/zGlobals.hpp" +#include "gc/z/zMapper_windows.hpp" +#include "gc/z/zVirtualMemory.hpp" +#include "utilities/align.hpp" +#include "utilities/debug.hpp" + +static void split_placeholder(uintptr_t start, size_t size) { + ZMapper::split_placeholder(ZAddress::marked0(start), size); + ZMapper::split_placeholder(ZAddress::marked1(start), size); + ZMapper::split_placeholder(ZAddress::remapped(start), size); +} + +static void coalesce_placeholders(uintptr_t start, size_t size) { + ZMapper::coalesce_placeholders(ZAddress::marked0(start), size); + ZMapper::coalesce_placeholders(ZAddress::marked1(start), size); + ZMapper::coalesce_placeholders(ZAddress::remapped(start), size); +} + +static void split_into_placeholder_granules(uintptr_t start, size_t size) { + for (uintptr_t addr = start; addr < start + size; addr += ZGranuleSize) { + split_placeholder(addr, ZGranuleSize); + } +} + +static void coalesce_into_one_placeholder(uintptr_t start, size_t size) { + assert(is_aligned(size, ZGranuleSize), "Must be granule aligned"); + + if (size > ZGranuleSize) { + coalesce_placeholders(start, size); + } +} + +static void create_callback(const ZMemory* area) { + assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned"); + coalesce_into_one_placeholder(area->start(), area->size()); +} + +static void destroy_callback(const ZMemory* area) { + assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned"); + // Don't try split the last granule - VirtualFree will fail + split_into_placeholder_granules(area->start(), area->size() - ZGranuleSize); +} + +static void shrink_from_front_callback(const ZMemory* area, size_t size) { + assert(is_aligned(size, ZGranuleSize), "Must be granule aligned"); + split_into_placeholder_granules(area->start(), size); +} + +static void shrink_from_back_callback(const ZMemory* area, size_t size) { + assert(is_aligned(size, ZGranuleSize), "Must be granule aligned"); + // Don't try split the last granule - VirtualFree will fail + split_into_placeholder_granules(area->end() - size, size - ZGranuleSize); +} + +static void grow_from_front_callback(const ZMemory* area, size_t size) { + assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned"); + coalesce_into_one_placeholder(area->start() - size, area->size() + size); +} + +static void grow_from_back_callback(const ZMemory* area, size_t size) { + assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned"); + coalesce_into_one_placeholder(area->start(), area->size() + size); +} + +void ZVirtualMemoryManager::initialize_os() { + // Each reserved virtual memory address area registered in _manager is + // exactly covered by a single placeholder. Callbacks are installed so + // that whenever a memory area changes, the corresponding placeholder + // is adjusted. + // + // The create and grow callbacks are called when virtual memory is + // returned to the memory manager. The new memory area is then covered + // by a new single placeholder. + // + // The destroy and shrink callbacks are called when virtual memory is + // allocated from the memory manager. The memory area is then is split + // into granule-sized placeholders. + // + // See comment in zMapper_windows.cpp explaining why placeholders are + // split into ZGranuleSize sized placeholders. + + ZMemoryManager::Callbacks callbacks; + + callbacks._create = &create_callback; + callbacks._destroy = &destroy_callback; + callbacks._shrink_from_front = &shrink_from_front_callback; + callbacks._shrink_from_back = &shrink_from_back_callback; + callbacks._grow_from_front = &grow_from_front_callback; + callbacks._grow_from_back = &grow_from_back_callback; + + _manager.register_callbacks(callbacks); +} + +bool ZVirtualMemoryManager::reserve_contiguous_platform(uintptr_t start, size_t size) { + assert(is_aligned(size, ZGranuleSize), "Must be granule aligned"); + + // Reserve address views + const uintptr_t marked0 = ZAddress::marked0(start); + const uintptr_t marked1 = ZAddress::marked1(start); + const uintptr_t remapped = ZAddress::remapped(start); + + // Reserve address space + if (ZMapper::reserve(marked0, size) != marked0) { + return false; + } + + if (ZMapper::reserve(marked1, size) != marked1) { + ZMapper::unreserve(marked0, size); + return false; + } + + if (ZMapper::reserve(remapped, size) != remapped) { + ZMapper::unreserve(marked0, size); + ZMapper::unreserve(marked1, size); + return false; + } + + // Register address views with native memory tracker + nmt_reserve(marked0, size); + nmt_reserve(marked1, size); + nmt_reserve(remapped, size); + + return true; +} diff --git a/src/hotspot/os/windows/os_perf_windows.cpp b/src/hotspot/os/windows/os_perf_windows.cpp index 3921dc37dd2..9a0e35b0592 100644 --- a/src/hotspot/os/windows/os_perf_windows.cpp +++ b/src/hotspot/os/windows/os_perf_windows.cpp @@ -30,6 +30,7 @@ #include "pdh_interface.hpp" #include "runtime/os_perf.hpp" #include "runtime/os.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" #include CPU_HEADER(vm_version_ext) #include @@ -1355,8 +1356,7 @@ class NetworkPerformanceInterface::NetworkPerformance : public CHeapObjprint("OS:"); os::win32::print_windows_version(st); + os::win32::print_uptime_info(st); + #ifdef _LP64 VM_Version::print_platform_virtualization_info(st); #endif diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index c81daba4efe..e09e2ca2b59 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -55,6 +55,7 @@ class win32 { static bool _has_exit_bug; static void print_windows_version(outputStream* st); + static void print_uptime_info(outputStream* st); public: // Windows-specific interface: @@ -190,9 +191,7 @@ class PlatformParker : public CHeapObj { // Platform specific implementations that underpin VM Mutex/Monitor classes class PlatformMutex : public CHeapObj { - // Disable copying - PlatformMutex(const PlatformMutex&); - PlatformMutex& operator=(const PlatformMutex&); + NONCOPYABLE(PlatformMutex); protected: CRITICAL_SECTION _mutex; // Native mutex for locking @@ -208,9 +207,7 @@ class PlatformMutex : public CHeapObj { class PlatformMonitor : public PlatformMutex { private: CONDITION_VARIABLE _cond; // Native condition variable for blocking - // Disable copying - PlatformMonitor(const PlatformMonitor&); - PlatformMonitor& operator=(const PlatformMonitor&); + NONCOPYABLE(PlatformMonitor); public: PlatformMonitor(); diff --git a/src/hotspot/os/windows/semaphore_windows.hpp b/src/hotspot/os/windows/semaphore_windows.hpp index c72fa52350e..db05d49536d 100644 --- a/src/hotspot/os/windows/semaphore_windows.hpp +++ b/src/hotspot/os/windows/semaphore_windows.hpp @@ -26,15 +26,14 @@ #define OS_WINDOWS_SEMAPHORE_WINDOWS_HPP #include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" #include class WindowsSemaphore : public CHeapObj { HANDLE _semaphore; - // Prevent copying and assignment. - WindowsSemaphore(const WindowsSemaphore&); - WindowsSemaphore& operator=(const WindowsSemaphore&); + NONCOPYABLE(WindowsSemaphore); public: WindowsSemaphore(uint value = 0); diff --git a/src/hotspot/share/adlc/output_h.cpp b/src/hotspot/share/adlc/output_h.cpp index c8e89b14e74..c3a187cf33e 100644 --- a/src/hotspot/share/adlc/output_h.cpp +++ b/src/hotspot/share/adlc/output_h.cpp @@ -1568,6 +1568,8 @@ void ArchDesc::declareClasses(FILE *fp) { fprintf(fp," assert(operand_index < _num_opnds, \"invalid _opnd_array index\");\n"); fprintf(fp," _opnd_array[operand_index] = operand;\n"); fprintf(fp," }\n"); + fprintf(fp," virtual uint rule() const { return %s_rule; }\n", + instr->_ident); fprintf(fp,"private:\n"); if ( instr->is_ideal_jump() ) { fprintf(fp," virtual void add_case_label(int index_num, Label* blockLabel) {\n"); @@ -1579,8 +1581,6 @@ void ArchDesc::declareClasses(FILE *fp) { } out_RegMask(fp); // output register mask - fprintf(fp," virtual uint rule() const { return %s_rule; }\n", - instr->_ident); // If this instruction contains a labelOper // Declare Node::methods that set operand Label's contents diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index 567fd3697e9..2ddf577252b 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -1707,7 +1707,7 @@ void GraphBuilder::access_field(Bytecodes::Code code) { // For CallSite objects add a dependency for invalidation of the optimization. if (field->is_call_site_target()) { ciCallSite* call_site = const_oop->as_call_site(); - if (!call_site->is_constant_call_site()) { + if (!call_site->is_fully_initialized_constant_call_site()) { ciMethodHandle* target = field_value.as_object()->as_method_handle(); dependency_recorder()->assert_call_site_target_value(call_site, target); } @@ -1725,6 +1725,23 @@ void GraphBuilder::access_field(Bytecodes::Code code) { Value replacement = !needs_patching ? _memory->load(load) : load; if (replacement != load) { assert(replacement->is_linked() || !replacement->can_be_linked(), "should already by linked"); + // Writing an (integer) value to a boolean, byte, char or short field includes an implicit narrowing + // conversion. Emit an explicit conversion here to get the correct field value after the write. + BasicType bt = field->type()->basic_type(); + switch (bt) { + case T_BOOLEAN: + case T_BYTE: + replacement = append(new Convert(Bytecodes::_i2b, replacement, as_ValueType(bt))); + break; + case T_CHAR: + replacement = append(new Convert(Bytecodes::_i2c, replacement, as_ValueType(bt))); + break; + case T_SHORT: + replacement = append(new Convert(Bytecodes::_i2s, replacement, as_ValueType(bt))); + break; + default: + break; + } push(type, replacement); } else { push(type, append(load)); diff --git a/src/hotspot/share/ci/ciCallSite.cpp b/src/hotspot/share/ci/ciCallSite.cpp index f3d2ca1071d..8be8c4abeab 100644 --- a/src/hotspot/share/ci/ciCallSite.cpp +++ b/src/hotspot/share/ci/ciCallSite.cpp @@ -29,8 +29,18 @@ // ciCallSite -bool ciCallSite::is_constant_call_site() { - return klass()->is_subclass_of(CURRENT_ENV->ConstantCallSite_klass()); +bool ciCallSite::is_fully_initialized_constant_call_site() { + if (klass()->is_subclass_of(CURRENT_ENV->ConstantCallSite_klass())) { + bool is_fully_initialized = _is_fully_initialized_cache; + if (!is_fully_initialized) { // changes monotonically: false => true + VM_ENTRY_MARK; + is_fully_initialized = (java_lang_invoke_ConstantCallSite::is_frozen(get_oop()) != JNI_FALSE); + _is_fully_initialized_cache = is_fully_initialized; // cache updated value + } + return is_fully_initialized; + } else { + return false; + } } // ------------------------------------------------------------------ diff --git a/src/hotspot/share/ci/ciCallSite.hpp b/src/hotspot/share/ci/ciCallSite.hpp index b7f6a27584e..2204636d02f 100644 --- a/src/hotspot/share/ci/ciCallSite.hpp +++ b/src/hotspot/share/ci/ciCallSite.hpp @@ -31,13 +31,16 @@ // // The class represents a java.lang.invoke.CallSite object. class ciCallSite : public ciInstance { -public: - ciCallSite(instanceHandle h_i) : ciInstance(h_i) {} + private: + bool _is_fully_initialized_cache; + + public: + ciCallSite(instanceHandle h_i) : ciInstance(h_i), _is_fully_initialized_cache(false) {} // What kind of ciObject is this? bool is_call_site() const { return true; } - bool is_constant_call_site(); + bool is_fully_initialized_constant_call_site(); // Return the target MethodHandle of this CallSite. ciMethodHandle* get_target() const; diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 13abc4b23bf..7231e9a0b12 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -55,6 +55,7 @@ #include "oops/metadata.hpp" #include "oops/method.inline.hpp" #include "oops/oop.inline.hpp" +#include "oops/recordComponent.hpp" #include "oops/symbol.hpp" #include "prims/jvmtiExport.hpp" #include "prims/jvmtiThreadState.hpp" @@ -3211,6 +3212,173 @@ u2 ClassFileParser::parse_classfile_nest_members_attribute(const ClassFileStream return length; } +// Record { +// u2 attribute_name_index; +// u4 attribute_length; +// u2 components_count; +// component_info components[components_count]; +// } +// component_info { +// u2 name_index; +// u2 descriptor_index +// u2 attributes_count; +// attribute_info_attributes[attributes_count]; +// } +u2 ClassFileParser::parse_classfile_record_attribute(const ClassFileStream* const cfs, + const ConstantPool* cp, + const u1* const record_attribute_start, + TRAPS) { + const u1* const current_mark = cfs->current(); + int components_count = 0; + unsigned int calculate_attr_size = 0; + if (record_attribute_start != NULL) { + cfs->set_current(record_attribute_start); + cfs->guarantee_more(2, CHECK_0); // num of components + components_count = (int)cfs->get_u2_fast(); + calculate_attr_size = 2; + } + + Array* const record_components = + MetadataFactory::new_array(_loader_data, components_count, NULL, CHECK_0); + _record_components = record_components; + + for (int x = 0; x < components_count; x++) { + cfs->guarantee_more(6, CHECK_0); // name_index, descriptor_index, attributes_count + + const u2 name_index = cfs->get_u2_fast(); + check_property(valid_symbol_at(name_index), + "Invalid constant pool index %u for name in Record attribute in class file %s", + name_index, CHECK_0); + const Symbol* const name = cp->symbol_at(name_index); + verify_legal_field_name(name, CHECK_0); + + const u2 descriptor_index = cfs->get_u2_fast(); + check_property(valid_symbol_at(descriptor_index), + "Invalid constant pool index %u for descriptor in Record attribute in class file %s", + descriptor_index, CHECK_0); + const Symbol* const descr = cp->symbol_at(descriptor_index); + verify_legal_field_signature(name, descr, CHECK_0); + + const u2 attributes_count = cfs->get_u2_fast(); + calculate_attr_size += 6; + u2 generic_sig_index = 0; + const u1* runtime_visible_annotations = NULL; + int runtime_visible_annotations_length = 0; + const u1* runtime_invisible_annotations = NULL; + int runtime_invisible_annotations_length = 0; + bool runtime_invisible_annotations_exists = false; + const u1* runtime_visible_type_annotations = NULL; + int runtime_visible_type_annotations_length = 0; + const u1* runtime_invisible_type_annotations = NULL; + int runtime_invisible_type_annotations_length = 0; + bool runtime_invisible_type_annotations_exists = false; + + // Expected attributes for record components are Signature, Runtime(In)VisibleAnnotations, + // and Runtime(In)VisibleTypeAnnotations. Other attributes are ignored. + for (int y = 0; y < attributes_count; y++) { + cfs->guarantee_more(6, CHECK_0); // attribute_name_index, attribute_length + const u2 attribute_name_index = cfs->get_u2_fast(); + const u4 attribute_length = cfs->get_u4_fast(); + calculate_attr_size += 6; + check_property( + valid_symbol_at(attribute_name_index), + "Invalid Record attribute name index %u in class file %s", + attribute_name_index, CHECK_0); + + const Symbol* const attribute_name = cp->symbol_at(attribute_name_index); + if (attribute_name == vmSymbols::tag_signature()) { + if (generic_sig_index != 0) { + classfile_parse_error( + "Multiple Signature attributes for Record component in class file %s", + CHECK_0); + } + if (attribute_length != 2) { + classfile_parse_error( + "Invalid Signature attribute length %u in Record component in class file %s", + attribute_length, CHECK_0); + } + generic_sig_index = parse_generic_signature_attribute(cfs, CHECK_0); + + } else if (attribute_name == vmSymbols::tag_runtime_visible_annotations()) { + if (runtime_visible_annotations != NULL) { + classfile_parse_error( + "Multiple RuntimeVisibleAnnotations attributes for Record component in class file %s", CHECK_0); + } + runtime_visible_annotations_length = attribute_length; + runtime_visible_annotations = cfs->current(); + + assert(runtime_visible_annotations != NULL, "null record component visible annotation"); + cfs->guarantee_more(runtime_visible_annotations_length, CHECK_0); + cfs->skip_u1_fast(runtime_visible_annotations_length); + + } else if (attribute_name == vmSymbols::tag_runtime_invisible_annotations()) { + if (runtime_invisible_annotations_exists) { + classfile_parse_error( + "Multiple RuntimeInvisibleAnnotations attributes for Record component in class file %s", CHECK_0); + } + runtime_invisible_annotations_exists = true; + if (PreserveAllAnnotations) { + runtime_invisible_annotations_length = attribute_length; + runtime_invisible_annotations = cfs->current(); + assert(runtime_invisible_annotations != NULL, "null record component invisible annotation"); + } + cfs->skip_u1(attribute_length, CHECK_0); + + } else if (attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { + if (runtime_visible_type_annotations != NULL) { + classfile_parse_error( + "Multiple RuntimeVisibleTypeAnnotations attributes for Record component in class file %s", CHECK_0); + } + runtime_visible_type_annotations_length = attribute_length; + runtime_visible_type_annotations = cfs->current(); + + assert(runtime_visible_type_annotations != NULL, "null record component visible type annotation"); + cfs->guarantee_more(runtime_visible_type_annotations_length, CHECK_0); + cfs->skip_u1_fast(runtime_visible_type_annotations_length); + + } else if (attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { + if (runtime_invisible_type_annotations_exists) { + classfile_parse_error( + "Multiple RuntimeInvisibleTypeAnnotations attributes for Record component in class file %s", CHECK_0); + } + runtime_invisible_type_annotations_exists = true; + if (PreserveAllAnnotations) { + runtime_invisible_type_annotations_length = attribute_length; + runtime_invisible_type_annotations = cfs->current(); + assert(runtime_invisible_type_annotations != NULL, "null record component invisible type annotation"); + } + cfs->skip_u1(attribute_length, CHECK_0); + + } else { + // Skip unknown attributes + cfs->skip_u1(attribute_length, CHECK_0); + } + calculate_attr_size += attribute_length; + } // End of attributes For loop + + AnnotationArray* annotations = assemble_annotations(runtime_visible_annotations, + runtime_visible_annotations_length, + runtime_invisible_annotations, + runtime_invisible_annotations_length, + CHECK_0); + AnnotationArray* type_annotations = assemble_annotations(runtime_visible_type_annotations, + runtime_visible_type_annotations_length, + runtime_invisible_type_annotations, + runtime_invisible_type_annotations_length, + CHECK_0); + + RecordComponent* record_component = + RecordComponent::allocate(_loader_data, name_index, descriptor_index, + attributes_count, generic_sig_index, + annotations, type_annotations, CHECK_0); + record_components->at_put(x, record_component); + } // End of component processing loop + + // Restore buffer's current position. + cfs->set_current(current_mark); + return calculate_attr_size; +} + void ClassFileParser::parse_classfile_synthetic_attribute(TRAPS) { set_class_synthetic_flag(true); } @@ -3308,6 +3476,12 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(const ClassFil CHECK); } +bool ClassFileParser::supports_records() { + return _major_version == JAVA_14_VERSION && + _minor_version == JAVA_PREVIEW_MINOR_VERSION && + Arguments::enable_preview(); +} + void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cfs, ConstantPool* cp, ClassFileParser::ClassAnnotationCollector* parsed_annotations, @@ -3326,6 +3500,7 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf bool parsed_innerclasses_attribute = false; bool parsed_nest_members_attribute = false; bool parsed_nest_host_attribute = false; + bool parsed_record_attribute = false; bool parsed_enclosingmethod_attribute = false; bool parsed_bootstrap_methods_attribute = false; const u1* runtime_visible_annotations = NULL; @@ -3345,6 +3520,8 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf u2 enclosing_method_method_index = 0; const u1* nest_members_attribute_start = NULL; u4 nest_members_attribute_length = 0; + const u1* record_attribute_start = NULL; + u4 record_attribute_length = 0; // Iterate over attributes while (attributes_count--) { @@ -3527,6 +3704,38 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf "Nest-host class_info_index %u has bad constant type in class file %s", class_info_index, CHECK); _nest_host = class_info_index; + } else if (_major_version >= JAVA_14_VERSION) { + if (tag == vmSymbols::tag_record()) { + // Skip over Record attribute if not supported or if super class is + // not java.lang.Record. + if (supports_records() && + cp->klass_name_at(_super_class_index) == vmSymbols::java_lang_Record()) { + if (parsed_record_attribute) { + classfile_parse_error("Multiple Record attributes in class file %s", CHECK); + } + // Check that class is final and not abstract. + if (!_access_flags.is_final() || _access_flags.is_abstract()) { + classfile_parse_error("Record attribute in non-final or abstract class file %s", CHECK); + } + parsed_record_attribute = true; + record_attribute_start = cfs->current(); + record_attribute_length = attribute_length; + } else if (log_is_enabled(Info, class, record)) { + // Log why the Record attribute was ignored. Note that if the + // class file version is 58.65535 and --enable-preview wasn't + // specified then a java.lang.UnsupportedClassVersionError + // exception would have been thrown. + ResourceMark rm(THREAD); + log_info(class, record)("Ignoring Record attribute in class %s because %s", + _class_name->as_C_string(), + supports_records() ? "super type is not java.lang.Record" : + "class file version is not 58.65535"); + } + cfs->skip_u1(attribute_length, CHECK); + } else { + // Unknown attribute + cfs->skip_u1(attribute_length, CHECK); + } } else { // Unknown attribute cfs->skip_u1(attribute_length, CHECK); @@ -3578,6 +3787,19 @@ void ClassFileParser::parse_classfile_attributes(const ClassFileStream* const cf } } + if (parsed_record_attribute) { + const unsigned int calculated_attr_length = parse_classfile_record_attribute( + cfs, + cp, + record_attribute_start, + CHECK); + if (_need_verify) { + guarantee_property(record_attribute_length == calculated_attr_length, + "Record attribute has wrong length in class file %s", + CHECK); + } + } + if (_max_bootstrap_specifier_index >= 0) { guarantee_property(parsed_bootstrap_methods_attribute, "Missing BootstrapMethods attribute in class file %s", CHECK); @@ -3632,7 +3854,8 @@ void ClassFileParser::create_combined_annotations(TRAPS) { // Transfer ownership of metadata allocated to the InstanceKlass. void ClassFileParser::apply_parsed_class_metadata( InstanceKlass* this_klass, - int java_fields_count, TRAPS) { + int java_fields_count, + TRAPS) { assert(this_klass != NULL, "invariant"); _cp->set_pool_holder(this_klass); @@ -3644,6 +3867,7 @@ void ClassFileParser::apply_parsed_class_metadata( this_klass->set_nest_host_index(_nest_host); this_klass->set_local_interfaces(_local_interfaces); this_klass->set_annotations(_combined_annotations); + this_klass->set_record_components(_record_components); // Delay the setting of _transitive_interfaces until after initialize_supers() in // fill_instance_klass(). It is because the _transitive_interfaces may be shared with // its _super. If an OOM occurs while loading the current klass, its _super field @@ -4514,6 +4738,7 @@ static Array* compute_transitive_interfaces(const InstanceKlass* static void check_super_class_access(const InstanceKlass* this_klass, TRAPS) { assert(this_klass != NULL, "invariant"); const Klass* const super = this_klass->super(); + if (super != NULL) { // If the loader is not the boot loader then throw an exception if its @@ -4715,12 +4940,13 @@ void ClassFileParser::verify_legal_class_modifiers(jint flags, TRAPS) const { const bool is_super = (flags & JVM_ACC_SUPER) != 0; const bool is_enum = (flags & JVM_ACC_ENUM) != 0; const bool is_annotation = (flags & JVM_ACC_ANNOTATION) != 0; - const bool major_gte_15 = _major_version >= JAVA_1_5_VERSION; + const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION; + const bool major_gte_14 = _major_version >= JAVA_14_VERSION; if ((is_abstract && is_final) || (is_interface && !is_abstract) || - (is_interface && major_gte_15 && (is_super || is_enum)) || - (!is_interface && major_gte_15 && is_annotation)) { + (is_interface && major_gte_1_5 && (is_super || is_enum)) || + (!is_interface && major_gte_1_5 && is_annotation)) { ResourceMark rm(THREAD); Exceptions::fthrow( THREAD_AND_LOCATION, @@ -4816,14 +5042,14 @@ void ClassFileParser::verify_legal_field_modifiers(jint flags, const bool is_volatile = (flags & JVM_ACC_VOLATILE) != 0; const bool is_transient = (flags & JVM_ACC_TRANSIENT) != 0; const bool is_enum = (flags & JVM_ACC_ENUM) != 0; - const bool major_gte_15 = _major_version >= JAVA_1_5_VERSION; + const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION; bool is_illegal = false; if (is_interface) { if (!is_public || !is_static || !is_final || is_private || is_protected || is_volatile || is_transient || - (major_gte_15 && is_enum)) { + (major_gte_1_5 && is_enum)) { is_illegal = true; } } else { // not interface @@ -4859,7 +5085,7 @@ void ClassFileParser::verify_legal_method_modifiers(jint flags, const bool is_strict = (flags & JVM_ACC_STRICT) != 0; const bool is_synchronized = (flags & JVM_ACC_SYNCHRONIZED) != 0; const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0; - const bool major_gte_15 = _major_version >= JAVA_1_5_VERSION; + const bool major_gte_1_5 = _major_version >= JAVA_1_5_VERSION; const bool major_gte_8 = _major_version >= JAVA_8_VERSION; const bool is_initializer = (name == vmSymbols::object_initializer_name()); @@ -4882,7 +5108,7 @@ void ClassFileParser::verify_legal_method_modifiers(jint flags, (is_abstract && (is_private || is_static || is_strict))) { is_illegal = true; } - } else if (major_gte_15) { + } else if (major_gte_1_5) { // Class file version in the interval [JAVA_1_5_VERSION, JAVA_8_VERSION) if (!is_public || is_private || is_protected || is_static || is_final || is_synchronized || is_native || !is_abstract || is_strict) { @@ -4900,13 +5126,13 @@ void ClassFileParser::verify_legal_method_modifiers(jint flags, } else { if (is_initializer) { if (is_static || is_final || is_synchronized || is_native || - is_abstract || (major_gte_15 && is_bridge)) { + is_abstract || (major_gte_1_5 && is_bridge)) { is_illegal = true; } } else { // not initializer if (is_abstract) { if ((is_final || is_native || is_private || is_static || - (major_gte_15 && (is_synchronized || is_strict)))) { + (major_gte_1_5 && (is_synchronized || is_strict)))) { is_illegal = true; } } @@ -5495,6 +5721,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa assert(NULL == _nest_members, "invariant"); assert(NULL == _local_interfaces, "invariant"); assert(NULL == _combined_annotations, "invariant"); + assert(NULL == _record_components, "invariant"); if (_has_final_method) { ik->set_has_final_method(); @@ -5776,6 +6003,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, _inner_classes(NULL), _nest_members(NULL), _nest_host(0), + _record_components(NULL), _local_interfaces(NULL), _transitive_interfaces(NULL), _combined_annotations(NULL), @@ -5886,6 +6114,7 @@ void ClassFileParser::clear_class_metadata() { _combined_annotations = NULL; _class_annotations = _class_type_annotations = NULL; _fields_annotations = _fields_type_annotations = NULL; + _record_components = NULL; } // Destructor to clean up @@ -5913,6 +6142,10 @@ ClassFileParser::~ClassFileParser() { MetadataFactory::free_array(_loader_data, _nest_members); } + if (_record_components != NULL) { + InstanceKlass::deallocate_record_components(_loader_data, _record_components); + } + // Free interfaces InstanceKlass::deallocate_interfaces(_loader_data, _super_klass, _local_interfaces, _transitive_interfaces); diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp index 440c8396fa3..d8cd9a17747 100644 --- a/src/hotspot/share/classfile/classFileParser.hpp +++ b/src/hotspot/share/classfile/classFileParser.hpp @@ -42,6 +42,7 @@ class FieldInfo; template class GrowableArray; class InstanceKlass; +class RecordComponent; class Symbol; class TempNewSymbol; @@ -98,6 +99,7 @@ class ClassFileParser { Array* _inner_classes; Array* _nest_members; u2 _nest_host; + Array* _record_components; Array* _local_interfaces; Array* _transitive_interfaces; Annotations* _combined_annotations; @@ -287,6 +289,13 @@ class ClassFileParser { const u1* const nest_members_attribute_start, TRAPS); + u2 parse_classfile_record_attribute(const ClassFileStream* const cfs, + const ConstantPool* cp, + const u1* const record_attribute_start, + TRAPS); + + bool supports_records(); + void parse_classfile_attributes(const ClassFileStream* const cfs, ConstantPool* cp, ClassAnnotationCollector* parsed_annotations, diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index 8c4f5604c2c..2975159cb6c 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -75,6 +75,8 @@ // Entry point in java.dll for path canonicalization +typedef int (*canonicalize_fn_t)(const char *orig, char *out, int len); + static canonicalize_fn_t CanonicalizeEntry = NULL; // Entry points in zip.dll for loading zip/jar file entries @@ -980,7 +982,7 @@ void ClassLoader::load_java_library() { vm_exit_during_initialization("Unable to load java library", NULL); } - CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, dll_lookup(javalib_handle, "Canonicalize", NULL)); + CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, dll_lookup(javalib_handle, "JDK_Canonicalize", NULL)); } void ClassLoader::load_zip_library() { @@ -1643,13 +1645,12 @@ void ClassLoader::classLoader_init2(TRAPS) { bool ClassLoader::get_canonical_path(const char* orig, char* out, int len) { assert(orig != NULL && out != NULL && len > 0, "bad arguments"); JavaThread* THREAD = JavaThread::current(); - JNIEnv* env = THREAD->jni_environment(); ResourceMark rm(THREAD); // os::native_path writes into orig_copy char* orig_copy = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, strlen(orig)+1); strcpy(orig_copy, orig); - if ((CanonicalizeEntry)(env, os::native_path(orig_copy), out, len) < 0) { + if ((CanonicalizeEntry)(os::native_path(orig_copy), out, len) < 0) { return false; } return true; diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index c0e3a573b72..99ce25575fc 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -50,6 +50,7 @@ #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" +#include "oops/recordComponent.hpp" #include "oops/typeArrayOop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "prims/resolvedMethodTable.hpp" @@ -3148,6 +3149,64 @@ void java_lang_reflect_Field::set_annotations(oop field, oop value) { field->obj_field_put(annotations_offset, value); } +oop java_lang_reflect_RecordComponent::create(InstanceKlass* holder, RecordComponent* component, TRAPS) { + // Allocate java.lang.reflect.RecordComponent instance + HandleMark hm(THREAD); + InstanceKlass* ik = SystemDictionary::RecordComponent_klass(); + assert(ik != NULL, "must be loaded"); + ik->initialize(CHECK_NULL); + + Handle element = ik->allocate_instance_handle(CHECK_NULL); + + Handle decl_class(THREAD, holder->java_mirror()); + java_lang_reflect_RecordComponent::set_clazz(element(), decl_class()); + + Symbol* name = holder->constants()->symbol_at(component->name_index()); // name_index is a utf8 + oop component_name = StringTable::intern(name, CHECK_NULL); + java_lang_reflect_RecordComponent::set_name(element(), component_name); + + Symbol* type = holder->constants()->symbol_at(component->descriptor_index()); + Handle component_type_h = + SystemDictionary::find_java_mirror_for_type(type, holder, SignatureStream::NCDFError, CHECK_NULL); + java_lang_reflect_RecordComponent::set_type(element(), component_type_h()); + + Method* accessor_method = NULL; + { + // Prepend "()" to type to create the full method signature. + ResourceMark rm(THREAD); + int sig_len = type->utf8_length() + 3; // "()" and null char + char* sig = NEW_RESOURCE_ARRAY(char, sig_len); + jio_snprintf(sig, sig_len, "%c%c%s", JVM_SIGNATURE_FUNC, JVM_SIGNATURE_ENDFUNC, type->as_C_string()); + TempNewSymbol full_sig = SymbolTable::new_symbol(sig); + accessor_method = holder->find_instance_method(name, full_sig); + } + + if (accessor_method != NULL) { + methodHandle method(THREAD, accessor_method); + oop m = Reflection::new_method(method, false, CHECK_NULL); + java_lang_reflect_RecordComponent::set_accessor(element(), m); + } else { + java_lang_reflect_RecordComponent::set_accessor(element(), NULL); + } + + int sig_index = component->generic_signature_index(); + if (sig_index > 0) { + Symbol* sig = holder->constants()->symbol_at(sig_index); // sig_index is a utf8 + oop component_sig = StringTable::intern(sig, CHECK_NULL); + java_lang_reflect_RecordComponent::set_signature(element(), component_sig); + } else { + java_lang_reflect_RecordComponent::set_signature(element(), NULL); + } + + typeArrayOop annotation_oop = Annotations::make_java_array(component->annotations(), CHECK_NULL); + java_lang_reflect_RecordComponent::set_annotations(element(), annotation_oop); + + typeArrayOop type_annotation_oop = Annotations::make_java_array(component->type_annotations(), CHECK_NULL); + java_lang_reflect_RecordComponent::set_typeAnnotations(element(), type_annotation_oop); + + return element(); +} + #define CONSTANTPOOL_FIELDS_DO(macro) \ macro(_oop_offset, k, "constantPoolOop", object_signature, false) @@ -3918,6 +3977,24 @@ oop java_lang_invoke_CallSite::context_no_keepalive(oop call_site) { return dep_oop; } +// Support for java_lang_invoke_ConstantCallSite + +int java_lang_invoke_ConstantCallSite::_is_frozen_offset; + +#define CONSTANTCALLSITE_FIELDS_DO(macro) \ + macro(_is_frozen_offset, k, "isFrozen", bool_signature, false) + +void java_lang_invoke_ConstantCallSite::compute_offsets() { + InstanceKlass* k = SystemDictionary::ConstantCallSite_klass(); + CONSTANTCALLSITE_FIELDS_DO(FIELD_COMPUTE_OFFSET); +} + +#if INCLUDE_CDS +void java_lang_invoke_ConstantCallSite::serialize_offsets(SerializeClosure* f) { + CONSTANTCALLSITE_FIELDS_DO(FIELD_SERIALIZE_OFFSET); +} +#endif + // Support for java_lang_invoke_MethodHandleNatives_CallSiteContext int java_lang_invoke_MethodHandleNatives_CallSiteContext::_vmdependencies_offset; @@ -3995,17 +4072,20 @@ int java_lang_ClassLoader::nameAndId_offset = -1; int java_lang_ClassLoader::unnamedModule_offset = -1; ClassLoaderData* java_lang_ClassLoader::loader_data_acquire(oop loader) { - assert(loader != NULL && oopDesc::is_oop(loader), "loader must be oop"); + assert(loader != NULL, "loader must not be NULL"); + assert(oopDesc::is_oop(loader), "loader must be oop"); return HeapAccess::load_at(loader, _loader_data_offset); } ClassLoaderData* java_lang_ClassLoader::loader_data_raw(oop loader) { - assert(loader != NULL && oopDesc::is_oop(loader), "loader must be oop"); + assert(loader != NULL, "loader must not be NULL"); + assert(oopDesc::is_oop(loader), "loader must be oop"); return RawAccess<>::load_at(loader, _loader_data_offset); } void java_lang_ClassLoader::release_set_loader_data(oop loader, ClassLoaderData* new_data) { - assert(loader != NULL && oopDesc::is_oop(loader), "loader must be oop"); + assert(loader != NULL, "loader must not be NULL"); + assert(oopDesc::is_oop(loader), "loader must be oop"); HeapAccess::store_at(loader, _loader_data_offset, new_data); } @@ -4290,6 +4370,13 @@ int java_lang_Short_ShortCache::_static_cache_offset; int java_lang_Byte_ByteCache::_static_cache_offset; int java_lang_Boolean::_static_TRUE_offset; int java_lang_Boolean::_static_FALSE_offset; +int java_lang_reflect_RecordComponent::clazz_offset; +int java_lang_reflect_RecordComponent::name_offset; +int java_lang_reflect_RecordComponent::type_offset; +int java_lang_reflect_RecordComponent::accessor_offset; +int java_lang_reflect_RecordComponent::signature_offset; +int java_lang_reflect_RecordComponent::annotations_offset; +int java_lang_reflect_RecordComponent::typeAnnotations_offset; @@ -4641,6 +4728,55 @@ static int member_offset(int hardcoded_offset) { return (hardcoded_offset * heapOopSize) + instanceOopDesc::base_offset_in_bytes(); } +#define RECORDCOMPONENT_FIELDS_DO(macro) \ + macro(clazz_offset, k, "clazz", class_signature, false); \ + macro(name_offset, k, "name", string_signature, false); \ + macro(type_offset, k, "type", class_signature, false); \ + macro(accessor_offset, k, "accessor", reflect_method_signature, false); \ + macro(signature_offset, k, "signature", string_signature, false); \ + macro(annotations_offset, k, "annotations", byte_array_signature, false); \ + macro(typeAnnotations_offset, k, "typeAnnotations", byte_array_signature, false); + +// Support for java_lang_reflect_RecordComponent +void java_lang_reflect_RecordComponent::compute_offsets() { + InstanceKlass* k = SystemDictionary::RecordComponent_klass(); + RECORDCOMPONENT_FIELDS_DO(FIELD_COMPUTE_OFFSET); +} + +#if INCLUDE_CDS +void java_lang_reflect_RecordComponent::serialize_offsets(SerializeClosure* f) { + RECORDCOMPONENT_FIELDS_DO(FIELD_SERIALIZE_OFFSET); +} +#endif + +void java_lang_reflect_RecordComponent::set_clazz(oop element, oop value) { + element->obj_field_put(clazz_offset, value); +} + +void java_lang_reflect_RecordComponent::set_name(oop element, oop value) { + element->obj_field_put(name_offset, value); +} + +void java_lang_reflect_RecordComponent::set_type(oop element, oop value) { + element->obj_field_put(type_offset, value); +} + +void java_lang_reflect_RecordComponent::set_accessor(oop element, oop value) { + element->obj_field_put(accessor_offset, value); +} + +void java_lang_reflect_RecordComponent::set_signature(oop element, oop value) { + element->obj_field_put(signature_offset, value); +} + +void java_lang_reflect_RecordComponent::set_annotations(oop element, oop value) { + element->obj_field_put(annotations_offset, value); +} + +void java_lang_reflect_RecordComponent::set_typeAnnotations(oop element, oop value) { + element->obj_field_put(typeAnnotations_offset, value); +} + // Compute hard-coded offsets // Invoked before SystemDictionary::initialize, so pre-loaded classes // are not available to determine the offset_of_static_fields. diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index 185e3fdb2ac..27c952e82e2 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -30,6 +30,8 @@ #include "oops/oop.hpp" #include "runtime/os.hpp" +class RecordComponent; + // Interface for manipulating the basic Java classes. // // All dependencies on layout of actual Java classes should be kept here. @@ -66,12 +68,14 @@ f(java_lang_invoke_LambdaForm) \ f(java_lang_invoke_MethodType) \ f(java_lang_invoke_CallSite) \ + f(java_lang_invoke_ConstantCallSite) \ f(java_lang_invoke_MethodHandleNatives_CallSiteContext) \ f(java_security_AccessControlContext) \ f(java_lang_reflect_AccessibleObject) \ f(java_lang_reflect_Method) \ f(java_lang_reflect_Constructor) \ f(java_lang_reflect_Field) \ + f(java_lang_reflect_RecordComponent) \ f(java_nio_Buffer) \ f(reflect_ConstantPool) \ f(reflect_UnsafeStaticFieldAccessorImpl) \ @@ -1226,6 +1230,28 @@ public: static int target_offset_in_bytes() { return _target_offset; } }; +// Interface to java.lang.invoke.ConstantCallSite objects + +class java_lang_invoke_ConstantCallSite: AllStatic { + friend class JavaClasses; + +private: + static int _is_frozen_offset; + + static void compute_offsets(); + +public: + static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; + // Accessors + static jboolean is_frozen(oop site); + + // Testers + static bool is_subclass(Klass* klass) { + return klass->is_subclass_of(SystemDictionary::ConstantCallSite_klass()); + } + static bool is_instance(oop obj); +}; + // Interface to java.lang.invoke.MethodHandleNatives$CallSiteContext objects #define CALLSITECONTEXT_INJECTED_FIELDS(macro) \ @@ -1460,6 +1486,39 @@ class java_lang_LiveStackFrameInfo: AllStatic { friend class JavaClasses; }; +// Interface to java.lang.reflect.RecordComponent objects + +class java_lang_reflect_RecordComponent: AllStatic { + private: + static int clazz_offset; + static int name_offset; + static int type_offset; + static int accessor_offset; + static int signature_offset; + static int annotations_offset; + static int typeAnnotations_offset; + + // Setters + static void set_clazz(oop element, oop value); + static void set_name(oop element, oop value); + static void set_type(oop element, oop value); + static void set_accessor(oop element, oop value); + static void set_signature(oop element, oop value); + static void set_annotations(oop element, oop value); + static void set_typeAnnotations(oop element, oop value); + + public: + // Create an instance of RecordComponent + static oop create(InstanceKlass* holder, RecordComponent* component, TRAPS); + + static void compute_offsets(); + static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; + + // Debugging + friend class JavaClasses; +}; + + // Interface to java.lang.AssertionStatusDirectives objects class java_lang_AssertionStatusDirectives: AllStatic { diff --git a/src/hotspot/share/classfile/javaClasses.inline.hpp b/src/hotspot/share/classfile/javaClasses.inline.hpp index 18176fcfb44..a003943bde4 100644 --- a/src/hotspot/share/classfile/javaClasses.inline.hpp +++ b/src/hotspot/share/classfile/javaClasses.inline.hpp @@ -179,6 +179,14 @@ inline bool java_lang_invoke_CallSite::is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); } +inline jboolean java_lang_invoke_ConstantCallSite::is_frozen(oop site) { + return site->bool_field(_is_frozen_offset); +} + +inline bool java_lang_invoke_ConstantCallSite::is_instance(oop obj) { + return obj != NULL && is_subclass(obj->klass()); +} + inline bool java_lang_invoke_MethodHandleNatives_CallSiteContext::is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); } diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index 52d276d49eb..936a12dc5ee 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -119,6 +119,7 @@ class GCTimer; do_klass(AccessController_klass, java_security_AccessController ) \ do_klass(SecureClassLoader_klass, java_security_SecureClassLoader ) \ do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException ) \ + do_klass(Record_klass, java_lang_Record ) \ do_klass(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError ) \ do_klass(LinkageError_klass, java_lang_LinkageError ) \ do_klass(ClassCastException_klass, java_lang_ClassCastException ) \ @@ -217,6 +218,9 @@ class GCTimer; /* force inline of iterators */ \ do_klass(Iterator_klass, java_util_Iterator ) \ \ + /* support for records */ \ + do_klass(RecordComponent_klass, java_lang_reflect_RecordComponent ) \ + \ /*end*/ class SystemDictionary : AllStatic { diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp index 267ab322137..d1de0bc35de 100644 --- a/src/hotspot/share/classfile/verifier.cpp +++ b/src/hotspot/share/classfile/verifier.cpp @@ -739,7 +739,7 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { StackMapTable stackmap_table(&reader, ¤t_frame, max_locals, max_stack, code_data, code_length, CHECK_VERIFY(this)); - LogTarget(Info, verification) lt; + LogTarget(Debug, verification) lt; if (lt.is_enabled()) { ResourceMark rm(THREAD); LogStream ls(lt); @@ -783,7 +783,7 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { VerificationType type, type2; VerificationType atype; - LogTarget(Info, verification) lt; + LogTarget(Debug, verification) lt; if (lt.is_enabled()) { ResourceMark rm(THREAD); LogStream ls(lt); @@ -2648,9 +2648,9 @@ void ClassVerifier::verify_invoke_init( verify_error(ErrorContext::bad_code(bci), "Bad method call from after the start of a try block"); return; - } else if (log_is_enabled(Info, verification)) { + } else if (log_is_enabled(Debug, verification)) { ResourceMark rm(THREAD); - log_info(verification)("Survived call to ends_in_athrow(): %s", + log_debug(verification)("Survived call to ends_in_athrow(): %s", current_class()->name()->as_C_string()); } } diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index ee4bfd94742..b23aa86d4fe 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -94,6 +94,7 @@ template(java_lang_reflect_Field, "java/lang/reflect/Field") \ template(java_lang_reflect_Parameter, "java/lang/reflect/Parameter") \ template(java_lang_reflect_Array, "java/lang/reflect/Array") \ + template(java_lang_reflect_RecordComponent, "java/lang/reflect/RecordComponent") \ template(java_lang_StringBuffer, "java/lang/StringBuffer") \ template(java_lang_StringBuilder, "java/lang/StringBuilder") \ template(java_lang_CharSequence, "java/lang/CharSequence") \ @@ -127,6 +128,7 @@ template(jdk_internal_vm_PostVMInitHook, "jdk/internal/vm/PostVMInitHook") \ template(sun_net_www_ParseUtil, "sun/net/www/ParseUtil") \ template(java_util_Iterator, "java/util/Iterator") \ + template(java_lang_Record, "java/lang/Record") \ \ template(jdk_internal_loader_ClassLoaders_AppClassLoader, "jdk/internal/loader/ClassLoaders$AppClassLoader") \ template(jdk_internal_loader_ClassLoaders_PlatformClassLoader, "jdk/internal/loader/ClassLoaders$PlatformClassLoader") \ @@ -161,6 +163,7 @@ template(tag_deprecated, "Deprecated") \ template(tag_source_debug_extension, "SourceDebugExtension") \ template(tag_signature, "Signature") \ + template(tag_record, "Record") \ template(tag_runtime_visible_annotations, "RuntimeVisibleAnnotations") \ template(tag_runtime_invisible_annotations, "RuntimeInvisibleAnnotations") \ template(tag_runtime_visible_parameter_annotations, "RuntimeVisibleParameterAnnotations") \ @@ -562,6 +565,7 @@ template(char_StringBuffer_signature, "(C)Ljava/lang/StringBuffer;") \ template(int_String_signature, "(I)Ljava/lang/String;") \ template(boolean_boolean_int_signature, "(ZZ)I") \ + template(reflect_method_signature, "Ljava/lang/reflect/Method;") \ /* signature symbols needed by intrinsics */ \ VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE) \ \ diff --git a/src/hotspot/share/code/codeBlob.hpp b/src/hotspot/share/code/codeBlob.hpp index 08f83cf267f..77c331a7969 100644 --- a/src/hotspot/share/code/codeBlob.hpp +++ b/src/hotspot/share/code/codeBlob.hpp @@ -147,6 +147,7 @@ public: inline bool is_compiled_by_c2() const { return _type == compiler_c2; }; inline bool is_compiled_by_jvmci() const { return _type == compiler_jvmci; }; const char* compiler_name() const; + CompilerType compiler_type() const { return _type; } // Casting nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; } diff --git a/src/hotspot/share/code/compiledMethod.cpp b/src/hotspot/share/code/compiledMethod.cpp index e4bacf31e11..042215d0931 100644 --- a/src/hotspot/share/code/compiledMethod.cpp +++ b/src/hotspot/share/code/compiledMethod.cpp @@ -30,6 +30,7 @@ #include "code/codeCache.hpp" #include "code/icBuffer.hpp" #include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetNMethod.hpp" #include "gc/shared/gcBehaviours.hpp" #include "interpreter/bytecode.inline.hpp" #include "logging/log.hpp" @@ -489,7 +490,20 @@ static bool clean_if_nmethod_is_unloaded(CompiledICorStaticCall *ic, address add if (nm != NULL) { // Clean inline caches pointing to both zombie and not_entrant methods if (clean_all || !nm->is_in_use() || nm->is_unloading() || (nm->method()->code() != nm)) { - if (!ic->set_to_clean(from->is_alive())) { + // Inline cache cleaning should only be initiated on CompiledMethods that have been + // observed to be is_alive(). However, with concurrent code cache unloading, it is + // possible that by now, the state has been racingly flipped to unloaded if the nmethod + // being cleaned is_unloading(). This is fine, because if that happens, then the inline + // caches have already been cleaned under the same CompiledICLocker that we now hold during + // inline cache cleaning, and we will simply walk the inline caches again, and likely not + // find much of interest to clean. However, this race prevents us from asserting that the + // nmethod is_alive(). The is_unloading() function is completely monotonic; once set due + // to an oop dying, it remains set forever until freed. Because of that, all unloaded + // nmethods are is_unloading(), but notably, an unloaded nmethod may also subsequently + // become zombie (when the sweeper converts it to zombie). Therefore, the most precise + // sanity check we can check for in this context is to not allow zombies. + assert(!from->is_zombie(), "should not clean inline caches on zombies"); + if (!ic->set_to_clean(!from->is_unloading())) { return false; } assert(ic->is_clean(), "nmethod " PTR_FORMAT "not clean %s", p2i(from), from->method()->name_and_sig_as_C_string()); @@ -543,6 +557,18 @@ void CompiledMethod::cleanup_inline_caches(bool clean_all) { return; } } + BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); + if (bs_nm != NULL) { + // We want to keep an invariant that nmethods found through iterations of a Thread's + // nmethods found in safepoints have gone through an entry barrier and are not armed. + // By calling this nmethod entry barrier from the sweeper, it plays along and acts + // like any other nmethod found on the stack of a thread (fewer surprises). + nmethod* nm = as_nmethod_or_null(); + if (nm != NULL) { + bool alive = bs_nm->nmethod_entry_barrier(nm); + assert(alive, "should be alive"); + } + } InlineCacheBuffer::refill_ic_stubs(); } } diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 4a4d4065608..4e0ac80731c 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -49,6 +49,7 @@ #include "oops/methodData.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiImpl.hpp" +#include "prims/jvmtiThreadState.hpp" #include "runtime/atomic.hpp" #include "runtime/deoptimization.hpp" #include "runtime/flags/flagSetting.hpp" @@ -58,6 +59,7 @@ #include "runtime/orderAccess.hpp" #include "runtime/os.hpp" #include "runtime/safepointVerifiers.hpp" +#include "runtime/serviceThread.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/sweeper.hpp" #include "runtime/vmThread.hpp" @@ -428,7 +430,8 @@ void nmethod::init_defaults() { _has_flushed_dependencies = 0; _lock_count = 0; _stack_traversal_mark = 0; - _unload_reported = false; // jvmti state + _load_reported = false; // jvmti state + _unload_reported = false; _is_far_code = false; // nmethods are located in CodeCache #ifdef ASSERT @@ -436,7 +439,6 @@ void nmethod::init_defaults() { #endif _oops_do_mark_link = NULL; - _jmethod_id = NULL; _osr_link = NULL; #if INCLUDE_RTM_OPT _rtm_state = NoRTM; @@ -1563,11 +1565,11 @@ void nmethod::flush_dependencies(bool delete_immediately) { // post_compiled_method_load_event // new method for install_code() path // Transfer information from compilation to jvmti -void nmethod::post_compiled_method_load_event() { +void nmethod::post_compiled_method_load_event(JvmtiThreadState* state) { - // This is a bad time for a safepoint. We don't want - // this nmethod to get unloaded while we're queueing the event. - NoSafepointVerifier nsv; + // This is a bad time for a safepoint. We don't want + // this nmethod to get unloaded while we're queueing the event. + NoSafepointVerifier nsv; Method* m = method(); HOTSPOT_COMPILED_METHOD_LOAD( @@ -1579,26 +1581,22 @@ void nmethod::post_compiled_method_load_event() { m->signature()->utf8_length(), insts_begin(), insts_size()); - if (JvmtiExport::should_post_compiled_method_load() || - JvmtiExport::should_post_compiled_method_unload()) { - get_and_cache_jmethod_id(); - } if (JvmtiExport::should_post_compiled_method_load()) { - // Let the Service thread (which is a real Java thread) post the event - MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); - JvmtiDeferredEventQueue::enqueue( - JvmtiDeferredEvent::compiled_method_load_event(this)); - } -} + // Only post unload events if load events are found. + set_load_reported(); + // Keep sweeper from turning this into zombie until it is posted. + mark_as_seen_on_stack(); -jmethodID nmethod::get_and_cache_jmethod_id() { - if (_jmethod_id == NULL) { - // Cache the jmethod_id since it can no longer be looked up once the - // method itself has been marked for unloading. - _jmethod_id = method()->jmethod_id(); + // If a JavaThread hasn't been passed in, let the Service thread + // (which is a real Java thread) post the event + JvmtiDeferredEvent event = JvmtiDeferredEvent::compiled_method_load_event(this); + if (state == NULL) { + ServiceThread::enqueue_deferred_event(&event); + } else { + state->enqueue_event(&event); + } } - return _jmethod_id; } void nmethod::post_compiled_method_unload() { @@ -1614,18 +1612,17 @@ void nmethod::post_compiled_method_unload() { // If a JVMTI agent has enabled the CompiledMethodUnload event then // post the event. Sometime later this nmethod will be made a zombie // by the sweeper but the Method* will not be valid at that point. - // If the _jmethod_id is null then no load event was ever requested - // so don't bother posting the unload. The main reason for this is - // that the jmethodID is a weak reference to the Method* so if + // The jmethodID is a weak reference to the Method* so if // it's being unloaded there's no way to look it up since the weak // ref will have been cleared. - if (_jmethod_id != NULL && JvmtiExport::should_post_compiled_method_unload()) { + + // Don't bother posting the unload if the load event wasn't posted. + if (load_reported() && JvmtiExport::should_post_compiled_method_unload()) { assert(!unload_reported(), "already unloaded"); JvmtiDeferredEvent event = - JvmtiDeferredEvent::compiled_method_unload_event(this, - _jmethod_id, insts_begin()); - MutexLocker ml(Service_lock, Mutex::_no_safepoint_check_flag); - JvmtiDeferredEventQueue::enqueue(event); + JvmtiDeferredEvent::compiled_method_unload_event( + method()->jmethod_id(), insts_begin()); + ServiceThread::enqueue_deferred_event(&event); } // The JVMTI CompiledMethodUnload event can be enabled or disabled at diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 2471424fccf..9caa8d1422d 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -30,6 +30,7 @@ class DepChange; class DirectiveSet; class DebugInformationRecorder; +class JvmtiThreadState; // nmethods (native methods) are the compiled code versions of Java methods. // @@ -71,7 +72,6 @@ class nmethod : public CompiledMethod { private: // Shared fields for all nmethod's int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method - jmethodID _jmethod_id; // Cache of method()->jmethod_id() // To support simple linked-list chaining of nmethods: nmethod* _osr_link; // from InstanceKlass::osr_nmethods_head @@ -227,8 +227,9 @@ class nmethod : public CompiledMethod { // protected by CodeCache_lock bool _has_flushed_dependencies; // Used for maintenance of dependencies (CodeCache_lock) - // used by jvmti to track if an unload event has been posted for this nmethod. + // used by jvmti to track if an event has been posted for this nmethod. bool _unload_reported; + bool _load_reported; // Protected by CompiledMethod_lock volatile signed char _state; // {not_installed, in_use, not_entrant, zombie, unloaded} @@ -482,10 +483,6 @@ class nmethod : public CompiledMethod { bool make_not_used() { return make_not_entrant(); } bool make_zombie() { return make_not_entrant_or_zombie(zombie); } - // used by jvmti to track if the unload event has been reported - bool unload_reported() { return _unload_reported; } - void set_unload_reported() { _unload_reported = true; } - int get_state() const { return _state; } @@ -621,6 +618,12 @@ public: address* orig_pc_addr(const frame* fr); + // used by jvmti to track if the load and unload events has been reported + bool unload_reported() const { return _unload_reported; } + void set_unload_reported() { _unload_reported = true; } + bool load_reported() const { return _load_reported; } + void set_load_reported() { _load_reported = true; } + public: // copying of debugging information void copy_scopes_pcs(PcDesc* pcs, int count); @@ -631,8 +634,7 @@ public: void set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; } // jvmti support: - void post_compiled_method_load_event(); - jmethodID get_and_cache_jmethod_id(); + void post_compiled_method_load_event(JvmtiThreadState* state = NULL); // verify operations void verify(); diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 3d88195939c..ed4b36aa1ff 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -2019,8 +2019,10 @@ void CompileBroker::post_compile(CompilerThread* thread, CompileTask* task, bool static void post_compilation_event(EventCompilation* event, CompileTask* task) { assert(event != NULL, "invariant"); assert(event->should_commit(), "invariant"); - event->set_method(task->method()); + assert(task != NULL, "invariant"); event->set_compileId(task->compile_id()); + event->set_compiler(task->compiler()->type()); + event->set_method(task->method()); event->set_compileLevel(task->comp_level()); event->set_succeded(task->is_success()); event->set_isOsr(task->osr_bci() != CompileBroker::standard_entry_bci); diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 8f78a8419ce..8b8c84771eb 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -55,6 +55,7 @@ #include "include/jvm.h" #include "logging/log.hpp" #include "memory/allocation.hpp" +#include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/access.inline.hpp" diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index f862ec10713..c99df841920 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -45,6 +45,7 @@ class G1ConcurrentMark; class G1OldTracer; class G1RegionToSpaceMapper; class G1SurvivorRegions; +class ThreadClosure; PRAGMA_DIAG_PUSH // warning C4522: multiple assignment operators specified diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp index 2b5153ec094..d502f3522cf 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp @@ -29,6 +29,7 @@ #include "gc/g1/g1DirtyCardQueue.hpp" #include "logging/log.hpp" #include "memory/allocation.inline.hpp" +#include "memory/iterator.hpp" #include "runtime/java.hpp" #include "runtime/thread.hpp" #include "utilities/debug.hpp" diff --git a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp index 6b167400fbd..c7f2c76cf08 100644 --- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp @@ -34,6 +34,7 @@ #include "gc/g1/heapRegionRemSet.hpp" #include "gc/shared/suspendibleThreadSet.hpp" #include "gc/shared/workgroup.hpp" +#include "memory/iterator.hpp" #include "runtime/flags/flagSetting.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/orderAccess.hpp" diff --git a/src/hotspot/share/gc/g1/g1FreeIdSet.hpp b/src/hotspot/share/gc/g1/g1FreeIdSet.hpp index 270a98169f6..3cc7a4ed1af 100644 --- a/src/hotspot/share/gc/g1/g1FreeIdSet.hpp +++ b/src/hotspot/share/gc/g1/g1FreeIdSet.hpp @@ -44,9 +44,7 @@ class G1FreeIdSet { uint head_index(uintx head) const; uintx make_head(uint index, uintx old_head) const; - // Noncopyable. - G1FreeIdSet(const G1FreeIdSet&); - G1FreeIdSet& operator=(const G1FreeIdSet&); + NONCOPYABLE(G1FreeIdSet); public: G1FreeIdSet(uint start, uint size); diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index 30484568474..3b6f8c738c6 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -48,119 +48,91 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) : { assert(max_gc_threads > 0, "Must have some GC threads"); - _gc_par_phases[GCWorkerStart] = new WorkerDataArray(max_gc_threads, "GC Worker Start (ms):"); - _gc_par_phases[ExtRootScan] = new WorkerDataArray(max_gc_threads, "Ext Root Scanning (ms):"); + _gc_par_phases[GCWorkerStart] = new WorkerDataArray("GC Worker Start (ms):", max_gc_threads); + _gc_par_phases[ExtRootScan] = new WorkerDataArray("Ext Root Scanning (ms):", max_gc_threads); // Root scanning phases - _gc_par_phases[ThreadRoots] = new WorkerDataArray(max_gc_threads, "Thread Roots (ms):"); - _gc_par_phases[UniverseRoots] = new WorkerDataArray(max_gc_threads, "Universe Roots (ms):"); - _gc_par_phases[JNIRoots] = new WorkerDataArray(max_gc_threads, "JNI Handles Roots (ms):"); - _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray(max_gc_threads, "ObjectSynchronizer Roots (ms):"); - _gc_par_phases[ManagementRoots] = new WorkerDataArray(max_gc_threads, "Management Roots (ms):"); - _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray(max_gc_threads, "SystemDictionary Roots (ms):"); - _gc_par_phases[CLDGRoots] = new WorkerDataArray(max_gc_threads, "CLDG Roots (ms):"); - _gc_par_phases[JVMTIRoots] = new WorkerDataArray(max_gc_threads, "JVMTI Roots (ms):"); - AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray(max_gc_threads, "AOT Root Scan (ms):");) - _gc_par_phases[CMRefRoots] = new WorkerDataArray(max_gc_threads, "CM RefProcessor Roots (ms):"); + _gc_par_phases[ThreadRoots] = new WorkerDataArray("Thread Roots (ms):", max_gc_threads); + _gc_par_phases[UniverseRoots] = new WorkerDataArray("Universe Roots (ms):", max_gc_threads); + _gc_par_phases[JNIRoots] = new WorkerDataArray("JNI Handles Roots (ms):", max_gc_threads); + _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray("ObjectSynchronizer Roots (ms):", max_gc_threads); + _gc_par_phases[ManagementRoots] = new WorkerDataArray("Management Roots (ms):", max_gc_threads); + _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray("SystemDictionary Roots (ms):", max_gc_threads); + _gc_par_phases[CLDGRoots] = new WorkerDataArray("CLDG Roots (ms):", max_gc_threads); + _gc_par_phases[JVMTIRoots] = new WorkerDataArray("JVMTI Roots (ms):", max_gc_threads); + AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray("AOT Root Scan (ms):", max_gc_threads);) + _gc_par_phases[CMRefRoots] = new WorkerDataArray("CM RefProcessor Roots (ms):", max_gc_threads); - _gc_par_phases[MergeER] = new WorkerDataArray(max_gc_threads, "Eager Reclaim (ms):"); + _gc_par_phases[MergeER] = new WorkerDataArray("Eager Reclaim (ms):", max_gc_threads); - _gc_par_phases[MergeRS] = new WorkerDataArray(max_gc_threads, "Remembered Sets (ms):"); - _merge_rs_merged_sparse = new WorkerDataArray(max_gc_threads, "Merged Sparse:"); - _gc_par_phases[MergeRS]->link_thread_work_items(_merge_rs_merged_sparse, MergeRSMergedSparse); - _merge_rs_merged_fine = new WorkerDataArray(max_gc_threads, "Merged Fine:"); - _gc_par_phases[MergeRS]->link_thread_work_items(_merge_rs_merged_fine, MergeRSMergedFine); - _merge_rs_merged_coarse = new WorkerDataArray(max_gc_threads, "Merged Coarse:"); - _gc_par_phases[MergeRS]->link_thread_work_items(_merge_rs_merged_coarse, MergeRSMergedCoarse); - _merge_rs_dirty_cards = new WorkerDataArray(max_gc_threads, "Dirty Cards:"); - _gc_par_phases[MergeRS]->link_thread_work_items(_merge_rs_dirty_cards, MergeRSDirtyCards); + _gc_par_phases[MergeRS] = new WorkerDataArray("Remembered Sets (ms):", max_gc_threads); + _gc_par_phases[MergeRS]->create_thread_work_items("Merged Sparse:", MergeRSMergedSparse); + _gc_par_phases[MergeRS]->create_thread_work_items("Merged Fine:", MergeRSMergedFine); + _gc_par_phases[MergeRS]->create_thread_work_items("Merged Coarse:", MergeRSMergedCoarse); + _gc_par_phases[MergeRS]->create_thread_work_items("Dirty Cards:", MergeRSDirtyCards); - _gc_par_phases[OptMergeRS] = new WorkerDataArray(max_gc_threads, "Optional Remembered Sets (ms):"); - _opt_merge_rs_merged_sparse = new WorkerDataArray(max_gc_threads, "Merged Sparse:"); - _gc_par_phases[OptMergeRS]->link_thread_work_items(_opt_merge_rs_merged_sparse, MergeRSMergedSparse); - _opt_merge_rs_merged_fine = new WorkerDataArray(max_gc_threads, "Merged Fine:"); - _gc_par_phases[OptMergeRS]->link_thread_work_items(_opt_merge_rs_merged_fine, MergeRSMergedFine); - _opt_merge_rs_merged_coarse = new WorkerDataArray(max_gc_threads, "Merged Coarse:"); - _gc_par_phases[OptMergeRS]->link_thread_work_items(_opt_merge_rs_merged_coarse, MergeRSMergedCoarse); - _opt_merge_rs_dirty_cards = new WorkerDataArray(max_gc_threads, "Dirty Cards:"); - _gc_par_phases[OptMergeRS]->link_thread_work_items(_opt_merge_rs_dirty_cards, MergeRSDirtyCards); + _gc_par_phases[OptMergeRS] = new WorkerDataArray("Optional Remembered Sets (ms):", max_gc_threads); + _gc_par_phases[OptMergeRS]->create_thread_work_items("Merged Sparse:", MergeRSMergedSparse); + _gc_par_phases[OptMergeRS]->create_thread_work_items("Merged Fine:", MergeRSMergedFine); + _gc_par_phases[OptMergeRS]->create_thread_work_items("Merged Coarse:", MergeRSMergedCoarse); + _gc_par_phases[OptMergeRS]->create_thread_work_items("Dirty Cards:", MergeRSDirtyCards); - _gc_par_phases[MergeLB] = new WorkerDataArray(max_gc_threads, "Log Buffers (ms):"); + _gc_par_phases[MergeLB] = new WorkerDataArray("Log Buffers (ms):", max_gc_threads); if (G1HotCardCache::default_use_cache()) { - _gc_par_phases[MergeHCC] = new WorkerDataArray(max_gc_threads, "Hot Card Cache (ms):"); - _merge_hcc_dirty_cards = new WorkerDataArray(max_gc_threads, "Dirty Cards:"); - _gc_par_phases[MergeHCC]->link_thread_work_items(_merge_hcc_dirty_cards, MergeHCCDirtyCards); - _merge_hcc_skipped_cards = new WorkerDataArray(max_gc_threads, "Skipped Cards:"); - _gc_par_phases[MergeHCC]->link_thread_work_items(_merge_hcc_skipped_cards, MergeHCCSkippedCards); + _gc_par_phases[MergeHCC] = new WorkerDataArray("Hot Card Cache (ms):", max_gc_threads); + _gc_par_phases[MergeHCC]->create_thread_work_items("Dirty Cards:", MergeHCCDirtyCards); + _gc_par_phases[MergeHCC]->create_thread_work_items("Skipped Cards:", MergeHCCSkippedCards); } else { _gc_par_phases[MergeHCC] = NULL; - _merge_hcc_dirty_cards = NULL; - _merge_hcc_skipped_cards = NULL; } - _gc_par_phases[ScanHR] = new WorkerDataArray(max_gc_threads, "Scan Heap Roots (ms):"); - _gc_par_phases[OptScanHR] = new WorkerDataArray(max_gc_threads, "Optional Scan Heap Roots (ms):"); - _gc_par_phases[CodeRoots] = new WorkerDataArray(max_gc_threads, "Code Root Scan (ms):"); - _gc_par_phases[OptCodeRoots] = new WorkerDataArray(max_gc_threads, "Optional Code Root Scan (ms):"); - _gc_par_phases[ObjCopy] = new WorkerDataArray(max_gc_threads, "Object Copy (ms):"); - _gc_par_phases[OptObjCopy] = new WorkerDataArray(max_gc_threads, "Optional Object Copy (ms):"); - _gc_par_phases[Termination] = new WorkerDataArray(max_gc_threads, "Termination (ms):"); - _gc_par_phases[OptTermination] = new WorkerDataArray(max_gc_threads, "Optional Termination (ms):"); - _gc_par_phases[GCWorkerTotal] = new WorkerDataArray(max_gc_threads, "GC Worker Total (ms):"); - _gc_par_phases[GCWorkerEnd] = new WorkerDataArray(max_gc_threads, "GC Worker End (ms):"); - _gc_par_phases[Other] = new WorkerDataArray(max_gc_threads, "GC Worker Other (ms):"); + _gc_par_phases[ScanHR] = new WorkerDataArray("Scan Heap Roots (ms):", max_gc_threads); + _gc_par_phases[OptScanHR] = new WorkerDataArray("Optional Scan Heap Roots (ms):", max_gc_threads); + _gc_par_phases[CodeRoots] = new WorkerDataArray("Code Root Scan (ms):", max_gc_threads); + _gc_par_phases[OptCodeRoots] = new WorkerDataArray("Optional Code Root Scan (ms):", max_gc_threads); + _gc_par_phases[ObjCopy] = new WorkerDataArray("Object Copy (ms):", max_gc_threads); + _gc_par_phases[OptObjCopy] = new WorkerDataArray("Optional Object Copy (ms):", max_gc_threads); + _gc_par_phases[Termination] = new WorkerDataArray("Termination (ms):", max_gc_threads); + _gc_par_phases[OptTermination] = new WorkerDataArray("Optional Termination (ms):", max_gc_threads); + _gc_par_phases[GCWorkerTotal] = new WorkerDataArray("GC Worker Total (ms):", max_gc_threads); + _gc_par_phases[GCWorkerEnd] = new WorkerDataArray("GC Worker End (ms):", max_gc_threads); + _gc_par_phases[Other] = new WorkerDataArray("GC Worker Other (ms):", max_gc_threads); - _scan_hr_scanned_cards = new WorkerDataArray(max_gc_threads, "Scanned Cards:"); - _gc_par_phases[ScanHR]->link_thread_work_items(_scan_hr_scanned_cards, ScanHRScannedCards); - _scan_hr_scanned_blocks = new WorkerDataArray(max_gc_threads, "Scanned Blocks:"); - _gc_par_phases[ScanHR]->link_thread_work_items(_scan_hr_scanned_blocks, ScanHRScannedBlocks); - _scan_hr_claimed_chunks = new WorkerDataArray(max_gc_threads, "Claimed Chunks:"); - _gc_par_phases[ScanHR]->link_thread_work_items(_scan_hr_claimed_chunks, ScanHRClaimedChunks); + _gc_par_phases[ScanHR]->create_thread_work_items("Scanned Cards:", ScanHRScannedCards); + _gc_par_phases[ScanHR]->create_thread_work_items("Scanned Blocks:", ScanHRScannedBlocks); + _gc_par_phases[ScanHR]->create_thread_work_items("Claimed Chunks:", ScanHRClaimedChunks); - _opt_scan_hr_scanned_cards = new WorkerDataArray(max_gc_threads, "Scanned Cards:"); - _gc_par_phases[OptScanHR]->link_thread_work_items(_opt_scan_hr_scanned_cards, ScanHRScannedCards); - _opt_scan_hr_scanned_blocks = new WorkerDataArray(max_gc_threads, "Scanned Blocks:"); - _gc_par_phases[OptScanHR]->link_thread_work_items(_opt_scan_hr_scanned_blocks, ScanHRScannedBlocks); - _opt_scan_hr_claimed_chunks = new WorkerDataArray(max_gc_threads, "Claimed Chunks:"); - _gc_par_phases[OptScanHR]->link_thread_work_items(_opt_scan_hr_claimed_chunks, ScanHRClaimedChunks); - _opt_scan_hr_scanned_opt_refs = new WorkerDataArray(max_gc_threads, "Scanned Refs:"); - _gc_par_phases[OptScanHR]->link_thread_work_items(_opt_scan_hr_scanned_opt_refs, ScanHRScannedOptRefs); - _opt_scan_hr_used_memory = new WorkerDataArray(max_gc_threads, "Used Memory:"); - _gc_par_phases[OptScanHR]->link_thread_work_items(_opt_scan_hr_used_memory, ScanHRUsedMemory); + _gc_par_phases[OptScanHR]->create_thread_work_items("Scanned Cards:", ScanHRScannedCards); + _gc_par_phases[OptScanHR]->create_thread_work_items("Scanned Blocks:", ScanHRScannedBlocks); + _gc_par_phases[OptScanHR]->create_thread_work_items("Claimed Chunks:", ScanHRClaimedChunks); + _gc_par_phases[OptScanHR]->create_thread_work_items("Scanned Refs:", ScanHRScannedOptRefs); + _gc_par_phases[OptScanHR]->create_thread_work_items("Used Memory:", ScanHRUsedMemory); - _merge_lb_dirty_cards = new WorkerDataArray(max_gc_threads, "Dirty Cards:"); - _gc_par_phases[MergeLB]->link_thread_work_items(_merge_lb_dirty_cards, MergeLBDirtyCards); - _merge_lb_skipped_cards = new WorkerDataArray(max_gc_threads, "Skipped Cards:"); - _gc_par_phases[MergeLB]->link_thread_work_items(_merge_lb_skipped_cards, MergeLBSkippedCards); + _gc_par_phases[MergeLB]->create_thread_work_items("Dirty Cards:", MergeLBDirtyCards); + _gc_par_phases[MergeLB]->create_thread_work_items("Skipped Cards:", MergeLBSkippedCards); - _gc_par_phases[MergePSS] = new WorkerDataArray(1, "Merge Per-Thread State", true /* is_serial */); + _gc_par_phases[MergePSS] = new WorkerDataArray("Merge Per-Thread State", 1 /* length */, true /* is_serial */); - _merge_pss_copied_bytes = new WorkerDataArray(max_gc_threads, "Copied Bytes"); - _gc_par_phases[MergePSS]->link_thread_work_items(_merge_pss_copied_bytes, MergePSSCopiedBytes); - _merge_pss_lab_waste_bytes = new WorkerDataArray(max_gc_threads, "LAB Waste"); - _gc_par_phases[MergePSS]->link_thread_work_items(_merge_pss_lab_waste_bytes, MergePSSLABWasteBytes); - _merge_pss_lab_undo_waste_bytes = new WorkerDataArray(max_gc_threads, "LAB Undo Waste"); - _gc_par_phases[MergePSS]->link_thread_work_items(_merge_pss_lab_undo_waste_bytes, MergePSSLABUndoWasteBytes); + _gc_par_phases[MergePSS]->create_thread_work_items("Copied Bytes", MergePSSCopiedBytes, max_gc_threads); + _gc_par_phases[MergePSS]->create_thread_work_items("LAB Waste", MergePSSLABWasteBytes, max_gc_threads); + _gc_par_phases[MergePSS]->create_thread_work_items("LAB Undo Waste", MergePSSLABUndoWasteBytes, max_gc_threads); - _termination_attempts = new WorkerDataArray(max_gc_threads, "Termination Attempts:"); - _gc_par_phases[Termination]->link_thread_work_items(_termination_attempts); + _gc_par_phases[Termination]->create_thread_work_items("Termination Attempts:"); - _opt_termination_attempts = new WorkerDataArray(max_gc_threads, "Optional Termination Attempts:"); - _gc_par_phases[OptTermination]->link_thread_work_items(_opt_termination_attempts); + _gc_par_phases[OptTermination]->create_thread_work_items("Optional Termination Attempts:"); if (UseStringDeduplication) { - _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray(max_gc_threads, "Queue Fixup (ms):"); - _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray(max_gc_threads, "Table Fixup (ms):"); + _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray("Queue Fixup (ms):", max_gc_threads); + _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray("Table Fixup (ms):", max_gc_threads); } else { _gc_par_phases[StringDedupQueueFixup] = NULL; _gc_par_phases[StringDedupTableFixup] = NULL; } - _gc_par_phases[RedirtyCards] = new WorkerDataArray(max_gc_threads, "Parallel Redirty (ms):"); - _redirtied_cards = new WorkerDataArray(max_gc_threads, "Redirtied Cards:"); - _gc_par_phases[RedirtyCards]->link_thread_work_items(_redirtied_cards); + _gc_par_phases[RedirtyCards] = new WorkerDataArray("Parallel Redirty (ms):", max_gc_threads); + _gc_par_phases[RedirtyCards]->create_thread_work_items("Redirtied Cards:"); - _gc_par_phases[YoungFreeCSet] = new WorkerDataArray(max_gc_threads, "Young Free Collection Set (ms):"); - _gc_par_phases[NonYoungFreeCSet] = new WorkerDataArray(max_gc_threads, "Non-Young Free Collection Set (ms):"); + _gc_par_phases[YoungFreeCSet] = new WorkerDataArray("Young Free Collection Set (ms):", max_gc_threads); + _gc_par_phases[NonYoungFreeCSet] = new WorkerDataArray("Non-Young Free Collection Set (ms):", max_gc_threads); reset(); } diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp index 0b946165069..0cd425ec34a 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp @@ -122,42 +122,6 @@ class G1GCPhaseTimes : public CHeapObj { WorkerDataArray* _gc_par_phases[GCParPhasesSentinel]; - WorkerDataArray* _merge_rs_merged_sparse; - WorkerDataArray* _merge_rs_merged_fine; - WorkerDataArray* _merge_rs_merged_coarse; - WorkerDataArray* _merge_rs_dirty_cards; - - WorkerDataArray* _merge_hcc_dirty_cards; - WorkerDataArray* _merge_hcc_skipped_cards; - - WorkerDataArray* _merge_lb_dirty_cards; - WorkerDataArray* _merge_lb_skipped_cards; - - WorkerDataArray* _scan_hr_scanned_cards; - WorkerDataArray* _scan_hr_scanned_blocks; - WorkerDataArray* _scan_hr_claimed_chunks; - - WorkerDataArray* _opt_merge_rs_merged_sparse; - WorkerDataArray* _opt_merge_rs_merged_fine; - WorkerDataArray* _opt_merge_rs_merged_coarse; - WorkerDataArray* _opt_merge_rs_dirty_cards; - - WorkerDataArray* _opt_scan_hr_scanned_cards; - WorkerDataArray* _opt_scan_hr_scanned_blocks; - WorkerDataArray* _opt_scan_hr_claimed_chunks; - WorkerDataArray* _opt_scan_hr_scanned_opt_refs; - WorkerDataArray* _opt_scan_hr_used_memory; - - WorkerDataArray* _merge_pss_copied_bytes; - WorkerDataArray* _merge_pss_lab_waste_bytes; - WorkerDataArray* _merge_pss_lab_undo_waste_bytes; - - WorkerDataArray* _termination_attempts; - - WorkerDataArray* _opt_termination_attempts; - - WorkerDataArray* _redirtied_cards; - double _cur_collection_initial_evac_time_ms; double _cur_optional_evac_time_ms; double _cur_collection_code_root_fixup_time_ms; diff --git a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp index 3aaeec583ee..f78971fcc5f 100644 --- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp +++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp @@ -34,6 +34,7 @@ #include "gc/g1/heapRegion.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "memory/allocation.inline.hpp" +#include "memory/iterator.hpp" #include "runtime/thread.inline.hpp" void G1RemSetSummary::update() { diff --git a/src/hotspot/share/gc/g1/g1SharedDirtyCardQueue.hpp b/src/hotspot/share/gc/g1/g1SharedDirtyCardQueue.hpp index d921b881714..2f28e2f6300 100644 --- a/src/hotspot/share/gc/g1/g1SharedDirtyCardQueue.hpp +++ b/src/hotspot/share/gc/g1/g1SharedDirtyCardQueue.hpp @@ -37,9 +37,7 @@ class G1SharedDirtyCardQueue { void** _buffer; size_t _index; - // Noncopyable - G1SharedDirtyCardQueue(const G1SharedDirtyCardQueue&); - G1SharedDirtyCardQueue& operator=(const G1SharedDirtyCardQueue&); + NONCOPYABLE(G1SharedDirtyCardQueue); public: G1SharedDirtyCardQueue(G1DirtyCardQueueSet* qset); diff --git a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp index 8b4a5d8d8cc..a6e3acbe20a 100644 --- a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp +++ b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ ParMarkBitMap::initialize(MemRegion covered_region) const idx_t bits = bits_required(covered_region); // The bits will be divided evenly between two bitmaps; each of them should be // an integral number of words. - assert(bits % (BitsPerWord * 2) == 0, "region size unaligned"); + assert(is_aligned(bits, (BitsPerWord * 2)), "region size unaligned"); const size_t words = bits / BitsPerWord; const size_t raw_bytes = words * sizeof(idx_t); @@ -118,7 +118,7 @@ ParMarkBitMap::live_words_in_range_helper(HeapWord* beg_addr, oop end_obj) const // The bitmap routines require the right boundary to be word-aligned. const idx_t end_bit = addr_to_bit((HeapWord*)end_obj); - const idx_t range_end = BitMap::word_align_up(end_bit); + const idx_t range_end = align_range_end(end_bit); idx_t beg_bit = find_obj_beg(addr_to_bit(beg_addr), range_end); while (beg_bit < end_bit) { @@ -177,7 +177,7 @@ ParMarkBitMap::iterate(ParMarkBitMapClosure* live_closure, assert(range_beg <= range_end, "live range invalid"); // The bitmap routines require the right boundary to be word-aligned. - const idx_t search_end = BitMap::word_align_up(range_end); + const idx_t search_end = align_range_end(range_end); idx_t cur_beg = find_obj_beg(range_beg, search_end); while (cur_beg < range_end) { @@ -216,8 +216,8 @@ ParMarkBitMap::iterate(ParMarkBitMapClosure* live_closure, assert(range_end <= dead_range_end, "dead range invalid"); // The bitmap routines require the right boundary to be word-aligned. - const idx_t live_search_end = BitMap::word_align_up(range_end); - const idx_t dead_search_end = BitMap::word_align_up(dead_range_end); + const idx_t live_search_end = align_range_end(range_end); + const idx_t dead_search_end = align_range_end(dead_range_end); idx_t cur_beg = range_beg; if (range_beg < range_end && is_unmarked(range_beg)) { diff --git a/src/hotspot/share/gc/parallel/parMarkBitMap.hpp b/src/hotspot/share/gc/parallel/parMarkBitMap.hpp index 17e8be8dc50..ed08fed4eb7 100644 --- a/src/hotspot/share/gc/parallel/parMarkBitMap.hpp +++ b/src/hotspot/share/gc/parallel/parMarkBitMap.hpp @@ -138,8 +138,12 @@ public: inline idx_t addr_to_bit(HeapWord* addr) const; inline HeapWord* bit_to_addr(idx_t bit) const; + // Return word-aligned up range_end, which must not be greater than size(). + inline idx_t align_range_end(idx_t range_end) const; + // Return the bit index of the first marked object that begins (or ends, // respectively) in the range [beg, end). If no object is found, return end. + // end must be word-aligned. inline idx_t find_obj_beg(idx_t beg, idx_t end) const; inline idx_t find_obj_end(idx_t beg, idx_t end) const; diff --git a/src/hotspot/share/gc/parallel/parMarkBitMap.inline.hpp b/src/hotspot/share/gc/parallel/parMarkBitMap.inline.hpp index cf9bbe82f52..055148e42a6 100644 --- a/src/hotspot/share/gc/parallel/parMarkBitMap.inline.hpp +++ b/src/hotspot/share/gc/parallel/parMarkBitMap.inline.hpp @@ -26,6 +26,7 @@ #define SHARE_GC_PARALLEL_PARMARKBITMAP_INLINE_HPP #include "gc/parallel/parMarkBitMap.hpp" +#include "utilities/align.hpp" #include "utilities/bitMap.inline.hpp" inline ParMarkBitMap::ParMarkBitMap(): @@ -146,7 +147,7 @@ inline bool ParMarkBitMap::mark_obj(oop obj, int size) { return mark_obj((HeapWord*)obj, (size_t)size); } -inline BitMap::idx_t ParMarkBitMap::addr_to_bit(HeapWord* addr) const { +inline ParMarkBitMap::idx_t ParMarkBitMap::addr_to_bit(HeapWord* addr) const { DEBUG_ONLY(verify_addr(addr);) return words_to_bits(pointer_delta(addr, region_start())); } @@ -156,6 +157,12 @@ inline HeapWord* ParMarkBitMap::bit_to_addr(idx_t bit) const { return region_start() + bits_to_words(bit); } +inline ParMarkBitMap::idx_t ParMarkBitMap::align_range_end(idx_t range_end) const { + // size is aligned, so if range_end <= size then so is aligned result. + assert(range_end <= size(), "range end out of range"); + return align_up(range_end, BitsPerWord); +} + inline ParMarkBitMap::idx_t ParMarkBitMap::find_obj_beg(idx_t beg, idx_t end) const { return _beg_bits.get_next_one_offset_aligned_right(beg, end); } @@ -167,7 +174,7 @@ inline ParMarkBitMap::idx_t ParMarkBitMap::find_obj_end(idx_t beg, idx_t end) co inline HeapWord* ParMarkBitMap::find_obj_beg(HeapWord* beg, HeapWord* end) const { const idx_t beg_bit = addr_to_bit(beg); const idx_t end_bit = addr_to_bit(end); - const idx_t search_end = BitMap::word_align_up(end_bit); + const idx_t search_end = align_range_end(end_bit); const idx_t res_bit = MIN2(find_obj_beg(beg_bit, search_end), end_bit); return bit_to_addr(res_bit); } @@ -175,7 +182,7 @@ inline HeapWord* ParMarkBitMap::find_obj_beg(HeapWord* beg, HeapWord* end) const inline HeapWord* ParMarkBitMap::find_obj_end(HeapWord* beg, HeapWord* end) const { const idx_t beg_bit = addr_to_bit(beg); const idx_t end_bit = addr_to_bit(end); - const idx_t search_end = BitMap::word_align_up(end_bit); + const idx_t search_end = align_range_end(end_bit); const idx_t res_bit = MIN2(find_obj_end(beg_bit, search_end), end_bit); return bit_to_addr(res_bit); } diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index dc6c52ce8a6..02f0e8b7de4 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -44,6 +44,7 @@ #include "gc/shared/locationPrinter.inline.hpp" #include "gc/shared/scavengableNMethods.hpp" #include "logging/log.hpp" +#include "memory/iterator.hpp" #include "memory/metaspaceCounters.hpp" #include "memory/universe.hpp" #include "oops/oop.inline.hpp" diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.cpp b/src/hotspot/share/gc/parallel/psCompactionManager.cpp index 6b12fd013c3..13e2cdd58a8 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp @@ -49,6 +49,8 @@ ParCompactionManager::ObjArrayTaskQueueSet* ObjectStartArray* ParCompactionManager::_start_array = NULL; ParMarkBitMap* ParCompactionManager::_mark_bitmap = NULL; RegionTaskQueueSet* ParCompactionManager::_region_array = NULL; +GrowableArray* ParCompactionManager::_shadow_region_array = NULL; +Monitor* ParCompactionManager::_shadow_region_monitor = NULL; ParCompactionManager::ParCompactionManager() : _action(CopyAndUpdate) { @@ -99,6 +101,11 @@ void ParCompactionManager::initialize(ParMarkBitMap* mbm) { "Could not create ParCompactionManager"); assert(ParallelScavengeHeap::heap()->workers().total_workers() != 0, "Not initialized?"); + + _shadow_region_array = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(10, true); + + _shadow_region_monitor = new Monitor(Mutex::barrier, "CompactionManager monitor", + Mutex::_allow_vm_block_flag, Monitor::_safepoint_check_never); } void ParCompactionManager::reset_all_bitmap_query_caches() { @@ -163,3 +170,33 @@ void ParCompactionManager::drain_region_stacks() { } } while (!region_stack()->is_empty()); } + +size_t ParCompactionManager::pop_shadow_region_mt_safe(PSParallelCompact::RegionData* region_ptr) { + MonitorLocker ml(_shadow_region_monitor, Mutex::_no_safepoint_check_flag); + while (true) { + if (!_shadow_region_array->is_empty()) { + return _shadow_region_array->pop(); + } + // Check if the corresponding heap region is available now. + // If so, we don't need to get a shadow region anymore, and + // we return InvalidShadow to indicate such a case. + if (region_ptr->claimed()) { + return InvalidShadow; + } + ml.wait(1); + } +} + +void ParCompactionManager::push_shadow_region_mt_safe(size_t shadow_region) { + MonitorLocker ml(_shadow_region_monitor, Mutex::_no_safepoint_check_flag); + _shadow_region_array->push(shadow_region); + ml.notify(); +} + +void ParCompactionManager::push_shadow_region(size_t shadow_region) { + _shadow_region_array->push(shadow_region); +} + +void ParCompactionManager::remove_all_shadow_regions() { + _shadow_region_array->clear(); +} \ No newline at end of file diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.hpp index c66bab7c914..7eba6ae31cd 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_GC_PARALLEL_PSCOMPACTIONMANAGER_HPP #define SHARE_GC_PARALLEL_PSCOMPACTIONMANAGER_HPP +#include "gc/parallel/psParallelCompact.hpp" #include "gc/shared/taskqueue.hpp" #include "memory/allocation.hpp" #include "utilities/stack.hpp" @@ -77,6 +78,7 @@ class ParCompactionManager : public CHeapObj { private: OverflowTaskQueue _marking_stack; ObjArrayTaskQueue _objarray_stack; + size_t _next_shadow_region; // Is there a way to reuse the _marking_stack for the // saving empty regions? For now just create a different @@ -85,6 +87,14 @@ private: static ParMarkBitMap* _mark_bitmap; + // Contains currently free shadow regions. We use it in + // a LIFO fashion for better data locality and utilization. + static GrowableArray* _shadow_region_array; + + // Provides mutual exclusive access of _shadow_region_array. + // See pop/push_shadow_region_mt_safe() below + static Monitor* _shadow_region_monitor; + Action _action; HeapWord* _last_query_beg; @@ -109,6 +119,19 @@ private: // marking stack and overflow stack directly. public: + static const size_t InvalidShadow = ~0; + static size_t pop_shadow_region_mt_safe(PSParallelCompact::RegionData* region_ptr); + static void push_shadow_region_mt_safe(size_t shadow_region); + static void push_shadow_region(size_t shadow_region); + static void remove_all_shadow_regions(); + + inline size_t next_shadow_region() { return _next_shadow_region; } + inline void set_next_shadow_region(size_t record) { _next_shadow_region = record; } + inline size_t move_next_shadow_region_by(size_t workers) { + _next_shadow_region += workers; + return next_shadow_region(); + } + void reset_bitmap_query_cache() { _last_query_beg = NULL; _last_query_obj = NULL; diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index f68ba635ce9..b132cc481fb 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -961,7 +961,7 @@ PSParallelCompact::clear_data_covering_space(SpaceId id) HeapWord* const max_top = MAX2(top, _space_info[id].new_top()); const idx_t beg_bit = _mark_bitmap.addr_to_bit(bot); - const idx_t end_bit = BitMap::word_align_up(_mark_bitmap.addr_to_bit(top)); + const idx_t end_bit = _mark_bitmap.align_range_end(_mark_bitmap.addr_to_bit(top)); _mark_bitmap.clear_range(beg_bit, end_bit); const size_t beg_region = _summary_data.addr_to_region_idx(bot); @@ -1023,6 +1023,7 @@ void PSParallelCompact::pre_compact() void PSParallelCompact::post_compact() { GCTraceTime(Info, gc, phases) tm("Post Compact", &_gc_timer); + ParCompactionManager::remove_all_shadow_regions(); for (unsigned int id = old_space_id; id < last_space_id; ++id) { // Clear the marking bitmap, summary data and split info. @@ -2417,6 +2418,8 @@ void PSParallelCompact::prepare_region_draining_tasks(uint parallel_gc_threads) for (size_t cur = end_region - 1; cur + 1 > beg_region; --cur) { if (sd.region(cur)->claim_unsafe()) { ParCompactionManager* cm = ParCompactionManager::manager_array(worker_id); + bool result = sd.region(cur)->mark_normal(); + assert(result, "Must succeed at this point."); cm->region_stack()->push(cur); region_logger.handle(cur); // Assign regions to tasks in round-robin fashion. @@ -2602,6 +2605,10 @@ static void compaction_with_stealing_work(ParallelTaskTerminator* terminator, ui if (ParCompactionManager::steal(worker_id, region_index)) { PSParallelCompact::fill_and_update_region(cm, region_index); cm->drain_region_stacks(); + } else if (PSParallelCompact::steal_unavailable_region(cm, region_index)) { + // Fill and update an unavailable region with the help of a shadow region + PSParallelCompact::fill_and_update_shadow_region(cm, region_index); + cm->drain_region_stacks(); } else { if (terminator->offer_termination()) { break; @@ -2656,6 +2663,7 @@ void PSParallelCompact::compact() { // // max push count is thus: last_space_id * (active_gc_threads * PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING + 1) TaskQueue task_queue(last_space_id * (active_gc_threads * PAR_OLD_DENSE_PREFIX_OVER_PARTITIONING + 1)); + initialize_shadow_regions(active_gc_threads); prepare_region_draining_tasks(active_gc_threads); enqueue_dense_prefix_tasks(task_queue, active_gc_threads); @@ -2849,7 +2857,7 @@ PSParallelCompact::skip_live_words(HeapWord* beg, HeapWord* end, size_t count) ParMarkBitMap* m = mark_bitmap(); idx_t bits_to_skip = m->words_to_bits(count); idx_t cur_beg = m->addr_to_bit(beg); - const idx_t search_end = BitMap::word_align_up(m->addr_to_bit(end)); + const idx_t search_end = m->align_range_end(m->addr_to_bit(end)); do { cur_beg = m->find_obj_beg(cur_beg, search_end); @@ -2962,7 +2970,17 @@ void PSParallelCompact::decrement_destination_counts(ParCompactionManager* cm, assert(cur->data_size() > 0, "region must have live data"); cur->decrement_destination_count(); if (cur < enqueue_end && cur->available() && cur->claim()) { - cm->push_region(sd.region(cur)); + if (cur->mark_normal()) { + cm->push_region(sd.region(cur)); + } else if (cur->mark_copied()) { + // Try to copy the content of the shadow region back to its corresponding + // heap region if the shadow region is filled. Otherwise, the GC thread + // fills the shadow region will copy the data back (see + // MoveAndUpdateShadowClosure::complete_region). + copy_back(sd.region_to_addr(cur->shadow_region()), sd.region_to_addr(cur)); + ParCompactionManager::push_shadow_region_mt_safe(cur->shadow_region()); + cur->set_completed(); + } } } } @@ -3040,28 +3058,19 @@ size_t PSParallelCompact::next_src_region(MoveAndUpdateClosure& closure, return 0; } -void PSParallelCompact::fill_region(ParCompactionManager* cm, size_t region_idx) +void PSParallelCompact::fill_region(ParCompactionManager* cm, MoveAndUpdateClosure& closure, size_t region_idx) { typedef ParMarkBitMap::IterationStatus IterationStatus; - const size_t RegionSize = ParallelCompactData::RegionSize; ParMarkBitMap* const bitmap = mark_bitmap(); ParallelCompactData& sd = summary_data(); RegionData* const region_ptr = sd.region(region_idx); - // Get the items needed to construct the closure. - HeapWord* dest_addr = sd.region_to_addr(region_idx); - SpaceId dest_space_id = space_id(dest_addr); - ObjectStartArray* start_array = _space_info[dest_space_id].start_array(); - HeapWord* new_top = _space_info[dest_space_id].new_top(); - assert(dest_addr < new_top, "sanity"); - const size_t words = MIN2(pointer_delta(new_top, dest_addr), RegionSize); - // Get the source region and related info. size_t src_region_idx = region_ptr->source_region(); SpaceId src_space_id = space_id(sd.region_to_addr(src_region_idx)); HeapWord* src_space_top = _space_info[src_space_id].space()->top(); + HeapWord* dest_addr = sd.region_to_addr(region_idx); - MoveAndUpdateClosure closure(bitmap, cm, start_array, dest_addr, words); closure.set_source(first_src_addr(dest_addr, src_space_id, src_region_idx)); // Adjust src_region_idx to prepare for decrementing destination counts (the @@ -3080,7 +3089,7 @@ void PSParallelCompact::fill_region(ParCompactionManager* cm, size_t region_idx) decrement_destination_counts(cm, src_space_id, src_region_idx, closure.source()); region_ptr->set_deferred_obj_addr(NULL); - region_ptr->set_completed(); + closure.complete_region(cm, dest_addr, region_ptr); return; } @@ -3129,7 +3138,7 @@ void PSParallelCompact::fill_region(ParCompactionManager* cm, size_t region_idx) decrement_destination_counts(cm, src_space_id, src_region_idx, closure.source()); - region_ptr->set_completed(); + closure.complete_region(cm, dest_addr, region_ptr); return; } @@ -3137,7 +3146,7 @@ void PSParallelCompact::fill_region(ParCompactionManager* cm, size_t region_idx) decrement_destination_counts(cm, src_space_id, src_region_idx, closure.source()); region_ptr->set_deferred_obj_addr(NULL); - region_ptr->set_completed(); + closure.complete_region(cm, dest_addr, region_ptr); return; } @@ -3150,6 +3159,96 @@ void PSParallelCompact::fill_region(ParCompactionManager* cm, size_t region_idx) } while (true); } +void PSParallelCompact::fill_and_update_region(ParCompactionManager* cm, size_t region_idx) +{ + MoveAndUpdateClosure cl(mark_bitmap(), cm, region_idx); + fill_region(cm, cl, region_idx); +} + +void PSParallelCompact::fill_and_update_shadow_region(ParCompactionManager* cm, size_t region_idx) +{ + // Get a shadow region first + ParallelCompactData& sd = summary_data(); + RegionData* const region_ptr = sd.region(region_idx); + size_t shadow_region = ParCompactionManager::pop_shadow_region_mt_safe(region_ptr); + // The InvalidShadow return value indicates the corresponding heap region is available, + // so use MoveAndUpdateClosure to fill the normal region. Otherwise, use + // MoveAndUpdateShadowClosure to fill the acquired shadow region. + if (shadow_region == ParCompactionManager::InvalidShadow) { + MoveAndUpdateClosure cl(mark_bitmap(), cm, region_idx); + region_ptr->shadow_to_normal(); + return fill_region(cm, cl, region_idx); + } else { + MoveAndUpdateShadowClosure cl(mark_bitmap(), cm, region_idx, shadow_region); + return fill_region(cm, cl, region_idx); + } +} + +void PSParallelCompact::copy_back(HeapWord *shadow_addr, HeapWord *region_addr) +{ + Copy::aligned_conjoint_words(shadow_addr, region_addr, _summary_data.RegionSize); +} + +bool PSParallelCompact::steal_unavailable_region(ParCompactionManager* cm, size_t ®ion_idx) +{ + size_t next = cm->next_shadow_region(); + ParallelCompactData& sd = summary_data(); + size_t old_new_top = sd.addr_to_region_idx(_space_info[old_space_id].new_top()); + uint active_gc_threads = ParallelScavengeHeap::heap()->workers().active_workers(); + + while (next < old_new_top) { + if (sd.region(next)->mark_shadow()) { + region_idx = next; + return true; + } + next = cm->move_next_shadow_region_by(active_gc_threads); + } + + return false; +} + +// The shadow region is an optimization to address region dependencies in full GC. The basic +// idea is making more regions available by temporally storing their live objects in empty +// shadow regions to resolve dependencies between them and the destination regions. Therefore, +// GC threads need not wait destination regions to be available before processing sources. +// +// A typical workflow would be: +// After draining its own stack and failing to steal from others, a GC worker would pick an +// unavailable region (destination count > 0) and get a shadow region. Then the worker fills +// the shadow region by copying live objects from source regions of the unavailable one. Once +// the unavailable region becomes available, the data in the shadow region will be copied back. +// Shadow regions are empty regions in the to-space and regions between top and end of other spaces. +// +// For more details, please refer to §4.2 of the VEE'19 paper: +// Haoyu Li, Mingyu Wu, Binyu Zang, and Haibo Chen. 2019. ScissorGC: scalable and efficient +// compaction for Java full garbage collection. In Proceedings of the 15th ACM SIGPLAN/SIGOPS +// International Conference on Virtual Execution Environments (VEE 2019). ACM, New York, NY, USA, +// 108-121. DOI: https://doi.org/10.1145/3313808.3313820 +void PSParallelCompact::initialize_shadow_regions(uint parallel_gc_threads) +{ + const ParallelCompactData& sd = PSParallelCompact::summary_data(); + + for (unsigned int id = old_space_id; id < last_space_id; ++id) { + SpaceInfo* const space_info = _space_info + id; + MutableSpace* const space = space_info->space(); + + const size_t beg_region = + sd.addr_to_region_idx(sd.region_align_up(MAX2(space_info->new_top(), space->top()))); + const size_t end_region = + sd.addr_to_region_idx(sd.region_align_down(space->end())); + + for (size_t cur = beg_region; cur < end_region; ++cur) { + ParCompactionManager::push_shadow_region(cur); + } + } + + size_t beg_region = sd.addr_to_region_idx(_space_info[old_space_id].dense_prefix()); + for (uint i = 0; i < parallel_gc_threads; i++) { + ParCompactionManager *cm = ParCompactionManager::manager_array(i); + cm->set_next_shadow_region(beg_region + i); + } +} + void PSParallelCompact::fill_blocks(size_t region_idx) { // Fill in the block table elements for the specified region. Each block @@ -3222,9 +3321,9 @@ void PSParallelCompact::reset_millis_since_last_gc() { ParMarkBitMap::IterationStatus MoveAndUpdateClosure::copy_until_full() { - if (source() != destination()) { + if (source() != copy_destination()) { DEBUG_ONLY(PSParallelCompact::check_new_location(source(), destination());) - Copy::aligned_conjoint_words(source(), destination(), words_remaining()); + Copy::aligned_conjoint_words(source(), copy_destination(), words_remaining()); } update_state(words_remaining()); assert(is_full(), "sanity"); @@ -3243,13 +3342,19 @@ void MoveAndUpdateClosure::copy_partial_obj() // This test is necessary; if omitted, the pointer updates to a partial object // that crosses the dense prefix boundary could be overwritten. - if (source() != destination()) { + if (source() != copy_destination()) { DEBUG_ONLY(PSParallelCompact::check_new_location(source(), destination());) - Copy::aligned_conjoint_words(source(), destination(), words); + Copy::aligned_conjoint_words(source(), copy_destination(), words); } update_state(words); } +void MoveAndUpdateClosure::complete_region(ParCompactionManager *cm, HeapWord *dest_addr, + PSParallelCompact::RegionData *region_ptr) { + assert(region_ptr->shadow_state() == ParallelCompactData::RegionData::NormalRegion, "Region should be finished"); + region_ptr->set_completed(); +} + ParMarkBitMapClosure::IterationStatus MoveAndUpdateClosure::do_addr(HeapWord* addr, size_t words) { assert(destination() != NULL, "sanity"); @@ -3268,20 +3373,39 @@ MoveAndUpdateClosure::do_addr(HeapWord* addr, size_t words) { _start_array->allocate_block(destination()); } - if (destination() != source()) { + if (copy_destination() != source()) { DEBUG_ONLY(PSParallelCompact::check_new_location(source(), destination());) - Copy::aligned_conjoint_words(source(), destination(), words); + Copy::aligned_conjoint_words(source(), copy_destination(), words); } - oop moved_oop = (oop) destination(); + oop moved_oop = (oop) copy_destination(); compaction_manager()->update_contents(moved_oop); assert(oopDesc::is_oop_or_null(moved_oop), "Expected an oop or NULL at " PTR_FORMAT, p2i(moved_oop)); update_state(words); - assert(destination() == (HeapWord*)moved_oop + moved_oop->size(), "sanity"); + assert(copy_destination() == (HeapWord*)moved_oop + moved_oop->size(), "sanity"); return is_full() ? ParMarkBitMap::full : ParMarkBitMap::incomplete; } +void MoveAndUpdateShadowClosure::complete_region(ParCompactionManager *cm, HeapWord *dest_addr, + PSParallelCompact::RegionData *region_ptr) { + assert(region_ptr->shadow_state() == ParallelCompactData::RegionData::ShadowRegion, "Region should be shadow"); + // Record the shadow region index + region_ptr->set_shadow_region(_shadow); + // Mark the shadow region as filled to indicate the data is ready to be + // copied back + region_ptr->mark_filled(); + // Try to copy the content of the shadow region back to its corresponding + // heap region if available; the GC thread that decreases the destination + // count to zero will do the copying otherwise (see + // PSParallelCompact::decrement_destination_counts). + if (((region_ptr->available() && region_ptr->claim()) || region_ptr->claimed()) && region_ptr->mark_copied()) { + region_ptr->set_completed(); + PSParallelCompact::copy_back(PSParallelCompact::summary_data().region_to_addr(_shadow), dest_addr); + ParCompactionManager::push_shadow_region_mt_safe(_shadow); + } +} + UpdateOnlyClosure::UpdateOnlyClosure(ParMarkBitMap* mbm, ParCompactionManager* cm, PSParallelCompact::SpaceId space_id) : diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.hpp index 75046941be3..93c466e44f1 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp @@ -241,6 +241,9 @@ public: // The first region containing data destined for this region. size_t source_region() const { return _source_region; } + // Reuse _source_region to store the corresponding shadow region index + size_t shadow_region() const { return _source_region; } + // The object (if any) starting in this region and ending in a different // region that could not be updated during the main (parallel) compaction // phase. This is different from _partial_obj_addr, which is an object that @@ -309,6 +312,7 @@ public: // These are not atomic. void set_destination(HeapWord* addr) { _destination = addr; } void set_source_region(size_t region) { _source_region = region; } + void set_shadow_region(size_t region) { _source_region = region; } void set_deferred_obj_addr(HeapWord* addr) { _partial_obj_addr = addr; } void set_partial_obj_addr(HeapWord* addr) { _partial_obj_addr = addr; } void set_partial_obj_size(size_t words) { @@ -328,6 +332,32 @@ public: inline void decrement_destination_count(); inline bool claim(); + // Possible values of _shadow_state, and transition is as follows + // Normal Path: + // UnusedRegion -> mark_normal() -> NormalRegion + // Shadow Path: + // UnusedRegion -> mark_shadow() -> ShadowRegion -> + // mark_filled() -> FilledShadow -> mark_copied() -> CopiedShadow + static const int UnusedRegion = 0; // The region is not collected yet + static const int ShadowRegion = 1; // Stolen by an idle thread, and a shadow region is created for it + static const int FilledShadow = 2; // Its shadow region has been filled and ready to be copied back + static const int CopiedShadow = 3; // The data of the shadow region has been copied back + static const int NormalRegion = 4; // The region will be collected by the original parallel algorithm + + // Mark the current region as normal or shadow to enter different processing paths + inline bool mark_normal(); + inline bool mark_shadow(); + // Mark the shadow region as filled and ready to be copied back + inline void mark_filled(); + // Mark the shadow region as copied back to avoid double copying. + inline bool mark_copied(); + // Special case: see the comment in PSParallelCompact::fill_and_update_shadow_region. + // Return to the normal path here + inline void shadow_to_normal(); + + + int shadow_state() { return _shadow_state; } + private: // The type used to represent object sizes within a region. typedef uint region_sz_t; @@ -348,6 +378,7 @@ public: region_sz_t _partial_obj_size; region_sz_t volatile _dc_and_los; bool volatile _blocks_filled; + int volatile _shadow_state; #ifdef ASSERT size_t _blocks_filled_count; // Number of block table fills. @@ -598,6 +629,29 @@ inline bool ParallelCompactData::RegionData::claim() return old == los; } +inline bool ParallelCompactData::RegionData::mark_normal() { + return Atomic::cmpxchg(&_shadow_state, UnusedRegion, NormalRegion, memory_order_relaxed) == UnusedRegion; +} + +inline bool ParallelCompactData::RegionData::mark_shadow() { + if (_shadow_state != UnusedRegion) return false; + return Atomic::cmpxchg(&_shadow_state, UnusedRegion, ShadowRegion, memory_order_relaxed) == UnusedRegion; +} + +inline void ParallelCompactData::RegionData::mark_filled() { + int old = Atomic::cmpxchg(&_shadow_state, ShadowRegion, FilledShadow, memory_order_relaxed); + assert(old == ShadowRegion, "Fail to mark the region as filled"); +} + +inline bool ParallelCompactData::RegionData::mark_copied() { + return Atomic::cmpxchg(&_shadow_state, FilledShadow, CopiedShadow, memory_order_relaxed) == FilledShadow; +} + +void ParallelCompactData::RegionData::shadow_to_normal() { + int old = Atomic::cmpxchg(&_shadow_state, ShadowRegion, NormalRegion, memory_order_relaxed); + assert(old == ShadowRegion, "Fail to mark the region as finish"); +} + inline ParallelCompactData::RegionData* ParallelCompactData::region(size_t region_idx) const { @@ -1181,11 +1235,16 @@ class PSParallelCompact : AllStatic { size_t beg_region, HeapWord* end_addr); - // Fill a region, copying objects from one or more source regions. - static void fill_region(ParCompactionManager* cm, size_t region_idx); - static void fill_and_update_region(ParCompactionManager* cm, size_t region) { - fill_region(cm, region); - } + static void fill_region(ParCompactionManager* cm, MoveAndUpdateClosure& closure, size_t region); + static void fill_and_update_region(ParCompactionManager* cm, size_t region); + + static bool steal_unavailable_region(ParCompactionManager* cm, size_t& region_idx); + static void fill_and_update_shadow_region(ParCompactionManager* cm, size_t region); + // Copy the content of a shadow region back to its corresponding heap region + static void copy_back(HeapWord* shadow_addr, HeapWord* region_addr); + // Collect empty regions as shadow regions and initialize the + // _next_shadow_region filed for each compact manager + static void initialize_shadow_regions(uint parallel_gc_threads); // Fill in the block table for the specified region. static void fill_blocks(size_t region_idx); @@ -1232,19 +1291,20 @@ class PSParallelCompact : AllStatic { }; class MoveAndUpdateClosure: public ParMarkBitMapClosure { + static inline size_t calculate_words_remaining(size_t region); public: inline MoveAndUpdateClosure(ParMarkBitMap* bitmap, ParCompactionManager* cm, - ObjectStartArray* start_array, - HeapWord* destination, size_t words); + size_t region); // Accessors. HeapWord* destination() const { return _destination; } + HeapWord* copy_destination() const { return _destination + _offset; } // If the object will fit (size <= words_remaining()), copy it to the current // destination, update the interior oops and the start array and return either // full (if the closure is full) or incomplete. If the object will not fit, // return would_overflow. - virtual IterationStatus do_addr(HeapWord* addr, size_t size); + IterationStatus do_addr(HeapWord* addr, size_t size); // Copy enough words to fill this closure, starting at source(). Interior // oops and the start array are not updated. Return full. @@ -1255,25 +1315,37 @@ class MoveAndUpdateClosure: public ParMarkBitMapClosure { // array are not updated. void copy_partial_obj(); - protected: + virtual void complete_region(ParCompactionManager* cm, HeapWord* dest_addr, + PSParallelCompact::RegionData* region_ptr); + +protected: // Update variables to indicate that word_count words were processed. inline void update_state(size_t word_count); protected: - ObjectStartArray* const _start_array; HeapWord* _destination; // Next addr to be written. + ObjectStartArray* const _start_array; + size_t _offset; }; +inline size_t MoveAndUpdateClosure::calculate_words_remaining(size_t region) { + HeapWord* dest_addr = PSParallelCompact::summary_data().region_to_addr(region); + PSParallelCompact::SpaceId dest_space_id = PSParallelCompact::space_id(dest_addr); + HeapWord* new_top = PSParallelCompact::new_top(dest_space_id); + assert(dest_addr < new_top, "sanity"); + + return MIN2(pointer_delta(new_top, dest_addr), ParallelCompactData::RegionSize); +} + inline MoveAndUpdateClosure::MoveAndUpdateClosure(ParMarkBitMap* bitmap, ParCompactionManager* cm, - ObjectStartArray* start_array, - HeapWord* destination, - size_t words) : - ParMarkBitMapClosure(bitmap, cm, words), _start_array(start_array) -{ - _destination = destination; -} + size_t region_idx) : + ParMarkBitMapClosure(bitmap, cm, calculate_words_remaining(region_idx)), + _destination(PSParallelCompact::summary_data().region_to_addr(region_idx)), + _start_array(PSParallelCompact::start_array(PSParallelCompact::space_id(_destination))), + _offset(0) { } + inline void MoveAndUpdateClosure::update_state(size_t words) { @@ -1282,6 +1354,36 @@ inline void MoveAndUpdateClosure::update_state(size_t words) _destination += words; } +class MoveAndUpdateShadowClosure: public MoveAndUpdateClosure { + inline size_t calculate_shadow_offset(size_t region_idx, size_t shadow_idx); +public: + inline MoveAndUpdateShadowClosure(ParMarkBitMap* bitmap, ParCompactionManager* cm, + size_t region, size_t shadow); + + virtual void complete_region(ParCompactionManager* cm, HeapWord* dest_addr, + PSParallelCompact::RegionData* region_ptr); + +private: + size_t _shadow; +}; + +inline size_t MoveAndUpdateShadowClosure::calculate_shadow_offset(size_t region_idx, size_t shadow_idx) { + ParallelCompactData& sd = PSParallelCompact::summary_data(); + HeapWord* dest_addr = sd.region_to_addr(region_idx); + HeapWord* shadow_addr = sd.region_to_addr(shadow_idx); + return pointer_delta(shadow_addr, dest_addr); +} + +inline +MoveAndUpdateShadowClosure::MoveAndUpdateShadowClosure(ParMarkBitMap *bitmap, + ParCompactionManager *cm, + size_t region, + size_t shadow) : + MoveAndUpdateClosure(bitmap, cm, region), + _shadow(shadow) { + _offset = calculate_shadow_offset(region, shadow); +} + class UpdateOnlyClosure: public ParMarkBitMapClosure { private: const PSParallelCompact::SpaceId _space_id; diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index 65c24bf6d17..621a4b83ba8 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -52,6 +52,7 @@ #include "gc/shared/weakProcessor.hpp" #include "gc/shared/workerPolicy.hpp" #include "gc/shared/workgroup.hpp" +#include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "logging/log.hpp" diff --git a/src/hotspot/share/gc/shared/barrierSetNMethod.hpp b/src/hotspot/share/gc/shared/barrierSetNMethod.hpp index 0d081cbaade..0d68b8cdfe9 100644 --- a/src/hotspot/share/gc/shared/barrierSetNMethod.hpp +++ b/src/hotspot/share/gc/shared/barrierSetNMethod.hpp @@ -36,10 +36,8 @@ class BarrierSetNMethod: public CHeapObj { void deoptimize(nmethod* nm, address* return_addr_ptr); int disarmed_value() const; -protected: - virtual bool nmethod_entry_barrier(nmethod* nm) = 0; - public: + virtual bool nmethod_entry_barrier(nmethod* nm) = 0; virtual ByteSize thread_disarmed_offset() const = 0; virtual int* disarmed_value_address() const = 0; diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index 2a190f6606b..f80fc126e2c 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -55,6 +55,7 @@ #include "gc/shared/weakProcessor.hpp" #include "gc/shared/workgroup.hpp" #include "memory/filemap.hpp" +#include "memory/iterator.hpp" #include "memory/metaspaceCounters.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" diff --git a/src/hotspot/share/gc/shared/oopStorage.hpp b/src/hotspot/share/gc/shared/oopStorage.hpp index 3cf529a6a7b..36862f954a0 100644 --- a/src/hotspot/share/gc/shared/oopStorage.hpp +++ b/src/hotspot/share/gc/shared/oopStorage.hpp @@ -193,9 +193,7 @@ private: const Block* _head; const Block* _tail; - // Noncopyable. - AllocationList(const AllocationList&); - AllocationList& operator=(const AllocationList&); + NONCOPYABLE(AllocationList); public: AllocationList(); diff --git a/src/hotspot/share/gc/shared/oopStorage.inline.hpp b/src/hotspot/share/gc/shared/oopStorage.inline.hpp index 618e7c93339..d0b11c4973c 100644 --- a/src/hotspot/share/gc/shared/oopStorage.inline.hpp +++ b/src/hotspot/share/gc/shared/oopStorage.inline.hpp @@ -48,9 +48,7 @@ class OopStorage::ActiveArray { ActiveArray(size_t size); ~ActiveArray(); - // Noncopyable - ActiveArray(const ActiveArray&); - ActiveArray& operator=(const ActiveArray&); + NONCOPYABLE(ActiveArray); static size_t blocks_offset(); Block* const* base_ptr() const; @@ -118,9 +116,7 @@ class OopStorage::AllocationListEntry { mutable const Block* _prev; mutable const Block* _next; - // Noncopyable. - AllocationListEntry(const AllocationListEntry&); - AllocationListEntry& operator=(const AllocationListEntry&); + NONCOPYABLE(AllocationListEntry); public: AllocationListEntry(); @@ -153,9 +149,7 @@ class OopStorage::Block /* No base class, to avoid messing up alignment. */ { template static bool iterate_impl(F f, BlockPtr b); - // Noncopyable. - Block(const Block&); - Block& operator=(const Block&); + NONCOPYABLE(Block); public: const AllocationListEntry& allocation_list_entry() const; diff --git a/src/hotspot/share/gc/shared/oopStorageParState.hpp b/src/hotspot/share/gc/shared/oopStorageParState.hpp index 32cc53a637a..010b5bea156 100644 --- a/src/hotspot/share/gc/shared/oopStorageParState.hpp +++ b/src/hotspot/share/gc/shared/oopStorageParState.hpp @@ -26,7 +26,7 @@ #define SHARE_GC_SHARED_OOPSTORAGEPARSTATE_HPP #include "gc/shared/oopStorage.hpp" -#include "utilities/macros.hpp" +#include "utilities/globalDefinitions.hpp" ////////////////////////////////////////////////////////////////////////////// // Support for parallel and optionally concurrent state iteration. @@ -134,9 +134,7 @@ class OopStorage::BasicParState { uint _estimated_thread_count; bool _concurrent; - // Noncopyable. - BasicParState(const BasicParState&); - BasicParState& operator=(const BasicParState&); + NONCOPYABLE(BasicParState); struct IterationData; diff --git a/src/hotspot/share/gc/shared/ptrQueue.hpp b/src/hotspot/share/gc/shared/ptrQueue.hpp index d2fe07ece69..3c48fa86b72 100644 --- a/src/hotspot/share/gc/shared/ptrQueue.hpp +++ b/src/hotspot/share/gc/shared/ptrQueue.hpp @@ -28,6 +28,7 @@ #include "memory/padded.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/lockFreeStack.hpp" #include "utilities/sizes.hpp" @@ -44,9 +45,7 @@ class PtrQueueSet; class PtrQueue { friend class VMStructs; - // Noncopyable - not defined. - PtrQueue(const PtrQueue&); - PtrQueue& operator=(const PtrQueue&); + NONCOPYABLE(PtrQueue); // The ptr queue set to which this queue belongs. PtrQueueSet* const _qset; @@ -205,6 +204,8 @@ class BufferNode { BufferNode() : _index(0), _next(NULL) { } ~BufferNode() { } + NONCOPYABLE(BufferNode); + static size_t buffer_offset() { return offset_of(BufferNode, _buffer); } @@ -273,6 +274,8 @@ class BufferNode::Allocator { void delete_list(BufferNode* list); bool try_transfer_pending(); + NONCOPYABLE(Allocator); + public: Allocator(const char* name, size_t buffer_size); ~Allocator(); @@ -295,9 +298,7 @@ public: class PtrQueueSet { BufferNode::Allocator* _allocator; - // Noncopyable - not defined. - PtrQueueSet(const PtrQueueSet&); - PtrQueueSet& operator=(const PtrQueueSet&); + NONCOPYABLE(PtrQueueSet); protected: bool _all_active; diff --git a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp index 20f487b1083..4b76ccf6609 100644 --- a/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessorPhaseTimes.cpp @@ -177,9 +177,9 @@ ReferenceProcessorPhaseTimes::ReferenceProcessorPhaseTimes(GCTimer* gc_timer, ui _processing_is_mt(false), _gc_timer(gc_timer) { for (uint i = 0; i < ReferenceProcessor::RefSubPhaseMax; i++) { - _sub_phases_worker_time_sec[i] = new WorkerDataArray(max_gc_threads, SubPhasesParWorkTitle[i]); + _sub_phases_worker_time_sec[i] = new WorkerDataArray(SubPhasesParWorkTitle[i], max_gc_threads); } - _phase2_worker_time_sec = new WorkerDataArray(max_gc_threads, Phase2ParWorkTitle); + _phase2_worker_time_sec = new WorkerDataArray(Phase2ParWorkTitle, max_gc_threads); reset(); } diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedup.cpp b/src/hotspot/share/gc/shared/stringdedup/stringDedup.cpp index c98c045fd09..c10902cb7dc 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedup.cpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedup.cpp @@ -27,6 +27,7 @@ #include "gc/shared/stringdedup/stringDedupQueue.hpp" #include "gc/shared/stringdedup/stringDedupTable.hpp" #include "gc/shared/stringdedup/stringDedupThread.hpp" +#include "memory/iterator.hpp" bool StringDedup::_enabled = false; diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedup.hpp b/src/hotspot/share/gc/shared/stringdedup/stringDedup.hpp index f9aba809b57..eb79ec79c15 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedup.hpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedup.hpp @@ -69,6 +69,8 @@ #include "memory/allocation.hpp" #include "runtime/thread.hpp" +class ThreadClosure; + // // Main interface for interacting with string deduplication. // diff --git a/src/hotspot/share/gc/shared/taskqueue.hpp b/src/hotspot/share/gc/shared/taskqueue.hpp index 6abe35e3085..f8dc3d0416b 100644 --- a/src/hotspot/share/gc/shared/taskqueue.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.hpp @@ -28,6 +28,7 @@ #include "memory/allocation.hpp" #include "memory/padded.hpp" #include "oops/oopsHierarchy.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/ostream.hpp" #include "utilities/stack.hpp" @@ -514,9 +515,8 @@ class TaskTerminator : public StackObj { private: ParallelTaskTerminator* _terminator; - // Noncopyable. - TaskTerminator(const TaskTerminator&); - TaskTerminator& operator=(const TaskTerminator&); + NONCOPYABLE(TaskTerminator); + public: TaskTerminator(uint n_threads, TaskQueueSetSuper* queue_set); ~TaskTerminator(); diff --git a/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp b/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp index 56ea3d1fee4..73afbf3dc57 100644 --- a/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp +++ b/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.cpp @@ -80,9 +80,7 @@ WeakProcessorPhaseTimes::WeakProcessorPhaseTimes(uint max_threads) : _max_threads(max_threads), _active_workers(0), _total_time_sec(uninitialized_time), - _worker_data(), - _worker_dead_items(), - _worker_total_items() + _worker_data() { assert(_max_threads > 0, "max_threads must not be zero"); @@ -93,9 +91,9 @@ WeakProcessorPhaseTimes::WeakProcessorPhaseTimes(uint max_threads) : for ( ; !it.is_end(); ++it) { assert(size_t(wpt - _worker_data) < ARRAY_SIZE(_worker_data), "invariant"); const char* description = it->name(); - *wpt = new WorkerDataArray(_max_threads, description); - (*wpt)->link_thread_work_items(new WorkerDataArray(_max_threads, "Dead"), DeadItems); - (*wpt)->link_thread_work_items(new WorkerDataArray(_max_threads, "Total"), TotalItems); + *wpt = new WorkerDataArray(description, _max_threads); + (*wpt)->create_thread_work_items("Dead", DeadItems); + (*wpt)->create_thread_work_items("Total", TotalItems); wpt++; } assert(size_t(wpt - _worker_data) == ARRAY_SIZE(_worker_data), "invariant"); @@ -104,8 +102,6 @@ WeakProcessorPhaseTimes::WeakProcessorPhaseTimes(uint max_threads) : WeakProcessorPhaseTimes::~WeakProcessorPhaseTimes() { for (size_t i = 0; i < ARRAY_SIZE(_worker_data); ++i) { delete _worker_data[i]; - delete _worker_dead_items[i]; - delete _worker_total_items[i]; } } diff --git a/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.hpp b/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.hpp index 6bf364eb461..b50f3241d52 100644 --- a/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.hpp +++ b/src/hotspot/share/gc/shared/weakProcessorPhaseTimes.hpp @@ -56,8 +56,6 @@ class WeakProcessorPhaseTimes : public CHeapObj { // Per-worker times and linked items. static const uint worker_data_count = WeakProcessorPhases::oopstorage_phase_count; WorkerDataArray* _worker_data[worker_data_count]; - WorkerDataArray* _worker_dead_items[worker_data_count]; - WorkerDataArray* _worker_total_items[worker_data_count]; WorkerDataArray* worker_data(WeakProcessorPhase phase) const; diff --git a/src/hotspot/share/gc/shared/workerDataArray.hpp b/src/hotspot/share/gc/shared/workerDataArray.hpp index 49f421eef58..4f7635a6c6e 100644 --- a/src/hotspot/share/gc/shared/workerDataArray.hpp +++ b/src/hotspot/share/gc/shared/workerDataArray.hpp @@ -45,10 +45,14 @@ private: WorkerDataArray* _thread_work_items[MaxThreadWorkItems]; public: - WorkerDataArray(uint length, const char* title, bool is_serial = false); + WorkerDataArray(const char* title, uint length, bool is_serial = false); ~WorkerDataArray(); - void link_thread_work_items(WorkerDataArray* thread_work_items, uint index = 0); + // Create an integer sub-item at the given index to this WorkerDataArray. If length_override + // is zero, use the same number of elements as this array, otherwise use the given + // number. + void create_thread_work_items(const char* title, uint index = 0, uint length_override = 0); + void set_thread_work_item(uint worker_i, size_t value, uint index = 0); void add_thread_work_item(uint worker_i, size_t value, uint index = 0); void set_or_add_thread_work_item(uint worker_i, size_t value, uint index = 0); diff --git a/src/hotspot/share/gc/shared/workerDataArray.inline.hpp b/src/hotspot/share/gc/shared/workerDataArray.inline.hpp index eeedd50e557..f698c2f21a2 100644 --- a/src/hotspot/share/gc/shared/workerDataArray.inline.hpp +++ b/src/hotspot/share/gc/shared/workerDataArray.inline.hpp @@ -30,7 +30,7 @@ #include "utilities/ostream.hpp" template -WorkerDataArray::WorkerDataArray(uint length, const char* title, bool is_serial) : +WorkerDataArray::WorkerDataArray(const char* title, uint length, bool is_serial) : _data(NULL), _length(length), _title(title), @@ -59,13 +59,18 @@ T WorkerDataArray::get(uint worker_i) const { template WorkerDataArray::~WorkerDataArray() { + for (uint i = 0; i < MaxThreadWorkItems; i++) { + delete _thread_work_items[i]; + } FREE_C_HEAP_ARRAY(T, _data); } template -void WorkerDataArray::link_thread_work_items(WorkerDataArray* thread_work_items, uint index) { +void WorkerDataArray::create_thread_work_items(const char* title, uint index, uint length_override) { assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)", index, MaxThreadWorkItems); - _thread_work_items[index] = thread_work_items; + assert(_thread_work_items[index] == NULL, "Tried to overwrite existing thread work item"); + uint length = length_override != 0 ? length_override : _length; + _thread_work_items[index] = new WorkerDataArray(title, length); } template diff --git a/src/hotspot/share/gc/shared/workgroup.cpp b/src/hotspot/share/gc/shared/workgroup.cpp index 396eda29292..e457301f6bf 100644 --- a/src/hotspot/share/gc/shared/workgroup.cpp +++ b/src/hotspot/share/gc/shared/workgroup.cpp @@ -28,6 +28,7 @@ #include "gc/shared/workerManager.hpp" #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" +#include "memory/iterator.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "runtime/semaphore.hpp" diff --git a/src/hotspot/share/gc/shared/workgroup.hpp b/src/hotspot/share/gc/shared/workgroup.hpp index dbf84ba922e..a2455c01114 100644 --- a/src/hotspot/share/gc/shared/workgroup.hpp +++ b/src/hotspot/share/gc/shared/workgroup.hpp @@ -50,6 +50,7 @@ class AbstractGangWorker; class Semaphore; +class ThreadClosure; class WorkGang; // An abstract task to be worked on by a gang. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp index cf038ee46c8..7829bfb6d84 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp @@ -26,6 +26,7 @@ #include "code/icBuffer.hpp" #include "code/nmethod.hpp" #include "gc/shenandoah/shenandoahCodeRoots.hpp" +#include "gc/shenandoah/shenandoahEvacOOMHandler.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahNMethod.inline.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" @@ -214,6 +215,7 @@ public: if (nm->is_unloading()) { ShenandoahReentrantLocker locker(nm_data->lock()); + ShenandoahEvacOOMScope evac_scope; unlink(nm); return; } @@ -221,7 +223,7 @@ public: ShenandoahReentrantLocker locker(nm_data->lock()); // Heal oops and disarm - ShenandoahEvacOOMScope scope; + ShenandoahEvacOOMScope evac_scope; ShenandoahNMethod::heal_nmethod(nm); ShenandoahNMethod::disarm_nmethod(nm); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp index d02713ab41b..42661f4f870 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.hpp @@ -30,6 +30,7 @@ #include "gc/shenandoah/shenandoahNMethod.hpp" #include "memory/allocation.hpp" #include "memory/iterator.hpp" +#include "utilities/globalDefinitions.hpp" class ShenandoahHeap; class ShenandoahHeapRegion; @@ -53,10 +54,8 @@ private: ShenandoahParallelCodeHeapIterator* _iters; int _length; -private: - // Noncopyable. - ShenandoahParallelCodeCacheIterator(const ShenandoahParallelCodeCacheIterator& o); - ShenandoahParallelCodeCacheIterator& operator=(const ShenandoahParallelCodeCacheIterator& o); + NONCOPYABLE(ShenandoahParallelCodeCacheIterator); + public: ShenandoahParallelCodeCacheIterator(const GrowableArray* heaps); ~ShenandoahParallelCodeCacheIterator(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index 7c2e8897503..13e9877885c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -115,7 +115,7 @@ HeapWord* ShenandoahFreeSet::allocate_single(ShenandoahAllocRequest& req, bool& size_t idx = c - 1; if (is_mutator_free(idx)) { ShenandoahHeapRegion* r = _heap->get_region(idx); - if (is_empty_or_trash(r)) { + if (can_allocate_from(r)) { flip_to_gc(r); HeapWord *result = try_allocate_in(r, req, in_new_region); if (result != NULL) { @@ -279,7 +279,7 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) { // If regions are not adjacent, then current [beg; end] is useless, and we may fast-forward. // If region is not completely free, the current [beg; end] is useless, and we may fast-forward. - if (!is_mutator_free(end) || !is_empty_or_trash(_heap->get_region(end))) { + if (!is_mutator_free(end) || !can_allocate_from(_heap->get_region(end))) { end++; beg = end; continue; @@ -342,8 +342,8 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req) { return _heap->get_region(beg)->bottom(); } -bool ShenandoahFreeSet::is_empty_or_trash(ShenandoahHeapRegion *r) { - return r->is_empty() || r->is_trash(); +bool ShenandoahFreeSet::can_allocate_from(ShenandoahHeapRegion *r) { + return r->is_empty() || (r->is_trash() && !_heap->is_concurrent_root_in_progress()); } size_t ShenandoahFreeSet::alloc_capacity(ShenandoahHeapRegion *r) { @@ -384,7 +384,7 @@ void ShenandoahFreeSet::flip_to_gc(ShenandoahHeapRegion* r) { size_t idx = r->region_number(); assert(_mutator_free_bitmap.at(idx), "Should be in mutator view"); - assert(is_empty_or_trash(r), "Should not be allocated"); + assert(can_allocate_from(r), "Should not be allocated"); _mutator_free_bitmap.clear_bit(idx); _collector_free_bitmap.set_bit(idx); @@ -443,7 +443,7 @@ void ShenandoahFreeSet::rebuild() { if (reserved >= to_reserve) break; ShenandoahHeapRegion* region = _heap->get_region(idx); - if (_mutator_free_bitmap.at(idx) && is_empty_or_trash(region)) { + if (_mutator_free_bitmap.at(idx) && can_allocate_from(region)) { _mutator_free_bitmap.clear_bit(idx); _collector_free_bitmap.set_bit(idx); size_t ac = alloc_capacity(region); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp index 546b46448d2..0f24c38cdc3 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp @@ -67,7 +67,7 @@ private: void try_recycle_trashed(ShenandoahHeapRegion *r); - bool is_empty_or_trash(ShenandoahHeapRegion *r); + bool can_allocate_from(ShenandoahHeapRegion *r); size_t alloc_capacity(ShenandoahHeapRegion *r); bool has_no_alloc_capacity(ShenandoahHeapRegion *r); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index 5b1ed5af5e1..ca962d1aa0a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -34,6 +34,7 @@ #include "gc/shenandoah/shenandoahSharedVariables.hpp" #include "gc/shenandoah/shenandoahUnload.hpp" #include "services/memoryManager.hpp" +#include "utilities/globalDefinitions.hpp" class ConcurrentGCTimer; class ReferenceProcessor; @@ -70,8 +71,7 @@ private: DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0); // No implicit copying: iterators should be passed by reference to capture the state - ShenandoahRegionIterator(const ShenandoahRegionIterator& that); - ShenandoahRegionIterator& operator=(const ShenandoahRegionIterator& o); + NONCOPYABLE(ShenandoahRegionIterator); public: ShenandoahRegionIterator(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionSet.hpp index efec2af8bad..5b15e7589b6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegionSet.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Red Hat, Inc. All rights reserved. + * Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved. * * 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 @@ -27,6 +27,7 @@ #include "memory/allocation.hpp" #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" +#include "utilities/globalDefinitions.hpp" class ShenandoahHeapRegionSet; @@ -40,8 +41,7 @@ private: DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0); // No implicit copying: iterators should be passed by reference to capture the state - ShenandoahHeapRegionSetIterator(const ShenandoahHeapRegionSetIterator& that); - ShenandoahHeapRegionSetIterator& operator=(const ShenandoahHeapRegionSetIterator& o); + NONCOPYABLE(ShenandoahHeapRegionSetIterator); public: ShenandoahHeapRegionSetIterator(const ShenandoahHeapRegionSet* const set); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp index 4a4a1d5abb7..d518720c67f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPhaseTimings.cpp @@ -138,7 +138,7 @@ ShenandoahWorkerTimings::ShenandoahWorkerTimings(uint max_gc_threads) : assert(max_gc_threads > 0, "Must have some GC threads"); #define GC_PAR_PHASE_DECLARE_WORKER_DATA(type, title) \ - _gc_par_phases[ShenandoahPhaseTimings::type] = new WorkerDataArray(max_gc_threads, title); + _gc_par_phases[ShenandoahPhaseTimings::type] = new WorkerDataArray(title, max_gc_threads); // Root scanning phases SHENANDOAH_GC_PAR_PHASE_DO(GC_PAR_PHASE_DECLARE_WORKER_DATA) #undef GC_PAR_PHASE_DECLARE_WORKER_DATA @@ -165,7 +165,7 @@ void ShenandoahWorkerTimings::print() const { ShenandoahTerminationTimings::ShenandoahTerminationTimings(uint max_gc_threads) { - _gc_termination_phase = new WorkerDataArray(max_gc_threads, "Task Termination (ms):"); + _gc_termination_phase = new WorkerDataArray("Task Termination (ms):", max_gc_threads); } void ShenandoahTerminationTimings::record_time_secs(uint worker_id, double secs) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp index 429c20c9d6c..1022cdd5b90 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp @@ -158,8 +158,9 @@ void ShenandoahUnload::purge() { CodeCache::purge_exception_caches(); } -class ShenandoahUnloadRendezvousClosure : public ThreadClosure { +class ShenandoahUnloadRendezvousClosure : public HandshakeClosure { public: + ShenandoahUnloadRendezvousClosure() : HandshakeClosure("ShenandoahUnloadRendezvous") {} void do_thread(Thread* thread) {} }; diff --git a/src/hotspot/share/gc/z/zArray.hpp b/src/hotspot/share/gc/z/zArray.hpp index 378e45032c2..ec1ff3ce6ac 100644 --- a/src/hotspot/share/gc/z/zArray.hpp +++ b/src/hotspot/share/gc/z/zArray.hpp @@ -25,6 +25,7 @@ #define SHARE_GC_Z_ZARRAY_HPP #include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" template class ZArray { @@ -35,9 +36,7 @@ private: size_t _size; size_t _capacity; - // Copy and assignment are not allowed - ZArray(const ZArray& array); - ZArray& operator=(const ZArray& array); + NONCOPYABLE(ZArray); void expand(size_t new_capacity); diff --git a/src/hotspot/share/gc/z/zCollectedHeap.cpp b/src/hotspot/share/gc/z/zCollectedHeap.cpp index 75fd677ee24..5652ff61d19 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.cpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp @@ -33,6 +33,7 @@ #include "gc/z/zServiceability.hpp" #include "gc/z/zStat.hpp" #include "gc/z/zUtils.inline.hpp" +#include "memory/iterator.hpp" #include "memory/universe.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/align.hpp" diff --git a/src/hotspot/share/gc/z/zForwarding.cpp b/src/hotspot/share/gc/z/zForwarding.cpp index db78433259b..f664233975a 100644 --- a/src/hotspot/share/gc/z/zForwarding.cpp +++ b/src/hotspot/share/gc/z/zForwarding.cpp @@ -24,9 +24,9 @@ #include "precompiled.hpp" #include "gc/z/zForwarding.inline.hpp" #include "gc/z/zPage.inline.hpp" -#include "gc/z/zUtils.inline.hpp" #include "memory/allocation.hpp" #include "utilities/debug.hpp" +#include "utilities/powerOfTwo.hpp" ZForwarding* ZForwarding::create(ZPage* page) { // Allocate table for linear probing. The size of the table must be @@ -34,7 +34,7 @@ ZForwarding* ZForwarding::create(ZPage* page) { // The table is sized to have a load factor of 50%, i.e. sized to have // double the number of entries actually inserted. assert(page->live_objects() > 0, "Invalid value"); - const size_t nentries = ZUtils::round_up_power_of_2(page->live_objects() * 2); + const size_t nentries = round_up_power_of_2(page->live_objects() * 2); return ::new (AttachedArray::alloc(nentries)) ZForwarding(page, nentries); } diff --git a/src/hotspot/share/gc/z/zHeap.cpp b/src/hotspot/share/gc/z/zHeap.cpp index c6c3c0ca6c0..bb10f7066b4 100644 --- a/src/hotspot/share/gc/z/zHeap.cpp +++ b/src/hotspot/share/gc/z/zHeap.cpp @@ -57,7 +57,7 @@ ZHeap* ZHeap::_heap = NULL; ZHeap::ZHeap() : _workers(), _object_allocator(), - _page_allocator(heap_min_size(), heap_initial_size(), heap_max_size(), heap_max_reserve_size()), + _page_allocator(&_workers, heap_min_size(), heap_initial_size(), heap_max_size(), heap_max_reserve_size()), _page_table(), _forwarding_table(), _mark(&_workers, &_page_table), @@ -326,9 +326,12 @@ void ZHeap::set_soft_reference_policy(bool clear) { _reference_processor.set_soft_reference_policy(clear); } -class ZRendezvousClosure : public ThreadClosure { +class ZRendezvousClosure : public HandshakeClosure { public: - virtual void do_thread(Thread* thread) {} + ZRendezvousClosure() : + HandshakeClosure("ZRendezvous") {} + + void do_thread(Thread* thread) {} }; void ZHeap::process_non_strong_references() { diff --git a/src/hotspot/share/gc/z/zHeap.hpp b/src/hotspot/share/gc/z/zHeap.hpp index 7c7c92b8d83..b45f1ddc788 100644 --- a/src/hotspot/share/gc/z/zHeap.hpp +++ b/src/hotspot/share/gc/z/zHeap.hpp @@ -39,6 +39,8 @@ #include "gc/z/zUnload.hpp" #include "gc/z/zWorkers.hpp" +class ThreadClosure; + class ZHeap { friend class VMStructs; diff --git a/src/hotspot/share/gc/z/zHeuristics.cpp b/src/hotspot/share/gc/z/zHeuristics.cpp index bf971c05bc1..c19c178553d 100644 --- a/src/hotspot/share/gc/z/zHeuristics.cpp +++ b/src/hotspot/share/gc/z/zHeuristics.cpp @@ -25,10 +25,10 @@ #include "gc/z/zCPU.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zHeuristics.hpp" -#include "gc/z/zUtils.inline.hpp" #include "logging/log.hpp" #include "runtime/globals.hpp" #include "runtime/os.hpp" +#include "utilities/powerOfTwo.hpp" void ZHeuristics::set_medium_page_size() { // Set ZPageSizeMedium so that a medium page occupies at most 3.125% of the @@ -39,7 +39,7 @@ void ZHeuristics::set_medium_page_size() { const size_t max = ZGranuleSize * 16; const size_t unclamped = MaxHeapSize * 0.03125; const size_t clamped = MIN2(MAX2(min, unclamped), max); - const size_t size = ZUtils::round_down_power_of_2(clamped); + const size_t size = round_down_power_of_2(clamped); if (size > ZPageSizeSmall) { // Enable medium pages diff --git a/src/hotspot/share/gc/z/zList.hpp b/src/hotspot/share/gc/z/zList.hpp index 6fc1a11758e..143540b4aaf 100644 --- a/src/hotspot/share/gc/z/zList.hpp +++ b/src/hotspot/share/gc/z/zList.hpp @@ -25,6 +25,7 @@ #define SHARE_GC_Z_ZLIST_HPP #include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" template class ZList; @@ -55,9 +56,7 @@ private: ZListNode _head; size_t _size; - // Passing by value and assignment is not allowed - ZList(const ZList& list); - ZList& operator=(const ZList& list); + NONCOPYABLE(ZList); void verify() const; diff --git a/src/hotspot/share/gc/z/zMark.cpp b/src/hotspot/share/gc/z/zMark.cpp index e9cb3b63a52..6a183cd1a49 100644 --- a/src/hotspot/share/gc/z/zMark.cpp +++ b/src/hotspot/share/gc/z/zMark.cpp @@ -48,6 +48,7 @@ #include "runtime/thread.hpp" #include "utilities/align.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" #include "utilities/ticks.hpp" static const ZStatSubPhase ZSubPhaseConcurrentMark("Concurrent Mark"); @@ -79,7 +80,7 @@ size_t ZMark::calculate_nstripes(uint nworkers) const { // Calculate the number of stripes from the number of workers we use, // where the number of stripes must be a power of two and we want to // have at least one worker per stripe. - const size_t nstripes = ZUtils::round_down_power_of_2(nworkers); + const size_t nstripes = round_down_power_of_2(nworkers); return MIN2(nstripes, ZMarkStripesMax); } @@ -413,13 +414,14 @@ void ZMark::idle() const { os::naked_short_sleep(1); } -class ZMarkFlushAndFreeStacksClosure : public ThreadClosure { +class ZMarkFlushAndFreeStacksClosure : public HandshakeClosure { private: ZMark* const _mark; bool _flushed; public: ZMarkFlushAndFreeStacksClosure(ZMark* mark) : + HandshakeClosure("ZMarkFlushAndFreeStacks"), _mark(mark), _flushed(false) {} diff --git a/src/hotspot/share/gc/z/zPageAllocator.cpp b/src/hotspot/share/gc/z/zPageAllocator.cpp index c92abdc7910..3849f5f02d7 100644 --- a/src/hotspot/share/gc/z/zPageAllocator.cpp +++ b/src/hotspot/share/gc/z/zPageAllocator.cpp @@ -33,7 +33,9 @@ #include "gc/z/zPageCache.inline.hpp" #include "gc/z/zSafeDelete.inline.hpp" #include "gc/z/zStat.hpp" +#include "gc/z/zTask.hpp" #include "gc/z/zTracer.inline.hpp" +#include "gc/z/zWorkers.hpp" #include "runtime/globals.hpp" #include "runtime/init.hpp" #include "runtime/java.hpp" @@ -95,7 +97,8 @@ public: ZPage* const ZPageAllocator::gc_marker = (ZPage*)-1; -ZPageAllocator::ZPageAllocator(size_t min_capacity, +ZPageAllocator::ZPageAllocator(ZWorkers* workers, + size_t min_capacity, size_t initial_capacity, size_t max_capacity, size_t max_reserve) : @@ -150,13 +153,42 @@ ZPageAllocator::ZPageAllocator(size_t min_capacity, } // Pre-map initial capacity - prime_cache(initial_capacity); + prime_cache(workers, initial_capacity); // Successfully initialized _initialized = true; } -void ZPageAllocator::prime_cache(size_t size) { +class ZPreTouchTask : public ZTask { +private: + const ZPhysicalMemoryManager* const _physical; + volatile uintptr_t _start; + const uintptr_t _end; + +public: + ZPreTouchTask(const ZPhysicalMemoryManager* physical, uintptr_t start, uintptr_t end) : + ZTask("ZPreTouchTask"), + _physical(physical), + _start(start), + _end(end) {} + + virtual void work() { + for (;;) { + // Get granule offset + const size_t size = ZGranuleSize; + const uintptr_t offset = Atomic::add(&_start, size) - size; + if (offset >= _end) { + // Done + break; + } + + // Pre-touch granule + _physical->pretouch(offset, size); + } + } +}; + +void ZPageAllocator::prime_cache(ZWorkers* workers, size_t size) { // Allocate physical memory const ZPhysicalMemory pmem = _physical.alloc(size); guarantee(!pmem.is_null(), "Invalid size"); @@ -172,6 +204,12 @@ void ZPageAllocator::prime_cache(size_t size) { map_page(page); page->set_pre_mapped(); + if (AlwaysPreTouch) { + // Pre-touch page + ZPreTouchTask task(&_physical, page->start(), page->end()); + workers->run_parallel(&task); + } + // Add page to cache page->set_last_used(); _cache.free_page(page); diff --git a/src/hotspot/share/gc/z/zPageAllocator.hpp b/src/hotspot/share/gc/z/zPageAllocator.hpp index 9bcd08cb6c7..c97a70fd028 100644 --- a/src/hotspot/share/gc/z/zPageAllocator.hpp +++ b/src/hotspot/share/gc/z/zPageAllocator.hpp @@ -34,6 +34,7 @@ #include "memory/allocation.hpp" class ZPageAllocRequest; +class ZWorkers; class ZPageAllocator { friend class VMStructs; @@ -61,7 +62,7 @@ private: static ZPage* const gc_marker; - void prime_cache(size_t size); + void prime_cache(ZWorkers* workers, size_t size); void increase_used(size_t size, bool relocation); void decrease_used(size_t size, bool reclaimed); @@ -86,7 +87,8 @@ private: void satisfy_alloc_queue(); public: - ZPageAllocator(size_t min_capacity, + ZPageAllocator(ZWorkers* workers, + size_t min_capacity, size_t initial_capacity, size_t max_capacity, size_t max_reserve); diff --git a/src/hotspot/share/gc/z/zPhysicalMemory.cpp b/src/hotspot/share/gc/z/zPhysicalMemory.cpp index ab878636566..c42ead0306b 100644 --- a/src/hotspot/share/gc/z/zPhysicalMemory.cpp +++ b/src/hotspot/share/gc/z/zPhysicalMemory.cpp @@ -173,6 +173,10 @@ void ZPhysicalMemoryManager::free(const ZPhysicalMemory& pmem) { _backing.free(pmem); } +void ZPhysicalMemoryManager::pretouch(uintptr_t offset, size_t size) const { + _backing.pretouch(offset, size); +} + void ZPhysicalMemoryManager::map(const ZPhysicalMemory& pmem, uintptr_t offset) const { _backing.map(pmem, offset); nmt_commit(pmem, offset); diff --git a/src/hotspot/share/gc/z/zPhysicalMemory.hpp b/src/hotspot/share/gc/z/zPhysicalMemory.hpp index e3701066a4f..de7ab41b628 100644 --- a/src/hotspot/share/gc/z/zPhysicalMemory.hpp +++ b/src/hotspot/share/gc/z/zPhysicalMemory.hpp @@ -82,6 +82,8 @@ public: ZPhysicalMemory alloc(size_t size); void free(const ZPhysicalMemory& pmem); + void pretouch(uintptr_t offset, size_t size) const; + void map(const ZPhysicalMemory& pmem, uintptr_t offset) const; void unmap(const ZPhysicalMemory& pmem, uintptr_t offset) const; diff --git a/src/hotspot/share/gc/z/zRootsIterator.cpp b/src/hotspot/share/gc/z/zRootsIterator.cpp index 4d297e26ad5..438e467c5f6 100644 --- a/src/hotspot/share/gc/z/zRootsIterator.cpp +++ b/src/hotspot/share/gc/z/zRootsIterator.cpp @@ -39,6 +39,7 @@ #include "gc/z/zRootsIterator.hpp" #include "gc/z/zStat.hpp" #include "gc/z/zThreadLocalData.hpp" +#include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "prims/jvmtiExport.hpp" diff --git a/src/hotspot/share/gc/z/zRuntimeWorkers.hpp b/src/hotspot/share/gc/z/zRuntimeWorkers.hpp index 99095c5b7a0..a201c79fa23 100644 --- a/src/hotspot/share/gc/z/zRuntimeWorkers.hpp +++ b/src/hotspot/share/gc/z/zRuntimeWorkers.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ #include "gc/shared/workgroup.hpp" +class ThreadClosure; + class ZRuntimeWorkers { private: WorkGang _workers; diff --git a/src/hotspot/share/gc/z/zUtils.inline.hpp b/src/hotspot/share/gc/z/zUtils.inline.hpp index a342c55a64e..aae97163075 100644 --- a/src/hotspot/share/gc/z/zUtils.inline.hpp +++ b/src/hotspot/share/gc/z/zUtils.inline.hpp @@ -32,21 +32,6 @@ #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" -inline size_t ZUtils::round_up_power_of_2(size_t value) { - assert(value != 0, "Invalid value"); - - if (is_power_of_2(value)) { - return value; - } - - return (size_t)1 << (log2_intptr(value) + 1); -} - -inline size_t ZUtils::round_down_power_of_2(size_t value) { - assert(value != 0, "Invalid value"); - return (size_t)1 << log2_intptr(value); -} - inline size_t ZUtils::bytes_to_words(size_t size_in_bytes) { assert(is_aligned(size_in_bytes, BytesPerWord), "Size not word aligned"); return size_in_bytes >> LogBytesPerWord; diff --git a/src/hotspot/share/gc/z/zWorkers.cpp b/src/hotspot/share/gc/z/zWorkers.cpp index 4bbe9675dd9..e7d1d0db7be 100644 --- a/src/hotspot/share/gc/z/zWorkers.cpp +++ b/src/hotspot/share/gc/z/zWorkers.cpp @@ -100,7 +100,6 @@ void ZWorkers::run(ZTask* task, uint nworkers) { } void ZWorkers::run_parallel(ZTask* task) { - assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint"); run(task, nparallel()); } diff --git a/src/hotspot/share/gc/z/zWorkers.hpp b/src/hotspot/share/gc/z/zWorkers.hpp index 7176c40e4da..329a1a21c42 100644 --- a/src/hotspot/share/gc/z/zWorkers.hpp +++ b/src/hotspot/share/gc/z/zWorkers.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "gc/shared/workgroup.hpp" #include "memory/allocation.hpp" +class ThreadClosure; class ZTask; class ZWorkers { diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index 6dbb0c8c31f..0a4a5eb51c5 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -518,6 +518,7 @@ JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly); JNIEXPORT jobjectArray JNICALL JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly); + /* Differs from JVM_GetClassModifiers in treatment of inner classes. This returns the access flags for the class as specified in the class file rather than searching the InnerClasses attribute (if @@ -538,6 +539,14 @@ JVM_GetNestHost(JNIEnv *env, jclass current); JNIEXPORT jobjectArray JNICALL JVM_GetNestMembers(JNIEnv *env, jclass current); +/* Records - since JDK 14 */ + +JNIEXPORT jboolean JNICALL +JVM_IsRecord(JNIEnv *env, jclass cls); + +JNIEXPORT jobjectArray JNICALL +JVM_GetRecordComponents(JNIEnv *env, jclass ofClass); + /* The following two reflection routines are still needed due to startup time issues */ /* * java.lang.reflect.Method @@ -1094,14 +1103,6 @@ typedef struct { JVM_ACC_STRICT | \ JVM_ACC_SYNTHETIC) -/* - * This is the function defined in libjava.so to perform path - * canonicalization. VM call this function before opening jar files - * to load system classes. - * - */ - -typedef int (*canonicalize_fn_t)(JNIEnv *env, char *orig, char *out, int len); /************************************************************************* PART 3: I/O and Network Support diff --git a/src/hotspot/share/jfr/jni/jfrJavaCall.hpp b/src/hotspot/share/jfr/jni/jfrJavaCall.hpp index b140ee846a9..8011b289ad3 100644 --- a/src/hotspot/share/jfr/jni/jfrJavaCall.hpp +++ b/src/hotspot/share/jfr/jni/jfrJavaCall.hpp @@ -28,6 +28,7 @@ #include "jni.h" #include "jfr/utilities/jfrAllocation.hpp" #include "utilities/exceptions.hpp" +#include "utilities/globalDefinitions.hpp" class JavaCallArguments; class JavaThread; @@ -86,8 +87,7 @@ class JfrJavaArguments : public StackObj { int _java_stack_slots; Parameters(); - Parameters(const Parameters&); // no impl - Parameters& operator=(const Parameters&); // no impl + NONCOPYABLE(Parameters); void push(const JavaValue& value); void push_large(const JavaValue& value); diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp index 79656e3b394..624ad097ad1 100644 --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp @@ -370,7 +370,7 @@ bool ReferenceToThreadRootClosure::do_thread_stack_detailed(JavaThread* jt) { JvmtiThreadState* const jvmti_thread_state = jt->jvmti_thread_state(); if (jvmti_thread_state != NULL) { - jvmti_thread_state->oops_do(&rcl); + jvmti_thread_state->oops_do(&rcl, NULL); } return rcl.complete(); diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index 77e2578ab3d..9a039e2ac53 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -465,8 +465,9 @@ - + + @@ -497,7 +498,7 @@ - + @@ -519,6 +520,17 @@ + + + + + + + + + + + @@ -1041,6 +1053,22 @@ + + + + + + + + + + + + + + + + diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp index 244387f19de..12858f88abe 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp @@ -42,6 +42,7 @@ #include "jfr/utilities/jfrTypes.hpp" #include "jfr/writers/jfrJavaEventWriter.hpp" #include "logging/log.hpp" +#include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "runtime/handles.inline.hpp" #include "runtime/mutex.hpp" diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp index 48ace4d6762..6b6229fc162 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp @@ -26,6 +26,7 @@ #include "classfile/javaClasses.inline.hpp" #include "code/codeBlob.hpp" #include "code/codeCache.hpp" +#include "compiler/compilerDefinitions.hpp" #include "gc/shared/gcCause.hpp" #include "gc/shared/gcName.hpp" #include "gc/shared/gcTrace.hpp" @@ -39,6 +40,7 @@ #include "jfr/support/jfrThreadLocal.hpp" #include "jfr/writers/jfrJavaEventWriter.hpp" #include "jfr/utilities/jfrThreadIterator.hpp" +#include "memory/iterator.hpp" #include "memory/metaspaceGCThresholdUpdater.hpp" #include "memory/referenceType.hpp" #include "memory/universe.hpp" @@ -293,3 +295,21 @@ void JfrThreadConstant::serialize(JfrCheckpointWriter& writer) { writer.write((traceid)0); // java thread id writer.write((traceid)0); // java thread group } + +void BytecodeConstant::serialize(JfrCheckpointWriter& writer) { + static const u4 nof_entries = Bytecodes::number_of_codes; + writer.write_count(nof_entries); + for (u4 i = 0; i < nof_entries; ++i) { + writer.write_key(i); + writer.write(Bytecodes::name((Bytecodes::Code)i)); + } +} + +void CompilerTypeConstant::serialize(JfrCheckpointWriter& writer) { + static const u4 nof_entries = compiler_number_of_types; + writer.write_count(nof_entries); + for (u4 i = 0; i < nof_entries; ++i) { + writer.write_key(i); + writer.write(compilertype2name((CompilerType)i)); + } +} diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.hpp index 2ee315d8e8b..ae15c2ac274 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.hpp @@ -115,4 +115,14 @@ class JfrThreadConstant : public JfrSerializer { void serialize(JfrCheckpointWriter& writer); }; +class BytecodeConstant : public JfrSerializer { + public: + void serialize(JfrCheckpointWriter& writer); +}; + +class CompilerTypeConstant : public JfrSerializer { + public: + void serialize(JfrCheckpointWriter& writer); +}; + #endif // SHARE_JFR_RECORDER_CHECKPOINT_TYPES_JFRTYPE_HPP diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp index 8a894e482e4..da674861b74 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp @@ -222,6 +222,8 @@ bool JfrTypeManager::initialize() { register_static_type(TYPE_CODEBLOBTYPE, true, new CodeBlobTypeConstant()); register_static_type(TYPE_VMOPERATIONTYPE, true, new VMOperationTypeConstant()); register_static_type(TYPE_THREADSTATE, true, new ThreadStateConstant()); + register_static_type(TYPE_BYTECODE, true, new BytecodeConstant()); + register_static_type(TYPE_COMPILERTYPE, true, new CompilerTypeConstant()); return true; } diff --git a/src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp b/src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp index 42aa7fb80ea..407315a7312 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrBuffer.cpp @@ -24,11 +24,9 @@ #include "precompiled.hpp" #include "jfr/recorder/storage/jfrBuffer.hpp" -#include "runtime/atomic.hpp" -#include "runtime/orderAccess.hpp" #include "runtime/thread.inline.hpp" -static const u1* const MUTEX_CLAIM = NULL; +static const u1* const TOP_CRITICAL_SECTION = NULL; JfrBuffer::JfrBuffer() : _next(NULL), _prev(NULL), @@ -39,14 +37,13 @@ JfrBuffer::JfrBuffer() : _next(NULL), _header_size(0), _size(0) {} -bool JfrBuffer::initialize(size_t header_size, size_t size, const void* id /* NULL */) { +bool JfrBuffer::initialize(size_t header_size, size_t size) { + assert(_next == NULL, "invariant"); + assert(_identity == NULL, "invariant"); _header_size = (u2)header_size; _size = (u4)(size / BytesPerWord); - assert(_identity == NULL, "invariant"); - _identity = id; set_pos(start()); set_top(start()); - assert(_next == NULL, "invariant"); assert(free_size() == size, "invariant"); assert(!transient(), "invariant"); assert(!lease(), "invariant"); @@ -55,9 +52,9 @@ bool JfrBuffer::initialize(size_t header_size, size_t size, const void* id /* NU } void JfrBuffer::reinitialize(bool exclusion /* false */) { + acquire_critical_section_top(); assert(!lease(), "invariant"); assert(!transient(), "invariant"); - set_pos(start()); if (exclusion != excluded()) { // update if (exclusion) { @@ -66,80 +63,43 @@ void JfrBuffer::reinitialize(bool exclusion /* false */) { clear_excluded(); } } - clear_retired(); - set_top(start()); -} - -void JfrBuffer::concurrent_reinitialization() { - concurrent_top(); - assert(!lease(), "invariant"); - assert(!transient(), "invariant"); set_pos(start()); - set_concurrent_top(start()); + release_critical_section_top(start()); clear_retired(); } -size_t JfrBuffer::discard() { - size_t discard_size = unflushed_size(); - set_top(pos()); - return discard_size; +const u1* JfrBuffer::top() const { + return Atomic::load_acquire(&_top); } const u1* JfrBuffer::stable_top() const { const u1* current_top; do { - current_top = Atomic::load(&_top); - } while (MUTEX_CLAIM == current_top); + current_top = top(); + } while (TOP_CRITICAL_SECTION == current_top); return current_top; } -const u1* JfrBuffer::top() const { - return _top; -} - void JfrBuffer::set_top(const u1* new_top) { - _top = new_top; + assert(new_top <= end(), "invariant"); + assert(new_top >= start(), "invariant"); + Atomic::release_store(&_top, new_top); } -const u1* JfrBuffer::concurrent_top() const { +const u1* JfrBuffer::acquire_critical_section_top() const { do { const u1* current_top = stable_top(); - if (Atomic::cmpxchg(&_top, current_top, MUTEX_CLAIM) == current_top) { + assert(current_top != TOP_CRITICAL_SECTION, "invariant"); + if (Atomic::cmpxchg(&_top, current_top, TOP_CRITICAL_SECTION) == current_top) { return current_top; } } while (true); } -void JfrBuffer::set_concurrent_top(const u1* new_top) { - assert(new_top != MUTEX_CLAIM, "invariant"); - assert(new_top <= end(), "invariant"); - assert(new_top >= start(), "invariant"); - assert(top() == MUTEX_CLAIM, "invariant"); - OrderAccess::storestore(); - _top = new_top; -} - -size_t JfrBuffer::unflushed_size() const { - return pos() - stable_top(); -} - -void JfrBuffer::acquire(const void* id) { - assert(id != NULL, "invariant"); - const void* current_id; - do { - current_id = Atomic::load(&_identity); - } while (current_id != NULL || Atomic::cmpxchg(&_identity, current_id, id) != current_id); -} - -bool JfrBuffer::try_acquire(const void* id) { - assert(id != NULL, "invariant"); - const void* const current_id = Atomic::load(&_identity); - return current_id == NULL && Atomic::cmpxchg(&_identity, current_id, id) == current_id; -} - -void JfrBuffer::release() { - OrderAccess::storestore(); - _identity = NULL; +void JfrBuffer::release_critical_section_top(const u1* new_top) { + assert(new_top != TOP_CRITICAL_SECTION, "invariant"); + assert(top() == TOP_CRITICAL_SECTION, "invariant"); + set_top(new_top); } bool JfrBuffer::acquired_by(const void* id) const { @@ -150,6 +110,25 @@ bool JfrBuffer::acquired_by_self() const { return acquired_by(Thread::current()); } +void JfrBuffer::acquire(const void* id) { + assert(id != NULL, "invariant"); + const void* current_id; + do { + current_id = identity(); + } while (current_id != NULL || Atomic::cmpxchg(&_identity, current_id, id) != current_id); +} + +bool JfrBuffer::try_acquire(const void* id) { + assert(id != NULL, "invariant"); + const void* const current_id = identity(); + return current_id == NULL && Atomic::cmpxchg(&_identity, current_id, id) == current_id; +} + +void JfrBuffer::release() { + assert(identity() != NULL, "invariant"); + Atomic::release_store(&_identity, (const void*)NULL); +} + #ifdef ASSERT static bool validate_to(const JfrBuffer* const to, size_t size) { assert(to != NULL, "invariant"); @@ -158,39 +137,40 @@ static bool validate_to(const JfrBuffer* const to, size_t size) { return true; } -static bool validate_concurrent_this(const JfrBuffer* const t, size_t size) { - assert(t->top() == MUTEX_CLAIM, "invariant"); - return true; -} - static bool validate_this(const JfrBuffer* const t, size_t size) { - assert(t->top() + size <= t->pos(), "invariant"); + assert(t->acquired_by_self(), "invariant"); + assert(t->top() == TOP_CRITICAL_SECTION, "invariant"); return true; } #endif // ASSERT void JfrBuffer::move(JfrBuffer* const to, size_t size) { assert(validate_to(to, size), "invariant"); + const u1* const current_top = acquire_critical_section_top(); assert(validate_this(this, size), "invariant"); - const u1* current_top = top(); - assert(current_top != NULL, "invariant"); - memcpy(to->pos(), current_top, size); - to->set_pos(size); + const size_t actual_size = pos() - current_top; + assert(actual_size <= size, "invariant"); + if (actual_size > 0) { + memcpy(to->pos(), current_top, actual_size); + to->set_pos(actual_size); + } to->release(); - set_top(current_top + size); + set_pos(start()); + release_critical_section_top(start()); } -void JfrBuffer::concurrent_move_and_reinitialize(JfrBuffer* const to, size_t size) { - assert(validate_to(to, size), "invariant"); - const u1* current_top = concurrent_top(); - assert(validate_concurrent_this(this, size), "invariant"); - const size_t actual_size = MIN2(size, (size_t)(pos() - current_top)); - assert(actual_size <= size, "invariant"); - memcpy(to->pos(), current_top, actual_size); - to->set_pos(actual_size); - set_pos(start()); - to->release(); - set_concurrent_top(start()); +size_t JfrBuffer::discard() { + const u1* const position = pos(); + // stable_top() provides acquire semantics for pos() + const u1* const current_top = stable_top(); + set_top(position); + return position - current_top; +} + +size_t JfrBuffer::unflushed_size() const { + const u1* const position = pos(); + // stable_top() provides acquire semantics for pos() + return position - stable_top(); } enum FLAG { @@ -200,67 +180,93 @@ enum FLAG { EXCLUDED = 8 }; +inline u2 load(const volatile u2* flags) { + assert(flags != NULL, "invariant"); + return Atomic::load_acquire(flags); +} + +inline void set(u2* flags, FLAG flag) { + assert(flags != NULL, "invariant"); + OrderAccess::storestore(); + *flags |= (u1)flag; +} + +inline void clear(u2* flags, FLAG flag) { + assert(flags != NULL, "invariant"); + OrderAccess::storestore(); + *flags ^= (u1)flag; +} + +inline bool test(const u2* flags, FLAG flag) { + return (u1)flag == (load(flags) & (u1)flag); +} + bool JfrBuffer::transient() const { - return (u1)TRANSIENT == (_flags & (u1)TRANSIENT); + return test(&_flags, TRANSIENT); } void JfrBuffer::set_transient() { - _flags |= (u1)TRANSIENT; + assert(acquired_by_self(), "invariant"); + set(&_flags, TRANSIENT); assert(transient(), "invariant"); } void JfrBuffer::clear_transient() { if (transient()) { - _flags ^= (u1)TRANSIENT; + assert(acquired_by_self(), "invariant"); + clear(&_flags, TRANSIENT); } assert(!transient(), "invariant"); } bool JfrBuffer::lease() const { - return (u1)LEASE == (_flags & (u1)LEASE); + return test(&_flags, LEASE); } void JfrBuffer::set_lease() { - _flags |= (u1)LEASE; + assert(acquired_by_self(), "invariant"); + set(&_flags, LEASE); assert(lease(), "invariant"); } void JfrBuffer::clear_lease() { if (lease()) { - _flags ^= (u1)LEASE; + assert(acquired_by_self(), "invariant"); + clear(&_flags, LEASE); } assert(!lease(), "invariant"); } bool JfrBuffer::excluded() const { - return (u1)EXCLUDED == (_flags & (u1)EXCLUDED); + return test(&_flags, EXCLUDED); } void JfrBuffer::set_excluded() { - _flags |= (u1)EXCLUDED; + assert(acquired_by_self(), "invariant"); + set(&_flags, EXCLUDED); assert(excluded(), "invariant"); } void JfrBuffer::clear_excluded() { if (excluded()) { - OrderAccess::storestore(); - _flags ^= (u1)EXCLUDED; + assert(identity() != NULL, "invariant"); + clear(&_flags, EXCLUDED); } assert(!excluded(), "invariant"); } bool JfrBuffer::retired() const { - return (_flags & (u1)RETIRED) == (u1)RETIRED; + return test(&_flags, RETIRED); } void JfrBuffer::set_retired() { - OrderAccess::storestore(); - _flags |= (u1)RETIRED; + assert(acquired_by_self(), "invariant"); + set(&_flags, RETIRED); } void JfrBuffer::clear_retired() { if (retired()) { - OrderAccess::storestore(); - _flags ^= (u1)RETIRED; + assert(identity() != NULL, "invariant"); + clear(&_flags, RETIRED); } } diff --git a/src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp b/src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp index ae548d38f3b..b7dc7ecacd9 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrBuffer.hpp @@ -26,32 +26,46 @@ #define SHARE_JFR_RECORDER_STORAGE_JFRBUFFER_HPP #include "memory/allocation.hpp" +#include "runtime/atomic.hpp" // // Represents a piece of committed memory. // -// u1* _pos <-- next store position +// Use acquire() and/or try_acquire() for exclusive access +// to the buffer (cas identity). This is a precondition +// for attempting stores. +// +// u1* _pos <-- last committed position // u1* _top <-- next unflushed position // -// const void* _identity <-- acquired by -// -// Must be the owner before attempting stores. -// Use acquire() and/or try_acquire() for exclusive access -// to the (entire) buffer (cas identity). -// -// Stores to the buffer should uphold transactional semantics. -// A new _pos must be updated only after all intended stores have completed. +// Stores must uphold transactional semantics. This means that _pos +// must be updated only after all intended stores have completed already. // The relation between _pos and _top must hold atomically, // e.g. the delta must always be fully parsable. // _top can move concurrently by other threads but is always <= _pos. // +// Memory ordering: +// +// Method Owner thread Other threads +// --------------------------------------------------------------- +// acquire() Acquire semantics (cas) Acquire semantics (cas) +// try_acquire() Acquire semantics (cas) Acquire semantics (cas) +// release() Release semantics Release semantics +// pos() Plain load Acquire semantics needed at call sites +// set_pos() Release semantics N/A +// top() Acquire semantics Acquire semantics +// set_top() Release semantics Release semantics +// acquire_crit_sec_top() Acquire semantics (cas) Acquire semantics (cas) +// release_crit_sec_top() Release semantics Release semantics +// + class JfrBuffer { private: JfrBuffer* _next; JfrBuffer* _prev; - const void* volatile _identity; + const void* _identity; u1* _pos; - mutable const u1* volatile _top; + mutable const u1* _top; u2 _flags; u2 _header_size; u4 _size; @@ -60,10 +74,9 @@ class JfrBuffer { public: JfrBuffer(); - bool initialize(size_t header_size, size_t size, const void* id = NULL); + bool initialize(size_t header_size, size_t size); void reinitialize(bool exclusion = false); - void concurrent_reinitialization(); - size_t discard(); + JfrBuffer* next() const { return _next; } @@ -92,6 +105,8 @@ class JfrBuffer { return start() + size(); } + // If pos() methods are invoked by a thread that is not the owner, + // then acquire semantics must be ensured at the call site. const u1* pos() const { return _pos; } @@ -101,48 +116,45 @@ class JfrBuffer { } u1** pos_address() { - return (u1**)&_pos; + return &_pos; } void set_pos(u1* new_pos) { assert(new_pos <= end(), "invariant"); - _pos = new_pos; + Atomic::release_store(&_pos, new_pos); } void set_pos(size_t size) { - assert(_pos + size <= end(), "invariant"); - _pos += size; + set_pos(pos() + size); } const u1* top() const; void set_top(const u1* new_top); - const u1* concurrent_top() const; - void set_concurrent_top(const u1* new_top); - size_t header_size() const { - return _header_size; - } + // mutual exclusion + const u1* acquire_critical_section_top() const; + void release_critical_section_top(const u1* new_top); size_t size() const { return _size * BytesPerWord; } size_t total_size() const { - return header_size() + size(); + return _header_size + size(); } size_t free_size() const { - return end() - pos(); + return end() - Atomic::load_acquire(&_pos); } size_t unflushed_size() const; bool empty() const { - return pos() == start(); + return Atomic::load_acquire(&_pos) == start(); } const void* identity() const { - return _identity; + return Atomic::load_acquire(&_identity); } void acquire(const void* id); @@ -151,8 +163,8 @@ class JfrBuffer { bool acquired_by_self() const; void release(); + size_t discard(); void move(JfrBuffer* const to, size_t size); - void concurrent_move_and_reinitialize(JfrBuffer* const to, size_t size); bool transient() const; void set_transient(); diff --git a/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp b/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp index 346a6a9d636..4909cd9f9d8 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp @@ -426,9 +426,11 @@ inline bool ReleaseOp::process(typename Mspace::Type* t) { return true; } t->reinitialize(); - assert(t->empty(), "invariant"); - assert(!t->retired(), "invariant"); - t->release(); // publish + if (t->identity() != NULL) { + assert(t->empty(), "invariant"); + assert(!t->retired(), "invariant"); + t->release(); // publish + } return true; } diff --git a/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp b/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp index 8dd4f3f44af..594507356a7 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp @@ -234,7 +234,7 @@ static void write_data_loss_event(JfrBuffer* buffer, u8 unflushed_size, Thread* static void write_data_loss(BufferPtr buffer, Thread* thread) { assert(buffer != NULL, "invariant"); const size_t unflushed_size = buffer->unflushed_size(); - buffer->concurrent_reinitialization(); + buffer->reinitialize(); if (unflushed_size == 0) { return; } @@ -249,7 +249,7 @@ bool JfrStorage::flush_regular_buffer(BufferPtr buffer, Thread* thread) { assert(!buffer->transient(), "invariant"); const size_t unflushed_size = buffer->unflushed_size(); if (unflushed_size == 0) { - buffer->concurrent_reinitialization(); + buffer->reinitialize(); assert(buffer->empty(), "invariant"); return true; } @@ -272,7 +272,7 @@ bool JfrStorage::flush_regular_buffer(BufferPtr buffer, Thread* thread) { } assert(promotion_buffer->acquired_by_self(), "invariant"); assert(promotion_buffer->free_size() >= unflushed_size, "invariant"); - buffer->concurrent_move_and_reinitialize(promotion_buffer, unflushed_size); + buffer->move(promotion_buffer, unflushed_size); assert(buffer->empty(), "invariant"); return true; } @@ -313,7 +313,7 @@ static void handle_registration_failure(BufferPtr buffer) { assert(buffer != NULL, "invariant"); assert(buffer->retired(), "invariant"); const size_t unflushed_size = buffer->unflushed_size(); - buffer->concurrent_reinitialization(); + buffer->reinitialize(); log_registration_failure(unflushed_size); } @@ -388,7 +388,7 @@ void JfrStorage::release(BufferPtr buffer, Thread* thread) { assert(!buffer->retired(), "invariant"); if (!buffer->empty()) { if (!flush_regular_buffer(buffer, thread)) { - buffer->concurrent_reinitialization(); + buffer->reinitialize(); } } assert(buffer->empty(), "invariant"); @@ -431,6 +431,7 @@ void JfrStorage::discard_oldest(Thread* thread) { assert(oldest_age_node->identity() == NULL, "invariant"); BufferPtr const buffer = oldest_age_node->retired_buffer(); assert(buffer->retired(), "invariant"); + assert(buffer->identity() != NULL, "invariant"); discarded_size += buffer->discard(); assert(buffer->unflushed_size() == 0, "invariant"); num_full_post_discard = control().decrement_full(); diff --git a/src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.inline.hpp b/src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.inline.hpp index b0160acaa06..33b5b0dccfb 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.inline.hpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrStorageUtils.inline.hpp @@ -26,6 +26,7 @@ #define SHARE_JFR_RECORDER_STORAGE_JFRSTORAGEUTILS_INLINE_HPP #include "jfr/recorder/storage/jfrStorageUtils.hpp" +#include "runtime/atomic.hpp" #include "runtime/thread.inline.hpp" template @@ -43,29 +44,36 @@ inline bool DefaultDiscarder::discard(T* t, const u1* data, size_t size) { return true; } +template +inline size_t get_unflushed_size(const u1* top, Type* t) { + assert(t != NULL, "invariant"); + return Atomic::load_acquire(t->pos_address()) - top; +} + template inline bool ConcurrentWriteOp::process(typename Operation::Type* t) { - const u1* const current_top = t->concurrent_top(); - const size_t unflushed_size = t->pos() - current_top; + // acquire_critical_section_top() must be read before pos() for stable access + const u1* const top = t->acquire_critical_section_top(); + const size_t unflushed_size = get_unflushed_size(top, t); if (unflushed_size == 0) { - t->set_concurrent_top(current_top); + t->release_critical_section_top(top); return true; } - const bool result = _operation.write(t, current_top, unflushed_size); - t->set_concurrent_top(current_top + unflushed_size); + const bool result = _operation.write(t, top, unflushed_size); + t->release_critical_section_top(top + unflushed_size); return result; } template inline bool MutexedWriteOp::process(typename Operation::Type* t) { assert(t != NULL, "invariant"); - const u1* const current_top = t->top(); - const size_t unflushed_size = t->pos() - current_top; + const u1* const top = t->top(); + const size_t unflushed_size = get_unflushed_size(top, t); if (unflushed_size == 0) { return true; } - const bool result = _operation.write(t, current_top, unflushed_size); - t->set_top(current_top + unflushed_size); + const bool result = _operation.write(t, top, unflushed_size); + t->set_top(top + unflushed_size); return result; } @@ -94,19 +102,19 @@ inline bool ExclusiveOp::process(typename Operation::Type* t) { template inline bool DiscardOp::process(typename Operation::Type* t) { assert(t != NULL, "invariant"); - const u1* const current_top = _mode == concurrent ? t->concurrent_top() : t->top(); - const size_t unflushed_size = t->pos() - current_top; + const u1* const top = _mode == concurrent ? t->acquire_critical_section_top() : t->top(); + const size_t unflushed_size = get_unflushed_size(top, t); if (unflushed_size == 0) { if (_mode == concurrent) { - t->set_concurrent_top(current_top); + t->release_critical_section_top(top); } return true; } - const bool result = _operation.discard(t, current_top, unflushed_size); + const bool result = _operation.discard(t, top, unflushed_size); if (_mode == concurrent) { - t->set_concurrent_top(current_top + unflushed_size); + t->release_critical_section_top(top + unflushed_size); } else { - t->set_top(current_top + unflushed_size); + t->set_top(top + unflushed_size); } return result; } diff --git a/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp b/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp index 162a44f287f..32162fc399b 100644 --- a/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp +++ b/src/hotspot/share/jfr/writers/jfrJavaEventWriter.cpp @@ -32,6 +32,7 @@ #include "jfr/support/jfrThreadId.hpp" #include "jfr/utilities/jfrTypes.hpp" #include "jfr/writers/jfrJavaEventWriter.hpp" +#include "memory/iterator.hpp" #include "oops/instanceKlass.hpp" #include "oops/oop.inline.hpp" #include "runtime/fieldDescriptor.inline.hpp" diff --git a/src/hotspot/share/libadt/dict.cpp b/src/hotspot/share/libadt/dict.cpp index f22396ed094..ade158824cc 100644 --- a/src/hotspot/share/libadt/dict.cpp +++ b/src/hotspot/share/libadt/dict.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "libadt/dict.hpp" +#include "utilities/powerOfTwo.hpp" // Dictionaries - An Abstract Data Type @@ -86,8 +87,7 @@ Dict::Dict(CmpKey initcmp, Hash inithash, Arena *arena, int size) initflag = 1; // Never again } - i=16; - while( i < size ) i <<= 1; + i = MAX2(16, round_up_power_of_2(size)); _size = i; // Size is a power of 2 _cnt = 0; // Dictionary is empty _bin = (bucket*)_arena->Amalloc_4(sizeof(bucket)*_size); diff --git a/src/hotspot/share/libadt/vectset.cpp b/src/hotspot/share/libadt/vectset.cpp index e6afd62b5ae..603f73aa61b 100644 --- a/src/hotspot/share/libadt/vectset.cpp +++ b/src/hotspot/share/libadt/vectset.cpp @@ -27,6 +27,7 @@ #include "memory/allocation.inline.hpp" #include "memory/arena.hpp" #include "utilities/count_leading_zeros.hpp" +#include "utilities/powerOfTwo.hpp" VectorSet::VectorSet(Arena *arena) : _size(2), _data(NEW_ARENA_ARRAY(arena, uint32_t, 2)), @@ -38,8 +39,8 @@ VectorSet::VectorSet(Arena *arena) : _size(2), // Expand the existing set to a bigger size void VectorSet::grow(uint new_size) { new_size = (new_size + bit_mask) >> word_bits; - assert(new_size != 0 && new_size < (1U << 31), ""); - uint x = (1U << 31) >> (count_leading_zeros(new_size) - 1); + assert(new_size > 0, "sanity"); + uint x = next_power_of_2(new_size); _data = REALLOC_ARENA_ARRAY(_set_arena, uint32_t, _data, _size, x); Copy::zero_to_bytes(_data + _size, (x - _size) * sizeof(uint32_t)); _size = x; diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp index e9ce26fae9e..891c05b06d4 100644 --- a/src/hotspot/share/logging/logTag.hpp +++ b/src/hotspot/share/logging/logTag.hpp @@ -137,6 +137,7 @@ LOG_TAG(parser) \ LOG_TAG(ptrqueue) \ LOG_TAG(purge) \ + LOG_TAG(record) \ LOG_TAG(resolve) \ LOG_TAG(safepoint) \ LOG_TAG(sampling) \ diff --git a/src/hotspot/share/memory/allocation.hpp b/src/hotspot/share/memory/allocation.hpp index 9840cba3ed1..b767b0c2491 100644 --- a/src/hotspot/share/memory/allocation.hpp +++ b/src/hotspot/share/memory/allocation.hpp @@ -300,7 +300,8 @@ class MetaspaceObj { f(ConstantPool) \ f(ConstantPoolCache) \ f(Annotations) \ - f(MethodCounters) + f(MethodCounters) \ + f(RecordComponent) #define METASPACE_OBJ_TYPE_DECLARE(name) name ## Type, #define METASPACE_OBJ_TYPE_NAME_CASE(name) case name ## Type: return #name; diff --git a/src/hotspot/share/memory/heapInspection.hpp b/src/hotspot/share/memory/heapInspection.hpp index 4d2d64c8455..4141a0e5da6 100644 --- a/src/hotspot/share/memory/heapInspection.hpp +++ b/src/hotspot/share/memory/heapInspection.hpp @@ -88,6 +88,8 @@ "Number of bytes used by the InstanceKlass::inner_classes() array") \ f(nest_members_bytes, IK_nest_members, \ "Number of bytes used by the InstanceKlass::nest_members() array") \ + f(record_components_bytes, IK_record_components, \ + "Number of bytes used by the InstanceKlass::record_components() array") \ f(signers_bytes, IK_signers, \ "Number of bytes used by the InstanceKlass::singers() array") \ f(class_annotations_bytes, class_annotations, \ diff --git a/src/hotspot/share/memory/iterator.hpp b/src/hotspot/share/memory/iterator.hpp index 73f1b41ebc6..520acf30d0f 100644 --- a/src/hotspot/share/memory/iterator.hpp +++ b/src/hotspot/share/memory/iterator.hpp @@ -37,11 +37,18 @@ class KlassClosure; class ClassLoaderData; class Symbol; class Metadata; +class Thread; // The following classes are C++ `closures` for iterating over objects, roots and spaces class Closure : public StackObj { }; +// Thread iterator +class ThreadClosure: public Closure { + public: + virtual void do_thread(Thread* thread) = 0; +}; + // OopClosure is used for iterating through references to Java objects. class OopClosure : public Closure { public: diff --git a/src/hotspot/share/memory/metaspaceClosure.hpp b/src/hotspot/share/memory/metaspaceClosure.hpp index 0bc8948283c..879b89df99c 100644 --- a/src/hotspot/share/memory/metaspaceClosure.hpp +++ b/src/hotspot/share/memory/metaspaceClosure.hpp @@ -28,6 +28,7 @@ #include "logging/log.hpp" #include "memory/allocation.hpp" #include "oops/array.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.inline.hpp" @@ -108,9 +109,8 @@ public: class Ref : public CHeapObj { Writability _writability; Ref* _next; - // Noncopyable. - Ref(const Ref&); - Ref& operator=(const Ref&); + NONCOPYABLE(Ref); + protected: virtual void** mpp() const = 0; Ref(Writability w) : _writability(w), _next(NULL) {} diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp index a181a434d50..eb7dfee76e7 100644 --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -823,6 +823,7 @@ intptr_t* MetaspaceShared::fix_cpp_vtable_for_dynamic_archive(MetaspaceObj::Type case MetaspaceObj::ConstantPoolCacheType: case MetaspaceObj::AnnotationsType: case MetaspaceObj::MethodCountersType: + case MetaspaceObj::RecordComponentType: // These have no vtables. break; case MetaspaceObj::ClassType: diff --git a/src/hotspot/share/oops/array.hpp b/src/hotspot/share/oops/array.hpp index 543907e21ad..f383564ac84 100644 --- a/src/hotspot/share/oops/array.hpp +++ b/src/hotspot/share/oops/array.hpp @@ -29,6 +29,7 @@ #include "memory/metaspace.hpp" #include "runtime/atomic.hpp" #include "utilities/align.hpp" +#include "utilities/globalDefinitions.hpp" // Array for metadata allocation @@ -49,9 +50,7 @@ protected: } private: - // Turn off copy constructor and assignment operator. - Array(const Array&); - void operator=(const Array&); + NONCOPYABLE(Array); void* operator new(size_t size, ClassLoaderData* loader_data, int length, TRAPS) throw() { size_t word_size = Array::size(length); diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 003121e3200..8f1ed169f6a 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -63,6 +63,7 @@ #include "oops/klass.inline.hpp" #include "oops/method.hpp" #include "oops/oop.inline.hpp" +#include "oops/recordComponent.hpp" #include "oops/symbol.hpp" #include "prims/jvmtiExport.hpp" #include "prims/jvmtiRedefineClasses.hpp" @@ -436,6 +437,7 @@ InstanceKlass::InstanceKlass(const ClassFileParser& parser, unsigned kind, Klass _nest_members(NULL), _nest_host_index(0), _nest_host(NULL), + _record_components(NULL), _static_field_size(parser.static_field_size()), _nonstatic_oop_map_size(nonstatic_oop_map_size(parser.total_oop_map_count())), _itable_len(parser.itable_size()), @@ -504,6 +506,17 @@ void InstanceKlass::deallocate_interfaces(ClassLoaderData* loader_data, } } +void InstanceKlass::deallocate_record_components(ClassLoaderData* loader_data, + Array* record_components) { + if (record_components != NULL && !record_components->is_shared()) { + for (int i = 0; i < record_components->length(); i++) { + RecordComponent* record_component = record_components->at(i); + MetadataFactory::free_metadata(loader_data, record_component); + } + MetadataFactory::free_array(loader_data, record_components); + } +} + // This function deallocates the metadata and C heap pointers that the // InstanceKlass points to. void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { @@ -532,6 +545,9 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { deallocate_methods(loader_data, methods()); set_methods(NULL); + deallocate_record_components(loader_data, record_components()); + set_record_components(NULL); + if (method_ordering() != NULL && method_ordering() != Universe::the_empty_int_array() && !method_ordering()->is_shared()) { @@ -2339,6 +2355,7 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) { } it->push(&_nest_members); + it->push(&_record_components); } void InstanceKlass::remove_unshareable_info() { @@ -3270,6 +3287,9 @@ void InstanceKlass::print_on(outputStream* st) const { } st->print(BULLET"inner classes: "); inner_classes()->print_value_on(st); st->cr(); st->print(BULLET"nest members: "); nest_members()->print_value_on(st); st->cr(); + if (record_components() != NULL) { + st->print(BULLET"record components: "); record_components()->print_value_on(st); st->cr(); + } if (java_mirror() != NULL) { st->print(BULLET"java mirror: "); java_mirror()->print_value_on(st); @@ -3532,6 +3552,7 @@ void InstanceKlass::collect_statistics(KlassSizeStats *sz) const { n += (sz->_fields_bytes = sz->count_array(fields())); n += (sz->_inner_classes_bytes = sz->count_array(inner_classes())); n += (sz->_nest_members_bytes = sz->count_array(nest_members())); + n += (sz->_record_components_bytes = sz->count_array(record_components())); sz->_ro_bytes += n; const ConstantPool* cp = constants(); @@ -3554,6 +3575,17 @@ void InstanceKlass::collect_statistics(KlassSizeStats *sz) const { } } } + + const Array* components = record_components(); + if (components != NULL) { + for (int i = 0; i < components->length(); i++) { + RecordComponent* component = components->at(i); + if (component != NULL) { + component->collect_statistics(sz); + } + } + } + } #endif // INCLUDE_SERVICES diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 58accb1b1f9..0203ac88601 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -41,6 +41,7 @@ #include "jfr/support/jfrKlassExtension.hpp" #endif +class RecordComponent; // An InstanceKlass is the VM level representation of a Java class. // It contains all information needed for at class at execution runtime. @@ -182,6 +183,9 @@ class InstanceKlass: public Klass { // By always being set it makes nest-member access checks simpler. InstanceKlass* _nest_host; + // The contents of the Record attribute. + Array* _record_components; + // the source debug extension for this klass, NULL if not specified. // Specified as UTF-8 string without terminating zero byte in the classfile, // it is stored in the instanceklass as a NULL-terminated UTF-8 string @@ -448,9 +452,17 @@ class InstanceKlass: public Klass { jushort nest_host_index() const { return _nest_host_index; } void set_nest_host_index(u2 i) { _nest_host_index = i; } + // record components + Array* record_components() const { return _record_components; } + void set_record_components(Array* record_components) { + _record_components = record_components; + } + bool is_record() const { return _record_components != NULL; } + private: // Called to verify that k is a member of this nest - does not look at k's nest-host bool has_nest_member(InstanceKlass* k, TRAPS) const; + public: // Returns nest-host class, resolving and validating it if needed // Returns NULL if an exception occurs during loading, or validation fails @@ -1152,6 +1164,8 @@ public: const Klass* super_klass, Array* local_interfaces, Array* transitive_interfaces); + void static deallocate_record_components(ClassLoaderData* loader_data, + Array* record_component); // The constant pool is on stack if any of the methods are executing or // referenced by handles. diff --git a/src/hotspot/share/oops/recordComponent.cpp b/src/hotspot/share/oops/recordComponent.cpp new file mode 100644 index 00000000000..f4c22c237d5 --- /dev/null +++ b/src/hotspot/share/oops/recordComponent.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "logging/log.hpp" +#include "memory/heapInspection.hpp" +#include "memory/metadataFactory.hpp" +#include "memory/metaspace.hpp" +#include "memory/metaspaceClosure.hpp" +#include "oops/annotations.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/recordComponent.hpp" +#include "utilities/globalDefinitions.hpp" + +RecordComponent* RecordComponent::allocate(ClassLoaderData* loader_data, + u2 name_index, u2 descriptor_index, + u2 attributes_count, + u2 generic_signature_index, + AnnotationArray* annotations, + AnnotationArray* type_annotations, TRAPS) { + return new (loader_data, size(), MetaspaceObj::RecordComponentType, THREAD) + RecordComponent(name_index, descriptor_index, attributes_count, + generic_signature_index, annotations, type_annotations); +} + +void RecordComponent::deallocate_contents(ClassLoaderData* loader_data) { + if (annotations() != NULL) { + MetadataFactory::free_array(loader_data, annotations()); + } + if (type_annotations() != NULL) { + MetadataFactory::free_array(loader_data, type_annotations()); + } +} + +void RecordComponent::metaspace_pointers_do(MetaspaceClosure* it) { + log_trace(cds)("Iter(RecordComponent): %p", this); + it->push(&_annotations); + it->push(&_type_annotations); +} + +void RecordComponent::print_value_on(outputStream* st) const { + st->print("RecordComponent(" INTPTR_FORMAT ")", p2i(this)); +} + +#if INCLUDE_SERVICES +void RecordComponent::collect_statistics(KlassSizeStats *sz) const { + if (_annotations != NULL) { + sz->_annotations_bytes += sz->count(_annotations); + sz->_ro_bytes += sz->count(_annotations); + } + if (_type_annotations != NULL) { + sz->_annotations_bytes += sz->count(_type_annotations); + sz->_ro_bytes += sz->count(_type_annotations); + } +} +#endif + +#ifndef PRODUCT +void RecordComponent::print_on(outputStream* st) const { + st->print("name_index: %d", _name_index); + st->print(" - descriptor_index: %d", _descriptor_index); + st->print(" - attributes_count: %d", _attributes_count); + if (_generic_signature_index != 0) { + st->print(" - generic_signature_index: %d", _generic_signature_index); + } + st->cr(); + if (_annotations != NULL) { + st->print_cr("record component annotations"); + _annotations->print_value_on(st); + } + if (_type_annotations != NULL) { + st->print_cr("record component type annotations"); + _type_annotations->print_value_on(st); + } +} +#endif // PRODUCT diff --git a/src/hotspot/share/oops/recordComponent.hpp b/src/hotspot/share/oops/recordComponent.hpp new file mode 100644 index 00000000000..c77cf4aa323 --- /dev/null +++ b/src/hotspot/share/oops/recordComponent.hpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_OOPS_RECORDCOMPONENT_HPP +#define SHARE_OOPS_RECORDCOMPONENT_HPP + +#include "oops/annotations.hpp" +#include "oops/metadata.hpp" +#include "utilities/globalDefinitions.hpp" + +class KlassSizeStats; + +// This class stores information extracted from the Record class attribute. +class RecordComponent: public MetaspaceObj { + private: + AnnotationArray* _annotations; + AnnotationArray* _type_annotations; + u2 _name_index; + u2 _descriptor_index; + u2 _attributes_count; + + // generic_signature_index gets set if the Record component has a Signature + // attribute. A zero value indicates that there was no Signature attribute. + u2 _generic_signature_index; + + public: + RecordComponent(u2 name_index, u2 descriptor_index, u2 attributes_count, + u2 generic_signature_index, AnnotationArray* annotations, + AnnotationArray* type_annotations): + _annotations(annotations), _type_annotations(type_annotations), + _name_index(name_index), _descriptor_index(descriptor_index), + _attributes_count(attributes_count), + _generic_signature_index(generic_signature_index) { } + + // Allocate instance of this class + static RecordComponent* allocate(ClassLoaderData* loader_data, + u2 name_index, u2 descriptor_index, + u2 attributes_count, + u2 generic_signature_index, + AnnotationArray* annotations, + AnnotationArray* type_annotations, TRAPS); + + void deallocate_contents(ClassLoaderData* loader_data); + + u2 name_index() const { return _name_index; } + void set_name_index(u2 name_index) { _name_index = name_index; } + + u2 descriptor_index() const { return _descriptor_index; } + void set_descriptor_index(u2 descriptor_index) { + _descriptor_index = descriptor_index; + } + + u2 attributes_count() const { return _attributes_count; } + + u2 generic_signature_index() const { return _generic_signature_index; } + void set_generic_signature_index(u2 generic_signature_index) { + _generic_signature_index = generic_signature_index; + } + + AnnotationArray* annotations() const { return _annotations; } + AnnotationArray* type_annotations() const { return _type_annotations; } + + // Size of RecordComponent, not including size of any annotations. + static int size() { return sizeof(RecordComponent) / wordSize; } + + void metaspace_pointers_do(MetaspaceClosure* it); + MetaspaceObj::Type type() const { return RecordComponentType; } + + // Record_components should be stored in the read-only region of CDS archive. + static bool is_read_only_by_default() { return true; } + DEBUG_ONLY(bool on_stack() { return false; }) // for template + +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif + + bool is_klass() const { return false; } + +#ifndef PRODUCT + void print_on(outputStream* st) const; +#endif + void print_value_on(outputStream* st) const; + +}; + +#endif // SHARE_OOPS_RECORDCOMPONENT_HPP diff --git a/src/hotspot/share/opto/block.cpp b/src/hotspot/share/opto/block.cpp index 444e893b3d6..bbc9626bf6f 100644 --- a/src/hotspot/share/opto/block.cpp +++ b/src/hotspot/share/opto/block.cpp @@ -36,6 +36,7 @@ #include "opto/opcodes.hpp" #include "opto/rootnode.hpp" #include "utilities/copy.hpp" +#include "utilities/powerOfTwo.hpp" void Block_Array::grow( uint i ) { assert(i >= Max(), "must be an overflow"); @@ -47,7 +48,7 @@ void Block_Array::grow( uint i ) { _blocks[0] = NULL; } uint old = _size; - while( i >= _size ) _size <<= 1; // Double to fit + _size = next_power_of_2(i); _blocks = (Block**)_arena->Arealloc( _blocks, old*sizeof(Block*),_size*sizeof(Block*)); Copy::zero_to_bytes( &_blocks[old], (_size-old)*sizeof(Block*) ); } diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 08552e0756f..595176ba48c 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -2466,7 +2466,11 @@ void Compile::Code_Gen() { { TracePhase tp("matcher", &timers[_t_matcher]); matcher.match(); + if (failing()) { + return; + } } + // In debug mode can dump m._nodes.dump() for mapping of ideal to machine // nodes. Mapping is only valid at the root of each matched subtree. NOT_PRODUCT( verify_graph_edges(); ) diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 48e18095133..e72d5cc265a 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -654,8 +654,8 @@ void PhaseIdealLoop::do_peeling(IdealLoopTree *loop, Node_List &old_new) { // Step 4: Correct dom-depth info. Set to loop-head depth. - int dd = dom_depth(head); - set_idom(head, head->in(1), dd); + int dd = dom_depth(head->skip_strip_mined()); + set_idom(head->skip_strip_mined(), head->skip_strip_mined()->in(LoopNode::EntryControl), dd); for (uint j3 = 0; j3 < loop->_body.size(); j3++) { Node *old = loop->_body.at(j3); Node *nnn = old_new[old->_idx]; diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 2038a4c8f9e..80aeb533682 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -3391,10 +3391,7 @@ void IdealLoopTree::verify_tree(IdealLoopTree *loop, const IdealLoopTree *parent void PhaseIdealLoop::set_idom(Node* d, Node* n, uint dom_depth) { uint idx = d->_idx; if (idx >= _idom_size) { - uint newsize = _idom_size<<1; - while( idx >= newsize ) { - newsize <<= 1; - } + uint newsize = next_power_of_2(idx); _idom = REALLOC_RESOURCE_ARRAY( Node*, _idom,_idom_size,newsize); _dom_depth = REALLOC_RESOURCE_ARRAY( uint, _dom_depth,_idom_size,newsize); memset( _dom_depth + _idom_size, 0, (newsize - _idom_size) * sizeof(uint) ); diff --git a/src/hotspot/share/opto/machnode.cpp b/src/hotspot/share/opto/machnode.cpp index 327a6d296e7..03fe38f48df 100644 --- a/src/hotspot/share/opto/machnode.cpp +++ b/src/hotspot/share/opto/machnode.cpp @@ -387,10 +387,10 @@ const class TypePtr *MachNode::adr_type() const { //-----------------------------operand_index--------------------------------- -int MachNode::operand_index( uint operand ) const { - if( operand < 1 ) return -1; +int MachNode::operand_index(uint operand) const { + if (operand < 1) return -1; assert(operand < num_opnds(), "oob"); - if( _opnds[operand]->num_edges() == 0 ) return -1; + if (_opnds[operand]->num_edges() == 0) return -1; uint skipped = oper_input_base(); // Sum of leaves skipped so far for (uint opcnt = 1; opcnt < operand; opcnt++) { @@ -412,6 +412,20 @@ int MachNode::operand_index(const MachOper *oper) const { return skipped; } +int MachNode::operand_index(Node* def) const { + uint skipped = oper_input_base(); // Sum of leaves skipped so far + for (uint opcnt = 1; opcnt < num_opnds(); opcnt++) { + uint num_edges = _opnds[opcnt]->num_edges(); // leaves for operand + for (uint i = 0; i < num_edges; i++) { + if (in(skipped + i) == def) { + return opcnt; + } + } + skipped += num_edges; + } + return -1; +} + //------------------------------peephole--------------------------------------- // Apply peephole rule(s) to this instruction MachNode *MachNode::peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted) { diff --git a/src/hotspot/share/opto/machnode.hpp b/src/hotspot/share/opto/machnode.hpp index e0c53d4ff61..52e893fda8d 100644 --- a/src/hotspot/share/opto/machnode.hpp +++ b/src/hotspot/share/opto/machnode.hpp @@ -243,6 +243,7 @@ public: // First index in _in[] corresponding to operand, or -1 if there is none int operand_index(uint operand) const; int operand_index(const MachOper *oper) const; + int operand_index(Node* m) const; // Register class input is expected in virtual const RegMask &in_RegMask(uint) const; diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index 11180e47958..ef49737bb27 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -2533,7 +2533,7 @@ bool PhaseMacroExpand::expand_macro_nodes() { while (progress) { progress = false; for (int i = C->macro_count(); i > 0; i--) { - Node * n = C->macro_node(i-1); + Node* n = C->macro_node(i-1); bool success = false; debug_only(int old_macro_count = C->macro_count();); if (n->Opcode() == Op_LoopLimit) { @@ -2578,7 +2578,7 @@ bool PhaseMacroExpand::expand_macro_nodes() { C->remove_macro_node(n); success = true; } - assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); + assert(!success || (C->macro_count() == (old_macro_count - 1)), "elimination must have deleted one node from macro list"); progress = progress || success; } } @@ -2586,32 +2586,30 @@ bool PhaseMacroExpand::expand_macro_nodes() { // expand arraycopy "macro" nodes first // For ReduceBulkZeroing, we must first process all arraycopy nodes // before the allocate nodes are expanded. - int macro_idx = C->macro_count() - 1; - while (macro_idx >= 0) { - Node * n = C->macro_node(macro_idx); + for (int i = C->macro_count(); i > 0; i--) { + Node* n = C->macro_node(i-1); assert(n->is_macro(), "only macro nodes expected here"); if (_igvn.type(n) == Type::TOP || (n->in(0) != NULL && n->in(0)->is_top())) { // node is unreachable, so don't try to expand it C->remove_macro_node(n); continue; } - int macro_count = C->macro_count(); + debug_only(int old_macro_count = C->macro_count();); switch (n->class_id()) { case Node::Class_Lock: expand_lock_node(n->as_Lock()); - assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); + assert(C->macro_count() == (old_macro_count - 1), "expansion must have deleted one node from macro list"); break; case Node::Class_Unlock: expand_unlock_node(n->as_Unlock()); - assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); + assert(C->macro_count() == (old_macro_count - 1), "expansion must have deleted one node from macro list"); break; case Node::Class_ArrayCopy: expand_arraycopy_node(n->as_ArrayCopy()); - assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); + assert(C->macro_count() == (old_macro_count - 1), "expansion must have deleted one node from macro list"); break; } if (C->failing()) return true; - macro_idx --; } // All nodes except Allocate nodes are expanded now. There could be diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index 2efbca99600..e134b0b156d 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -392,10 +392,16 @@ void Matcher::match( ) { NOT_DEBUG( old->destruct_contents() ); // ------------------------ - // Set up save-on-entry registers + // Set up save-on-entry registers. Fixup_Save_On_Entry( ); -} + { // Cleanup mach IR after selection phase is over. + Compile::TracePhase tp("postselect_cleanup", &timers[_t_postselect_cleanup]); + do_postselect_cleanup(); + if (C->failing()) return; + assert(verify_after_postselect_cleanup(), ""); + } +} //------------------------------Fixup_Save_On_Entry---------------------------- // The stated purpose of this routine is to take care of save-on-entry @@ -851,54 +857,23 @@ void Matcher::init_spill_mask( Node *ret ) { // Grab the Frame Pointer Node *fp = ret->in(TypeFunc::FramePtr); - Node *mem = ret->in(TypeFunc::Memory); - const TypePtr* atp = TypePtr::BOTTOM; // Share frame pointer while making spill ops set_shared(fp); - // Compute generic short-offset Loads +// Get the ADLC notion of the right regmask, for each basic type. #ifdef _LP64 - MachNode *spillCP = match_tree(new LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered)); + idealreg2regmask[Op_RegN] = regmask_for_ideal_register(Op_RegN, ret); #endif - MachNode *spillI = match_tree(new LoadINode(NULL,mem,fp,atp,TypeInt::INT,MemNode::unordered)); - MachNode *spillL = match_tree(new LoadLNode(NULL,mem,fp,atp,TypeLong::LONG,MemNode::unordered, LoadNode::DependsOnlyOnTest, false)); - MachNode *spillF = match_tree(new LoadFNode(NULL,mem,fp,atp,Type::FLOAT,MemNode::unordered)); - MachNode *spillD = match_tree(new LoadDNode(NULL,mem,fp,atp,Type::DOUBLE,MemNode::unordered)); - MachNode *spillP = match_tree(new LoadPNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM,MemNode::unordered)); - assert(spillI != NULL && spillL != NULL && spillF != NULL && - spillD != NULL && spillP != NULL, ""); - // Get the ADLC notion of the right regmask, for each basic type. -#ifdef _LP64 - idealreg2regmask[Op_RegN] = &spillCP->out_RegMask(); -#endif - idealreg2regmask[Op_RegI] = &spillI->out_RegMask(); - idealreg2regmask[Op_RegL] = &spillL->out_RegMask(); - idealreg2regmask[Op_RegF] = &spillF->out_RegMask(); - idealreg2regmask[Op_RegD] = &spillD->out_RegMask(); - idealreg2regmask[Op_RegP] = &spillP->out_RegMask(); - - // Vector regmasks. - if (Matcher::vector_size_supported(T_BYTE,4)) { - TypeVect::VECTS = TypeVect::make(T_BYTE, 4); - MachNode *spillVectS = match_tree(new LoadVectorNode(NULL,mem,fp,atp,TypeVect::VECTS)); - idealreg2regmask[Op_VecS] = &spillVectS->out_RegMask(); - } - if (Matcher::vector_size_supported(T_FLOAT,2)) { - MachNode *spillVectD = match_tree(new LoadVectorNode(NULL,mem,fp,atp,TypeVect::VECTD)); - idealreg2regmask[Op_VecD] = &spillVectD->out_RegMask(); - } - if (Matcher::vector_size_supported(T_FLOAT,4)) { - MachNode *spillVectX = match_tree(new LoadVectorNode(NULL,mem,fp,atp,TypeVect::VECTX)); - idealreg2regmask[Op_VecX] = &spillVectX->out_RegMask(); - } - if (Matcher::vector_size_supported(T_FLOAT,8)) { - MachNode *spillVectY = match_tree(new LoadVectorNode(NULL,mem,fp,atp,TypeVect::VECTY)); - idealreg2regmask[Op_VecY] = &spillVectY->out_RegMask(); - } - if (Matcher::vector_size_supported(T_FLOAT,16)) { - MachNode *spillVectZ = match_tree(new LoadVectorNode(NULL,mem,fp,atp,TypeVect::VECTZ)); - idealreg2regmask[Op_VecZ] = &spillVectZ->out_RegMask(); - } + idealreg2regmask[Op_RegI] = regmask_for_ideal_register(Op_RegI, ret); + idealreg2regmask[Op_RegP] = regmask_for_ideal_register(Op_RegP, ret); + idealreg2regmask[Op_RegF] = regmask_for_ideal_register(Op_RegF, ret); + idealreg2regmask[Op_RegD] = regmask_for_ideal_register(Op_RegD, ret); + idealreg2regmask[Op_RegL] = regmask_for_ideal_register(Op_RegL, ret); + idealreg2regmask[Op_VecS] = regmask_for_ideal_register(Op_VecS, ret); + idealreg2regmask[Op_VecD] = regmask_for_ideal_register(Op_VecD, ret); + idealreg2regmask[Op_VecX] = regmask_for_ideal_register(Op_VecX, ret); + idealreg2regmask[Op_VecY] = regmask_for_ideal_register(Op_VecY, ret); + idealreg2regmask[Op_VecZ] = regmask_for_ideal_register(Op_VecZ, ret); } #ifdef ASSERT @@ -2502,6 +2477,167 @@ bool Matcher::gen_narrow_oop_implicit_null_checks() { CompressedOops::base() != NULL); } +// Compute RegMask for an ideal register. +const RegMask* Matcher::regmask_for_ideal_register(uint ideal_reg, Node* ret) { + const Type* t = Type::mreg2type[ideal_reg]; + if (t == NULL) { + assert(ideal_reg >= Op_VecS && ideal_reg <= Op_VecZ, "not a vector: %d", ideal_reg); + return NULL; // not supported + } + Node* fp = ret->in(TypeFunc::FramePtr); + Node* mem = ret->in(TypeFunc::Memory); + const TypePtr* atp = TypePtr::BOTTOM; + MemNode::MemOrd mo = MemNode::unordered; + + Node* spill; + switch (ideal_reg) { + case Op_RegN: spill = new LoadNNode(NULL, mem, fp, atp, t->is_narrowoop(), mo); break; + case Op_RegI: spill = new LoadINode(NULL, mem, fp, atp, t->is_int(), mo); break; + case Op_RegP: spill = new LoadPNode(NULL, mem, fp, atp, t->is_ptr(), mo); break; + case Op_RegF: spill = new LoadFNode(NULL, mem, fp, atp, t, mo); break; + case Op_RegD: spill = new LoadDNode(NULL, mem, fp, atp, t, mo); break; + case Op_RegL: spill = new LoadLNode(NULL, mem, fp, atp, t->is_long(), mo); break; + + case Op_VecS: // fall-through + case Op_VecD: // fall-through + case Op_VecX: // fall-through + case Op_VecY: // fall-through + case Op_VecZ: spill = new LoadVectorNode(NULL, mem, fp, atp, t->is_vect()); break; + + default: ShouldNotReachHere(); + } + MachNode* mspill = match_tree(spill); + assert(mspill != NULL, "matching failed: %d", ideal_reg); + // Handle generic vector operand case + if (Matcher::supports_generic_vector_operands && t->isa_vect()) { + specialize_mach_node(mspill); + } + return &mspill->out_RegMask(); +} + +// Process Mach IR right after selection phase is over. +void Matcher::do_postselect_cleanup() { + if (supports_generic_vector_operands) { + specialize_generic_vector_operands(); + if (C->failing()) return; + } +} + +//---------------------------------------------------------------------- +// Generic machine operands elision. +//---------------------------------------------------------------------- + +// Convert (leg)Vec to (leg)Vec[SDXYZ]. +MachOper* Matcher::specialize_vector_operand_helper(MachNode* m, MachOper* original_opnd) { + const Type* t = m->bottom_type(); + uint ideal_reg = t->ideal_reg(); + // Handle special cases + if (t->isa_vect()) { + // RShiftCntV/RShiftCntV report wide vector type, but VecS as ideal register (see vectornode.hpp). + if (m->ideal_Opcode() == Op_RShiftCntV || m->ideal_Opcode() == Op_LShiftCntV) { + ideal_reg = TypeVect::VECTS->ideal_reg(); // ideal_reg == Op_VecS + } + } else { + // Chain instructions which convert scalar to vector (e.g., vshiftcntimm on x86) don't have vector type. + int size_in_bytes = 4 * type2size[t->basic_type()]; + ideal_reg = Matcher::vector_ideal_reg(size_in_bytes); + } + return Matcher::specialize_generic_vector_operand(original_opnd, ideal_reg); +} + +// Compute concrete vector operand for a generic TEMP vector mach node based on its user info. +void Matcher::specialize_temp_node(MachTempNode* tmp, MachNode* use, uint idx) { + assert(use->in(idx) == tmp, "not a user"); + assert(!Matcher::is_generic_vector(use->_opnds[0]), "use not processed yet"); + + if ((uint)idx == use->two_adr()) { // DEF_TEMP case + tmp->_opnds[0] = use->_opnds[0]->clone(); + } else { + uint ideal_vreg = vector_ideal_reg(C->max_vector_size()); + tmp->_opnds[0] = specialize_generic_vector_operand(tmp->_opnds[0], ideal_vreg); + } +} + +// Compute concrete vector operand for a generic DEF/USE vector operand (of mach node m at index idx). +MachOper* Matcher::specialize_vector_operand(MachNode* m, uint idx) { + assert(Matcher::is_generic_vector(m->_opnds[idx]), "repeated updates"); + if (idx == 0) { // DEF + // Use mach node itself to compute vector operand type. + return specialize_vector_operand_helper(m, m->_opnds[0]); + } else { + // Use def node to compute operand type. + int base_idx = m->operand_index(idx); + MachNode* in = m->in(base_idx)->as_Mach(); + if (in->is_MachTemp() && Matcher::is_generic_vector(in->_opnds[0])) { + specialize_temp_node(in->as_MachTemp(), m, base_idx); // MachTemp node use site + } else if (is_generic_reg2reg_move(in)) { + in = in->in(1)->as_Mach(); // skip over generic reg-to-reg moves + } + return specialize_vector_operand_helper(in, m->_opnds[idx]); + } +} + +void Matcher::specialize_mach_node(MachNode* m) { + assert(!m->is_MachTemp(), "processed along with its user"); + // For generic use operands pull specific register class operands from + // its def instruction's output operand (def operand). + for (uint i = 0; i < m->num_opnds(); i++) { + if (Matcher::is_generic_vector(m->_opnds[i])) { + m->_opnds[i] = specialize_vector_operand(m, i); + } + } +} + +// Replace generic vector operands with concrete vector operands and eliminate generic reg-to-reg moves from the graph. +void Matcher::specialize_generic_vector_operands() { + assert(supports_generic_vector_operands, "sanity"); + ResourceMark rm; + + if (C->max_vector_size() == 0) { + return; // no vector instructions or operands + } + // Replace generic vector operands (vec/legVec) with concrete ones (vec[SDXYZ]/legVec[SDXYZ]) + // and remove reg-to-reg vector moves (MoveVec2Leg and MoveLeg2Vec). + Unique_Node_List live_nodes; + C->identify_useful_nodes(live_nodes); + + while (live_nodes.size() > 0) { + MachNode* m = live_nodes.pop()->isa_Mach(); + if (m != NULL) { + if (Matcher::is_generic_reg2reg_move(m)) { + // Register allocator properly handles vec <=> leg moves using register masks. + int opnd_idx = m->operand_index(1); + Node* def = m->in(opnd_idx); + m->subsume_by(def, C); + } else if (m->is_MachTemp()) { + // process MachTemp nodes at use site (see Matcher::specialize_vector_operand) + } else { + specialize_mach_node(m); + } + } + } +} + +#ifdef ASSERT +bool Matcher::verify_after_postselect_cleanup() { + assert(!C->failing(), "sanity"); + if (supports_generic_vector_operands) { + Unique_Node_List useful; + C->identify_useful_nodes(useful); + for (uint i = 0; i < useful.size(); i++) { + MachNode* m = useful.at(i)->isa_Mach(); + if (m != NULL) { + assert(!Matcher::is_generic_reg2reg_move(m), "no MoveVec nodes allowed"); + for (uint j = 0; j < m->num_opnds(); j++) { + assert(!Matcher::is_generic_vector(m->_opnds[j]), "no generic vector operands allowed"); + } + } + } + } + return true; +} +#endif // ASSERT + // Used by the DFA in dfa_xxx.cpp. Check for a following barrier or // atomic instruction acting as a store_load barrier without any // intervening volatile load, and thus we don't need a barrier here. diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index e167c7aa257..6879c04f2a3 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -506,6 +506,30 @@ public: // postalloc expand)? static const bool require_postalloc_expand; + // Does the platform support generic vector operands? + // Requires cleanup after selection phase. + static const bool supports_generic_vector_operands; + + private: + void do_postselect_cleanup(); + + void specialize_generic_vector_operands(); + void specialize_mach_node(MachNode* m); + void specialize_temp_node(MachTempNode* tmp, MachNode* use, uint idx); + MachOper* specialize_vector_operand(MachNode* m, uint idx); + MachOper* specialize_vector_operand_helper(MachNode* m, MachOper* generic_opnd); + + static MachOper* specialize_generic_vector_operand(MachOper* generic_opnd, uint ideal_reg); + + static bool is_generic_reg2reg_move(MachNode* m); + static bool is_generic_vector(MachOper* opnd); + + const RegMask* regmask_for_ideal_register(uint ideal_reg, Node* ret); + + // Graph verification code + DEBUG_ONLY( bool verify_after_postselect_cleanup(); ) + + public: // Perform a platform dependent implicit null fixup. This is needed // on windows95 to take care of some unusual register constraints. void pd_implicit_null_fixup(MachNode *load, uint idx); diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index 6ac444f8ec3..b692b8192dc 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -41,6 +41,7 @@ #include "opto/type.hpp" #include "utilities/copy.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" class RegMask; // #include "phase.hpp" @@ -653,7 +654,7 @@ void Node::grow( uint len ) { to[3] = NULL; return; } - while( new_max <= len ) new_max <<= 1; // Find next power-of-2 + new_max = next_power_of_2(len); // Trimming to limit allows a uint8 to handle up to 255 edges. // Previously I was using only powers-of-2 which peaked at 128 edges. //if( new_max >= limit ) new_max = limit-1; @@ -676,7 +677,7 @@ void Node::out_grow( uint len ) { _out = (Node **)arena->Amalloc(4*sizeof(Node*)); return; } - while( new_max <= len ) new_max <<= 1; // Find next power-of-2 + new_max = next_power_of_2(len); // Trimming to limit allows a uint8 to handle up to 255 edges. // Previously I was using only powers-of-2 which peaked at 128 edges. //if( new_max >= limit ) new_max = limit-1; @@ -2256,7 +2257,7 @@ void Node_Array::grow( uint i ) { _nodes[0] = NULL; } uint old = _max; - while( i >= _max ) _max <<= 1; // Double to fit + _max = next_power_of_2(i); _nodes = (Node**)_a->Arealloc( _nodes, old*sizeof(Node*),_max*sizeof(Node*)); Copy::zero_to_bytes( &_nodes[old], (_max-old)*sizeof(Node*) ); } diff --git a/src/hotspot/share/opto/phase.cpp b/src/hotspot/share/opto/phase.cpp index 23386a9285d..01eff476703 100644 --- a/src/hotspot/share/opto/phase.cpp +++ b/src/hotspot/share/opto/phase.cpp @@ -103,8 +103,11 @@ void Phase::print_timers() { } } - tty->print_cr (" Matcher: %7.3f s", timers[_t_matcher].seconds()); - tty->print_cr (" Scheduler: %7.3f s", timers[_t_scheduler].seconds()); + tty->print_cr (" Matcher: %7.3f s", timers[_t_matcher].seconds()); + if (Matcher::supports_generic_vector_operands) { + tty->print_cr (" Post Selection Cleanup: %7.3f s", timers[_t_postselect_cleanup].seconds()); + } + tty->print_cr (" Scheduler: %7.3f s", timers[_t_scheduler].seconds()); { tty->print_cr (" Regalloc: %7.3f s", timers[_t_registerAllocation].seconds()); diff --git a/src/hotspot/share/opto/phase.hpp b/src/hotspot/share/opto/phase.hpp index 25252551cb0..5285b0fef5b 100644 --- a/src/hotspot/share/opto/phase.hpp +++ b/src/hotspot/share/opto/phase.hpp @@ -83,6 +83,7 @@ public: _t_barrierExpand, _t_graphReshaping, _t_matcher, + _t_postselect_cleanup, _t_scheduler, _t_registerAllocation, _t_ctorChaitin, diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 3275a7a54a8..da4e07ddc18 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ #include "opto/regalloc.hpp" #include "opto/rootnode.hpp" #include "utilities/macros.hpp" +#include "utilities/powerOfTwo.hpp" //============================================================================= #define NODE_HASH_MINIMUM_SIZE 255 @@ -260,12 +261,9 @@ bool NodeHash::hash_delete( const Node *n ) { //------------------------------round_up--------------------------------------- // Round up to nearest power of 2 -uint NodeHash::round_up( uint x ) { - x += (x>>2); // Add 25% slop - if( x <16 ) return 16; // Small stuff - uint i=16; - while( i < x ) i <<= 1; // Double to fit - return i; // Return hash table size +uint NodeHash::round_up(uint x) { + x += (x >> 2); // Add 25% slop + return MAX2(16U, round_up_power_of_2(x)); } //------------------------------grow------------------------------------------- @@ -2138,7 +2136,7 @@ void Type_Array::grow( uint i ) { _types[0] = NULL; } uint old = _max; - while( i >= _max ) _max <<= 1; // Double to fit + _max = next_power_of_2(i); _types = (const Type**)_a->Arealloc( _types, old*sizeof(Type*),_max*sizeof(Type*)); memset( &_types[old], 0, (_max-old)*sizeof(Type*) ); } diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 8f3d9cd20f4..6098be845f2 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -375,7 +375,7 @@ const Type* Type::make_constant_from_field(ciField* field, ciInstance* holder, field->is_autobox_cache()); if (con_type != NULL && field->is_call_site_target()) { ciCallSite* call_site = holder->as_call_site(); - if (!call_site->is_constant_call_site()) { + if (!call_site->is_fully_initialized_constant_call_site()) { ciMethodHandle* target = con.as_object()->as_method_handle(); Compile::current()->dependencies()->assert_call_site_target_value(call_site, target); } @@ -4104,32 +4104,22 @@ const TypeOopPtr *TypeAryPtr::cast_to_nonconst() const { } -//-----------------------------narrow_size_type------------------------------- -// Local cache for arrayOopDesc::max_array_length(etype), -// which is kind of slow (and cached elsewhere by other users). -static jint max_array_length_cache[T_CONFLICT+1]; -static jint max_array_length(BasicType etype) { - jint& cache = max_array_length_cache[etype]; - jint res = cache; - if (res == 0) { - switch (etype) { - case T_NARROWOOP: +//-----------------------------max_array_length------------------------------- +// A wrapper around arrayOopDesc::max_array_length(etype) with some input normalization. +jint TypeAryPtr::max_array_length(BasicType etype) { + if (!is_java_primitive(etype) && !is_reference_type(etype)) { + if (etype == T_NARROWOOP) { etype = T_OBJECT; - break; - case T_NARROWKLASS: - case T_CONFLICT: - case T_ILLEGAL: - case T_VOID: - etype = T_BYTE; // will produce conservatively high value - break; - default: - break; + } else if (etype == T_ILLEGAL) { // bottom[] + etype = T_BYTE; // will produce conservatively high value + } else { + fatal("not an element type: %s", type2name(etype)); } - cache = res = arrayOopDesc::max_array_length(etype); } - return res; + return arrayOopDesc::max_array_length(etype); } +//-----------------------------narrow_size_type------------------------------- // Narrow the given size type to the index range for the given array base type. // Return NULL if the resulting int type becomes empty. const TypeInt* TypeAryPtr::narrow_size_type(const TypeInt* size) const { diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index 57ace034f14..4917254bfd0 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -455,7 +455,6 @@ public: private: // support arrays - static const BasicType _basic_type[]; static const Type* _zero_type[T_CONFLICT+1]; static const Type* _const_basic_type[T_CONFLICT+1]; }; @@ -1225,6 +1224,8 @@ public: const TypeAryPtr* cast_to_autobox_cache(bool cache) const; + static jint max_array_length(BasicType etype) ; + // Convenience common pre-built types. static const TypeAryPtr *RANGE; static const TypeAryPtr *OOPS; diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 89397eb3ff0..baee082eed4 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -51,6 +51,7 @@ #include "oops/fieldStreams.inline.hpp" #include "oops/instanceKlass.hpp" #include "oops/method.hpp" +#include "oops/recordComponent.hpp" #include "oops/objArrayKlass.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" @@ -1693,6 +1694,54 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, } JVM_END +JVM_ENTRY(jboolean, JVM_IsRecord(JNIEnv *env, jclass cls)) +{ + JVMWrapper("JVM_IsRecord"); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); + if (k != NULL && k->is_instance_klass()) { + InstanceKlass* ik = InstanceKlass::cast(k); + return ik->is_record(); + } else { + return false; + } +} +JVM_END + +JVM_ENTRY(jobjectArray, JVM_GetRecordComponents(JNIEnv* env, jclass ofClass)) +{ + JVMWrapper("JVM_GetRecordComponents"); + Klass* c = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)); + assert(c->is_instance_klass(), "must be"); + InstanceKlass* ik = InstanceKlass::cast(c); + + if (ik->is_record()) { + Array* components = ik->record_components(); + assert(components != NULL, "components should not be NULL"); + { + JvmtiVMObjectAllocEventCollector oam; + constantPoolHandle cp(THREAD, ik->constants()); + int length = components->length(); + assert(length >= 0, "unexpected record_components length"); + objArrayOop record_components = + oopFactory::new_objArray(SystemDictionary::RecordComponent_klass(), length, CHECK_NULL); + objArrayHandle components_h (THREAD, record_components); + + for (int x = 0; x < length; x++) { + RecordComponent* component = components->at(x); + assert(component != NULL, "unexpected NULL record component"); + oop component_oop = java_lang_reflect_RecordComponent::create(ik, component, CHECK_NULL); + components_h->obj_at_put(x, component_oop); + } + return (jobjectArray)JNIHandles::make_local(components_h()); + } + } + + // Return empty array if ofClass is not a record. + objArrayOop result = oopFactory::new_objArray(SystemDictionary::RecordComponent_klass(), 0, CHECK_NULL); + return (jobjectArray)JNIHandles::make_local(env, result); +} +JVM_END + static bool select_method(const methodHandle& method, bool want_constructor) { if (want_constructor) { return (method->is_initializer() && !method->is_static()); diff --git a/src/hotspot/share/prims/jvmti.xml b/src/hotspot/share/prims/jvmti.xml index fb7096714f6..5f90917857c 100644 --- a/src/hotspot/share/prims/jvmti.xml +++ b/src/hotspot/share/prims/jvmti.xml @@ -49,7 +49,7 @@
    -agentlib:<agent-lib-name>=<options>
    - The name following -agentlib: is the name of the - library to load. Lookup of the library, both its full name and location, - proceeds in a platform-specific manner. - Typically, the <agent-lib-name> is expanded to an - operating system specific file name. - The <options> will be passed to the agent on start-up. - For example, if the option - -agentlib:foo=opt1,opt2 is specified, the VM will attempt to - load the shared library foo.dll from the system PATH + The name following -agentlib: is the name of the + library to load. Lookup of the library, both its full name and location, + proceeds in a platform-specific manner. + Typically, the <agent-lib-name> is expanded to an + operating system specific file name. + The <options> will be passed to the agent on start-up. + For example, if the option + -agentlib:foo=opt1,opt2 is specified, the VM will attempt to + load the shared library foo.dll from the system PATH under Windows or libfoo.so from the - LD_LIBRARY_PATH under the Solaris operating + LD_LIBRARY_PATH under the Solaris operating environment. If the agent library is statically linked into the executable then no actual loading takes place. @@ -505,13 +505,13 @@
    -agentpath:<path-to-agent>=<options>
    - The path following -agentpath: is the absolute path from which - to load the library. - No library name expansion will occur. - The <options> will be passed to the agent on start-up. - For example, if the option - -agentpath:c:\myLibs\foo.dll=opt1,opt2 is specified, the VM will attempt to - load the shared library c:\myLibs\foo.dll. If the agent + The path following -agentpath: is the absolute path from which + to load the library. + No library name expansion will occur. + The <options> will be passed to the agent on start-up. + For example, if the option + -agentpath:c:\myLibs\foo.dll=opt1,opt2 is specified, the VM will attempt to + load the shared library c:\myLibs\foo.dll. If the agent library is statically linked into the executable then no actual loading takes place.

    @@ -574,12 +574,12 @@ Agent_OnLoad_L(JavaVM *vm, char *options, void *reserved) It will be called early enough in VM initialization that:

    • system properties - may be set before they have been used in the start-up of the VM
    • + may be set before they have been used in the start-up of the VM
    • the full set of - capabilities - is still available (note that capabilities that configure the VM - may only be available at this time--see the - Capability function section)
    • + capabilities + is still available (note that capabilities that configure the VM + may only be available at this time--see the + Capability function section)
    • no bytecodes have executed
    • no classes have been loaded
    • no objects have been created
    • @@ -795,29 +795,29 @@ Agent_OnUnload_L(JavaVM *vm) Instrumentation can be inserted in one of three ways:
      • - Static Instrumentation: The class file is instrumented before it - is loaded into the VM - for example, by creating a duplicate directory of - *.class files which have been modified to add the instrumentation. - This method is extremely awkward and, in general, an agent cannot know - the origin of the class files which will be loaded. + Static Instrumentation: The class file is instrumented before it + is loaded into the VM - for example, by creating a duplicate directory of + *.class files which have been modified to add the instrumentation. + This method is extremely awkward and, in general, an agent cannot know + the origin of the class files which will be loaded.
      • - Load-Time Instrumentation: When a class file is loaded by the VM, the raw - bytes of the class file are sent for instrumentation to the agent. - The - event, triggered by the class load, - provides this functionality. This mechanism provides efficient - and complete access to one-time instrumentation. + Load-Time Instrumentation: When a class file is loaded by the VM, the raw + bytes of the class file are sent for instrumentation to the agent. + The + event, triggered by the class load, + provides this functionality. This mechanism provides efficient + and complete access to one-time instrumentation.
      • - Dynamic Instrumentation: A class which is already loaded (and possibly - even running) is modified. This optional feature is provided by the - event, triggered by calling the - function. - Classes can be modified multiple times and can be returned to their - original state. - The mechanism allows instrumentation which changes during the - course of execution. + Dynamic Instrumentation: A class which is already loaded (and possibly + even running) is modified. This optional feature is provided by the + event, triggered by calling the + function. + Classes can be modified multiple times and can be returned to their + original state. + The mechanism allows instrumentation which changes during the + course of execution.

      @@ -1058,49 +1058,49 @@ jvmtiEnv *jvmti; Allocate - Allocate an area of memory through the allocator. + Allocate an area of memory through the allocator. The allocated - memory should be freed with . + memory should be freed with . jvmdi - - - - The number of bytes to allocate. - - jlong is used for compatibility with JVMDI. - - - - - - - On return, a pointer to the beginning of the allocated memory. + + + + The number of bytes to allocate. + + jlong is used for compatibility with JVMDI. + + + + + + + On return, a pointer to the beginning of the allocated memory. If size is zero, NULL is returned. - - + + - - Memory request cannot be honored. - - - is less than zero. - + + Memory request cannot be honored. + + + is less than zero. + Deallocate - Deallocate mem using the allocator. + Deallocate mem using the allocator. This function should - be used to deallocate any memory allocated and returned + be used to deallocate any memory allocated and returned by a function - (including memory allocated with ). + (including memory allocated with ). All allocated memory must be deallocated or the memory cannot be reclaimed. @@ -1108,17 +1108,17 @@ jvmtiEnv *jvmti; - - + + - the call is ignored + the call is ignored - - A pointer to the beginning of the allocated memory. + + A pointer to the beginning of the allocated memory. Please ignore "On return, the elements are set." keep it from generating "On return, the elements are set" - - + + @@ -1209,55 +1209,55 @@ jvmtiEnv *jvmti;

    - The answers are represented by the following bit vector. - - - Thread is alive. Zero if thread is new (not started) or terminated. - - - Thread has completed execution. - - - Thread is runnable. - - - Thread is waiting to enter a synchronization block/method or, + The answers are represented by the following bit vector. + + + Thread is alive. Zero if thread is new (not started) or terminated. + + + Thread has completed execution. + + + Thread is runnable. + + + Thread is waiting to enter a synchronization block/method or, after an Object.wait(), waiting to re-enter a synchronization block/method. - - - Thread is waiting. - - - Thread is waiting without a timeout. + + + Thread is waiting. + + + Thread is waiting without a timeout. For example, Object.wait(). - - - Thread is waiting with a maximum time to wait specified. + + + Thread is waiting with a maximum time to wait specified. For example, Object.wait(long). - - - Thread is sleeping -- Thread.sleep(long). - - - Thread is waiting on an object monitor -- Object.wait. - - - Thread is parked, for example: LockSupport.park, + + + Thread is sleeping -- Thread.sleep(long). + + + Thread is waiting on an object monitor -- Object.wait. + + + Thread is parked, for example: LockSupport.park, LockSupport.parkUtil and LockSupport.parkNanos. - - - Thread suspended. - java.lang.Thread.suspend() - or a suspend function + + + Thread suspended. + java.lang.Thread.suspend() + or a suspend function (such as ) has been called on the thread. If this bit - is set, the other bits refer to the thread state before suspension. - - - Thread has been interrupted. - - + is set, the other bits refer to the thread state before suspension. + + + Thread has been interrupted. + + Thread is in native code--that is, a native method is running which has not called back into the VM or Java programming language code. @@ -1266,49 +1266,49 @@ jvmtiEnv *jvmti; language code nor is it set when running VM code or VM support code. Native VM interface functions, such as JNI and functions, may be implemented as VM code. - - + + Defined by VM vendor. - - + + Defined by VM vendor. - - + + Defined by VM vendor. - - + + The following definitions are used to convert thread state to java.lang.Thread.State style states. - - + - Mask the state with this before comparison - - + - java.lang.Thread.State.NEW - - java.lang.Thread.State.NEW + + - java.lang.Thread.State.TERMINATED - - java.lang.Thread.State.TERMINATED + + - java.lang.Thread.State.RUNNABLE - - java.lang.Thread.State.RUNNABLE + + - java.lang.Thread.State.BLOCKED - - java.lang.Thread.State.BLOCKED + + - java.lang.Thread.State.WAITING - - java.lang.Thread.State.WAITING + + - java.lang.Thread.State.TIMED_WAITING - - + java.lang.Thread.State.TIMED_WAITING + + Rules

    There can be no more than one answer to a question, although there can be no @@ -1403,26 +1403,26 @@ jvmtiEnv *jvmti; In most cases, the thread state can be determined by testing the one bit corresponding to that question. For example, the code to test if a thread is sleeping: - jint state; - jvmtiError err; + jint state; + jvmtiError err; - err = (*jvmti)->GetThreadState(jvmti, thread, &state); - if (err == JVMTI_ERROR_NONE) { - if (state & JVMTI_THREAD_STATE_SLEEPING) { ... + err = (*jvmti)->GetThreadState(jvmti, thread, &state); + if (err == JVMTI_ERROR_NONE) { + if (state & JVMTI_THREAD_STATE_SLEEPING) { ...

    For waiting (that is, in Object.wait, parked, or sleeping) it would be: - if (state & JVMTI_THREAD_STATE_WAITING) { ... + if (state & JVMTI_THREAD_STATE_WAITING) { ... For some states, more than one bit will need to be tested as is the case when testing if a thread has not yet been started: - if ((state & (JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_TERMINATED)) == 0) { ... + if ((state & (JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_TERMINATED)) == 0) { ... To distinguish timed from untimed Object.wait: - if (state & JVMTI_THREAD_STATE_IN_OBJECT_WAIT) { + if (state & JVMTI_THREAD_STATE_IN_OBJECT_WAIT) { if (state & JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT) { printf("in Object.wait(long timeout)\n"); } else { @@ -1440,8 +1440,8 @@ jvmtiEnv *jvmti; by using the provided conversion masks. For example, this returns the name of the java.lang.Thread.State thread state: - err = (*jvmti)->GetThreadState(jvmti, thread, &state); - abortOnError(err); + err = (*jvmti)->GetThreadState(jvmti, thread, &state); + abortOnError(err); switch (state & JVMTI_JAVA_LANG_THREAD_STATE_MASK) { case JVMTI_JAVA_LANG_THREAD_STATE_NEW: return "NEW"; @@ -1462,19 +1462,19 @@ jvmtiEnv *jvmti; - - - - The thread to query. - - - - - - On return, points to state flags, - as defined by the Thread State Flags. - - + + + + The thread to query. + + + + + + On return, points to state flags, + as defined by the Thread State Flags. + + @@ -1499,11 +1499,11 @@ jvmtiEnv *jvmti; - - - On return, points to the current thread, or NULL. - - + + + On return, points to the current thread, or NULL. + + @@ -1528,18 +1528,18 @@ jvmtiEnv *jvmti; - - - On return, points to the number of running threads. - - + + + On return, points to the number of running threads. + + - - - On return, points to an array of references, one - for each running thread. - - + + + On return, points to an array of references, one + for each running thread. + + @@ -1560,11 +1560,11 @@ jvmtiEnv *jvmti; - - - The thread to suspend. - - + + + The thread to suspend. + + @@ -1577,9 +1577,9 @@ jvmtiEnv *jvmti; Suspend All Threads - - There has been no explicit call for this function, and it will - thus be removed if there is no interest. + + There has been no explicit call for this function, and it will + thus be removed if there is no interest. Suspend all live threads except: