diff --git a/.editorconfig b/.editorconfig
index 0e6c17e7674..98f07b3c5fb 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,3 +5,7 @@ trim_trailing_whitespace = true
[Makefile]
trim_trailing_whitespace = true
+
+[src/hotspot/**.{cpp,hpp,h}]
+indent_style = space
+indent_size = 2
diff --git a/doc/building.html b/doc/building.html
index 1e6f99e97c9..a085f10c48e 100644
--- a/doc/building.html
+++ b/doc/building.html
@@ -594,7 +594,7 @@ to compile successfully without issues.
Windows
-
Microsoft Visual Studio 2022 version 17.6.5
+
Microsoft Visual Studio 2022 version 17.13.2
diff --git a/doc/building.md b/doc/building.md
index 18e030baa9e..a31cd5fe775 100644
--- a/doc/building.md
+++ b/doc/building.md
@@ -390,11 +390,11 @@ possible to compile the JDK with both older and newer versions, but the closer
you stay to this list, the more likely you are to compile successfully without
issues.
-| Operating system | Toolchain version |
-| ------------------ | ------------------------------------------- |
-| Linux | gcc 14.2.0 |
-| macOS | Apple Xcode 14.3.1 (using clang 14.0.3) |
-| Windows | Microsoft Visual Studio 2022 version 17.6.5 |
+| Operating system | Toolchain version |
+| ------------------ | -------------------------------------------- |
+| Linux | gcc 14.2.0 |
+| macOS | Apple Xcode 14.3.1 (using clang 14.0.3) |
+| Windows | Microsoft Visual Studio 2022 version 17.13.2 |
All compilers are expected to be able to handle the C11 language standard for
C, and C++14 for C++.
diff --git a/make/Bundles.gmk b/make/Bundles.gmk
index 8962b596278..ba8ec0c864b 100644
--- a/make/Bundles.gmk
+++ b/make/Bundles.gmk
@@ -174,9 +174,11 @@ else
JRE_IMAGE_HOMEDIR := $(JRE_IMAGE_DIR)
JDK_BUNDLE_SUBDIR := jdk-$(VERSION_NUMBER)
JRE_BUNDLE_SUBDIR := jre-$(VERSION_NUMBER)
+ STATIC_JDK_BUNDLE_SUBDIR := static-jdk-$(VERSION_NUMBER)
ifneq ($(DEBUG_LEVEL), release)
JDK_BUNDLE_SUBDIR := $(JDK_BUNDLE_SUBDIR)/$(DEBUG_LEVEL)
JRE_BUNDLE_SUBDIR := $(JRE_BUNDLE_SUBDIR)/$(DEBUG_LEVEL)
+ STATIC_JDK_BUNDLE_SUBDIR := $(STATIC_JDK_BUNDLE_SUBDIR)/$(DEBUG_LEVEL)
endif
# In certain situations, the JDK_IMAGE_DIR points to an image without the
# the symbols and demos. If so, the symobls and demos can be found in a
@@ -500,6 +502,21 @@ ifneq ($(filter static-libs-graal-bundles, $(MAKECMDGOALS)), )
STATIC_LIBS_GRAAL_TARGETS += $(BUILD_STATIC_LIBS_GRAAL_BUNDLE)
endif
+#################################################################################
+
+ifneq ($(filter static-jdk-bundles, $(MAKECMDGOALS)), )
+ STATIC_JDK_BUNDLE_FILES := $(call FindFiles, $(STATIC_JDK_IMAGE_DIR))
+
+ $(eval $(call SetupBundleFile, BUILD_STATIC_JDK_BUNDLE, \
+ BUNDLE_NAME := $(STATIC_JDK_BUNDLE_NAME), \
+ FILES := $(STATIC_JDK_BUNDLE_FILES), \
+ BASE_DIRS := $(STATIC_JDK_IMAGE_DIR), \
+ SUBDIR := $(STATIC_JDK_BUNDLE_SUBDIR), \
+ ))
+
+ STATIC_JDK_TARGETS += $(BUILD_STATIC_JDK_BUNDLE)
+endif
+
################################################################################
product-bundles: $(PRODUCT_TARGETS)
@@ -510,11 +527,12 @@ docs-javase-bundles: $(DOCS_JAVASE_TARGETS)
docs-reference-bundles: $(DOCS_REFERENCE_TARGETS)
static-libs-bundles: $(STATIC_LIBS_TARGETS)
static-libs-graal-bundles: $(STATIC_LIBS_GRAAL_TARGETS)
+static-jdk-bundles: $(STATIC_JDK_TARGETS)
jcov-bundles: $(JCOV_TARGETS)
.PHONY: product-bundles test-bundles \
docs-jdk-bundles docs-javase-bundles docs-reference-bundles \
- static-libs-bundles static-libs-graal-bundles jcov-bundles
+ static-libs-bundles static-libs-graal-bundles static-jdk-bundles jcov-bundles
################################################################################
diff --git a/make/Docs.gmk b/make/Docs.gmk
index 60c029ce8f9..965ae689e21 100644
--- a/make/Docs.gmk
+++ b/make/Docs.gmk
@@ -98,7 +98,7 @@ JAVADOC_DISABLED_DOCLINT_PACKAGES := org.w3c.* javax.smartcardio
JAVADOC_OPTIONS := -use -keywords -notimestamp \
-serialwarn -encoding ISO-8859-1 -docencoding UTF-8 -breakiterator \
-splitIndex --system none -javafx --expand-requires transitive \
- --override-methods=summary
+ --override-methods=summary --syntax-highlight
# The reference options must stay stable to allow for comparisons across the
# development cycle.
diff --git a/make/GenerateLinkOptData.gmk b/make/GenerateLinkOptData.gmk
index 5fc745ba223..54022e4e27a 100644
--- a/make/GenerateLinkOptData.gmk
+++ b/make/GenerateLinkOptData.gmk
@@ -66,7 +66,7 @@ endif
# default classlist is minimal, let's filter out the '@cp' lines until we can
# find a proper solution.
CLASSLIST_FILE_VM_OPTS = \
- -Duser.language=en -Duser.country=US
+ -Duser.language=en -Duser.country=US --enable-native-access=ALL-UNNAMED
# Save the stderr output of the command and print it along with stdout in case
# something goes wrong.
diff --git a/make/Main.gmk b/make/Main.gmk
index eda3b79265a..3535ad16aae 100644
--- a/make/Main.gmk
+++ b/make/Main.gmk
@@ -875,6 +875,12 @@ $(eval $(call SetupTarget, static-libs-graal-bundles, \
DEPS := static-libs-graal-image, \
))
+$(eval $(call SetupTarget, static-jdk-bundles, \
+ MAKEFILE := Bundles, \
+ TARGET := static-jdk-bundles, \
+ DEPS := static-jdk-image, \
+))
+
ifeq ($(JCOV_ENABLED), true)
$(eval $(call SetupTarget, jcov-bundles, \
MAKEFILE := Bundles, \
diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4
index 79e44dd4ad1..f8a512f503d 100644
--- a/make/autoconf/jdk-options.m4
+++ b/make/autoconf/jdk-options.m4
@@ -520,8 +520,21 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER],
# Silence them for now.
UBSAN_CHECKS="-fsanitize=undefined -fsanitize=float-divide-by-zero -fno-sanitize=shift-base -fno-sanitize=alignment \
$ADDITIONAL_UBSAN_CHECKS"
- UBSAN_CFLAGS="$UBSAN_CHECKS -Wno-stringop-truncation -Wno-format-overflow -Wno-array-bounds -Wno-stringop-overflow -fno-omit-frame-pointer -DUNDEFINED_BEHAVIOR_SANITIZER"
+ UBSAN_CFLAGS="$UBSAN_CHECKS -Wno-array-bounds -fno-omit-frame-pointer -DUNDEFINED_BEHAVIOR_SANITIZER"
+ if test "x$TOOLCHAIN_TYPE" = "xgcc"; then
+ UBSAN_CFLAGS="$UBSAN_CFLAGS -Wno-format-overflow -Wno-stringop-overflow -Wno-stringop-truncation"
+ fi
UBSAN_LDFLAGS="$UBSAN_CHECKS"
+ # On AIX, the llvm_symbolizer is not found out of the box, so we have to provide the
+ # full qualified llvm_symbolizer path in the __ubsan_default_options() function in
+ # make/data/ubsan/ubsan_default_options.c. To get it there we compile our sources
+ # with an additional define LLVM_SYMBOLIZER, which we set here.
+ # To calculate the correct llvm_symbolizer path we can use the location of the compiler, because
+ # their relation is fixed.
+ if test "x$TOOLCHAIN_TYPE" = "xclang" && test "x$OPENJDK_TARGET_OS" = "xaix"; then
+ UBSAN_CFLAGS="$UBSAN_CFLAGS -fno-sanitize=function,vptr -DLLVM_SYMBOLIZER=$(dirname $(dirname $CC))/tools/ibm-llvm-symbolizer"
+ UBSAN_LDFLAGS="$UBSAN_LDFLAGS -fno-sanitize=function,vptr -Wl,-bbigtoc"
+ fi
UTIL_ARG_ENABLE(NAME: ubsan, DEFAULT: false, RESULT: UBSAN_ENABLED,
DESC: [enable UndefinedBehaviorSanitizer],
CHECK_AVAILABLE: [
diff --git a/make/autoconf/spec.gmk.template b/make/autoconf/spec.gmk.template
index 907a60290ec..ebaa487b40a 100644
--- a/make/autoconf/spec.gmk.template
+++ b/make/autoconf/spec.gmk.template
@@ -846,10 +846,12 @@ SVE_CFLAGS := @SVE_CFLAGS@
JDK_IMAGE_SUBDIR := jdk
JRE_IMAGE_SUBDIR := jre
JCOV_IMAGE_SUBDIR := jdk-jcov
+STATIC_JDK_IMAGE_SUBDIR := static-jdk
# Colon left out to be able to override output dir for bootcycle-images
JDK_IMAGE_DIR = $(IMAGES_OUTPUTDIR)/$(JDK_IMAGE_SUBDIR)
JRE_IMAGE_DIR = $(IMAGES_OUTPUTDIR)/$(JRE_IMAGE_SUBDIR)
+STATIC_JDK_IMAGE_DIR = $(IMAGES_OUTPUTDIR)/$(STATIC_JDK_IMAGE_SUBDIR)
JCOV_IMAGE_DIR = $(IMAGES_OUTPUTDIR)/$(JCOV_IMAGE_SUBDIR)
# Test image, as above
@@ -929,6 +931,7 @@ DOCS_JAVASE_BUNDLE_NAME := javase-$(BASE_NAME)_doc-api-spec$(DEBUG_PART).tar.gz
DOCS_REFERENCE_BUNDLE_NAME := jdk-reference-$(BASE_NAME)_doc-api-spec$(DEBUG_PART).tar.gz
STATIC_LIBS_BUNDLE_NAME := jdk-$(BASE_NAME)_bin-static-libs$(DEBUG_PART).tar.gz
STATIC_LIBS_GRAAL_BUNDLE_NAME := jdk-$(BASE_NAME)_bin-static-libs-graal$(DEBUG_PART).tar.gz
+STATIC_JDK_BUNDLE_NAME := static-jdk-$(BASE_NAME)_bin$(DEBUG_PART).$(JDK_BUNDLE_EXTENSION)
JCOV_BUNDLE_NAME := jdk-jcov-$(BASE_NAME)_bin$(DEBUG_PART).$(JDK_BUNDLE_EXTENSION)
JDK_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(JDK_BUNDLE_NAME)
@@ -939,6 +942,7 @@ TEST_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(TEST_BUNDLE_NAME)
DOCS_JDK_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(DOCS_JDK_BUNDLE_NAME)
DOCS_JAVASE_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(DOCS_JAVASE_BUNDLE_NAME)
DOCS_REFERENCE_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(DOCS_REFERENCE_BUNDLE_NAME)
+STATIC_JDK_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(STATIC_JDK_BUNDLE_NAME)
JCOV_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(JCOV_BUNDLE_NAME)
# This macro is called to allow inclusion of closed source counterparts.
diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js
index aa4d846280e..40fa453f954 100644
--- a/make/conf/jib-profiles.js
+++ b/make/conf/jib-profiles.js
@@ -1090,7 +1090,7 @@ var getJibProfilesDependencies = function (input, common) {
var devkit_platform_revisions = {
linux_x64: "gcc14.2.0-OL6.4+1.0",
macosx: "Xcode14.3.1+1.0",
- windows_x64: "VS2022-17.6.5+1.0",
+ windows_x64: "VS2022-17.13.2+1.0",
linux_aarch64: "gcc14.2.0-OL7.6+1.0",
linux_arm: "gcc8.2.0-Fedora27+1.0",
linux_ppc64le: "gcc14.2.0-Fedora_41+1.0",
diff --git a/make/data/ubsan/ubsan_default_options.c b/make/data/ubsan/ubsan_default_options.c
index 011d1a675a9..05e4722e45a 100644
--- a/make/data/ubsan/ubsan_default_options.c
+++ b/make/data/ubsan/ubsan_default_options.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2025, 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
@@ -43,6 +43,18 @@
#define ATTRIBUTE_USED
#endif
+// On AIX, the llvm_symbolizer is not found out of the box, so we have to provide the
+// full qualified llvm_symbolizer path in the __ubsan_default_options() function.
+// To get it here we compile our sources with an additional define LLVM_SYMBOLIZER
+// containing the path, which we set in make/autoconf/jdk-options.m4.
+#ifdef LLVM_SYMBOLIZER
+#define _LLVM_SYMBOLIZER(X) ",external_symbolizer_path=" X_LLVM_SYMBOLIZER(X)
+#define X_LLVM_SYMBOLIZER(X) #X
+#else
+#define LLVM_SYMBOLIZER
+#define _LLVM_SYMBOLIZER(X)
+#endif
+
// Override weak symbol exposed by UBSan to override default options. This is called by UBSan
// extremely early during library loading, before main is called. We need to override the default
// options because by default UBSan only prints a warning for each occurrence. We want jtreg tests
@@ -50,5 +62,5 @@
// thread so it is easier to track down. You can override these options by setting the environment
// variable UBSAN_OPTIONS.
ATTRIBUTE_DEFAULT_VISIBILITY ATTRIBUTE_USED const char* __ubsan_default_options() {
- return "halt_on_error=1,print_stacktrace=1";
+ return "halt_on_error=1,print_stacktrace=1" _LLVM_SYMBOLIZER(LLVM_SYMBOLIZER);
}
diff --git a/make/devkit/createWindowsDevkit.sh b/make/devkit/createWindowsDevkit.sh
index 0646cb68ef4..757fb157ad4 100644
--- a/make/devkit/createWindowsDevkit.sh
+++ b/make/devkit/createWindowsDevkit.sh
@@ -56,16 +56,22 @@ BUILD_DIR="${SCRIPT_DIR}/../../build/devkit"
UNAME_SYSTEM=`uname -s`
UNAME_RELEASE=`uname -r`
+UNAME_OS=`uname -o`
# Detect cygwin or WSL
IS_CYGWIN=`echo $UNAME_SYSTEM | grep -i CYGWIN`
IS_WSL=`echo $UNAME_RELEASE | grep Microsoft`
+IS_MSYS=`echo $UNAME_OS | grep -i Msys`
+MSYS2_ARG_CONV_EXCL="*" # make "cmd.exe /c" work for msys2
+CMD_EXE="cmd.exe /c"
if test "x$IS_CYGWIN" != "x"; then
BUILD_ENV="cygwin"
+elif test "x$IS_MSYS" != "x"; then
+ BUILD_ENV="cygwin"
elif test "x$IS_WSL" != "x"; then
BUILD_ENV="wsl"
else
- echo "Unknown environment; only Cygwin and WSL are supported."
+ echo "Unknown environment; only Cygwin/MSYS2/WSL are supported."
exit 1
fi
@@ -76,7 +82,7 @@ elif test "x$BUILD_ENV" = "xwsl"; then
fi
# Work around the insanely named ProgramFiles(x86) env variable
-PROGRAMFILES_X86="$($WINDOWS_PATH_TO_UNIX_PATH "$(cmd.exe /c set | sed -n 's/^ProgramFiles(x86)=//p' | tr -d '\r')")"
+PROGRAMFILES_X86="$($WINDOWS_PATH_TO_UNIX_PATH "$(${CMD_EXE} set | sed -n 's/^ProgramFiles(x86)=//p' | tr -d '\r')")"
PROGRAMFILES="$($WINDOWS_PATH_TO_UNIX_PATH "$PROGRAMFILES")"
case $VS_VERSION in
@@ -99,13 +105,15 @@ esac
# Find Visual Studio installation dir
-VSNNNCOMNTOOLS=`cmd.exe /c echo %VS${VS_VERSION_NUM_NODOT}COMNTOOLS% | tr -d '\r'`
+VSNNNCOMNTOOLS=`${CMD_EXE} echo %VS${VS_VERSION_NUM_NODOT}COMNTOOLS% | tr -d '\r'`
+VSNNNCOMNTOOLS="$($WINDOWS_PATH_TO_UNIX_PATH "$VSNNNCOMNTOOLS")"
if [ -d "$VSNNNCOMNTOOLS" ]; then
- VS_INSTALL_DIR="$($WINDOWS_PATH_TO_UNIX_PATH "$VSNNNCOMNTOOLS/../..")"
+ VS_INSTALL_DIR="$VSNNNCOMNTOOLS/../.."
else
VS_INSTALL_DIR="${MSVC_PROGRAMFILES_DIR}/Microsoft Visual Studio/$VS_VERSION"
VS_INSTALL_DIR="$(ls -d "${VS_INSTALL_DIR}/"{Community,Professional,Enterprise} 2>/dev/null | head -n1)"
fi
+echo "VSNNNCOMNTOOLS: $VSNNNCOMNTOOLS"
echo "VS_INSTALL_DIR: $VS_INSTALL_DIR"
# Extract semantic version
@@ -180,7 +188,11 @@ cp $DEVKIT_ROOT/VC/redist/arm64/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/arm64
################################################################################
# Copy SDK files
-SDK_INSTALL_DIR="$PROGRAMFILES_X86/Windows Kits/$SDK_VERSION"
+SDK_INSTALL_DIR=`${CMD_EXE} echo %WindowsSdkDir% | tr -d '\r'`
+SDK_INSTALL_DIR="$($WINDOWS_PATH_TO_UNIX_PATH "$SDK_INSTALL_DIR")"
+if [ ! -d "$SDK_INSTALL_DIR" ]; then
+ SDK_INSTALL_DIR="$PROGRAMFILES_X86/Windows Kits/$SDK_VERSION"
+fi
echo "SDK_INSTALL_DIR: $SDK_INSTALL_DIR"
SDK_FULL_VERSION="$(ls "$SDK_INSTALL_DIR/bin" | sort -r -n | head -n1)"
diff --git a/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java b/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java
index 1b930ca7527..9434889e0bb 100644
--- a/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java
+++ b/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2025, 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
@@ -31,6 +31,8 @@
*/
package build.tools.classlist;
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.foreign.Linker;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
@@ -59,6 +61,7 @@ public class HelloClasslist {
private static final Logger LOGGER = Logger.getLogger("Hello");
+ @SuppressWarnings("restricted")
public static void main(String ... args) throws Throwable {
FileSystems.getDefault();
@@ -141,6 +144,7 @@ public class HelloClasslist {
HelloClasslist.class.getMethod("staticMethod_V").invoke(null);
var obj = HelloClasslist.class.getMethod("staticMethod_L_L", Object.class).invoke(null, instance);
HelloClasslist.class.getField("field").get(instance);
+ MethodHandles.Lookup.ClassOption.class.getEnumConstants();
// A selection of trivial and relatively common MH operations
invoke(MethodHandles.identity(double.class), 1.0);
@@ -160,6 +164,9 @@ public class HelloClasslist {
case B b -> b.b;
default -> 17;
};
+ // record run-time methods
+ o.equals(new B(5));
+ o.hashCode();
LOGGER.log(Level.FINE, "Value: " + value);
// The Striped64$Cell is loaded rarely only when there's a contention among
@@ -167,6 +174,10 @@ public class HelloClasslist {
// an inconsistency in the classlist between builds (see JDK-8295951).
// To avoid the problem, load the class explicitly.
Class> striped64Class = Class.forName("java.util.concurrent.atomic.Striped64$Cell");
+
+ // Initialize FFM linkers
+ var signature = FunctionDescriptor.ofVoid();
+ Linker.nativeLinker().downcallHandle(signature);
}
public HelloClasslist() {}
diff --git a/make/modules/java.base/Lib.gmk b/make/modules/java.base/Lib.gmk
index 84ee309dadd..51d323a0344 100644
--- a/make/modules/java.base/Lib.gmk
+++ b/make/modules/java.base/Lib.gmk
@@ -158,6 +158,7 @@ endif
$(eval $(call SetupJdkLibrary, BUILD_LIBSYSLOOKUP, \
NAME := syslookup, \
+ EXTRA_HEADER_DIRS := java.base:libjava, \
LD_SET_ORIGIN := false, \
LDFLAGS_linux := -Wl$(COMMA)--no-as-needed, \
LDFLAGS_aix := -brtl -bexpfull, \
diff --git a/src/hotspot/.editorconfig b/src/hotspot/.editorconfig
deleted file mode 100644
index 48e63362b54..00000000000
--- a/src/hotspot/.editorconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-[*.{cpp,hpp,c,h}]
-indent_style = space
-indent_size = 2
diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad
index 76e3c92ddc2..1b128f2a0ce 100644
--- a/src/hotspot/cpu/aarch64/aarch64.ad
+++ b/src/hotspot/cpu/aarch64/aarch64.ad
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2014, 2024, Red Hat, Inc. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
@@ -2296,6 +2296,26 @@ bool Matcher::match_rule_supported(int opcode) {
return false;
}
break;
+ case Op_FmaHF:
+ // UseFMA flag also needs to be checked along with FEAT_FP16
+ if (!UseFMA || !is_feat_fp16_supported()) {
+ return false;
+ }
+ break;
+ case Op_AddHF:
+ case Op_SubHF:
+ case Op_MulHF:
+ case Op_DivHF:
+ case Op_MinHF:
+ case Op_MaxHF:
+ case Op_SqrtHF:
+ // Half-precision floating point scalar operations require FEAT_FP16
+ // to be available. FEAT_FP16 is enabled if both "fphp" and "asimdhp"
+ // features are supported.
+ if (!is_feat_fp16_supported()) {
+ return false;
+ }
+ break;
}
return true; // Per default match rules are supported.
@@ -2306,11 +2326,11 @@ const RegMask* Matcher::predicate_reg_mask(void) {
}
bool Matcher::supports_vector_calling_convention(void) {
- return EnableVectorSupport && UseVectorStubs;
+ return EnableVectorSupport;
}
OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
- assert(EnableVectorSupport && UseVectorStubs, "sanity");
+ assert(EnableVectorSupport, "sanity");
int lo = V0_num;
int hi = V0_H_num;
if (ideal_reg == Op_VecX || ideal_reg == Op_VecA) {
@@ -4599,6 +4619,15 @@ operand immF0()
interface(CONST_INTER);
%}
+// Half Float (FP16) Immediate
+operand immH()
+%{
+ match(ConH);
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
//
operand immFPacked()
%{
@@ -6942,6 +6971,21 @@ instruct loadConD(vRegD dst, immD con) %{
ins_pipe(fp_load_constant_d);
%}
+// Load Half Float Constant
+// The "ldr" instruction loads a 32-bit word from the constant pool into a
+// 32-bit register but only the bottom half will be populated and the top
+// 16 bits are zero.
+instruct loadConH(vRegF dst, immH con) %{
+ match(Set dst con);
+ format %{
+ "ldrs $dst, [$constantaddress]\t# load from constant table: half float=$con\n\t"
+ %}
+ ins_encode %{
+ __ ldrs(as_FloatRegister($dst$$reg), $constantaddress($con));
+ %}
+ ins_pipe(fp_load_constant_s);
+%}
+
// Store Instructions
// Store Byte
@@ -8144,6 +8188,7 @@ instruct castPP(iRegPNoSp dst)
instruct castII(iRegI dst)
%{
+ predicate(VerifyConstraintCasts == 0);
match(Set dst (CastII dst));
size(0);
@@ -8153,8 +8198,22 @@ instruct castII(iRegI dst)
ins_pipe(pipe_class_empty);
%}
+instruct castII_checked(iRegI dst, rFlagsReg cr)
+%{
+ predicate(VerifyConstraintCasts > 0);
+ match(Set dst (CastII dst));
+ effect(KILL cr);
+
+ format %{ "# castII_checked of $dst" %}
+ ins_encode %{
+ __ verify_int_in_range(_idx, bottom_type()->is_int(), $dst$$Register, rscratch1);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
instruct castLL(iRegL dst)
%{
+ predicate(VerifyConstraintCasts == 0);
match(Set dst (CastLL dst));
size(0);
@@ -8164,6 +8223,19 @@ instruct castLL(iRegL dst)
ins_pipe(pipe_class_empty);
%}
+instruct castLL_checked(iRegL dst, rFlagsReg cr)
+%{
+ predicate(VerifyConstraintCasts > 0);
+ match(Set dst (CastLL dst));
+ effect(KILL cr);
+
+ format %{ "# castLL_checked of $dst" %}
+ ins_encode %{
+ __ verify_long_in_range(_idx, bottom_type()->is_long(), $dst$$Register, rscratch1);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
instruct castFF(vRegF dst)
%{
match(Set dst (CastFF dst));
@@ -13606,6 +13678,17 @@ instruct bits_reverse_L(iRegLNoSp dst, iRegL src)
// ============================================================================
// Floating Point Arithmetic Instructions
+instruct addHF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
+ match(Set dst (AddHF src1 src2));
+ format %{ "faddh $dst, $src1, $src2" %}
+ ins_encode %{
+ __ faddh($dst$$FloatRegister,
+ $src1$$FloatRegister,
+ $src2$$FloatRegister);
+ %}
+ ins_pipe(fp_dop_reg_reg_s);
+%}
+
instruct addF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (AddF src1 src2));
@@ -13636,6 +13719,17 @@ instruct addD_reg_reg(vRegD dst, vRegD src1, vRegD src2) %{
ins_pipe(fp_dop_reg_reg_d);
%}
+instruct subHF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
+ match(Set dst (SubHF src1 src2));
+ format %{ "fsubh $dst, $src1, $src2" %}
+ ins_encode %{
+ __ fsubh($dst$$FloatRegister,
+ $src1$$FloatRegister,
+ $src2$$FloatRegister);
+ %}
+ ins_pipe(fp_dop_reg_reg_s);
+%}
+
instruct subF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (SubF src1 src2));
@@ -13666,6 +13760,17 @@ instruct subD_reg_reg(vRegD dst, vRegD src1, vRegD src2) %{
ins_pipe(fp_dop_reg_reg_d);
%}
+instruct mulHF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
+ match(Set dst (MulHF src1 src2));
+ format %{ "fmulh $dst, $src1, $src2" %}
+ ins_encode %{
+ __ fmulh($dst$$FloatRegister,
+ $src1$$FloatRegister,
+ $src2$$FloatRegister);
+ %}
+ ins_pipe(fp_dop_reg_reg_s);
+%}
+
instruct mulF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (MulF src1 src2));
@@ -13696,6 +13801,20 @@ instruct mulD_reg_reg(vRegD dst, vRegD src1, vRegD src2) %{
ins_pipe(fp_dop_reg_reg_d);
%}
+// src1 * src2 + src3 (half-precision float)
+instruct maddHF_reg_reg(vRegF dst, vRegF src1, vRegF src2, vRegF src3) %{
+ match(Set dst (FmaHF src3 (Binary src1 src2)));
+ format %{ "fmaddh $dst, $src1, $src2, $src3" %}
+ ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
+ __ fmaddh($dst$$FloatRegister,
+ $src1$$FloatRegister,
+ $src2$$FloatRegister,
+ $src3$$FloatRegister);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
// src1 * src2 + src3
instruct maddF_reg_reg(vRegF dst, vRegF src1, vRegF src2, vRegF src3) %{
match(Set dst (FmaF src3 (Binary src1 src2)));
@@ -13837,6 +13956,29 @@ instruct mnsubD_reg_reg(vRegD dst, vRegD src1, vRegD src2, vRegD src3, immD0 zer
ins_pipe(pipe_class_default);
%}
+// Math.max(HH)H (half-precision float)
+instruct maxHF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
+ match(Set dst (MaxHF src1 src2));
+ format %{ "fmaxh $dst, $src1, $src2" %}
+ ins_encode %{
+ __ fmaxh($dst$$FloatRegister,
+ $src1$$FloatRegister,
+ $src2$$FloatRegister);
+ %}
+ ins_pipe(fp_dop_reg_reg_s);
+%}
+
+// Math.min(HH)H (half-precision float)
+instruct minHF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
+ match(Set dst (MinHF src1 src2));
+ format %{ "fminh $dst, $src1, $src2" %}
+ ins_encode %{
+ __ fminh($dst$$FloatRegister,
+ $src1$$FloatRegister,
+ $src2$$FloatRegister);
+ %}
+ ins_pipe(fp_dop_reg_reg_s);
+%}
// Math.max(FF)F
instruct maxF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
@@ -13894,6 +14036,16 @@ instruct minD_reg_reg(vRegD dst, vRegD src1, vRegD src2) %{
ins_pipe(fp_dop_reg_reg_d);
%}
+instruct divHF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
+ match(Set dst (DivHF src1 src2));
+ format %{ "fdivh $dst, $src1, $src2" %}
+ ins_encode %{
+ __ fdivh($dst$$FloatRegister,
+ $src1$$FloatRegister,
+ $src2$$FloatRegister);
+ %}
+ ins_pipe(fp_div_s);
+%}
instruct divF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (DivF src1 src2));
@@ -14067,6 +14219,16 @@ instruct sqrtF_reg(vRegF dst, vRegF src) %{
ins_pipe(fp_div_d);
%}
+instruct sqrtHF_reg(vRegF dst, vRegF src) %{
+ match(Set dst (SqrtHF src));
+ format %{ "fsqrth $dst, $src" %}
+ ins_encode %{
+ __ fsqrth($dst$$FloatRegister,
+ $src$$FloatRegister);
+ %}
+ ins_pipe(fp_div_s);
+%}
+
// Math.rint, floor, ceil
instruct roundD_reg(vRegD dst, vRegD src, immI rmode) %{
match(Set dst (RoundDoubleMode src rmode));
@@ -17116,6 +17278,64 @@ instruct expandBitsL_memcon(iRegINoSp dst, memory8 mem, immL mask,
ins_pipe(pipe_slow);
%}
+//----------------------------- Reinterpret ----------------------------------
+// Reinterpret a half-precision float value in a floating point register to a general purpose register
+instruct reinterpretHF2S(iRegINoSp dst, vRegF src) %{
+ match(Set dst (ReinterpretHF2S src));
+ format %{ "reinterpretHF2S $dst, $src" %}
+ ins_encode %{
+ __ smov($dst$$Register, $src$$FloatRegister, __ H, 0);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+// Reinterpret a half-precision float value in a general purpose register to a floating point register
+instruct reinterpretS2HF(vRegF dst, iRegINoSp src) %{
+ match(Set dst (ReinterpretS2HF src));
+ format %{ "reinterpretS2HF $dst, $src" %}
+ ins_encode %{
+ __ mov($dst$$FloatRegister, __ H, 0, $src$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+// Without this optimization, ReinterpretS2HF (ConvF2HF src) would result in the following
+// instructions (the first two are for ConvF2HF and the last instruction is for ReinterpretS2HF) -
+// fcvt $tmp1_fpr, $src_fpr // Convert float to half-precision float
+// mov $tmp2_gpr, $tmp1_fpr // Move half-precision float in FPR to a GPR
+// mov $dst_fpr, $tmp2_gpr // Move the result from a GPR to an FPR
+// The move from FPR to GPR in ConvF2HF and the move from GPR to FPR in ReinterpretS2HF
+// can be omitted in this pattern, resulting in -
+// fcvt $dst, $src // Convert float to half-precision float
+instruct convF2HFAndS2HF(vRegF dst, vRegF src)
+%{
+ match(Set dst (ReinterpretS2HF (ConvF2HF src)));
+ format %{ "convF2HFAndS2HF $dst, $src" %}
+ ins_encode %{
+ __ fcvtsh($dst$$FloatRegister, $src$$FloatRegister);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+// Without this optimization, ConvHF2F (ReinterpretHF2S src) would result in the following
+// instructions (the first one is for ReinterpretHF2S and the last two are for ConvHF2F) -
+// mov $tmp1_gpr, $src_fpr // Move the half-precision float from an FPR to a GPR
+// mov $tmp2_fpr, $tmp1_gpr // Move the same value from GPR to an FPR
+// fcvt $dst_fpr, $tmp2_fpr // Convert the half-precision float to 32-bit float
+// The move from FPR to GPR in ReinterpretHF2S and the move from GPR to FPR in ConvHF2F
+// can be omitted as the input (src) is already in an FPR required for the fcvths instruction
+// resulting in -
+// fcvt $dst, $src // Convert half-precision float to a 32-bit float
+instruct convHF2SAndHF2F(vRegF dst, vRegF src)
+%{
+ match(Set dst (ConvHF2F (ReinterpretHF2S src)));
+ format %{ "convHF2SAndHF2F $dst, $src" %}
+ ins_encode %{
+ __ fcvths($dst$$FloatRegister, $src$$FloatRegister);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
// ============================================================================
// This name is KNOWN by the ADLC and cannot be changed.
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp
index 3db7d308844..5c02e30963e 100644
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp
@@ -2032,6 +2032,8 @@ void mvnw(Register Rd, Register Rm,
INSN(fsqrtd, 0b01, 0b000011);
INSN(fcvtd, 0b01, 0b000100); // Double-precision to single-precision
+ INSN(fsqrth, 0b11, 0b000011); // Half-precision sqrt
+
private:
void _fcvt_narrow_extend(FloatRegister Vd, SIMD_Arrangement Ta,
FloatRegister Vn, SIMD_Arrangement Tb, bool do_extend) {
@@ -2059,37 +2061,68 @@ public:
#undef INSN
// Floating-point data-processing (2 source)
- void data_processing(unsigned op31, unsigned type, unsigned opcode,
+ void data_processing(unsigned op31, unsigned type, unsigned opcode, unsigned op21,
FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) {
starti;
f(op31, 31, 29);
f(0b11110, 28, 24);
- f(type, 23, 22), f(1, 21), f(opcode, 15, 10);
+ f(type, 23, 22), f(op21, 21), f(opcode, 15, 10);
rf(Vm, 16), rf(Vn, 5), rf(Vd, 0);
}
-#define INSN(NAME, op31, type, opcode) \
+#define INSN(NAME, op31, type, opcode, op21) \
void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) { \
- data_processing(op31, type, opcode, Vd, Vn, Vm); \
+ data_processing(op31, type, opcode, op21, Vd, Vn, Vm); \
}
- INSN(fabds, 0b011, 0b10, 0b110101);
- INSN(fmuls, 0b000, 0b00, 0b000010);
- INSN(fdivs, 0b000, 0b00, 0b000110);
- INSN(fadds, 0b000, 0b00, 0b001010);
- INSN(fsubs, 0b000, 0b00, 0b001110);
- INSN(fmaxs, 0b000, 0b00, 0b010010);
- INSN(fmins, 0b000, 0b00, 0b010110);
- INSN(fnmuls, 0b000, 0b00, 0b100010);
+ INSN(fmuls, 0b000, 0b00, 0b000010, 0b1);
+ INSN(fdivs, 0b000, 0b00, 0b000110, 0b1);
+ INSN(fadds, 0b000, 0b00, 0b001010, 0b1);
+ INSN(fsubs, 0b000, 0b00, 0b001110, 0b1);
+ INSN(fmaxs, 0b000, 0b00, 0b010010, 0b1);
+ INSN(fmins, 0b000, 0b00, 0b010110, 0b1);
+ INSN(fnmuls, 0b000, 0b00, 0b100010, 0b1);
- INSN(fabdd, 0b011, 0b11, 0b110101);
- INSN(fmuld, 0b000, 0b01, 0b000010);
- INSN(fdivd, 0b000, 0b01, 0b000110);
- INSN(faddd, 0b000, 0b01, 0b001010);
- INSN(fsubd, 0b000, 0b01, 0b001110);
- INSN(fmaxd, 0b000, 0b01, 0b010010);
- INSN(fmind, 0b000, 0b01, 0b010110);
- INSN(fnmuld, 0b000, 0b01, 0b100010);
+ INSN(fmuld, 0b000, 0b01, 0b000010, 0b1);
+ INSN(fdivd, 0b000, 0b01, 0b000110, 0b1);
+ INSN(faddd, 0b000, 0b01, 0b001010, 0b1);
+ INSN(fsubd, 0b000, 0b01, 0b001110, 0b1);
+ INSN(fmaxd, 0b000, 0b01, 0b010010, 0b1);
+ INSN(fmind, 0b000, 0b01, 0b010110, 0b1);
+ INSN(fnmuld, 0b000, 0b01, 0b100010, 0b1);
+
+ // Half-precision floating-point instructions
+ INSN(fmulh, 0b000, 0b11, 0b000010, 0b1);
+ INSN(fdivh, 0b000, 0b11, 0b000110, 0b1);
+ INSN(faddh, 0b000, 0b11, 0b001010, 0b1);
+ INSN(fsubh, 0b000, 0b11, 0b001110, 0b1);
+ INSN(fmaxh, 0b000, 0b11, 0b010010, 0b1);
+ INSN(fminh, 0b000, 0b11, 0b010110, 0b1);
+ INSN(fnmulh, 0b000, 0b11, 0b100010, 0b1);
+#undef INSN
+
+// Advanced SIMD scalar three same
+#define INSN(NAME, U, size, opcode) \
+ void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) { \
+ starti; \
+ f(0b01, 31, 30), f(U, 29), f(0b11110, 28, 24), f(size, 23, 22), f(1, 21); \
+ rf(Vm, 16), f(opcode, 15, 11), f(1, 10), rf(Vn, 5), rf(Vd, 0); \
+ }
+
+ INSN(fabds, 0b1, 0b10, 0b11010); // Floating-point Absolute Difference (single-precision)
+ INSN(fabdd, 0b1, 0b11, 0b11010); // Floating-point Absolute Difference (double-precision)
+
+#undef INSN
+
+// Advanced SIMD scalar three same FP16
+#define INSN(NAME, U, a, opcode) \
+ void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) { \
+ starti; \
+ f(0b01, 31, 30), f(U, 29), f(0b11110, 28, 24), f(a, 23), f(0b10, 22, 21); \
+ rf(Vm, 16), f(0b00, 15, 14), f(opcode, 13, 11), f(1, 10), rf(Vn, 5), rf(Vd, 0); \
+ }
+
+ INSN(fabdh, 0b1, 0b1, 0b010); // Floating-point Absolute Difference (half-precision float)
#undef INSN
@@ -2120,6 +2153,7 @@ public:
INSN(fnmaddd, 0b000, 0b01, 1, 0);
INSN(fnmsub, 0b000, 0b01, 1, 1);
+ INSN(fmaddh, 0b000, 0b11, 0, 0); // half-precision fused multiply-add (scalar)
#undef INSN
// Floating-point conditional select
diff --git a/src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp
index 2334cbdff24..2e53ecb8058 100644
--- a/src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp
@@ -69,7 +69,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ far_call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
return;
}
@@ -90,7 +90,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ blr(lr);
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) {
@@ -103,7 +103,7 @@ void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
__ far_call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
void DivByZeroStub::emit_code(LIR_Assembler* ce) {
@@ -274,7 +274,7 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
__ far_call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
@@ -289,7 +289,7 @@ void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
}
__ far_call(RuntimeAddress(Runtime1::entry_for(_stub)), rscratch2);
ce->add_call_info_here(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp
index 56a91310dcd..585812a99ee 100644
--- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp
@@ -2743,3 +2743,107 @@ bool C2_MacroAssembler::in_scratch_emit_size() {
}
return MacroAssembler::in_scratch_emit_size();
}
+
+static void abort_verify_int_in_range(uint idx, jint val, jint lo, jint hi) {
+ fatal("Invalid CastII, idx: %u, val: %d, lo: %d, hi: %d", idx, val, lo, hi);
+}
+
+void C2_MacroAssembler::verify_int_in_range(uint idx, const TypeInt* t, Register rval, Register rtmp) {
+ assert(!t->empty() && !t->singleton(), "%s", Type::str(t));
+ if (t == TypeInt::INT) {
+ return;
+ }
+ BLOCK_COMMENT("verify_int_in_range {");
+ Label L_success, L_failure;
+
+ jint lo = t->_lo;
+ jint hi = t->_hi;
+
+ if (lo != min_jint && hi != max_jint) {
+ subsw(rtmp, rval, lo);
+ br(Assembler::LT, L_failure);
+ subsw(rtmp, rval, hi);
+ br(Assembler::LE, L_success);
+ } else if (lo != min_jint) {
+ subsw(rtmp, rval, lo);
+ br(Assembler::GE, L_success);
+ } else if (hi != max_jint) {
+ subsw(rtmp, rval, hi);
+ br(Assembler::LE, L_success);
+ } else {
+ ShouldNotReachHere();
+ }
+
+ bind(L_failure);
+ movw(c_rarg0, idx);
+ mov(c_rarg1, rval);
+ movw(c_rarg2, lo);
+ movw(c_rarg3, hi);
+ reconstruct_frame_pointer(rtmp);
+ rt_call(CAST_FROM_FN_PTR(address, abort_verify_int_in_range), rtmp);
+ hlt(0);
+
+ bind(L_success);
+ BLOCK_COMMENT("} verify_int_in_range");
+}
+
+static void abort_verify_long_in_range(uint idx, jlong val, jlong lo, jlong hi) {
+ fatal("Invalid CastLL, idx: %u, val: " JLONG_FORMAT ", lo: " JLONG_FORMAT ", hi: " JLONG_FORMAT, idx, val, lo, hi);
+}
+
+void C2_MacroAssembler::verify_long_in_range(uint idx, const TypeLong* t, Register rval, Register rtmp) {
+ assert(!t->empty() && !t->singleton(), "%s", Type::str(t));
+ if (t == TypeLong::LONG) {
+ return;
+ }
+ BLOCK_COMMENT("verify_long_in_range {");
+ Label L_success, L_failure;
+
+ jlong lo = t->_lo;
+ jlong hi = t->_hi;
+
+ if (lo != min_jlong && hi != max_jlong) {
+ subs(rtmp, rval, lo);
+ br(Assembler::LT, L_failure);
+ subs(rtmp, rval, hi);
+ br(Assembler::LE, L_success);
+ } else if (lo != min_jlong) {
+ subs(rtmp, rval, lo);
+ br(Assembler::GE, L_success);
+ } else if (hi != max_jlong) {
+ subs(rtmp, rval, hi);
+ br(Assembler::LE, L_success);
+ } else {
+ ShouldNotReachHere();
+ }
+
+ bind(L_failure);
+ movw(c_rarg0, idx);
+ mov(c_rarg1, rval);
+ mov(c_rarg2, lo);
+ mov(c_rarg3, hi);
+ reconstruct_frame_pointer(rtmp);
+ rt_call(CAST_FROM_FN_PTR(address, abort_verify_long_in_range), rtmp);
+ hlt(0);
+
+ bind(L_success);
+ BLOCK_COMMENT("} verify_long_in_range");
+}
+
+void C2_MacroAssembler::reconstruct_frame_pointer(Register rtmp) {
+ const int framesize = Compile::current()->output()->frame_size_in_bytes();
+ if (PreserveFramePointer) {
+ // frame pointer is valid
+#ifdef ASSERT
+ // Verify frame pointer value in rfp.
+ add(rtmp, sp, framesize - 2 * wordSize);
+ Label L_success;
+ cmp(rfp, rtmp);
+ br(Assembler::EQ, L_success);
+ stop("frame pointer mismatch");
+ bind(L_success);
+#endif // ASSERT
+ } else {
+ add(rfp, sp, framesize - 2 * wordSize);
+ }
+}
diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp
index e0eaa0b76e6..70e4265c7cc 100644
--- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp
@@ -188,4 +188,9 @@
void vector_signum_sve(FloatRegister dst, FloatRegister src, FloatRegister zero,
FloatRegister one, FloatRegister vtmp, PRegister pgtmp, SIMD_RegVariant T);
+ void verify_int_in_range(uint idx, const TypeInt* t, Register val, Register tmp);
+ void verify_long_in_range(uint idx, const TypeLong* t, Register val, Register tmp);
+
+ void reconstruct_frame_pointer(Register rtmp);
+
#endif // CPU_AARCH64_C2_MACROASSEMBLER_AARCH64_HPP
diff --git a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp
index 0c2d9a32c8c..3874c8cd54e 100644
--- a/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/compressedKlass_aarch64.cpp
@@ -70,7 +70,7 @@ static char* reserve_at_eor_compatible_address(size_t size, bool aslr) {
const uint64_t immediate = ((uint64_t)immediates[index]) << 32;
assert(immediate > 0 && Assembler::operand_valid_for_logical_immediate(/*is32*/false, immediate),
"Invalid immediate %d " UINT64_FORMAT, index, immediate);
- result = os::attempt_reserve_memory_at((char*)immediate, size, false);
+ result = os::attempt_reserve_memory_at((char*)immediate, size, mtNone);
if (result == nullptr) {
log_trace(metaspace, map)("Failed to attach at " UINT64_FORMAT_X, immediate);
}
@@ -114,7 +114,7 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size
if (result == nullptr) {
constexpr size_t alignment = nth_bit(32);
log_debug(metaspace, map)("Trying to reserve at a 32-bit-aligned address");
- result = os::reserve_memory_aligned(size, alignment, false);
+ result = os::reserve_memory_aligned(size, alignment, mtNone);
}
return result;
diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
index f231caeba9f..fd6af0b9b4b 100644
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
@@ -1003,9 +1003,6 @@ void MacroAssembler::c2bool(Register x) {
address MacroAssembler::ic_call(address entry, jint method_index) {
RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index);
- // address const_ptr = long_constant((jlong)Universe::non_oop_word());
- // uintptr_t offset;
- // ldr_constant(rscratch2, const_ptr);
movptr(rscratch2, (intptr_t)Universe::non_oop_word());
return trampoline_call(Address(entry, rh));
}
@@ -5520,9 +5517,8 @@ void MacroAssembler::movoop(Register dst, jobject obj) {
mov(dst, Address((address)obj, rspec));
} else {
address dummy = address(uintptr_t(pc()) & -wordSize); // A nearby aligned address
- ldr_constant(dst, Address(dummy, rspec));
+ ldr(dst, Address(dummy, rspec));
}
-
}
// Move a metadata address into a register.
diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
index af09f97e938..e6075b0073b 100644
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
@@ -1472,16 +1472,6 @@ public:
public:
- void ldr_constant(Register dest, const Address &const_addr) {
- if (NearCpool) {
- ldr(dest, const_addr);
- } else {
- uint64_t offset;
- adrp(dest, InternalAddress(const_addr.target()), offset);
- ldr(dest, Address(dest, offset));
- }
- }
-
address read_polling_page(Register r, relocInfo::relocType rtype);
void get_polling_page(Register dest, relocInfo::relocType rtype);
diff --git a/src/hotspot/cpu/aarch64/matcher_aarch64.hpp b/src/hotspot/cpu/aarch64/matcher_aarch64.hpp
index a6cd0557758..0fbc2ef141e 100644
--- a/src/hotspot/cpu/aarch64/matcher_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/matcher_aarch64.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2025, 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
@@ -200,4 +200,8 @@
return false;
}
+ // Is FEAT_FP16 supported for this CPU?
+ static bool is_feat_fp16_supported() {
+ return (VM_Version::supports_fphp() && VM_Version::supports_asimdhp());
+ }
#endif // CPU_AARCH64_MATCHER_AARCH64_HPP
diff --git a/src/hotspot/cpu/aarch64/runtime_aarch64.cpp b/src/hotspot/cpu/aarch64/runtime_aarch64.cpp
index 83e43c3ebd2..2361d584f42 100644
--- a/src/hotspot/cpu/aarch64/runtime_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/runtime_aarch64.cpp
@@ -65,6 +65,9 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBuffer buffer(name, 2048, 1024);
+ if (buffer.blob() == nullptr) {
+ return nullptr;
+ }
MacroAssembler* masm = new MacroAssembler(&buffer);
assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned");
@@ -285,6 +288,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 2048, 1024);
+ if (buffer.blob() == nullptr) {
+ return nullptr;
+ }
MacroAssembler* masm = new MacroAssembler(&buffer);
// TODO check various assumptions made here
diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
index a6cc757f6a0..f5567dcc03a 100644
--- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
@@ -11166,79 +11166,6 @@ class StubGenerator: public StubCodeGenerator {
// }
};
- void generate_vector_math_stubs() {
- // Get native vector math stub routine addresses
- void* libsleef = nullptr;
- char ebuf[1024];
- char dll_name[JVM_MAXPATHLEN];
- if (os::dll_locate_lib(dll_name, sizeof(dll_name), Arguments::get_dll_dir(), "sleef")) {
- libsleef = os::dll_load(dll_name, ebuf, sizeof ebuf);
- }
- if (libsleef == nullptr) {
- log_info(library)("Failed to load native vector math library, %s!", ebuf);
- return;
- }
- // Method naming convention
- // All the methods are named as _
- // Where:
- // is the operation name, e.g. sin
- // is optional to indicate float/double
- // "f/d" for vector float/double operation
- // is the number of elements in the vector
- // "2/4" for neon, and "x" for sve
- // is the precision level
- // "u10/u05" represents 1.0/0.5 ULP error bounds
- // We use "u10" for all operations by default
- // But for those functions do not have u10 support, we use "u05" instead
- // indicates neon/sve
- // "sve/advsimd" for sve/neon implementations
- // e.g. sinfx_u10sve is the method for computing vector float sin using SVE instructions
- // cosd2_u10advsimd is the method for computing 2 elements vector double cos using NEON instructions
- //
- log_info(library)("Loaded library %s, handle " INTPTR_FORMAT, JNI_LIB_PREFIX "sleef" JNI_LIB_SUFFIX, p2i(libsleef));
-
- // Math vector stubs implemented with SVE for scalable vector size.
- if (UseSVE > 0) {
- for (int op = 0; op < VectorSupport::NUM_VECTOR_OP_MATH; op++) {
- int vop = VectorSupport::VECTOR_OP_MATH_START + op;
- // Skip "tanh" because there is performance regression
- if (vop == VectorSupport::VECTOR_OP_TANH) {
- continue;
- }
-
- // The native library does not support u10 level of "hypot".
- const char* ulf = (vop == VectorSupport::VECTOR_OP_HYPOT) ? "u05" : "u10";
-
- snprintf(ebuf, sizeof(ebuf), "%sfx_%ssve", VectorSupport::mathname[op], ulf);
- StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_SCALABLE][op] = (address)os::dll_lookup(libsleef, ebuf);
-
- snprintf(ebuf, sizeof(ebuf), "%sdx_%ssve", VectorSupport::mathname[op], ulf);
- StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_SCALABLE][op] = (address)os::dll_lookup(libsleef, ebuf);
- }
- }
-
- // Math vector stubs implemented with NEON for 64/128 bits vector size.
- for (int op = 0; op < VectorSupport::NUM_VECTOR_OP_MATH; op++) {
- int vop = VectorSupport::VECTOR_OP_MATH_START + op;
- // Skip "tanh" because there is performance regression
- if (vop == VectorSupport::VECTOR_OP_TANH) {
- continue;
- }
-
- // The native library does not support u10 level of "hypot".
- const char* ulf = (vop == VectorSupport::VECTOR_OP_HYPOT) ? "u05" : "u10";
-
- snprintf(ebuf, sizeof(ebuf), "%sf4_%sadvsimd", VectorSupport::mathname[op], ulf);
- StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_64][op] = (address)os::dll_lookup(libsleef, ebuf);
-
- snprintf(ebuf, sizeof(ebuf), "%sf4_%sadvsimd", VectorSupport::mathname[op], ulf);
- StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_128][op] = (address)os::dll_lookup(libsleef, ebuf);
-
- snprintf(ebuf, sizeof(ebuf), "%sd2_%sadvsimd", VectorSupport::mathname[op], ulf);
- StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_128][op] = (address)os::dll_lookup(libsleef, ebuf);
- }
- }
-
// Initialization
void generate_initial_stubs() {
// Generate initial stubs and initializes the entry points
@@ -11392,8 +11319,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_montgomerySquare = g.generate_multiply();
}
- generate_vector_math_stubs();
-
#endif // COMPILER2
if (UseChaCha20Intrinsics) {
diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
index b2d34553487..6ed7a6be585 100644
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
@@ -642,6 +642,7 @@ void VM_Version::initialize() {
if (_model2) {
os::snprintf_checked(buf + buf_used_len, sizeof(buf) - buf_used_len, "(0x%03x)", _model2);
}
+ size_t features_offset = strnlen(buf, sizeof(buf));
#define ADD_FEATURE_IF_SUPPORTED(id, name, bit) \
do { \
if (VM_Version::supports_##name()) strcat(buf, ", " #name); \
@@ -649,7 +650,11 @@ void VM_Version::initialize() {
CPU_FEATURE_FLAGS(ADD_FEATURE_IF_SUPPORTED)
#undef ADD_FEATURE_IF_SUPPORTED
- _features_string = os::strdup(buf);
+ _cpu_info_string = os::strdup(buf);
+
+ _features_string = extract_features_string(_cpu_info_string,
+ strnlen(_cpu_info_string, sizeof(buf)),
+ features_offset);
}
#if defined(LINUX)
@@ -716,7 +721,7 @@ void VM_Version::initialize_cpu_information(void) {
int desc_len = snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "AArch64 ");
get_compatible_board(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len);
desc_len = (int)strlen(_cpu_desc);
- snprintf(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len, " %s", _features_string);
+ snprintf(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len, " %s", _cpu_info_string);
_initialized = true;
}
diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp
index 04cf9c9c2a0..373f8da5405 100644
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -125,6 +125,8 @@ enum Ampere_CPU_Model {
decl(SHA2, sha256, 6) \
decl(CRC32, crc32, 7) \
decl(LSE, lse, 8) \
+ decl(FPHP, fphp, 9) \
+ decl(ASIMDHP, asimdhp, 10) \
decl(DCPOP, dcpop, 16) \
decl(SHA3, sha3, 17) \
decl(SHA512, sha512, 21) \
diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad
index f3b97d23ad3..4a0b557968c 100644
--- a/src/hotspot/cpu/arm/arm.ad
+++ b/src/hotspot/cpu/arm/arm.ad
@@ -1238,11 +1238,11 @@ encode %{
enc_class save_last_PC %{
// preserve mark
address mark = __ inst_mark();
- debug_only(int off0 = __ offset());
+ DEBUG_ONLY(int off0 = __ offset());
int ret_addr_offset = as_MachCall()->ret_addr_offset();
__ adr(LR, mark + ret_addr_offset);
__ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset()));
- debug_only(int off1 = __ offset());
+ DEBUG_ONLY(int off1 = __ offset());
assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction");
// restore mark
__ set_inst_mark(mark);
@@ -1251,11 +1251,11 @@ encode %{
enc_class preserve_SP %{
// preserve mark
address mark = __ inst_mark();
- debug_only(int off0 = __ offset());
+ DEBUG_ONLY(int off0 = __ offset());
// FP is preserved across all calls, even compiled calls.
// Use it to preserve SP in places where the callee might change the SP.
__ mov(Rmh_SP_save, SP);
- debug_only(int off1 = __ offset());
+ DEBUG_ONLY(int off1 = __ offset());
assert(off1 - off0 == 4, "correct size prediction");
// restore mark
__ set_inst_mark(mark);
diff --git a/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp b/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp
index bca6c7ca30c..5683bc59d5c 100644
--- a/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp
+++ b/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp
@@ -59,7 +59,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ call(Runtime1::entry_for(C1StubId::predicate_failed_trap_id), relocInfo::runtime_call_type);
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
return;
}
// Pass the array index on stack because all registers must be preserved
@@ -91,7 +91,7 @@ void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
__ call(Runtime1::entry_for(C1StubId::predicate_failed_trap_id), relocInfo::runtime_call_type);
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
void DivByZeroStub::emit_code(LIR_Assembler* ce) {
diff --git a/src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp b/src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp
index c6cc0ce406e..52d71ca65c2 100644
--- a/src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp
+++ b/src/hotspot/cpu/arm/gc/shared/barrierSetNMethod_arm.cpp
@@ -72,7 +72,7 @@ void NativeNMethodBarrier::verify() const {
static NativeNMethodBarrier* native_nmethod_barrier(nmethod* nm) {
address barrier_address = nm->code_begin() + nm->frame_complete_offset() - entry_barrier_bytes;
NativeNMethodBarrier* barrier = reinterpret_cast(barrier_address);
- debug_only(barrier->verify());
+ DEBUG_ONLY(barrier->verify());
return barrier;
}
diff --git a/src/hotspot/cpu/arm/runtime_arm.cpp b/src/hotspot/cpu/arm/runtime_arm.cpp
index 20c1bc199d3..615a63eac19 100644
--- a/src/hotspot/cpu/arm/runtime_arm.cpp
+++ b/src/hotspot/cpu/arm/runtime_arm.cpp
@@ -54,6 +54,9 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Measured 8/7/03 at 660 in 32bit debug build
CodeBuffer buffer(name, 2000, 512);
#endif
+ if (buffer.blob() == nullptr) {
+ return nullptr;
+ }
// bypassed when code generation useless
MacroAssembler* masm = new MacroAssembler(&buffer);
const Register Rublock = R6;
@@ -209,6 +212,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
// Measured 8/7/03 at 256 in 32bit debug build
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 600, 512);
+ if (buffer.blob() == nullptr) {
+ return nullptr;
+ }
MacroAssembler* masm = new MacroAssembler(&buffer);
int framesize_in_words = 2; // FP + LR
diff --git a/src/hotspot/cpu/arm/vm_version_arm_32.cpp b/src/hotspot/cpu/arm/vm_version_arm_32.cpp
index 148786a55da..d0941936035 100644
--- a/src/hotspot/cpu/arm/vm_version_arm_32.cpp
+++ b/src/hotspot/cpu/arm/vm_version_arm_32.cpp
@@ -295,7 +295,7 @@ void VM_Version::initialize() {
(has_multiprocessing_extensions() ? ", mp_ext" : ""));
// buf is started with ", " or is empty
- _features_string = os::strdup(buf);
+ _cpu_info_string = os::strdup(buf);
if (has_simd()) {
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
@@ -363,6 +363,6 @@ void VM_Version::initialize_cpu_information(void) {
_no_of_threads = _no_of_cores;
_no_of_sockets = _no_of_cores;
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "ARM%d", _arm_arch);
- snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _features_string);
+ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _cpu_info_string);
_initialized = true;
}
diff --git a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp
index d4f5faa29a8..a390a6eeed4 100644
--- a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp
+++ b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp
@@ -74,7 +74,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ bctrl();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ illtrap());
+ DEBUG_ONLY(__ illtrap());
return;
}
@@ -98,7 +98,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ bctrl();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ illtrap());
+ DEBUG_ONLY(__ illtrap());
}
@@ -115,7 +115,7 @@ void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
__ bctrl();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ illtrap());
+ DEBUG_ONLY(__ illtrap());
}
@@ -156,7 +156,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) {
__ bctrl();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ illtrap());
+ DEBUG_ONLY(__ illtrap());
}
@@ -179,7 +179,7 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
__ bctrl();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ illtrap());
+ DEBUG_ONLY(__ illtrap());
}
@@ -193,7 +193,7 @@ void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
__ mtctr(R0);
__ bctrl();
ce->add_call_info_here(_info);
- debug_only( __ illtrap(); )
+ DEBUG_ONLY( __ illtrap(); )
}
@@ -441,7 +441,7 @@ void DeoptimizeStub::emit_code(LIR_Assembler* ce) {
__ load_const_optimized(R0, _trap_request); // Pass trap request in R0.
__ bctrl();
ce->add_call_info_here(_info);
- debug_only(__ illtrap());
+ DEBUG_ONLY(__ illtrap());
}
diff --git a/src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp b/src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp
index e4684613e25..8ce324a570b 100644
--- a/src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp
+++ b/src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp
@@ -189,7 +189,7 @@ LIR_Opr FrameMap::_caller_save_fpu_regs[] = {};
FloatRegister FrameMap::nr2floatreg (int rnr) {
assert(_init_done, "tables not initialized");
- debug_only(fpu_range_check(rnr);)
+ DEBUG_ONLY(fpu_range_check(rnr);)
return _fpu_regs[rnr];
}
diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp
index 1b44a169e67..d3bb9cc3c04 100644
--- a/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp
+++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp
@@ -108,7 +108,7 @@ static NativeNMethodBarrier* get_nmethod_barrier(nmethod* nm) {
}
auto barrier = reinterpret_cast(barrier_address);
- debug_only(barrier->verify());
+ DEBUG_ONLY(barrier->verify());
return barrier;
}
diff --git a/src/hotspot/cpu/ppc/runtime_ppc.cpp b/src/hotspot/cpu/ppc/runtime_ppc.cpp
index 94e8c08ebf5..6d9a1dfcb1e 100644
--- a/src/hotspot/cpu/ppc/runtime_ppc.cpp
+++ b/src/hotspot/cpu/ppc/runtime_ppc.cpp
@@ -73,6 +73,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
// Setup code generation tools.
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 2048, 1024);
+ if (buffer.blob() == nullptr) {
+ return nullptr;
+ }
InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer);
address start = __ pc();
diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
index 5a94d469434..1c9c88b3c30 100644
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
+++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
@@ -3106,6 +3106,9 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Setup code generation tools.
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBuffer buffer(name, 2048, 1024);
+ if (buffer.blob() == nullptr) {
+ return nullptr;
+ }
InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer);
address start = __ pc();
diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp
index 8ec69bffe15..3cb0bf9bf72 100644
--- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp
+++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp
@@ -219,7 +219,7 @@ void VM_Version::initialize() {
(has_brw() ? " brw" : "")
// Make sure number of %s matches num_features!
);
- _features_string = os::strdup(buf);
+ _cpu_info_string = os::strdup(buf);
if (Verbose) {
print_features();
}
@@ -519,7 +519,7 @@ void VM_Version::print_platform_virtualization_info(outputStream* st) {
}
void VM_Version::print_features() {
- tty->print_cr("Version: %s L1_data_cache_line_size=%d", features_string(), L1_data_cache_line_size());
+ tty->print_cr("Version: %s L1_data_cache_line_size=%d", cpu_info_string(), L1_data_cache_line_size());
if (Verbose) {
if (ContendedPaddingWidth > 0) {
@@ -726,6 +726,6 @@ void VM_Version::initialize_cpu_information(void) {
_no_of_threads = _no_of_cores;
_no_of_sockets = _no_of_cores;
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE, "PowerPC POWER%lu", PowerArchitecturePPC64);
- snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "PPC %s", features_string());
+ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "PPC %s", cpu_info_string());
_initialized = true;
}
diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp
index e036cb6b1ec..4773043e1ba 100644
--- a/src/hotspot/cpu/riscv/assembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp
@@ -2323,6 +2323,7 @@ enum Nf {
}
// Vector Bit-manipulation used in Cryptography (Zvbb) Extension
+ INSN(vandn_vx, 0b1010111, 0b100, 0b000001);
INSN(vrol_vx, 0b1010111, 0b100, 0b010101);
INSN(vror_vx, 0b1010111, 0b100, 0b010100);
diff --git a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp
index d55521823ec..ea299181ca7 100644
--- a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp
+++ b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp
@@ -70,7 +70,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ far_call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
return;
}
@@ -92,7 +92,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ rt_call(Runtime1::entry_for(stub_id), ra);
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) {
@@ -105,7 +105,7 @@ void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
__ far_call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
void DivByZeroStub::emit_code(LIR_Assembler* ce) {
@@ -258,7 +258,7 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
__ far_call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
@@ -272,7 +272,7 @@ void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
}
__ far_call(RuntimeAddress(Runtime1::entry_for(_stub)));
ce->add_call_info_here(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
void ArrayCopyStub::emit_code(LIR_Assembler* ce) {
diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp
index 295e92bbc1b..d8f5fa57816 100644
--- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp
+++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp
@@ -300,7 +300,7 @@ public:
inline NativeGeneralJump* nativeGeneralJump_at(address addr) {
assert_cond(addr != nullptr);
NativeGeneralJump* jump = (NativeGeneralJump*)(addr);
- debug_only(jump->verify();)
+ DEBUG_ONLY(jump->verify();)
return jump;
}
diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad
index 2e9d25c8156..f6fb2e195d3 100644
--- a/src/hotspot/cpu/riscv/riscv.ad
+++ b/src/hotspot/cpu/riscv/riscv.ad
@@ -1596,7 +1596,8 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r
__ unspill(as_VectorRegister(Matcher::_regEncode[dst_lo]), ra_->reg2offset(src_lo));
} else if (src_lo_rc == rc_vector && dst_lo_rc == rc_vector) {
// vpr to vpr
- __ vmv1r_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo]));
+ __ vsetvli_helper(T_BYTE, MaxVectorSize);
+ __ vmv_v_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo]));
} else {
ShouldNotReachHere();
}
@@ -1614,7 +1615,8 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r
__ unspill_vmask(as_VectorRegister(Matcher::_regEncode[dst_lo]), ra_->reg2offset(src_lo));
} else if (src_lo_rc == rc_vector && dst_lo_rc == rc_vector) {
// vmask to vmask
- __ vmv1r_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo]));
+ __ vsetvli_helper(T_BYTE, MaxVectorSize >> 3);
+ __ vmv_v_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo]));
} else {
ShouldNotReachHere();
}
@@ -1914,9 +1916,10 @@ bool Matcher::match_rule_supported(int opcode) {
case Op_FmaF:
case Op_FmaD:
+ return UseFMA;
case Op_FmaVF:
case Op_FmaVD:
- return UseFMA;
+ return UseRVV && UseFMA;
case Op_ConvHF2F:
case Op_ConvF2HF:
@@ -1950,11 +1953,11 @@ const RegMask* Matcher::predicate_reg_mask(void) {
// Vector calling convention not yet implemented.
bool Matcher::supports_vector_calling_convention(void) {
- return EnableVectorSupport && UseVectorStubs;
+ return EnableVectorSupport;
}
OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
- assert(EnableVectorSupport && UseVectorStubs, "sanity");
+ assert(EnableVectorSupport, "sanity");
assert(ideal_reg == Op_VecA, "sanity");
// check more info at https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc
int lo = V8_num;
diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad
index 6fea439954c..58c78874797 100644
--- a/src/hotspot/cpu/riscv/riscv_v.ad
+++ b/src/hotspot/cpu/riscv/riscv_v.ad
@@ -415,11 +415,11 @@ instruct vadd_fp_masked(vReg dst_src1, vReg src2, vRegMask_V0 v0) %{
// vector-immediate add (unpredicated)
-instruct vadd_immI(vReg dst, vReg src1, immI5 con) %{
+instruct vadd_vi(vReg dst, vReg src1, immI5 con) %{
match(Set dst (AddVB src1 (Replicate con)));
match(Set dst (AddVS src1 (Replicate con)));
match(Set dst (AddVI src1 (Replicate con)));
- format %{ "vadd_immI $dst, $src1, $con" %}
+ format %{ "vadd_vi $dst, $src1, $con" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -430,9 +430,9 @@ instruct vadd_immI(vReg dst, vReg src1, immI5 con) %{
ins_pipe(pipe_slow);
%}
-instruct vadd_immL(vReg dst, vReg src1, immL5 con) %{
+instruct vaddL_vi(vReg dst, vReg src1, immL5 con) %{
match(Set dst (AddVL src1 (Replicate con)));
- format %{ "vadd_immL $dst, $src1, $con" %}
+ format %{ "vaddL_vi $dst, $src1, $con" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vadd_vi(as_VectorRegister($dst$$reg),
@@ -444,11 +444,11 @@ instruct vadd_immL(vReg dst, vReg src1, immL5 con) %{
// vector-scalar add (unpredicated)
-instruct vadd_regI(vReg dst, vReg src1, iRegIorL2I src2) %{
+instruct vadd_vx(vReg dst, vReg src1, iRegIorL2I src2) %{
match(Set dst (AddVB src1 (Replicate src2)));
match(Set dst (AddVS src1 (Replicate src2)));
match(Set dst (AddVI src1 (Replicate src2)));
- format %{ "vadd_regI $dst, $src1, $src2" %}
+ format %{ "vadd_vx $dst, $src1, $src2" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -459,9 +459,9 @@ instruct vadd_regI(vReg dst, vReg src1, iRegIorL2I src2) %{
ins_pipe(pipe_slow);
%}
-instruct vadd_regL(vReg dst, vReg src1, iRegL src2) %{
+instruct vaddL_vx(vReg dst, vReg src1, iRegL src2) %{
match(Set dst (AddVL src1 (Replicate src2)));
- format %{ "vadd_regL $dst, $src1, $src2" %}
+ format %{ "vaddL_vx $dst, $src1, $src2" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vadd_vx(as_VectorRegister($dst$$reg),
@@ -473,11 +473,11 @@ instruct vadd_regL(vReg dst, vReg src1, iRegL src2) %{
// vector-immediate add (predicated)
-instruct vadd_immI_masked(vReg dst_src, immI5 con, vRegMask_V0 v0) %{
+instruct vadd_vi_masked(vReg dst_src, immI5 con, vRegMask_V0 v0) %{
match(Set dst_src (AddVB (Binary dst_src (Replicate con)) v0));
match(Set dst_src (AddVS (Binary dst_src (Replicate con)) v0));
match(Set dst_src (AddVI (Binary dst_src (Replicate con)) v0));
- format %{ "vadd_immI_masked $dst_src, $dst_src, $con" %}
+ format %{ "vadd_vi_masked $dst_src, $dst_src, $con, $v0" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -488,9 +488,9 @@ instruct vadd_immI_masked(vReg dst_src, immI5 con, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vadd_immL_masked(vReg dst_src, immL5 con, vRegMask_V0 v0) %{
+instruct vaddL_vi_masked(vReg dst_src, immL5 con, vRegMask_V0 v0) %{
match(Set dst_src (AddVL (Binary dst_src (Replicate con)) v0));
- format %{ "vadd_immL_masked $dst_src, $dst_src, $con" %}
+ format %{ "vaddL_vi_masked $dst_src, $dst_src, $con, $v0" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vadd_vi(as_VectorRegister($dst_src$$reg),
@@ -502,11 +502,11 @@ instruct vadd_immL_masked(vReg dst_src, immL5 con, vRegMask_V0 v0) %{
// vector-scalar add (predicated)
-instruct vadd_regI_masked(vReg dst_src, iRegIorL2I src2, vRegMask_V0 v0) %{
+instruct vadd_vx_masked(vReg dst_src, iRegIorL2I src2, vRegMask_V0 v0) %{
match(Set dst_src (AddVB (Binary dst_src (Replicate src2)) v0));
match(Set dst_src (AddVS (Binary dst_src (Replicate src2)) v0));
match(Set dst_src (AddVI (Binary dst_src (Replicate src2)) v0));
- format %{ "vadd_regI_masked $dst_src, $dst_src, $src2" %}
+ format %{ "vadd_vx_masked $dst_src, $dst_src, $src2, $v0" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -517,9 +517,9 @@ instruct vadd_regI_masked(vReg dst_src, iRegIorL2I src2, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vadd_regL_masked(vReg dst_src, iRegL src2, vRegMask_V0 v0) %{
+instruct vaddL_vx_masked(vReg dst_src, iRegL src2, vRegMask_V0 v0) %{
match(Set dst_src (AddVL (Binary dst_src (Replicate src2)) v0));
- format %{ "vadd_regL_masked $dst_src, $dst_src, $src2" %}
+ format %{ "vaddL_vx_masked $dst_src, $dst_src, $src2, $v0" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vadd_vx(as_VectorRegister($dst_src$$reg),
@@ -595,11 +595,11 @@ instruct vsub_fp_masked(vReg dst_src1, vReg src2, vRegMask_V0 v0) %{
// vector-scalar sub (unpredicated)
-instruct vsub_regI(vReg dst, vReg src1, iRegIorL2I src2) %{
+instruct vsub_vx(vReg dst, vReg src1, iRegIorL2I src2) %{
match(Set dst (SubVB src1 (Replicate src2)));
match(Set dst (SubVS src1 (Replicate src2)));
match(Set dst (SubVI src1 (Replicate src2)));
- format %{ "vsub_regI $dst, $src1, $src2" %}
+ format %{ "vsub_vx $dst, $src1, $src2" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -610,9 +610,9 @@ instruct vsub_regI(vReg dst, vReg src1, iRegIorL2I src2) %{
ins_pipe(pipe_slow);
%}
-instruct vsub_regL(vReg dst, vReg src1, iRegL src2) %{
+instruct vsubL_vx(vReg dst, vReg src1, iRegL src2) %{
match(Set dst (SubVL src1 (Replicate src2)));
- format %{ "vsub_regL $dst, $src1, $src2" %}
+ format %{ "vsubL_vx $dst, $src1, $src2" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vsub_vx(as_VectorRegister($dst$$reg),
@@ -624,11 +624,11 @@ instruct vsub_regL(vReg dst, vReg src1, iRegL src2) %{
// vector-scalar sub (predicated)
-instruct vsub_regI_masked(vReg dst_src, iRegIorL2I src2, vRegMask_V0 v0) %{
+instruct vsub_vx_masked(vReg dst_src, iRegIorL2I src2, vRegMask_V0 v0) %{
match(Set dst_src (SubVB (Binary dst_src (Replicate src2)) v0));
match(Set dst_src (SubVS (Binary dst_src (Replicate src2)) v0));
match(Set dst_src (SubVI (Binary dst_src (Replicate src2)) v0));
- format %{ "vsub_regI_masked $dst_src, $dst_src, $src2" %}
+ format %{ "vsub_vx_masked $dst_src, $dst_src, $src2, $v0" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -639,9 +639,9 @@ instruct vsub_regI_masked(vReg dst_src, iRegIorL2I src2, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vsub_regL_masked(vReg dst_src, iRegL src2, vRegMask_V0 v0) %{
+instruct vsubL_vx_masked(vReg dst_src, iRegL src2, vRegMask_V0 v0) %{
match(Set dst_src (SubVL (Binary dst_src (Replicate src2)) v0));
- format %{ "vsub_regL_masked $dst_src, $dst_src, $src2" %}
+ format %{ "vsubL_vx_masked $dst_src, $dst_src, $src2, $v0" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vsub_vx(as_VectorRegister($dst_src$$reg),
@@ -685,30 +685,30 @@ instruct vand_masked(vReg dst_src1, vReg src2, vRegMask_V0 v0) %{
// vector-immediate and (unpredicated)
-instruct vand_immI(vReg dst_src, immI5 con) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
- match(Set dst_src (AndV dst_src (Replicate con)));
- format %{ "vand_immI $dst_src, $dst_src, $con" %}
+instruct vand_vi(vReg dst, vReg src1, immI5 con) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
+ match(Set dst (AndV src1 (Replicate con)));
+ format %{ "vand_vi $dst, $src1, $con" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
- __ vand_vi(as_VectorRegister($dst_src$$reg),
- as_VectorRegister($dst_src$$reg),
+ __ vand_vi(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
$con$$constant);
%}
ins_pipe(pipe_slow);
%}
-instruct vand_immL(vReg dst_src, immL5 con) %{
+instruct vandL_vi(vReg dst, vReg src1, immL5 con) %{
predicate(Matcher::vector_element_basic_type(n) == T_LONG);
- match(Set dst_src (AndV dst_src (Replicate con)));
- format %{ "vand_immL $dst_src, $dst_src, $con" %}
+ match(Set dst (AndV src1 (Replicate con)));
+ format %{ "vandL_vi $dst, $src1, $con" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
- __ vand_vi(as_VectorRegister($dst_src$$reg),
- as_VectorRegister($dst_src$$reg),
+ __ vand_vi(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
$con$$constant);
%}
ins_pipe(pipe_slow);
@@ -716,43 +716,43 @@ instruct vand_immL(vReg dst_src, immL5 con) %{
// vector-scalar and (unpredicated)
-instruct vand_regI(vReg dst_src, iRegIorL2I src) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
- match(Set dst_src (AndV dst_src (Replicate src)));
- format %{ "vand_regI $dst_src, $dst_src, $src" %}
+instruct vand_vx(vReg dst, vReg src1, iRegIorL2I src2) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
+ match(Set dst (AndV src1 (Replicate src2)));
+ format %{ "vand_vx $dst, $src1, $src2" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
- __ vand_vx(as_VectorRegister($dst_src$$reg),
- as_VectorRegister($dst_src$$reg),
- as_Register($src$$reg));
+ __ vand_vx(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
+ as_Register($src2$$reg));
%}
ins_pipe(pipe_slow);
%}
-instruct vand_regL(vReg dst_src, iRegL src) %{
+instruct vandL_vx(vReg dst, vReg src1, iRegL src2) %{
predicate(Matcher::vector_element_basic_type(n) == T_LONG);
- match(Set dst_src (AndV dst_src (Replicate src)));
- format %{ "vand_regL $dst_src, $dst_src, $src" %}
+ match(Set dst (AndV src1 (Replicate src2)));
+ format %{ "vandL_vx $dst, $src1, $src2" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
- __ vand_vx(as_VectorRegister($dst_src$$reg),
- as_VectorRegister($dst_src$$reg),
- as_Register($src$$reg));
+ __ vand_vx(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
+ as_Register($src2$$reg));
%}
ins_pipe(pipe_slow);
%}
// vector-immediate and (predicated)
-instruct vand_immI_masked(vReg dst_src, immI5 con, vRegMask_V0 v0) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
+instruct vand_vi_masked(vReg dst_src, immI5 con, vRegMask_V0 v0) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
match(Set dst_src (AndV (Binary dst_src (Replicate con)) v0));
- format %{ "vand_immI_masked $dst_src, $dst_src, $con" %}
+ format %{ "vand_vi_masked $dst_src, $dst_src, $con, $v0" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -763,10 +763,10 @@ instruct vand_immI_masked(vReg dst_src, immI5 con, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vand_immL_masked(vReg dst_src, immL5 con, vRegMask_V0 v0) %{
+instruct vandL_vi_masked(vReg dst_src, immL5 con, vRegMask_V0 v0) %{
predicate(Matcher::vector_element_basic_type(n) == T_LONG);
match(Set dst_src (AndV (Binary dst_src (Replicate con)) v0));
- format %{ "vand_immL_masked $dst_src, $dst_src, $con" %}
+ format %{ "vandL_vi_masked $dst_src, $dst_src, $con, $v0" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vand_vi(as_VectorRegister($dst_src$$reg),
@@ -778,12 +778,12 @@ instruct vand_immL_masked(vReg dst_src, immL5 con, vRegMask_V0 v0) %{
// vector-scalar and (predicated)
-instruct vand_regI_masked(vReg dst_src, iRegIorL2I src, vRegMask_V0 v0) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
+instruct vand_vx_masked(vReg dst_src, iRegIorL2I src, vRegMask_V0 v0) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
match(Set dst_src (AndV (Binary dst_src (Replicate src)) v0));
- format %{ "vand_regI_masked $dst_src, $dst_src, $src" %}
+ format %{ "vand_vx_masked $dst_src, $dst_src, $src, $v0" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -794,10 +794,10 @@ instruct vand_regI_masked(vReg dst_src, iRegIorL2I src, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vand_regL_masked(vReg dst_src, iRegL src, vRegMask_V0 v0) %{
+instruct vandL_vx_masked(vReg dst_src, iRegL src, vRegMask_V0 v0) %{
predicate(Matcher::vector_element_basic_type(n) == T_LONG);
match(Set dst_src (AndV (Binary dst_src (Replicate src)) v0));
- format %{ "vand_regL_masked $dst_src, $dst_src, $src" %}
+ format %{ "vandL_vx_masked $dst_src, $dst_src, $src, $v0" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vand_vx(as_VectorRegister($dst_src$$reg),
@@ -841,30 +841,30 @@ instruct vor_masked(vReg dst_src1, vReg src2, vRegMask_V0 v0) %{
// vector-immediate or (unpredicated)
-instruct vor_immI(vReg dst_src, immI5 con) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
- match(Set dst_src (OrV dst_src (Replicate con)));
- format %{ "vor_immI $dst_src, $dst_src, $con" %}
+instruct vor_vi(vReg dst, vReg src1, immI5 con) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
+ match(Set dst (OrV src1 (Replicate con)));
+ format %{ "vor_vi $dst, $src1, $con" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
- __ vor_vi(as_VectorRegister($dst_src$$reg),
- as_VectorRegister($dst_src$$reg),
+ __ vor_vi(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
$con$$constant);
%}
ins_pipe(pipe_slow);
%}
-instruct vor_immL(vReg dst_src, immL5 con) %{
+instruct vorL_vi(vReg dst, vReg src1, immL5 con) %{
predicate(Matcher::vector_element_basic_type(n) == T_LONG);
- match(Set dst_src (OrV dst_src (Replicate con)));
- format %{ "vor_immL $dst_src, $dst_src, $con" %}
+ match(Set dst (OrV src1 (Replicate con)));
+ format %{ "vorL_vi $dst, $src1, $con" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
- __ vor_vi(as_VectorRegister($dst_src$$reg),
- as_VectorRegister($dst_src$$reg),
+ __ vor_vi(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
$con$$constant);
%}
ins_pipe(pipe_slow);
@@ -872,43 +872,43 @@ instruct vor_immL(vReg dst_src, immL5 con) %{
// vector-scalar or (unpredicated)
-instruct vor_regI(vReg dst_src, iRegIorL2I src) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
- match(Set dst_src (OrV dst_src (Replicate src)));
- format %{ "vor_regI $dst_src, $dst_src, $src" %}
+instruct vor_vx(vReg dst, vReg src1, iRegIorL2I src2) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
+ match(Set dst (OrV src1 (Replicate src2)));
+ format %{ "vor_vx $dst, $src1, $src2" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
- __ vor_vx(as_VectorRegister($dst_src$$reg),
- as_VectorRegister($dst_src$$reg),
- as_Register($src$$reg));
+ __ vor_vx(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
+ as_Register($src2$$reg));
%}
ins_pipe(pipe_slow);
%}
-instruct vor_regL(vReg dst_src, iRegL src) %{
+instruct vorL_vx(vReg dst, vReg src1, iRegL src2) %{
predicate(Matcher::vector_element_basic_type(n) == T_LONG);
- match(Set dst_src (OrV dst_src (Replicate src)));
- format %{ "vor_regL $dst_src, $dst_src, $src" %}
+ match(Set dst (OrV src1 (Replicate src2)));
+ format %{ "vorL_vx $dst, $src1, $src2" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
- __ vor_vx(as_VectorRegister($dst_src$$reg),
- as_VectorRegister($dst_src$$reg),
- as_Register($src$$reg));
+ __ vor_vx(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
+ as_Register($src2$$reg));
%}
ins_pipe(pipe_slow);
%}
// vector-immediate or (predicated)
-instruct vor_immI_masked(vReg dst_src, immI5 con, vRegMask_V0 v0) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
+instruct vor_vi_masked(vReg dst_src, immI5 con, vRegMask_V0 v0) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
match(Set dst_src (OrV (Binary dst_src (Replicate con)) v0));
- format %{ "vor_immI_masked $dst_src, $dst_src, $con" %}
+ format %{ "vor_vi_masked $dst_src, $dst_src, $con, $v0" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -919,10 +919,10 @@ instruct vor_immI_masked(vReg dst_src, immI5 con, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vor_immL_masked(vReg dst_src, immL5 con, vRegMask_V0 v0) %{
+instruct vorL_vi_masked(vReg dst_src, immL5 con, vRegMask_V0 v0) %{
predicate(Matcher::vector_element_basic_type(n) == T_LONG);
match(Set dst_src (OrV (Binary dst_src (Replicate con)) v0));
- format %{ "vor_immL_masked $dst_src, $dst_src, $con" %}
+ format %{ "vorL_vi_masked $dst_src, $dst_src, $con, $v0" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vor_vi(as_VectorRegister($dst_src$$reg),
@@ -934,12 +934,12 @@ instruct vor_immL_masked(vReg dst_src, immL5 con, vRegMask_V0 v0) %{
// vector-scalar or (predicated)
-instruct vor_regI_masked(vReg dst_src, iRegIorL2I src, vRegMask_V0 v0) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
+instruct vor_vx_masked(vReg dst_src, iRegIorL2I src, vRegMask_V0 v0) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
match(Set dst_src (OrV (Binary dst_src (Replicate src)) v0));
- format %{ "vor_regI_masked $dst_src, $dst_src, $src" %}
+ format %{ "vor_vx_masked $dst_src, $dst_src, $src, $v0" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -950,10 +950,10 @@ instruct vor_regI_masked(vReg dst_src, iRegIorL2I src, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vor_regL_masked(vReg dst_src, iRegL src, vRegMask_V0 v0) %{
+instruct vorL_vx_masked(vReg dst_src, iRegL src, vRegMask_V0 v0) %{
predicate(Matcher::vector_element_basic_type(n) == T_LONG);
match(Set dst_src (OrV (Binary dst_src (Replicate src)) v0));
- format %{ "vor_regL_masked $dst_src, $dst_src, $src" %}
+ format %{ "vorL_vx_masked $dst_src, $dst_src, $src, $v0" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vor_vx(as_VectorRegister($dst_src$$reg),
@@ -997,30 +997,30 @@ instruct vxor_masked(vReg dst_src1, vReg src2, vRegMask_V0 v0) %{
// vector-immediate xor (unpredicated)
-instruct vxor_immI(vReg dst_src, immI5 con) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
- match(Set dst_src (XorV dst_src (Replicate con)));
- format %{ "vxor_immI $dst_src, $dst_src, $con" %}
+instruct vxor_vi(vReg dst, vReg src1, immI5 con) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
+ match(Set dst (XorV src1 (Replicate con)));
+ format %{ "vxor_vi $dst, $src1, $con" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
- __ vxor_vi(as_VectorRegister($dst_src$$reg),
- as_VectorRegister($dst_src$$reg),
+ __ vxor_vi(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
$con$$constant);
%}
ins_pipe(pipe_slow);
%}
-instruct vxor_immL(vReg dst_src, immL5 con) %{
+instruct vxorL_vi(vReg dst, vReg src1, immL5 con) %{
predicate(Matcher::vector_element_basic_type(n) == T_LONG);
- match(Set dst_src (XorV dst_src (Replicate con)));
- format %{ "vxor_immL $dst_src, $dst_src, $con" %}
+ match(Set dst (XorV src1 (Replicate con)));
+ format %{ "vxorL_vi $dst, $src1, $con" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
- __ vxor_vi(as_VectorRegister($dst_src$$reg),
- as_VectorRegister($dst_src$$reg),
+ __ vxor_vi(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
$con$$constant);
%}
ins_pipe(pipe_slow);
@@ -1028,43 +1028,43 @@ instruct vxor_immL(vReg dst_src, immL5 con) %{
// vector-scalar xor (unpredicated)
-instruct vxor_regI(vReg dst_src, iRegIorL2I src) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
- match(Set dst_src (XorV dst_src (Replicate src)));
- format %{ "vxor_regI $dst_src, $dst_src, $src" %}
+instruct vxor_vx(vReg dst, vReg src1, iRegIorL2I src2) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
+ match(Set dst (XorV src1 (Replicate src2)));
+ format %{ "vxor_vx $dst, $src1, $src2" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
- __ vxor_vx(as_VectorRegister($dst_src$$reg),
- as_VectorRegister($dst_src$$reg),
- as_Register($src$$reg));
+ __ vxor_vx(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
+ as_Register($src2$$reg));
%}
ins_pipe(pipe_slow);
%}
-instruct vxor_regL(vReg dst_src, iRegL src) %{
+instruct vxorL_vx(vReg dst, vReg src1, iRegL src2) %{
predicate(Matcher::vector_element_basic_type(n) == T_LONG);
- match(Set dst_src (XorV dst_src (Replicate src)));
- format %{ "vxor_regL $dst_src, $dst_src, $src" %}
+ match(Set dst (XorV src1 (Replicate src2)));
+ format %{ "vxorL_vx $dst, $src1, $src2" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
- __ vxor_vx(as_VectorRegister($dst_src$$reg),
- as_VectorRegister($dst_src$$reg),
- as_Register($src$$reg));
+ __ vxor_vx(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
+ as_Register($src2$$reg));
%}
ins_pipe(pipe_slow);
%}
// vector-immediate xor (predicated)
-instruct vxor_immI_masked(vReg dst_src, immI5 con, vRegMask_V0 v0) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
+instruct vxor_vi_masked(vReg dst_src, immI5 con, vRegMask_V0 v0) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
match(Set dst_src (XorV (Binary dst_src (Replicate con)) v0));
- format %{ "vxor_immI_masked $dst_src, $dst_src, $con" %}
+ format %{ "vxor_vi_masked $dst_src, $dst_src, $con, $v0" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -1075,10 +1075,10 @@ instruct vxor_immI_masked(vReg dst_src, immI5 con, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vxor_immL_masked(vReg dst_src, immL5 con, vRegMask_V0 v0) %{
+instruct vxorL_vi_masked(vReg dst_src, immL5 con, vRegMask_V0 v0) %{
predicate(Matcher::vector_element_basic_type(n) == T_LONG);
match(Set dst_src (XorV (Binary dst_src (Replicate con)) v0));
- format %{ "vxor_immL_masked $dst_src, $dst_src, $con" %}
+ format %{ "vxorL_vi_masked $dst_src, $dst_src, $con, $v0" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vxor_vi(as_VectorRegister($dst_src$$reg),
@@ -1090,12 +1090,12 @@ instruct vxor_immL_masked(vReg dst_src, immL5 con, vRegMask_V0 v0) %{
// vector-scalar xor (predicated)
-instruct vxor_regI_masked(vReg dst_src, iRegIorL2I src, vRegMask_V0 v0) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
+instruct vxor_vx_masked(vReg dst_src, iRegIorL2I src, vRegMask_V0 v0) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
match(Set dst_src (XorV (Binary dst_src (Replicate src)) v0));
- format %{ "vxor_regI_masked $dst_src, $dst_src, $src" %}
+ format %{ "vxor_vx_masked $dst_src, $dst_src, $src, $v0" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -1106,10 +1106,10 @@ instruct vxor_regI_masked(vReg dst_src, iRegIorL2I src, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vxor_regL_masked(vReg dst_src, iRegL src, vRegMask_V0 v0) %{
+instruct vxorL_vx_masked(vReg dst_src, iRegL src, vRegMask_V0 v0) %{
predicate(Matcher::vector_element_basic_type(n) == T_LONG);
match(Set dst_src (XorV (Binary dst_src (Replicate src)) v0));
- format %{ "vxor_regL_masked $dst_src, $dst_src, $src" %}
+ format %{ "vxorL_vx_masked $dst_src, $dst_src, $src, $v0" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vxor_vx(as_VectorRegister($dst_src$$reg),
@@ -1123,16 +1123,38 @@ instruct vxor_regL_masked(vReg dst_src, iRegL src, vRegMask_V0 v0) %{
// vector and not
+instruct vand_notB(vReg dst, vReg src1, vReg src2, immI_M1 m1) %{
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_BYTE);
+ match(Set dst (AndV src1 (XorV src2 (Replicate m1))));
+ format %{ "vand_notB $dst, $src1, $src2" %}
+ ins_encode %{
+ __ vsetvli_helper(T_BYTE, Matcher::vector_length(this));
+ __ vandn_vv(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
+ as_VectorRegister($src2$$reg));
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct vand_notS(vReg dst, vReg src1, vReg src2, immI_M1 m1) %{
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_SHORT);
+ match(Set dst (AndV src1 (XorV src2 (Replicate m1))));
+ format %{ "vand_notS $dst, $src1, $src2" %}
+ ins_encode %{
+ __ vsetvli_helper(T_SHORT, Matcher::vector_length(this));
+ __ vandn_vv(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
+ as_VectorRegister($src2$$reg));
+ %}
+ ins_pipe(pipe_slow);
+%}
+
instruct vand_notI(vReg dst, vReg src1, vReg src2, immI_M1 m1) %{
- predicate(UseZvbb);
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_INT);
match(Set dst (AndV src1 (XorV src2 (Replicate m1))));
format %{ "vand_notI $dst, $src1, $src2" %}
ins_encode %{
- BasicType bt = Matcher::vector_element_basic_type(this);
- __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vsetvli_helper(T_INT, Matcher::vector_length(this));
__ vandn_vv(as_VectorRegister($dst$$reg),
as_VectorRegister($src1$$reg),
as_VectorRegister($src2$$reg));
@@ -1141,8 +1163,7 @@ instruct vand_notI(vReg dst, vReg src1, vReg src2, immI_M1 m1) %{
%}
instruct vand_notL(vReg dst, vReg src1, vReg src2, immL_M1 m1) %{
- predicate(UseZvbb);
- predicate(Matcher::vector_element_basic_type(n) == T_LONG);
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_LONG);
match(Set dst (AndV src1 (XorV src2 (Replicate m1))));
format %{ "vand_notL $dst, $src1, $src2" %}
ins_encode %{
@@ -1154,16 +1175,40 @@ instruct vand_notL(vReg dst, vReg src1, vReg src2, immL_M1 m1) %{
ins_pipe(pipe_slow);
%}
+instruct vand_notB_masked(vReg dst_src1, vReg src2, immI_M1 m1, vRegMask_V0 v0) %{
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_BYTE);
+ match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (Replicate m1))) v0));
+ format %{ "vand_notB_masked $dst_src1, $dst_src1, $src2, $v0" %}
+ ins_encode %{
+ __ vsetvli_helper(T_BYTE, Matcher::vector_length(this));
+ __ vandn_vv(as_VectorRegister($dst_src1$$reg),
+ as_VectorRegister($dst_src1$$reg),
+ as_VectorRegister($src2$$reg),
+ Assembler::v0_t);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct vand_notS_masked(vReg dst_src1, vReg src2, immI_M1 m1, vRegMask_V0 v0) %{
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_SHORT);
+ match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (Replicate m1))) v0));
+ format %{ "vand_notS_masked $dst_src1, $dst_src1, $src2, $v0" %}
+ ins_encode %{
+ __ vsetvli_helper(T_SHORT, Matcher::vector_length(this));
+ __ vandn_vv(as_VectorRegister($dst_src1$$reg),
+ as_VectorRegister($dst_src1$$reg),
+ as_VectorRegister($src2$$reg),
+ Assembler::v0_t);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
instruct vand_notI_masked(vReg dst_src1, vReg src2, immI_M1 m1, vRegMask_V0 v0) %{
- predicate(UseZvbb);
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_INT);
match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (Replicate m1))) v0));
format %{ "vand_notI_masked $dst_src1, $dst_src1, $src2, $v0" %}
ins_encode %{
- BasicType bt = Matcher::vector_element_basic_type(this);
- __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vsetvli_helper(T_INT, Matcher::vector_length(this));
__ vandn_vv(as_VectorRegister($dst_src1$$reg),
as_VectorRegister($dst_src1$$reg),
as_VectorRegister($src2$$reg),
@@ -1173,8 +1218,7 @@ instruct vand_notI_masked(vReg dst_src1, vReg src2, immI_M1 m1, vRegMask_V0 v0)
%}
instruct vand_notL_masked(vReg dst_src1, vReg src2, immL_M1 m1, vRegMask_V0 v0) %{
- predicate(UseZvbb);
- predicate(Matcher::vector_element_basic_type(n) == T_LONG);
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_LONG);
match(Set dst_src1 (AndV (Binary dst_src1 (XorV src2 (Replicate m1))) v0));
format %{ "vand_notL_masked $dst_src1, $dst_src1, $src2, $v0" %}
ins_encode %{
@@ -1187,16 +1231,124 @@ instruct vand_notL_masked(vReg dst_src1, vReg src2, immL_M1 m1, vRegMask_V0 v0)
ins_pipe(pipe_slow);
%}
+instruct vand_notB_vx(vReg dst, vReg src1, iRegIorL2I src2, immI_M1 m1) %{
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_BYTE);
+ match(Set dst (AndV src1 (Replicate (XorI src2 m1))));
+ format %{ "vand_notB_vx $dst, $src1, $src2" %}
+ ins_encode %{
+ __ vsetvli_helper(T_BYTE, Matcher::vector_length(this));
+ __ vandn_vx(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
+ as_Register($src2$$reg));
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct vand_notS_vx(vReg dst, vReg src1, iRegIorL2I src2, immI_M1 m1) %{
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_SHORT);
+ match(Set dst (AndV src1 (Replicate (XorI src2 m1))));
+ format %{ "vand_notS_vx $dst, $src1, $src2" %}
+ ins_encode %{
+ __ vsetvli_helper(T_SHORT, Matcher::vector_length(this));
+ __ vandn_vx(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
+ as_Register($src2$$reg));
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct vand_notI_vx(vReg dst, vReg src1, iRegIorL2I src2, immI_M1 m1) %{
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_INT);
+ match(Set dst (AndV src1 (Replicate (XorI src2 m1))));
+ format %{ "vand_notI_vx $dst, $src1, $src2" %}
+ ins_encode %{
+ __ vsetvli_helper(T_INT, Matcher::vector_length(this));
+ __ vandn_vx(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
+ as_Register($src2$$reg));
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct vand_notL_vx(vReg dst, vReg src1, iRegL src2, immL_M1 m1) %{
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_LONG);
+ match(Set dst (AndV src1 (Replicate (XorL src2 m1))));
+ format %{ "vand_notL_vx $dst, $src1, $src2" %}
+ ins_encode %{
+ __ vsetvli_helper(T_LONG, Matcher::vector_length(this));
+ __ vandn_vx(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg),
+ as_Register($src2$$reg));
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct vand_notB_vx_masked(vReg dst_src1, iRegIorL2I src2, immI_M1 m1, vRegMask_V0 v0) %{
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_BYTE);
+ match(Set dst_src1 (AndV (Binary dst_src1 (Replicate (XorI src2 m1))) v0));
+ format %{ "vand_notB_vx_masked $dst_src1, $dst_src1, $src2, $v0" %}
+ ins_encode %{
+ __ vsetvli_helper(T_BYTE, Matcher::vector_length(this));
+ __ vandn_vx(as_VectorRegister($dst_src1$$reg),
+ as_VectorRegister($dst_src1$$reg),
+ as_Register($src2$$reg),
+ Assembler::v0_t);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct vand_notS_vx_masked(vReg dst_src1, iRegIorL2I src2, immI_M1 m1, vRegMask_V0 v0) %{
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_SHORT);
+ match(Set dst_src1 (AndV (Binary dst_src1 (Replicate (XorI src2 m1))) v0));
+ format %{ "vand_notS_vx_masked $dst_src1, $dst_src1, $src2, $v0" %}
+ ins_encode %{
+ __ vsetvli_helper(T_SHORT, Matcher::vector_length(this));
+ __ vandn_vx(as_VectorRegister($dst_src1$$reg),
+ as_VectorRegister($dst_src1$$reg),
+ as_Register($src2$$reg),
+ Assembler::v0_t);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct vand_notI_vx_masked(vReg dst_src1, iRegIorL2I src2, immI_M1 m1, vRegMask_V0 v0) %{
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_INT);
+ match(Set dst_src1 (AndV (Binary dst_src1 (Replicate (XorI src2 m1))) v0));
+ format %{ "vand_notI_vx_masked $dst_src1, $dst_src1, $src2, $v0" %}
+ ins_encode %{
+ __ vsetvli_helper(T_INT, Matcher::vector_length(this));
+ __ vandn_vx(as_VectorRegister($dst_src1$$reg),
+ as_VectorRegister($dst_src1$$reg),
+ as_Register($src2$$reg),
+ Assembler::v0_t);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct vand_notL_vx_masked(vReg dst_src1, iRegL src2, immL_M1 m1, vRegMask_V0 v0) %{
+ predicate(UseZvbb && Matcher::vector_element_basic_type(n) == T_LONG);
+ match(Set dst_src1 (AndV (Binary dst_src1 (Replicate (XorL src2 m1))) v0));
+ format %{ "vand_notL_vx_masked $dst_src1, $dst_src1, $src2, $v0" %}
+ ins_encode %{
+ __ vsetvli_helper(T_LONG, Matcher::vector_length(this));
+ __ vandn_vx(as_VectorRegister($dst_src1$$reg),
+ as_VectorRegister($dst_src1$$reg),
+ as_Register($src2$$reg),
+ Assembler::v0_t);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
// ------------------------------ Vector not -----------------------------------
// vector not
-instruct vnotI(vReg dst, vReg src, immI_M1 m1) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
+instruct vnot(vReg dst, vReg src, immI_M1 m1) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
match(Set dst (XorV src (Replicate m1)));
- format %{ "vnotI $dst, $src" %}
+ format %{ "vnot $dst, $src" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -1222,12 +1374,12 @@ instruct vnotL(vReg dst, vReg src, immL_M1 m1) %{
// vector not - predicated
-instruct vnotI_masked(vReg dst_src, immI_M1 m1, vRegMask_V0 v0) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
+instruct vnot_masked(vReg dst_src, immI_M1 m1, vRegMask_V0 v0) %{
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
match(Set dst_src (XorV (Binary dst_src (Replicate m1)) v0));
- format %{ "vnotI_masked $dst_src, $dst_src, $v0" %}
+ format %{ "vnot_masked $dst_src, $dst_src, $v0" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -1349,6 +1501,66 @@ instruct vmin_masked(vReg dst_src1, vReg src2, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
+// vector unsigned integer max/min
+
+instruct vmaxu(vReg dst, vReg src1, vReg src2) %{
+ match(Set dst (UMaxV src1 src2));
+ ins_cost(VEC_COST);
+ format %{ "vmaxu $dst, $src1, $src2" %}
+ ins_encode %{
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ assert(is_integral_type(bt), "unsupported type");
+ __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vmaxu_vv(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg));
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct vminu(vReg dst, vReg src1, vReg src2) %{
+ match(Set dst (UMinV src1 src2));
+ ins_cost(VEC_COST);
+ format %{ "vminu $dst, $src1, $src2" %}
+ ins_encode %{
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ assert(is_integral_type(bt), "unsupported type");
+ __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vminu_vv(as_VectorRegister($dst$$reg),
+ as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg));
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+// vector unsigned integer max/min - predicated
+
+instruct vmaxu_masked(vReg dst_src1, vReg src2, vRegMask_V0 v0) %{
+ match(Set dst_src1 (UMaxV (Binary dst_src1 src2) v0));
+ ins_cost(VEC_COST);
+ format %{ "vmaxu_masked $dst_src1, $dst_src1, $src2, $v0" %}
+ ins_encode %{
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ assert(is_integral_type(bt), "unsupported type");
+ __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vmaxu_vv(as_VectorRegister($dst_src1$$reg), as_VectorRegister($dst_src1$$reg),
+ as_VectorRegister($src2$$reg), Assembler::v0_t);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct vminu_masked(vReg dst_src1, vReg src2, vRegMask_V0 v0) %{
+ match(Set dst_src1 (UMinV (Binary dst_src1 src2) v0));
+ ins_cost(VEC_COST);
+ format %{ "vminu_masked $dst_src1, $dst_src1, $src2, $v0" %}
+ ins_encode %{
+ BasicType bt = Matcher::vector_element_basic_type(this);
+ assert(is_integral_type(bt), "unsupported type");
+ __ vsetvli_helper(bt, Matcher::vector_length(this));
+ __ vminu_vv(as_VectorRegister($dst_src1$$reg), as_VectorRegister($dst_src1$$reg),
+ as_VectorRegister($src2$$reg), Assembler::v0_t);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
// vector float-point max/min
instruct vmax_fp(vReg dst, vReg src1, vReg src2, vRegMask_V0 v0) %{
@@ -1737,11 +1949,11 @@ instruct vmul_fp_masked(vReg dst_src1, vReg src2, vRegMask_V0 v0) %{
// vector-scalar mul (unpredicated)
-instruct vmul_regI(vReg dst, vReg src1, iRegIorL2I src2) %{
+instruct vmul_vx(vReg dst, vReg src1, iRegIorL2I src2) %{
match(Set dst (MulVB src1 (Replicate src2)));
match(Set dst (MulVS src1 (Replicate src2)));
match(Set dst (MulVI src1 (Replicate src2)));
- format %{ "vmul_regI $dst, $src1, $src2" %}
+ format %{ "vmul_vx $dst, $src1, $src2" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -1752,9 +1964,9 @@ instruct vmul_regI(vReg dst, vReg src1, iRegIorL2I src2) %{
ins_pipe(pipe_slow);
%}
-instruct vmul_regL(vReg dst, vReg src1, iRegL src2) %{
+instruct vmulL_vx(vReg dst, vReg src1, iRegL src2) %{
match(Set dst (MulVL src1 (Replicate src2)));
- format %{ "vmul_regL $dst, $src1, $src2" %}
+ format %{ "vmulL_vx $dst, $src1, $src2" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vmul_vx(as_VectorRegister($dst$$reg),
@@ -1766,11 +1978,11 @@ instruct vmul_regL(vReg dst, vReg src1, iRegL src2) %{
// vector-scalar mul (predicated)
-instruct vmul_regI_masked(vReg dst_src, iRegIorL2I src2, vRegMask_V0 v0) %{
+instruct vmul_vx_masked(vReg dst_src, iRegIorL2I src2, vRegMask_V0 v0) %{
match(Set dst_src (MulVB (Binary dst_src (Replicate src2)) v0));
match(Set dst_src (MulVS (Binary dst_src (Replicate src2)) v0));
match(Set dst_src (MulVI (Binary dst_src (Replicate src2)) v0));
- format %{ "vmul_regI_masked $dst_src, $dst_src, $src2" %}
+ format %{ "vmul_vx_masked $dst_src, $dst_src, $src2, $v0" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -1781,9 +1993,9 @@ instruct vmul_regI_masked(vReg dst_src, iRegIorL2I src2, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vmul_regL_masked(vReg dst_src, iRegL src2, vRegMask_V0 v0) %{
+instruct vmulL_vx_masked(vReg dst_src, iRegL src2, vRegMask_V0 v0) %{
match(Set dst_src (MulVL (Binary dst_src (Replicate src2)) v0));
- format %{ "vmul_regL_masked $dst_src, $dst_src, $src2" %}
+ format %{ "vmulL_vx_masked $dst_src, $dst_src, $src2, $v0" %}
ins_encode %{
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
__ vmul_vx(as_VectorRegister($dst_src$$reg),
@@ -1857,14 +2069,14 @@ instruct vfneg_masked(vReg dst_src, vRegMask_V0 v0) %{
// vector and reduction
-instruct reduce_andI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
+instruct reduce_and(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (AndReductionV src1 src2));
effect(TEMP tmp);
ins_cost(VEC_COST);
- format %{ "reduce_andI $dst, $src1, $src2\t# KILL $tmp" %}
+ format %{ "reduce_and $dst, $src1, $src2\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_integral_v($dst$$Register, $src1$$Register,
@@ -1891,14 +2103,14 @@ instruct reduce_andL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
// vector and reduction - predicated
-instruct reduce_andI_masked(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegMask_V0 v0, vReg tmp) %{
+instruct reduce_and_masked(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegMask_V0 v0, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (AndReductionV (Binary src1 src2) v0));
effect(TEMP tmp);
ins_cost(VEC_COST);
- format %{ "reduce_andI_masked $dst, $src1, $src2, $v0\t# KILL $tmp" %}
+ format %{ "reduce_and_masked $dst, $src1, $src2, $v0\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_integral_v($dst$$Register, $src1$$Register,
@@ -1927,14 +2139,14 @@ instruct reduce_andL_masked(iRegLNoSp dst, iRegL src1, vReg src2, vRegMask_V0 v0
// vector or reduction
-instruct reduce_orI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
+instruct reduce_or(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (OrReductionV src1 src2));
effect(TEMP tmp);
ins_cost(VEC_COST);
- format %{ "reduce_orI $dst, $src1, $src2\t# KILL $tmp" %}
+ format %{ "reduce_or $dst, $src1, $src2\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_integral_v($dst$$Register, $src1$$Register,
@@ -1961,14 +2173,14 @@ instruct reduce_orL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
// vector or reduction - predicated
-instruct reduce_orI_masked(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegMask_V0 v0, vReg tmp) %{
+instruct reduce_or_masked(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegMask_V0 v0, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (OrReductionV (Binary src1 src2) v0));
effect(TEMP tmp);
ins_cost(VEC_COST);
- format %{ "reduce_orI_masked $dst, $src1, $src2, $v0\t# KILL $tmp" %}
+ format %{ "reduce_or_masked $dst, $src1, $src2, $v0\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_integral_v($dst$$Register, $src1$$Register,
@@ -1997,14 +2209,14 @@ instruct reduce_orL_masked(iRegLNoSp dst, iRegL src1, vReg src2, vRegMask_V0 v0,
// vector xor reduction
-instruct reduce_xorI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
+instruct reduce_xor(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (XorReductionV src1 src2));
effect(TEMP tmp);
ins_cost(VEC_COST);
- format %{ "reduce_xorI $dst, $src1, $src2\t# KILL $tmp" %}
+ format %{ "reduce_xor $dst, $src1, $src2\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_integral_v($dst$$Register, $src1$$Register,
@@ -2031,14 +2243,14 @@ instruct reduce_xorL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
// vector xor reduction - predicated
-instruct reduce_xorI_masked(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegMask_V0 v0, vReg tmp) %{
+instruct reduce_xor_masked(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegMask_V0 v0, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (XorReductionV (Binary src1 src2) v0));
effect(TEMP tmp);
ins_cost(VEC_COST);
- format %{ "reduce_xorI_masked $dst, $src1, $src2, $v0\t# KILL $tmp" %}
+ format %{ "reduce_xor_masked $dst, $src1, $src2, $v0\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_integral_v($dst$$Register, $src1$$Register,
@@ -2067,14 +2279,14 @@ instruct reduce_xorL_masked(iRegLNoSp dst, iRegL src1, vReg src2, vRegMask_V0 v0
// vector add reduction
-instruct reduce_addI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
+instruct reduce_add(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (AddReductionVI src1 src2));
effect(TEMP tmp);
ins_cost(VEC_COST);
- format %{ "reduce_addI $dst, $src1, $src2\t# KILL $tmp" %}
+ format %{ "reduce_add $dst, $src1, $src2\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_integral_v($dst$$Register, $src1$$Register,
@@ -2173,14 +2385,14 @@ instruct reduce_addD_unordered(fRegD dst, fRegD src1, vReg src2, vReg tmp) %{
// vector add reduction - predicated
-instruct reduce_addI_masked(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegMask_V0 v0, vReg tmp) %{
+instruct reduce_add_masked(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegMask_V0 v0, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (AddReductionVI (Binary src1 src2) v0));
effect(TEMP tmp);
ins_cost(VEC_COST);
- format %{ "reduce_addI_masked $dst, $src1, $src2, $v0\t# KILL $tmp" %}
+ format %{ "reduce_add_masked $dst, $src1, $src2, $v0\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_integral_v($dst$$Register, $src1$$Register,
@@ -2239,14 +2451,14 @@ instruct reduce_addD_masked(fRegD dst, fRegD src1, vReg src2, vRegMask_V0 v0, vR
// vector integer max reduction
-instruct vreduce_maxI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
+instruct vreduce_max(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (MaxReductionV src1 src2));
ins_cost(VEC_COST);
effect(TEMP tmp);
- format %{ "vreduce_maxI $dst, $src1, $src2\t# KILL $tmp" %}
+ format %{ "vreduce_max $dst, $src1, $src2\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_integral_v($dst$$Register, $src1$$Register,
@@ -2273,14 +2485,14 @@ instruct vreduce_maxL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
// vector integer max reduction - predicated
-instruct vreduce_maxI_masked(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegMask_V0 v0, vReg tmp) %{
+instruct vreduce_max_masked(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegMask_V0 v0, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (MaxReductionV (Binary src1 src2) v0));
effect(TEMP tmp);
ins_cost(VEC_COST);
- format %{ "vreduce_maxI_masked $dst, $src1, $src2, $v0\t# KILL $tmp" %}
+ format %{ "vreduce_max_masked $dst, $src1, $src2, $v0\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_integral_v($dst$$Register, $src1$$Register,
@@ -2309,14 +2521,14 @@ instruct vreduce_maxL_masked(iRegLNoSp dst, iRegL src1, vReg src2, vRegMask_V0 v
// vector integer min reduction
-instruct vreduce_minI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
+instruct vreduce_min(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (MinReductionV src1 src2));
ins_cost(VEC_COST);
effect(TEMP tmp);
- format %{ "vreduce_minI $dst, $src1, $src2\t# KILL $tmp" %}
+ format %{ "vreduce_min $dst, $src1, $src2\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_integral_v($dst$$Register, $src1$$Register,
@@ -2343,14 +2555,14 @@ instruct vreduce_minL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{
// vector integer min reduction - predicated
-instruct vreduce_minI_masked(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegMask_V0 v0, vReg tmp) %{
+instruct vreduce_min_masked(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegMask_V0 v0, vReg tmp) %{
predicate(Matcher::vector_element_basic_type(n->in(2)) == T_BYTE ||
Matcher::vector_element_basic_type(n->in(2)) == T_SHORT ||
Matcher::vector_element_basic_type(n->in(2)) == T_INT);
match(Set dst (MinReductionV (Binary src1 src2) v0));
effect(TEMP tmp);
ins_cost(VEC_COST);
- format %{ "vreduce_minI_masked $dst, $src1, $src2, $v0\t# KILL $tmp" %}
+ format %{ "vreduce_min_masked $dst, $src1, $src2, $v0\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this, $src2);
__ reduce_integral_v($dst$$Register, $src1$$Register,
@@ -3058,10 +3270,10 @@ instruct vlsrL_masked(vReg dst_src, vReg shift, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vasrB_imm(vReg dst, vReg src, immI shift) %{
+instruct vasrB_vi(vReg dst, vReg src, immI shift) %{
match(Set dst (RShiftVB src (RShiftCntV shift)));
ins_cost(VEC_COST);
- format %{ "vasrB_imm $dst, $src, $shift" %}
+ format %{ "vasrB_vi $dst, $src, $shift" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_BYTE, Matcher::vector_length(this));
@@ -3076,10 +3288,10 @@ instruct vasrB_imm(vReg dst, vReg src, immI shift) %{
ins_pipe(pipe_slow);
%}
-instruct vasrS_imm(vReg dst, vReg src, immI shift) %{
+instruct vasrS_vi(vReg dst, vReg src, immI shift) %{
match(Set dst (RShiftVS src (RShiftCntV shift)));
ins_cost(VEC_COST);
- format %{ "vasrS_imm $dst, $src, $shift" %}
+ format %{ "vasrS_vi $dst, $src, $shift" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_SHORT, Matcher::vector_length(this));
@@ -3094,10 +3306,10 @@ instruct vasrS_imm(vReg dst, vReg src, immI shift) %{
ins_pipe(pipe_slow);
%}
-instruct vasrI_imm(vReg dst, vReg src, immI shift) %{
+instruct vasrI_vi(vReg dst, vReg src, immI shift) %{
match(Set dst (RShiftVI src (RShiftCntV shift)));
ins_cost(VEC_COST);
- format %{ "vasrI_imm $dst, $src, $shift" %}
+ format %{ "vasrI_vi $dst, $src, $shift" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_INT, Matcher::vector_length(this));
@@ -3111,11 +3323,11 @@ instruct vasrI_imm(vReg dst, vReg src, immI shift) %{
ins_pipe(pipe_slow);
%}
-instruct vasrL_imm(vReg dst, vReg src, immI shift) %{
+instruct vasrL_vi(vReg dst, vReg src, immI shift) %{
predicate((n->in(2)->in(1)->get_int() & 0x3f) < 32);
match(Set dst (RShiftVL src (RShiftCntV shift)));
ins_cost(VEC_COST);
- format %{ "vasrL_imm $dst, $src, $shift" %}
+ format %{ "vasrL_vi $dst, $src, $shift" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
@@ -3129,10 +3341,10 @@ instruct vasrL_imm(vReg dst, vReg src, immI shift) %{
ins_pipe(pipe_slow);
%}
-instruct vasrB_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vasrB_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
match(Set dst_src (RShiftVB (Binary dst_src (RShiftCntV shift)) v0));
ins_cost(VEC_COST);
- format %{ "vasrB_imm_masked $dst_src, $dst_src, $shift, $v0" %}
+ format %{ "vasrB_vi_masked $dst_src, $dst_src, $shift, $v0" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
if (con == 0) {
@@ -3146,10 +3358,10 @@ instruct vasrB_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vasrS_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vasrS_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
match(Set dst_src (RShiftVS (Binary dst_src (RShiftCntV shift)) v0));
ins_cost(VEC_COST);
- format %{ "vasrS_imm_masked $dst_src, $dst_src, $shift, $v0" %}
+ format %{ "vasrS_vi_masked $dst_src, $dst_src, $shift, $v0" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
if (con == 0) {
@@ -3163,10 +3375,10 @@ instruct vasrS_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vasrI_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vasrI_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
match(Set dst_src (RShiftVI (Binary dst_src (RShiftCntV shift)) v0));
ins_cost(VEC_COST);
- format %{ "vasrI_imm_masked $dst_src, $dst_src, $shift, $v0" %}
+ format %{ "vasrI_vi_masked $dst_src, $dst_src, $shift, $v0" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
if (con == 0) {
@@ -3179,11 +3391,11 @@ instruct vasrI_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vasrL_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vasrL_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
predicate((n->in(1)->in(2)->in(1)->get_int() & 0x3f) < 32);
match(Set dst_src (RShiftVL (Binary dst_src (RShiftCntV shift)) v0));
ins_cost(VEC_COST);
- format %{ "vasrL_imm_masked $dst_src, $dst_src, $shift, $v0" %}
+ format %{ "vasrL_vi_masked $dst_src, $dst_src, $shift, $v0" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
if (con == 0) {
@@ -3196,10 +3408,10 @@ instruct vasrL_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vlsrB_imm(vReg dst, vReg src, immI shift) %{
+instruct vlsrB_vi(vReg dst, vReg src, immI shift) %{
match(Set dst (URShiftVB src (RShiftCntV shift)));
ins_cost(VEC_COST);
- format %{ "vlsrB_imm $dst, $src, $shift" %}
+ format %{ "vlsrB_vi $dst, $src, $shift" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_BYTE, Matcher::vector_length(this));
@@ -3218,10 +3430,10 @@ instruct vlsrB_imm(vReg dst, vReg src, immI shift) %{
ins_pipe(pipe_slow);
%}
-instruct vlsrS_imm(vReg dst, vReg src, immI shift) %{
+instruct vlsrS_vi(vReg dst, vReg src, immI shift) %{
match(Set dst (URShiftVS src (RShiftCntV shift)));
ins_cost(VEC_COST);
- format %{ "vlsrS_imm $dst, $src, $shift" %}
+ format %{ "vlsrS_vi $dst, $src, $shift" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_SHORT, Matcher::vector_length(this));
@@ -3240,10 +3452,10 @@ instruct vlsrS_imm(vReg dst, vReg src, immI shift) %{
ins_pipe(pipe_slow);
%}
-instruct vlsrI_imm(vReg dst, vReg src, immI shift) %{
+instruct vlsrI_vi(vReg dst, vReg src, immI shift) %{
match(Set dst (URShiftVI src (RShiftCntV shift)));
ins_cost(VEC_COST);
- format %{ "vlsrI_imm $dst, $src, $shift" %}
+ format %{ "vlsrI_vi $dst, $src, $shift" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_INT, Matcher::vector_length(this));
@@ -3257,11 +3469,11 @@ instruct vlsrI_imm(vReg dst, vReg src, immI shift) %{
ins_pipe(pipe_slow);
%}
-instruct vlsrL_imm(vReg dst, vReg src, immI shift) %{
+instruct vlsrL_vi(vReg dst, vReg src, immI shift) %{
predicate((n->in(2)->in(1)->get_int() & 0x3f) < 32);
match(Set dst (URShiftVL src (RShiftCntV shift)));
ins_cost(VEC_COST);
- format %{ "vlsrL_imm $dst, $src, $shift" %}
+ format %{ "vlsrL_vi $dst, $src, $shift" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
@@ -3275,10 +3487,10 @@ instruct vlsrL_imm(vReg dst, vReg src, immI shift) %{
ins_pipe(pipe_slow);
%}
-instruct vlsrB_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vlsrB_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
match(Set dst_src (URShiftVB (Binary dst_src (RShiftCntV shift)) v0));
ins_cost(VEC_COST);
- format %{ "vlsrB_imm_masked $dst_src, $dst_src, $shift, $v0" %}
+ format %{ "vlsrB_vi_masked $dst_src, $dst_src, $shift, $v0" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
if (con == 0) {
@@ -3296,10 +3508,10 @@ instruct vlsrB_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vlsrS_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vlsrS_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
match(Set dst_src (URShiftVS (Binary dst_src (RShiftCntV shift)) v0));
ins_cost(VEC_COST);
- format %{ "vlsrS_imm_masked $dst_src, $dst_src, $shift, $v0" %}
+ format %{ "vlsrS_vi_masked $dst_src, $dst_src, $shift, $v0" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
if (con == 0) {
@@ -3317,10 +3529,10 @@ instruct vlsrS_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vlsrI_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vlsrI_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
match(Set dst_src (URShiftVI (Binary dst_src (RShiftCntV shift)) v0));
ins_cost(VEC_COST);
- format %{ "vlsrI_imm_masked $dst_src, $dst_src, $shift, $v0" %}
+ format %{ "vlsrI_vi_masked $dst_src, $dst_src, $shift, $v0" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
if (con == 0) {
@@ -3333,11 +3545,11 @@ instruct vlsrI_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vlsrL_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vlsrL_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
predicate((n->in(1)->in(2)->in(1)->get_int() & 0x3f) < 32);
match(Set dst_src (URShiftVL (Binary dst_src (RShiftCntV shift)) v0));
ins_cost(VEC_COST);
- format %{ "vlsrL_imm_masked $dst_src, $dst_src, $shift, $v0" %}
+ format %{ "vlsrL_vi_masked $dst_src, $dst_src, $shift, $v0" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
if (con == 0) {
@@ -3350,10 +3562,10 @@ instruct vlsrL_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vlslB_imm(vReg dst, vReg src, immI shift) %{
+instruct vlslB_vi(vReg dst, vReg src, immI shift) %{
match(Set dst (LShiftVB src (LShiftCntV shift)));
ins_cost(VEC_COST);
- format %{ "vlslB_imm $dst, $src, $shift" %}
+ format %{ "vlslB_vi $dst, $src, $shift" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_BYTE, Matcher::vector_length(this));
@@ -3367,10 +3579,10 @@ instruct vlslB_imm(vReg dst, vReg src, immI shift) %{
ins_pipe(pipe_slow);
%}
-instruct vlslS_imm(vReg dst, vReg src, immI shift) %{
+instruct vlslS_vi(vReg dst, vReg src, immI shift) %{
match(Set dst (LShiftVS src (LShiftCntV shift)));
ins_cost(VEC_COST);
- format %{ "vlslS_imm $dst, $src, $shift" %}
+ format %{ "vlslS_vi $dst, $src, $shift" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_SHORT, Matcher::vector_length(this));
@@ -3384,10 +3596,10 @@ instruct vlslS_imm(vReg dst, vReg src, immI shift) %{
ins_pipe(pipe_slow);
%}
-instruct vlslI_imm(vReg dst, vReg src, immI shift) %{
+instruct vlslI_vi(vReg dst, vReg src, immI shift) %{
match(Set dst (LShiftVI src (LShiftCntV shift)));
ins_cost(VEC_COST);
- format %{ "vlslI_imm $dst, $src, $shift" %}
+ format %{ "vlslI_vi $dst, $src, $shift" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_INT, Matcher::vector_length(this));
@@ -3396,11 +3608,11 @@ instruct vlslI_imm(vReg dst, vReg src, immI shift) %{
ins_pipe(pipe_slow);
%}
-instruct vlslL_imm(vReg dst, vReg src, immI shift) %{
+instruct vlslL_vi(vReg dst, vReg src, immI shift) %{
predicate((n->in(2)->in(1)->get_int() & 0x3f) < 32);
match(Set dst (LShiftVL src (LShiftCntV shift)));
ins_cost(VEC_COST);
- format %{ "vlslL_imm $dst, $src, $shift" %}
+ format %{ "vlslL_vi $dst, $src, $shift" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
@@ -3409,10 +3621,10 @@ instruct vlslL_imm(vReg dst, vReg src, immI shift) %{
ins_pipe(pipe_slow);
%}
-instruct vlslB_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vlslB_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
match(Set dst_src (LShiftVB (Binary dst_src (LShiftCntV shift)) v0));
ins_cost(VEC_COST);
- format %{ "vlslB_imm_masked $dst_src, $dst_src, $shift, $v0" %}
+ format %{ "vlslB_vi_masked $dst_src, $dst_src, $shift, $v0" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_BYTE, Matcher::vector_length(this));
@@ -3427,10 +3639,10 @@ instruct vlslB_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vlslS_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vlslS_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
match(Set dst_src (LShiftVS (Binary dst_src (LShiftCntV shift)) v0));
ins_cost(VEC_COST);
- format %{ "vlslS_imm_masked $dst_src, $dst_src, $shift, $v0" %}
+ format %{ "vlslS_vi_masked $dst_src, $dst_src, $shift, $v0" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_SHORT, Matcher::vector_length(this));
@@ -3445,10 +3657,10 @@ instruct vlslS_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vlslI_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vlslI_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
match(Set dst_src (LShiftVI (Binary dst_src (LShiftCntV shift)) v0));
ins_cost(VEC_COST);
- format %{ "vlslI_imm_masked $dst_src, $dst_src, $shift, $v0" %}
+ format %{ "vlslI_vi_masked $dst_src, $dst_src, $shift, $v0" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_INT, Matcher::vector_length(this));
@@ -3458,11 +3670,11 @@ instruct vlslI_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
ins_pipe(pipe_slow);
%}
-instruct vlslL_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vlslL_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
predicate((n->in(1)->in(2)->in(1)->get_int() & 0x3f) < 32);
match(Set dst_src (LShiftVL (Binary dst_src (LShiftCntV shift)) v0));
ins_cost(VEC_COST);
- format %{ "vlslL_imm_masked $dst_src, $dst_src, $shift, $v0" %}
+ format %{ "vlslL_vi_masked $dst_src, $dst_src, $shift, $v0" %}
ins_encode %{
uint32_t con = (unsigned)$shift$$constant & 0x1f;
__ vsetvli_helper(T_LONG, Matcher::vector_length(this));
@@ -3502,9 +3714,9 @@ instruct vrotate_right(vReg dst, vReg src, vReg shift) %{
%}
// Only the low log2(SEW) bits of shift value are used, all other bits are ignored.
-instruct vrotate_right_reg(vReg dst, vReg src, iRegIorL2I shift) %{
+instruct vrotate_right_vx(vReg dst, vReg src, iRegIorL2I shift) %{
match(Set dst (RotateRightV src (Replicate shift)));
- format %{ "vrotate_right_reg $dst, $src, $shift\t" %}
+ format %{ "vrotate_right_vx $dst, $src, $shift\t" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -3514,9 +3726,9 @@ instruct vrotate_right_reg(vReg dst, vReg src, iRegIorL2I shift) %{
ins_pipe(pipe_slow);
%}
-instruct vrotate_right_imm(vReg dst, vReg src, immI shift) %{
+instruct vrotate_right_vi(vReg dst, vReg src, immI shift) %{
match(Set dst (RotateRightV src shift));
- format %{ "vrotate_right_imm $dst, $src, $shift\t" %}
+ format %{ "vrotate_right_vi $dst, $src, $shift\t" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
uint32_t bits = type2aelembytes(bt) * 8;
@@ -3534,7 +3746,7 @@ instruct vrotate_right_imm(vReg dst, vReg src, immI shift) %{
instruct vrotate_right_masked(vReg dst_src, vReg shift, vRegMask_V0 v0) %{
match(Set dst_src (RotateRightV (Binary dst_src shift) v0));
- format %{ "vrotate_right_masked $dst_src, $dst_src, $shift, v0.t\t" %}
+ format %{ "vrotate_right_masked $dst_src, $dst_src, $shift, $v0\t" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -3545,9 +3757,9 @@ instruct vrotate_right_masked(vReg dst_src, vReg shift, vRegMask_V0 v0) %{
%}
// Only the low log2(SEW) bits of shift value are used, all other bits are ignored.
-instruct vrotate_right_reg_masked(vReg dst_src, iRegIorL2I shift, vRegMask_V0 v0) %{
+instruct vrotate_right_vx_masked(vReg dst_src, iRegIorL2I shift, vRegMask_V0 v0) %{
match(Set dst_src (RotateRightV (Binary dst_src (Replicate shift)) v0));
- format %{ "vrotate_right_reg_masked $dst_src, $dst_src, $shift, v0.t\t" %}
+ format %{ "vrotate_right_vx_masked $dst_src, $dst_src, $shift, $v0\t" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -3557,9 +3769,9 @@ instruct vrotate_right_reg_masked(vReg dst_src, iRegIorL2I shift, vRegMask_V0 v0
ins_pipe(pipe_slow);
%}
-instruct vrotate_right_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vrotate_right_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
match(Set dst_src (RotateRightV (Binary dst_src shift) v0));
- format %{ "vrotate_right_imm_masked $dst_src, $dst_src, $shift, v0.t\t" %}
+ format %{ "vrotate_right_vi_masked $dst_src, $dst_src, $shift, $v0\t" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
uint32_t bits = type2aelembytes(bt) * 8;
@@ -3589,9 +3801,9 @@ instruct vrotate_left(vReg dst, vReg src, vReg shift) %{
%}
// Only the low log2(SEW) bits of shift value are used, all other bits are ignored.
-instruct vrotate_left_reg(vReg dst, vReg src, iRegIorL2I shift) %{
+instruct vrotate_left_vx(vReg dst, vReg src, iRegIorL2I shift) %{
match(Set dst (RotateLeftV src (Replicate shift)));
- format %{ "vrotate_left_reg $dst, $src, $shift\t" %}
+ format %{ "vrotate_left_vx $dst, $src, $shift\t" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -3601,9 +3813,9 @@ instruct vrotate_left_reg(vReg dst, vReg src, iRegIorL2I shift) %{
ins_pipe(pipe_slow);
%}
-instruct vrotate_left_imm(vReg dst, vReg src, immI shift) %{
+instruct vrotate_left_vi(vReg dst, vReg src, immI shift) %{
match(Set dst (RotateLeftV src shift));
- format %{ "vrotate_left_imm $dst, $src, $shift\t" %}
+ format %{ "vrotate_left_vi $dst, $src, $shift\t" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
uint32_t bits = type2aelembytes(bt) * 8;
@@ -3622,7 +3834,7 @@ instruct vrotate_left_imm(vReg dst, vReg src, immI shift) %{
instruct vrotate_left_masked(vReg dst_src, vReg shift, vRegMask_V0 v0) %{
match(Set dst_src (RotateLeftV (Binary dst_src shift) v0));
- format %{ "vrotate_left_masked $dst_src, $dst_src, $shift, v0.t\t" %}
+ format %{ "vrotate_left_masked $dst_src, $dst_src, $shift, $v0\t" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -3633,9 +3845,9 @@ instruct vrotate_left_masked(vReg dst_src, vReg shift, vRegMask_V0 v0) %{
%}
// Only the low log2(SEW) bits of shift value are used, all other bits are ignored.
-instruct vrotate_left_reg_masked(vReg dst_src, iRegIorL2I shift, vRegMask_V0 v0) %{
+instruct vrotate_left_vx_masked(vReg dst_src, iRegIorL2I shift, vRegMask_V0 v0) %{
match(Set dst_src (RotateLeftV (Binary dst_src (Replicate shift)) v0));
- format %{ "vrotate_left_reg_masked $dst_src, $dst_src, $shift, v0.t\t" %}
+ format %{ "vrotate_left_vx_masked $dst_src, $dst_src, $shift, $v0\t" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -3645,9 +3857,9 @@ instruct vrotate_left_reg_masked(vReg dst_src, iRegIorL2I shift, vRegMask_V0 v0)
ins_pipe(pipe_slow);
%}
-instruct vrotate_left_imm_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
+instruct vrotate_left_vi_masked(vReg dst_src, immI shift, vRegMask_V0 v0) %{
match(Set dst_src (RotateLeftV (Binary dst_src shift) v0));
- format %{ "vrotate_left_imm_masked $dst_src, $dst_src, $shift, v0.t\t" %}
+ format %{ "vrotate_left_vi_masked $dst_src, $dst_src, $shift, $v0\t" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
uint32_t bits = type2aelembytes(bt) * 8;
@@ -4243,8 +4455,8 @@ instruct vcvtStoB(vReg dst, vReg src) %{
%}
instruct vcvtStoX(vReg dst, vReg src) %{
- predicate((Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_LONG));
+ predicate(Matcher::vector_element_basic_type(n) == T_INT ||
+ Matcher::vector_element_basic_type(n) == T_LONG);
match(Set dst (VectorCastS2X src));
effect(TEMP_DEF dst);
format %{ "vcvtStoX $dst, $src" %}
@@ -4257,8 +4469,8 @@ instruct vcvtStoX(vReg dst, vReg src) %{
%}
instruct vcvtStoX_fp(vReg dst, vReg src) %{
- predicate((Matcher::vector_element_basic_type(n) == T_FLOAT ||
- Matcher::vector_element_basic_type(n) == T_DOUBLE));
+ predicate(Matcher::vector_element_basic_type(n) == T_FLOAT ||
+ Matcher::vector_element_basic_type(n) == T_DOUBLE);
match(Set dst (VectorCastS2X src));
effect(TEMP_DEF dst);
format %{ "vcvtStoX_fp $dst, $src" %}
@@ -4355,9 +4567,9 @@ instruct vcvtItoD(vReg dst, vReg src) %{
// VectorCastL2X
instruct vcvtLtoI(vReg dst, vReg src) %{
- predicate(Matcher::vector_element_basic_type(n) == T_INT ||
- Matcher::vector_element_basic_type(n) == T_BYTE ||
- Matcher::vector_element_basic_type(n) == T_SHORT);
+ predicate(Matcher::vector_element_basic_type(n) == T_BYTE ||
+ Matcher::vector_element_basic_type(n) == T_SHORT ||
+ Matcher::vector_element_basic_type(n) == T_INT);
match(Set dst (VectorCastL2X src));
format %{ "vcvtLtoI $dst, $src" %}
ins_encode %{
@@ -5093,14 +5305,14 @@ instruct populateindex(vReg dst, iRegIorL2I src1, iRegIorL2I src2, vReg tmp) %{
// BYTE, SHORT, INT
-instruct insertI_index_lt32(vReg dst, vReg src, iRegIorL2I val, immI idx, vRegMask_V0 v0) %{
+instruct insert_index_lt32(vReg dst, vReg src, iRegIorL2I val, immI idx, vRegMask_V0 v0) %{
predicate(n->in(2)->get_int() < 32 &&
(Matcher::vector_element_basic_type(n) == T_BYTE ||
Matcher::vector_element_basic_type(n) == T_SHORT ||
Matcher::vector_element_basic_type(n) == T_INT));
match(Set dst (VectorInsert (Binary src val) idx));
effect(TEMP v0);
- format %{ "insertI_index_lt32 $dst, $src, $val, $idx" %}
+ format %{ "insert_index_lt32 $dst, $src, $val, $idx" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -5112,14 +5324,14 @@ instruct insertI_index_lt32(vReg dst, vReg src, iRegIorL2I val, immI idx, vRegMa
ins_pipe(pipe_slow);
%}
-instruct insertI_index(vReg dst, vReg src, iRegIorL2I val, iRegIorL2I idx, vReg tmp, vRegMask_V0 v0) %{
+instruct insert_index(vReg dst, vReg src, iRegIorL2I val, iRegIorL2I idx, vReg tmp, vRegMask_V0 v0) %{
predicate(n->in(2)->get_int() >= 32 &&
(Matcher::vector_element_basic_type(n) == T_BYTE ||
Matcher::vector_element_basic_type(n) == T_SHORT ||
Matcher::vector_element_basic_type(n) == T_INT));
match(Set dst (VectorInsert (Binary src val) idx));
effect(TEMP tmp, TEMP v0);
- format %{ "insertI_index $dst, $src, $val, $idx\t# KILL $tmp" %}
+ format %{ "insert_index $dst, $src, $val, $idx\t# KILL $tmp" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
diff --git a/src/hotspot/cpu/riscv/runtime_riscv.cpp b/src/hotspot/cpu/riscv/runtime_riscv.cpp
index 44a8e35e285..7c8ca853bc4 100644
--- a/src/hotspot/cpu/riscv/runtime_riscv.cpp
+++ b/src/hotspot/cpu/riscv/runtime_riscv.cpp
@@ -63,6 +63,9 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBuffer buffer(name, 2048, 1024);
+ if (buffer.blob() == nullptr) {
+ return nullptr;
+ }
MacroAssembler* masm = new MacroAssembler(&buffer);
assert_cond(masm != nullptr);
@@ -282,6 +285,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 2048, 1024);
+ if (buffer.blob() == nullptr) {
+ return nullptr;
+ }
MacroAssembler* masm = new MacroAssembler(&buffer);
assert_cond(masm != nullptr);
diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
index 4527a32926f..fb4539267ae 100644
--- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
+++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
@@ -6458,58 +6458,6 @@ static const int64_t right_3_bits = right_n_bits(3);
return start;
}
- void generate_vector_math_stubs() {
- if (!UseRVV) {
- log_info(library)("vector is not supported, skip loading vector math (sleef) library!");
- return;
- }
-
- // Get native vector math stub routine addresses
- void* libsleef = nullptr;
- char ebuf[1024];
- char dll_name[JVM_MAXPATHLEN];
- if (os::dll_locate_lib(dll_name, sizeof(dll_name), Arguments::get_dll_dir(), "sleef")) {
- libsleef = os::dll_load(dll_name, ebuf, sizeof ebuf);
- }
- if (libsleef == nullptr) {
- log_info(library)("Failed to load native vector math (sleef) library, %s!", ebuf);
- return;
- }
-
- // Method naming convention
- // All the methods are named as _
- //
- // Where:
- // is the operation name, e.g. sin, cos
- // is to indicate float/double
- // "fx/dx" for vector float/double operation
- // is the precision level
- // "u10/u05" represents 1.0/0.5 ULP error bounds
- // We use "u10" for all operations by default
- // But for those functions do not have u10 support, we use "u05" instead
- // rvv, indicates riscv vector extension
- //
- // e.g. sinfx_u10rvv is the method for computing vector float sin using rvv instructions
- //
- log_info(library)("Loaded library %s, handle " INTPTR_FORMAT, JNI_LIB_PREFIX "sleef" JNI_LIB_SUFFIX, p2i(libsleef));
-
- for (int op = 0; op < VectorSupport::NUM_VECTOR_OP_MATH; op++) {
- int vop = VectorSupport::VECTOR_OP_MATH_START + op;
- if (vop == VectorSupport::VECTOR_OP_TANH) { // skip tanh because of performance regression
- continue;
- }
-
- // The native library does not support u10 level of "hypot".
- const char* ulf = (vop == VectorSupport::VECTOR_OP_HYPOT) ? "u05" : "u10";
-
- snprintf(ebuf, sizeof(ebuf), "%sfx_%srvv", VectorSupport::mathname[op], ulf);
- StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_SCALABLE][op] = (address)os::dll_lookup(libsleef, ebuf);
-
- snprintf(ebuf, sizeof(ebuf), "%sdx_%srvv", VectorSupport::mathname[op], ulf);
- StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_SCALABLE][op] = (address)os::dll_lookup(libsleef, ebuf);
- }
- }
-
#endif // COMPILER2
/**
@@ -6741,8 +6689,6 @@ static const int64_t right_3_bits = right_n_bits(3);
generate_string_indexof_stubs();
- generate_vector_math_stubs();
-
#endif // COMPILER2
}
diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp
index 8dcffc9c646..28c32ed33c8 100644
--- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp
+++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp
@@ -468,7 +468,7 @@ void VM_Version::initialize_cpu_information(void) {
_no_of_threads = _no_of_cores;
_no_of_sockets = _no_of_cores;
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "RISCV64");
- snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "RISCV64 %s", features_string());
+ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "RISCV64 %s", cpu_info_string());
_initialized = true;
}
diff --git a/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp b/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp
index c858a4b8cb1..430928a66ed 100644
--- a/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp
+++ b/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp
@@ -52,7 +52,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
CHECK_BAILOUT();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
return;
}
@@ -74,7 +74,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
CHECK_BAILOUT();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) {
@@ -88,7 +88,7 @@ void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
CHECK_BAILOUT();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
void CounterOverflowStub::emit_code(LIR_Assembler* ce) {
@@ -116,7 +116,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) {
ce->emit_call_c(Runtime1::entry_for (C1StubId::throw_div0_exception_id));
CHECK_BAILOUT();
ce->add_call_info_here(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
@@ -134,7 +134,7 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
CHECK_BAILOUT();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
// Note: pass object in Z_R1_scratch
@@ -147,7 +147,7 @@ void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
ce->emit_call_c(a);
CHECK_BAILOUT();
ce->add_call_info_here(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, C1StubId stub_id) {
diff --git a/src/hotspot/cpu/s390/c1_FrameMap_s390.cpp b/src/hotspot/cpu/s390/c1_FrameMap_s390.cpp
index 9fa6da8341f..ddba445154a 100644
--- a/src/hotspot/cpu/s390/c1_FrameMap_s390.cpp
+++ b/src/hotspot/cpu/s390/c1_FrameMap_s390.cpp
@@ -144,13 +144,13 @@ LIR_Opr FrameMap::_caller_save_fpu_regs[] = {};
// c1 rnr -> FloatRegister
FloatRegister FrameMap::nr2floatreg (int rnr) {
assert(_init_done, "tables not initialized");
- debug_only(fpu_range_check(rnr);)
+ DEBUG_ONLY(fpu_range_check(rnr);)
return _fpu_rnr2reg[rnr];
}
void FrameMap::map_float_register(int rnr, FloatRegister reg) {
- debug_only(fpu_range_check(rnr);)
- debug_only(fpu_range_check(reg->encoding());)
+ DEBUG_ONLY(fpu_range_check(rnr);)
+ DEBUG_ONLY(fpu_range_check(reg->encoding());)
_fpu_rnr2reg[rnr] = reg; // mapping c1 regnr. -> FloatRegister
_fpu_reg2rnr[reg->encoding()] = rnr; // mapping assembler encoding -> c1 regnr.
}
diff --git a/src/hotspot/cpu/s390/c1_FrameMap_s390.hpp b/src/hotspot/cpu/s390/c1_FrameMap_s390.hpp
index 66ccc8de876..721995f41fe 100644
--- a/src/hotspot/cpu/s390/c1_FrameMap_s390.hpp
+++ b/src/hotspot/cpu/s390/c1_FrameMap_s390.hpp
@@ -107,7 +107,7 @@
static int fpu_reg2rnr (FloatRegister reg) {
assert(_init_done, "tables not initialized");
int c1rnr = _fpu_reg2rnr[reg->encoding()];
- debug_only(fpu_range_check(c1rnr);)
+ DEBUG_ONLY(fpu_range_check(c1rnr);)
return c1rnr;
}
diff --git a/src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp b/src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp
index 85dcc0a4e73..88b3199e4e1 100644
--- a/src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp
+++ b/src/hotspot/cpu/s390/gc/shared/barrierSetNMethod_s390.cpp
@@ -40,7 +40,7 @@ class NativeMethodBarrier: public NativeInstruction {
address get_patchable_data_address() const {
address inst_addr = get_barrier_start_address() + PATCHABLE_INSTRUCTION_OFFSET;
- debug_only(Assembler::is_z_cfi(*((long*)inst_addr)));
+ DEBUG_ONLY(Assembler::is_z_cfi(*((long*)inst_addr)));
return inst_addr + 2;
}
@@ -91,7 +91,7 @@ static NativeMethodBarrier* get_nmethod_barrier(nmethod* nm) {
address barrier_address = nm->code_begin() + nm->frame_complete_offset() - NativeMethodBarrier::BARRIER_TOTAL_LENGTH;
auto barrier = reinterpret_cast(barrier_address);
- debug_only(barrier->verify());
+ DEBUG_ONLY(barrier->verify());
return barrier;
}
diff --git a/src/hotspot/cpu/s390/interp_masm_s390.cpp b/src/hotspot/cpu/s390/interp_masm_s390.cpp
index 4ba99eb9e88..09995334330 100644
--- a/src/hotspot/cpu/s390/interp_masm_s390.cpp
+++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp
@@ -444,7 +444,7 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
// Useful if consumed previously by access via stackTop().
void InterpreterMacroAssembler::popx(int len) {
add2reg(Z_esp, len*Interpreter::stackElementSize);
- debug_only(verify_esp(Z_esp, Z_R1_scratch));
+ DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
}
// Get Address object of stack top. No checks. No pop.
@@ -458,38 +458,38 @@ void InterpreterMacroAssembler::pop_i(Register r) {
z_l(r, Interpreter::expr_offset_in_bytes(0), Z_esp);
add2reg(Z_esp, Interpreter::stackElementSize);
assert_different_registers(r, Z_R1_scratch);
- debug_only(verify_esp(Z_esp, Z_R1_scratch));
+ DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
}
void InterpreterMacroAssembler::pop_ptr(Register r) {
z_lg(r, Interpreter::expr_offset_in_bytes(0), Z_esp);
add2reg(Z_esp, Interpreter::stackElementSize);
assert_different_registers(r, Z_R1_scratch);
- debug_only(verify_esp(Z_esp, Z_R1_scratch));
+ DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
}
void InterpreterMacroAssembler::pop_l(Register r) {
z_lg(r, Interpreter::expr_offset_in_bytes(0), Z_esp);
add2reg(Z_esp, 2*Interpreter::stackElementSize);
assert_different_registers(r, Z_R1_scratch);
- debug_only(verify_esp(Z_esp, Z_R1_scratch));
+ DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
}
void InterpreterMacroAssembler::pop_f(FloatRegister f) {
mem2freg_opt(f, Address(Z_esp, Interpreter::expr_offset_in_bytes(0)), false);
add2reg(Z_esp, Interpreter::stackElementSize);
- debug_only(verify_esp(Z_esp, Z_R1_scratch));
+ DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
}
void InterpreterMacroAssembler::pop_d(FloatRegister f) {
mem2freg_opt(f, Address(Z_esp, Interpreter::expr_offset_in_bytes(0)), true);
add2reg(Z_esp, 2*Interpreter::stackElementSize);
- debug_only(verify_esp(Z_esp, Z_R1_scratch));
+ DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
}
void InterpreterMacroAssembler::push_i(Register r) {
assert_different_registers(r, Z_R1_scratch);
- debug_only(verify_esp(Z_esp, Z_R1_scratch));
+ DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
z_st(r, Address(Z_esp));
add2reg(Z_esp, -Interpreter::stackElementSize);
}
@@ -501,7 +501,7 @@ void InterpreterMacroAssembler::push_ptr(Register r) {
void InterpreterMacroAssembler::push_l(Register r) {
assert_different_registers(r, Z_R1_scratch);
- debug_only(verify_esp(Z_esp, Z_R1_scratch));
+ DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
int offset = -Interpreter::stackElementSize;
z_stg(r, Address(Z_esp, offset));
clear_mem(Address(Z_esp), Interpreter::stackElementSize);
@@ -509,13 +509,13 @@ void InterpreterMacroAssembler::push_l(Register r) {
}
void InterpreterMacroAssembler::push_f(FloatRegister f) {
- debug_only(verify_esp(Z_esp, Z_R1_scratch));
+ DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
freg2mem_opt(f, Address(Z_esp), false);
add2reg(Z_esp, -Interpreter::stackElementSize);
}
void InterpreterMacroAssembler::push_d(FloatRegister d) {
- debug_only(verify_esp(Z_esp, Z_R1_scratch));
+ DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
int offset = -Interpreter::stackElementSize;
freg2mem_opt(d, Address(Z_esp, offset));
add2reg(Z_esp, 2 * offset);
diff --git a/src/hotspot/cpu/s390/runtime_s390.cpp b/src/hotspot/cpu/s390/runtime_s390.cpp
index 4eedb3877d2..8f96ff55ccb 100644
--- a/src/hotspot/cpu/s390/runtime_s390.cpp
+++ b/src/hotspot/cpu/s390/runtime_s390.cpp
@@ -72,6 +72,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 2048, 1024);
+ if (buffer.blob() == nullptr) {
+ return nullptr;
+ }
MacroAssembler* masm = new MacroAssembler(&buffer);
Register handle_exception = Z_ARG5;
diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
index f4487ccabec..099e28a3adc 100644
--- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
+++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp
@@ -2768,6 +2768,9 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBuffer buffer(name, 2048, 1024);
+ if (buffer.blob() == nullptr) {
+ return nullptr;
+ }
InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer);
Register unroll_block_reg = Z_tmp_1;
diff --git a/src/hotspot/cpu/s390/vm_version_s390.cpp b/src/hotspot/cpu/s390/vm_version_s390.cpp
index 157b945e6e1..8261fbd083a 100644
--- a/src/hotspot/cpu/s390/vm_version_s390.cpp
+++ b/src/hotspot/cpu/s390/vm_version_s390.cpp
@@ -90,7 +90,7 @@ static const char* z_features[] = {" ",
void VM_Version::initialize() {
determine_features(); // Get processor capabilities.
- set_features_string(); // Set a descriptive feature indication.
+ set_cpu_info_string(); // Set a descriptive feature indication.
if (Verbose || PrintAssembly || PrintStubCode) {
print_features_internal("CPU Version as detected internally:", PrintAssembly || PrintStubCode);
@@ -388,9 +388,9 @@ int VM_Version::get_model_index() {
}
-void VM_Version::set_features_string() {
- // A note on the _features_string format:
- // There are jtreg tests checking the _features_string for various properties.
+void VM_Version::set_cpu_info_string() {
+ // A note on the _cpu_info_string format:
+ // There are jtreg tests checking the _cpu_info_string for various properties.
// For some strange reason, these tests require the string to contain
// only _lowercase_ characters. Keep that in mind when being surprised
// about the unusual notation of features - and when adding new ones.
@@ -412,29 +412,29 @@ void VM_Version::set_features_string() {
_model_string = "unknown model";
strcpy(buf, "z/Architecture (ambiguous detection)");
}
- _features_string = os::strdup(buf);
+ _cpu_info_string = os::strdup(buf);
if (has_Crypto_AES()) {
- assert(strlen(_features_string) + 3*8 < sizeof(buf), "increase buffer size");
+ assert(strlen(_cpu_info_string) + 3*8 < sizeof(buf), "increase buffer size");
jio_snprintf(buf, sizeof(buf), "%s%s%s%s",
- _features_string,
+ _cpu_info_string,
has_Crypto_AES128() ? ", aes128" : "",
has_Crypto_AES192() ? ", aes192" : "",
has_Crypto_AES256() ? ", aes256" : "");
- os::free((void *)_features_string);
- _features_string = os::strdup(buf);
+ os::free((void *)_cpu_info_string);
+ _cpu_info_string = os::strdup(buf);
}
if (has_Crypto_SHA()) {
- assert(strlen(_features_string) + 6 + 2*8 + 7 < sizeof(buf), "increase buffer size");
+ assert(strlen(_cpu_info_string) + 6 + 2*8 + 7 < sizeof(buf), "increase buffer size");
jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s",
- _features_string,
+ _cpu_info_string,
has_Crypto_SHA1() ? ", sha1" : "",
has_Crypto_SHA256() ? ", sha256" : "",
has_Crypto_SHA512() ? ", sha512" : "",
has_Crypto_GHASH() ? ", ghash" : "");
- os::free((void *)_features_string);
- _features_string = os::strdup(buf);
+ os::free((void *)_cpu_info_string);
+ _cpu_info_string = os::strdup(buf);
}
}
@@ -464,7 +464,7 @@ bool VM_Version::test_feature_bit(unsigned long* featureBuffer, int featureNum,
}
void VM_Version::print_features_internal(const char* text, bool print_anyway) {
- tty->print_cr("%s %s", text, features_string());
+ tty->print_cr("%s %s", text, cpu_info_string());
tty->cr();
if (Verbose || print_anyway) {
@@ -906,7 +906,7 @@ void VM_Version::set_features_from(const char* march) {
err = true;
}
if (!err) {
- set_features_string();
+ set_cpu_info_string();
if (prt || PrintAssembly) {
print_features_internal("CPU Version as set by cmdline option:", prt);
}
@@ -1542,6 +1542,6 @@ void VM_Version::initialize_cpu_information(void) {
_no_of_threads = _no_of_cores;
_no_of_sockets = _no_of_cores;
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE, "s390 %s", VM_Version::get_model_string());
- snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "s390 %s", features_string());
+ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "s390 %s", cpu_info_string());
_initialized = true;
}
diff --git a/src/hotspot/cpu/s390/vm_version_s390.hpp b/src/hotspot/cpu/s390/vm_version_s390.hpp
index 49e6f5686f6..6c6eb76bf7b 100644
--- a/src/hotspot/cpu/s390/vm_version_s390.hpp
+++ b/src/hotspot/cpu/s390/vm_version_s390.hpp
@@ -148,7 +148,7 @@ class VM_Version: public Abstract_VM_Version {
static bool test_feature_bit(unsigned long* featureBuffer, int featureNum, unsigned int bufLen);
static int get_model_index();
- static void set_features_string();
+ static void set_cpu_info_string();
static void print_features_internal(const char* text, bool print_anyway=false);
static void determine_features();
static long call_getFeatures(unsigned long* buffer, int buflen, int functionCode);
diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp
index 3ea00681ada..7a4d7c6d6f3 100644
--- a/src/hotspot/cpu/x86/assembler_x86.cpp
+++ b/src/hotspot/cpu/x86/assembler_x86.cpp
@@ -801,7 +801,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
address ip = inst;
bool is_64bit = false;
- debug_only(bool has_disp32 = false);
+ DEBUG_ONLY(bool has_disp32 = false);
int tail_size = 0; // other random bytes (#32, #16, etc.) at end of insn
again_after_prefix:
@@ -859,7 +859,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x8A: // movb r, a
case 0x8B: // movl r, a
case 0x8F: // popl a
- debug_only(has_disp32 = true);
+ DEBUG_ONLY(has_disp32 = true);
break;
case 0x68: // pushq #32
@@ -898,10 +898,10 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x8B: // movw r, a
case 0x89: // movw a, r
- debug_only(has_disp32 = true);
+ DEBUG_ONLY(has_disp32 = true);
break;
case 0xC7: // movw a, #16
- debug_only(has_disp32 = true);
+ DEBUG_ONLY(has_disp32 = true);
tail_size = 2; // the imm16
break;
case 0x0F: // several SSE/SSE2 variants
@@ -923,7 +923,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x69: // imul r, a, #32
case 0xC7: // movl a, #32(oop?)
tail_size = 4;
- debug_only(has_disp32 = true); // has both kinds of operands!
+ DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
case 0x0F: // movx..., etc.
@@ -932,11 +932,11 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
tail_size = 1;
case 0x38: // ptest, pmovzxbw
ip++; // skip opcode
- debug_only(has_disp32 = true); // has both kinds of operands!
+ DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
case 0x70: // pshufd r, r/a, #8
- debug_only(has_disp32 = true); // has both kinds of operands!
+ DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
case 0x73: // psrldq r, #8
tail_size = 1;
break;
@@ -961,7 +961,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0xAE: // ldmxcsr, stmxcsr, fxrstor, fxsave, clflush
case 0xD6: // movq
case 0xFE: // paddd
- debug_only(has_disp32 = true);
+ DEBUG_ONLY(has_disp32 = true);
break;
case 0xAD: // shrd r, a, %cl
@@ -976,18 +976,18 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0xC1: // xaddl
case 0xC7: // cmpxchg8
case REP16(0x90): // setcc a
- debug_only(has_disp32 = true);
+ DEBUG_ONLY(has_disp32 = true);
// fall out of the switch to decode the address
break;
case 0xC4: // pinsrw r, a, #8
- debug_only(has_disp32 = true);
+ DEBUG_ONLY(has_disp32 = true);
case 0xC5: // pextrw r, r, #8
tail_size = 1; // the imm8
break;
case 0xAC: // shrd r, a, #8
- debug_only(has_disp32 = true);
+ DEBUG_ONLY(has_disp32 = true);
tail_size = 1; // the imm8
break;
@@ -1004,12 +1004,12 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
// also: orl, adcl, sbbl, andl, subl, xorl, cmpl
// on 32bit in the case of cmpl, the imm might be an oop
tail_size = 4;
- debug_only(has_disp32 = true); // has both kinds of operands!
+ DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
case 0x83: // addl a, #8; addl r, #8
// also: orl, adcl, sbbl, andl, subl, xorl, cmpl
- debug_only(has_disp32 = true); // has both kinds of operands!
+ DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
tail_size = 1;
break;
@@ -1026,7 +1026,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x9B:
switch (0xFF & *ip++) {
case 0xD9: // fnstcw a
- debug_only(has_disp32 = true);
+ DEBUG_ONLY(has_disp32 = true);
break;
default:
ShouldNotReachHere();
@@ -1045,7 +1045,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x87: // xchg r, a
case REP4(0x38): // cmp...
case 0x85: // test r, a
- debug_only(has_disp32 = true); // has both kinds of operands!
+ DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
case 0xA8: // testb rax, #8
@@ -1057,7 +1057,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0xC6: // movb a, #8
case 0x80: // cmpb a, #8
case 0x6B: // imul r, a, #8
- debug_only(has_disp32 = true); // has both kinds of operands!
+ DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
tail_size = 1; // the imm8
break;
@@ -1109,7 +1109,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
break;
}
ip++; // skip opcode
- debug_only(has_disp32 = true); // has both kinds of operands!
+ DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
case 0x62: // EVEX_4bytes
@@ -1135,7 +1135,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
break;
}
ip++; // skip opcode
- debug_only(has_disp32 = true); // has both kinds of operands!
+ DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
case 0xD1: // sal a, 1; sar a, 1; shl a, 1; shr a, 1
@@ -1147,7 +1147,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0xD8: // fadd_s a; fsubr_s a; fmul_s a; fdivr_s a; fcomp_s a
case 0xDC: // fadd_d a; fsubr_d a; fmul_d a; fdivr_d a; fcomp_d a
case 0xDE: // faddp_d a; fsubrp_d a; fmulp_d a; fdivrp_d a; fcompp_d a
- debug_only(has_disp32 = true);
+ DEBUG_ONLY(has_disp32 = true);
break;
case 0xE8: // call rdisp32
@@ -1184,7 +1184,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
default:
ip++;
}
- debug_only(has_disp32 = true); // has both kinds of operands!
+ DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
default:
diff --git a/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp b/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp
index 73262b21365..7c0d3ff624d 100644
--- a/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp
+++ b/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp
@@ -68,7 +68,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
return;
}
@@ -88,7 +88,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ call(RuntimeAddress(Runtime1::entry_for(stub_id)));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) {
@@ -101,7 +101,7 @@ void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
__ call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
void DivByZeroStub::emit_code(LIR_Assembler* ce) {
@@ -111,7 +111,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
__ call(RuntimeAddress(Runtime1::entry_for(C1StubId::throw_div0_exception_id)));
ce->add_call_info_here(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
@@ -399,7 +399,7 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
__ call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
@@ -413,7 +413,7 @@ void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
}
__ call(RuntimeAddress(Runtime1::entry_for(_stub)));
ce->add_call_info_here(_info);
- debug_only(__ should_not_reach_here());
+ DEBUG_ONLY(__ should_not_reach_here());
}
diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
index 574bc081fce..19e25cde2ec 100644
--- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
@@ -787,6 +787,119 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax,
// C2 uses the value of ZF to determine the continuation.
}
+static void abort_verify_int_in_range(uint idx, jint val, jint lo, jint hi) {
+ fatal("Invalid CastII, idx: %u, val: %d, lo: %d, hi: %d", idx, val, lo, hi);
+}
+
+static void reconstruct_frame_pointer_helper(MacroAssembler* masm, Register dst) {
+ const int framesize = Compile::current()->output()->frame_size_in_bytes();
+ masm->movptr(dst, rsp);
+ if (framesize > 2 * wordSize) {
+ masm->addptr(dst, framesize - 2 * wordSize);
+ }
+}
+
+void C2_MacroAssembler::reconstruct_frame_pointer(Register rtmp) {
+ if (PreserveFramePointer) {
+ // frame pointer is valid
+#ifdef ASSERT
+ // Verify frame pointer value in rbp.
+ reconstruct_frame_pointer_helper(this, rtmp);
+ Label L_success;
+ cmpq(rbp, rtmp);
+ jccb(Assembler::equal, L_success);
+ STOP("frame pointer mismatch");
+ bind(L_success);
+#endif // ASSERT
+ } else {
+ reconstruct_frame_pointer_helper(this, rbp);
+ }
+}
+
+void C2_MacroAssembler::verify_int_in_range(uint idx, const TypeInt* t, Register val) {
+ jint lo = t->_lo;
+ jint hi = t->_hi;
+ assert(lo < hi, "type should not be empty or constant, idx: %u, lo: %d, hi: %d", idx, lo, hi);
+ if (t == TypeInt::INT) {
+ return;
+ }
+
+ BLOCK_COMMENT("CastII {");
+ Label fail;
+ Label succeed;
+ if (hi == max_jint) {
+ cmpl(val, lo);
+ jccb(Assembler::greaterEqual, succeed);
+ } else {
+ if (lo != min_jint) {
+ cmpl(val, lo);
+ jccb(Assembler::less, fail);
+ }
+ cmpl(val, hi);
+ jccb(Assembler::lessEqual, succeed);
+ }
+
+ bind(fail);
+ movl(c_rarg0, idx);
+ movl(c_rarg1, val);
+ movl(c_rarg2, lo);
+ movl(c_rarg3, hi);
+ reconstruct_frame_pointer(rscratch1);
+ call(RuntimeAddress(CAST_FROM_FN_PTR(address, abort_verify_int_in_range)));
+ hlt();
+ bind(succeed);
+ BLOCK_COMMENT("} // CastII");
+}
+
+static void abort_verify_long_in_range(uint idx, jlong val, jlong lo, jlong hi) {
+ fatal("Invalid CastLL, idx: %u, val: " JLONG_FORMAT ", lo: " JLONG_FORMAT ", hi: " JLONG_FORMAT, idx, val, lo, hi);
+}
+
+void C2_MacroAssembler::verify_long_in_range(uint idx, const TypeLong* t, Register val, Register tmp) {
+ jlong lo = t->_lo;
+ jlong hi = t->_hi;
+ assert(lo < hi, "type should not be empty or constant, idx: %u, lo: " JLONG_FORMAT ", hi: " JLONG_FORMAT, idx, lo, hi);
+ if (t == TypeLong::LONG) {
+ return;
+ }
+
+ BLOCK_COMMENT("CastLL {");
+ Label fail;
+ Label succeed;
+
+ auto cmp_val = [&](jlong bound) {
+ if (is_simm32(bound)) {
+ cmpq(val, checked_cast(bound));
+ } else {
+ mov64(tmp, bound);
+ cmpq(val, tmp);
+ }
+ };
+
+ if (hi == max_jlong) {
+ cmp_val(lo);
+ jccb(Assembler::greaterEqual, succeed);
+ } else {
+ if (lo != min_jlong) {
+ cmp_val(lo);
+ jccb(Assembler::less, fail);
+ }
+ cmp_val(hi);
+ jccb(Assembler::lessEqual, succeed);
+ }
+
+ bind(fail);
+ movl(c_rarg0, idx);
+ movq(c_rarg1, val);
+ mov64(c_rarg2, lo);
+ mov64(c_rarg3, hi);
+ reconstruct_frame_pointer(rscratch1);
+ call(RuntimeAddress(CAST_FROM_FN_PTR(address, abort_verify_long_in_range)));
+ hlt();
+ bind(succeed);
+ BLOCK_COMMENT("} // CastLL");
+}
+
//-------------------------------------------------------------------------------------------
// Generic instructions support for use in .ad files C2 code generation
diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp
index dd2880d88c3..713eb73d68f 100644
--- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp
+++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp
@@ -44,6 +44,9 @@ public:
Register t, Register thread);
void fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread);
+ void verify_int_in_range(uint idx, const TypeInt* t, Register val);
+ void verify_long_in_range(uint idx, const TypeLong* t, Register val, Register tmp);
+
// Generic instructions support for use in .ad files C2 code generation
void vabsnegd(int opcode, XMMRegister dst, XMMRegister src);
void vabsnegd(int opcode, XMMRegister dst, XMMRegister src, int vector_len);
@@ -574,4 +577,7 @@ public:
void scalar_max_min_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2,
KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2);
+
+ void reconstruct_frame_pointer(Register rtmp);
+
#endif // CPU_X86_C2_MACROASSEMBLER_X86_HPP
diff --git a/src/hotspot/cpu/x86/globalDefinitions_x86.hpp b/src/hotspot/cpu/x86/globalDefinitions_x86.hpp
index 873cfbdcea0..3c1474ae861 100644
--- a/src/hotspot/cpu/x86/globalDefinitions_x86.hpp
+++ b/src/hotspot/cpu/x86/globalDefinitions_x86.hpp
@@ -34,9 +34,7 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
#define SUPPORTS_NATIVE_CX8
-#ifdef _LP64
#define SUPPORT_MONITOR_COUNT
-#endif
#define CPU_MULTI_COPY_ATOMIC
@@ -44,15 +42,11 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
#define DEFAULT_CACHE_LINE_SIZE 64
// The default padding size for data structures to avoid false sharing.
-#ifdef _LP64
// The common wisdom is that adjacent cache line prefetchers on some hardware
// may pull two cache lines on access, so we have to pessimistically assume twice
// the cache line size for padding. TODO: Check if this is still true for modern
// hardware. If not, DEFAULT_CACHE_LINE_SIZE might as well suffice.
#define DEFAULT_PADDING_SIZE (DEFAULT_CACHE_LINE_SIZE*2)
-#else
-#define DEFAULT_PADDING_SIZE DEFAULT_CACHE_LINE_SIZE
-#endif
#if defined(LINUX) || defined(__APPLE__)
#define SUPPORT_RESERVED_STACK_AREA
diff --git a/src/hotspot/cpu/x86/globals_x86.hpp b/src/hotspot/cpu/x86/globals_x86.hpp
index 5b5f5683961..a1d4a71874f 100644
--- a/src/hotspot/cpu/x86/globals_x86.hpp
+++ b/src/hotspot/cpu/x86/globals_x86.hpp
@@ -61,29 +61,19 @@ define_pd_global(intx, InlineSmallCode, 1000);
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
#define MIN_STACK_RESERVED_PAGES (0)
-#ifdef _LP64
// Java_java_net_SocketOutputStream_socketWrite0() uses a 64k buffer on the
-// stack if compiled for unix and LP64. To pass stack overflow tests we need
-// 20 shadow pages.
+// stack if compiled for unix. To pass stack overflow tests we need 20 shadow pages.
#define DEFAULT_STACK_SHADOW_PAGES (NOT_WIN64(20) WIN64_ONLY(8) DEBUG_ONLY(+4))
// For those clients that do not use write socket, we allow
// the min range value to be below that of the default
#define MIN_STACK_SHADOW_PAGES (NOT_WIN64(10) WIN64_ONLY(8) DEBUG_ONLY(+4))
-#else
-#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
-#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
-#endif // _LP64
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
-#ifdef _LP64
define_pd_global(bool, VMContinuations, true);
-#else
-define_pd_global(bool, VMContinuations, false);
-#endif
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
diff --git a/src/hotspot/cpu/x86/nativeInst_x86.cpp b/src/hotspot/cpu/x86/nativeInst_x86.cpp
index 4ee741077dc..c3345be2172 100644
--- a/src/hotspot/cpu/x86/nativeInst_x86.cpp
+++ b/src/hotspot/cpu/x86/nativeInst_x86.cpp
@@ -67,9 +67,7 @@ void NativeCall::print() {
// Inserts a native call instruction at a given pc
void NativeCall::insert(address code_pos, address entry) {
intptr_t disp = (intptr_t)entry - ((intptr_t)code_pos + 1 + 4);
-#ifdef AMD64
guarantee(disp == (intptr_t)(jint)disp, "must be 32-bit offset");
-#endif // AMD64
*code_pos = instruction_code;
*((int32_t *)(code_pos+1)) = (int32_t) disp;
ICache::invalidate_range(code_pos, instruction_size);
@@ -140,7 +138,7 @@ bool NativeCall::is_displacement_aligned() {
// Used in the runtime linkage of calls; see class CompiledIC.
// (Cf. 4506997 and 4479829, where threads witnessed garbage displacements.)
void NativeCall::set_destination_mt_safe(address dest) {
- debug_only(verify());
+ DEBUG_ONLY(verify());
// Make sure patching code is locked. No two threads can patch at the same
// time but one may be executing this code.
assert(CodeCache_lock->is_locked() || SafepointSynchronize::is_at_safepoint() ||
@@ -157,7 +155,6 @@ void NativeCall::set_destination_mt_safe(address dest) {
void NativeMovConstReg::verify() {
-#ifdef AMD64
// make sure code pattern is actually a mov reg64, imm64 instruction
bool valid_rex_prefix = ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB;
bool valid_rex2_prefix = ubyte_at(0) == Assembler::REX2 &&
@@ -169,12 +166,6 @@ void NativeMovConstReg::verify() {
print();
fatal("not a REX.W[B] mov reg64, imm64");
}
-#else
- // make sure code pattern is actually a mov reg, imm32 instruction
- u_char test_byte = *(u_char*)instruction_address();
- u_char test_byte_2 = test_byte & ( 0xff ^ register_mask);
- if (test_byte_2 != instruction_code) fatal("not a mov reg, imm32");
-#endif // AMD64
}
@@ -192,12 +183,10 @@ int NativeMovRegMem::instruction_start() const {
// See comment in Assembler::locate_operand() about VEX prefixes.
if (instr_0 == instruction_VEX_prefix_2bytes) {
assert((UseAVX > 0), "shouldn't have VEX prefix");
- NOT_LP64(assert((0xC0 & ubyte_at(1)) == 0xC0, "shouldn't have LDS and LES instructions"));
return 2;
}
if (instr_0 == instruction_VEX_prefix_3bytes) {
assert((UseAVX > 0), "shouldn't have VEX prefix");
- NOT_LP64(assert((0xC0 & ubyte_at(1)) == 0xC0, "shouldn't have LDS and LES instructions"));
return 3;
}
if (instr_0 == instruction_EVEX_prefix_4bytes) {
@@ -313,8 +302,7 @@ void NativeMovRegMem::print() {
void NativeLoadAddress::verify() {
// make sure code pattern is actually a mov [reg+offset], reg instruction
u_char test_byte = *(u_char*)instruction_address();
- if ( ! ((test_byte == lea_instruction_code)
- LP64_ONLY(|| (test_byte == mov64_instruction_code) ))) {
+ if ((test_byte != lea_instruction_code) && (test_byte != mov64_instruction_code)) {
fatal ("not a lea reg, [reg+offs] instruction");
}
}
@@ -340,9 +328,7 @@ void NativeJump::verify() {
void NativeJump::insert(address code_pos, address entry) {
intptr_t disp = (intptr_t)entry - ((intptr_t)code_pos + 1 + 4);
-#ifdef AMD64
guarantee(disp == (intptr_t)(int32_t)disp, "must be 32-bit offset");
-#endif // AMD64
*code_pos = instruction_code;
*((int32_t*)(code_pos + 1)) = (int32_t)disp;
@@ -355,11 +341,7 @@ void NativeJump::check_verified_entry_alignment(address entry, address verified_
// in use. The patching in that instance must happen only when certain
// alignment restrictions are true. These guarantees check those
// conditions.
-#ifdef AMD64
const int linesize = 64;
-#else
- const int linesize = 32;
-#endif // AMD64
// Must be wordSize aligned
guarantee(((uintptr_t) verified_entry & (wordSize -1)) == 0,
@@ -386,7 +368,6 @@ void NativeJump::check_verified_entry_alignment(address entry, address verified_
//
void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
// complete jump instruction (to be inserted) is in code_buffer;
-#ifdef _LP64
union {
jlong cb_long;
unsigned char code_buffer[8];
@@ -402,43 +383,6 @@ void NativeJump::patch_verified_entry(address entry, address verified_entry, add
Atomic::store((jlong *) verified_entry, u.cb_long);
ICache::invalidate_range(verified_entry, 8);
-
-#else
- unsigned char code_buffer[5];
- code_buffer[0] = instruction_code;
- intptr_t disp = (intptr_t)dest - ((intptr_t)verified_entry + 1 + 4);
- *(int32_t*)(code_buffer + 1) = (int32_t)disp;
-
- check_verified_entry_alignment(entry, verified_entry);
-
- // Can't call nativeJump_at() because it's asserts jump exists
- NativeJump* n_jump = (NativeJump*) verified_entry;
-
- //First patch dummy jmp in place
-
- unsigned char patch[4];
- assert(sizeof(patch)==sizeof(int32_t), "sanity check");
- patch[0] = 0xEB; // jmp rel8
- patch[1] = 0xFE; // jmp to self
- patch[2] = 0xEB;
- patch[3] = 0xFE;
-
- // First patch dummy jmp in place
- *(int32_t*)verified_entry = *(int32_t *)patch;
-
- n_jump->wrote(0);
-
- // Patch 5th byte (from jump instruction)
- verified_entry[4] = code_buffer[4];
-
- n_jump->wrote(4);
-
- // Patch bytes 0-3 (from jump instruction)
- *(int32_t*)verified_entry = *(int32_t *)code_buffer;
- // Invalidate. Opteron requires a flush after every write.
- n_jump->wrote(0);
-#endif // _LP64
-
}
void NativeIllegalInstruction::insert(address code_pos) {
@@ -455,9 +399,7 @@ void NativeGeneralJump::verify() {
void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
intptr_t disp = (intptr_t)entry - ((intptr_t)code_pos + 1 + 4);
-#ifdef AMD64
guarantee(disp == (intptr_t)(int32_t)disp, "must be 32-bit offset");
-#endif // AMD64
*code_pos = unconditional_long_jump;
*((int32_t *)(code_pos+1)) = (int32_t) disp;
diff --git a/src/hotspot/cpu/x86/nativeInst_x86.hpp b/src/hotspot/cpu/x86/nativeInst_x86.hpp
index d02387aa9ff..b2448cb99fd 100644
--- a/src/hotspot/cpu/x86/nativeInst_x86.hpp
+++ b/src/hotspot/cpu/x86/nativeInst_x86.hpp
@@ -126,10 +126,8 @@ class NativeCall: public NativeInstruction {
address return_address() const { return addr_at(return_address_offset); }
address destination() const;
void set_destination(address dest) {
-#ifdef AMD64
intptr_t disp = dest - return_address();
guarantee(disp == (intptr_t)(jint)disp, "must be 32-bit offset");
-#endif // AMD64
set_int_at(displacement_offset, (int)(dest - return_address()));
}
// Returns whether the 4-byte displacement operand is 4-byte aligned.
@@ -211,15 +209,9 @@ class NativeCallReg: public NativeInstruction {
// Instruction format for implied addressing mode immediate operand move to register instruction:
// [REX/REX2] [OPCODE] [IMM32]
class NativeMovConstReg: public NativeInstruction {
-#ifdef AMD64
static const bool has_rex = true;
static const int rex_size = 1;
static const int rex2_size = 2;
-#else
- static const bool has_rex = false;
- static const int rex_size = 0;
- static const int rex2_size = 0;
-#endif // AMD64
public:
enum Intel_specific_constants {
instruction_code = 0xB8,
@@ -390,13 +382,8 @@ inline NativeMovRegMem* nativeMovRegMem_at (address address) {
// leal reg, [reg + offset]
class NativeLoadAddress: public NativeMovRegMem {
-#ifdef AMD64
static const bool has_rex = true;
static const int rex_size = 1;
-#else
- static const bool has_rex = false;
- static const int rex_size = 0;
-#endif // AMD64
public:
enum Intel_specific_constants {
instruction_prefix_wide = Assembler::REX_W,
@@ -447,9 +434,7 @@ class NativeJump: public NativeInstruction {
if (dest == (address) -1) {
val = -5; // jump to self
}
-#ifdef AMD64
assert((labs(val) & 0xFFFFFFFF00000000) == 0 || dest == (address)-1, "must be 32bit offset or -1");
-#endif // AMD64
set_int_at(data_offset, (jint)val);
}
@@ -503,7 +488,7 @@ class NativeGeneralJump: public NativeInstruction {
inline NativeGeneralJump* nativeGeneralJump_at(address address) {
NativeGeneralJump* jump = (NativeGeneralJump*)(address);
- debug_only(jump->verify();)
+ DEBUG_ONLY(jump->verify();)
return jump;
}
@@ -572,19 +557,14 @@ inline bool NativeInstruction::is_jump_reg() {
inline bool NativeInstruction::is_cond_jump() { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ ||
(ubyte_at(0) & 0xF0) == 0x70; /* short jump */ }
inline bool NativeInstruction::is_safepoint_poll() {
-#ifdef AMD64
const bool has_rex_prefix = ubyte_at(0) == NativeTstRegMem::instruction_rex_b_prefix;
const int test_offset = has_rex2_prefix() ? 2 : (has_rex_prefix ? 1 : 0);
-#else
- const int test_offset = 0;
-#endif
const bool is_test_opcode = ubyte_at(test_offset) == NativeTstRegMem::instruction_code_memXregl;
const bool is_rax_target = (ubyte_at(test_offset + 1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg;
return is_test_opcode && is_rax_target;
}
inline bool NativeInstruction::is_mov_literal64() {
-#ifdef AMD64
bool valid_rex_prefix = ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB;
bool valid_rex2_prefix = ubyte_at(0) == Assembler::REX2 &&
(ubyte_at(1) == Assembler::REX2BIT_W ||
@@ -593,9 +573,6 @@ inline bool NativeInstruction::is_mov_literal64() {
int opcode = has_rex2_prefix() ? ubyte_at(2) : ubyte_at(1);
return ((valid_rex_prefix || valid_rex2_prefix) && (opcode & (0xff ^ NativeMovConstReg::register_mask)) == 0xB8);
-#else
- return false;
-#endif // AMD64
}
class NativePostCallNop: public NativeInstruction {
diff --git a/src/hotspot/cpu/x86/runtime_x86_64.cpp b/src/hotspot/cpu/x86/runtime_x86_64.cpp
index a063c7aeb37..027a523b33d 100644
--- a/src/hotspot/cpu/x86/runtime_x86_64.cpp
+++ b/src/hotspot/cpu/x86/runtime_x86_64.cpp
@@ -61,6 +61,9 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBuffer buffer(name, 2048, 1024);
+ if (buffer.blob() == nullptr) {
+ return nullptr;
+ }
MacroAssembler* masm = new MacroAssembler(&buffer);
assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned");
@@ -267,6 +270,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 2048, 1024);
+ if (buffer.blob() == nullptr) {
+ return nullptr;
+ }
MacroAssembler* masm = new MacroAssembler(&buffer);
diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
index b88a2bd1f8e..1a16416787d 100644
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
@@ -4333,70 +4333,6 @@ void StubGenerator::generate_compiler_stubs() {
}
}
- // Get svml stub routine addresses
- void *libjsvml = nullptr;
- char ebuf[1024];
- char dll_name[JVM_MAXPATHLEN];
- if (os::dll_locate_lib(dll_name, sizeof(dll_name), Arguments::get_dll_dir(), "jsvml")) {
- libjsvml = os::dll_load(dll_name, ebuf, sizeof ebuf);
- }
- if (libjsvml != nullptr) {
- // SVML method naming convention
- // All the methods are named as __jsvml_op_ha_
- // Where:
- // ha stands for high accuracy
- // is optional to indicate float/double
- // Set to f for vector float operation
- // Omitted for vector double operation
- // is the number of elements in the vector
- // 1, 2, 4, 8, 16
- // e.g. 128 bit float vector has 4 float elements
- // indicates the avx/sse level:
- // z0 is AVX512, l9 is AVX2, e9 is AVX1 and ex is for SSE2
- // e.g. __jsvml_expf16_ha_z0 is the method for computing 16 element vector float exp using AVX 512 insns
- // __jsvml_exp8_ha_z0 is the method for computing 8 element vector double exp using AVX 512 insns
-
- log_info(library)("Loaded library %s, handle " INTPTR_FORMAT, JNI_LIB_PREFIX "jsvml" JNI_LIB_SUFFIX, p2i(libjsvml));
- if (UseAVX > 2) {
- for (int op = 0; op < VectorSupport::NUM_VECTOR_OP_MATH; op++) {
- int vop = VectorSupport::VECTOR_OP_MATH_START + op;
- if ((!VM_Version::supports_avx512dq()) &&
- (vop == VectorSupport::VECTOR_OP_LOG || vop == VectorSupport::VECTOR_OP_LOG10 || vop == VectorSupport::VECTOR_OP_POW)) {
- continue;
- }
- snprintf(ebuf, sizeof(ebuf), "__jsvml_%sf16_ha_z0", VectorSupport::mathname[op]);
- StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_512][op] = (address)os::dll_lookup(libjsvml, ebuf);
-
- snprintf(ebuf, sizeof(ebuf), "__jsvml_%s8_ha_z0", VectorSupport::mathname[op]);
- StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_512][op] = (address)os::dll_lookup(libjsvml, ebuf);
- }
- }
- const char* avx_sse_str = (UseAVX >= 2) ? "l9" : ((UseAVX == 1) ? "e9" : "ex");
- for (int op = 0; op < VectorSupport::NUM_VECTOR_OP_MATH; op++) {
- int vop = VectorSupport::VECTOR_OP_MATH_START + op;
- if (vop == VectorSupport::VECTOR_OP_POW) {
- continue;
- }
- snprintf(ebuf, sizeof(ebuf), "__jsvml_%sf4_ha_%s", VectorSupport::mathname[op], avx_sse_str);
- StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_64][op] = (address)os::dll_lookup(libjsvml, ebuf);
-
- snprintf(ebuf, sizeof(ebuf), "__jsvml_%sf4_ha_%s", VectorSupport::mathname[op], avx_sse_str);
- StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_128][op] = (address)os::dll_lookup(libjsvml, ebuf);
-
- snprintf(ebuf, sizeof(ebuf), "__jsvml_%sf8_ha_%s", VectorSupport::mathname[op], avx_sse_str);
- StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_256][op] = (address)os::dll_lookup(libjsvml, ebuf);
-
- snprintf(ebuf, sizeof(ebuf), "__jsvml_%s1_ha_%s", VectorSupport::mathname[op], avx_sse_str);
- StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_64][op] = (address)os::dll_lookup(libjsvml, ebuf);
-
- snprintf(ebuf, sizeof(ebuf), "__jsvml_%s2_ha_%s", VectorSupport::mathname[op], avx_sse_str);
- StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_128][op] = (address)os::dll_lookup(libjsvml, ebuf);
-
- snprintf(ebuf, sizeof(ebuf), "__jsvml_%s4_ha_%s", VectorSupport::mathname[op], avx_sse_str);
- StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_256][op] = (address)os::dll_lookup(libjsvml, ebuf);
- }
- }
-
#endif // COMPILER2
#endif // COMPILER2_OR_JVMCI
}
diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp
index 19ae2dc8d2b..5306f0becef 100644
--- a/src/hotspot/cpu/x86/vm_version_x86.cpp
+++ b/src/hotspot/cpu/x86/vm_version_x86.cpp
@@ -72,8 +72,6 @@ static get_cpu_info_stub_t get_cpu_info_stub = nullptr;
static detect_virt_stub_t detect_virt_stub = nullptr;
static clear_apx_test_state_t clear_apx_test_state_stub = nullptr;
-#ifdef _LP64
-
bool VM_Version::supports_clflush() {
// clflush should always be available on x86_64
// if not we are in real trouble because we rely on it
@@ -87,7 +85,6 @@ bool VM_Version::supports_clflush() {
assert ((!Universe::is_fully_initialized() || (_features & CPU_FLUSH) != 0), "clflush should be available");
return true;
}
-#endif
#define CPUID_STANDARD_FN 0x0
#define CPUID_STANDARD_FN_1 0x1
@@ -107,7 +104,6 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
-#if defined(_LP64)
address clear_apx_test_state() {
# define __ _masm->
address start = __ pc();
@@ -126,7 +122,6 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ ret(0);
return start;
}
-#endif
address generate_get_cpu_info() {
// Flags to test CPU type.
@@ -151,14 +146,10 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
//
// void get_cpu_info(VM_Version::CpuidInfo* cpuid_info);
//
- // LP64: rcx and rdx are first and second argument registers on windows
+ // rcx and rdx are first and second argument registers on windows
__ push(rbp);
-#ifdef _LP64
__ mov(rbp, c_rarg0); // cpuid_info address
-#else
- __ movptr(rbp, Address(rsp, 8)); // cpuid_info address
-#endif
__ push(rbx);
__ push(rsi);
__ pushf(); // preserve rbx, and flags
@@ -418,7 +409,6 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movl(Address(rsi, 8), rcx);
__ movl(Address(rsi,12), rdx);
-#if defined(_LP64)
//
// Check if OS has enabled XGETBV instruction to access XCR0
// (OSXSAVE feature flag) and CPU supports APX
@@ -453,7 +443,6 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movq(Address(rsi, 8), r31);
UseAPX = save_apx;
-#endif
#endif
__ bind(vector_save_restore);
//
@@ -527,10 +516,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movdl(xmm0, rcx);
__ vpbroadcastd(xmm0, xmm0, Assembler::AVX_512bit);
__ evmovdqul(xmm7, xmm0, Assembler::AVX_512bit);
-#ifdef _LP64
__ evmovdqul(xmm8, xmm0, Assembler::AVX_512bit);
__ evmovdqul(xmm31, xmm0, Assembler::AVX_512bit);
-#endif
VM_Version::clean_cpuFeatures();
__ jmp(save_restore_except);
}
@@ -556,10 +543,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ pshufd(xmm0, xmm0, 0x00);
__ vinsertf128_high(xmm0, xmm0);
__ vmovdqu(xmm7, xmm0);
-#ifdef _LP64
__ vmovdqu(xmm8, xmm0);
__ vmovdqu(xmm15, xmm0);
-#endif
VM_Version::clean_cpuFeatures();
__ bind(save_restore_except);
@@ -600,10 +585,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ lea(rsi, Address(rbp, in_bytes(VM_Version::zmm_save_offset())));
__ evmovdqul(Address(rsi, 0), xmm0, Assembler::AVX_512bit);
__ evmovdqul(Address(rsi, 64), xmm7, Assembler::AVX_512bit);
-#ifdef _LP64
__ evmovdqul(Address(rsi, 128), xmm8, Assembler::AVX_512bit);
__ evmovdqul(Address(rsi, 192), xmm31, Assembler::AVX_512bit);
-#endif
#ifdef _WINDOWS
__ evmovdqul(xmm31, Address(rsp, 0), Assembler::AVX_512bit);
@@ -628,10 +611,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset())));
__ vmovdqu(Address(rsi, 0), xmm0);
__ vmovdqu(Address(rsi, 32), xmm7);
-#ifdef _LP64
__ vmovdqu(Address(rsi, 64), xmm8);
__ vmovdqu(Address(rsi, 96), xmm15);
-#endif
#ifdef _WINDOWS
__ vmovdqu(xmm15, Address(rsp, 0));
@@ -687,13 +668,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ push(rbx);
__ push(rsi); // for Windows
-#ifdef _LP64
__ mov(rax, c_rarg0); // CPUID leaf
__ mov(rsi, c_rarg1); // register array address (eax, ebx, ecx, edx)
-#else
- __ movptr(rax, Address(rsp, 16)); // CPUID leaf
- __ movptr(rsi, Address(rsp, 20)); // register array address
-#endif
__ cpuid();
@@ -734,14 +710,10 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
//
// void getCPUIDBrandString(VM_Version::CpuidInfo* cpuid_info);
//
- // LP64: rcx and rdx are first and second argument registers on windows
+ // rcx and rdx are first and second argument registers on windows
__ push(rbp);
-#ifdef _LP64
__ mov(rbp, c_rarg0); // cpuid_info address
-#else
- __ movptr(rbp, Address(rsp, 8)); // cpuid_info address
-#endif
__ push(rbx);
__ push(rsi);
__ pushf(); // preserve rbx, and flags
@@ -889,19 +861,16 @@ void VM_Version::get_processor_features() {
// xchg and xadd instructions
_supports_atomic_getset4 = true;
_supports_atomic_getadd4 = true;
- LP64_ONLY(_supports_atomic_getset8 = true);
- LP64_ONLY(_supports_atomic_getadd8 = true);
+ _supports_atomic_getset8 = true;
+ _supports_atomic_getadd8 = true;
-#ifdef _LP64
// OS should support SSE for x64 and hardware should support at least SSE2.
if (!VM_Version::supports_sse2()) {
vm_exit_during_initialization("Unknown x64 processor: SSE2 not supported");
}
// in 64 bit the use of SSE2 is the minimum
if (UseSSE < 2) UseSSE = 2;
-#endif
-#ifdef AMD64
// flush_icache_stub have to be generated first.
// That is why Icache line size is hard coded in ICache class,
// see icache_x86.hpp. It is also the reason why we can't use
@@ -913,9 +882,7 @@ void VM_Version::get_processor_features() {
guarantee(_cpuid_info.std_cpuid1_edx.bits.clflush != 0, "clflush is not supported");
// clflush_size is size in quadwords (8 bytes).
guarantee(_cpuid_info.std_cpuid1_ebx.bits.clflush_size == 8, "such clflush size is not supported");
-#endif
-#ifdef _LP64
// assigning this field effectively enables Unsafe.writebackMemory()
// by initing UnsafeConstant.DATA_CACHE_LINE_FLUSH_SIZE to non-zero
// that is only implemented on x86_64 and only if the OS plays ball
@@ -924,7 +891,6 @@ void VM_Version::get_processor_features() {
// let if default to zero thereby disabling writeback
_data_cache_line_flush_size = _cpuid_info.std_cpuid1_ebx.bits.clflush_size * 8;
}
-#endif
// Check if processor has Intel Ecore
if (FLAG_IS_DEFAULT(EnableX86ECoreOpts) && is_intel() && cpu_family() == 6 &&
@@ -1114,15 +1080,19 @@ void VM_Version::get_processor_features() {
}
char buf[1024];
- int res = jio_snprintf(
+ int cpu_info_size = jio_snprintf(
buf, sizeof(buf),
"(%u cores per cpu, %u threads per core) family %d model %d stepping %d microcode 0x%x",
cores_per_cpu(), threads_per_core(),
cpu_family(), _model, _stepping, os::cpu_microcode_revision());
- assert(res > 0, "not enough temporary space allocated");
- insert_features_names(buf + res, sizeof(buf) - res, _features_names);
+ assert(cpu_info_size > 0, "not enough temporary space allocated");
+ insert_features_names(buf + cpu_info_size, sizeof(buf) - cpu_info_size, _features_names);
- _features_string = os::strdup(buf);
+ _cpu_info_string = os::strdup(buf);
+
+ _features_string = extract_features_string(_cpu_info_string,
+ strnlen(_cpu_info_string, sizeof(buf)),
+ cpu_info_size);
// Use AES instructions if available.
if (supports_aes()) {
@@ -1206,7 +1176,6 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
}
-#ifdef _LP64
if (supports_avx2()) {
if (FLAG_IS_DEFAULT(UseAdler32Intrinsics)) {
UseAdler32Intrinsics = true;
@@ -1217,12 +1186,6 @@ void VM_Version::get_processor_features() {
}
FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
}
-#else
- if (UseAdler32Intrinsics) {
- warning("Adler32Intrinsics not available on this CPU.");
- FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
- }
-#endif
if (supports_sse4_2() && supports_clmul()) {
if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
@@ -1246,7 +1209,6 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
}
-#ifdef _LP64
// ChaCha20 Intrinsics
// As long as the system supports AVX as a baseline we can do a
// SIMD-enabled block function. StubGenerator makes the determination
@@ -1262,24 +1224,14 @@ void VM_Version::get_processor_features() {
}
FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false);
}
-#else
- // No support currently for ChaCha20 intrinsics on 32-bit platforms
- if (UseChaCha20Intrinsics) {
- warning("ChaCha20 intrinsics are not available on this CPU.");
- FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false);
- }
-#endif // _LP64
// Dilithium Intrinsics
// Currently we only have them for AVX512
-#ifdef _LP64
if (supports_evex() && supports_avx512bw()) {
if (FLAG_IS_DEFAULT(UseDilithiumIntrinsics)) {
UseDilithiumIntrinsics = true;
}
- } else
-#endif
- if (UseDilithiumIntrinsics) {
+ } else if (UseDilithiumIntrinsics) {
warning("Intrinsics for ML-DSA are not available on this CPU.");
FLAG_SET_DEFAULT(UseDilithiumIntrinsics, false);
}
@@ -1308,7 +1260,7 @@ void VM_Version::get_processor_features() {
UseMD5Intrinsics = true;
}
- if (supports_sha() LP64_ONLY(|| (supports_avx2() && supports_bmi2()))) {
+ if (supports_sha() || (supports_avx2() && supports_bmi2())) {
if (FLAG_IS_DEFAULT(UseSHA)) {
UseSHA = true;
}
@@ -1335,27 +1287,20 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
}
-#ifdef _LP64
- // These are only supported on 64-bit
if (UseSHA && supports_avx2() && (supports_bmi2() || supports_sha512())) {
if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
}
- } else
-#endif
- if (UseSHA512Intrinsics) {
+ } else if (UseSHA512Intrinsics) {
warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
}
-#ifdef _LP64
if (supports_evex() && supports_avx512bw()) {
if (FLAG_IS_DEFAULT(UseSHA3Intrinsics)) {
UseSHA3Intrinsics = true;
}
- } else
-#endif
- if (UseSHA3Intrinsics) {
+ } else if (UseSHA3Intrinsics) {
warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA3Intrinsics, false);
}
@@ -1377,11 +1322,7 @@ void VM_Version::get_processor_features() {
max_vector_size = 64;
}
-#ifdef _LP64
int min_vector_size = 4; // We require MaxVectorSize to be at least 4 on 64bit
-#else
- int min_vector_size = 0;
-#endif
if (!FLAG_IS_DEFAULT(MaxVectorSize)) {
if (MaxVectorSize < min_vector_size) {
@@ -1405,7 +1346,7 @@ void VM_Version::get_processor_features() {
if (MaxVectorSize > 0) {
if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) {
tty->print_cr("State of YMM registers after signal handle:");
- int nreg = 2 LP64_ONLY(+2);
+ int nreg = 4;
const char* ymm_name[4] = {"0", "7", "8", "15"};
for (int i = 0; i < nreg; i++) {
tty->print("YMM%s:", ymm_name[i]);
@@ -1418,31 +1359,24 @@ void VM_Version::get_processor_features() {
}
#endif // COMPILER2 && ASSERT
-#ifdef _LP64
if ((supports_avx512ifma() && supports_avx512vlbw()) || supports_avxifma()) {
if (FLAG_IS_DEFAULT(UsePoly1305Intrinsics)) {
FLAG_SET_DEFAULT(UsePoly1305Intrinsics, true);
}
- } else
-#endif
- if (UsePoly1305Intrinsics) {
+ } else if (UsePoly1305Intrinsics) {
warning("Intrinsics for Poly1305 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UsePoly1305Intrinsics, false);
}
-#ifdef _LP64
if ((supports_avx512ifma() && supports_avx512vlbw()) || supports_avxifma()) {
if (FLAG_IS_DEFAULT(UseIntPolyIntrinsics)) {
FLAG_SET_DEFAULT(UseIntPolyIntrinsics, true);
}
- } else
-#endif
- if (UseIntPolyIntrinsics) {
+ } else if (UseIntPolyIntrinsics) {
warning("Intrinsics for Polynomial crypto functions not available on this CPU.");
FLAG_SET_DEFAULT(UseIntPolyIntrinsics, false);
}
-#ifdef _LP64
if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
UseMultiplyToLenIntrinsic = true;
}
@@ -1458,38 +1392,6 @@ void VM_Version::get_processor_features() {
if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
UseMontgomerySquareIntrinsic = true;
}
-#else
- if (UseMultiplyToLenIntrinsic) {
- if (!FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
- warning("multiplyToLen intrinsic is not available in 32-bit VM");
- }
- FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false);
- }
- if (UseMontgomeryMultiplyIntrinsic) {
- if (!FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
- warning("montgomeryMultiply intrinsic is not available in 32-bit VM");
- }
- FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, false);
- }
- if (UseMontgomerySquareIntrinsic) {
- if (!FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
- warning("montgomerySquare intrinsic is not available in 32-bit VM");
- }
- FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, false);
- }
- if (UseSquareToLenIntrinsic) {
- if (!FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
- warning("squareToLen intrinsic is not available in 32-bit VM");
- }
- FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, false);
- }
- if (UseMulAddIntrinsic) {
- if (!FLAG_IS_DEFAULT(UseMulAddIntrinsic)) {
- warning("mulAdd intrinsic is not available in 32-bit VM");
- }
- FLAG_SET_DEFAULT(UseMulAddIntrinsic, false);
- }
-#endif // _LP64
#endif // COMPILER2_OR_JVMCI
// On new cpus instructions which update whole XMM register should be used
@@ -1766,7 +1668,6 @@ void VM_Version::get_processor_features() {
}
#endif
-#ifdef _LP64
if (UseSSE42Intrinsics) {
if (FLAG_IS_DEFAULT(UseVectorizedMismatchIntrinsic)) {
UseVectorizedMismatchIntrinsic = true;
@@ -1783,20 +1684,6 @@ void VM_Version::get_processor_features() {
warning("vectorizedHashCode intrinsics are not available on this CPU");
FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, false);
}
-#else
- if (UseVectorizedMismatchIntrinsic) {
- if (!FLAG_IS_DEFAULT(UseVectorizedMismatchIntrinsic)) {
- warning("vectorizedMismatch intrinsic is not available in 32-bit VM");
- }
- FLAG_SET_DEFAULT(UseVectorizedMismatchIntrinsic, false);
- }
- if (UseVectorizedHashCodeIntrinsic) {
- if (!FLAG_IS_DEFAULT(UseVectorizedHashCodeIntrinsic)) {
- warning("vectorizedHashCode intrinsic is not available in 32-bit VM");
- }
- FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, false);
- }
-#endif // _LP64
// Use count leading zeros count instruction if available.
if (supports_lzcnt()) {
@@ -1945,7 +1832,6 @@ void VM_Version::get_processor_features() {
#endif
}
-#ifdef _LP64
// Prefetch settings
// Prefetch interval for gc copy/scan == 9 dcache lines. Derived from
@@ -1964,7 +1850,6 @@ void VM_Version::get_processor_features() {
if (FLAG_IS_DEFAULT(PrefetchScanIntervalInBytes)) {
FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, 576);
}
-#endif
if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
(cache_line_size > ContendedPaddingWidth))
@@ -2195,11 +2080,9 @@ int VM_Version::avx3_threshold() {
FLAG_IS_DEFAULT(AVX3Threshold)) ? 0 : AVX3Threshold;
}
-#if defined(_LP64)
void VM_Version::clear_apx_test_state() {
clear_apx_test_state_stub();
}
-#endif
static bool _vm_version_initialized = false;
@@ -2217,14 +2100,11 @@ void VM_Version::initialize() {
g.generate_get_cpu_info());
detect_virt_stub = CAST_TO_FN_PTR(detect_virt_stub_t,
g.generate_detect_virt());
-
-#if defined(_LP64)
clear_apx_test_state_stub = CAST_TO_FN_PTR(clear_apx_test_state_t,
g.clear_apx_test_state());
-#endif
get_processor_features();
- LP64_ONLY(Assembler::precompute_instructions();)
+ Assembler::precompute_instructions();
if (VM_Version::supports_hv()) { // Supports hypervisor
check_virtualizations();
@@ -2991,12 +2871,10 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const {
result |= CPU_CMOV;
if (std_cpuid1_edx.bits.clflush != 0)
result |= CPU_FLUSH;
-#ifdef _LP64
// clflush should always be available on x86_64
// if not we are in real trouble because we rely on it
// to flush the code cache.
assert ((result & CPU_FLUSH) != 0, "clflush should be available");
-#endif
if (std_cpuid1_edx.bits.fxsr != 0 || (is_amd_family() &&
ext_cpuid1_edx.bits.fxsr != 0))
result |= CPU_FXSR;
@@ -3168,7 +3046,7 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const {
bool VM_Version::os_supports_avx_vectors() {
bool retVal = false;
- int nreg = 2 LP64_ONLY(+2);
+ int nreg = 4;
if (supports_evex()) {
// Verify that OS save/restore all bits of EVEX registers
// during signal processing.
@@ -3324,11 +3202,7 @@ int VM_Version::allocate_prefetch_distance(bool use_watermark_prefetch) {
if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus
return 192;
} else if (use_watermark_prefetch) { // watermark prefetching on Core
-#ifdef _LP64
return 384;
-#else
- return 320;
-#endif
}
}
if (supports_sse2()) {
diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp
index cc5c6c1c639..7eb627c8714 100644
--- a/src/hotspot/cpu/x86/vm_version_x86.hpp
+++ b/src/hotspot/cpu/x86/vm_version_x86.hpp
@@ -642,7 +642,7 @@ public:
static void set_cpuinfo_cont_addr_apx(address pc) { _cpuinfo_cont_addr_apx = pc; }
static address cpuinfo_cont_addr_apx() { return _cpuinfo_cont_addr_apx; }
- LP64_ONLY(static void clear_apx_test_state());
+ static void clear_apx_test_state();
static void clean_cpuFeatures() { _features = 0; }
static void set_avx_cpuFeatures() { _features |= (CPU_SSE | CPU_SSE2 | CPU_AVX | CPU_VZEROUPPER ); }
@@ -839,12 +839,12 @@ public:
// x86_64 supports fast class initialization checks
static bool supports_fast_class_init_checks() {
- return LP64_ONLY(true) NOT_LP64(false); // not implemented on x86_32
+ return true;
}
// x86_64 supports secondary supers table
constexpr static bool supports_secondary_supers_table() {
- return LP64_ONLY(true) NOT_LP64(false); // not implemented on x86_32
+ return true;
}
constexpr static bool supports_stack_watermark_barrier() {
@@ -879,11 +879,7 @@ public:
// synchronize with other memory ops. so, it needs preceding
// and trailing StoreStore fences.
-#ifdef _LP64
static bool supports_clflush(); // Can't inline due to header file conflict
-#else
- static bool supports_clflush() { return ((_features & CPU_FLUSH) != 0); }
-#endif // _LP64
// Note: CPU_FLUSHOPT and CPU_CLWB bits should always be zero for 32-bit
static bool supports_clflushopt() { return ((_features & CPU_FLUSHOPT) != 0); }
diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad
index 078150c61fb..25cee7a3094 100644
--- a/src/hotspot/cpu/x86/x86_64.ad
+++ b/src/hotspot/cpu/x86/x86_64.ad
@@ -422,6 +422,18 @@ source_hpp %{
#include "peephole_x86_64.hpp"
+bool castLL_is_imm32(const Node* n);
+
+%}
+
+source %{
+
+bool castLL_is_imm32(const Node* n) {
+ assert(n->is_CastLL(), "must be a CastLL");
+ const TypeLong* t = n->bottom_type()->is_long();
+ return (t->_lo == min_jlong || Assembler::is_simm32(t->_lo)) && (t->_hi == max_jlong || Assembler::is_simm32(t->_hi));
+}
+
%}
// Register masks
@@ -1584,14 +1596,11 @@ uint MachUEPNode::size(PhaseRegAlloc* ra_) const
//=============================================================================
bool Matcher::supports_vector_calling_convention(void) {
- if (EnableVectorSupport && UseVectorStubs) {
- return true;
- }
- return false;
+ return EnableVectorSupport;
}
OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
- assert(EnableVectorSupport && UseVectorStubs, "sanity");
+ assert(EnableVectorSupport, "sanity");
int lo = XMM0_num;
int hi = XMM0b_num;
if (ideal_reg == Op_VecX) hi = XMM0d_num;
@@ -1838,14 +1847,14 @@ encode %{
%}
enc_class clear_avx %{
- debug_only(int off0 = __ offset());
+ DEBUG_ONLY(int off0 = __ offset());
if (generate_vzeroupper(Compile::current())) {
// Clear upper bits of YMM registers to avoid AVX <-> SSE transition penalty
// Clear upper bits of YMM registers when current compiled code uses
// wide vectors to avoid AVX <-> SSE transition penalty during call.
__ vzeroupper();
}
- debug_only(int off1 = __ offset());
+ DEBUG_ONLY(int off1 = __ offset());
assert(off1 - off0 == clear_avx_size(), "correct size prediction");
%}
@@ -7605,6 +7614,7 @@ instruct castPP(rRegP dst)
instruct castII(rRegI dst)
%{
+ predicate(VerifyConstraintCasts == 0);
match(Set dst (CastII dst));
size(0);
@@ -7614,8 +7624,22 @@ instruct castII(rRegI dst)
ins_pipe(empty);
%}
+instruct castII_checked(rRegI dst, rFlagsReg cr)
+%{
+ predicate(VerifyConstraintCasts > 0);
+ match(Set dst (CastII dst));
+
+ effect(KILL cr);
+ format %{ "# cast_checked_II $dst" %}
+ ins_encode %{
+ __ verify_int_in_range(_idx, bottom_type()->is_int(), $dst$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
instruct castLL(rRegL dst)
%{
+ predicate(VerifyConstraintCasts == 0);
match(Set dst (CastLL dst));
size(0);
@@ -7625,6 +7649,32 @@ instruct castLL(rRegL dst)
ins_pipe(empty);
%}
+instruct castLL_checked_L32(rRegL dst, rFlagsReg cr)
+%{
+ predicate(VerifyConstraintCasts > 0 && castLL_is_imm32(n));
+ match(Set dst (CastLL dst));
+
+ effect(KILL cr);
+ format %{ "# cast_checked_LL $dst" %}
+ ins_encode %{
+ __ verify_long_in_range(_idx, bottom_type()->is_long(), $dst$$Register, noreg);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct castLL_checked(rRegL dst, rRegL tmp, rFlagsReg cr)
+%{
+ predicate(VerifyConstraintCasts > 0 && !castLL_is_imm32(n));
+ match(Set dst (CastLL dst));
+
+ effect(KILL cr, TEMP tmp);
+ format %{ "# cast_checked_LL $dst\tusing $tmp as TEMP" %}
+ ins_encode %{
+ __ verify_long_in_range(_idx, bottom_type()->is_long(), $dst$$Register, $tmp$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
instruct castFF(regF dst)
%{
match(Set dst (CastFF dst));
diff --git a/src/hotspot/cpu/zero/vm_version_zero.cpp b/src/hotspot/cpu/zero/vm_version_zero.cpp
index e38561e19c5..3ce9227c193 100644
--- a/src/hotspot/cpu/zero/vm_version_zero.cpp
+++ b/src/hotspot/cpu/zero/vm_version_zero.cpp
@@ -151,6 +151,6 @@ void VM_Version::initialize_cpu_information(void) {
_no_of_threads = _no_of_cores;
_no_of_sockets = _no_of_cores;
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "Zero VM");
- snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _features_string);
+ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _cpu_info_string);
_initialized = true;
}
diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp
index 49dcebd0083..1bbaf29125d 100644
--- a/src/hotspot/os/aix/os_aix.cpp
+++ b/src/hotspot/os/aix/os_aix.cpp
@@ -132,8 +132,6 @@ extern "C" int getargs(procsinfo*, int, char*, int);
#define MAX_PATH (2 * K)
-// for timer info max values which include all bits
-#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
// for multipage initialization error analysis (in 'g_multipage_error')
#define ERROR_MP_OS_TOO_OLD 100
#define ERROR_MP_EXTSHM_ACTIVE 101
@@ -906,7 +904,7 @@ jlong os::javaTimeNanos() {
}
void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
- info_ptr->max_value = ALL_64_BITS;
+ info_ptr->max_value = all_bits_jlong;
// mread_real_time() is monotonic (see 'os::javaTimeNanos()')
info_ptr->may_skip_backward = false;
info_ptr->may_skip_forward = false;
@@ -2571,14 +2569,14 @@ jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
}
void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
- info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
+ info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits
info_ptr->may_skip_backward = false; // elapsed time not wall time
info_ptr->may_skip_forward = false; // elapsed time not wall time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
}
void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
- info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
+ info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits
info_ptr->may_skip_backward = false; // elapsed time not wall time
info_ptr->may_skip_forward = false; // elapsed time not wall time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
diff --git a/src/hotspot/os/aix/os_perf_aix.cpp b/src/hotspot/os/aix/os_perf_aix.cpp
index 0b008a197de..8444002b871 100644
--- a/src/hotspot/os/aix/os_perf_aix.cpp
+++ b/src/hotspot/os/aix/os_perf_aix.cpp
@@ -72,7 +72,7 @@ enum {
* Get info for requested PID from /proc//psinfo file
*/
static bool read_psinfo(const u_longlong_t& pid, psinfo_t& psinfo) {
- static size_t BUF_LENGTH = 32 + sizeof(u_longlong_t);
+ const size_t BUF_LENGTH = 32 + sizeof(u_longlong_t);
FILE* fp;
char buf[BUF_LENGTH];
@@ -118,7 +118,6 @@ static OSReturn get_lcpu_ticks(perfstat_id_t* lcpu_name, cpu_tick_store_t* ptick
* Return CPU load caused by the currently executing process (the jvm).
*/
static OSReturn get_jvm_load(double* jvm_uload, double* jvm_sload) {
- static clock_t ticks_per_sec = sysconf(_SC_CLK_TCK);
static u_longlong_t last_timebase = 0;
perfstat_process_t jvm_stats;
@@ -204,8 +203,6 @@ static bool populate_lcpu_names(int ncpus, perfstat_id_t* lcpu_names) {
* (Context Switches / Tick) * (Tick / s) = Context Switches per second
*/
static OSReturn perf_context_switch_rate(double* rate) {
- static clock_t ticks_per_sec = sysconf(_SC_CLK_TCK);
-
u_longlong_t ticks;
perfstat_cpu_total_t cpu_stats;
@@ -214,7 +211,7 @@ static OSReturn perf_context_switch_rate(double* rate) {
}
ticks = cpu_stats.user + cpu_stats.sys + cpu_stats.idle + cpu_stats.wait;
- *rate = (cpu_stats.pswitch / ticks) * ticks_per_sec;
+ *rate = (cpu_stats.pswitch / ticks) * os::Posix::clock_tics_per_second();
return OS_OK;
}
diff --git a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp
index 86549e878cb..861fda7a71d 100644
--- a/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp
+++ b/src/hotspot/os/bsd/gc/z/zPhysicalMemoryBacking_bsd.cpp
@@ -77,7 +77,7 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity)
_initialized(false) {
// Reserve address space for backing memory
- _base = (uintptr_t)os::reserve_memory(max_capacity, false, mtJavaHeap);
+ _base = (uintptr_t)os::reserve_memory(max_capacity, mtJavaHeap);
if (_base == 0) {
// Failed
ZInitialize::error("Failed to reserve address space for backing memory");
diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp
index 193c7cb0689..9a9954b3eb9 100644
--- a/src/hotspot/os/bsd/os_bsd.cpp
+++ b/src/hotspot/os/bsd/os_bsd.cpp
@@ -114,9 +114,6 @@
#define MAX_PATH (2 * K)
-// for timer info max values which include all bits
-#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
-
////////////////////////////////////////////////////////////////////////////////
// global variables
julong os::Bsd::_physical_memory = 0;
@@ -815,7 +812,7 @@ jlong os::javaTimeNanos() {
}
void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
- info_ptr->max_value = ALL_64_BITS;
+ info_ptr->max_value = all_bits_jlong;
info_ptr->may_skip_backward = false; // not subject to resetting or drifting
info_ptr->may_skip_forward = false; // not subject to resetting or drifting
info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time
@@ -2423,14 +2420,14 @@ jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
- info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
+ info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits
info_ptr->may_skip_backward = false; // elapsed time not wall time
info_ptr->may_skip_forward = false; // elapsed time not wall time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
}
void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
- info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
+ info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits
info_ptr->may_skip_backward = false; // elapsed time not wall time
info_ptr->may_skip_forward = false; // elapsed time not wall time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp
index 1afece719cb..9bd45b0fec8 100644
--- a/src/hotspot/os/linux/os_linux.cpp
+++ b/src/hotspot/os/linux/os_linux.cpp
@@ -139,9 +139,6 @@
#define MAX_PATH (2 * K)
-// for timer info max values which include all bits
-#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
-
#ifdef MUSL_LIBC
// dlvsym is not a part of POSIX
// and musl libc doesn't implement it.
@@ -213,8 +210,6 @@ typedef int (*malloc_info_func_t)(int options, FILE *stream);
static malloc_info_func_t g_malloc_info = nullptr;
#endif // __GLIBC__
-static int clock_tics_per_sec = 100;
-
// If the VM might have been created on the primordial thread, we need to resolve the
// primordial thread stack bounds and check if the current thread might be the
// primordial thread in places. If we know that the primordial thread is never used,
@@ -1667,7 +1662,7 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
}
ThreadInVMfromNative tiv(jt);
- debug_only(VMNativeEntryWrapper vew;)
+ DEBUG_ONLY(VMNativeEntryWrapper vew;)
VM_LinuxDllLoad op(filename, ebuf, ebuflen);
VMThread::execute(&op);
@@ -4381,8 +4376,6 @@ static void check_pax(void) {
// this is called _before_ most of the global arguments have been parsed
void os::init(void) {
char dummy; // used to get a guess on initial stack address
-
- clock_tics_per_sec = checked_cast(sysconf(_SC_CLK_TCK));
int sys_pg_size = checked_cast(sysconf(_SC_PAGESIZE));
if (sys_pg_size < 0) {
fatal("os_linux.cpp: os::init: sysconf failed (%s)",
@@ -4575,7 +4568,7 @@ static void workaround_expand_exec_shield_cs_limit() {
*/
char* hint = (char*)(os::Linux::initial_thread_stack_bottom() -
(StackOverflow::stack_guard_zone_size() + page_size));
- char* codebuf = os::attempt_reserve_memory_at(hint, page_size, false, mtThread);
+ char* codebuf = os::attempt_reserve_memory_at(hint, page_size, mtThread);
if (codebuf == nullptr) {
// JDK-8197429: There may be a stack gap of one megabyte between
@@ -4583,7 +4576,7 @@ static void workaround_expand_exec_shield_cs_limit() {
// Linux kernel workaround for CVE-2017-1000364. If we failed to
// map our codebuf, try again at an address one megabyte lower.
hint -= 1 * M;
- codebuf = os::attempt_reserve_memory_at(hint, page_size, false, mtThread);
+ codebuf = os::attempt_reserve_memory_at(hint, page_size, mtThread);
}
if ((codebuf == nullptr) || (!os::commit_memory(codebuf, page_size, true))) {
@@ -5135,21 +5128,21 @@ static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
&user_time, &sys_time);
if (count != 13) return -1;
if (user_sys_cpu_time) {
- return ((jlong)sys_time + (jlong)user_time) * (1000000000 / clock_tics_per_sec);
+ return ((jlong)sys_time + (jlong)user_time) * (1000000000 / os::Posix::clock_tics_per_second());
} else {
- return (jlong)user_time * (1000000000 / clock_tics_per_sec);
+ return (jlong)user_time * (1000000000 / os::Posix::clock_tics_per_second());
}
}
void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
- info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
+ info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits
info_ptr->may_skip_backward = false; // elapsed time not wall time
info_ptr->may_skip_forward = false; // elapsed time not wall time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
}
void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
- info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
+ info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits
info_ptr->may_skip_backward = false; // elapsed time not wall time
info_ptr->may_skip_forward = false; // elapsed time not wall time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp
index df084ae6898..1da0eb219b6 100644
--- a/src/hotspot/os/posix/os_posix.cpp
+++ b/src/hotspot/os/posix/os_posix.cpp
@@ -492,9 +492,9 @@ static char* chop_extra_memory(size_t size, size_t alignment, char* extra_base,
// Multiple threads can race in this code, and can remap over each other with MAP_FIXED,
// so on posix, unmap the section at the start and at the end of the chunk that we mapped
// rather than unmapping and remapping the whole chunk to get requested alignment.
-char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) {
+char* os::reserve_memory_aligned(size_t size, size_t alignment, MemTag mem_tag, bool exec) {
size_t extra_size = calculate_aligned_extra_size(size, alignment);
- char* extra_base = os::reserve_memory(extra_size, exec);
+ char* extra_base = os::reserve_memory(extra_size, mem_tag, exec);
if (extra_base == nullptr) {
return nullptr;
}
@@ -1326,6 +1326,10 @@ void os::Posix::init_2(void) {
_use_clock_monotonic_condattr ? "CLOCK_MONOTONIC" : "the default clock");
}
+int os::Posix::clock_tics_per_second() {
+ return clock_tics_per_sec;
+}
+
// Utility to convert the given timeout to an absolute timespec
// (based on the appropriate clock) to use with pthread_cond_timewait,
// and sem_timedwait().
@@ -1473,12 +1477,9 @@ jlong os::javaTimeNanos() {
return result;
}
-// for timer info max values which include all bits
-#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
-
void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
// CLOCK_MONOTONIC - amount of time since some arbitrary point in the past
- info_ptr->max_value = ALL_64_BITS;
+ info_ptr->max_value = all_bits_jlong;
info_ptr->may_skip_backward = false; // not subject to resetting or drifting
info_ptr->may_skip_forward = false; // not subject to resetting or drifting
info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time
diff --git a/src/hotspot/os/posix/os_posix.hpp b/src/hotspot/os/posix/os_posix.hpp
index 248a30d04ad..5c3b1f35bd1 100644
--- a/src/hotspot/os/posix/os_posix.hpp
+++ b/src/hotspot/os/posix/os_posix.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2025, 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
@@ -91,6 +91,9 @@ public:
static void to_RTC_abstime(timespec* abstime, int64_t millis);
+ // clock ticks per second of the system
+ static int clock_tics_per_second();
+
static bool handle_stack_overflow(JavaThread* thread, address addr, address pc,
const void* ucVoid,
address* stub);
diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp
index 4d6fc1e4b8c..cbbecea3a6a 100644
--- a/src/hotspot/os/posix/perfMemory_posix.cpp
+++ b/src/hotspot/os/posix/perfMemory_posix.cpp
@@ -64,7 +64,7 @@ static char* backing_store_file_name = nullptr; // name of the backing store
static char* create_standard_memory(size_t size) {
// allocate an aligned chuck of memory
- char* mapAddress = os::reserve_memory(size);
+ char* mapAddress = os::reserve_memory(size, mtInternal);
if (mapAddress == nullptr) {
return nullptr;
diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp
index 555ac832aae..e900d5695ae 100644
--- a/src/hotspot/os/posix/signals_posix.cpp
+++ b/src/hotspot/os/posix/signals_posix.cpp
@@ -147,7 +147,7 @@ public:
};
-debug_only(static bool signal_sets_initialized = false);
+DEBUG_ONLY(static bool signal_sets_initialized = false);
static sigset_t unblocked_sigs, vm_sigs, preinstalled_sigs;
// Our own signal handlers should never ever get replaced by a third party one.
@@ -1547,7 +1547,7 @@ static void signal_sets_init() {
if (!ReduceSignalUsage) {
sigaddset(&vm_sigs, BREAK_SIGNAL);
}
- debug_only(signal_sets_initialized = true);
+ DEBUG_ONLY(signal_sets_initialized = true);
}
// These are signals that are unblocked while a thread is running Java.
diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp
index 959a0616834..c6107b95259 100644
--- a/src/hotspot/os/windows/os_windows.cpp
+++ b/src/hotspot/os/windows/os_windows.cpp
@@ -112,9 +112,6 @@
#include
#include
-// for timer info max values which include all bits
-#define ALL_64_BITS CONST64(-1)
-
// For DLL loading/load error detection
// Values of PE COFF
#define IMAGE_FILE_PTR_TO_SIGNATURE 0x3c
@@ -1225,16 +1222,16 @@ void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
if (freq < NANOSECS_PER_SEC) {
// the performance counter is 64 bits and we will
// be multiplying it -- so no wrap in 64 bits
- info_ptr->max_value = ALL_64_BITS;
+ info_ptr->max_value = all_bits_jlong;
} else if (freq > NANOSECS_PER_SEC) {
// use the max value the counter can reach to
// determine the max value which could be returned
- julong max_counter = (julong)ALL_64_BITS;
+ julong max_counter = (julong)all_bits_jlong;
info_ptr->max_value = (jlong)(max_counter / (freq / NANOSECS_PER_SEC));
} else {
// the performance counter is 64 bits and we will
// be using it directly -- so no wrap in 64 bits
- info_ptr->max_value = ALL_64_BITS;
+ info_ptr->max_value = all_bits_jlong;
}
// using a counter, so no skipping
@@ -3020,7 +3017,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags,
PAGE_READWRITE);
// If reservation failed, return null
if (p_buf == nullptr) return nullptr;
- MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC);
+ MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC, mtNone);
os::release_memory(p_buf, bytes + chunk_size);
// we still need to round up to a page boundary (in case we are using large pages)
@@ -3081,7 +3078,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags,
// need to create a dummy 'reserve' record to match
// the release.
MemTracker::record_virtual_memory_reserve((address)p_buf,
- bytes_to_release, CALLER_PC);
+ bytes_to_release, CALLER_PC, mtNone);
os::release_memory(p_buf, bytes_to_release);
}
#ifdef ASSERT
@@ -3099,9 +3096,9 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags,
// Although the memory is allocated individually, it is returned as one.
// NMT records it as one block.
if ((flags & MEM_COMMIT) != 0) {
- MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC);
+ MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC, mtNone);
} else {
- MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC);
+ MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC, mtNone);
}
// made it this far, success
@@ -3241,7 +3238,7 @@ char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, in
// Multiple threads can race in this code but it's not possible to unmap small sections of
// virtual space to get requested alignment, like posix-like os's.
// Windows prevents multiple thread from remapping over each other so this loop is thread-safe.
-static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MemTag mem_tag = mtNone) {
+static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MemTag mem_tag) {
assert(is_aligned(alignment, os::vm_allocation_granularity()),
"Alignment must be a multiple of allocation granularity (page size)");
assert(is_aligned(size, os::vm_allocation_granularity()),
@@ -3255,7 +3252,7 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi
for (int attempt = 0; attempt < max_attempts && aligned_base == nullptr; attempt ++) {
char* extra_base = file_desc != -1 ? os::map_memory_to_file(extra_size, file_desc, mem_tag) :
- os::reserve_memory(extra_size, false, mem_tag);
+ os::reserve_memory(extra_size, mem_tag);
if (extra_base == nullptr) {
return nullptr;
}
@@ -3272,7 +3269,7 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi
// Attempt to map, into the just vacated space, the slightly smaller aligned area.
// Which may fail, hence the loop.
aligned_base = file_desc != -1 ? os::attempt_map_memory_to_file_at(aligned_base, size, file_desc, mem_tag) :
- os::attempt_reserve_memory_at(aligned_base, size, false, mem_tag);
+ os::attempt_reserve_memory_at(aligned_base, size, mem_tag);
}
assert(aligned_base != nullptr,
@@ -3281,9 +3278,9 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi
return aligned_base;
}
-char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) {
+char* os::reserve_memory_aligned(size_t size, size_t alignment, MemTag mem_tag, bool exec) {
// exec can be ignored
- return map_or_reserve_memory_aligned(size, alignment, -1 /* file_desc */);
+ return map_or_reserve_memory_aligned(size, alignment, -1/* file_desc */, mem_tag);
}
char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag) {
@@ -4813,14 +4810,14 @@ jlong os::thread_cpu_time(Thread* thread, bool user_sys_cpu_time) {
}
void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
- info_ptr->max_value = ALL_64_BITS; // the max value -- all 64 bits
+ info_ptr->max_value = all_bits_jlong; // the max value -- all 64 bits
info_ptr->may_skip_backward = false; // GetThreadTimes returns absolute time
info_ptr->may_skip_forward = false; // GetThreadTimes returns absolute time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
}
void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
- info_ptr->max_value = ALL_64_BITS; // the max value -- all 64 bits
+ info_ptr->max_value = all_bits_jlong; // the max value -- all 64 bits
info_ptr->may_skip_backward = false; // GetThreadTimes returns absolute time
info_ptr->may_skip_forward = false; // GetThreadTimes returns absolute time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
@@ -5188,7 +5185,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
}
// Record virtual memory allocation
- MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC);
+ MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC, mtNone);
DWORD bytes_read;
OVERLAPPED overlapped;
diff --git a/src/hotspot/os/windows/perfMemory_windows.cpp b/src/hotspot/os/windows/perfMemory_windows.cpp
index dda0acde793..322b844f413 100644
--- a/src/hotspot/os/windows/perfMemory_windows.cpp
+++ b/src/hotspot/os/windows/perfMemory_windows.cpp
@@ -54,7 +54,7 @@ typedef BOOL (WINAPI *SetSecurityDescriptorControlFnPtr)(
static char* create_standard_memory(size_t size) {
// allocate an aligned chuck of memory
- char* mapAddress = os::reserve_memory(size);
+ char* mapAddress = os::reserve_memory(size, mtInternal);
if (mapAddress == nullptr) {
return nullptr;
diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp
index dabc69403f3..9725c6cd6c0 100644
--- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp
+++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp
@@ -75,6 +75,14 @@
#define HWCAP_PACA (1 << 30)
#endif
+#ifndef HWCAP_FPHP
+#define HWCAP_FPHP (1<<9)
+#endif
+
+#ifndef HWCAP_ASIMDHP
+#define HWCAP_ASIMDHP (1<<10)
+#endif
+
#ifndef HWCAP2_SVE2
#define HWCAP2_SVE2 (1 << 1)
#endif
@@ -119,6 +127,8 @@ void VM_Version::get_os_cpu_info() {
static_assert(CPU_SHA512 == HWCAP_SHA512, "Flag CPU_SHA512 must follow Linux HWCAP");
static_assert(CPU_SVE == HWCAP_SVE, "Flag CPU_SVE must follow Linux HWCAP");
static_assert(CPU_PACA == HWCAP_PACA, "Flag CPU_PACA must follow Linux HWCAP");
+ static_assert(CPU_FPHP == HWCAP_FPHP, "Flag CPU_FPHP must follow Linux HWCAP");
+ static_assert(CPU_ASIMDHP == HWCAP_ASIMDHP, "Flag CPU_ASIMDHP must follow Linux HWCAP");
_features = auxv & (
HWCAP_FP |
HWCAP_ASIMD |
@@ -133,7 +143,9 @@ void VM_Version::get_os_cpu_info() {
HWCAP_SHA3 |
HWCAP_SHA512 |
HWCAP_SVE |
- HWCAP_PACA);
+ HWCAP_PACA |
+ HWCAP_FPHP |
+ HWCAP_ASIMDHP);
if (auxv2 & HWCAP2_SVE2) _features |= CPU_SVE2;
if (auxv2 & HWCAP2_SVEBITPERM) _features |= CPU_SVEBITPERM;
diff --git a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp
index b6095c279cb..506c78cacca 100644
--- a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp
+++ b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp
@@ -129,6 +129,9 @@ void VM_Version::setup_cpu_available_features() {
snprintf(buf, sizeof(buf)/2, "%s ", uarch);
}
os::free((void*) uarch);
+
+ int features_offset = strnlen(buf, sizeof(buf));
+
strcat(buf, "rv64");
int i = 0;
while (_feature_list[i] != nullptr) {
@@ -191,7 +194,9 @@ void VM_Version::setup_cpu_available_features() {
}
}
- _features_string = os::strdup(buf);
+ _cpu_info_string = os::strdup(buf);
+
+ _features_string = _cpu_info_string + features_offset;
}
void VM_Version::os_aux_features() {
diff --git a/src/hotspot/share/asm/assembler.hpp b/src/hotspot/share/asm/assembler.hpp
index 9abd3eb7171..961b5fab700 100644
--- a/src/hotspot/share/asm/assembler.hpp
+++ b/src/hotspot/share/asm/assembler.hpp
@@ -73,7 +73,7 @@ class Label;
*/
class Label {
private:
- enum { PatchCacheSize = 4 debug_only( +4 ) };
+ enum { PatchCacheSize = 4 DEBUG_ONLY( +4 ) };
// _loc encodes both the binding state (via its sign)
// and the binding locator (via its value) of a label.
diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp
index 917569e2be6..fc8f72a881e 100644
--- a/src/hotspot/share/asm/codeBuffer.cpp
+++ b/src/hotspot/share/asm/codeBuffer.cpp
@@ -92,7 +92,7 @@ CodeBuffer::CodeBuffer(CodeBlob* blob) DEBUG_ONLY(: Scrubber(this, sizeof(*this)
// Provide code buffer with meaningful name
initialize_misc(blob->name());
initialize(blob->content_begin(), blob->content_size());
- debug_only(verify_section_allocation();)
+ DEBUG_ONLY(verify_section_allocation();)
}
void CodeBuffer::initialize(csize_t code_size, csize_t locs_size) {
@@ -120,7 +120,7 @@ void CodeBuffer::initialize(csize_t code_size, csize_t locs_size) {
_insts.initialize_locs(locs_size / sizeof(relocInfo));
}
- debug_only(verify_section_allocation();)
+ DEBUG_ONLY(verify_section_allocation();)
}
@@ -494,7 +494,7 @@ void CodeBuffer::compute_final_layout(CodeBuffer* dest) const {
prev_cs = cs;
}
- debug_only(dest_cs->_start = nullptr); // defeat double-initialization assert
+ DEBUG_ONLY(dest_cs->_start = nullptr); // defeat double-initialization assert
dest_cs->initialize(buf+buf_offset, csize);
dest_cs->set_end(buf+buf_offset+csize);
assert(dest_cs->is_allocated(), "must always be allocated");
@@ -505,7 +505,7 @@ void CodeBuffer::compute_final_layout(CodeBuffer* dest) const {
// Done calculating sections; did it come out to the right end?
assert(buf_offset == total_content_size(), "sanity");
- debug_only(dest->verify_section_allocation();)
+ DEBUG_ONLY(dest->verify_section_allocation();)
}
// Append an oop reference that keeps the class alive.
@@ -939,11 +939,11 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) {
cb.set_blob(nullptr);
// Zap the old code buffer contents, to avoid mistakenly using them.
- debug_only(Copy::fill_to_bytes(bxp->_total_start, bxp->_total_size,
+ DEBUG_ONLY(Copy::fill_to_bytes(bxp->_total_start, bxp->_total_size,
badCodeHeapFreeVal);)
// Make certain that the new sections are all snugly inside the new blob.
- debug_only(verify_section_allocation();)
+ DEBUG_ONLY(verify_section_allocation();)
#ifndef PRODUCT
_decode_begin = nullptr; // sanity
@@ -1042,6 +1042,9 @@ void CodeBuffer::shared_stub_to_interp_for(ciMethod* callee, csize_t call_offset
#ifndef PRODUCT
void CodeBuffer::block_comment(ptrdiff_t offset, const char* comment) {
+ if (insts()->scratch_emit()) {
+ return;
+ }
if (_collect_comments) {
const char* str = _asm_remarks.insert(offset, comment);
postcond(str != comment);
@@ -1049,6 +1052,9 @@ void CodeBuffer::block_comment(ptrdiff_t offset, const char* comment) {
}
const char* CodeBuffer::code_string(const char* str) {
+ if (insts()->scratch_emit()) {
+ return str;
+ }
const char* tmp = _dbg_strings.insert(str);
postcond(tmp != str);
return tmp;
diff --git a/src/hotspot/share/asm/codeBuffer.hpp b/src/hotspot/share/asm/codeBuffer.hpp
index f855d41b181..b38cc74cc3b 100644
--- a/src/hotspot/share/asm/codeBuffer.hpp
+++ b/src/hotspot/share/asm/codeBuffer.hpp
@@ -121,8 +121,8 @@ class CodeSection {
_locs_own = false;
_scratch_emit = false;
_skipped_instructions_size = 0;
- debug_only(_index = -1);
- debug_only(_outer = (CodeBuffer*)badAddress);
+ DEBUG_ONLY(_index = -1);
+ DEBUG_ONLY(_outer = (CodeBuffer*)badAddress);
}
void initialize_outer(CodeBuffer* outer, int8_t index) {
@@ -535,7 +535,7 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) {
assert(code_start != nullptr, "sanity");
initialize_misc("static buffer");
initialize(code_start, code_size);
- debug_only(verify_section_allocation();)
+ DEBUG_ONLY(verify_section_allocation();)
}
// (2) CodeBuffer referring to pre-allocated CodeBlob.
diff --git a/src/hotspot/share/c1/c1_FrameMap.hpp b/src/hotspot/share/c1/c1_FrameMap.hpp
index 4e4fde0cb4a..f10c4d3f226 100644
--- a/src/hotspot/share/c1/c1_FrameMap.hpp
+++ b/src/hotspot/share/c1/c1_FrameMap.hpp
@@ -109,19 +109,19 @@ class FrameMap : public CompilationResourceObj {
static Register cpu_rnr2reg (int rnr) {
assert(_init_done, "tables not initialized");
- debug_only(cpu_range_check(rnr);)
+ DEBUG_ONLY(cpu_range_check(rnr);)
return _cpu_rnr2reg[rnr];
}
static int cpu_reg2rnr (Register reg) {
assert(_init_done, "tables not initialized");
- debug_only(cpu_range_check(reg->encoding());)
+ DEBUG_ONLY(cpu_range_check(reg->encoding());)
return _cpu_reg2rnr[reg->encoding()];
}
static void map_register(int rnr, Register reg) {
- debug_only(cpu_range_check(rnr);)
- debug_only(cpu_range_check(reg->encoding());)
+ DEBUG_ONLY(cpu_range_check(rnr);)
+ DEBUG_ONLY(cpu_range_check(reg->encoding());)
_cpu_rnr2reg[rnr] = reg;
_cpu_reg2rnr[reg->encoding()] = rnr;
}
diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp
index 9d4b35024ed..0f87a90a417 100644
--- a/src/hotspot/share/c1/c1_Runtime1.cpp
+++ b/src/hotspot/share/c1/c1_Runtime1.cpp
@@ -1363,7 +1363,7 @@ int Runtime1::move_klass_patching(JavaThread* current) {
//
// NOTE: we are still in Java
//
- debug_only(NoHandleMark nhm;)
+ DEBUG_ONLY(NoHandleMark nhm;)
{
// Enter VM mode
ResetNoHandleMark rnhm;
@@ -1380,7 +1380,7 @@ int Runtime1::move_mirror_patching(JavaThread* current) {
//
// NOTE: we are still in Java
//
- debug_only(NoHandleMark nhm;)
+ DEBUG_ONLY(NoHandleMark nhm;)
{
// Enter VM mode
ResetNoHandleMark rnhm;
@@ -1397,7 +1397,7 @@ int Runtime1::move_appendix_patching(JavaThread* current) {
//
// NOTE: we are still in Java
//
- debug_only(NoHandleMark nhm;)
+ DEBUG_ONLY(NoHandleMark nhm;)
{
// Enter VM mode
ResetNoHandleMark rnhm;
diff --git a/src/hotspot/share/cds/aotArtifactFinder.cpp b/src/hotspot/share/cds/aotArtifactFinder.cpp
index 65eb06ca7f0..d87b501150b 100644
--- a/src/hotspot/share/cds/aotArtifactFinder.cpp
+++ b/src/hotspot/share/cds/aotArtifactFinder.cpp
@@ -25,6 +25,7 @@
#include "cds/aotClassLinker.hpp"
#include "cds/aotArtifactFinder.hpp"
#include "cds/aotClassInitializer.hpp"
+#include "cds/aotReferenceObjSupport.hpp"
#include "cds/dumpTimeClassInfo.inline.hpp"
#include "cds/heapShared.hpp"
#include "cds/lambdaProxyClassDictionary.hpp"
@@ -73,6 +74,7 @@ void AOTArtifactFinder::find_artifacts() {
// Note, if a class is not excluded, it does NOT mean it will be automatically included
// into the AOT cache -- that will be decided by the code below.
SystemDictionaryShared::finish_exclusion_checks();
+ AOTReferenceObjSupport::init_keep_alive_objs_table();
start_scanning_for_oops();
diff --git a/src/hotspot/share/cds/aotClassInitializer.cpp b/src/hotspot/share/cds/aotClassInitializer.cpp
index 297f8109eb4..be7e1f31d8a 100644
--- a/src/hotspot/share/cds/aotClassInitializer.cpp
+++ b/src/hotspot/share/cds/aotClassInitializer.cpp
@@ -338,7 +338,8 @@ bool AOTClassInitializer::can_archive_initialized_mirror(InstanceKlass* ik) {
bool AOTClassInitializer::is_runtime_setup_required(InstanceKlass* ik) {
return ik == vmClasses::Class_klass() ||
ik == vmClasses::internal_Unsafe_klass() ||
- ik == vmClasses::ConcurrentHashMap_klass();
+ ik == vmClasses::ConcurrentHashMap_klass() ||
+ ik == vmClasses::Reference_klass();
}
void AOTClassInitializer::call_runtime_setup(JavaThread* current, InstanceKlass* ik) {
diff --git a/src/hotspot/share/cds/aotReferenceObjSupport.cpp b/src/hotspot/share/cds/aotReferenceObjSupport.cpp
new file mode 100644
index 00000000000..e948a6cefa3
--- /dev/null
+++ b/src/hotspot/share/cds/aotReferenceObjSupport.cpp
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2025, 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 "cds/aotReferenceObjSupport.hpp"
+#include "cds/heapShared.hpp"
+#include "classfile/javaClasses.hpp"
+#include "classfile/symbolTable.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "logging/log.hpp"
+#include "memory/resourceArea.hpp"
+#include "memory/universe.hpp"
+#include "oops/oop.inline.hpp"
+#include "oops/oopHandle.inline.hpp"
+#include "runtime/fieldDescriptor.inline.hpp"
+#include "runtime/javaCalls.hpp"
+#include "utilities/resourceHash.hpp"
+
+// Handling of java.lang.ref.Reference objects in the AOT cache
+// ============================================================
+//
+// When AOTArtifactFinder finds an oop which is a instance of java.lang.ref.Reference:
+//
+// - We check if the oop is eligible to be stored in the AOT cache. If not, the AOT cache
+// creation fails -- see AOTReferenceObjSupport::check_if_ref_obj()
+//
+// - Otherwise, we store the oop into the AOT cache, but we unconditionally reset its
+// "next" and "discovered" fields to null. Otherwise, if AOTArtifactFinder follows these
+// fields, it may found unrelated objects that we don't intend to cache.
+//
+// Eligibility
+// ===========
+//
+// [1] A reference that does not require special clean up (i.e., Reference::queue == ReferenceQueue.NULL_QUEUE)
+// is eligible.
+//
+// [2] A reference that REQUIRE specials clean up (i.e., Reference::queue != ReferenceQueue.NULL_QUEUE)
+// is eligible ONLY if its referent is not null.
+//
+// As of this version, the only oops in group [2] that can be found by AOTArtifactFinder are
+// the keys used by ReferencedKeyMap in the implementation of MethodType::internTable.
+// stabilize_cached_reference_objects() ensures that all keys found by AOTArtifactFinder are eligible.
+//
+// The purpose of the error check in check_if_ref_obj() is to guard against changes in the JDK core
+// libs that might introduce new types of oops in group [2] into the AOT cache.
+//
+// Reasons for the eligibility restrictions
+// ========================================
+//
+// Reference handling is complex. In this version, we implement only enough functionality to support
+// the use of Weak/Soft references used by java.lang.invoke.
+//
+// We intend to evolve the implementation in the future by
+// -- implementing more assemblySetup() operations for other use cases, and/or
+// -- relaxing the eligibility restrictions.
+//
+//
+// null referents for group [1]
+// ============================
+//
+// Any cached reference R1 of group [1] is allowed to have a null referent.
+// This can happen in the following situations:
+// (a) R1.clear() was called by Java code during the assembly phase.
+// (b) The referent has been collected, and R1 is in the "pending" state.
+// In case (b), the "next" and "discovered" fields of the cached copy of R1 will
+// be set to null. During the production run:
+// - It would appear to the Java program as if immediately during VM start-up, the referent
+// was collected and ReferenceThread completed processing of R1.
+// - It would appear to the GC as if immediately during VM start-up, the Java program called
+// R1.clear().
+
+#if INCLUDE_CDS_JAVA_HEAP
+
+class KeepAliveObjectsTable : public ResourceHashtable {};
+
+static KeepAliveObjectsTable* _keep_alive_objs_table;
+static OopHandle _keep_alive_objs_array;
+static OopHandle _null_queue;
+
+bool AOTReferenceObjSupport::is_enabled() {
+ // For simplicity, AOTReferenceObjSupport is enabled only when dumping method handles.
+ // Otherwise we won't see Reference objects in the AOT cache. Let's be conservative now.
+ return CDSConfig::is_dumping_method_handles();
+}
+
+void AOTReferenceObjSupport::initialize(TRAPS) {
+ if (!AOTReferenceObjSupport::is_enabled()) {
+ return;
+ }
+
+ TempNewSymbol class_name = SymbolTable::new_symbol("java/lang/ref/ReferenceQueue");
+ Klass* k = SystemDictionary::resolve_or_fail(class_name, true, CHECK);
+ InstanceKlass* ik = InstanceKlass::cast(k);
+ ik->initialize(CHECK);
+
+ TempNewSymbol field_name = SymbolTable::new_symbol("NULL_QUEUE");
+ fieldDescriptor fd;
+ bool found = ik->find_local_field(field_name, vmSymbols::referencequeue_signature(), &fd);
+ precond(found);
+ precond(fd.is_static());
+
+ _null_queue = OopHandle(Universe::vm_global(), ik->java_mirror()->obj_field(fd.offset()));
+}
+
+// Ensure that all group [2] references found by AOTArtifactFinder are eligible.
+void AOTReferenceObjSupport::stabilize_cached_reference_objects(TRAPS) {
+ if (AOTReferenceObjSupport::is_enabled()) {
+ // This assert means that the MethodType and MethodTypeForm tables won't be
+ // updated concurrently, so we can remove GC'ed entries ...
+ assert(CDSConfig::allow_only_single_java_thread(), "Required");
+
+ {
+ TempNewSymbol method_name = SymbolTable::new_symbol("assemblySetup");
+ JavaValue result(T_VOID);
+ JavaCalls::call_static(&result, vmClasses::MethodType_klass(),
+ method_name,
+ vmSymbols::void_method_signature(),
+ CHECK);
+ }
+
+ {
+ Symbol* cds_name = vmSymbols::jdk_internal_misc_CDS();
+ Klass* cds_klass = SystemDictionary::resolve_or_fail(cds_name, true /*throw error*/, CHECK);
+ TempNewSymbol method_name = SymbolTable::new_symbol("getKeepAliveObjects");
+ TempNewSymbol method_sig = SymbolTable::new_symbol("()[Ljava/lang/Object;");
+ JavaValue result(T_OBJECT);
+ JavaCalls::call_static(&result, cds_klass, method_name, method_sig, CHECK);
+
+ _keep_alive_objs_array = OopHandle(Universe::vm_global(), result.get_oop());
+ }
+ }
+}
+
+void AOTReferenceObjSupport::init_keep_alive_objs_table() {
+ assert_at_safepoint(); // _keep_alive_objs_table uses raw oops
+ oop a = _keep_alive_objs_array.resolve();
+ if (a != nullptr) {
+ precond(a->is_objArray());
+ precond(AOTReferenceObjSupport::is_enabled());
+ objArrayOop array = objArrayOop(a);
+
+ _keep_alive_objs_table = new (mtClass)KeepAliveObjectsTable();
+ for (int i = 0; i < array->length(); i++) {
+ oop obj = array->obj_at(i);
+ _keep_alive_objs_table->put(obj, true); // The array may have duplicated entries but that's OK.
+ }
+ }
+}
+
+// Returns true IFF obj is an instance of java.lang.ref.Reference. If so, perform extra eligibility checks.
+bool AOTReferenceObjSupport::check_if_ref_obj(oop obj) {
+ // We have a single Java thread. This means java.lang.ref.Reference$ReferenceHandler thread
+ // is not running. Otherwise the checks for next/discovered may not work.
+ precond(CDSConfig::allow_only_single_java_thread());
+ assert_at_safepoint(); // _keep_alive_objs_table uses raw oops
+
+ if (obj->klass()->is_subclass_of(vmClasses::Reference_klass())) {
+ precond(AOTReferenceObjSupport::is_enabled());
+ precond(JavaClasses::is_supported_for_archiving(obj));
+ precond(_keep_alive_objs_table != nullptr);
+
+ // GC needs to know about this load, It will keep referent alive until the current safepoint ends.
+ oop referent = HeapAccess::oop_load_at(obj, java_lang_ref_Reference::referent_offset());
+
+ oop queue = obj->obj_field(java_lang_ref_Reference::queue_offset());
+ oop next = java_lang_ref_Reference::next(obj);
+ oop discovered = java_lang_ref_Reference::discovered(obj);
+ bool needs_special_cleanup = (queue != _null_queue.resolve());
+
+ // If you see the errors below, you probably modified the implementation of java.lang.invoke.
+ // Please check the comments at the top of this file.
+ if (needs_special_cleanup && (referent == nullptr || !_keep_alive_objs_table->contains(referent))) {
+ ResourceMark rm;
+
+ log_error(cds, heap)("Cannot archive reference object " PTR_FORMAT " of class %s",
+ p2i(obj), obj->klass()->external_name());
+ log_error(cds, heap)("referent = " PTR_FORMAT
+ ", queue = " PTR_FORMAT
+ ", next = " PTR_FORMAT
+ ", discovered = " PTR_FORMAT,
+ p2i(referent), p2i(queue), p2i(next), p2i(discovered));
+ log_error(cds, heap)("This object requires special clean up as its queue is not ReferenceQueue::N" "ULL ("
+ PTR_FORMAT ")", p2i(_null_queue.resolve()));
+ log_error(cds, heap)("%s", (referent == nullptr) ?
+ "referent cannot be null" : "referent is not registered with CDS.keepAlive()");
+ HeapShared::debug_trace();
+ MetaspaceShared::unrecoverable_writing_error();
+ }
+
+ if (log_is_enabled(Info, cds, ref)) {
+ ResourceMark rm;
+ log_info(cds, ref)("Reference obj:"
+ " r=" PTR_FORMAT
+ " q=" PTR_FORMAT
+ " n=" PTR_FORMAT
+ " d=" PTR_FORMAT
+ " %s",
+ p2i(referent),
+ p2i(queue),
+ p2i(next),
+ p2i(discovered),
+ obj->klass()->external_name());
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool AOTReferenceObjSupport::skip_field(int field_offset) {
+ return (field_offset == java_lang_ref_Reference::next_offset() ||
+ field_offset == java_lang_ref_Reference::discovered_offset());
+}
+
+#endif // INCLUDE_CDS_JAVA_HEAP
diff --git a/src/hotspot/share/cds/aotReferenceObjSupport.hpp b/src/hotspot/share/cds/aotReferenceObjSupport.hpp
new file mode 100644
index 00000000000..3d645c2df17
--- /dev/null
+++ b/src/hotspot/share/cds/aotReferenceObjSupport.hpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2025, 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_CDS_AOTREFERENCEOBJSUPPORT_HPP
+#define SHARE_CDS_AOTREFERENCEOBJSUPPORT_HPP
+
+#include "memory/allStatic.hpp"
+#include "oops/oopsHierarchy.hpp"
+#include "utilities/exceptions.hpp"
+
+// Support for ahead-of-time allocated instances of java.lang.ref.Reference
+
+class AOTReferenceObjSupport : AllStatic {
+
+public:
+ static void initialize(TRAPS);
+ static void stabilize_cached_reference_objects(TRAPS);
+ static void init_keep_alive_objs_table() NOT_CDS_JAVA_HEAP_RETURN;
+ static bool check_if_ref_obj(oop obj);
+ static bool skip_field(int field_offset);
+ static bool is_enabled();
+};
+
+#endif // SHARE_CDS_AOTREFERENCEOBJSUPPORT_HPP
diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp
index c309de17b4c..ef75bd42323 100644
--- a/src/hotspot/share/cds/archiveBuilder.cpp
+++ b/src/hotspot/share/cds/archiveBuilder.cpp
@@ -309,7 +309,8 @@ address ArchiveBuilder::reserve_buffer() {
size_t buffer_size = LP64_ONLY(CompressedClassSpaceSize) NOT_LP64(256 * M);
ReservedSpace rs = MemoryReserver::reserve(buffer_size,
MetaspaceShared::core_region_alignment(),
- os::vm_page_size());
+ os::vm_page_size(),
+ mtClassShared);
if (!rs.is_reserved()) {
log_error(cds)("Failed to reserve %zu bytes of output buffer.", buffer_size);
MetaspaceShared::unrecoverable_writing_error();
@@ -1201,7 +1202,7 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
#undef _LOG_PREFIX
// Log information about a region, whose address at dump time is [base .. top). At
- // runtime, this region will be mapped to requested_base. requested_base is 0 if this
+ // runtime, this region will be mapped to requested_base. requested_base is nullptr if this
// region will be mapped at os-selected addresses (such as the bitmap region), or will
// be accessed with os::read (the header).
//
@@ -1210,7 +1211,11 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
static void log_region(const char* name, address base, address top, address requested_base) {
size_t size = top - base;
base = requested_base;
- top = requested_base + size;
+ if (requested_base == nullptr) {
+ top = (address)size;
+ } else {
+ top = requested_base + size;
+ }
log_info(cds, map)("[%-18s " PTR_FORMAT " - " PTR_FORMAT " %9zu bytes]",
name, p2i(base), p2i(top), size);
}
diff --git a/src/hotspot/share/cds/archiveHeapWriter.cpp b/src/hotspot/share/cds/archiveHeapWriter.cpp
index 5684066105f..2b6d403d835 100644
--- a/src/hotspot/share/cds/archiveHeapWriter.cpp
+++ b/src/hotspot/share/cds/archiveHeapWriter.cpp
@@ -22,6 +22,7 @@
*
*/
+#include "cds/aotReferenceObjSupport.hpp"
#include "cds/archiveHeapWriter.hpp"
#include "cds/cdsConfig.hpp"
#include "cds/filemap.hpp"
@@ -607,18 +608,27 @@ class ArchiveHeapWriter::EmbeddedOopRelocator: public BasicOopIterateClosure {
oop _src_obj;
address _buffered_obj;
CHeapBitMap* _oopmap;
-
+ bool _is_java_lang_ref;
public:
EmbeddedOopRelocator(oop src_obj, address buffered_obj, CHeapBitMap* oopmap) :
- _src_obj(src_obj), _buffered_obj(buffered_obj), _oopmap(oopmap) {}
+ _src_obj(src_obj), _buffered_obj(buffered_obj), _oopmap(oopmap)
+ {
+ _is_java_lang_ref = AOTReferenceObjSupport::check_if_ref_obj(src_obj);
+ }
void do_oop(narrowOop *p) { EmbeddedOopRelocator::do_oop_work(p); }
void do_oop( oop *p) { EmbeddedOopRelocator::do_oop_work(p); }
private:
template void do_oop_work(T *p) {
- size_t field_offset = pointer_delta(p, _src_obj, sizeof(char));
- ArchiveHeapWriter::relocate_field_in_buffer((T*)(_buffered_obj + field_offset), _oopmap);
+ int field_offset = pointer_delta_as_int((char*)p, cast_from_oop(_src_obj));
+ T* field_addr = (T*)(_buffered_obj + field_offset);
+ if (_is_java_lang_ref && AOTReferenceObjSupport::skip_field(field_offset)) {
+ // Do not copy these fields. Set them to null
+ *field_addr = (T)0x0;
+ } else {
+ ArchiveHeapWriter::relocate_field_in_buffer(field_addr, _oopmap);
+ }
}
};
diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp
index 64ad07b0cf8..9af83653351 100644
--- a/src/hotspot/share/cds/cdsConfig.cpp
+++ b/src/hotspot/share/cds/cdsConfig.cpp
@@ -536,9 +536,6 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla
// run to another which resulting in non-determinstic CDS archives.
// Disable UseStringDeduplication while dumping CDS archive.
UseStringDeduplication = false;
-
- // Don't use SoftReferences so that objects used by java.lang.invoke tables can be archived.
- Arguments::PropertyList_add(new SystemProperty("java.lang.invoke.MethodHandleNatives.USE_SOFT_CACHE", "false", false));
}
// RecordDynamicDumpInfo is not compatible with ArchiveClassesAtExit
diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp
index 580699b60b5..1b5d455485c 100644
--- a/src/hotspot/share/cds/filemap.cpp
+++ b/src/hotspot/share/cds/filemap.cpp
@@ -1066,10 +1066,10 @@ void FileMapInfo::close() {
*/
static char* map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
- bool allow_exec, MemTag mem_tag = mtNone) {
+ bool allow_exec, MemTag mem_tag) {
char* mem = os::map_memory(fd, file_name, file_offset, addr, bytes,
- AlwaysPreTouch ? false : read_only,
- allow_exec, mem_tag);
+ mem_tag, AlwaysPreTouch ? false : read_only,
+ allow_exec);
if (mem != nullptr && AlwaysPreTouch) {
os::pretouch_memory(mem, mem + bytes);
}
@@ -1094,7 +1094,7 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() {
assert(WINDOWS_ONLY(false) NOT_WINDOWS(true), "Don't call on Windows");
// Replace old mapping with new one that is writable.
char *base = os::map_memory(_fd, _full_path, r->file_offset(),
- addr, size, false /* !read_only */,
+ addr, size, mtNone, false /* !read_only */,
r->allow_exec());
close();
// These have to be errors because the shared region is now unmapped.
@@ -1620,7 +1620,7 @@ bool FileMapInfo::map_heap_region_impl() {
} else {
base = map_memory(_fd, _full_path, r->file_offset(),
addr, _mapped_heap_memregion.byte_size(), r->read_only(),
- r->allow_exec());
+ r->allow_exec(), mtJavaHeap);
if (base == nullptr || base != addr) {
dealloc_heap_region();
log_info(cds)("UseSharedSpaces: Unable to map at required address in java heap. "
diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp
index ce98b2b93b7..ef71d5895f6 100644
--- a/src/hotspot/share/cds/heapShared.cpp
+++ b/src/hotspot/share/cds/heapShared.cpp
@@ -25,6 +25,7 @@
#include "cds/aotArtifactFinder.hpp"
#include "cds/aotClassInitializer.hpp"
#include "cds/aotClassLocation.hpp"
+#include "cds/aotReferenceObjSupport.hpp"
#include "cds/archiveBuilder.hpp"
#include "cds/archiveHeapLoader.hpp"
#include "cds/archiveHeapWriter.hpp"
@@ -1363,34 +1364,37 @@ void HeapShared::clear_archived_roots_of(Klass* k) {
}
}
-// Push all oops that are referenced by _referencing_obj onto the _stack.
-class HeapShared::ReferentPusher: public BasicOopIterateClosure {
+// Push all oop fields (or oop array elemenets in case of an objArray) in
+// _referencing_obj onto the _stack.
+class HeapShared::OopFieldPusher: public BasicOopIterateClosure {
PendingOopStack* _stack;
GrowableArray _found_oop_fields;
int _level;
bool _record_klasses_only;
KlassSubGraphInfo* _subgraph_info;
oop _referencing_obj;
+ bool _is_java_lang_ref;
public:
- ReferentPusher(PendingOopStack* stack,
- int level,
- bool record_klasses_only,
- KlassSubGraphInfo* subgraph_info,
- oop orig) :
+ OopFieldPusher(PendingOopStack* stack,
+ int level,
+ bool record_klasses_only,
+ KlassSubGraphInfo* subgraph_info,
+ oop orig) :
_stack(stack),
_found_oop_fields(),
_level(level),
_record_klasses_only(record_klasses_only),
_subgraph_info(subgraph_info),
_referencing_obj(orig) {
+ _is_java_lang_ref = AOTReferenceObjSupport::check_if_ref_obj(orig);
}
- void do_oop(narrowOop *p) { ReferentPusher::do_oop_work(p); }
- void do_oop( oop *p) { ReferentPusher::do_oop_work(p); }
+ void do_oop(narrowOop *p) { OopFieldPusher::do_oop_work(p); }
+ void do_oop( oop *p) { OopFieldPusher::do_oop_work(p); }
- ~ReferentPusher() {
+ ~OopFieldPusher() {
while (_found_oop_fields.length() > 0) {
// This produces the exact same traversal order as the previous version
- // of ReferentPusher that recurses on the C stack -- a depth-first search,
+ // of OopFieldPusher that recurses on the C stack -- a depth-first search,
// walking the oop fields in _referencing_obj by ascending field offsets.
oop obj = _found_oop_fields.pop();
_stack->push(PendingOop(obj, _referencing_obj, _level + 1));
@@ -1399,14 +1403,18 @@ class HeapShared::ReferentPusher: public BasicOopIterateClosure {
protected:
template void do_oop_work(T *p) {
- oop obj = RawAccess<>::oop_load(p);
+ int field_offset = pointer_delta_as_int((char*)p, cast_from_oop(_referencing_obj));
+ oop obj = HeapAccess::oop_load_at(_referencing_obj, field_offset);
if (!CompressedOops::is_null(obj)) {
- size_t field_delta = pointer_delta(p, _referencing_obj, sizeof(char));
+ if (_is_java_lang_ref && AOTReferenceObjSupport::skip_field(field_offset)) {
+ // Do not follow these fields. They will be cleared to null.
+ return;
+ }
if (!_record_klasses_only && log_is_enabled(Debug, cds, heap)) {
ResourceMark rm;
- log_debug(cds, heap)("(%d) %s[%zu] ==> " PTR_FORMAT " size %zu %s", _level,
- _referencing_obj->klass()->external_name(), field_delta,
+ log_debug(cds, heap)("(%d) %s[%d] ==> " PTR_FORMAT " size %zu %s", _level,
+ _referencing_obj->klass()->external_name(), field_offset,
p2i(obj), obj->size() * HeapWordSize, obj->klass()->external_name());
if (log_is_enabled(Trace, cds, heap)) {
LogTarget(Trace, cds, heap) log;
@@ -1586,7 +1594,7 @@ bool HeapShared::walk_one_object(PendingOopStack* stack, int level, KlassSubGrap
// Find all the oops that are referenced by orig_obj, push them onto the stack
// so we can work on them next.
ResourceMark rm;
- ReferentPusher pusher(stack, level, record_klasses_only, subgraph_info, orig_obj);
+ OopFieldPusher pusher(stack, level, record_klasses_only, subgraph_info, orig_obj);
orig_obj->oop_iterate(&pusher);
}
@@ -1613,7 +1621,7 @@ bool HeapShared::walk_one_object(PendingOopStack* stack, int level, KlassSubGrap
// - No java.lang.Class instance (java mirror) can be included inside
// an archived sub-graph. Mirror can only be the sub-graph entry object.
//
-// The Java heap object sub-graph archiving process (see ReferentPusher):
+// The Java heap object sub-graph archiving process (see OopFieldPusher):
//
// 1) Java object sub-graph archiving starts from a given static field
// within a Class instance (java mirror). If the static field is a
diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp
index 04c9ae91381..f4e86aa5895 100644
--- a/src/hotspot/share/cds/heapShared.hpp
+++ b/src/hotspot/share/cds/heapShared.hpp
@@ -164,8 +164,8 @@ private:
static void count_allocation(size_t size);
static void print_stats();
- static void debug_trace();
public:
+ static void debug_trace();
static unsigned oop_hash(oop const& p);
static unsigned string_oop_hash(oop const& string) {
return java_lang_String::hash_code(string);
@@ -357,7 +357,7 @@ private:
int level() const { return _level; }
};
- class ReferentPusher;
+ class OopFieldPusher;
using PendingOopStack = GrowableArrayCHeap;
static PendingOop _object_being_archived;
diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp
index ef2a6dcb8e6..bdec6441080 100644
--- a/src/hotspot/share/cds/metaspaceShared.cpp
+++ b/src/hotspot/share/cds/metaspaceShared.cpp
@@ -28,6 +28,7 @@
#include "cds/aotClassLocation.hpp"
#include "cds/aotConstantPoolResolver.hpp"
#include "cds/aotLinkedClassBulkLoader.hpp"
+#include "cds/aotReferenceObjSupport.hpp"
#include "cds/archiveBuilder.hpp"
#include "cds/archiveHeapLoader.hpp"
#include "cds/archiveHeapWriter.hpp"
@@ -962,22 +963,14 @@ void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS
#if INCLUDE_CDS_JAVA_HEAP
if (CDSConfig::is_dumping_heap()) {
ArchiveHeapWriter::init();
+
if (CDSConfig::is_dumping_full_module_graph()) {
ClassLoaderDataShared::ensure_module_entry_tables_exist();
HeapShared::reset_archived_object_states(CHECK);
}
- if (CDSConfig::is_dumping_method_handles()) {
- // This assert means that the MethodType and MethodTypeForm tables won't be
- // updated concurrently when we are saving their contents into a side table.
- assert(CDSConfig::allow_only_single_java_thread(), "Required");
-
- JavaValue result(T_VOID);
- JavaCalls::call_static(&result, vmClasses::MethodType_klass(),
- vmSymbols::createArchivedObjects(),
- vmSymbols::void_method_signature(),
- CHECK);
- }
+ AOTReferenceObjSupport::initialize(CHECK);
+ AOTReferenceObjSupport::stabilize_cached_reference_objects(CHECK);
if (CDSConfig::is_initing_classes_at_dump_time()) {
// java.lang.Class::reflectionFactory cannot be archived yet. We set this field
@@ -1345,7 +1338,7 @@ MapArchiveResult MetaspaceShared::map_archives(FileMapInfo* static_mapinfo, File
if (prot_zone_size > 0) {
assert(prot_zone_size >= os::vm_allocation_granularity(), "must be"); // not just page size!
char* p = os::attempt_reserve_memory_at(mapped_base_address, prot_zone_size,
- false, MemTag::mtClassShared);
+ mtClassShared);
assert(p == mapped_base_address || p == nullptr, "must be");
if (p == nullptr) {
log_debug(cds)("Failed to re-reserve protection zone");
@@ -1537,7 +1530,8 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
archive_space_rs = MemoryReserver::reserve((char*)base_address,
archive_space_size,
archive_space_alignment,
- os::vm_page_size());
+ os::vm_page_size(),
+ mtNone);
if (archive_space_rs.is_reserved()) {
assert(base_address == nullptr ||
(address)archive_space_rs.base() == base_address, "Sanity");
@@ -1605,11 +1599,13 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
archive_space_rs = MemoryReserver::reserve((char*)base_address,
archive_space_size,
archive_space_alignment,
- os::vm_page_size());
+ os::vm_page_size(),
+ mtNone);
class_space_rs = MemoryReserver::reserve((char*)ccs_base,
class_space_size,
class_space_alignment,
- os::vm_page_size());
+ os::vm_page_size(),
+ mtNone);
}
if (!archive_space_rs.is_reserved() || !class_space_rs.is_reserved()) {
release_reserved_spaces(total_space_rs, archive_space_rs, class_space_rs);
@@ -1622,7 +1618,8 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
total_space_rs = MemoryReserver::reserve((char*) base_address,
total_range_size,
base_address_alignment,
- os::vm_page_size());
+ os::vm_page_size(),
+ mtNone);
} else {
// We did not manage to reserve at the preferred address, or were instructed to relocate. In that
// case we reserve wherever possible, but the start address needs to be encodable as narrow Klass
diff --git a/src/hotspot/share/ci/ciInstance.cpp b/src/hotspot/share/ci/ciInstance.cpp
index ad456ba6726..9591298e3ab 100644
--- a/src/hotspot/share/ci/ciInstance.cpp
+++ b/src/hotspot/share/ci/ciInstance.cpp
@@ -138,3 +138,9 @@ ciKlass* ciInstance::java_lang_Class_klass() {
assert(java_lang_Class::as_Klass(get_oop()) != nullptr, "klass is null");
return CURRENT_ENV->get_metadata(java_lang_Class::as_Klass(get_oop()))->as_klass();
}
+
+char* ciInstance::java_lang_String_str(char* buf, size_t buflen) {
+ VM_ENTRY_MARK;
+ assert(get_oop()->is_a(vmClasses::String_klass()), "not a String");
+ return java_lang_String::as_utf8_string(get_oop(), buf, buflen);
+}
diff --git a/src/hotspot/share/ci/ciInstance.hpp b/src/hotspot/share/ci/ciInstance.hpp
index 3af07edcd9e..1fb09985930 100644
--- a/src/hotspot/share/ci/ciInstance.hpp
+++ b/src/hotspot/share/ci/ciInstance.hpp
@@ -67,6 +67,7 @@ public:
ciConstant field_value_by_offset(int field_offset);
ciKlass* java_lang_Class_klass();
+ char* java_lang_String_str(char* buf, size_t buflen);
};
#endif // SHARE_CI_CIINSTANCE_HPP
diff --git a/src/hotspot/share/ci/ciMethod.cpp b/src/hotspot/share/ci/ciMethod.cpp
index 3b2670c3eb0..6b6f1b6f0a8 100644
--- a/src/hotspot/share/ci/ciMethod.cpp
+++ b/src/hotspot/share/ci/ciMethod.cpp
@@ -914,8 +914,14 @@ int ciMethod::scale_count(int count, float prof_factor) {
method_life = counter_life;
}
if (counter_life > 0) {
- count = (int)((double)count * prof_factor * method_life / counter_life + 0.5);
- count = (count > 0) ? count : 1;
+ double count_d = (double)count * prof_factor * method_life / counter_life + 0.5;
+ if (count_d >= static_cast(INT_MAX)) {
+ // Clamp in case of overflowing int range.
+ count = INT_MAX;
+ } else {
+ count = int(count_d);
+ count = (count > 0) ? count : 1;
+ }
} else {
count = 1;
}
diff --git a/src/hotspot/share/ci/ciTypeFlow.cpp b/src/hotspot/share/ci/ciTypeFlow.cpp
index 234b4611ea1..6df090a7ce5 100644
--- a/src/hotspot/share/ci/ciTypeFlow.cpp
+++ b/src/hotspot/share/ci/ciTypeFlow.cpp
@@ -2924,7 +2924,7 @@ void ciTypeFlow::flow_types() {
// Continue flow analysis until fixed point reached
- debug_only(int max_block = _next_pre_order;)
+ DEBUG_ONLY(int max_block = _next_pre_order;)
while (!work_list_empty()) {
Block* blk = work_list_next();
diff --git a/src/hotspot/share/ci/ciTypeFlow.hpp b/src/hotspot/share/ci/ciTypeFlow.hpp
index 92db6253aa0..adfb85dc17f 100644
--- a/src/hotspot/share/ci/ciTypeFlow.hpp
+++ b/src/hotspot/share/ci/ciTypeFlow.hpp
@@ -253,7 +253,7 @@ public:
set_type_at_tos(type);
}
void pop() {
- debug_only(set_type_at_tos(bottom_type()));
+ DEBUG_ONLY(set_type_at_tos(bottom_type()));
_stack_size--;
}
ciType* pop_value() {
diff --git a/src/hotspot/share/ci/ciUtilities.inline.hpp b/src/hotspot/share/ci/ciUtilities.inline.hpp
index 05e73d8ca64..91f848368ac 100644
--- a/src/hotspot/share/ci/ciUtilities.inline.hpp
+++ b/src/hotspot/share/ci/ciUtilities.inline.hpp
@@ -37,7 +37,7 @@
ThreadInVMfromNative __tiv(thread); \
HandleMarkCleaner __hm(thread); \
JavaThread* THREAD = thread; /* For exception macros. */ \
- debug_only(VMNativeEntryWrapper __vew;)
+ DEBUG_ONLY(VMNativeEntryWrapper __vew;)
@@ -49,10 +49,10 @@
* [TODO] The NoHandleMark line does nothing but declare a function prototype \
* The NoHandkeMark constructor is NOT executed. If the ()'s are \
* removed, causes the NoHandleMark assert to trigger. \
- * debug_only(NoHandleMark __hm();) \
+ * DEBUG_ONLY(NoHandleMark __hm();) \
*/ \
JavaThread* THREAD = thread; /* For exception macros. */ \
- debug_only(VMNativeEntryWrapper __vew;)
+ DEBUG_ONLY(VMNativeEntryWrapper __vew;)
#define EXCEPTION_CONTEXT \
diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp
index 3e6246d4aee..757f0e72c8c 100644
--- a/src/hotspot/share/classfile/classFileParser.cpp
+++ b/src/hotspot/share/classfile/classFileParser.cpp
@@ -176,7 +176,7 @@ void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const s
const ClassFileStream cfs1 = *stream;
const ClassFileStream* const cfs = &cfs1;
- debug_only(const u1* const old_current = stream->current();)
+ DEBUG_ONLY(const u1* const old_current = stream->current();)
// Used for batching symbol allocations.
const char* names[SymbolTable::symbol_alloc_batch_size];
@@ -5243,7 +5243,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik,
// it's official
set_klass(ik);
- debug_only(ik->verify();)
+ DEBUG_ONLY(ik->verify();)
}
void ClassFileParser::update_class_name(Symbol* new_class_name) {
diff --git a/src/hotspot/share/classfile/compactHashtable.cpp b/src/hotspot/share/classfile/compactHashtable.cpp
index 8d50e8136a3..15ae5ba8013 100644
--- a/src/hotspot/share/classfile/compactHashtable.cpp
+++ b/src/hotspot/share/classfile/compactHashtable.cpp
@@ -226,7 +226,7 @@ HashtableTextDump::HashtableTextDump(const char* filename) : _fd(-1) {
if (_fd < 0) {
quit("Unable to open hashtable dump file", filename);
}
- _base = os::map_memory(_fd, filename, 0, nullptr, _size, true, false);
+ _base = os::map_memory(_fd, filename, 0, nullptr, _size, mtNone, true, false);
if (_base == nullptr) {
quit("Unable to map hashtable dump file", filename);
}
diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp
index a2ad1dce5e4..c7cca9682fe 100644
--- a/src/hotspot/share/classfile/javaClasses.cpp
+++ b/src/hotspot/share/classfile/javaClasses.cpp
@@ -22,6 +22,7 @@
*
*/
+#include "cds/aotReferenceObjSupport.hpp"
#include "cds/archiveBuilder.hpp"
#include "cds/archiveHeapLoader.hpp"
#include "cds/cdsConfig.hpp"
@@ -4821,7 +4822,7 @@ bool java_lang_ClassLoader::isAncestor(oop loader, oop cl) {
assert(is_instance(loader), "loader must be oop");
assert(cl == nullptr || is_instance(cl), "cl argument must be oop");
oop acl = loader;
- debug_only(jint loop_count = 0);
+ DEBUG_ONLY(jint loop_count = 0);
// This loop taken verbatim from ClassLoader.java:
do {
acl = parent(acl);
@@ -5460,9 +5461,7 @@ bool JavaClasses::is_supported_for_archiving(oop obj) {
}
}
- if (klass->is_subclass_of(vmClasses::Reference_klass())) {
- // It's problematic to archive Reference objects. One of the reasons is that
- // Reference::discovered may pull in unwanted objects (see JDK-8284336)
+ if (!AOTReferenceObjSupport::is_enabled() && klass->is_subclass_of(vmClasses::Reference_klass())) {
return false;
}
diff --git a/src/hotspot/share/classfile/modules.cpp b/src/hotspot/share/classfile/modules.cpp
index 3f2ff90ccab..a506c4502a4 100644
--- a/src/hotspot/share/classfile/modules.cpp
+++ b/src/hotspot/share/classfile/modules.cpp
@@ -466,13 +466,9 @@ void Modules::define_module(Handle module, jboolean is_open, jstring version,
if (EnableVectorSupport && EnableVectorReboxing && FLAG_IS_DEFAULT(EnableVectorAggressiveReboxing)) {
FLAG_SET_DEFAULT(EnableVectorAggressiveReboxing, true);
}
- if (EnableVectorSupport && FLAG_IS_DEFAULT(UseVectorStubs)) {
- FLAG_SET_DEFAULT(UseVectorStubs, true);
- }
log_info(compilation)("EnableVectorSupport=%s", (EnableVectorSupport ? "true" : "false"));
log_info(compilation)("EnableVectorReboxing=%s", (EnableVectorReboxing ? "true" : "false"));
log_info(compilation)("EnableVectorAggressiveReboxing=%s", (EnableVectorAggressiveReboxing ? "true" : "false"));
- log_info(compilation)("UseVectorStubs=%s", (UseVectorStubs ? "true" : "false"));
}
#endif // COMPILER2_OR_JVMCI
}
@@ -580,13 +576,14 @@ public:
};
Modules::ArchivedProperty Modules::_archived_props[] = {
- // numbered
+ // non-numbered
{"jdk.module.main", false},
- // non-numbered
+ // numbered
{"jdk.module.addexports", true}, // --add-exports
{"jdk.module.addmods", true}, // --add-modules
{"jdk.module.enable.native.access", true}, // --enable-native-access
+ {"jdk.module.addopens", true}, // --add-opens
};
constexpr size_t Modules::num_archived_props() {
diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp
index 68de40f1788..2959f35ef2c 100644
--- a/src/hotspot/share/classfile/vmIntrinsics.hpp
+++ b/src/hotspot/share/classfile/vmIntrinsics.hpp
@@ -1001,7 +1001,8 @@ class methodHandle;
do_intrinsic(_VectorUnaryOp, jdk_internal_vm_vector_VectorSupport, vector_unary_op_name, vector_unary_op_sig, F_S) \
do_signature(vector_unary_op_sig, "(I" \
"Ljava/lang/Class;" \
- "Ljava/lang/Class;Ljava/lang/Class;" \
+ "Ljava/lang/Class;" \
+ "Ljava/lang/Class;" \
"I" \
"Ljdk/internal/vm/vector/VectorSupport$Vector;" \
"Ljdk/internal/vm/vector/VectorSupport$VectorMask;" \
@@ -1022,6 +1023,29 @@ class methodHandle;
"Ljdk/internal/vm/vector/VectorSupport$VectorPayload;") \
do_name(vector_binary_op_name, "binaryOp") \
\
+ do_intrinsic(_VectorUnaryLibOp, jdk_internal_vm_vector_VectorSupport, vector_unary_lib_op_name, vector_unary_lib_op_sig, F_S) \
+ do_signature(vector_unary_lib_op_sig,"(J" \
+ "Ljava/lang/Class;" \
+ "Ljava/lang/Class;" \
+ "I" \
+ "Ljava/lang/String;" \
+ "Ljdk/internal/vm/vector/VectorSupport$Vector;" \
+ "Ljdk/internal/vm/vector/VectorSupport$UnaryOperation;)" \
+ "Ljdk/internal/vm/vector/VectorSupport$Vector;") \
+ do_name(vector_unary_lib_op_name, "libraryUnaryOp") \
+ \
+ do_intrinsic(_VectorBinaryLibOp, jdk_internal_vm_vector_VectorSupport, vector_binary_lib_op_name, vector_binary_lib_op_sig, F_S) \
+ do_signature(vector_binary_lib_op_sig,"(J" \
+ "Ljava/lang/Class;" \
+ "Ljava/lang/Class;" \
+ "I" \
+ "Ljava/lang/String;" \
+ "Ljdk/internal/vm/vector/VectorSupport$VectorPayload;" \
+ "Ljdk/internal/vm/vector/VectorSupport$VectorPayload;" \
+ "Ljdk/internal/vm/vector/VectorSupport$BinaryOperation;)" \
+ "Ljdk/internal/vm/vector/VectorSupport$VectorPayload;") \
+ do_name(vector_binary_lib_op_name, "libraryBinaryOp") \
+ \
do_intrinsic(_VectorTernaryOp, jdk_internal_vm_vector_VectorSupport, vector_ternary_op_name, vector_ternary_op_sig, F_S) \
do_signature(vector_ternary_op_sig, "(I" \
"Ljava/lang/Class;" \
diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp
index e66066738ef..f9f6bd07254 100644
--- a/src/hotspot/share/classfile/vmSymbols.hpp
+++ b/src/hotspot/share/classfile/vmSymbols.hpp
@@ -719,7 +719,6 @@ class SerializeClosure;
JFR_TEMPLATES(template) \
\
/* CDS */ \
- template(createArchivedObjects, "createArchivedObjects") \
template(dumpSharedArchive, "dumpSharedArchive") \
template(dumpSharedArchive_signature, "(ZLjava/lang/String;)Ljava/lang/String;") \
template(generateLambdaFormHolderClasses, "generateLambdaFormHolderClasses") \
diff --git a/src/hotspot/share/code/debugInfoRec.cpp b/src/hotspot/share/code/debugInfoRec.cpp
index 02cd23407bf..8449f5d6929 100644
--- a/src/hotspot/share/code/debugInfoRec.cpp
+++ b/src/hotspot/share/code/debugInfoRec.cpp
@@ -140,7 +140,7 @@ DebugInformationRecorder::DebugInformationRecorder(OopRecorder* oop_recorder)
add_new_pc_offset(PcDesc::lower_offset_limit); // sentinel record
- debug_only(_recording_state = rs_null);
+ DEBUG_ONLY(_recording_state = rs_null);
}
@@ -159,7 +159,7 @@ void DebugInformationRecorder::add_safepoint(int pc_offset, OopMap* map) {
add_new_pc_offset(pc_offset);
assert(_recording_state == rs_null, "nesting of recording calls");
- debug_only(_recording_state = rs_safepoint);
+ DEBUG_ONLY(_recording_state = rs_safepoint);
}
void DebugInformationRecorder::add_non_safepoint(int pc_offset) {
@@ -169,7 +169,7 @@ void DebugInformationRecorder::add_non_safepoint(int pc_offset) {
add_new_pc_offset(pc_offset);
assert(_recording_state == rs_null, "nesting of recording calls");
- debug_only(_recording_state = rs_non_safepoint);
+ DEBUG_ONLY(_recording_state = rs_non_safepoint);
}
void DebugInformationRecorder::add_new_pc_offset(int pc_offset) {
@@ -360,7 +360,7 @@ void DebugInformationRecorder::dump_object_pool(GrowableArray* obje
void DebugInformationRecorder::end_scopes(int pc_offset, bool is_safepoint) {
assert(_recording_state == (is_safepoint? rs_safepoint: rs_non_safepoint),
"nesting of recording calls");
- debug_only(_recording_state = rs_null);
+ DEBUG_ONLY(_recording_state = rs_null);
// Try to compress away an equivalent non-safepoint predecessor.
// (This only works because we have previously recognized redundant
@@ -413,13 +413,13 @@ DebugToken* DebugInformationRecorder::create_monitor_values(GrowableArrayposition();
}
int DebugInformationRecorder::pcs_size() {
- debug_only(mark_recorders_frozen()); // mark it "frozen" for asserts
+ DEBUG_ONLY(mark_recorders_frozen()); // mark it "frozen" for asserts
if (last_pc()->pc_offset() != PcDesc::upper_offset_limit)
add_new_pc_offset(PcDesc::upper_offset_limit);
return _pcs_length * sizeof(PcDesc);
diff --git a/src/hotspot/share/code/dependencyContext.cpp b/src/hotspot/share/code/dependencyContext.cpp
index 2b3253030c5..a8ef707978d 100644
--- a/src/hotspot/share/code/dependencyContext.cpp
+++ b/src/hotspot/share/code/dependencyContext.cpp
@@ -91,18 +91,40 @@ void DependencyContext::mark_dependent_nmethods(DeoptimizationScope* deopt_scope
//
void DependencyContext::add_dependent_nmethod(nmethod* nm) {
assert_lock_strong(CodeCache_lock);
- for (nmethodBucket* b = dependencies_not_unloading(); b != nullptr; b = b->next_not_unloading()) {
- if (nm == b->get_nmethod()) {
- return;
- }
+ assert(nm->is_not_installed(), "Precondition: new nmethod");
+
+ // This method tries to add never before seen nmethod, holding the CodeCache_lock
+ // until all dependencies are added. The caller code can call multiple times
+ // with the same nmethod, but always under the same lock hold.
+ //
+ // This means the buckets list is guaranteed to be in either of two states, with
+ // regards to the newly added nmethod:
+ // 1. The nmethod is not in the list, and can be just added to the head of the list.
+ // 2. The nmethod is in the list, and it is already at the head of the list.
+ //
+ // This path is the only path that adds to the list. There can be concurrent removals
+ // from the list, but they do not break this invariant. This invariant allows us
+ // to skip list scans. The individual method checks are cheap, but walking the large
+ // list of dependencies gets expensive.
+
+ nmethodBucket* head = Atomic::load(_dependency_context_addr);
+ if (head != nullptr && nm == head->get_nmethod()) {
+ return;
}
+
+#ifdef ASSERT
+ for (nmethodBucket* b = head; b != nullptr; b = b->next()) {
+ assert(nm != b->get_nmethod(), "Invariant: should not be in the list yet");
+ }
+#endif
+
nmethodBucket* new_head = new nmethodBucket(nm, nullptr);
for (;;) {
- nmethodBucket* head = Atomic::load(_dependency_context_addr);
new_head->set_next(head);
if (Atomic::cmpxchg(_dependency_context_addr, head, new_head) == head) {
break;
}
+ head = Atomic::load(_dependency_context_addr);
}
if (UsePerfData) {
_perf_total_buckets_allocated_count->inc();
diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp
index 56ba76a806e..4576a348a4f 100644
--- a/src/hotspot/share/code/nmethod.cpp
+++ b/src/hotspot/share/code/nmethod.cpp
@@ -1122,7 +1122,7 @@ nmethod* nmethod::new_native_nmethod(const methodHandle& method,
if (nm != nullptr) {
// verify nmethod
- debug_only(nm->verify();) // might block
+ DEBUG_ONLY(nm->verify();) // might block
nm->log_new_nmethod();
}
@@ -1269,7 +1269,7 @@ void nmethod::post_init() {
finalize_relocations();
Universe::heap()->register_nmethod(this);
- debug_only(Universe::heap()->verify_nmethod(this));
+ DEBUG_ONLY(Universe::heap()->verify_nmethod(this));
CodeCache::commit(this);
}
@@ -1296,7 +1296,7 @@ nmethod::nmethod(
_native_basic_lock_sp_offset(basic_lock_sp_offset)
{
{
- debug_only(NoSafepointVerifier nsv;)
+ DEBUG_ONLY(NoSafepointVerifier nsv;)
assert_locked_or_safepoint(CodeCache_lock);
init_defaults(code_buffer, offsets);
@@ -1437,7 +1437,7 @@ nmethod::nmethod(
{
assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR");
{
- debug_only(NoSafepointVerifier nsv;)
+ DEBUG_ONLY(NoSafepointVerifier nsv;)
assert_locked_or_safepoint(CodeCache_lock);
init_defaults(code_buffer, offsets);
@@ -2802,7 +2802,7 @@ PcDesc* PcDescContainer::find_pc_desc_internal(address pc, bool approximate, add
}
// Take giant steps at first (4096, then 256, then 16, then 1)
- const int LOG2_RADIX = 4 /*smaller steps in debug mode:*/ debug_only(-1);
+ const int LOG2_RADIX = 4 /*smaller steps in debug mode:*/ DEBUG_ONLY(-1);
const int RADIX = (1 << LOG2_RADIX);
for (int step = (1 << (LOG2_RADIX*3)); step > 1; step >>= LOG2_RADIX) {
while ((mid = lower + step) < upper) {
diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp
index 7b19cf75a76..1c536a5d7e1 100644
--- a/src/hotspot/share/code/nmethod.hpp
+++ b/src/hotspot/share/code/nmethod.hpp
@@ -100,7 +100,7 @@ class PcDescCache {
typedef PcDesc* PcDescPtr;
volatile PcDescPtr _pc_descs[cache_size]; // last cache_size pc_descs found
public:
- PcDescCache() { debug_only(_pc_descs[0] = nullptr); }
+ PcDescCache() { DEBUG_ONLY(_pc_descs[0] = nullptr); }
void init_to(PcDesc* initial_pc_desc);
PcDesc* find_pc_desc(int pc_offset, bool approximate);
void add_pc_desc(PcDesc* pc_desc);
diff --git a/src/hotspot/share/code/oopRecorder.cpp b/src/hotspot/share/code/oopRecorder.cpp
index af23bf12b43..c37651892cc 100644
--- a/src/hotspot/share/code/oopRecorder.cpp
+++ b/src/hotspot/share/code/oopRecorder.cpp
@@ -122,7 +122,7 @@ template int ValueRecorder::add_handle(T h, bool make_findable) {
template int ValueRecorder::maybe_find_index(T h) {
- debug_only(_find_index_calls++);
+ DEBUG_ONLY(_find_index_calls++);
assert(!_complete, "cannot allocate more elements after size query");
maybe_initialize();
if (h == nullptr) return null_index;
@@ -134,7 +134,7 @@ template int ValueRecorder::maybe_find_index(T h) {
return -1; // We know this handle is completely new.
}
if (cindex >= first_index && _handles->at(cindex - first_index) == h) {
- debug_only(_hit_indexes++);
+ DEBUG_ONLY(_hit_indexes++);
return cindex;
}
if (!_indexes->cache_location_collision(cloc)) {
@@ -151,7 +151,7 @@ template int ValueRecorder::maybe_find_index(T h) {
if (cloc != nullptr) {
_indexes->set_cache_location_index(cloc, findex);
}
- debug_only(_missed_indexes++);
+ DEBUG_ONLY(_missed_indexes++);
return findex;
}
}
diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp
index ad194c71bb2..a828a8356aa 100644
--- a/src/hotspot/share/code/relocInfo.cpp
+++ b/src/hotspot/share/code/relocInfo.cpp
@@ -78,7 +78,7 @@ relocInfo* relocInfo::finish_prefix(short* prefix_limit) {
assert(prefix_limit >= p, "must be a valid span of data");
int plen = checked_cast(prefix_limit - p);
if (plen == 0) {
- debug_only(_value = 0xFFFF);
+ DEBUG_ONLY(_value = 0xFFFF);
return this; // no data: remove self completely
}
if (plen == 1 && fits_into_immediate(p[0])) {
@@ -342,7 +342,7 @@ address Relocation::old_addr_for(address newa,
address Relocation::new_addr_for(address olda,
const CodeBuffer* src, CodeBuffer* dest) {
- debug_only(const CodeBuffer* src0 = src);
+ DEBUG_ONLY(const CodeBuffer* src0 = src);
int sect = CodeBuffer::SECT_NONE;
// Look for olda in the source buffer, and all previous incarnations
// if the source buffer has been expanded.
diff --git a/src/hotspot/share/code/relocInfo.hpp b/src/hotspot/share/code/relocInfo.hpp
index 25cca49e50b..a10f653bbb1 100644
--- a/src/hotspot/share/code/relocInfo.hpp
+++ b/src/hotspot/share/code/relocInfo.hpp
@@ -574,7 +574,7 @@ class RelocIterator : public StackObj {
void set_has_current(bool b) {
_datalen = !b ? -1 : 0;
- debug_only(_data = nullptr);
+ DEBUG_ONLY(_data = nullptr);
}
void set_current(relocInfo& ri) {
_current = &ri;
diff --git a/src/hotspot/share/code/stubs.cpp b/src/hotspot/share/code/stubs.cpp
index 074241ff611..6ae71f93709 100644
--- a/src/hotspot/share/code/stubs.cpp
+++ b/src/hotspot/share/code/stubs.cpp
@@ -176,14 +176,14 @@ void StubQueue::commit(int committed_code_size) {
_queue_end += committed_size;
_number_of_stubs++;
if (_mutex != nullptr) _mutex->unlock();
- debug_only(stub_verify(s);)
+ DEBUG_ONLY(stub_verify(s);)
}
void StubQueue::remove_first() {
if (number_of_stubs() == 0) return;
Stub* s = first();
- debug_only(stub_verify(s);)
+ DEBUG_ONLY(stub_verify(s);)
stub_finalize(s);
_queue_begin += stub_size(s);
assert(_queue_begin <= _buffer_limit, "sanity check");
@@ -210,7 +210,7 @@ void StubQueue::remove_first(int n) {
void StubQueue::remove_all(){
- debug_only(verify();)
+ DEBUG_ONLY(verify();)
remove_first(number_of_stubs());
assert(number_of_stubs() == 0, "sanity check");
}
diff --git a/src/hotspot/share/compiler/compilationMemoryStatistic.cpp b/src/hotspot/share/compiler/compilationMemoryStatistic.cpp
index 0c2822c94d2..3138eb3a8c0 100644
--- a/src/hotspot/share/compiler/compilationMemoryStatistic.cpp
+++ b/src/hotspot/share/compiler/compilationMemoryStatistic.cpp
@@ -374,7 +374,7 @@ void ArenaStatCounter::on_arena_chunk_deallocation(size_t size, uint64_t stamp)
void ArenaStatCounter::print_peak_state_on(outputStream* st) const {
st->print("Total Usage: %zu ", _peak);
if (_peak > 0) {
-#ifdef COMPILER2
+#ifdef COMPILER1
// C1: print allocations broken down by arena types
if (_comp_type == CompilerType::compiler_c1) {
st->print("[");
diff --git a/src/hotspot/share/compiler/oopMap.cpp b/src/hotspot/share/compiler/oopMap.cpp
index ea2c770d66f..88249fc8555 100644
--- a/src/hotspot/share/compiler/oopMap.cpp
+++ b/src/hotspot/share/compiler/oopMap.cpp
@@ -326,7 +326,7 @@ void OopMap::set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional) {
assert(reg->value() < _locs_length, "too big reg value for stack size");
assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" );
- debug_only( _locs_used[reg->value()] = x; )
+ DEBUG_ONLY( _locs_used[reg->value()] = x; )
OopMapValue o(reg, x, optional);
o.write_on(write_stream());
@@ -511,7 +511,7 @@ void ImmutableOopMap::update_register_map(const frame *fr, RegisterMap *reg_map)
// Any reg might be saved by a safepoint handler (see generate_handler_blob).
assert( reg_map->_update_for_id == nullptr || fr->is_older(reg_map->_update_for_id),
"already updated this map; do not 'update' it twice!" );
- debug_only(reg_map->_update_for_id = fr->id());
+ DEBUG_ONLY(reg_map->_update_for_id = fr->id());
// Check if caller must update oop argument
assert((reg_map->include_argument_oops() ||
diff --git a/src/hotspot/share/compiler/oopMap.hpp b/src/hotspot/share/compiler/oopMap.hpp
index 634fb8b0bfa..191996f0f05 100644
--- a/src/hotspot/share/compiler/oopMap.hpp
+++ b/src/hotspot/share/compiler/oopMap.hpp
@@ -162,7 +162,7 @@ class OopMap: public ResourceObj {
bool _has_derived_oops;
CompressedWriteStream* _write_stream;
- debug_only( OopMapValue::oop_types* _locs_used; int _locs_length;)
+ DEBUG_ONLY( OopMapValue::oop_types* _locs_used; int _locs_length;)
// Accessors
int omv_count() const { return _omv_count; }
diff --git a/src/hotspot/share/gc/g1/g1Arguments.cpp b/src/hotspot/share/gc/g1/g1Arguments.cpp
index b1cf9fd3046..bd156a69fe6 100644
--- a/src/hotspot/share/gc/g1/g1Arguments.cpp
+++ b/src/hotspot/share/gc/g1/g1Arguments.cpp
@@ -71,6 +71,9 @@ void G1Arguments::initialize_alignments() {
}
size_t G1Arguments::conservative_max_heap_alignment() {
+ if (FLAG_IS_DEFAULT(G1HeapRegionSize)) {
+ return G1HeapRegion::max_ergonomics_size();
+ }
return G1HeapRegion::max_region_size();
}
diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
index 4ce45d06d1d..ad52388a64f 100644
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp
@@ -1230,7 +1230,8 @@ G1RegionToSpaceMapper* G1CollectedHeap::create_aux_memory_mapper(const char* des
// Allocate a new reserved space, preferring to use large pages.
ReservedSpace rs = MemoryReserver::reserve(size,
alignment,
- preferred_page_size);
+ preferred_page_size,
+ mtGC);
size_t page_size = rs.page_size();
G1RegionToSpaceMapper* result =
diff --git a/src/hotspot/share/gc/g1/g1HeapRegion.cpp b/src/hotspot/share/gc/g1/g1HeapRegion.cpp
index 288ddae48fb..03610ab520b 100644
--- a/src/hotspot/share/gc/g1/g1HeapRegion.cpp
+++ b/src/hotspot/share/gc/g1/g1HeapRegion.cpp
@@ -57,6 +57,10 @@ size_t G1HeapRegion::max_region_size() {
return G1HeapRegionBounds::max_size();
}
+size_t G1HeapRegion::max_ergonomics_size() {
+ return G1HeapRegionBounds::max_ergonomics_size();
+}
+
size_t G1HeapRegion::min_region_size_in_words() {
return G1HeapRegionBounds::min_size() >> LogHeapWordSize;
}
diff --git a/src/hotspot/share/gc/g1/g1HeapRegion.hpp b/src/hotspot/share/gc/g1/g1HeapRegion.hpp
index 62804b47d93..1962d3173b7 100644
--- a/src/hotspot/share/gc/g1/g1HeapRegion.hpp
+++ b/src/hotspot/share/gc/g1/g1HeapRegion.hpp
@@ -316,6 +316,7 @@ public:
}
static size_t max_region_size();
+ static size_t max_ergonomics_size();
static size_t min_region_size_in_words();
// It sets up the heap region size (GrainBytes / GrainWords), as well as
diff --git a/src/hotspot/share/gc/parallel/objectStartArray.cpp b/src/hotspot/share/gc/parallel/objectStartArray.cpp
index e8d94b28d18..d2c91b302b5 100644
--- a/src/hotspot/share/gc/parallel/objectStartArray.cpp
+++ b/src/hotspot/share/gc/parallel/objectStartArray.cpp
@@ -121,7 +121,7 @@ void ObjectStartArray::update_for_block_work(HeapWord* blk_start,
assert(start_entry_for_region > end_entry, "Sanity check");
}
- debug_only(verify_for_block(blk_start, blk_end);)
+ DEBUG_ONLY(verify_for_block(blk_start, blk_end);)
}
void ObjectStartArray::verify_for_block(HeapWord* blk_start, HeapWord* blk_end) const {
diff --git a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp
index f33d7f93f1d..d2d168cc2c0 100644
--- a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp
+++ b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp
@@ -48,7 +48,8 @@ ParMarkBitMap::initialize(MemRegion covered_region)
ReservedSpace rs = MemoryReserver::reserve(_reserved_byte_size,
rs_align,
- page_sz);
+ page_sz,
+ mtGC);
if (!rs.is_reserved()) {
// Failed to reserve memory for the bitmap,
diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp
index e63ff686312..ed8df5d42f6 100644
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp
@@ -246,7 +246,8 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size)
ReservedSpace rs = MemoryReserver::reserve(_reserved_byte_size,
rs_align,
- page_sz);
+ page_sz,
+ mtGC);
if (!rs.is_reserved()) {
// Failed to reserve memory.
@@ -1629,7 +1630,7 @@ void PSParallelCompact::forward_to_new_addr() {
} task(nworkers);
ParallelScavengeHeap::heap()->workers().run_task(&task);
- debug_only(verify_forward();)
+ DEBUG_ONLY(verify_forward();)
}
#ifdef ASSERT
diff --git a/src/hotspot/share/gc/parallel/psPromotionLAB.cpp b/src/hotspot/share/gc/parallel/psPromotionLAB.cpp
index e3ed819ceb1..a6612d5cd2d 100644
--- a/src/hotspot/share/gc/parallel/psPromotionLAB.cpp
+++ b/src/hotspot/share/gc/parallel/psPromotionLAB.cpp
@@ -45,7 +45,7 @@ void PSPromotionLAB::initialize(MemRegion lab) {
// We can be initialized to a zero size!
if (free() > 0) {
if (ZapUnusedHeapArea) {
- debug_only(Copy::fill_to_words(top(), free()/HeapWordSize, badHeapWord));
+ DEBUG_ONLY(Copy::fill_to_words(top(), free()/HeapWordSize, badHeapWord));
}
// NOTE! We need to allow space for a filler object.
diff --git a/src/hotspot/share/gc/parallel/psPromotionLAB.hpp b/src/hotspot/share/gc/parallel/psPromotionLAB.hpp
index e8e42d3754b..60bd4ec250a 100644
--- a/src/hotspot/share/gc/parallel/psPromotionLAB.hpp
+++ b/src/hotspot/share/gc/parallel/psPromotionLAB.hpp
@@ -55,7 +55,7 @@ class PSPromotionLAB : public CHeapObj {
void set_end(HeapWord* value) { _end = value; }
// The shared initialize code invokes this.
- debug_only(virtual bool lab_is_valid(MemRegion lab) { return false; });
+ DEBUG_ONLY(virtual bool lab_is_valid(MemRegion lab) { return false; });
PSPromotionLAB() : _top(nullptr), _bottom(nullptr), _end(nullptr), _state(zero_size) { }
@@ -95,7 +95,7 @@ class PSYoungPromotionLAB : public PSPromotionLAB {
// Not MT safe
inline HeapWord* allocate(size_t size);
- debug_only(virtual bool lab_is_valid(MemRegion lab);)
+ DEBUG_ONLY(virtual bool lab_is_valid(MemRegion lab);)
};
class PSOldPromotionLAB : public PSPromotionLAB {
@@ -127,7 +127,7 @@ class PSOldPromotionLAB : public PSPromotionLAB {
return nullptr;
}
- debug_only(virtual bool lab_is_valid(MemRegion lab));
+ DEBUG_ONLY(virtual bool lab_is_valid(MemRegion lab));
};
#endif // SHARE_GC_PARALLEL_PSPROMOTIONLAB_HPP
diff --git a/src/hotspot/share/gc/serial/serialBlockOffsetTable.cpp b/src/hotspot/share/gc/serial/serialBlockOffsetTable.cpp
index 5baad7f995a..afaf1aba538 100644
--- a/src/hotspot/share/gc/serial/serialBlockOffsetTable.cpp
+++ b/src/hotspot/share/gc/serial/serialBlockOffsetTable.cpp
@@ -155,7 +155,7 @@ void SerialBlockOffsetTable::update_for_block_work(HeapWord* blk_start,
assert(start_card_for_region > end_card, "Sanity check");
}
- debug_only(verify_for_block(blk_start, blk_end);)
+ DEBUG_ONLY(verify_for_block(blk_start, blk_end);)
}
HeapWord* SerialBlockOffsetTable::block_start_reaching_into_card(const void* addr) const {
diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp
index e5dbbcc0746..76fe73abaf6 100644
--- a/src/hotspot/share/gc/shared/cardTable.cpp
+++ b/src/hotspot/share/gc/shared/cardTable.cpp
@@ -80,7 +80,7 @@ void CardTable::initialize(void* region0_start, void* region1_start) {
HeapWord* high_bound = _whole_heap.end();
const size_t rs_align = MAX2(_page_size, os::vm_allocation_granularity());
- ReservedSpace rs = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size);
+ ReservedSpace rs = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size, mtGC);
if (!rs.is_reserved()) {
vm_exit_during_initialization("Could not reserve enough space for the "
diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp
index 439563a4b62..8bf47d6b0bb 100644
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp
@@ -179,7 +179,7 @@ protected:
virtual void trace_heap(GCWhen::Type when, const GCTracer* tracer);
// Verification functions
- debug_only(static void check_for_valid_allocation_state();)
+ DEBUG_ONLY(static void check_for_valid_allocation_state();)
public:
enum Name {
diff --git a/src/hotspot/share/gc/shared/hSpaceCounters.cpp b/src/hotspot/share/gc/shared/hSpaceCounters.cpp
index de5dd2912a5..818d7422fba 100644
--- a/src/hotspot/share/gc/shared/hSpaceCounters.cpp
+++ b/src/hotspot/share/gc/shared/hSpaceCounters.cpp
@@ -82,7 +82,7 @@ void HSpaceCounters::update_all(size_t capacity, size_t used) {
update_used(used);
}
-debug_only(
+DEBUG_ONLY(
// for security reasons, we do not allow arbitrary reads from
// the counters as they may live in shared memory.
jlong HSpaceCounters::used() {
diff --git a/src/hotspot/share/gc/shared/hSpaceCounters.hpp b/src/hotspot/share/gc/shared/hSpaceCounters.hpp
index 63aabf1479b..01310e456f6 100644
--- a/src/hotspot/share/gc/shared/hSpaceCounters.hpp
+++ b/src/hotspot/share/gc/shared/hSpaceCounters.hpp
@@ -56,7 +56,7 @@ class HSpaceCounters: public CHeapObj {
void update_all(size_t capacity, size_t used);
- debug_only(
+ DEBUG_ONLY(
// for security reasons, we do not allow arbitrary reads from
// the counters as they may live in shared memory.
jlong used();
diff --git a/src/hotspot/share/gc/shared/memAllocator.cpp b/src/hotspot/share/gc/shared/memAllocator.cpp
index 74ef1f66184..a8ba2074cd1 100644
--- a/src/hotspot/share/gc/shared/memAllocator.cpp
+++ b/src/hotspot/share/gc/shared/memAllocator.cpp
@@ -126,6 +126,10 @@ bool MemAllocator::Allocation::check_out_of_memory() {
// -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support
report_java_out_of_memory(message);
if (JvmtiExport::should_post_resource_exhausted()) {
+#ifdef CHECK_UNHANDLED_OOPS
+ // obj is null, no need to handle, but CheckUnhandledOops is not aware about null
+ THREAD->allow_unhandled_oop(_obj_ptr);
+#endif // CHECK_UNHANDLED_OOPS
JvmtiExport::post_resource_exhausted(
JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP,
message);
@@ -145,7 +149,7 @@ void MemAllocator::Allocation::verify_before() {
// not take out a lock if from tlab, so clear here.
JavaThread* THREAD = _thread; // For exception macros.
assert(!HAS_PENDING_EXCEPTION, "Should not allocate with exception pending");
- debug_only(check_for_valid_allocation_state());
+ DEBUG_ONLY(check_for_valid_allocation_state());
assert(!Universe::heap()->is_stw_gc_active(), "Allocation during GC pause not allowed");
}
@@ -327,7 +331,7 @@ HeapWord* MemAllocator::mem_allocate(Allocation& allocation) const {
}
// Allocation of an oop can always invoke a safepoint.
- debug_only(allocation._thread->check_for_valid_safepoint_state());
+ DEBUG_ONLY(allocation._thread->check_for_valid_safepoint_state());
if (UseTLAB) {
// Try refilling the TLAB and allocating the object in it.
diff --git a/src/hotspot/share/gc/shared/scavengableNMethods.cpp b/src/hotspot/share/gc/shared/scavengableNMethods.cpp
index 0dff5526911..887ac5f43a2 100644
--- a/src/hotspot/share/gc/shared/scavengableNMethods.cpp
+++ b/src/hotspot/share/gc/shared/scavengableNMethods.cpp
@@ -131,13 +131,13 @@ bool ScavengableNMethods::has_scavengable_oops(nmethod* nm) {
void ScavengableNMethods::nmethods_do_and_prune(NMethodToOopClosure* cl) {
assert_locked_or_safepoint(CodeCache_lock);
- debug_only(mark_on_list_nmethods());
+ DEBUG_ONLY(mark_on_list_nmethods());
nmethod* prev = nullptr;
nmethod* cur = _head;
while (cur != nullptr) {
ScavengableNMethodsData data = gc_data(cur);
- debug_only(data.clear_marked());
+ DEBUG_ONLY(data.clear_marked());
assert(data.on_list(), "else shouldn't be on this list");
if (cl != nullptr) {
@@ -156,7 +156,7 @@ void ScavengableNMethods::nmethods_do_and_prune(NMethodToOopClosure* cl) {
}
// Check for stray marks.
- debug_only(verify_nmethods());
+ DEBUG_ONLY(verify_nmethods());
}
void ScavengableNMethods::prune_nmethods_not_into_young() {
@@ -166,13 +166,13 @@ void ScavengableNMethods::prune_nmethods_not_into_young() {
void ScavengableNMethods::prune_unlinked_nmethods() {
assert_locked_or_safepoint(CodeCache_lock);
- debug_only(mark_on_list_nmethods());
+ DEBUG_ONLY(mark_on_list_nmethods());
nmethod* prev = nullptr;
nmethod* cur = _head;
while (cur != nullptr) {
ScavengableNMethodsData data = gc_data(cur);
- debug_only(data.clear_marked());
+ DEBUG_ONLY(data.clear_marked());
assert(data.on_list(), "else shouldn't be on this list");
nmethod* const next = data.next();
@@ -187,7 +187,7 @@ void ScavengableNMethods::prune_unlinked_nmethods() {
}
// Check for stray marks.
- debug_only(verify_nmethods());
+ DEBUG_ONLY(verify_nmethods());
}
// Walk the list of methods which might contain oops to the java heap.
diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp
index d71e84d33b0..f12b3dc5fa8 100644
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp
@@ -896,7 +896,7 @@ void ShenandoahBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCo
uint gc_state_idx = Compile::AliasIdxRaw;
const TypePtr* gc_state_adr_type = nullptr; // debug-mode-only argument
- debug_only(gc_state_adr_type = phase->C->get_adr_type(gc_state_idx));
+ DEBUG_ONLY(gc_state_adr_type = phase->C->get_adr_type(gc_state_idx));
Node* gc_state = phase->transform_later(new LoadBNode(ctrl, mem, gc_state_addr, gc_state_adr_type, TypeInt::BYTE, MemNode::unordered));
Node* stable_and = phase->transform_later(new AndINode(gc_state, phase->igvn().intcon(ShenandoahHeap::HAS_FORWARDED)));
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp
index cf1a76ff4ff..2d0bbfd5e4a 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp
@@ -639,12 +639,9 @@ bool ShenandoahOldHeuristics::should_resume_old_cycle() {
bool ShenandoahOldHeuristics::should_start_gc() {
const ShenandoahHeap* heap = ShenandoahHeap::heap();
- if (_old_generation->is_doing_mixed_evacuations()) {
- // Do not try to start an old cycle if we are waiting for old regions to be evacuated (we need
- // a young cycle for this). Note that the young heuristic has a feature to expedite old evacuations.
- // Future refinement: under certain circumstances, we might be more sophisticated about this choice.
- // For example, we could choose to abandon the previous old collection before it has completed evacuations.
- log_debug(gc)("Not starting an old cycle because we are waiting for mixed evacuations");
+ if (!_old_generation->is_idle()) {
+ // Do not try to start an old cycle if old-gen is marking, doing mixed evacuations, or coalescing and filling.
+ log_debug(gc)("Not starting an old cycle because old gen is busy");
return false;
}
diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp
index ba09eeb8794..3aca436104b 100644
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahYoungHeuristics.cpp
@@ -120,6 +120,7 @@ bool ShenandoahYoungHeuristics::should_start_gc() {
if (old_time_elapsed < ShenandoahMinimumOldTimeMs) {
// Do not decline_trigger() when waiting for minimum quantum of Old-gen marking. It is not at our discretion
// to trigger at this time.
+ log_debug(gc)("Young heuristics declines to trigger because old_time_elapsed < ShenandoahMinimumOldTimeMs");
return false;
}
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp
index 00f11938489..e9e52475fb9 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCardTable.cpp
@@ -45,7 +45,7 @@ void ShenandoahCardTable::initialize() {
// ReservedSpace constructor would assert rs_align >= os::vm_page_size().
const size_t rs_align = MAX2(_page_size, granularity);
- ReservedSpace write_space = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size);
+ ReservedSpace write_space = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size, mtGC);
initialize(write_space);
// The assembler store_check code will do an unsigned shift of the oop,
@@ -60,7 +60,7 @@ void ShenandoahCardTable::initialize() {
_write_byte_map = _byte_map;
_write_byte_map_base = _byte_map_base;
- ReservedSpace read_space = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size);
+ ReservedSpace read_space = MemoryReserver::reserve(_byte_map_size, rs_align, _page_size, mtGC);
initialize(read_space);
_read_byte_map = (CardValue*) read_space.base();
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp
index 1d353163463..25b900f8d77 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp
@@ -190,11 +190,11 @@ void ShenandoahCollectionSet::print_on(outputStream* out) const {
byte_size_in_proper_unit(live()), proper_unit_for_byte_size(live()),
byte_size_in_proper_unit(used()), proper_unit_for_byte_size(used()));
- debug_only(size_t regions = 0;)
+ DEBUG_ONLY(size_t regions = 0;)
for (size_t index = 0; index < _heap->num_regions(); index ++) {
if (is_in(index)) {
_heap->get_region(index)->print_on(out);
- debug_only(regions ++;)
+ DEBUG_ONLY(regions ++;)
}
}
assert(regions == count(), "Must match");
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
index 6975bd9f350..d8eb8e0a4e1 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp
@@ -299,7 +299,10 @@ void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cau
// Full GC --------------------------/
//
ShenandoahHeap* heap = ShenandoahHeap::heap();
- if (check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle)) return;
+ if (check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle)) {
+ log_info(gc)("Cancelled");
+ return;
+ }
ShenandoahGCSession session(cause, heap->global_generation());
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp
index fe4679bbf05..6b33d5207d0 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp
@@ -482,17 +482,14 @@ bool ShenandoahGenerationalControlThread::resume_concurrent_old_cycle(Shenandoah
}
if (_heap->cancelled_gc()) {
- // It's possible the gc cycle was cancelled after the last time
- // the collection checked for cancellation. In which case, the
- // old gc cycle is still completed, and we have to deal with this
- // cancellation. We set the degeneration point to be outside
- // the cycle because if this is an allocation failure, that is
- // what must be done (there is no degenerated old cycle). If the
- // cancellation was due to a heuristic wanting to start a young
- // cycle, then we are not actually going to a degenerated cycle,
- // so the degenerated point doesn't matter here.
- check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle);
- if (cause == GCCause::_shenandoah_concurrent_gc) {
+ // It's possible the gc cycle was cancelled after the last time the collection checked for cancellation. In which
+ // case, the old gc cycle is still completed, and we have to deal with this cancellation. We set the degeneration
+ // point to be outside the cycle because if this is an allocation failure, that is what must be done (there is no
+ // degenerated old cycle). If the cancellation was due to a heuristic wanting to start a young cycle, then we are
+ // not actually going to a degenerated cycle, so don't set the degeneration point here.
+ if (ShenandoahCollectorPolicy::is_allocation_failure(cause)) {
+ check_cancellation_or_degen(ShenandoahGC::_degenerated_outside_cycle);
+ } else if (cause == GCCause::_shenandoah_concurrent_gc) {
_heap->shenandoah_policy()->record_interrupted_old();
}
return false;
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
index b5b8e4b9e1a..41faf3efa24 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
@@ -161,7 +161,7 @@ static ReservedSpace reserve(size_t size, size_t preferred_page_size) {
size = align_up(size, alignment);
}
- const ReservedSpace reserved = MemoryReserver::reserve(size, alignment, preferred_page_size);
+ const ReservedSpace reserved = MemoryReserver::reserve(size, alignment, preferred_page_size, mtGC);
if (!reserved.is_reserved()) {
vm_exit_during_initialization("Could not reserve space");
}
@@ -375,7 +375,7 @@ jint ShenandoahHeap::initialize() {
for (uintptr_t addr = min; addr <= max; addr <<= 1u) {
char* req_addr = (char*)addr;
assert(is_aligned(req_addr, cset_align), "Should be aligned");
- cset_rs = MemoryReserver::reserve(req_addr, cset_size, cset_align, cset_page_size);
+ cset_rs = MemoryReserver::reserve(req_addr, cset_size, cset_align, cset_page_size, mtGC);
if (cset_rs.is_reserved()) {
assert(cset_rs.base() == req_addr, "Allocated where requested: " PTR_FORMAT ", " PTR_FORMAT, p2i(cset_rs.base()), addr);
_collection_set = new ShenandoahCollectionSet(this, cset_rs, sh_rs.base());
@@ -384,7 +384,7 @@ jint ShenandoahHeap::initialize() {
}
if (_collection_set == nullptr) {
- cset_rs = MemoryReserver::reserve(cset_size, cset_align, os::vm_page_size());
+ cset_rs = MemoryReserver::reserve(cset_size, cset_align, os::vm_page_size(), mtGC);
if (!cset_rs.is_reserved()) {
vm_exit_during_initialization("Cannot reserve memory for collection set");
}
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp
index bf309af9743..774c4f7d941 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp
@@ -67,22 +67,18 @@ void ShenandoahRegulatorThread::regulate_young_and_old_cycles() {
_global_heuristics->cancel_trigger_request();
}
} else {
- if (_young_heuristics->should_start_gc()) {
- // Give the old generation a chance to run. The old generation cycle
- // begins with a 'bootstrap' cycle that will also collect young.
- if (start_old_cycle()) {
- log_debug(gc)("Heuristics request for old collection accepted");
- _young_heuristics->cancel_trigger_request();
- _old_heuristics->cancel_trigger_request();
- } else if (request_concurrent_gc(_heap->young_generation())) {
- log_debug(gc)("Heuristics request for young collection accepted");
- _young_heuristics->cancel_trigger_request();
- }
- } else if (_old_heuristics->should_resume_old_cycle() || _old_heuristics->should_start_gc()) {
+ if (_old_heuristics->should_resume_old_cycle()) {
if (request_concurrent_gc(_heap->old_generation())) {
_old_heuristics->cancel_trigger_request();
log_debug(gc)("Heuristics request to resume old collection accepted");
}
+ } else if (start_old_cycle()) {
+ log_debug(gc)("Heuristics request for old collection accepted");
+ _young_heuristics->cancel_trigger_request();
+ _old_heuristics->cancel_trigger_request();
+ } else if (start_young_cycle()) {
+ log_debug(gc)("Heuristics request for young collection accepted");
+ _young_heuristics->cancel_trigger_request();
}
}
} else if (mode == ShenandoahGenerationalControlThread::servicing_old) {
diff --git a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp
index 342b599caf5..af661fd1dc4 100644
--- a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp
@@ -309,14 +309,14 @@ private:
volatile jint _claimed_index;
shenandoah_padding(1);
- debug_only(uint _reserved; )
+ DEBUG_ONLY(uint _reserved; )
public:
using GenericTaskQueueSet::size;
public:
ParallelClaimableQueueSet(int n) : GenericTaskQueueSet(n), _claimed_index(0) {
- debug_only(_reserved = 0; )
+ DEBUG_ONLY(_reserved = 0; )
}
void clear_claimed() { _claimed_index = 0; }
@@ -326,10 +326,10 @@ public:
void reserve(uint n) {
assert(n <= size(), "Sanity");
_claimed_index = (jint)n;
- debug_only(_reserved = n;)
+ DEBUG_ONLY(_reserved = n;)
}
- debug_only(uint get_reserved() const { return (uint)_reserved; })
+ DEBUG_ONLY(uint get_reserved() const { return (uint)_reserved; })
};
template
diff --git a/src/hotspot/share/interpreter/oopMapCache.cpp b/src/hotspot/share/interpreter/oopMapCache.cpp
index 62ce860594b..e577ce42c1e 100644
--- a/src/hotspot/share/interpreter/oopMapCache.cpp
+++ b/src/hotspot/share/interpreter/oopMapCache.cpp
@@ -311,7 +311,7 @@ void OopMapCacheEntry::deallocate_bit_mask() {
assert(!Thread::current()->resource_area()->contains((void*)_bit_mask[0]),
"This bit mask should not be in the resource area");
FREE_C_HEAP_ARRAY(uintptr_t, _bit_mask[0]);
- debug_only(_bit_mask[0] = 0;)
+ DEBUG_ONLY(_bit_mask[0] = 0;)
}
}
diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
index 8dbc3d4fcea..7736d3f4565 100644
--- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
+++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp
@@ -504,7 +504,7 @@ void JfrCheckpointManager::begin_epoch_shift() {
void JfrCheckpointManager::end_epoch_shift() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
- debug_only(const u1 current_epoch = JfrTraceIdEpoch::current();)
+ DEBUG_ONLY(const u1 current_epoch = JfrTraceIdEpoch::current();)
JfrTraceIdEpoch::end_epoch_shift();
assert(current_epoch != JfrTraceIdEpoch::current(), "invariant");
JfrStringPool::on_epoch_shift();
diff --git a/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp b/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp
index a7a21f65944..ca54b297b38 100644
--- a/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp
+++ b/src/hotspot/share/jfr/recorder/storage/jfrStorage.cpp
@@ -398,7 +398,7 @@ static void assert_flush_large_precondition(ConstBufferPtr cur, const u1* const
#endif // ASSERT
BufferPtr JfrStorage::flush(BufferPtr cur, size_t used, size_t req, bool native, Thread* t) {
- debug_only(assert_flush_precondition(cur, used, native, t);)
+ DEBUG_ONLY(assert_flush_precondition(cur, used, native, t);)
const u1* const cur_pos = cur->pos();
req += used;
// requested size now encompass the outstanding used size
@@ -407,7 +407,7 @@ BufferPtr JfrStorage::flush(BufferPtr cur, size_t used, size_t req, bool native,
}
BufferPtr JfrStorage::flush_regular(BufferPtr cur, const u1* const cur_pos, size_t used, size_t req, bool native, Thread* t) {
- debug_only(assert_flush_regular_precondition(cur, cur_pos, used, req, t);)
+ DEBUG_ONLY(assert_flush_regular_precondition(cur, cur_pos, used, req, t);)
// A flush is needed before memmove since a non-large buffer is thread stable
// (thread local). The flush will not modify memory in addresses above pos()
// which is where the "used / uncommitted" data resides. It is therefore both
@@ -450,7 +450,7 @@ static BufferPtr restore_shelved_buffer(bool native, Thread* t) {
}
BufferPtr JfrStorage::flush_large(BufferPtr cur, const u1* const cur_pos, size_t used, size_t req, bool native, Thread* t) {
- debug_only(assert_flush_large_precondition(cur, cur_pos, used, req, native, t);)
+ DEBUG_ONLY(assert_flush_large_precondition(cur, cur_pos, used, req, native, t);)
// Can the "regular" buffer (now shelved) accommodate the requested size?
BufferPtr shelved = t->jfr_thread_local()->shelved_buffer();
assert(shelved != nullptr, "invariant");
@@ -480,7 +480,7 @@ static BufferPtr large_fail(BufferPtr cur, bool native, JfrStorage& storage_inst
// even though it might be smaller than the requested size.
// Caller needs to ensure if the size was successfully accommodated.
BufferPtr JfrStorage::provision_large(BufferPtr cur, const u1* const cur_pos, size_t used, size_t req, bool native, Thread* t) {
- debug_only(assert_provision_large_precondition(cur, used, req, t);)
+ DEBUG_ONLY(assert_provision_large_precondition(cur, used, req, t);)
assert(t->jfr_thread_local()->shelved_buffer() != nullptr, "invariant");
BufferPtr const buffer = acquire_large(req, t);
if (buffer == nullptr) {
diff --git a/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp b/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp
index 97f2b8a1990..0ba54fc79be 100644
--- a/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp
+++ b/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp
@@ -106,7 +106,8 @@ bool JfrVirtualMemorySegment::initialize(size_t reservation_size_request_bytes)
assert(is_aligned(reservation_size_request_bytes, os::vm_allocation_granularity()), "invariant");
_rs = MemoryReserver::reserve(reservation_size_request_bytes,
os::vm_allocation_granularity(),
- os::vm_page_size());
+ os::vm_page_size(),
+ mtTracing);
if (!_rs.is_reserved()) {
return false;
}
diff --git a/src/hotspot/share/jfr/utilities/jfrAllocation.cpp b/src/hotspot/share/jfr/utilities/jfrAllocation.cpp
index f97838c7869..faf0baf2bcb 100644
--- a/src/hotspot/share/jfr/utilities/jfrAllocation.cpp
+++ b/src/hotspot/share/jfr/utilities/jfrAllocation.cpp
@@ -83,7 +83,7 @@ static void hook_memory_allocation(const char* allocation, size_t alloc_size) {
vm_exit_out_of_memory(alloc_size, OOM_MALLOC_ERROR, "AllocateHeap");
}
}
- debug_only(add(alloc_size));
+ DEBUG_ONLY(add(alloc_size));
}
void JfrCHeapObj::on_memory_allocation(const void* allocation, size_t size) {
@@ -111,12 +111,12 @@ void* JfrCHeapObj::operator new [](size_t size, const std::nothrow_t& nothrow_c
}
void JfrCHeapObj::operator delete(void* p, size_t size) {
- debug_only(hook_memory_deallocation(size);)
+ DEBUG_ONLY(hook_memory_deallocation(size);)
CHeapObj::operator delete(p);
}
void JfrCHeapObj::operator delete[](void* p, size_t size) {
- debug_only(hook_memory_deallocation(size);)
+ DEBUG_ONLY(hook_memory_deallocation(size);)
CHeapObj::operator delete[](p);
}
@@ -127,7 +127,7 @@ char* JfrCHeapObj::realloc_array(char* old, size_t size) {
}
void JfrCHeapObj::free(void* p, size_t size) {
- debug_only(hook_memory_deallocation(size);)
+ DEBUG_ONLY(hook_memory_deallocation(size);)
FreeHeap(p);
}
diff --git a/src/hotspot/share/jfr/utilities/jfrDoublyLinkedList.hpp b/src/hotspot/share/jfr/utilities/jfrDoublyLinkedList.hpp
index 4e66af7f478..814f15017e0 100644
--- a/src/hotspot/share/jfr/utilities/jfrDoublyLinkedList.hpp
+++ b/src/hotspot/share/jfr/utilities/jfrDoublyLinkedList.hpp
@@ -205,7 +205,7 @@ void JfrDoublyLinkedList::append_list(T* const head_node, T* const tail_node,
}
*lt = tail_node;
const T* node = head_node;
- debug_only(validate_count_param(node, count);)
+ DEBUG_ONLY(validate_count_param(node, count);)
_count += count;
assert(tail() == tail_node, "invariant");
assert(in_list(tail_node), "not in list error");
diff --git a/src/hotspot/share/jfr/utilities/jfrSpinlockHelper.hpp b/src/hotspot/share/jfr/utilities/jfrSpinlockHelper.hpp
index 8d381a646ee..4b5ca80470e 100644
--- a/src/hotspot/share/jfr/utilities/jfrSpinlockHelper.hpp
+++ b/src/hotspot/share/jfr/utilities/jfrSpinlockHelper.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,11 +33,7 @@ class JfrSpinlockHelper {
public:
JfrSpinlockHelper(volatile int* lock) : _lock(lock) {
- Thread::SpinAcquire(_lock, nullptr);
- }
-
- JfrSpinlockHelper(volatile int* const lock, const char* name) : _lock(lock) {
- Thread::SpinAcquire(_lock, name);
+ Thread::SpinAcquire(_lock);
}
~JfrSpinlockHelper() {
diff --git a/src/hotspot/share/jfr/writers/jfrMemoryWriterHost.hpp b/src/hotspot/share/jfr/writers/jfrMemoryWriterHost.hpp
index ad47c954fd7..af87f2bc5fb 100644
--- a/src/hotspot/share/jfr/writers/jfrMemoryWriterHost.hpp
+++ b/src/hotspot/share/jfr/writers/jfrMemoryWriterHost.hpp
@@ -45,7 +45,7 @@ class ExclusiveAccessAssert {
template
class MemoryWriterHost : public StorageHost {
- debug_only(AccessAssert _access;)
+ DEBUG_ONLY(AccessAssert _access;)
public:
typedef typename Adapter::StorageType StorageType;
protected:
@@ -53,7 +53,7 @@ class MemoryWriterHost : public StorageHost {
MemoryWriterHost(StorageType* storage, Thread* thread);
MemoryWriterHost(StorageType* storage, size_t size);
MemoryWriterHost(Thread* thread);
- debug_only(bool is_acquired() const;)
+ DEBUG_ONLY(bool is_acquired() const;)
public:
void acquire();
void release();
diff --git a/src/hotspot/share/jfr/writers/jfrMemoryWriterHost.inline.hpp b/src/hotspot/share/jfr/writers/jfrMemoryWriterHost.inline.hpp
index 55229e5d732..ad16b7abde3 100644
--- a/src/hotspot/share/jfr/writers/jfrMemoryWriterHost.inline.hpp
+++ b/src/hotspot/share/jfr/writers/jfrMemoryWriterHost.inline.hpp
@@ -52,18 +52,18 @@ inline MemoryWriterHost::MemoryWriterHost(Thread* thr
template
inline void MemoryWriterHost::acquire() {
- debug_only(_access.acquire();)
+ DEBUG_ONLY(_access.acquire();)
if (!this->is_valid()) {
this->flush();
}
- debug_only(is_acquired();)
+ DEBUG_ONLY(is_acquired();)
}
template
inline void MemoryWriterHost::release() {
- debug_only(is_acquired();)
+ DEBUG_ONLY(is_acquired();)
StorageHost::release();
- debug_only(_access.release();)
+ DEBUG_ONLY(_access.release();)
}
#ifdef ASSERT
diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
index cffac62c1c8..a4a8f3bb1d0 100644
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
@@ -173,7 +173,7 @@ Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) {
ThreadInVMfromNative __tiv(thread); \
HandleMarkCleaner __hm(thread); \
JavaThread* THREAD = thread; \
- debug_only(VMNativeEntryWrapper __vew;)
+ DEBUG_ONLY(VMNativeEntryWrapper __vew;)
// Native method block that transitions current thread to '_thread_in_vm'.
// Note: CompilerThreadCanCallJava must precede JVMCIENV_FROM_JNI so that
diff --git a/src/hotspot/share/jvmci/jvmci_globals.cpp b/src/hotspot/share/jvmci/jvmci_globals.cpp
index dfc7e6b5970..a41351218f8 100644
--- a/src/hotspot/share/jvmci/jvmci_globals.cpp
+++ b/src/hotspot/share/jvmci/jvmci_globals.cpp
@@ -144,8 +144,9 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() {
JVMCI_FLAG_CHECKED(UseMulAddIntrinsic)
JVMCI_FLAG_CHECKED(UseMontgomeryMultiplyIntrinsic)
JVMCI_FLAG_CHECKED(UseMontgomerySquareIntrinsic)
- JVMCI_FLAG_CHECKED(UseVectorStubs)
#endif // !COMPILER2
+ //
+ JVMCI_FLAG_CHECKED(UseVectorStubs)
#ifndef PRODUCT
#define JVMCI_CHECK4(type, name, value, ...) assert(name##checked, #name " flag not checked");
diff --git a/src/hotspot/share/jvmci/jvmci_globals.hpp b/src/hotspot/share/jvmci/jvmci_globals.hpp
index 4da49b24e6e..5bcead9ff7b 100644
--- a/src/hotspot/share/jvmci/jvmci_globals.hpp
+++ b/src/hotspot/share/jvmci/jvmci_globals.hpp
@@ -184,8 +184,8 @@ class fileStream;
NOT_COMPILER2(product(bool, EnableVectorAggressiveReboxing, false, EXPERIMENTAL, \
"Enables aggressive reboxing of vectors")) \
\
- NOT_COMPILER2(product(bool, UseVectorStubs, false, EXPERIMENTAL, \
- "Use stubs for vector transcendental operations")) \
+ product(bool, UseVectorStubs, false, EXPERIMENTAL, \
+ "Use stubs for vector transcendental operations") \
// end of JVMCI_FLAGS
diff --git a/src/hotspot/share/logging/logConfiguration.cpp b/src/hotspot/share/logging/logConfiguration.cpp
index 662c1f1c2bb..b883dbccacf 100644
--- a/src/hotspot/share/logging/logConfiguration.cpp
+++ b/src/hotspot/share/logging/logConfiguration.cpp
@@ -59,17 +59,17 @@ class ConfigurationLock : public StackObj {
private:
// Semaphore used as lock
static Semaphore _semaphore;
- debug_only(static intx _locking_thread_id;)
+ DEBUG_ONLY(static intx _locking_thread_id;)
public:
ConfigurationLock() {
_semaphore.wait();
- debug_only(_locking_thread_id = os::current_thread_id());
+ DEBUG_ONLY(_locking_thread_id = os::current_thread_id());
}
~ConfigurationLock() {
- debug_only(_locking_thread_id = -1);
+ DEBUG_ONLY(_locking_thread_id = -1);
_semaphore.signal();
}
- debug_only(static bool current_thread_has_lock();)
+ DEBUG_ONLY(static bool current_thread_has_lock();)
};
Semaphore ConfigurationLock::_semaphore(1);
diff --git a/src/hotspot/share/memory/allocation.inline.hpp b/src/hotspot/share/memory/allocation.inline.hpp
index 8d531c6dd23..01af1616ce1 100644
--- a/src/hotspot/share/memory/allocation.inline.hpp
+++ b/src/hotspot/share/memory/allocation.inline.hpp
@@ -58,7 +58,7 @@ template
E* MmapArrayAllocator::allocate_or_null(size_t length, MemTag mem_tag) {
size_t size = size_for(length);
- char* addr = os::reserve_memory(size, !ExecMem, mem_tag);
+ char* addr = os::reserve_memory(size, mem_tag);
if (addr == nullptr) {
return nullptr;
}
@@ -75,7 +75,7 @@ template
E* MmapArrayAllocator::allocate(size_t length, MemTag mem_tag) {
size_t size = size_for(length);
- char* addr = os::reserve_memory(size, !ExecMem, mem_tag);
+ char* addr = os::reserve_memory(size, mem_tag);
if (addr == nullptr) {
vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "Allocator (reserve)");
}
diff --git a/src/hotspot/share/memory/memoryReserver.cpp b/src/hotspot/share/memory/memoryReserver.cpp
index 43cc71355ff..457818139cd 100644
--- a/src/hotspot/share/memory/memoryReserver.cpp
+++ b/src/hotspot/share/memory/memoryReserver.cpp
@@ -90,13 +90,13 @@ static char* reserve_memory_inner(char* requested_address,
assert(is_aligned(requested_address, alignment),
"Requested address " PTR_FORMAT " must be aligned to %zu",
p2i(requested_address), alignment);
- return os::attempt_reserve_memory_at(requested_address, size, exec, mem_tag);
+ return os::attempt_reserve_memory_at(requested_address, size, mem_tag, exec);
}
// Optimistically assume that the OS returns an aligned base pointer.
// When reserving a large address range, most OSes seem to align to at
// least 64K.
- char* base = os::reserve_memory(size, exec, mem_tag);
+ char* base = os::reserve_memory(size, mem_tag, exec);
if (is_aligned(base, alignment)) {
return base;
}
@@ -107,7 +107,7 @@ static char* reserve_memory_inner(char* requested_address,
}
// Map using the requested alignment.
- return os::reserve_memory_aligned(size, alignment, exec);
+ return os::reserve_memory_aligned(size, alignment, mem_tag, exec);
}
ReservedSpace MemoryReserver::reserve_memory(char* requested_address,
@@ -261,7 +261,7 @@ static char* map_memory_to_file(char* requested_address,
// Optimistically assume that the OS returns an aligned base pointer.
// When reserving a large address range, most OSes seem to align to at
// least 64K.
- char* base = os::map_memory_to_file(size, fd);
+ char* base = os::map_memory_to_file(size, fd, mem_tag);
if (is_aligned(base, alignment)) {
return base;
}
diff --git a/src/hotspot/share/memory/memoryReserver.hpp b/src/hotspot/share/memory/memoryReserver.hpp
index 1e16ec252a9..f8f642cca95 100644
--- a/src/hotspot/share/memory/memoryReserver.hpp
+++ b/src/hotspot/share/memory/memoryReserver.hpp
@@ -58,12 +58,12 @@ public:
size_t size,
size_t alignment,
size_t page_size,
- MemTag mem_tag = mtNone);
+ MemTag mem_tag);
static ReservedSpace reserve(size_t size,
size_t alignment,
size_t page_size,
- MemTag mem_tag = mtNone);
+ MemTag mem_tag);
static ReservedSpace reserve(size_t size,
MemTag mem_tag);
diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp
index ab7202d046a..c28360e5553 100644
--- a/src/hotspot/share/memory/metaspace.cpp
+++ b/src/hotspot/share/memory/metaspace.cpp
@@ -598,7 +598,7 @@ ReservedSpace Metaspace::reserve_address_space_for_compressed_classes(size_t siz
if (result == nullptr) {
// Fallback: reserve anywhere
log_debug(metaspace, map)("Trying anywhere...");
- result = os::reserve_memory_aligned(size, Metaspace::reserve_alignment(), false);
+ result = os::reserve_memory_aligned(size, Metaspace::reserve_alignment(), mtClass);
}
// Wrap resulting range in ReservedSpace
@@ -771,7 +771,8 @@ void Metaspace::global_initialize() {
rs = MemoryReserver::reserve((char*)base,
size,
Metaspace::reserve_alignment(),
- os::vm_page_size());
+ os::vm_page_size(),
+ mtClass);
if (rs.is_reserved()) {
log_info(metaspace)("Successfully forced class space address to " PTR_FORMAT, p2i(base));
diff --git a/src/hotspot/share/memory/metaspace/testHelpers.cpp b/src/hotspot/share/memory/metaspace/testHelpers.cpp
index 76fa1e36c45..f06f6c855be 100644
--- a/src/hotspot/share/memory/metaspace/testHelpers.cpp
+++ b/src/hotspot/share/memory/metaspace/testHelpers.cpp
@@ -82,7 +82,7 @@ MetaspaceTestContext::MetaspaceTestContext(const char* name, size_t commit_limit
reserve_limit, Metaspace::reserve_alignment_words());
if (reserve_limit > 0) {
// have reserve limit -> non-expandable context
- _rs = MemoryReserver::reserve(reserve_limit * BytesPerWord, Metaspace::reserve_alignment(), os::vm_page_size());
+ _rs = MemoryReserver::reserve(reserve_limit * BytesPerWord, Metaspace::reserve_alignment(), os::vm_page_size(), mtTest);
_context = MetaspaceContext::create_nonexpandable_context(name, _rs, &_commit_limiter);
} else {
// no reserve limit -> expandable vslist
@@ -142,4 +142,3 @@ size_t MetaspaceTestContext::reserved_words() const {
}
} // namespace metaspace
-
diff --git a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp
index 66644c805a9..bb59192cf16 100644
--- a/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp
+++ b/src/hotspot/share/memory/metaspace/virtualSpaceNode.cpp
@@ -256,7 +256,7 @@ VirtualSpaceNode* VirtualSpaceNode::create_node(size_t word_size,
ReservedSpace rs = MemoryReserver::reserve(word_size * BytesPerWord,
Settings::virtual_space_node_reserve_alignment_words() * BytesPerWord,
- os::vm_page_size());
+ os::vm_page_size(), mtMetaspace);
if (!rs.is_reserved()) {
vm_exit_out_of_memory(word_size * BytesPerWord, OOM_MMAP_ERROR, "Failed to reserve memory for metaspace");
}
diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp
index e846eb3ddde..156c96d621f 100644
--- a/src/hotspot/share/memory/universe.cpp
+++ b/src/hotspot/share/memory/universe.cpp
@@ -165,8 +165,8 @@ uintx Universe::_the_array_interfaces_bitmap = 0;
uintx Universe::_the_empty_klass_bitmap = 0;
// These variables are guarded by FullGCALot_lock.
-debug_only(OopHandle Universe::_fullgc_alot_dummy_array;)
-debug_only(int Universe::_fullgc_alot_dummy_next = 0;)
+DEBUG_ONLY(OopHandle Universe::_fullgc_alot_dummy_array;)
+DEBUG_ONLY(int Universe::_fullgc_alot_dummy_next = 0;)
// Heap
int Universe::_verify_count = 0;
diff --git a/src/hotspot/share/memory/universe.hpp b/src/hotspot/share/memory/universe.hpp
index 69f8642d6da..35c31330f08 100644
--- a/src/hotspot/share/memory/universe.hpp
+++ b/src/hotspot/share/memory/universe.hpp
@@ -117,8 +117,8 @@ class Universe: AllStatic {
static intptr_t _non_oop_bits;
// array of dummy objects used with +FullGCAlot
- debug_only(static OopHandle _fullgc_alot_dummy_array;)
- debug_only(static int _fullgc_alot_dummy_next;)
+ DEBUG_ONLY(static OopHandle _fullgc_alot_dummy_array;)
+ DEBUG_ONLY(static int _fullgc_alot_dummy_next;)
// Compiler/dispatch support
static int _base_vtable_size; // Java vtbl size of klass Object (in words)
@@ -357,7 +357,7 @@ class Universe: AllStatic {
// Change the number of dummy objects kept reachable by the full gc dummy
// array; this should trigger relocation in a sliding compaction collector.
- debug_only(static bool release_fullgc_alot_dummy();)
+ DEBUG_ONLY(static bool release_fullgc_alot_dummy();)
// The non-oop pattern (see compiledIC.hpp, etc)
static void* non_oop_word();
static bool contains_non_oop_word(void* p);
diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp
index fa1de208804..2c2d629f032 100644
--- a/src/hotspot/share/memory/virtualspace.cpp
+++ b/src/hotspot/share/memory/virtualspace.cpp
@@ -200,7 +200,7 @@ static bool commit_expanded(char* start, size_t size, size_t alignment, bool pre
return true;
}
- debug_only(warning(
+ DEBUG_ONLY(warning(
"INFO: os::commit_memory(" PTR_FORMAT ", " PTR_FORMAT
" size=%zu, executable=%d) failed",
p2i(start), p2i(start + size), size, executable);)
@@ -371,7 +371,7 @@ void VirtualSpace::shrink_by(size_t size) {
aligned_upper_new_high + upper_needs <= upper_high_boundary(),
"must not shrink beyond region");
if (!os::uncommit_memory(aligned_upper_new_high, upper_needs, _executable)) {
- debug_only(warning("os::uncommit_memory failed"));
+ DEBUG_ONLY(warning("os::uncommit_memory failed"));
return;
} else {
_upper_high -= upper_needs;
@@ -382,7 +382,7 @@ void VirtualSpace::shrink_by(size_t size) {
aligned_middle_new_high + middle_needs <= middle_high_boundary(),
"must not shrink beyond region");
if (!os::uncommit_memory(aligned_middle_new_high, middle_needs, _executable)) {
- debug_only(warning("os::uncommit_memory failed"));
+ DEBUG_ONLY(warning("os::uncommit_memory failed"));
return;
} else {
_middle_high -= middle_needs;
@@ -393,7 +393,7 @@ void VirtualSpace::shrink_by(size_t size) {
aligned_lower_new_high + lower_needs <= lower_high_boundary(),
"must not shrink beyond region");
if (!os::uncommit_memory(aligned_lower_new_high, lower_needs, _executable)) {
- debug_only(warning("os::uncommit_memory failed"));
+ DEBUG_ONLY(warning("os::uncommit_memory failed"));
return;
} else {
_lower_high -= lower_needs;
diff --git a/src/hotspot/share/nmt/memReporter.cpp b/src/hotspot/share/nmt/memReporter.cpp
index c7327782a4a..512e1975929 100644
--- a/src/hotspot/share/nmt/memReporter.cpp
+++ b/src/hotspot/share/nmt/memReporter.cpp
@@ -249,7 +249,7 @@ void MemSummaryReporter::report_summary_of_tag(MemTag mem_tag,
// report malloc'd memory
if (amount_in_current_scale(MAX2(malloc_memory->malloc_size(), pk_malloc)) > 0) {
- print_malloc(malloc_memory->malloc_counter());
+ print_malloc(malloc_memory->malloc_counter(), mem_tag);
out->cr();
}
diff --git a/src/hotspot/share/nmt/memReporter.hpp b/src/hotspot/share/nmt/memReporter.hpp
index 05b1588f38b..2238d42f15f 100644
--- a/src/hotspot/share/nmt/memReporter.hpp
+++ b/src/hotspot/share/nmt/memReporter.hpp
@@ -108,7 +108,7 @@ class MemReporterBase : public StackObj {
// Print summary total, malloc and virtual memory
void print_total(size_t reserved, size_t committed, size_t peak = 0) const;
- void print_malloc(const MemoryCounter* c, MemTag mem_tag = mtNone) const;
+ void print_malloc(const MemoryCounter* c, MemTag mem_tag) const;
void print_virtual_memory(size_t reserved, size_t committed, size_t peak) const;
void print_arena(const MemoryCounter* c) const;
diff --git a/src/hotspot/share/nmt/memTracker.hpp b/src/hotspot/share/nmt/memTracker.hpp
index 981e991a41e..3918e81dab7 100644
--- a/src/hotspot/share/nmt/memTracker.hpp
+++ b/src/hotspot/share/nmt/memTracker.hpp
@@ -127,7 +127,7 @@ class MemTracker : AllStatic {
// (we do not do any reservations before that).
static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack,
- MemTag mem_tag = mtNone) {
+ MemTag mem_tag) {
assert_post_init();
if (!enabled()) return;
if (addr != nullptr) {
@@ -153,7 +153,7 @@ class MemTracker : AllStatic {
}
static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size,
- const NativeCallStack& stack, MemTag mem_tag = mtNone) {
+ const NativeCallStack& stack, MemTag mem_tag) {
assert_post_init();
if (!enabled()) return;
if (addr != nullptr) {
diff --git a/src/hotspot/share/nmt/virtualMemoryTracker.hpp b/src/hotspot/share/nmt/virtualMemoryTracker.hpp
index 74d299e6637..2b3b5722571 100644
--- a/src/hotspot/share/nmt/virtualMemoryTracker.hpp
+++ b/src/hotspot/share/nmt/virtualMemoryTracker.hpp
@@ -297,7 +297,7 @@ class ReservedMemoryRegion : public VirtualMemoryRegion {
public:
ReservedMemoryRegion(address base, size_t size, const NativeCallStack& stack,
- MemTag mem_tag = mtNone) :
+ MemTag mem_tag) :
VirtualMemoryRegion(base, size), _stack(stack), _mem_tag(mem_tag) { }
@@ -380,7 +380,7 @@ class VirtualMemoryTracker : AllStatic {
public:
static bool initialize(NMT_TrackingLevel level);
- static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MemTag mem_tag = mtNone);
+ static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MemTag mem_tag);
static bool add_committed_region (address base_addr, size_t size, const NativeCallStack& stack);
static bool remove_uncommitted_region (address base_addr, size_t size);
diff --git a/src/hotspot/share/oops/cpCache.hpp b/src/hotspot/share/oops/cpCache.hpp
index 6490a012e9a..83af4b88e32 100644
--- a/src/hotspot/share/oops/cpCache.hpp
+++ b/src/hotspot/share/oops/cpCache.hpp
@@ -76,7 +76,7 @@ class ConstantPoolCache: public MetaspaceObj {
Array* _resolved_method_entries;
// Sizing
- debug_only(friend class ClassVerifier;)
+ DEBUG_ONLY(friend class ClassVerifier;)
public:
// specific but defiinitions for ldc
diff --git a/src/hotspot/share/oops/generateOopMap.cpp b/src/hotspot/share/oops/generateOopMap.cpp
index a3db976046d..a17d1ca4e37 100644
--- a/src/hotspot/share/oops/generateOopMap.cpp
+++ b/src/hotspot/share/oops/generateOopMap.cpp
@@ -2027,7 +2027,7 @@ void GenerateOopMap::ret_jump_targets_do(BytecodeStream *bcs, jmpFct_t jmpFct, i
int target_bci = rtEnt->jsrs(i);
// Make sure a jrtRet does not set the changed bit for dead basicblock.
BasicBlock* jsr_bb = get_basic_block_containing(target_bci - 1);
- debug_only(BasicBlock* target_bb = &jsr_bb[1];)
+ DEBUG_ONLY(BasicBlock* target_bb = &jsr_bb[1];)
assert(target_bb == get_basic_block_at(target_bci), "wrong calc. of successor basicblock");
bool alive = jsr_bb->is_alive();
if (TraceNewOopMapGeneration) {
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
index 715c8f473d0..00ef75d8486 100644
--- a/src/hotspot/share/oops/instanceKlass.cpp
+++ b/src/hotspot/share/oops/instanceKlass.cpp
@@ -1321,7 +1321,7 @@ void InstanceKlass::initialize_impl(TRAPS) {
// Step 9
if (!HAS_PENDING_EXCEPTION) {
set_initialization_state_and_notify(fully_initialized, CHECK);
- debug_only(vtable().verify(tty, true);)
+ DEBUG_ONLY(vtable().verify(tty, true);)
}
else {
// Step 10 and 11
@@ -2501,6 +2501,7 @@ void InstanceKlass::mark_dependent_nmethods(DeoptimizationScope* deopt_scope, Kl
}
void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
+ assert_lock_strong(CodeCache_lock);
dependencies().add_dependent_nmethod(nm);
}
@@ -4191,7 +4192,7 @@ JNIid::JNIid(Klass* holder, int offset, JNIid* next) {
_holder = holder;
_offset = offset;
_next = next;
- debug_only(_is_static_field_id = false;)
+ DEBUG_ONLY(_is_static_field_id = false;)
}
diff --git a/src/hotspot/share/oops/instanceRefKlass.cpp b/src/hotspot/share/oops/instanceRefKlass.cpp
index eb507495cf5..b8327492493 100644
--- a/src/hotspot/share/oops/instanceRefKlass.cpp
+++ b/src/hotspot/share/oops/instanceRefKlass.cpp
@@ -71,10 +71,10 @@ void InstanceRefKlass::update_nonstatic_oop_maps(Klass* k) {
InstanceKlass* ik = InstanceKlass::cast(k);
// Check that we have the right class
- debug_only(static bool first_time = true);
+ DEBUG_ONLY(static bool first_time = true);
assert(k == vmClasses::Reference_klass() && first_time,
"Invalid update of maps");
- debug_only(first_time = false);
+ DEBUG_ONLY(first_time = false);
assert(ik->nonstatic_oop_map_count() == 1, "just checking");
OopMapBlock* map = ik->start_of_nonstatic_oop_maps();
diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp
index ac0e125ab4c..b0d2e84335e 100644
--- a/src/hotspot/share/oops/klass.cpp
+++ b/src/hotspot/share/oops/klass.cpp
@@ -678,7 +678,7 @@ void Klass::append_to_sibling_list() {
if (Universe::is_fully_initialized()) {
assert_locked_or_safepoint(Compile_lock);
}
- debug_only(verify();)
+ DEBUG_ONLY(verify();)
// add ourselves to superklass' subklass list
InstanceKlass* super = superklass();
if (super == nullptr) return; // special case: class Object
@@ -703,7 +703,7 @@ void Klass::append_to_sibling_list() {
return;
}
}
- debug_only(verify();)
+ DEBUG_ONLY(verify();)
}
void Klass::clean_subklass() {
diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp
index 0c4430b44c3..07f2c559604 100644
--- a/src/hotspot/share/oops/method.cpp
+++ b/src/hotspot/share/oops/method.cpp
@@ -1256,7 +1256,7 @@ address Method::make_adapters(const methodHandle& mh, TRAPS) {
// or adapter that it points to is still live and valid.
// This function must not hit a safepoint!
address Method::verified_code_entry() {
- debug_only(NoSafepointVerifier nsv;)
+ DEBUG_ONLY(NoSafepointVerifier nsv;)
assert(_from_compiled_entry != nullptr, "must be set");
return _from_compiled_entry;
}
diff --git a/src/hotspot/share/opto/block.cpp b/src/hotspot/share/opto/block.cpp
index 5d4ac471303..c33f656047d 100644
--- a/src/hotspot/share/opto/block.cpp
+++ b/src/hotspot/share/opto/block.cpp
@@ -42,7 +42,7 @@ void Block_Array::grow( uint i ) {
if (i < Max()) {
return; // No need to grow
}
- debug_only(_limit = i+1);
+ DEBUG_ONLY(_limit = i+1);
if( i < _size ) return;
if( !_size ) {
_size = 1;
diff --git a/src/hotspot/share/opto/block.hpp b/src/hotspot/share/opto/block.hpp
index 4ac6399d3a0..5baa72dfffb 100644
--- a/src/hotspot/share/opto/block.hpp
+++ b/src/hotspot/share/opto/block.hpp
@@ -48,7 +48,7 @@ struct Tarjan;
// allocation I do not need a destructor to reclaim storage.
class Block_Array : public ArenaObj {
uint _size; // allocated size, as opposed to formal limit
- debug_only(uint _limit;) // limit to formal domain
+ DEBUG_ONLY(uint _limit;) // limit to formal domain
Arena *_arena; // Arena to allocate in
ReallocMark _nesting; // Safety checks for arena reallocation
protected:
@@ -57,7 +57,7 @@ protected:
public:
Block_Array(Arena *a) : _size(OptoBlockListSize), _arena(a) {
- debug_only(_limit=0);
+ DEBUG_ONLY(_limit=0);
_blocks = NEW_ARENA_ARRAY( a, Block *, OptoBlockListSize );
for( int i = 0; i < OptoBlockListSize; i++ ) {
_blocks[i] = nullptr;
@@ -69,7 +69,7 @@ public:
{ assert( i < Max(), "oob" ); return _blocks[i]; }
// Extend the mapping: index i maps to Block *n.
void map( uint i, Block *n ) { grow(i); _blocks[i] = n; }
- uint Max() const { debug_only(return _limit); return _size; }
+ uint Max() const { DEBUG_ONLY(return _limit); return _size; }
};
diff --git a/src/hotspot/share/opto/buildOopMap.cpp b/src/hotspot/share/opto/buildOopMap.cpp
index f135df21114..675113163e8 100644
--- a/src/hotspot/share/opto/buildOopMap.cpp
+++ b/src/hotspot/share/opto/buildOopMap.cpp
@@ -191,7 +191,7 @@ void OopFlow::clone( OopFlow *flow, int max_size ) {
OopFlow *OopFlow::make( Arena *A, int max_size, Compile* C ) {
short *callees = NEW_ARENA_ARRAY(A,short,max_size+1);
Node **defs = NEW_ARENA_ARRAY(A,Node*,max_size+1);
- debug_only( memset(defs,0,(max_size+1)*sizeof(Node*)) );
+ DEBUG_ONLY( memset(defs,0,(max_size+1)*sizeof(Node*)) );
OopFlow *flow = new (A) OopFlow(callees+1, defs+1, C);
assert( &flow->_callees[OptoReg::Bad] == callees, "Ok to index at OptoReg::Bad" );
assert( &flow->_defs [OptoReg::Bad] == defs , "Ok to index at OptoReg::Bad" );
@@ -209,7 +209,7 @@ static void clr_live_bit( int *live, int reg ) {
OopMap *OopFlow::build_oop_map( Node *n, int max_reg, PhaseRegAlloc *regalloc, int* live ) {
int framesize = regalloc->_framesize;
int max_inarg_slot = OptoReg::reg2stack(regalloc->_matcher._new_SP);
- debug_only( char *dup_check = NEW_RESOURCE_ARRAY(char,OptoReg::stack0());
+ DEBUG_ONLY( char *dup_check = NEW_RESOURCE_ARRAY(char,OptoReg::stack0());
memset(dup_check,0,OptoReg::stack0()) );
OopMap *omap = new OopMap( framesize, max_inarg_slot );
@@ -351,7 +351,7 @@ OopMap *OopFlow::build_oop_map( Node *n, int max_reg, PhaseRegAlloc *regalloc, i
} else if( OptoReg::is_valid(_callees[reg])) { // callee-save?
// It's a callee-save value
assert( dup_check[_callees[reg]]==0, "trying to callee save same reg twice" );
- debug_only( dup_check[_callees[reg]]=1; )
+ DEBUG_ONLY( dup_check[_callees[reg]]=1; )
VMReg callee = OptoReg::as_VMReg(OptoReg::Name(_callees[reg]));
omap->set_callee_saved(r, callee);
diff --git a/src/hotspot/share/opto/c2_MacroAssembler.hpp b/src/hotspot/share/opto/c2_MacroAssembler.hpp
index 41347313a8c..1fb7714153d 100644
--- a/src/hotspot/share/opto/c2_MacroAssembler.hpp
+++ b/src/hotspot/share/opto/c2_MacroAssembler.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2025, 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
@@ -31,6 +31,8 @@
#include "utilities/macros.hpp"
class C2EntryBarrierStub;
+class TypeInt;
+class TypeLong;
class C2_MacroAssembler: public MacroAssembler {
public:
diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp
index 41b08161097..2246bd62f4e 100644
--- a/src/hotspot/share/opto/c2_globals.hpp
+++ b/src/hotspot/share/opto/c2_globals.hpp
@@ -669,6 +669,16 @@
develop(bool, VerifyAliases, false, \
"perform extra checks on the results of alias analysis") \
\
+ product(uint, VerifyConstraintCasts, 0, DIAGNOSTIC, \
+ "Perform runtime checks to verify the value of a " \
+ "ConstraintCast lies inside its type" \
+ "0 = does not perform any verification, " \
+ "1 = perform verification on ConstraintCastNodes that are " \
+ "present during code emission, " \
+ "2 = Do not do widening of ConstraintCastNodes so that we can " \
+ "have more verification coverage") \
+ range(0, 2) \
+ \
product(intx, MaxInlineLevel, 15, \
"maximum number of nested calls that are inlined by high tier " \
"compiler") \
@@ -750,9 +760,6 @@
product(bool, EnableVectorAggressiveReboxing, false, EXPERIMENTAL, \
"Enables aggressive reboxing of vectors") \
\
- product(bool, UseVectorStubs, false, EXPERIMENTAL, \
- "Use stubs for vector transcendental operations") \
- \
product(bool, UseTypeSpeculation, true, \
"Speculatively propagate types from profiles") \
\
diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp
index f39937b9cdd..272692446ae 100644
--- a/src/hotspot/share/opto/c2compiler.cpp
+++ b/src/hotspot/share/opto/c2compiler.cpp
@@ -848,6 +848,9 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) {
case vmIntrinsics::_IndexVector:
case vmIntrinsics::_IndexPartiallyInUpperRange:
return EnableVectorSupport;
+ case vmIntrinsics::_VectorUnaryLibOp:
+ case vmIntrinsics::_VectorBinaryLibOp:
+ return EnableVectorSupport && Matcher::supports_vector_calling_convention();
case vmIntrinsics::_blackhole:
#if INCLUDE_JVMTI
case vmIntrinsics::_notifyJvmtiVThreadStart:
diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp
index bb30dcb2976..3527e46c24b 100644
--- a/src/hotspot/share/opto/callnode.cpp
+++ b/src/hotspot/share/opto/callnode.cpp
@@ -266,8 +266,8 @@ JVMState::JVMState(ciMethod* method, JVMState* caller) :
assert(method != nullptr, "must be valid call site");
_bci = InvocationEntryBci;
_reexecute = Reexecute_Undefined;
- debug_only(_bci = -99); // random garbage value
- debug_only(_map = (SafePointNode*)-1);
+ DEBUG_ONLY(_bci = -99); // random garbage value
+ DEBUG_ONLY(_map = (SafePointNode*)-1);
_caller = caller;
_depth = 1 + (caller == nullptr ? 0 : caller->depth());
_locoff = TypeFunc::Parms;
@@ -281,7 +281,7 @@ JVMState::JVMState(int stack_size) :
_method(nullptr) {
_bci = InvocationEntryBci;
_reexecute = Reexecute_Undefined;
- debug_only(_map = (SafePointNode*)-1);
+ DEBUG_ONLY(_map = (SafePointNode*)-1);
_caller = nullptr;
_depth = 1;
_locoff = TypeFunc::Parms;
@@ -323,14 +323,14 @@ bool JVMState::same_calls_as(const JVMState* that) const {
//------------------------------debug_start------------------------------------
uint JVMState::debug_start() const {
- debug_only(JVMState* jvmroot = of_depth(1));
+ DEBUG_ONLY(JVMState* jvmroot = of_depth(1));
assert(jvmroot->locoff() <= this->locoff(), "youngest JVMState must be last");
return of_depth(1)->locoff();
}
//-------------------------------debug_end-------------------------------------
uint JVMState::debug_end() const {
- debug_only(JVMState* jvmroot = of_depth(1));
+ DEBUG_ONLY(JVMState* jvmroot = of_depth(1));
assert(jvmroot->endoff() <= this->endoff(), "youngest JVMState must be last");
return endoff();
}
@@ -1465,7 +1465,7 @@ void SafePointNode::push_monitor(const FastLockNode *lock) {
void SafePointNode::pop_monitor() {
// Delete last monitor from debug info
- debug_only(int num_before_pop = jvms()->nof_monitors());
+ DEBUG_ONLY(int num_before_pop = jvms()->nof_monitors());
const int MonitorEdges = 2;
assert(JVMState::logMonitorEdges == exact_log2(MonitorEdges), "correct MonitorEdges");
int scloff = jvms()->scloff();
diff --git a/src/hotspot/share/opto/castnode.cpp b/src/hotspot/share/opto/castnode.cpp
index 198634af71b..6b3058d94f6 100644
--- a/src/hotspot/share/opto/castnode.cpp
+++ b/src/hotspot/share/opto/castnode.cpp
@@ -531,6 +531,18 @@ const Type* ConstraintCastNode::widen_type(const PhaseGVN* phase, const Type* re
if (!phase->C->post_loop_opts_phase()) {
return res;
}
+
+ // At VerifyConstraintCasts == 1, we verify the ConstraintCastNodes that are present during code
+ // emission. This allows us detecting possible mis-scheduling due to these nodes being pinned at
+ // the wrong control nodes.
+ // At VerifyConstraintCasts == 2, we do not perform widening so that we can verify the
+ // correctness of more ConstraintCastNodes. This further helps us detect possible
+ // mis-transformations that may happen due to these nodes being pinned at the wrong control
+ // nodes.
+ if (VerifyConstraintCasts > 1) {
+ return res;
+ }
+
const TypeInteger* this_type = res->is_integer(bt);
const TypeInteger* in_type = phase->type(in(1))->isa_integer(bt);
if (in_type != nullptr &&
diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp
index 4885d44a13d..92f6c938dba 100644
--- a/src/hotspot/share/opto/cfgnode.cpp
+++ b/src/hotspot/share/opto/cfgnode.cpp
@@ -2233,7 +2233,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
}
// One unique input.
- debug_only(Node* ident = Identity(phase));
+ DEBUG_ONLY(Node* ident = Identity(phase));
// The unique input must eventually be detected by the Identity call.
#ifdef ASSERT
if (ident != uin && !ident->is_top() && !must_wait_for_region_in_irreducible_loop(phase)) {
diff --git a/src/hotspot/share/opto/chaitin.cpp b/src/hotspot/share/opto/chaitin.cpp
index 11e1797d034..7832cbd42f8 100644
--- a/src/hotspot/share/opto/chaitin.cpp
+++ b/src/hotspot/share/opto/chaitin.cpp
@@ -1323,7 +1323,7 @@ void PhaseChaitin::Simplify( ) {
bool bound = lrgs(lo_score)._is_bound;
// Find cheapest guy
- debug_only( int lo_no_simplify=0; );
+ DEBUG_ONLY( int lo_no_simplify=0; );
for (uint i = _hi_degree; i; i = lrgs(i)._next) {
assert(!_ifg->_yanked->test(i), "");
// It's just vaguely possible to move hi-degree to lo-degree without
@@ -1335,7 +1335,7 @@ void PhaseChaitin::Simplify( ) {
lo_score = i;
break;
}
- debug_only( if( lrgs(i)._was_lo ) lo_no_simplify=i; );
+ DEBUG_ONLY( if( lrgs(i)._was_lo ) lo_no_simplify=i; );
double iscore = lrgs(i).score();
double iarea = lrgs(i)._area;
double icost = lrgs(i)._cost;
@@ -1577,7 +1577,7 @@ uint PhaseChaitin::Select( ) {
// Remove neighbor colors
IndexSet *s = _ifg->neighbors(lidx);
- debug_only(RegMask orig_mask = lrg->mask();)
+ DEBUG_ONLY(RegMask orig_mask = lrg->mask();)
if (!s->is_empty()) {
IndexSetIterator elements(s);
@@ -1706,8 +1706,8 @@ uint PhaseChaitin::Select( ) {
ttyLocker ttyl;
tty->print("L%d spilling with neighbors: ", lidx);
s->dump();
- debug_only(tty->print(" original mask: "));
- debug_only(orig_mask.dump());
+ DEBUG_ONLY(tty->print(" original mask: "));
+ DEBUG_ONLY(orig_mask.dump());
dump_lrg(lidx);
}
#endif
diff --git a/src/hotspot/share/opto/chaitin.hpp b/src/hotspot/share/opto/chaitin.hpp
index 4b74420f996..cc3d3479c81 100644
--- a/src/hotspot/share/opto/chaitin.hpp
+++ b/src/hotspot/share/opto/chaitin.hpp
@@ -82,11 +82,11 @@ public:
// set makes it not valid.
void set_degree( uint degree ) {
_eff_degree = degree;
- debug_only(_degree_valid = 1;)
+ DEBUG_ONLY(_degree_valid = 1;)
assert(!_mask.is_AllStack() || (_mask.is_AllStack() && lo_degree()), "_eff_degree can't be bigger than AllStack_size - _num_regs if the mask supports stack registers");
}
// Made a change that hammered degree
- void invalid_degree() { debug_only(_degree_valid=0;) }
+ void invalid_degree() { DEBUG_ONLY(_degree_valid=0;) }
// Incrementally modify degree. If it was correct, it should remain correct
void inc_degree( uint mod ) {
_eff_degree += mod;
@@ -128,15 +128,15 @@ public:
// count of bits in the current mask.
int get_invalid_mask_size() const { return _mask_size; }
const RegMask &mask() const { return _mask; }
- void set_mask( const RegMask &rm ) { _mask = rm; debug_only(_msize_valid=0;)}
- void AND( const RegMask &rm ) { _mask.AND(rm); debug_only(_msize_valid=0;)}
- void SUBTRACT( const RegMask &rm ) { _mask.SUBTRACT(rm); debug_only(_msize_valid=0;)}
- void Clear() { _mask.Clear() ; debug_only(_msize_valid=1); _mask_size = 0; }
- void Set_All() { _mask.Set_All(); debug_only(_msize_valid=1); _mask_size = RegMask::CHUNK_SIZE; }
+ void set_mask( const RegMask &rm ) { _mask = rm; DEBUG_ONLY(_msize_valid=0;)}
+ void AND( const RegMask &rm ) { _mask.AND(rm); DEBUG_ONLY(_msize_valid=0;)}
+ void SUBTRACT( const RegMask &rm ) { _mask.SUBTRACT(rm); DEBUG_ONLY(_msize_valid=0;)}
+ void Clear() { _mask.Clear() ; DEBUG_ONLY(_msize_valid=1); _mask_size = 0; }
+ void Set_All() { _mask.Set_All(); DEBUG_ONLY(_msize_valid=1); _mask_size = RegMask::CHUNK_SIZE; }
- void Insert( OptoReg::Name reg ) { _mask.Insert(reg); debug_only(_msize_valid=0;) }
- void Remove( OptoReg::Name reg ) { _mask.Remove(reg); debug_only(_msize_valid=0;) }
- void clear_to_sets() { _mask.clear_to_sets(_num_regs); debug_only(_msize_valid=0;) }
+ void Insert( OptoReg::Name reg ) { _mask.Insert(reg); DEBUG_ONLY(_msize_valid=0;) }
+ void Remove( OptoReg::Name reg ) { _mask.Remove(reg); DEBUG_ONLY(_msize_valid=0;) }
+ void clear_to_sets() { _mask.clear_to_sets(_num_regs); DEBUG_ONLY(_msize_valid=0;) }
private:
// Number of registers this live range uses when it colors
diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp
index e4e82cbddab..effc7e21354 100644
--- a/src/hotspot/share/opto/compile.cpp
+++ b/src/hotspot/share/opto/compile.cpp
@@ -474,7 +474,7 @@ void Compile::disconnect_useless_nodes(Unique_Node_List& useful, Unique_Node_Lis
remove_useless_late_inlines( &_string_late_inlines, useful);
remove_useless_late_inlines( &_boxing_late_inlines, useful);
remove_useless_late_inlines(&_vector_reboxing_late_inlines, useful);
- debug_only(verify_graph_edges(true /*check for no_dead_code*/, root_and_safepoints);)
+ DEBUG_ONLY(verify_graph_edges(true /*check for no_dead_code*/, root_and_safepoints);)
}
// ============================================================================
diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp
index 1fb34e799b2..3a6a81f656e 100644
--- a/src/hotspot/share/opto/escape.cpp
+++ b/src/hotspot/share/opto/escape.cpp
@@ -4567,7 +4567,7 @@ void ConnectionGraph::split_unique_types(GrowableArray &alloc_worklist,
}
}
} else {
- debug_only(n->dump();)
+ DEBUG_ONLY(n->dump();)
assert(false, "EA: unexpected node");
continue;
}
diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp
index df9177a4938..20feca26ede 100644
--- a/src/hotspot/share/opto/graphKit.cpp
+++ b/src/hotspot/share/opto/graphKit.cpp
@@ -72,8 +72,8 @@ GraphKit::GraphKit()
{
_exceptions = nullptr;
set_map(nullptr);
- debug_only(_sp = -99);
- debug_only(set_bci(-99));
+ DEBUG_ONLY(_sp = -99);
+ DEBUG_ONLY(set_bci(-99));
}
@@ -196,7 +196,7 @@ bool GraphKit::has_exception_handler() {
void GraphKit::set_saved_ex_oop(SafePointNode* ex_map, Node* ex_oop) {
assert(!has_saved_ex_oop(ex_map), "clear ex-oop before setting again");
ex_map->add_req(ex_oop);
- debug_only(verify_exception_state(ex_map));
+ DEBUG_ONLY(verify_exception_state(ex_map));
}
inline static Node* common_saved_ex_oop(SafePointNode* ex_map, bool clear_it) {
@@ -296,7 +296,7 @@ JVMState* GraphKit::transfer_exceptions_into_jvms() {
_map = clone_map();
_map->set_next_exception(nullptr);
clear_saved_ex_oop(_map);
- debug_only(verify_map());
+ DEBUG_ONLY(verify_map());
} else {
// ...or created from scratch
JVMState* jvms = new (C) JVMState(_method, nullptr);
@@ -672,7 +672,7 @@ ciInstance* GraphKit::builtin_throw_exception(Deoptimization::DeoptReason reason
//----------------------------PreserveJVMState---------------------------------
PreserveJVMState::PreserveJVMState(GraphKit* kit, bool clone_map) {
- debug_only(kit->verify_map());
+ DEBUG_ONLY(kit->verify_map());
_kit = kit;
_map = kit->map(); // preserve the map
_sp = kit->sp();
@@ -780,7 +780,7 @@ void GraphKit::set_map_clone(SafePointNode* m) {
_map = m;
_map = clone_map();
_map->set_next_exception(nullptr);
- debug_only(verify_map());
+ DEBUG_ONLY(verify_map());
}
@@ -1537,7 +1537,7 @@ Node* GraphKit::memory(uint alias_idx) {
Node* GraphKit::reset_memory() {
Node* mem = map()->memory();
// do not use this node for any more parsing!
- debug_only( map()->set_memory((Node*)nullptr) );
+ DEBUG_ONLY( map()->set_memory((Node*)nullptr) );
return _gvn.transform( mem );
}
@@ -1574,7 +1574,7 @@ Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt,
int adr_idx = C->get_alias_index(_gvn.type(adr)->isa_ptr());
assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" );
const TypePtr* adr_type = nullptr; // debug-mode-only argument
- debug_only(adr_type = C->get_adr_type(adr_idx));
+ DEBUG_ONLY(adr_type = C->get_adr_type(adr_idx));
Node* mem = memory(adr_idx);
Node* ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency, require_atomic_access, unaligned, mismatched, unsafe, barrier_data);
ld = _gvn.transform(ld);
@@ -1602,7 +1602,7 @@ Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt,
int adr_idx = C->get_alias_index(_gvn.type(adr)->isa_ptr());
assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" );
const TypePtr* adr_type = nullptr;
- debug_only(adr_type = C->get_adr_type(adr_idx));
+ DEBUG_ONLY(adr_type = C->get_adr_type(adr_idx));
Node *mem = memory(adr_idx);
Node* st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo, require_atomic_access);
if (unaligned) {
diff --git a/src/hotspot/share/opto/graphKit.hpp b/src/hotspot/share/opto/graphKit.hpp
index d1b58526a6d..28773d75333 100644
--- a/src/hotspot/share/opto/graphKit.hpp
+++ b/src/hotspot/share/opto/graphKit.hpp
@@ -145,7 +145,7 @@ class GraphKit : public Phase {
_sp = jvms->sp();
_bci = jvms->bci();
_method = jvms->has_method() ? jvms->method() : nullptr; }
- void set_map(SafePointNode* m) { _map = m; debug_only(verify_map()); }
+ void set_map(SafePointNode* m) { _map = m; DEBUG_ONLY(verify_map()); }
void set_sp(int sp) { assert(sp >= 0, "sp must be non-negative: %d", sp); _sp = sp; }
void clean_stack(int from_sp); // clear garbage beyond from_sp to top
@@ -226,14 +226,14 @@ class GraphKit : public Phase {
if (ex_map != nullptr) {
_exceptions = ex_map->next_exception();
ex_map->set_next_exception(nullptr);
- debug_only(verify_exception_state(ex_map));
+ DEBUG_ONLY(verify_exception_state(ex_map));
}
return ex_map;
}
// Add an exception, using the given JVM state, without commoning.
void push_exception_state(SafePointNode* ex_map) {
- debug_only(verify_exception_state(ex_map));
+ DEBUG_ONLY(verify_exception_state(ex_map));
ex_map->set_next_exception(_exceptions);
_exceptions = ex_map;
}
diff --git a/src/hotspot/share/opto/idealKit.cpp b/src/hotspot/share/opto/idealKit.cpp
index 8c26e1cc39d..dd7e9ae52b7 100644
--- a/src/hotspot/share/opto/idealKit.cpp
+++ b/src/hotspot/share/opto/idealKit.cpp
@@ -354,7 +354,7 @@ Node* IdealKit::load(Node* ctl,
assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" );
const TypePtr* adr_type = nullptr; // debug-mode-only argument
- debug_only(adr_type = C->get_adr_type(adr_idx));
+ DEBUG_ONLY(adr_type = C->get_adr_type(adr_idx));
Node* mem = memory(adr_idx);
Node* ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency, require_atomic_access);
return transform(ld);
@@ -366,7 +366,7 @@ Node* IdealKit::store(Node* ctl, Node* adr, Node *val, BasicType bt,
bool mismatched) {
assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory");
const TypePtr* adr_type = nullptr;
- debug_only(adr_type = C->get_adr_type(adr_idx));
+ DEBUG_ONLY(adr_type = C->get_adr_type(adr_idx));
Node *mem = memory(adr_idx);
Node* st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo, require_atomic_access);
if (mismatched) {
diff --git a/src/hotspot/share/opto/indexSet.cpp b/src/hotspot/share/opto/indexSet.cpp
index 7f02f01c83f..367f5b78af2 100644
--- a/src/hotspot/share/opto/indexSet.cpp
+++ b/src/hotspot/share/opto/indexSet.cpp
@@ -121,7 +121,7 @@ IndexSet::BitBlock *IndexSet::alloc_block_containing(uint element) {
// Add a BitBlock to the free list.
void IndexSet::free_block(uint i) {
- debug_only(check_watch("free block", i));
+ DEBUG_ONLY(check_watch("free block", i));
assert(i < _max_blocks, "block index too large");
BitBlock *block = _blocks[i];
assert(block != &_empty_block, "cannot free the empty block");
diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp
index 017564173a8..65635001e13 100644
--- a/src/hotspot/share/opto/library_call.cpp
+++ b/src/hotspot/share/opto/library_call.cpp
@@ -721,6 +721,10 @@ bool LibraryCallKit::try_to_inline(int predicate) {
return inline_vector_nary_operation(1);
case vmIntrinsics::_VectorBinaryOp:
return inline_vector_nary_operation(2);
+ case vmIntrinsics::_VectorUnaryLibOp:
+ return inline_vector_call(1);
+ case vmIntrinsics::_VectorBinaryLibOp:
+ return inline_vector_call(2);
case vmIntrinsics::_VectorTernaryOp:
return inline_vector_nary_operation(3);
case vmIntrinsics::_VectorFromBitsCoerced:
diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp
index cb755267ec5..1be08df32ae 100644
--- a/src/hotspot/share/opto/library_call.hpp
+++ b/src/hotspot/share/opto/library_call.hpp
@@ -369,6 +369,7 @@ class LibraryCallKit : public GraphKit {
// Vector API support
bool inline_vector_nary_operation(int n);
+ bool inline_vector_call(int arity);
bool inline_vector_frombits_coerced();
bool inline_vector_mask_operation();
bool inline_vector_mem_operation(bool is_store);
diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp
index c3f411eea94..195d48b37c6 100644
--- a/src/hotspot/share/opto/loopnode.cpp
+++ b/src/hotspot/share/opto/loopnode.cpp
@@ -359,7 +359,7 @@ void PhaseIdealLoop::insert_loop_limit_check_predicate(ParsePredicateSuccessProj
// for this loop
if (TraceLoopLimitCheck) {
tty->print_cr("Counted Loop Limit Check generated:");
- debug_only( bol->dump(2); )
+ DEBUG_ONLY( bol->dump(2); )
}
#endif
}
diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp
index 1bd35f9dcc9..1fe59c9156b 100644
--- a/src/hotspot/share/opto/macro.cpp
+++ b/src/hotspot/share/opto/macro.cpp
@@ -225,7 +225,7 @@ static Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_me
if (!ClearArrayNode::step_through(&mem, alloc->_idx, phase)) {
// Can not bypass initialization of the instance
// we are looking.
- debug_only(intptr_t offset;)
+ DEBUG_ONLY(intptr_t offset;)
assert(alloc == AllocateNode::Ideal_allocation(mem->in(3), phase, offset), "sanity");
InitializeNode* init = alloc->as_Allocate()->initialization();
// We are looking for stored value, return Initialize node
@@ -1328,7 +1328,7 @@ void PhaseMacroExpand::expand_allocate_common(
// No initial test, just fall into next case
assert(allocation_has_use || !expand_fast_path, "Should already have been handled");
toobig_false = ctrl;
- debug_only(slow_region = NodeSentinel);
+ DEBUG_ONLY(slow_region = NodeSentinel);
}
// If we are here there are several possibilities
diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp
index e34a43cc1e2..0849b40ad7e 100644
--- a/src/hotspot/share/opto/matcher.cpp
+++ b/src/hotspot/share/opto/matcher.cpp
@@ -128,7 +128,7 @@ Matcher::Matcher()
idealreg2mhdebugmask[Op_RegFlags] = nullptr;
idealreg2mhdebugmask[Op_RegVectMask] = nullptr;
- debug_only(_mem_node = nullptr;) // Ideal memory node consumed by mach node
+ DEBUG_ONLY(_mem_node = nullptr;) // Ideal memory node consumed by mach node
}
//------------------------------warp_incoming_stk_arg------------------------
@@ -1184,7 +1184,7 @@ Node *Matcher::xform( Node *n, int max_stack ) {
n->_idx);
C->set_node_notes_at(m->_idx, nn);
}
- debug_only(match_alias_type(C, n, m));
+ DEBUG_ONLY(match_alias_type(C, n, m));
}
n = m; // n is now a new-space node
mstack.set_node(n);
@@ -1591,7 +1591,7 @@ MachNode *Matcher::match_tree( const Node *n ) {
}
}
- debug_only( _mem_node = save_mem_node; )
+ DEBUG_ONLY( _mem_node = save_mem_node; )
return m;
}
@@ -1965,9 +1965,9 @@ void Matcher::ReduceInst_Chain_Rule(State* s, int rule, Node* &mem, MachNode* ma
assert(newrule >= _LAST_MACH_OPER, "Do NOT chain from internal operand");
mach->_opnds[1] = s->MachOperGenerator(_reduceOp[catch_op]);
Node *mem1 = (Node*)1;
- debug_only(Node *save_mem_node = _mem_node;)
+ DEBUG_ONLY(Node *save_mem_node = _mem_node;)
mach->add_req( ReduceInst(s, newrule, mem1) );
- debug_only(_mem_node = save_mem_node;)
+ DEBUG_ONLY(_mem_node = save_mem_node;)
}
return;
}
@@ -1979,7 +1979,7 @@ uint Matcher::ReduceInst_Interior( State *s, int rule, Node *&mem, MachNode *mac
if( s->_leaf->is_Load() ) {
Node *mem2 = s->_leaf->in(MemNode::Memory);
assert( mem == (Node*)1 || mem == mem2, "multiple Memories being matched at once?" );
- debug_only( if( mem == (Node*)1 ) _mem_node = s->_leaf;)
+ DEBUG_ONLY( if( mem == (Node*)1 ) _mem_node = s->_leaf;)
mem = mem2;
}
if( s->_leaf->in(0) != nullptr && s->_leaf->req() > 1) {
@@ -2023,9 +2023,9 @@ uint Matcher::ReduceInst_Interior( State *s, int rule, Node *&mem, MachNode *mac
// --> ReduceInst( newrule )
mach->_opnds[num_opnds++] = s->MachOperGenerator(_reduceOp[catch_op]);
Node *mem1 = (Node*)1;
- debug_only(Node *save_mem_node = _mem_node;)
+ DEBUG_ONLY(Node *save_mem_node = _mem_node;)
mach->add_req( ReduceInst( newstate, newrule, mem1 ) );
- debug_only(_mem_node = save_mem_node;)
+ DEBUG_ONLY(_mem_node = save_mem_node;)
}
}
assert( mach->_opnds[num_opnds-1], "" );
@@ -2056,7 +2056,7 @@ void Matcher::ReduceOper( State *s, int rule, Node *&mem, MachNode *mach ) {
if( s->_leaf->is_Load() ) {
assert( mem == (Node*)1, "multiple Memories being matched at once?" );
mem = s->_leaf->in(MemNode::Memory);
- debug_only(_mem_node = s->_leaf;)
+ DEBUG_ONLY(_mem_node = s->_leaf;)
}
handle_precedence_edges(s->_leaf, mach);
@@ -2085,9 +2085,9 @@ void Matcher::ReduceOper( State *s, int rule, Node *&mem, MachNode *mach ) {
// Reduce the instruction, and add a direct pointer from this
// machine instruction to the newly reduced one.
Node *mem1 = (Node*)1;
- debug_only(Node *save_mem_node = _mem_node;)
+ DEBUG_ONLY(Node *save_mem_node = _mem_node;)
mach->add_req( ReduceInst( kid, newrule, mem1 ) );
- debug_only(_mem_node = save_mem_node;)
+ DEBUG_ONLY(_mem_node = save_mem_node;)
}
}
}
diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp
index 157cc1866a0..a751022f752 100644
--- a/src/hotspot/share/opto/memnode.hpp
+++ b/src/hotspot/share/opto/memnode.hpp
@@ -71,7 +71,7 @@ protected:
_unsafe_access(false),
_barrier_data(0) {
init_class_id(Class_Mem);
- debug_only(_adr_type=at; adr_type();)
+ DEBUG_ONLY(_adr_type=at; adr_type();)
}
MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at, Node *c3 ) :
Node(c0,c1,c2,c3),
@@ -80,7 +80,7 @@ protected:
_unsafe_access(false),
_barrier_data(0) {
init_class_id(Class_Mem);
- debug_only(_adr_type=at; adr_type();)
+ DEBUG_ONLY(_adr_type=at; adr_type();)
}
MemNode( Node *c0, Node *c1, Node *c2, const TypePtr* at, Node *c3, Node *c4) :
Node(c0,c1,c2,c3,c4),
@@ -89,7 +89,7 @@ protected:
_unsafe_access(false),
_barrier_data(0) {
init_class_id(Class_Mem);
- debug_only(_adr_type=at; adr_type();)
+ DEBUG_ONLY(_adr_type=at; adr_type();)
}
virtual Node* find_previous_arraycopy(PhaseValues* phase, Node* ld_alloc, Node*& mem, bool can_see_stored_value) const { return nullptr; }
@@ -273,7 +273,7 @@ public:
// Following method is copied from TypeNode:
void set_type(const Type* t) {
assert(t != nullptr, "sanity");
- debug_only(uint check_hash = (VerifyHashTableKeys && _hash_lock) ? hash() : NO_HASH);
+ DEBUG_ONLY(uint check_hash = (VerifyHashTableKeys && _hash_lock) ? hash() : NO_HASH);
*(const Type**)&_type = t; // cast away const-ness
// If this node is in the hash table, make sure it doesn't need a rehash.
assert(check_hash == NO_HASH || check_hash == hash(), "type change must preserve hash code");
@@ -1497,7 +1497,7 @@ class MergeMemStream : public StackObj {
MergeMemStream(MergeMemNode* mm) {
mm->iteration_setup();
init(mm);
- debug_only(_cnt2 = 999);
+ DEBUG_ONLY(_cnt2 = 999);
}
// iterate in parallel over two merges
// only iterates through non-empty elements of mm2
diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp
index 1d046583ee0..72562a657ea 100644
--- a/src/hotspot/share/opto/mulnode.cpp
+++ b/src/hotspot/share/opto/mulnode.cpp
@@ -924,13 +924,15 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if( t12 && t12->is_con() ) { // Shift is by a constant
int shift = t12->get_con();
shift &= BitsPerJavaLong - 1; // semantics of Java shifts
- const julong sign_bits_mask = ~(((julong)CONST64(1) << (julong)(BitsPerJavaLong - shift)) -1);
- // If the AND'ing of the 2 masks has no bits, then only original shifted
- // bits survive. NO sign-extension bits survive the maskings.
- if( (sign_bits_mask & mask) == 0 ) {
- // Use zero-fill shift instead
- Node *zshift = phase->transform(new URShiftLNode(in1->in(1), in1->in(2)));
- return new AndLNode(zshift, in(2));
+ if (shift != 0) {
+ const julong sign_bits_mask = ~(((julong)CONST64(1) << (julong)(BitsPerJavaLong - shift)) -1);
+ // If the AND'ing of the 2 masks has no bits, then only original shifted
+ // bits survive. NO sign-extension bits survive the maskings.
+ if( (sign_bits_mask & mask) == 0 ) {
+ // Use zero-fill shift instead
+ Node *zshift = phase->transform(new URShiftLNode(in1->in(1), in1->in(2)));
+ return new AndLNode(zshift, in(2));
+ }
}
}
}
diff --git a/src/hotspot/share/opto/multnode.hpp b/src/hotspot/share/opto/multnode.hpp
index 25dad70a50a..dff2caed38d 100644
--- a/src/hotspot/share/opto/multnode.hpp
+++ b/src/hotspot/share/opto/multnode.hpp
@@ -71,7 +71,7 @@ public:
// Optimistic setting. Need additional checks in Node::is_dead_loop_safe().
if (con != TypeFunc::Memory || src->is_Start())
init_flags(Flag_is_dead_loop_safe);
- debug_only(check_con());
+ DEBUG_ONLY(check_con());
}
const uint _con; // The field in the tuple we are projecting
const bool _is_io_use; // Used to distinguish between the projections
diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp
index 76e19360910..a635abebec1 100644
--- a/src/hotspot/share/opto/node.cpp
+++ b/src/hotspot/share/opto/node.cpp
@@ -322,7 +322,7 @@ Node::Node(uint req)
#endif
{
assert( req < Compile::current()->max_node_limit() - NodeLimitFudgeFactor, "Input limit exceeded" );
- debug_only( verify_construction() );
+ DEBUG_ONLY( verify_construction() );
NOT_PRODUCT(nodes_created++);
if (req == 0) {
_in = nullptr;
@@ -341,7 +341,7 @@ Node::Node(Node *n0)
, _parse_idx(_idx)
#endif
{
- debug_only( verify_construction() );
+ DEBUG_ONLY( verify_construction() );
NOT_PRODUCT(nodes_created++);
assert( is_not_dead(n0), "can not use dead node");
_in[0] = n0; if (n0 != nullptr) n0->add_out((Node *)this);
@@ -354,7 +354,7 @@ Node::Node(Node *n0, Node *n1)
, _parse_idx(_idx)
#endif
{
- debug_only( verify_construction() );
+ DEBUG_ONLY( verify_construction() );
NOT_PRODUCT(nodes_created++);
assert( is_not_dead(n0), "can not use dead node");
assert( is_not_dead(n1), "can not use dead node");
@@ -369,7 +369,7 @@ Node::Node(Node *n0, Node *n1, Node *n2)
, _parse_idx(_idx)
#endif
{
- debug_only( verify_construction() );
+ DEBUG_ONLY( verify_construction() );
NOT_PRODUCT(nodes_created++);
assert( is_not_dead(n0), "can not use dead node");
assert( is_not_dead(n1), "can not use dead node");
@@ -386,7 +386,7 @@ Node::Node(Node *n0, Node *n1, Node *n2, Node *n3)
, _parse_idx(_idx)
#endif
{
- debug_only( verify_construction() );
+ DEBUG_ONLY( verify_construction() );
NOT_PRODUCT(nodes_created++);
assert( is_not_dead(n0), "can not use dead node");
assert( is_not_dead(n1), "can not use dead node");
@@ -405,7 +405,7 @@ Node::Node(Node *n0, Node *n1, Node *n2, Node *n3, Node *n4)
, _parse_idx(_idx)
#endif
{
- debug_only( verify_construction() );
+ DEBUG_ONLY( verify_construction() );
NOT_PRODUCT(nodes_created++);
assert( is_not_dead(n0), "can not use dead node");
assert( is_not_dead(n1), "can not use dead node");
@@ -427,7 +427,7 @@ Node::Node(Node *n0, Node *n1, Node *n2, Node *n3,
, _parse_idx(_idx)
#endif
{
- debug_only( verify_construction() );
+ DEBUG_ONLY( verify_construction() );
NOT_PRODUCT(nodes_created++);
assert( is_not_dead(n0), "can not use dead node");
assert( is_not_dead(n1), "can not use dead node");
@@ -451,7 +451,7 @@ Node::Node(Node *n0, Node *n1, Node *n2, Node *n3,
, _parse_idx(_idx)
#endif
{
- debug_only( verify_construction() );
+ DEBUG_ONLY( verify_construction() );
NOT_PRODUCT(nodes_created++);
assert( is_not_dead(n0), "can not use dead node");
assert( is_not_dead(n1), "can not use dead node");
@@ -489,7 +489,7 @@ Node *Node::clone() const {
n->_outcnt = 0;
n->_outmax = 0;
// Unlock this guy, since he is not in any hash table.
- debug_only(n->_hash_lock = 0);
+ DEBUG_ONLY(n->_hash_lock = 0);
// Walk the old node's input list to duplicate its edges
uint i;
for( i = 0; i < len(); i++ ) {
@@ -525,11 +525,11 @@ Node *Node::clone() const {
n->set_idx(C->next_unique()); // Get new unique index as well
NOT_PRODUCT(n->_igv_idx = C->next_igv_idx());
- debug_only( n->verify_construction() );
+ DEBUG_ONLY( n->verify_construction() );
NOT_PRODUCT(nodes_created++);
// Do not patch over the debug_idx of a clone, because it makes it
// impossible to break on the clone's moment of creation.
- //debug_only( n->set_debug_idx( debug_idx() ) );
+ //DEBUG_ONLY( n->set_debug_idx( debug_idx() ) );
C->copy_node_notes_to(n, (Node*) this);
@@ -942,7 +942,7 @@ void Node::disconnect_inputs(Compile* C) {
#endif
// Node::destruct requires all out edges be deleted first
- // debug_only(destruct();) // no reuse benefit expected
+ // DEBUG_ONLY(destruct();) // no reuse benefit expected
C->record_dead_node(_idx);
}
diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp
index 1cb9009ef27..e1a4ee22661 100644
--- a/src/hotspot/share/opto/node.hpp
+++ b/src/hotspot/share/opto/node.hpp
@@ -427,11 +427,11 @@ public:
assert(_outcnt > 0,"oob");
#if OPTO_DU_ITERATOR_ASSERT
// Record that a change happened here.
- debug_only(_last_del = _out[i]; ++_del_tick);
+ DEBUG_ONLY(_last_del = _out[i]; ++_del_tick);
#endif
_out[i] = _out[--_outcnt];
// Smash the old edge so it can't be used accidentally.
- debug_only(_out[_outcnt] = (Node *)(uintptr_t)0xdeadbeef);
+ DEBUG_ONLY(_out[_outcnt] = (Node *)(uintptr_t)0xdeadbeef);
}
#ifdef ASSERT
@@ -533,10 +533,10 @@ private:
} while (*--outp != n);
*outp = _out[--_outcnt];
// Smash the old edge so it can't be used accidentally.
- debug_only(_out[_outcnt] = (Node *)(uintptr_t)0xdeadbeef);
+ DEBUG_ONLY(_out[_outcnt] = (Node *)(uintptr_t)0xdeadbeef);
// Record that a change happened here.
#if OPTO_DU_ITERATOR_ASSERT
- debug_only(_last_del = n; ++_del_tick);
+ DEBUG_ONLY(_last_del = n; ++_del_tick);
#endif
}
// Close gap after removing edge.
@@ -593,7 +593,7 @@ public:
}
// Swap input edge order. (Edge indexes i1 and i2 are usually 1 and 2.)
void swap_edges(uint i1, uint i2) {
- debug_only(uint check_hash = (VerifyHashTableKeys && _hash_lock) ? hash() : NO_HASH);
+ DEBUG_ONLY(uint check_hash = (VerifyHashTableKeys && _hash_lock) ? hash() : NO_HASH);
// Def-Use info is unchanged
Node* n1 = in(i1);
Node* n2 = in(i2);
@@ -1431,15 +1431,15 @@ class DUIterator : public DUIterator_Common {
#endif
DUIterator(const Node* node, int dummy_to_avoid_conversion)
- { _idx = 0; debug_only(sample(node)); }
+ { _idx = 0; DEBUG_ONLY(sample(node)); }
public:
// initialize to garbage; clear _vdui to disable asserts
DUIterator()
- { /*initialize to garbage*/ debug_only(_vdui = false); }
+ { /*initialize to garbage*/ DEBUG_ONLY(_vdui = false); }
DUIterator(const DUIterator& that)
- { _idx = that._idx; debug_only(_vdui = false; reset(that)); }
+ { _idx = that._idx; DEBUG_ONLY(_vdui = false; reset(that)); }
void operator++(int dummy_to_specify_postfix_op)
{ _idx++; VDUI_ONLY(verify_increment()); }
@@ -1451,7 +1451,7 @@ class DUIterator : public DUIterator_Common {
{ VDUI_ONLY(verify_finish()); }
void operator=(const DUIterator& that)
- { _idx = that._idx; debug_only(reset(that)); }
+ { _idx = that._idx; DEBUG_ONLY(reset(that)); }
};
DUIterator Node::outs() const
@@ -1461,7 +1461,7 @@ DUIterator& Node::refresh_out_pos(DUIterator& i) const
bool Node::has_out(DUIterator& i) const
{ I_VDUI_ONLY(i, i.verify(this,true));return i._idx < _outcnt; }
Node* Node::out(DUIterator& i) const
- { I_VDUI_ONLY(i, i.verify(this)); return debug_only(i._last=) _out[i._idx]; }
+ { I_VDUI_ONLY(i, i.verify(this)); return DEBUG_ONLY(i._last=) _out[i._idx]; }
// Faster DU iterator. Disallows insertions into the out array.
@@ -1496,15 +1496,15 @@ class DUIterator_Fast : public DUIterator_Common {
// Note: offset must be signed, since -1 is sometimes passed
DUIterator_Fast(const Node* node, ptrdiff_t offset)
- { _outp = node->_out + offset; debug_only(sample(node)); }
+ { _outp = node->_out + offset; DEBUG_ONLY(sample(node)); }
public:
// initialize to garbage; clear _vdui to disable asserts
DUIterator_Fast()
- { /*initialize to garbage*/ debug_only(_vdui = false); }
+ { /*initialize to garbage*/ DEBUG_ONLY(_vdui = false); }
DUIterator_Fast(const DUIterator_Fast& that)
- { _outp = that._outp; debug_only(_vdui = false; reset(that)); }
+ { _outp = that._outp; DEBUG_ONLY(_vdui = false; reset(that)); }
void operator++(int dummy_to_specify_postfix_op)
{ _outp++; VDUI_ONLY(verify(_node, true)); }
@@ -1522,7 +1522,7 @@ class DUIterator_Fast : public DUIterator_Common {
}
void operator=(const DUIterator_Fast& that)
- { _outp = that._outp; debug_only(reset(that)); }
+ { _outp = that._outp; DEBUG_ONLY(reset(that)); }
};
DUIterator_Fast Node::fast_outs(DUIterator_Fast& imax) const {
@@ -1533,7 +1533,7 @@ DUIterator_Fast Node::fast_outs(DUIterator_Fast& imax) const {
}
Node* Node::fast_out(DUIterator_Fast& i) const {
I_VDUI_ONLY(i, i.verify(this));
- return debug_only(i._last=) *i._outp;
+ return DEBUG_ONLY(i._last=) *i._outp;
}
@@ -1591,7 +1591,7 @@ DUIterator_Last Node::last_outs(DUIterator_Last& imin) const {
}
Node* Node::last_out(DUIterator_Last& i) const {
I_VDUI_ONLY(i, i.verify(this));
- return debug_only(i._last=) *i._outp;
+ return DEBUG_ONLY(i._last=) *i._outp;
}
#endif //OPTO_DU_ITERATOR_ASSERT
@@ -2035,7 +2035,7 @@ protected:
public:
void set_type(const Type* t) {
assert(t != nullptr, "sanity");
- debug_only(uint check_hash = (VerifyHashTableKeys && _hash_lock) ? hash() : NO_HASH);
+ DEBUG_ONLY(uint check_hash = (VerifyHashTableKeys && _hash_lock) ? hash() : NO_HASH);
*(const Type**)&_type = t; // cast away const-ness
// If this node is in the hash table, make sure it doesn't need a rehash.
assert(check_hash == NO_HASH || check_hash == hash(), "type change must preserve hash code");
diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp
index 9fe5ad562b0..1cd6ebabc4b 100644
--- a/src/hotspot/share/opto/output.cpp
+++ b/src/hotspot/share/opto/output.cpp
@@ -2971,7 +2971,7 @@ void Scheduling::anti_do_def( Block *b, Node *def, OptoReg::Name def_reg, int is
}
Node *kill = def; // Rename 'def' to more descriptive 'kill'
- debug_only( def = (Node*)((intptr_t)0xdeadbeef); )
+ DEBUG_ONLY( def = (Node*)((intptr_t)0xdeadbeef); )
// After some number of kills there _may_ be a later def
Node *later_def = nullptr;
diff --git a/src/hotspot/share/opto/parse1.cpp b/src/hotspot/share/opto/parse1.cpp
index f7330d10df3..6fa0b0f497d 100644
--- a/src/hotspot/share/opto/parse1.cpp
+++ b/src/hotspot/share/opto/parse1.cpp
@@ -1835,10 +1835,10 @@ void Parse::merge_common(Parse::Block* target, int pnum) {
// Now _gvn will join that with the meet of current inputs.
// BOTTOM is never permissible here, 'cause pessimistically
// Phis of pointers cannot lose the basic pointer type.
- debug_only(const Type* bt1 = phi->bottom_type());
+ DEBUG_ONLY(const Type* bt1 = phi->bottom_type());
assert(bt1 != Type::BOTTOM, "should not be building conflict phis");
map()->set_req(j, _gvn.transform(phi));
- debug_only(const Type* bt2 = phi->bottom_type());
+ DEBUG_ONLY(const Type* bt2 = phi->bottom_type());
assert(bt2->higher_equal_speculative(bt1), "must be consistent with type-flow");
record_for_igvn(phi);
}
@@ -1936,7 +1936,7 @@ void Parse::ensure_phis_everywhere() {
// Ensure a phi on all currently known memories.
for (MergeMemStream mms(merged_memory()); mms.next_non_empty(); ) {
ensure_memory_phi(mms.alias_idx());
- debug_only(mms.set_memory()); // keep the iterator happy
+ DEBUG_ONLY(mms.set_memory()); // keep the iterator happy
}
// Note: This is our only chance to create phis for memory slices.
diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp
index 9be15b153b3..82e5b3f9d85 100644
--- a/src/hotspot/share/opto/phaseX.cpp
+++ b/src/hotspot/share/opto/phaseX.cpp
@@ -123,7 +123,7 @@ Node *NodeHash::hash_find_insert( Node *n ) {
if( !k ) { // ?Miss?
NOT_PRODUCT( _lookup_misses++ );
_table[key] = n; // Insert into table!
- debug_only(n->enter_hash_lock()); // Lock down the node while in the table.
+ DEBUG_ONLY(n->enter_hash_lock()); // Lock down the node while in the table.
check_grow(); // Grow table if insert hit limit
return nullptr; // Miss!
}
@@ -152,7 +152,7 @@ Node *NodeHash::hash_find_insert( Node *n ) {
NOT_PRODUCT( _lookup_misses++ );
key = (first_sentinel == 0) ? key : first_sentinel; // ?saw sentinel?
_table[key] = n; // Insert into table!
- debug_only(n->enter_hash_lock()); // Lock down the node while in the table.
+ DEBUG_ONLY(n->enter_hash_lock()); // Lock down the node while in the table.
check_grow(); // Grow table if insert hit limit
return nullptr; // Miss!
}
@@ -188,7 +188,7 @@ void NodeHash::hash_insert( Node *n ) {
key = (key + stride) & (_max-1); // Stride through table w/ relative prime
}
_table[key] = n; // Insert into table!
- debug_only(n->enter_hash_lock()); // Lock down the node while in the table.
+ DEBUG_ONLY(n->enter_hash_lock()); // Lock down the node while in the table.
// if( conflict ) { n->dump(); }
}
@@ -203,9 +203,9 @@ bool NodeHash::hash_delete( const Node *n ) {
}
uint key = hash & (_max-1);
uint stride = key | 0x01;
- debug_only( uint counter = 0; );
+ DEBUG_ONLY( uint counter = 0; );
for( ; /* (k != nullptr) && (k != _sentinel) */; ) {
- debug_only( counter++ );
+ DEBUG_ONLY( counter++ );
NOT_PRODUCT( _delete_probes++ );
k = _table[key]; // Get hashed value
if( !k ) { // Miss?
@@ -215,7 +215,7 @@ bool NodeHash::hash_delete( const Node *n ) {
else if( n == k ) {
NOT_PRODUCT( _delete_hits++ );
_table[key] = _sentinel; // Hit! Label as deleted entry
- debug_only(((Node*)n)->exit_hash_lock()); // Unlock the node upon removal from table.
+ DEBUG_ONLY(((Node*)n)->exit_hash_lock()); // Unlock the node upon removal from table.
return true;
}
else {
@@ -257,7 +257,7 @@ void NodeHash::grow() {
for( uint i = 0; i < old_max; i++ ) {
Node *m = *old_table++;
if( !m || m == _sentinel ) continue;
- debug_only(m->exit_hash_lock()); // Unlock the node upon removal from old table.
+ DEBUG_ONLY(m->exit_hash_lock()); // Unlock the node upon removal from old table.
hash_insert(m);
}
}
@@ -289,7 +289,7 @@ void NodeHash::remove_useless_nodes(VectorSet &useful) {
for( uint i = 0; i < max; ++i ) {
Node *n = at(i);
if(n != nullptr && n != sentinel_node && !useful.test(n->_idx)) {
- debug_only(n->exit_hash_lock()); // Unlock the node when removed
+ DEBUG_ONLY(n->exit_hash_lock()); // Unlock the node when removed
_table[i] = sentinel_node; // Replace with placeholder
}
}
diff --git a/src/hotspot/share/opto/regalloc.hpp b/src/hotspot/share/opto/regalloc.hpp
index 86877e18325..c724406a168 100644
--- a/src/hotspot/share/opto/regalloc.hpp
+++ b/src/hotspot/share/opto/regalloc.hpp
@@ -60,12 +60,12 @@ public:
// Get the register associated with the Node
OptoReg::Name get_reg_first( const Node *n ) const {
- debug_only( if( n->_idx >= _node_regs_max_index ) n->dump(); );
+ DEBUG_ONLY( if( n->_idx >= _node_regs_max_index ) n->dump(); );
assert( n->_idx < _node_regs_max_index, "Exceeded _node_regs array");
return _node_regs[n->_idx].first();
}
OptoReg::Name get_reg_second( const Node *n ) const {
- debug_only( if( n->_idx >= _node_regs_max_index ) n->dump(); );
+ DEBUG_ONLY( if( n->_idx >= _node_regs_max_index ) n->dump(); );
assert( n->_idx < _node_regs_max_index, "Exceeded _node_regs array");
return _node_regs[n->_idx].second();
}
diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp
index 6d24fb26cd2..fcb0ac38ace 100644
--- a/src/hotspot/share/opto/runtime.cpp
+++ b/src/hotspot/share/opto/runtime.cpp
@@ -1944,7 +1944,7 @@ address OptoRuntime::handle_exception_C(JavaThread* current) {
#ifndef PRODUCT
SharedRuntime::_find_handler_ctr++; // find exception handler
#endif
- debug_only(NoHandleMark __hm;)
+ DEBUG_ONLY(NoHandleMark __hm;)
nmethod* nm = nullptr;
address handler_address = nullptr;
{
diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp
index 4556555acea..163f94ee959 100644
--- a/src/hotspot/share/opto/type.cpp
+++ b/src/hotspot/share/opto/type.cpp
@@ -756,7 +756,7 @@ void Type::Initialize(Compile* current) {
// delete the current Type and return the existing Type. Otherwise stick the
// current Type in the Type table.
const Type *Type::hashcons(void) {
- debug_only(base()); // Check the assertion in Type::base().
+ DEBUG_ONLY(base()); // Check the assertion in Type::base().
// Look up the Type in the Type dictionary
Dict *tdic = type_dict();
Type* old = (Type*)(tdic->Insert(this, this, false));
diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp
index e33d7b19686..13acc0469eb 100644
--- a/src/hotspot/share/opto/vectorIntrinsics.cpp
+++ b/src/hotspot/share/opto/vectorIntrinsics.cpp
@@ -366,17 +366,11 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) {
int num_elem = vlen->get_con();
int opc = VectorSupport::vop2ideal(opr->get_con(), elem_bt);
int sopc = has_scalar_op ? VectorNode::opcode(opc, elem_bt) : opc;
- if ((opc != Op_CallLeafVector) && (sopc == 0)) {
- log_if_needed(" ** operation not supported: opc=%s bt=%s", NodeClassNames[opc], type2name(elem_bt));
+ if (sopc == 0 || num_elem == 1) {
+ log_if_needed(" ** operation not supported: arity=%d opc=%s[%d] vlen=%d etype=%s",
+ n, NodeClassNames[opc], opc, num_elem, type2name(elem_bt));
return false; // operation not supported
}
- if (num_elem == 1) {
- if (opc != Op_CallLeafVector || elem_bt != T_DOUBLE) {
- log_if_needed(" ** not a svml call: arity=%d opc=%d vlen=%d etype=%s",
- n, opc, num_elem, type2name(elem_bt));
- return false;
- }
- }
ciKlass* vbox_klass = vector_klass->const_oop()->as_instance()->java_lang_Class_klass();
const TypeInstPtr* vbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, vbox_klass);
@@ -384,22 +378,6 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) {
assert(!is_masked_op, "mask operations do not need mask to control");
}
- if (opc == Op_CallLeafVector) {
- if (!UseVectorStubs) {
- log_if_needed(" ** vector stubs support is disabled");
- return false;
- }
- if (!Matcher::supports_vector_calling_convention()) {
- log_if_needed(" ** no vector calling conventions supported");
- return false;
- }
- if (!Matcher::vector_size_supported(elem_bt, num_elem)) {
- log_if_needed(" ** vector size (vlen=%d, etype=%s) is not supported",
- num_elem, type2name(elem_bt));
- return false;
- }
- }
-
// When using mask, mask use type needs to be VecMaskUseLoad.
VectorMaskUseType mask_use_type = is_vector_mask(vbox_klass) ? VecMaskUseAll
: is_masked_op ? VecMaskUseLoad : VecMaskNotUsed;
@@ -464,30 +442,18 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) {
}
Node* operation = nullptr;
- if (opc == Op_CallLeafVector) {
- assert(UseVectorStubs, "sanity");
- operation = gen_call_to_vector_math(opr->get_con(), elem_bt, num_elem, opd1, opd2);
- if (operation == nullptr) {
- log_if_needed(" ** Vector math call failed for %s_%s_%d",
- (elem_bt == T_FLOAT) ? "float" : "double",
- VectorSupport::mathname[opr->get_con() - VectorSupport::VECTOR_OP_MATH_START],
- num_elem * type2aelembytes(elem_bt));
- return false;
- }
- } else {
- const TypeVect* vt = TypeVect::make(elem_bt, num_elem, is_vector_mask(vbox_klass));
- switch (n) {
- case 1:
- case 2: {
- operation = VectorNode::make(sopc, opd1, opd2, vt, is_vector_mask(vbox_klass), VectorNode::is_shift_opcode(opc), is_unsigned);
- break;
- }
- case 3: {
- operation = VectorNode::make(sopc, opd1, opd2, opd3, vt);
- break;
- }
- default: fatal("unsupported arity: %d", n);
+ const TypeVect* vt = TypeVect::make(elem_bt, num_elem, is_vector_mask(vbox_klass));
+ switch (n) {
+ case 1:
+ case 2: {
+ operation = VectorNode::make(sopc, opd1, opd2, vt, is_vector_mask(vbox_klass), VectorNode::is_shift_opcode(opc), is_unsigned);
+ break;
}
+ case 3: {
+ operation = VectorNode::make(sopc, opd1, opd2, opd3, vt);
+ break;
+ }
+ default: fatal("unsupported arity: %d", n);
}
if (is_masked_op && mask != nullptr) {
@@ -510,6 +476,107 @@ bool LibraryCallKit::inline_vector_nary_operation(int n) {
}
// public static
+// , E>
+// V libraryUnaryOp(long address, Class extends V> vClass, Class elementType, int length, String debugName,
+// V v,
+// UnaryOperation defaultImpl)
+//
+// public static
+//
+// V libraryBinaryOp(long address, Class extends V> vClass, Class elementType, int length, String debugName,
+// V v1, V v2,
+// BinaryOperation defaultImpl)
+bool LibraryCallKit::inline_vector_call(int arity) {
+ assert(Matcher::supports_vector_calling_convention(), "required");
+
+ const TypeLong* entry = gvn().type(argument(0))->isa_long();
+ const TypeInstPtr* vector_klass = gvn().type(argument(2))->isa_instptr();
+ const TypeInstPtr* elem_klass = gvn().type(argument(3))->isa_instptr();
+ const TypeInt* vlen = gvn().type(argument(4))->isa_int();
+ const TypeInstPtr* debug_name_oop = gvn().type(argument(5))->isa_instptr();
+
+ if (entry == nullptr || !entry->is_con() ||
+ vector_klass == nullptr || vector_klass->const_oop() == nullptr ||
+ elem_klass == nullptr || elem_klass->const_oop() == nullptr ||
+ vlen == nullptr || !vlen->is_con() ||
+ debug_name_oop == nullptr || debug_name_oop->const_oop() == nullptr) {
+ log_if_needed(" ** missing constant: opr=%s vclass=%s etype=%s vlen=%s debug_name=%s",
+ NodeClassNames[argument(0)->Opcode()],
+ NodeClassNames[argument(2)->Opcode()],
+ NodeClassNames[argument(3)->Opcode()],
+ NodeClassNames[argument(4)->Opcode()],
+ NodeClassNames[argument(5)->Opcode()]);
+ return false; // not enough info for intrinsification
+ }
+
+ if (entry->get_con() == 0) {
+ log_if_needed(" ** missing entry point");
+ return false;
+ }
+
+ ciType* elem_type = elem_klass->const_oop()->as_instance()->java_mirror_type();
+ if (!elem_type->is_primitive_type()) {
+ log_if_needed(" ** not a primitive bt=%d", elem_type->basic_type());
+ return false; // should be primitive type
+ }
+ if (!is_klass_initialized(vector_klass)) {
+ log_if_needed(" ** klass argument not initialized");
+ return false;
+ }
+
+ BasicType elem_bt = elem_type->basic_type();
+ int num_elem = vlen->get_con();
+ if (!Matcher::vector_size_supported(elem_bt, num_elem)) {
+ log_if_needed(" ** vector size (vlen=%d, etype=%s) is not supported",
+ num_elem, type2name(elem_bt));
+ return false;
+ }
+
+ ciKlass* vbox_klass = vector_klass->const_oop()->as_instance()->java_lang_Class_klass();
+ const TypeInstPtr* vbox_type = TypeInstPtr::make_exact(TypePtr::NotNull, vbox_klass);
+
+ Node* opd1 = unbox_vector(argument(6), vbox_type, elem_bt, num_elem);
+ if (opd1 == nullptr) {
+ log_if_needed(" ** unbox failed v1=%s", NodeClassNames[argument(6)->Opcode()]);
+ return false;
+ }
+
+ Node* opd2 = nullptr;
+ if (arity > 1) {
+ opd2 = unbox_vector(argument(7), vbox_type, elem_bt, num_elem);
+ if (opd2 == nullptr) {
+ log_if_needed(" ** unbox failed v2=%s", NodeClassNames[argument(7)->Opcode()]);
+ return false;
+ }
+ }
+ assert(arity == 1 || arity == 2, "arity %d not supported", arity);
+ const TypeVect* vt = TypeVect::make(elem_bt, num_elem);
+ const TypeFunc* call_type = OptoRuntime::Math_Vector_Vector_Type(arity, vt, vt);
+ address entry_addr = (address)entry->get_con();
+
+ const char* debug_name = "";
+ if (!debug_name_oop->const_oop()->is_null_object()) {
+ size_t buflen = 100;
+ char* buf = NEW_ARENA_ARRAY(C->comp_arena(), char, buflen);
+ debug_name = debug_name_oop->const_oop()->as_instance()->java_lang_String_str(buf, buflen);
+ }
+ Node* vcall = make_runtime_call(RC_VECTOR,
+ call_type,
+ entry_addr,
+ debug_name,
+ TypePtr::BOTTOM,
+ opd1,
+ opd2);
+
+ vcall = gvn().transform(new ProjNode(gvn().transform(vcall), TypeFunc::Parms));
+
+ // Wrap it up in VectorBox to keep object type information.
+ Node* vbox = box_vector(vcall, vbox_type, elem_bt, num_elem);
+ set_result(vbox);
+ C->set_max_vector_size(MAX2(C->max_vector_size(), (uint)(num_elem * type2aelembytes(elem_bt))));
+ return true;
+}
+
//
// long maskReductionCoerced(int oper, Class extends M> maskClass, Class> elemClass,
// int length, M m, VectorMaskOp defaultImpl)
@@ -1844,50 +1911,6 @@ bool LibraryCallKit::inline_vector_rearrange() {
return true;
}
-static address get_vector_math_address(int vop, int bits, BasicType bt, char* name_ptr, int name_len) {
- address addr = nullptr;
- assert(UseVectorStubs, "sanity");
- assert(name_ptr != nullptr, "unexpected");
- assert((vop >= VectorSupport::VECTOR_OP_MATH_START) && (vop <= VectorSupport::VECTOR_OP_MATH_END), "unexpected");
- int op = vop - VectorSupport::VECTOR_OP_MATH_START;
-
- switch(bits) {
- case 64: //fallthough
- case 128: //fallthough
- case 256: //fallthough
- case 512:
- if (bt == T_FLOAT) {
- snprintf(name_ptr, name_len, "vector_%s_float_%dbits_fixed", VectorSupport::mathname[op], bits);
- addr = StubRoutines::_vector_f_math[exact_log2(bits/64)][op];
- } else {
- assert(bt == T_DOUBLE, "must be FP type only");
- snprintf(name_ptr, name_len, "vector_%s_double_%dbits_fixed", VectorSupport::mathname[op], bits);
- addr = StubRoutines::_vector_d_math[exact_log2(bits/64)][op];
- }
- break;
- default:
- if (!Matcher::supports_scalable_vector() || !Matcher::vector_size_supported(bt, bits/type2aelembytes(bt)) ) {
- snprintf(name_ptr, name_len, "invalid");
- addr = nullptr;
- Unimplemented();
- }
- break;
- }
-
- if (addr == nullptr && Matcher::supports_scalable_vector()) {
- if (bt == T_FLOAT) {
- snprintf(name_ptr, name_len, "vector_%s_float_%dbits_scalable", VectorSupport::mathname[op], bits);
- addr = StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_SCALABLE][op];
- } else {
- assert(bt == T_DOUBLE, "must be FP type only");
- snprintf(name_ptr, name_len, "vector_%s_double_%dbits_scalable", VectorSupport::mathname[op], bits);
- addr = StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_SCALABLE][op];
- }
- }
-
- return addr;
-}
-
// public static
// ,
// M extends VectorMask,
@@ -2044,32 +2067,6 @@ bool LibraryCallKit::inline_vector_select_from() {
return true;
}
-Node* LibraryCallKit::gen_call_to_vector_math(int vector_api_op_id, BasicType bt, int num_elem, Node* opd1, Node* opd2) {
- assert(UseVectorStubs, "sanity");
- assert(vector_api_op_id >= VectorSupport::VECTOR_OP_MATH_START && vector_api_op_id <= VectorSupport::VECTOR_OP_MATH_END, "need valid op id");
- assert(opd1 != nullptr, "must not be null");
- const TypeVect* vt = TypeVect::make(bt, num_elem);
- const TypeFunc* call_type = OptoRuntime::Math_Vector_Vector_Type(opd2 != nullptr ? 2 : 1, vt, vt);
- char name[100] = "";
-
- // Get address for vector math method.
- address addr = get_vector_math_address(vector_api_op_id, vt->length_in_bytes() * BitsPerByte, bt, name, 100);
-
- if (addr == nullptr) {
- return nullptr;
- }
-
- assert(name[0] != '\0', "name must not be null");
- Node* operation = make_runtime_call(RC_VECTOR,
- call_type,
- addr,
- name,
- TypePtr::BOTTOM,
- opd1,
- opd2);
- return gvn().transform(new ProjNode(gvn().transform(operation), TypeFunc::Parms));
-}
-
// public static
// ,
// M extends VectorMask,
diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp
index 084b70a6906..05ef64af704 100644
--- a/src/hotspot/share/opto/vectornode.cpp
+++ b/src/hotspot/share/opto/vectornode.cpp
@@ -2237,6 +2237,72 @@ bool MulVLNode::has_uint_inputs() const {
has_vector_elements_fit_uint(in(2));
}
+static Node* UMinMaxV_Ideal(Node* n, PhaseGVN* phase, bool can_reshape) {
+ int vopc = n->Opcode();
+ assert(vopc == Op_UMinV || vopc == Op_UMaxV, "Unexpected opcode");
+
+ Node* umin = nullptr;
+ Node* umax = nullptr;
+ int lopc = n->in(1)->Opcode();
+ int ropc = n->in(2)->Opcode();
+
+ if (lopc == Op_UMinV && ropc == Op_UMaxV) {
+ umin = n->in(1);
+ umax = n->in(2);
+ } else if (lopc == Op_UMaxV && ropc == Op_UMinV) {
+ umin = n->in(2);
+ umax = n->in(1);
+ } else {
+ return nullptr;
+ }
+
+ // UMin (UMin(a, b), UMax(a, b)) => UMin(a, b)
+ // UMin (UMax(a, b), UMin(b, a)) => UMin(a, b)
+ // UMax (UMin(a, b), UMax(a, b)) => UMax(a, b)
+ // UMax (UMax(a, b), UMin(b, a)) => UMax(a, b)
+ if (umin != nullptr && umax != nullptr) {
+ if ((umin->in(1) == umax->in(1) && umin->in(2) == umax->in(2)) ||
+ (umin->in(2) == umax->in(1) && umin->in(1) == umax->in(2))) {
+ if (vopc == Op_UMinV) {
+ return new UMinVNode(umax->in(1), umax->in(2), n->bottom_type()->is_vect());
+ } else {
+ return new UMaxVNode(umax->in(1), umax->in(2), n->bottom_type()->is_vect());
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+Node* UMinVNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ Node* progress = UMinMaxV_Ideal(this, phase, can_reshape);
+ if (progress != nullptr) return progress;
+
+ return VectorNode::Ideal(phase, can_reshape);
+}
+
+Node* UMinVNode::Identity(PhaseGVN* phase) {
+ // UMin (a, a) => a
+ if (in(1) == in(2)) {
+ return in(1);
+ }
+ return this;
+}
+
+Node* UMaxVNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ Node* progress = UMinMaxV_Ideal(this, phase, can_reshape);
+ if (progress != nullptr) return progress;
+
+ return VectorNode::Ideal(phase, can_reshape);
+}
+
+Node* UMaxVNode::Identity(PhaseGVN* phase) {
+ // UMax (a, a) => a
+ if (in(1) == in(2)) {
+ return in(1);
+ }
+ return this;
+}
#ifndef PRODUCT
void VectorBoxAllocateNode::dump_spec(outputStream *st) const {
CallStaticJavaNode::dump_spec(st);
diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp
index ae817598d39..e72c3880c79 100644
--- a/src/hotspot/share/opto/vectornode.hpp
+++ b/src/hotspot/share/opto/vectornode.hpp
@@ -675,9 +675,12 @@ class UMinVNode : public VectorNode {
UMinVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2 ,vt) {
assert(is_integral_type(vt->element_basic_type()), "");
}
+ virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+ virtual Node* Identity(PhaseGVN* phase);
virtual int Opcode() const;
};
+
//------------------------------MaxVNode--------------------------------------
// Vector Max
class MaxVNode : public VectorNode {
@@ -691,6 +694,8 @@ class UMaxVNode : public VectorNode {
UMaxVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {
assert(is_integral_type(vt->element_basic_type()), "");
}
+ virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+ virtual Node* Identity(PhaseGVN* phase);
virtual int Opcode() const;
};
diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp
index d2916fad185..228244bbd05 100644
--- a/src/hotspot/share/prims/jni.cpp
+++ b/src/hotspot/share/prims/jni.cpp
@@ -215,7 +215,7 @@ intptr_t jfieldIDWorkaround::encode_klass_hash(Klass* k, int offset) {
field_klass = super_klass; // super contains the field also
super_klass = field_klass->super();
}
- debug_only(NoSafepointVerifier nosafepoint;)
+ DEBUG_ONLY(NoSafepointVerifier nosafepoint;)
uintptr_t klass_hash = field_klass->identity_hash();
return ((klass_hash & klass_mask) << klass_shift) | checked_mask_in_place;
} else {
@@ -235,7 +235,7 @@ bool jfieldIDWorkaround::klass_hash_ok(Klass* k, jfieldID id) {
uintptr_t as_uint = (uintptr_t) id;
intptr_t klass_hash = (as_uint >> klass_shift) & klass_mask;
do {
- debug_only(NoSafepointVerifier nosafepoint;)
+ DEBUG_ONLY(NoSafepointVerifier nosafepoint;)
// Could use a non-blocking query for identity_hash here...
if ((k->identity_hash() & klass_mask) == klass_hash)
return true;
@@ -410,7 +410,7 @@ JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field))
int offset = InstanceKlass::cast(k1)->field_offset( slot );
JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
assert(id != nullptr, "corrupt Field object");
- debug_only(id->set_is_static_field_id();)
+ DEBUG_ONLY(id->set_is_static_field_id();)
// A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
ret = jfieldIDWorkaround::to_static_jfieldID(id);
return ret;
@@ -472,7 +472,7 @@ JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
// return mirror for superclass
Klass* super = k->java_super();
// super2 is the value computed by the compiler's getSuperClass intrinsic:
- debug_only(Klass* super2 = ( k->is_array_klass()
+ DEBUG_ONLY(Klass* super2 = ( k->is_array_klass()
? vmClasses::Object_klass()
: k->super() ) );
assert(super == super2,
@@ -906,7 +906,7 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive
selected_method = m;
} else if (!m->has_itable_index()) {
// non-interface call -- for that little speed boost, don't handlize
- debug_only(NoSafepointVerifier nosafepoint;)
+ DEBUG_ONLY(NoSafepointVerifier nosafepoint;)
// jni_GetMethodID makes sure class is linked and initialized
// so m should have a valid vtable index.
assert(m->valid_vtable_index(), "no valid vtable index");
@@ -1995,9 +1995,9 @@ JNI_ENTRY(jfieldID, jni_GetStaticFieldID(JNIEnv *env, jclass clazz,
// A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
JNIid* id = fd.field_holder()->jni_id_for(fd.offset());
- debug_only(id->set_is_static_field_id();)
+ DEBUG_ONLY(id->set_is_static_field_id();)
- debug_only(id->verify(fd.field_holder()));
+ DEBUG_ONLY(id->verify(fd.field_holder()));
ret = jfieldIDWorkaround::to_static_jfieldID(id);
return ret;
@@ -2400,7 +2400,7 @@ static char* get_bad_address() {
static char* bad_address = nullptr;
if (bad_address == nullptr) {
size_t size = os::vm_allocation_granularity();
- bad_address = os::reserve_memory(size, false, mtInternal);
+ bad_address = os::reserve_memory(size, mtInternal);
if (bad_address != nullptr) {
os::protect_memory(bad_address, size, os::MEM_PROT_READ,
/*is_committed*/false);
diff --git a/src/hotspot/share/prims/jniCheck.cpp b/src/hotspot/share/prims/jniCheck.cpp
index aa158490eab..14d9c36c9fd 100644
--- a/src/hotspot/share/prims/jniCheck.cpp
+++ b/src/hotspot/share/prims/jniCheck.cpp
@@ -2320,7 +2320,7 @@ struct JNINativeInterface_* jni_functions_check() {
// make sure the last pointer in the checked table is not null, indicating
// an addition to the JNINativeInterface_ structure without initializing
// it in the checked table.
- debug_only(intptr_t *lastPtr = (intptr_t *)((char *)&checked_jni_NativeInterface + \
+ DEBUG_ONLY(intptr_t *lastPtr = (intptr_t *)((char *)&checked_jni_NativeInterface + \
sizeof(*unchecked_jni_NativeInterface) - sizeof(char *));)
assert(*lastPtr != 0,
"Mismatched JNINativeInterface tables, check for new entries");
diff --git a/src/hotspot/share/prims/jvmtiEnter.xsl b/src/hotspot/share/prims/jvmtiEnter.xsl
index bbca1ccc6e1..d1274158be4 100644
--- a/src/hotspot/share/prims/jvmtiEnter.xsl
+++ b/src/hotspot/share/prims/jvmtiEnter.xsl
@@ -444,7 +444,7 @@ struct jvmtiInterface_1_ jvmti
, current_thread)
- debug_only(VMNativeEntryWrapper __vew;)
+ DEBUG_ONLY(VMNativeEntryWrapper __vew;)PreserveExceptionMark __em(this_thread);
diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp
index 7a0c9a428c5..b2af12b08a6 100644
--- a/src/hotspot/share/prims/jvmtiEnv.cpp
+++ b/src/hotspot/share/prims/jvmtiEnv.cpp
@@ -199,7 +199,7 @@ JvmtiEnv::GetThreadLocalStorage(jthread thread, void** data_ptr) {
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current_thread));
ThreadInVMfromNative __tiv(current_thread);
VM_ENTRY_BASE(jvmtiError, JvmtiEnv::GetThreadLocalStorage , current_thread)
- debug_only(VMNativeEntryWrapper __vew;)
+ DEBUG_ONLY(VMNativeEntryWrapper __vew;)
JvmtiVTMSTransitionDisabler disabler(thread);
ThreadsListHandle tlh(current_thread);
diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp
index 32dd6fc13e7..13822f73f77 100644
--- a/src/hotspot/share/prims/jvmtiExport.cpp
+++ b/src/hotspot/share/prims/jvmtiExport.cpp
@@ -384,7 +384,7 @@ JvmtiExport::get_jvmti_interface(JavaVM *jvm, void **penv, jint version) {
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current_thread));
ThreadInVMfromNative __tiv(current_thread);
VM_ENTRY_BASE(jvmtiEnv*, JvmtiExport::get_jvmti_interface, current_thread)
- debug_only(VMNativeEntryWrapper __vew;)
+ DEBUG_ONLY(VMNativeEntryWrapper __vew;)
JvmtiEnv *jvmti_env = JvmtiEnv::create_a_jvmti(version);
*penv = jvmti_env->jvmti_external(); // actual type is jvmtiEnv* -- not to be confused with JvmtiEnv*
diff --git a/src/hotspot/share/prims/jvmtiThreadState.cpp b/src/hotspot/share/prims/jvmtiThreadState.cpp
index e9d496fc696..b4119825bd3 100644
--- a/src/hotspot/share/prims/jvmtiThreadState.cpp
+++ b/src/hotspot/share/prims/jvmtiThreadState.cpp
@@ -102,7 +102,7 @@ JvmtiThreadState::JvmtiThreadState(JavaThread* thread, oop thread_oop)
{
// The thread state list manipulation code must not have safepoints.
// See periodic_clean_up().
- debug_only(NoSafepointVerifier nosafepoint;)
+ DEBUG_ONLY(NoSafepointVerifier nosafepoint;)
_prev = nullptr;
_next = _head;
@@ -154,7 +154,7 @@ JvmtiThreadState::~JvmtiThreadState() {
{
// The thread state list manipulation code must not have safepoints.
// See periodic_clean_up().
- debug_only(NoSafepointVerifier nosafepoint;)
+ DEBUG_ONLY(NoSafepointVerifier nosafepoint;)
if (_prev == nullptr) {
assert(_head == this, "sanity check");
@@ -759,7 +759,7 @@ void JvmtiThreadState::add_env(JvmtiEnvBase *env) {
// add this environment thread state to the end of the list (order is important)
{
// list deallocation (which occurs at a safepoint) cannot occur simultaneously
- debug_only(NoSafepointVerifier nosafepoint;)
+ DEBUG_ONLY(NoSafepointVerifier nosafepoint;)
JvmtiEnvThreadStateIterator it(this);
JvmtiEnvThreadState* previous_ets = nullptr;
diff --git a/src/hotspot/share/prims/methodHandles.cpp b/src/hotspot/share/prims/methodHandles.cpp
index 246e2cdbb13..1ab5d6ab7f7 100644
--- a/src/hotspot/share/prims/methodHandles.cpp
+++ b/src/hotspot/share/prims/methodHandles.cpp
@@ -929,8 +929,7 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) {
}
void MethodHandles::add_dependent_nmethod(oop call_site, nmethod* nm) {
- assert_locked_or_safepoint(CodeCache_lock);
-
+ assert_lock_strong(CodeCache_lock);
DependencyContext deps = java_lang_invoke_CallSite::vmdependencies(call_site);
deps.add_dependent_nmethod(nm);
}
diff --git a/src/hotspot/share/prims/perf.cpp b/src/hotspot/share/prims/perf.cpp
index f5f91e4614f..0b051bbc60f 100644
--- a/src/hotspot/share/prims/perf.cpp
+++ b/src/hotspot/share/prims/perf.cpp
@@ -111,7 +111,7 @@ PERF_ENTRY(jobject, Perf_CreateLong(JNIEnv *env, jobject perf, jstring name,
char* name_utf = nullptr;
if (units <= 0 || units > PerfData::U_Last) {
- debug_only(warning("unexpected units argument, units = %d", units));
+ DEBUG_ONLY(warning("unexpected units argument, units = %d", units));
THROW_NULL(vmSymbols::java_lang_IllegalArgumentException());
}
@@ -150,7 +150,7 @@ PERF_ENTRY(jobject, Perf_CreateLong(JNIEnv *env, jobject perf, jstring name,
break;
default: /* Illegal Argument */
- debug_only(warning("unexpected variability value: %d", variability));
+ DEBUG_ONLY(warning("unexpected variability value: %d", variability));
THROW_NULL(vmSymbols::java_lang_IllegalArgumentException());
break;
}
@@ -179,14 +179,14 @@ PERF_ENTRY(jobject, Perf_CreateByteArray(JNIEnv *env, jobject perf,
// check for valid variability classification
if (variability != PerfData::V_Constant &&
variability != PerfData::V_Variable) {
- debug_only(warning("unexpected variability value: %d", variability));
+ DEBUG_ONLY(warning("unexpected variability value: %d", variability));
THROW_NULL(vmSymbols::java_lang_IllegalArgumentException());
}
// check for valid units
if (units != PerfData::U_String) {
// only String based ByteArray objects are currently supported
- debug_only(warning("unexpected units value: %d", variability));
+ DEBUG_ONLY(warning("unexpected units value: %d", variability));
THROW_NULL(vmSymbols::java_lang_IllegalArgumentException());
}
diff --git a/src/hotspot/share/prims/upcallLinker.cpp b/src/hotspot/share/prims/upcallLinker.cpp
index 911f0f3ad2c..bc6a56dab05 100644
--- a/src/hotspot/share/prims/upcallLinker.cpp
+++ b/src/hotspot/share/prims/upcallLinker.cpp
@@ -104,7 +104,7 @@ JavaThread* UpcallLinker::on_entry(UpcallStub::FrameData* context) {
context->jfa.copy(thread->frame_anchor());
thread->frame_anchor()->clear();
- debug_only(thread->inc_java_call_counter());
+ DEBUG_ONLY(thread->inc_java_call_counter());
thread->set_active_handles(context->new_handles); // install new handle block and reset Java frame linkage
return thread;
@@ -118,7 +118,7 @@ void UpcallLinker::on_exit(UpcallStub::FrameData* context) {
// restore previous handle block
thread->set_active_handles(context->old_handles);
- debug_only(thread->dec_java_call_counter());
+ DEBUG_ONLY(thread->dec_java_call_counter());
thread->frame_anchor()->copy(&context->jfa);
diff --git a/src/hotspot/share/prims/vectorSupport.cpp b/src/hotspot/share/prims/vectorSupport.cpp
index a00656f30ee..c907ddb4885 100644
--- a/src/hotspot/share/prims/vectorSupport.cpp
+++ b/src/hotspot/share/prims/vectorSupport.cpp
@@ -39,31 +39,9 @@
#include "runtime/stackValue.hpp"
#ifdef COMPILER2
#include "opto/matcher.hpp"
+#include "opto/vectornode.hpp"
#endif // COMPILER2
-#ifdef COMPILER2
-const char* VectorSupport::mathname[VectorSupport::NUM_VECTOR_OP_MATH] = {
- "tan",
- "tanh",
- "sin",
- "sinh",
- "cos",
- "cosh",
- "asin",
- "acos",
- "atan",
- "atan2",
- "cbrt",
- "log",
- "log10",
- "log1p",
- "pow",
- "exp",
- "expm1",
- "hypot",
-};
-#endif
-
bool VectorSupport::is_vector(Klass* klass) {
return klass->is_subclass_of(vmClasses::vector_VectorPayload_klass());
}
@@ -615,25 +593,6 @@ int VectorSupport::vop2ideal(jint id, BasicType bt) {
break;
}
- case VECTOR_OP_TAN:
- case VECTOR_OP_TANH:
- case VECTOR_OP_SIN:
- case VECTOR_OP_SINH:
- case VECTOR_OP_COS:
- case VECTOR_OP_COSH:
- case VECTOR_OP_ASIN:
- case VECTOR_OP_ACOS:
- case VECTOR_OP_ATAN:
- case VECTOR_OP_ATAN2:
- case VECTOR_OP_CBRT:
- case VECTOR_OP_LOG:
- case VECTOR_OP_LOG10:
- case VECTOR_OP_LOG1P:
- case VECTOR_OP_POW:
- case VECTOR_OP_EXP:
- case VECTOR_OP_EXPM1:
- case VECTOR_OP_HYPOT:
- return Op_CallLeafVector;
default: fatal("unknown op: %d", vop);
}
return 0; // Unimplemented
@@ -655,16 +614,26 @@ JVM_ENTRY(jint, VectorSupport_GetMaxLaneCount(JNIEnv *env, jclass vsclazz, jobje
return -1;
} JVM_END
+JVM_ENTRY(jstring, VectorSupport_GetCPUFeatures(JNIEnv* env, jclass ignored))
+ const char* features_string = VM_Version::features_string();
+ assert(features_string != nullptr, "missing cpu features info");
+
+ oop result = java_lang_String::create_oop_from_str(features_string, CHECK_NULL);
+ return (jstring) JNIHandles::make_local(THREAD, result);
+JVM_END
+
// JVM_RegisterVectorSupportMethods
#define LANG "Ljava/lang/"
#define CLS LANG "Class;"
+#define LSTR LANG "String;"
#define CC (char*) /*cast a literal from (const char*)*/
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
static JNINativeMethod jdk_internal_vm_vector_VectorSupport_methods[] = {
- {CC "getMaxLaneCount", CC "(" CLS ")I", FN_PTR(VectorSupport_GetMaxLaneCount)}
+ {CC "getMaxLaneCount", CC "(" CLS ")I", FN_PTR(VectorSupport_GetMaxLaneCount)},
+ {CC "getCPUFeatures", CC "()" LSTR, FN_PTR(VectorSupport_GetCPUFeatures)}
};
#undef CC
@@ -672,6 +641,7 @@ static JNINativeMethod jdk_internal_vm_vector_VectorSupport_methods[] = {
#undef LANG
#undef CLS
+#undef LSTR
// This function is exported, used by NativeLookup.
diff --git a/src/hotspot/share/prims/vectorSupport.hpp b/src/hotspot/share/prims/vectorSupport.hpp
index 688fb595099..5ba18cdfaa8 100644
--- a/src/hotspot/share/prims/vectorSupport.hpp
+++ b/src/hotspot/share/prims/vectorSupport.hpp
@@ -101,36 +101,12 @@ class VectorSupport : AllStatic {
VECTOR_OP_COMPRESS_BITS = 33,
VECTOR_OP_EXPAND_BITS = 34,
- // Vector Math Library
- VECTOR_OP_TAN = 101,
- VECTOR_OP_TANH = 102,
- VECTOR_OP_SIN = 103,
- VECTOR_OP_SINH = 104,
- VECTOR_OP_COS = 105,
- VECTOR_OP_COSH = 106,
- VECTOR_OP_ASIN = 107,
- VECTOR_OP_ACOS = 108,
- VECTOR_OP_ATAN = 109,
- VECTOR_OP_ATAN2 = 110,
- VECTOR_OP_CBRT = 111,
- VECTOR_OP_LOG = 112,
- VECTOR_OP_LOG10 = 113,
- VECTOR_OP_LOG1P = 114,
- VECTOR_OP_POW = 115,
- VECTOR_OP_EXP = 116,
- VECTOR_OP_EXPM1 = 117,
- VECTOR_OP_HYPOT = 118,
-
VECTOR_OP_SADD = 119,
VECTOR_OP_SSUB = 120,
VECTOR_OP_SUADD = 121,
VECTOR_OP_SUSUB = 122,
VECTOR_OP_UMIN = 123,
VECTOR_OP_UMAX = 124,
-
- VECTOR_OP_MATH_START = VECTOR_OP_TAN,
- VECTOR_OP_MATH_END = VECTOR_OP_HYPOT,
- NUM_VECTOR_OP_MATH = VECTOR_OP_MATH_END - VECTOR_OP_MATH_START + 1
};
enum {
@@ -147,8 +123,6 @@ class VectorSupport : AllStatic {
MODE_BITS_COERCED_LONG_TO_MASK = 1
};
- static const char* mathname[VectorSupport::NUM_VECTOR_OP_MATH];
-
static int vop2ideal(jint vop, BasicType bt);
static bool has_scalar_op(jint id);
static bool is_unsigned_op(jint id);
diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp
index e08a5ba5ebd..2e277ffadab 100644
--- a/src/hotspot/share/prims/whitebox.cpp
+++ b/src/hotspot/share/prims/whitebox.cpp
@@ -728,11 +728,11 @@ WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
WB_END
WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
- return (jlong)(uintptr_t)os::reserve_memory(size, false, mtTest);
+ return (jlong)(uintptr_t)os::reserve_memory(size, mtTest);
WB_END
WB_ENTRY(jlong, WB_NMTAttemptReserveMemoryAt(JNIEnv* env, jobject o, jlong addr, jlong size))
- return (jlong)(uintptr_t)os::attempt_reserve_memory_at((char*)(uintptr_t)addr, (size_t)size, false, mtTest);
+ return (jlong)(uintptr_t)os::attempt_reserve_memory_at((char*)(uintptr_t)addr, (size_t)size, mtTest);
WB_END
WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
@@ -1524,7 +1524,7 @@ WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
static char c;
static volatile char* p;
- p = os::reserve_memory(os::vm_allocation_granularity());
+ p = os::reserve_memory(os::vm_allocation_granularity(), mtTest);
if (p == nullptr) {
THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory");
}
@@ -1533,7 +1533,7 @@ WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
WB_END
WB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o))
- const char* features = VM_Version::features_string();
+ const char* features = VM_Version::cpu_info_string();
ThreadToNativeFromVM ttn(thread);
jstring features_string = env->NewStringUTF(features);
diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp
index e95c96b4e9c..c0667d739ce 100644
--- a/src/hotspot/share/runtime/abstract_vm_version.cpp
+++ b/src/hotspot/share/runtime/abstract_vm_version.cpp
@@ -34,6 +34,7 @@ const char* Abstract_VM_Version::_s_internal_vm_info_string = Abstract_VM_Versio
uint64_t Abstract_VM_Version::_features = 0;
const char* Abstract_VM_Version::_features_string = "";
+const char* Abstract_VM_Version::_cpu_info_string = "";
uint64_t Abstract_VM_Version::_cpu_features = 0;
#ifndef SUPPORTS_NATIVE_CX8
@@ -340,6 +341,19 @@ void Abstract_VM_Version::insert_features_names(char* buf, size_t buflen, const
}
}
+const char* Abstract_VM_Version::extract_features_string(const char* cpu_info_string,
+ size_t cpu_info_string_len,
+ size_t features_offset) {
+ assert(features_offset <= cpu_info_string_len, "");
+ if (features_offset < cpu_info_string_len) {
+ assert(cpu_info_string[features_offset + 0] == ',', "");
+ assert(cpu_info_string[features_offset + 1] == ' ', "");
+ return cpu_info_string + features_offset + 2; // skip initial ", "
+ } else {
+ return ""; // empty
+ }
+}
+
bool Abstract_VM_Version::print_matching_lines_from_file(const char* filename, outputStream* st, const char* keywords_to_match[]) {
char line[500];
FILE* fp = os::fopen(filename, "r");
diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp
index 8cfc7031f97..6f1b886bc98 100644
--- a/src/hotspot/share/runtime/abstract_vm_version.hpp
+++ b/src/hotspot/share/runtime/abstract_vm_version.hpp
@@ -58,6 +58,8 @@ class Abstract_VM_Version: AllStatic {
static uint64_t _features;
static const char* _features_string;
+ static const char* _cpu_info_string;
+
// Original CPU feature flags, not affected by VM settings.
static uint64_t _cpu_features;
@@ -128,7 +130,11 @@ class Abstract_VM_Version: AllStatic {
static uint64_t features() { return _features; }
static const char* features_string() { return _features_string; }
+ static const char* cpu_info_string() { return _cpu_info_string; }
static void insert_features_names(char* buf, size_t buflen, const char* features_names[]);
+ static const char* extract_features_string(const char* cpu_info_string,
+ size_t cpu_info_string_len,
+ size_t features_offset);
static VirtualizationType get_detected_virtualization() {
return _detected_virtualization;
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
index b3e0600df34..69d37a11e45 100644
--- a/src/hotspot/share/runtime/arguments.cpp
+++ b/src/hotspot/share/runtime/arguments.cpp
@@ -332,7 +332,6 @@ bool Arguments::internal_module_property_helper(const char* property, bool check
if (strncmp(property, MODULE_PROPERTY_PREFIX, MODULE_PROPERTY_PREFIX_LEN) == 0) {
const char* property_suffix = property + MODULE_PROPERTY_PREFIX_LEN;
if (matches_property_suffix(property_suffix, ADDREADS, ADDREADS_LEN) ||
- matches_property_suffix(property_suffix, ADDOPENS, ADDOPENS_LEN) ||
matches_property_suffix(property_suffix, PATCH, PATCH_LEN) ||
matches_property_suffix(property_suffix, LIMITMODS, LIMITMODS_LEN) ||
matches_property_suffix(property_suffix, UPGRADE_PATH, UPGRADE_PATH_LEN) ||
@@ -343,6 +342,7 @@ bool Arguments::internal_module_property_helper(const char* property, bool check
if (!check_for_cds) {
// CDS notes: these properties are supported by CDS archived full module graph.
if (matches_property_suffix(property_suffix, ADDEXPORTS, ADDEXPORTS_LEN) ||
+ matches_property_suffix(property_suffix, ADDOPENS, ADDOPENS_LEN) ||
matches_property_suffix(property_suffix, PATH, PATH_LEN) ||
matches_property_suffix(property_suffix, ADDMODS, ADDMODS_LEN) ||
matches_property_suffix(property_suffix, ENABLE_NATIVE_ACCESS, ENABLE_NATIVE_ACCESS_LEN)) {
@@ -3786,11 +3786,6 @@ jint Arguments::apply_ergo() {
}
}
FLAG_SET_DEFAULT(EnableVectorAggressiveReboxing, false);
-
- if (!FLAG_IS_DEFAULT(UseVectorStubs) && UseVectorStubs) {
- warning("Disabling UseVectorStubs since EnableVectorSupport is turned off.");
- }
- FLAG_SET_DEFAULT(UseVectorStubs, false);
}
#endif // COMPILER2_OR_JVMCI
diff --git a/src/hotspot/share/runtime/handles.cpp b/src/hotspot/share/runtime/handles.cpp
index f747b4dc76e..cd3bd3eb3e0 100644
--- a/src/hotspot/share/runtime/handles.cpp
+++ b/src/hotspot/share/runtime/handles.cpp
@@ -133,7 +133,7 @@ void HandleMark::initialize(Thread* thread) {
_hwm = _area->_hwm;
_max = _area->_max;
_size_in_bytes = _area->_size_in_bytes;
- debug_only(_area->_handle_mark_nesting++);
+ DEBUG_ONLY(_area->_handle_mark_nesting++);
assert(_area->_handle_mark_nesting > 0, "must stack allocate HandleMarks");
// Link this in the thread
diff --git a/src/hotspot/share/runtime/handles.hpp b/src/hotspot/share/runtime/handles.hpp
index 8ed16d33a2f..d2020e34121 100644
--- a/src/hotspot/share/runtime/handles.hpp
+++ b/src/hotspot/share/runtime/handles.hpp
@@ -188,8 +188,8 @@ class HandleArea: public Arena {
public:
// Constructor
HandleArea(MemTag mem_tag, HandleArea* prev) : Arena(mem_tag, Tag::tag_ha, Chunk::tiny_size) {
- debug_only(_handle_mark_nesting = 0);
- debug_only(_no_handle_mark_nesting = 0);
+ DEBUG_ONLY(_handle_mark_nesting = 0);
+ DEBUG_ONLY(_no_handle_mark_nesting = 0);
_prev = prev;
}
@@ -212,7 +212,7 @@ class HandleArea: public Arena {
// Garbage collection support
void oops_do(OopClosure* f);
- debug_only(bool no_handle_mark_active() { return _no_handle_mark_nesting > 0; })
+ DEBUG_ONLY(bool no_handle_mark_active() { return _no_handle_mark_nesting > 0; })
};
diff --git a/src/hotspot/share/runtime/handles.inline.hpp b/src/hotspot/share/runtime/handles.inline.hpp
index 669a940eca9..4d3dd527c0d 100644
--- a/src/hotspot/share/runtime/handles.inline.hpp
+++ b/src/hotspot/share/runtime/handles.inline.hpp
@@ -80,7 +80,7 @@ inline void HandleMark::push() {
// This is intentionally a NOP. pop_and_restore will reset
// values to the HandleMark further down the stack, typically
// in JavaCalls::call_helper.
- debug_only(_area->_handle_mark_nesting++);
+ DEBUG_ONLY(_area->_handle_mark_nesting++);
}
inline void HandleMark::pop_and_restore() {
@@ -95,7 +95,7 @@ inline void HandleMark::pop_and_restore() {
_area->_chunk = _chunk;
_area->_hwm = _hwm;
_area->_max = _max;
- debug_only(_area->_handle_mark_nesting--);
+ DEBUG_ONLY(_area->_handle_mark_nesting--);
}
inline HandleMarkCleaner::HandleMarkCleaner(Thread* thread) {
diff --git a/src/hotspot/share/runtime/interfaceSupport.inline.hpp b/src/hotspot/share/runtime/interfaceSupport.inline.hpp
index 403ff1d9ea2..c52c2664faa 100644
--- a/src/hotspot/share/runtime/interfaceSupport.inline.hpp
+++ b/src/hotspot/share/runtime/interfaceSupport.inline.hpp
@@ -259,12 +259,12 @@ class VMNativeEntryWrapper {
// in the codecache.
#define VM_LEAF_BASE(result_type, header) \
- debug_only(NoHandleMark __hm;) \
+ DEBUG_ONLY(NoHandleMark __hm;) \
os::verify_stack_alignment(); \
/* begin of body */
#define VM_ENTRY_BASE_FROM_LEAF(result_type, header, thread) \
- debug_only(ResetNoHandleMark __rnhm;) \
+ DEBUG_ONLY(ResetNoHandleMark __rnhm;) \
HandleMarkCleaner __hm(thread); \
JavaThread* THREAD = thread; /* For exception macros. */ \
os::verify_stack_alignment(); \
@@ -286,7 +286,7 @@ class VMNativeEntryWrapper {
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \
ThreadInVMfromJava __tiv(current); \
VM_ENTRY_BASE(result_type, header, current) \
- debug_only(VMEntryWrapper __vew;)
+ DEBUG_ONLY(VMEntryWrapper __vew;)
// JRT_LEAF currently can be called from either _thread_in_Java or
// _thread_in_native mode.
@@ -305,7 +305,7 @@ class VMNativeEntryWrapper {
#define JRT_LEAF(result_type, header) \
result_type header { \
VM_LEAF_BASE(result_type, header) \
- debug_only(NoSafepointVerifier __nsv;)
+ DEBUG_ONLY(NoSafepointVerifier __nsv;)
#define JRT_ENTRY_NO_ASYNC(result_type, header) \
@@ -314,7 +314,7 @@ class VMNativeEntryWrapper {
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, current)); \
ThreadInVMfromJava __tiv(current, false /* check asyncs */); \
VM_ENTRY_BASE(result_type, header, current) \
- debug_only(VMEntryWrapper __vew;)
+ DEBUG_ONLY(VMEntryWrapper __vew;)
// Same as JRT Entry but allows for return value after the safepoint
// to get back into Java from the VM
@@ -329,14 +329,14 @@ class VMNativeEntryWrapper {
assert(current == JavaThread::current(), "Must be"); \
ThreadInVMfromJava __tiv(current); \
JavaThread* THREAD = current; /* For exception macros. */ \
- debug_only(VMEntryWrapper __vew;)
+ DEBUG_ONLY(VMEntryWrapper __vew;)
#define JRT_BLOCK_NO_ASYNC \
{ \
assert(current == JavaThread::current(), "Must be"); \
ThreadInVMfromJava __tiv(current, false /* check asyncs */); \
JavaThread* THREAD = current; /* For exception macros. */ \
- debug_only(VMEntryWrapper __vew;)
+ DEBUG_ONLY(VMEntryWrapper __vew;)
#define JRT_BLOCK_END }
@@ -360,7 +360,7 @@ extern "C" { \
assert(thread == Thread::current(), "JNIEnv is only valid in same thread"); \
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \
ThreadInVMfromNative __tiv(thread); \
- debug_only(VMNativeEntryWrapper __vew;) \
+ DEBUG_ONLY(VMNativeEntryWrapper __vew;) \
VM_ENTRY_BASE(result_type, header, thread)
@@ -385,7 +385,7 @@ extern "C" { \
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \
ThreadInVMfromNative __tiv(thread); \
- debug_only(VMNativeEntryWrapper __vew;) \
+ DEBUG_ONLY(VMNativeEntryWrapper __vew;) \
VM_ENTRY_BASE(result_type, header, thread)
@@ -395,7 +395,7 @@ extern "C" { \
JavaThread* thread = JavaThread::current(); \
MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \
ThreadInVMfromNative __tiv(thread); \
- debug_only(VMNativeEntryWrapper __vew;) \
+ DEBUG_ONLY(VMNativeEntryWrapper __vew;) \
VM_ENTRY_BASE(result_type, header, thread)
diff --git a/src/hotspot/share/runtime/javaCalls.cpp b/src/hotspot/share/runtime/javaCalls.cpp
index 012cea19bb0..04bd0871073 100644
--- a/src/hotspot/share/runtime/javaCalls.cpp
+++ b/src/hotspot/share/runtime/javaCalls.cpp
@@ -91,7 +91,7 @@ JavaCallWrapper::JavaCallWrapper(const methodHandle& callee_method, Handle recei
_anchor.copy(_thread->frame_anchor());
_thread->frame_anchor()->clear();
- debug_only(_thread->inc_java_call_counter());
+ DEBUG_ONLY(_thread->inc_java_call_counter());
_thread->set_active_handles(new_handles); // install new handle block and reset Java frame linkage
MACOS_AARCH64_ONLY(_thread->enable_wx(WXExec));
@@ -109,7 +109,7 @@ JavaCallWrapper::~JavaCallWrapper() {
_thread->frame_anchor()->zap();
- debug_only(_thread->dec_java_call_counter());
+ DEBUG_ONLY(_thread->dec_java_call_counter());
// Old thread-local info. has been restored. We are not back in the VM.
ThreadStateTransition::transition_from_java(_thread, _thread_in_vm);
diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp
index e4f377a1217..8a6da52d762 100644
--- a/src/hotspot/share/runtime/javaThread.cpp
+++ b/src/hotspot/share/runtime/javaThread.cpp
@@ -553,7 +553,7 @@ void JavaThread::interrupt() {
// All callers should have 'this' thread protected by a
// ThreadsListHandle so that it cannot terminate and deallocate
// itself.
- debug_only(check_for_dangling_thread_pointer(this);)
+ DEBUG_ONLY(check_for_dangling_thread_pointer(this);)
// For Windows _interrupt_event
WINDOWS_ONLY(osthread()->set_interrupted(true);)
@@ -569,7 +569,7 @@ void JavaThread::interrupt() {
}
bool JavaThread::is_interrupted(bool clear_interrupted) {
- debug_only(check_for_dangling_thread_pointer(this);)
+ DEBUG_ONLY(check_for_dangling_thread_pointer(this);)
if (_threadObj.peek() == nullptr) {
// If there is no j.l.Thread then it is impossible to have
diff --git a/src/hotspot/share/runtime/jfieldIDWorkaround.hpp b/src/hotspot/share/runtime/jfieldIDWorkaround.hpp
index e44fb064813..68db2e36d45 100644
--- a/src/hotspot/share/runtime/jfieldIDWorkaround.hpp
+++ b/src/hotspot/share/runtime/jfieldIDWorkaround.hpp
@@ -157,7 +157,7 @@ class jfieldIDWorkaround: AllStatic {
static jfieldID to_jfieldID(InstanceKlass* k, int offset, bool is_static) {
if (is_static) {
JNIid *id = k->jni_id_for(offset);
- debug_only(id->set_is_static_field_id());
+ DEBUG_ONLY(id->set_is_static_field_id());
return jfieldIDWorkaround::to_static_jfieldID(id);
} else {
return jfieldIDWorkaround::to_instance_jfieldID(k, offset);
diff --git a/src/hotspot/share/runtime/jniHandles.cpp b/src/hotspot/share/runtime/jniHandles.cpp
index b4fc32947dd..e7564467a81 100644
--- a/src/hotspot/share/runtime/jniHandles.cpp
+++ b/src/hotspot/share/runtime/jniHandles.cpp
@@ -342,9 +342,9 @@ JNIHandleBlock* JNIHandleBlock::allocate_block(JavaThread* thread, AllocFailType
block->_next = nullptr;
block->_pop_frame_link = nullptr;
// _last, _free_list & _allocate_before_rebuild initialized in allocate_handle
- debug_only(block->_last = nullptr);
- debug_only(block->_free_list = nullptr);
- debug_only(block->_allocate_before_rebuild = -1);
+ DEBUG_ONLY(block->_last = nullptr);
+ DEBUG_ONLY(block->_free_list = nullptr);
+ DEBUG_ONLY(block->_allocate_before_rebuild = -1);
return block;
}
diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp
index 48e068714f5..44899225691 100644
--- a/src/hotspot/share/runtime/objectMonitor.cpp
+++ b/src/hotspot/share/runtime/objectMonitor.cpp
@@ -1805,7 +1805,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
// returns because of a timeout of interrupt. Contention is exceptionally rare
// so we use a simple spin-lock instead of a heavier-weight blocking lock.
- Thread::SpinAcquire(&_wait_set_lock, "wait_set - add");
+ Thread::SpinAcquire(&_wait_set_lock);
add_waiter(&node);
Thread::SpinRelease(&_wait_set_lock);
@@ -1864,7 +1864,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
// That is, we fail toward safety.
if (node.TState == ObjectWaiter::TS_WAIT) {
- Thread::SpinAcquire(&_wait_set_lock, "wait_set - unlink");
+ Thread::SpinAcquire(&_wait_set_lock);
if (node.TState == ObjectWaiter::TS_WAIT) {
dequeue_specific_waiter(&node); // unlink from wait_set
assert(!node._notified, "invariant");
@@ -1980,7 +1980,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) {
bool ObjectMonitor::notify_internal(JavaThread* current) {
bool did_notify = false;
- Thread::SpinAcquire(&_wait_set_lock, "wait_set - notify");
+ Thread::SpinAcquire(&_wait_set_lock);
ObjectWaiter* iterator = dequeue_waiter();
if (iterator != nullptr) {
guarantee(iterator->TState == ObjectWaiter::TS_WAIT, "invariant");
@@ -2120,7 +2120,7 @@ void ObjectMonitor::vthread_wait(JavaThread* current, jlong millis) {
// returns because of a timeout or interrupt. Contention is exceptionally rare
// so we use a simple spin-lock instead of a heavier-weight blocking lock.
- Thread::SpinAcquire(&_wait_set_lock, "wait_set - add");
+ Thread::SpinAcquire(&_wait_set_lock);
add_waiter(node);
Thread::SpinRelease(&_wait_set_lock);
@@ -2143,7 +2143,7 @@ bool ObjectMonitor::vthread_wait_reenter(JavaThread* current, ObjectWaiter* node
// need to check if we were interrupted or the wait timed-out, and
// in that case remove ourselves from the _wait_set queue.
if (node->TState == ObjectWaiter::TS_WAIT) {
- Thread::SpinAcquire(&_wait_set_lock, "wait_set - unlink");
+ Thread::SpinAcquire(&_wait_set_lock);
if (node->TState == ObjectWaiter::TS_WAIT) {
dequeue_specific_waiter(node); // unlink from wait_set
assert(!node->_notified, "invariant");
diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp
index 67b25be8eb9..8e85c0a8c02 100644
--- a/src/hotspot/share/runtime/os.cpp
+++ b/src/hotspot/share/runtime/os.cpp
@@ -243,7 +243,7 @@ char* os::iso8601_time(jlong milliseconds_since_19700101, char* buffer, size_t b
}
OSReturn os::set_priority(Thread* thread, ThreadPriority p) {
- debug_only(Thread::check_for_dangling_thread_pointer(thread);)
+ DEBUG_ONLY(Thread::check_for_dangling_thread_pointer(thread);)
if ((p >= MinPriority && p <= MaxPriority) ||
(p == CriticalPriority && thread->is_ConcurrentGC_thread())) {
@@ -598,7 +598,7 @@ char *os::strdup(const char *str, MemTag mem_tag) {
size_t size = strlen(str);
char *dup_str = (char *)malloc(size + 1, mem_tag);
if (dup_str == nullptr) return nullptr;
- strcpy(dup_str, str);
+ memcpy(dup_str, str, size + 1);
return dup_str;
}
@@ -1168,7 +1168,7 @@ void os::print_cpu_info(outputStream* st, char* buf, size_t buflen) {
// We access the raw value here because the assert in the accessor will
// fail if the crash occurs before initialization of this value.
st->print(" (initial active %d)", _initial_active_processor_count);
- st->print(" %s", VM_Version::features_string());
+ st->print(" %s", VM_Version::cpu_info_string());
st->cr();
pd_print_cpu_info(st, buf, buflen);
}
@@ -1968,7 +1968,7 @@ bool os::create_stack_guard_pages(char* addr, size_t bytes) {
return os::pd_create_stack_guard_pages(addr, bytes);
}
-char* os::reserve_memory(size_t bytes, bool executable, MemTag mem_tag) {
+char* os::reserve_memory(size_t bytes, MemTag mem_tag, bool executable) {
char* result = pd_reserve_memory(bytes, executable);
if (result != nullptr) {
MemTracker::record_virtual_memory_reserve(result, bytes, CALLER_PC, mem_tag);
@@ -1979,7 +1979,7 @@ char* os::reserve_memory(size_t bytes, bool executable, MemTag mem_tag) {
return result;
}
-char* os::attempt_reserve_memory_at(char* addr, size_t bytes, bool executable, MemTag mem_tag) {
+char* os::attempt_reserve_memory_at(char* addr, size_t bytes, MemTag mem_tag, bool executable) {
char* result = SimulateFullAddressSpace ? nullptr : pd_attempt_reserve_memory_at(addr, bytes, executable);
if (result != nullptr) {
MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC, mem_tag);
@@ -2185,7 +2185,7 @@ char* os::attempt_reserve_memory_between(char* min, char* max, size_t bytes, siz
assert(is_aligned(result, alignment), "alignment invalid (" ERRFMT ")", ERRFMTARGS);
log_trace(os, map)(ERRFMT, ERRFMTARGS);
log_debug(os, map)("successfully attached at " PTR_FORMAT, p2i(result));
- MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
+ MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC, mtNone);
} else {
log_debug(os, map)("failed to attach anywhere in [" PTR_FORMAT "-" PTR_FORMAT ")", p2i(min), p2i(max));
}
@@ -2362,8 +2362,8 @@ char* os::attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc,
}
char* os::map_memory(int fd, const char* file_name, size_t file_offset,
- char *addr, size_t bytes, bool read_only,
- bool allow_exec, MemTag mem_tag) {
+ char *addr, size_t bytes, MemTag mem_tag,
+ bool read_only, bool allow_exec) {
char* result = pd_map_memory(fd, file_name, file_offset, addr, bytes, read_only, allow_exec);
if (result != nullptr) {
MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC, mem_tag);
@@ -2401,7 +2401,7 @@ char* os::reserve_memory_special(size_t size, size_t alignment, size_t page_size
char* result = pd_reserve_memory_special(size, alignment, page_size, addr, executable);
if (result != nullptr) {
// The memory is committed
- MemTracker::record_virtual_memory_reserve_and_commit((address)result, size, CALLER_PC);
+ MemTracker::record_virtual_memory_reserve_and_commit((address)result, size, CALLER_PC, mtNone);
log_debug(os, map)("Reserved and committed " RANGEFMT, RANGEFMTARGS(result, size));
} else {
log_info(os, map)("Reserve and commit failed (%zu bytes)", size);
diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp
index 16a74cd7ea9..dde80806912 100644
--- a/src/hotspot/share/runtime/os.hpp
+++ b/src/hotspot/share/runtime/os.hpp
@@ -457,14 +457,14 @@ class os: AllStatic {
inline static size_t cds_core_region_alignment();
// Reserves virtual memory.
- static char* reserve_memory(size_t bytes, bool executable = false, MemTag mem_tag = mtNone);
+ static char* reserve_memory(size_t bytes, MemTag mem_tag, bool executable = false);
// Reserves virtual memory that starts at an address that is aligned to 'alignment'.
- static char* reserve_memory_aligned(size_t size, size_t alignment, bool executable = false);
+ static char* reserve_memory_aligned(size_t size, size_t alignment, MemTag mem_tag, bool executable = false);
// Attempts to reserve the virtual memory at [addr, addr + bytes).
// Does not overwrite existing mappings.
- static char* attempt_reserve_memory_at(char* addr, size_t bytes, bool executable = false, MemTag mem_tag = mtNone);
+ static char* attempt_reserve_memory_at(char* addr, size_t bytes, MemTag mem_tag, bool executable = false);
// Given an address range [min, max), attempts to reserve memory within this area, with the given alignment.
// If randomize is true, the location will be randomized.
@@ -516,16 +516,16 @@ class os: AllStatic {
static int create_file_for_heap(const char* dir);
// Map memory to the file referred by fd. This function is slightly different from map_memory()
// and is added to be used for implementation of -XX:AllocateHeapAt
- static char* map_memory_to_file(size_t size, int fd, MemTag mem_tag = mtNone);
- static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag = mtNone);
+ static char* map_memory_to_file(size_t size, int fd, MemTag mem_tag);
+ static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag);
static char* map_memory_to_file(char* base, size_t size, int fd);
- static char* attempt_map_memory_to_file_at(char* base, size_t size, int fd, MemTag mem_tag = mtNone);
+ static char* attempt_map_memory_to_file_at(char* base, size_t size, int fd, MemTag mem_tag);
// Replace existing reserved memory with file mapping
static char* replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd);
static char* map_memory(int fd, const char* file_name, size_t file_offset,
- char *addr, size_t bytes, bool read_only = false,
- bool allow_exec = false, MemTag mem_tag = mtNone);
+ char *addr, size_t bytes, MemTag mem_tag, bool read_only = false,
+ bool allow_exec = false);
static bool unmap_memory(char *addr, size_t bytes);
static void disclaim_memory(char *addr, size_t bytes);
static void realign_memory(char *addr, size_t bytes, size_t alignment_hint);
diff --git a/src/hotspot/share/runtime/park.cpp b/src/hotspot/share/runtime/park.cpp
index a5a67686f2c..37dfe6fcc3d 100644
--- a/src/hotspot/share/runtime/park.cpp
+++ b/src/hotspot/share/runtime/park.cpp
@@ -60,7 +60,7 @@ ParkEvent * ParkEvent::Allocate (Thread * t) {
// Using a spin lock since we are part of the mutex impl.
// 8028280: using concurrent free list without memory management can leak
// pretty badly it turns out.
- Thread::SpinAcquire(&ListLock, "ParkEventFreeListAllocate");
+ Thread::SpinAcquire(&ListLock);
{
ev = FreeList;
if (ev != nullptr) {
@@ -88,7 +88,7 @@ void ParkEvent::Release (ParkEvent * ev) {
ev->AssociatedWith = nullptr ;
// Note that if we didn't have the TSM/immortal constraint, then
// when reattaching we could trim the list.
- Thread::SpinAcquire(&ListLock, "ParkEventFreeListRelease");
+ Thread::SpinAcquire(&ListLock);
{
ev->FreeNext = FreeList;
FreeList = ev;
diff --git a/src/hotspot/share/runtime/park.hpp b/src/hotspot/share/runtime/park.hpp
index 6d8f67edb9b..f353ce34b74 100644
--- a/src/hotspot/share/runtime/park.hpp
+++ b/src/hotspot/share/runtime/park.hpp
@@ -117,10 +117,6 @@ class ParkEvent : public PlatformEvent {
// Current association
Thread * AssociatedWith ;
- public:
- volatile int TState ;
- volatile int Notified ; // for native monitor construct
-
private:
static ParkEvent * volatile FreeList ;
static volatile int ListLock ;
@@ -137,8 +133,6 @@ class ParkEvent : public PlatformEvent {
ParkEvent() : PlatformEvent() {
AssociatedWith = nullptr ;
FreeNext = nullptr ;
- TState = 0 ;
- Notified = 0 ;
}
// We use placement-new to force ParkEvent instances to be
diff --git a/src/hotspot/share/runtime/safepointMechanism.cpp b/src/hotspot/share/runtime/safepointMechanism.cpp
index 51038d764bb..71224bbff4c 100644
--- a/src/hotspot/share/runtime/safepointMechanism.cpp
+++ b/src/hotspot/share/runtime/safepointMechanism.cpp
@@ -57,7 +57,7 @@ void SafepointMechanism::default_initialize() {
// Polling page
const size_t page_size = os::vm_page_size();
const size_t allocation_size = 2 * page_size;
- char* polling_page = os::reserve_memory(allocation_size, !ExecMem, mtSafepoint);
+ char* polling_page = os::reserve_memory(allocation_size, mtSafepoint);
os::commit_memory_or_exit(polling_page, allocation_size, !ExecMem, "Unable to commit Safepoint polling page");
char* bad_page = polling_page;
diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp
index b1b1f1d6056..358434938f2 100644
--- a/src/hotspot/share/runtime/stubRoutines.cpp
+++ b/src/hotspot/share/runtime/stubRoutines.cpp
@@ -101,8 +101,6 @@ jint StubRoutines::_verify_oop_count = 0;
address StubRoutines::_string_indexof_array[4] = { nullptr };
-address StubRoutines::_vector_f_math[VectorSupport::NUM_VEC_SIZES][VectorSupport::NUM_VECTOR_OP_MATH] = {{nullptr}, {nullptr}};
-address StubRoutines::_vector_d_math[VectorSupport::NUM_VEC_SIZES][VectorSupport::NUM_VECTOR_OP_MATH] = {{nullptr}, {nullptr}};
const char* StubRoutines::get_blob_name(StubGenBlobId id) {
assert(0 <= id && id < StubGenBlobId::NUM_BLOBIDS, "invalid blob id");
diff --git a/src/hotspot/share/runtime/stubRoutines.hpp b/src/hotspot/share/runtime/stubRoutines.hpp
index 3189415a6c5..7548a97ced8 100644
--- a/src/hotspot/share/runtime/stubRoutines.hpp
+++ b/src/hotspot/share/runtime/stubRoutines.hpp
@@ -305,10 +305,6 @@ public:
/* special case: stub employs array of entries */
- // Vector Math Routines
- static address _vector_f_math[VectorSupport::NUM_VEC_SIZES][VectorSupport::NUM_VECTOR_OP_MATH];
- static address _vector_d_math[VectorSupport::NUM_VEC_SIZES][VectorSupport::NUM_VECTOR_OP_MATH];
-
static bool is_stub_code(address addr) { return contains(addr); }
// generate code to implement method contains
diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp
index a42576b562d..400d69ad510 100644
--- a/src/hotspot/share/runtime/thread.cpp
+++ b/src/hotspot/share/runtime/thread.cpp
@@ -92,7 +92,7 @@ Thread::Thread(MemTag mem_tag) {
new HandleMark(this);
// plain initialization
- debug_only(_owned_locks = nullptr;)
+ DEBUG_ONLY(_owned_locks = nullptr;)
NOT_PRODUCT(_skip_gcalot = false;)
_jvmti_env_iteration_count = 0;
set_allocated_bytes(0);
@@ -379,7 +379,7 @@ bool Thread::is_JavaThread_protected_by_TLH(const JavaThread* target) {
}
void Thread::set_priority(Thread* thread, ThreadPriority priority) {
- debug_only(check_for_dangling_thread_pointer(thread);)
+ DEBUG_ONLY(check_for_dangling_thread_pointer(thread);)
// Can return an error!
(void)os::set_priority(thread, priority);
}
@@ -488,7 +488,7 @@ void Thread::print_on(outputStream* st, bool print_extended_info) const {
}
ThreadsSMRSupport::print_info_on(this, st);
st->print(" ");
- debug_only(if (WizardMode) print_owned_locks_on(st);)
+ DEBUG_ONLY(if (WizardMode) print_owned_locks_on(st);)
}
void Thread::print() const { print_on(tty); }
@@ -562,7 +562,7 @@ bool Thread::set_as_starting_thread(JavaThread* jt) {
// short-duration critical sections where we're concerned
// about native mutex_t or HotSpot Mutex:: latency.
-void Thread::SpinAcquire(volatile int * adr, const char * LockName) {
+void Thread::SpinAcquire(volatile int * adr) {
if (Atomic::cmpxchg(adr, 0, 1) == 0) {
return; // normal fast-path return
}
diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp
index d0c0e4d5f73..81307c4acab 100644
--- a/src/hotspot/share/runtime/thread.hpp
+++ b/src/hotspot/share/runtime/thread.hpp
@@ -605,7 +605,7 @@ protected:
// Low-level leaf-lock primitives used to implement synchronization.
// Not for general synchronization use.
- static void SpinAcquire(volatile int * Lock, const char * Name);
+ static void SpinAcquire(volatile int * Lock);
static void SpinRelease(volatile int * Lock);
#if defined(__APPLE__) && defined(AARCH64)
diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp
index f865380fdb7..77fae3becb5 100644
--- a/src/hotspot/share/runtime/vmStructs.cpp
+++ b/src/hotspot/share/runtime/vmStructs.cpp
@@ -702,6 +702,7 @@
static_field(Abstract_VM_Version, _s_internal_vm_info_string, const char*) \
static_field(Abstract_VM_Version, _features, uint64_t) \
static_field(Abstract_VM_Version, _features_string, const char*) \
+ static_field(Abstract_VM_Version, _cpu_info_string, const char*) \
static_field(Abstract_VM_Version, _vm_major_version, int) \
static_field(Abstract_VM_Version, _vm_minor_version, int) \
static_field(Abstract_VM_Version, _vm_security_version, int) \
diff --git a/src/hotspot/share/services/heapDumper.cpp b/src/hotspot/share/services/heapDumper.cpp
index 7a2c8d52969..a042a390925 100644
--- a/src/hotspot/share/services/heapDumper.cpp
+++ b/src/hotspot/share/services/heapDumper.cpp
@@ -455,7 +455,7 @@ class AbstractDumpWriter : public CHeapObj {
void AbstractDumpWriter::write_fast(const void* s, size_t len) {
assert(!_in_dump_segment || (_sub_record_left >= len), "sub-record too large");
assert(buffer_size() - position() >= len, "Must fit");
- debug_only(_sub_record_left -= len);
+ DEBUG_ONLY(_sub_record_left -= len);
memcpy(buffer() + position(), s, len);
set_position(position() + len);
}
@@ -467,7 +467,7 @@ bool AbstractDumpWriter::can_write_fast(size_t len) {
// write raw bytes
void AbstractDumpWriter::write_raw(const void* s, size_t len) {
assert(!_in_dump_segment || (_sub_record_left >= len), "sub-record too large");
- debug_only(_sub_record_left -= len);
+ DEBUG_ONLY(_sub_record_left -= len);
// flush buffer to make room.
while (len > buffer_size() - position()) {
@@ -591,8 +591,8 @@ void AbstractDumpWriter::start_sub_record(u1 tag, u4 len) {
return;
}
- debug_only(_sub_record_left = len);
- debug_only(_sub_record_ended = false);
+ DEBUG_ONLY(_sub_record_left = len);
+ DEBUG_ONLY(_sub_record_ended = false);
write_u1(tag);
}
@@ -601,7 +601,7 @@ void AbstractDumpWriter::end_sub_record() {
assert(_in_dump_segment, "must be in dump segment");
assert(_sub_record_left == 0, "sub-record not written completely");
assert(!_sub_record_ended, "Must not have ended yet");
- debug_only(_sub_record_ended = true);
+ DEBUG_ONLY(_sub_record_ended = true);
}
// Supports I/O operations for a dump
diff --git a/src/hotspot/share/services/threadService.cpp b/src/hotspot/share/services/threadService.cpp
index 89ee69242c9..d320e17fafb 100644
--- a/src/hotspot/share/services/threadService.cpp
+++ b/src/hotspot/share/services/threadService.cpp
@@ -228,7 +228,7 @@ void ThreadService::current_thread_exiting(JavaThread* jt, bool daemon) {
// FIXME: JVMTI should call this function
Handle ThreadService::get_current_contended_monitor(JavaThread* thread) {
assert(thread != nullptr, "should be non-null");
- debug_only(Thread::check_for_dangling_thread_pointer(thread);)
+ DEBUG_ONLY(Thread::check_for_dangling_thread_pointer(thread);)
// This function can be called on a target JavaThread that is not
// the caller and we are not at a safepoint. So it is possible for
diff --git a/src/hotspot/share/utilities/compilerWarnings.hpp b/src/hotspot/share/utilities/compilerWarnings.hpp
index e2c9fc289f6..bf5ca5b4893 100644
--- a/src/hotspot/share/utilities/compilerWarnings.hpp
+++ b/src/hotspot/share/utilities/compilerWarnings.hpp
@@ -62,9 +62,6 @@
#ifndef PRAGMA_FORMAT_NONLITERAL_IGNORED
#define PRAGMA_FORMAT_NONLITERAL_IGNORED
#endif
-#ifndef PRAGMA_FORMAT_IGNORED
-#define PRAGMA_FORMAT_IGNORED
-#endif
#ifndef PRAGMA_STRINGOP_TRUNCATION_IGNORED
#define PRAGMA_STRINGOP_TRUNCATION_IGNORED
diff --git a/src/hotspot/share/utilities/compilerWarnings_gcc.hpp b/src/hotspot/share/utilities/compilerWarnings_gcc.hpp
index 863cc512cca..c10650598cd 100644
--- a/src/hotspot/share/utilities/compilerWarnings_gcc.hpp
+++ b/src/hotspot/share/utilities/compilerWarnings_gcc.hpp
@@ -51,8 +51,6 @@
PRAGMA_DISABLE_GCC_WARNING("-Wformat-nonliteral") \
PRAGMA_DISABLE_GCC_WARNING("-Wformat-security")
-#define PRAGMA_FORMAT_IGNORED PRAGMA_DISABLE_GCC_WARNING("-Wformat")
-
// Disable -Wstringop-truncation which is introduced in GCC 8.
// https://gcc.gnu.org/gcc-8/changes.html
#if !defined(__clang_major__) && (__GNUC__ >= 8)
diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp
index 9413f1f72d7..abe3d6757b5 100644
--- a/src/hotspot/share/utilities/debug.cpp
+++ b/src/hotspot/share/utilities/debug.cpp
@@ -712,7 +712,7 @@ struct TestMultipleStaticAssertFormsInClassScope {
// Support for showing register content on asserts/guarantees.
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
void initialize_assert_poison() {
- char* page = os::reserve_memory(os::vm_page_size(), !ExecMem, mtInternal);
+ char* page = os::reserve_memory(os::vm_page_size(), mtInternal);
if (page) {
if (os::commit_memory(page, os::vm_page_size(), !ExecMem) &&
os::protect_memory(page, os::vm_page_size(), os::MEM_PROT_NONE)) {
diff --git a/src/hotspot/share/utilities/exceptions.cpp b/src/hotspot/share/utilities/exceptions.cpp
index 724797eb9f3..a3ad480f50c 100644
--- a/src/hotspot/share/utilities/exceptions.cpp
+++ b/src/hotspot/share/utilities/exceptions.cpp
@@ -540,6 +540,7 @@ inline void ExceptionMark::check_no_pending_exception() {
if (_thread->has_pending_exception()) {
oop exception = _thread->pending_exception();
_thread->clear_pending_exception(); // Needed to avoid infinite recursion
+ ResourceMark rm;
exception->print();
fatal("ExceptionMark constructor expects no pending exceptions");
}
@@ -551,6 +552,7 @@ ExceptionMark::~ExceptionMark() {
Handle exception(_thread, _thread->pending_exception());
_thread->clear_pending_exception(); // Needed to avoid infinite recursion
if (is_init_completed()) {
+ ResourceMark rm;
exception->print();
fatal("ExceptionMark destructor expects no pending exceptions");
} else {
diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp
index 085939b0131..cc5f3ebb291 100644
--- a/src/hotspot/share/utilities/globalDefinitions.hpp
+++ b/src/hotspot/share/utilities/globalDefinitions.hpp
@@ -269,6 +269,9 @@ inline jdouble jdouble_cast(jlong x);
const jlong min_jlong = CONST64(0x8000000000000000);
const jlong max_jlong = CONST64(0x7fffffffffffffff);
+// for timer info max values which include all bits, 0xffffffffffffffff
+const jlong all_bits_jlong = ~jlong(0);
+
//-------------------------------------------
// Constant for jdouble
const jlong min_jlongDouble = CONST64(0x0000000000000001);
diff --git a/src/hotspot/share/utilities/growableArray.hpp b/src/hotspot/share/utilities/growableArray.hpp
index 31e797fc192..86b7ed5f917 100644
--- a/src/hotspot/share/utilities/growableArray.hpp
+++ b/src/hotspot/share/utilities/growableArray.hpp
@@ -622,7 +622,7 @@ class GrowableArrayMetadata {
uintptr_t _bits;
// resource area nesting at creation
- debug_only(GrowableArrayNestingCheck _nesting_check;)
+ DEBUG_ONLY(GrowableArrayNestingCheck _nesting_check;)
// Resource allocation
static uintptr_t bits() {
@@ -645,19 +645,19 @@ public:
// Resource allocation
GrowableArrayMetadata() :
_bits(bits())
- debug_only(COMMA _nesting_check(true)) {
+ DEBUG_ONLY(COMMA _nesting_check(true)) {
}
// Arena allocation
GrowableArrayMetadata(Arena* arena) :
_bits(bits(arena))
- debug_only(COMMA _nesting_check(arena)) {
+ DEBUG_ONLY(COMMA _nesting_check(arena)) {
}
// CHeap allocation
GrowableArrayMetadata(MemTag mem_tag) :
_bits(bits(mem_tag))
- debug_only(COMMA _nesting_check(false)) {
+ DEBUG_ONLY(COMMA _nesting_check(false)) {
}
#ifdef ASSERT
@@ -725,7 +725,7 @@ class GrowableArray : public GrowableArrayWithAllocator> {
GrowableArrayMetadata _metadata;
- void init_checks() const { debug_only(_metadata.init_checks(this);) }
+ void init_checks() const { DEBUG_ONLY(_metadata.init_checks(this);) }
// Where are we going to allocate memory?
bool on_C_heap() const { return _metadata.on_C_heap(); }
@@ -734,7 +734,7 @@ class GrowableArray : public GrowableArrayWithAllocator> {
E* allocate() {
if (on_resource_area()) {
- debug_only(_metadata.on_resource_area_alloc_check());
+ DEBUG_ONLY(_metadata.on_resource_area_alloc_check());
return allocate(this->_capacity);
}
@@ -743,7 +743,7 @@ class GrowableArray : public GrowableArrayWithAllocator> {
}
assert(on_arena(), "Sanity");
- debug_only(_metadata.on_arena_alloc_check());
+ DEBUG_ONLY(_metadata.on_arena_alloc_check());
return allocate(this->_capacity, _metadata.arena());
}
diff --git a/src/hotspot/share/utilities/macros.hpp b/src/hotspot/share/utilities/macros.hpp
index 5c3cfaa0dd5..a5caf316aa3 100644
--- a/src/hotspot/share/utilities/macros.hpp
+++ b/src/hotspot/share/utilities/macros.hpp
@@ -377,13 +377,10 @@
#define DEBUG_ONLY(code) code
#define NOT_DEBUG(code)
#define NOT_DEBUG_RETURN /*next token must be ;*/
-// Historical.
-#define debug_only(code) code
#else // ASSERT
#define DEBUG_ONLY(code)
#define NOT_DEBUG(code) code
#define NOT_DEBUG_RETURN {}
-#define debug_only(code)
#endif // ASSERT
#ifdef _LP64
diff --git a/src/java.base/aix/native/libsyslookup/syslookup.c b/src/java.base/aix/native/libsyslookup/syslookup.c
index 66bd50e01a0..95aff2d4300 100644
--- a/src/java.base/aix/native/libsyslookup/syslookup.c
+++ b/src/java.base/aix/native/libsyslookup/syslookup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, IBM Corp.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -29,6 +29,10 @@
#include
#include
+#include "jni_util.h"
+
+DEF_STATIC_JNI_OnLoad
+
// Addresses of functions to be referenced using static linking.
void* funcs[] = {
//string.h
diff --git a/src/java.base/share/classes/java/io/FilePermission.java b/src/java.base/share/classes/java/io/FilePermission.java
index aa6f11e00ee..883f0410b6d 100644
--- a/src/java.base/share/classes/java/io/FilePermission.java
+++ b/src/java.base/share/classes/java/io/FilePermission.java
@@ -34,11 +34,9 @@ import java.util.StringJoiner;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
-import jdk.internal.access.JavaIOFilePermissionAccess;
-import jdk.internal.access.SharedSecrets;
import sun.nio.fs.DefaultFileSystemProvider;
-import sun.security.util.FilePermCompat;
import sun.security.util.SecurityConstants;
+import sun.security.util.SecurityProperties;
/**
* This class represents access to a file or directory. A FilePermission consists
@@ -155,6 +153,26 @@ public final class FilePermission extends Permission implements Serializable {
private static final char RECURSIVE_CHAR = '-';
private static final char WILD_CHAR = '*';
+ /**
+ * New behavior? Keep compatibility?
+ * The new behavior does not use the canonical path normalization
+ */
+ private static final boolean nb = initNb();
+
+ // Initialize the nb flag from the System property jdk.io.permissionsUseCanonicalPath.
+ private static boolean initNb() {
+ String flag = SecurityProperties.getOverridableProperty(
+ "jdk.io.permissionsUseCanonicalPath");
+ return switch (flag) {
+ case "true" -> false; // compatibility mode to canonicalize paths
+ case "false" -> true; // do not canonicalize
+ case null -> true; // default, do not canonicalize
+ default ->
+ throw new RuntimeException(
+ "Invalid jdk.io.permissionsUseCanonicalPath: " + flag);
+ };
+ }
+
// public String toString() {
// StringBuilder sb = new StringBuilder();
// sb.append("*** FilePermission on " + getName() + " ***");
@@ -232,51 +250,49 @@ public final class FilePermission extends Permission implements Serializable {
}
}
- static {
- SharedSecrets.setJavaIOFilePermissionAccess(
- /**
- * Creates FilePermission objects with special internals.
- * See {@link FilePermCompat#newPermPlusAltPath(Permission)} and
- * {@link FilePermCompat#newPermUsingAltPath(Permission)}.
- */
- new JavaIOFilePermissionAccess() {
- public FilePermission newPermPlusAltPath(FilePermission input) {
- if (!input.invalid && input.npath2 == null && !input.allFiles) {
- Path npath2 = altPath(input.npath);
- if (npath2 != null) {
- // Please note the name of the new permission is
- // different than the original so that when one is
- // added to a FilePermissionCollection it will not
- // be merged with the original one.
- return new FilePermission(input.getName() + "#plus",
- input,
- input.npath,
- npath2,
- input.mask,
- input.actions);
- }
- }
- return input;
- }
- public FilePermission newPermUsingAltPath(FilePermission input) {
- if (!input.invalid && !input.allFiles) {
- Path npath2 = altPath(input.npath);
- if (npath2 != null) {
- // New name, see above.
- return new FilePermission(input.getName() + "#using",
- input,
- npath2,
- null,
- input.mask,
- input.actions);
- }
- }
- return null;
- }
+ // Construct a new Permission with altPath
+ // Used by test FilePermissionCollectionMerge
+ private FilePermission newPermPlusAltPath() {
+ System.err.println("PlusAlt path: " + this + ", npath: " + npath);
+ if (nb && !invalid && npath2 == null && !allFiles) {
+ Path npath2 = altPath(npath);
+ if (npath2 != null) {
+ // Please note the name of the new permission is
+ // different than the original so that when one is
+ // added to a FilePermissionCollection it will not
+ // be merged with the original one.
+ return new FilePermission(getName() + "#plus",
+ this,
+ npath,
+ npath2,
+ mask,
+ actions);
}
- );
+ }
+ return this;
}
+ // Construct a new Permission adding altPath
+ // Used by test FilePermissionCollectionMerge
+ private FilePermission newPermUsingAltPath() {
+ System.err.println("Alt path: " + this + ", npath: " + npath);
+ if (!invalid && !allFiles) {
+ Path npath2 = altPath(npath);
+ if (npath2 != null) {
+ // New name, see above.
+ return new FilePermission(getName() + "#using",
+ this,
+ npath2,
+ null,
+ mask,
+ actions);
+ }
+ }
+ return this;
+}
+
+
+
/**
* initialize a FilePermission object. Common to all constructors.
* Also called during de-serialization.
@@ -291,7 +307,7 @@ public final class FilePermission extends Permission implements Serializable {
if (mask == NONE)
throw new IllegalArgumentException("invalid actions mask");
- if (FilePermCompat.nb) {
+ if (nb) {
String name = getName();
if (name == null)
@@ -567,7 +583,7 @@ public final class FilePermission extends Permission implements Serializable {
if (that.allFiles) {
return false;
}
- if (FilePermCompat.nb) {
+ if (nb) {
// Left at least same level of wildness as right
if ((this.recursive && that.recursive) != that.recursive
|| (this.directory && that.directory) != that.directory) {
@@ -766,7 +782,7 @@ public final class FilePermission extends Permission implements Serializable {
if (this.invalid || that.invalid) {
return false;
}
- if (FilePermCompat.nb) {
+ if (nb) {
return (this.mask == that.mask) &&
(this.allFiles == that.allFiles) &&
this.npath.equals(that.npath) &&
@@ -789,7 +805,7 @@ public final class FilePermission extends Permission implements Serializable {
*/
@Override
public int hashCode() {
- if (FilePermCompat.nb) {
+ if (nb) {
return Objects.hash(
mask, allFiles, directory, recursive, npath, npath2, invalid);
} else {
diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
index c2f90e22802..b8d209b8a6e 100644
--- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
+++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@ import jdk.internal.math.DoubleToDecimal;
import jdk.internal.math.FloatToDecimal;
import jdk.internal.util.DecimalDigits;
-import java.io.IOException;
import java.nio.CharBuffer;
import java.util.Arrays;
import java.util.Spliterator;
@@ -360,8 +359,12 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
*/
@Override
public char charAt(int index) {
+ byte coder = this.coder;
+ byte[] value = this.value;
+ // Ensure count is less than or equal to capacity (racy reads and writes can produce inconsistent values)
+ int count = Math.min(this.count, value.length >> coder);
checkIndex(index, count);
- if (isLatin1()) {
+ if (coder == LATIN1) {
return (char)(value[index] & 0xff);
}
return StringUTF16.getChar(value, index);
@@ -420,6 +423,7 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
* of this sequence.
*/
public int codePointBefore(int index) {
+ byte[] value = this.value;
int i = index - 1;
checkIndex(i, count);
if (isLatin1()) {
@@ -1730,7 +1734,7 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
} else {
inflate();
// store c to make sure it has a UTF16 char
- StringUTF16.putChar(this.value, j++, c);
+ StringUTF16.putCharSB(this.value, j++, c);
i++;
StringUTF16.putCharsSB(this.value, j, s, i, end);
return;
@@ -1825,7 +1829,7 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
count = j;
inflate();
// Store c to make sure sb has a UTF16 char
- StringUTF16.putChar(this.value, j++, c);
+ StringUTF16.putCharSB(this.value, j++, c);
count = j;
i++;
StringUTF16.putCharsSB(this.value, j, s, i, end);
diff --git a/src/java.base/share/classes/java/lang/Boolean.java b/src/java.base/share/classes/java/lang/Boolean.java
index aa64d799b66..4c24e98a549 100644
--- a/src/java.base/share/classes/java/lang/Boolean.java
+++ b/src/java.base/share/classes/java/lang/Boolean.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2025, 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
@@ -104,7 +104,7 @@ public final class Boolean implements java.io.Serializable,
* Also consider using the final fields {@link #TRUE} and {@link #FALSE}
* if possible.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Boolean(boolean value) {
this.value = value;
}
@@ -124,7 +124,7 @@ public final class Boolean implements java.io.Serializable,
* {@code boolean} primitive, or use {@link #valueOf(String)}
* to convert a string to a {@code Boolean} object.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Boolean(String s) {
this(parseBoolean(s));
}
diff --git a/src/java.base/share/classes/java/lang/Byte.java b/src/java.base/share/classes/java/lang/Byte.java
index 5835f65366f..accd448a0cd 100644
--- a/src/java.base/share/classes/java/lang/Byte.java
+++ b/src/java.base/share/classes/java/lang/Byte.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2025, 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
@@ -346,7 +346,7 @@ public final class Byte extends Number implements Comparable, Constable {
* {@link #valueOf(byte)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Byte(byte value) {
this.value = value;
}
@@ -369,7 +369,7 @@ public final class Byte extends Number implements Comparable, Constable {
* {@code byte} primitive, or use {@link #valueOf(String)}
* to convert a string to a {@code Byte} object.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Byte(String s) throws NumberFormatException {
this.value = parseByte(s, 10);
}
diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java
index 4347a3bc8aa..a439a90761d 100644
--- a/src/java.base/share/classes/java/lang/Character.java
+++ b/src/java.base/share/classes/java/lang/Character.java
@@ -9232,7 +9232,7 @@ class Character implements java.io.Serializable, Comparable, Constabl
* {@link #valueOf(char)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Character(char value) {
this.value = value;
}
diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java
index d86baaac362..8be5ae8fa15 100644
--- a/src/java.base/share/classes/java/lang/Class.java
+++ b/src/java.base/share/classes/java/lang/Class.java
@@ -1384,10 +1384,8 @@ public final class Class implements java.io.Serializable,
isAnonymousClass() || isArray()) ?
AccessFlag.Location.INNER_CLASS :
AccessFlag.Location.CLASS;
- return AccessFlag.maskToAccessFlags((location == AccessFlag.Location.CLASS) ?
- getClassAccessFlagsRaw() :
- getModifiers(),
- location);
+ return getReflectionFactory().parseAccessFlags((location == AccessFlag.Location.CLASS) ?
+ getClassAccessFlagsRaw() : getModifiers(), location, this);
}
/**
@@ -4125,7 +4123,7 @@ public final class Class implements java.io.Serializable,
* type is returned. If the class is a primitive type then the latest class
* file major version is returned and zero is returned for the minor version.
*/
- private int getClassFileVersion() {
+ int getClassFileVersion() {
Class> c = isArray() ? elementType() : this;
return c.getClassFileVersion0();
}
diff --git a/src/java.base/share/classes/java/lang/ClassLoader.java b/src/java.base/share/classes/java/lang/ClassLoader.java
index b890ba51651..6082bc53297 100644
--- a/src/java.base/share/classes/java/lang/ClassLoader.java
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java
@@ -2565,22 +2565,38 @@ public abstract class ClassLoader {
*/
private boolean trySetObjectField(String name, Object obj) {
Unsafe unsafe = Unsafe.getUnsafe();
- Class> k = ClassLoader.class;
- long offset;
- offset = unsafe.objectFieldOffset(k, name);
+ long offset = unsafe.objectFieldOffset(ClassLoader.class, name);
return unsafe.compareAndSetReference(this, offset, null, obj);
}
+ private void reinitObjectField(String name, Object obj) {
+ Unsafe unsafe = Unsafe.getUnsafe();
+ long offset = unsafe.objectFieldOffset(ClassLoader.class, name);
+
+ // Extra safety: check the types
+ Object current = unsafe.getReference(this, offset);
+ if (current.getClass() != obj.getClass()) {
+ throw new IllegalStateException("Wrong field type");
+ }
+
+ unsafe.putReference(this, offset, obj);
+ }
+
/**
- * Called by the VM, during -Xshare:dump
+ * Called only by the VM, during -Xshare:dump.
+ *
+ * @implNote This is done while the JVM is running in single-threaded mode,
+ * and at the very end of Java bytecode execution. We know that no more classes
+ * will be loaded and none of the fields modified by this method will be used again.
*/
private void resetArchivedStates() {
if (parallelLockMap != null) {
- parallelLockMap.clear();
+ reinitObjectField("parallelLockMap", new ConcurrentHashMap<>());
}
- packages.clear();
- package2certs.clear();
+ reinitObjectField("packages", new ConcurrentHashMap<>());
+ reinitObjectField("package2certs", new ConcurrentHashMap<>());
classes.clear();
+ classes.trimToSize();
classLoaderValueMap = null;
}
}
diff --git a/src/java.base/share/classes/java/lang/Double.java b/src/java.base/share/classes/java/lang/Double.java
index 54be998cac5..5ab6dce080b 100644
--- a/src/java.base/share/classes/java/lang/Double.java
+++ b/src/java.base/share/classes/java/lang/Double.java
@@ -1041,7 +1041,7 @@ public final class Double extends Number
* {@link #valueOf(double)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Double(double value) {
this.value = value;
}
@@ -1062,7 +1062,7 @@ public final class Double extends Number
* {@code double} primitive, or use {@link #valueOf(String)}
* to convert a string to a {@code Double} object.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Double(String s) throws NumberFormatException {
value = parseDouble(s);
}
diff --git a/src/java.base/share/classes/java/lang/Float.java b/src/java.base/share/classes/java/lang/Float.java
index 746d90db81e..4344d9657b4 100644
--- a/src/java.base/share/classes/java/lang/Float.java
+++ b/src/java.base/share/classes/java/lang/Float.java
@@ -668,7 +668,7 @@ public final class Float extends Number
* {@link #valueOf(float)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Float(float value) {
this.value = value;
}
@@ -684,7 +684,7 @@ public final class Float extends Number
* static factory method {@link #valueOf(float)} method as follows:
* {@code Float.valueOf((float)value)}.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Float(double value) {
this.value = (float)value;
}
@@ -705,7 +705,7 @@ public final class Float extends Number
* {@code float} primitive, or use {@link #valueOf(String)}
* to convert a string to a {@code Float} object.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Float(String s) throws NumberFormatException {
value = parseFloat(s);
}
diff --git a/src/java.base/share/classes/java/lang/Integer.java b/src/java.base/share/classes/java/lang/Integer.java
index 99b056ec18a..1350a66b66c 100644
--- a/src/java.base/share/classes/java/lang/Integer.java
+++ b/src/java.base/share/classes/java/lang/Integer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2025, 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
@@ -1024,7 +1024,7 @@ public final class Integer extends Number
* {@link #valueOf(int)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Integer(int value) {
this.value = value;
}
@@ -1046,7 +1046,7 @@ public final class Integer extends Number
* {@code int} primitive, or use {@link #valueOf(String)}
* to convert a string to an {@code Integer} object.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Integer(String s) throws NumberFormatException {
this.value = parseInt(s, 10);
}
diff --git a/src/java.base/share/classes/java/lang/Long.java b/src/java.base/share/classes/java/lang/Long.java
index c401fcd8027..3093f37e99a 100644
--- a/src/java.base/share/classes/java/lang/Long.java
+++ b/src/java.base/share/classes/java/lang/Long.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2025, 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
@@ -1109,7 +1109,7 @@ public final class Long extends Number
* {@link #valueOf(long)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Long(long value) {
this.value = value;
}
@@ -1132,7 +1132,7 @@ public final class Long extends Number
* {@code long} primitive, or use {@link #valueOf(String)}
* to convert a string to a {@code Long} object.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Long(String s) throws NumberFormatException {
this.value = parseLong(s, 10);
}
diff --git a/src/java.base/share/classes/java/lang/Module.java b/src/java.base/share/classes/java/lang/Module.java
index dcc92d012de..065e1ac4620 100644
--- a/src/java.base/share/classes/java/lang/Module.java
+++ b/src/java.base/share/classes/java/lang/Module.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2025, 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
@@ -40,7 +40,6 @@ import java.lang.reflect.AnnotatedElement;
import java.net.URI;
import java.net.URL;
import java.security.CodeSource;
-import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -688,7 +687,6 @@ public final class Module implements AnnotatedElement {
return implIsExportedOrOpen(pn, EVERYONE_MODULE, /*open*/true);
}
-
/**
* Returns {@code true} if this module exports or opens the given package
* to the given module. If the other module is {@code EVERYONE_MODULE} then
@@ -707,12 +705,12 @@ public final class Module implements AnnotatedElement {
if (descriptor.isOpen() || descriptor.isAutomatic())
return descriptor.packages().contains(pn);
- // exported/opened via module declaration/descriptor
- if (isStaticallyExportedOrOpen(pn, other, open))
+ // exported/opened via module declaration/descriptor or CLI options
+ if (isExplicitlyExportedOrOpened(pn, other, open))
return true;
// exported via addExports/addOpens
- if (isReflectivelyExportedOrOpen(pn, other, open))
+ if (isReflectivelyExportedOrOpened(pn, other, open))
return true;
// not exported or open to other
@@ -723,7 +721,7 @@ public final class Module implements AnnotatedElement {
* Returns {@code true} if this module exports or opens a package to
* the given module via its module declaration or CLI options.
*/
- private boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
+ private boolean isExplicitlyExportedOrOpened(String pn, Module other, boolean open) {
// test if package is open to everyone or
Map> openPackages = this.openPackages;
if (openPackages != null && allows(openPackages.get(pn), other)) {
@@ -764,7 +762,7 @@ public final class Module implements AnnotatedElement {
* Returns {@code true} if this module reflectively exports or opens the
* given package to the given module.
*/
- private boolean isReflectivelyExportedOrOpen(String pn, Module other, boolean open) {
+ private boolean isReflectivelyExportedOrOpened(String pn, Module other, boolean open) {
// exported or open to all modules
Map exports = ReflectionData.exports.get(this, EVERYONE_MODULE);
if (exports != null) {
@@ -809,7 +807,7 @@ public final class Module implements AnnotatedElement {
* given package to the given module.
*/
boolean isReflectivelyExported(String pn, Module other) {
- return isReflectivelyExportedOrOpen(pn, other, false);
+ return isReflectivelyExportedOrOpened(pn, other, false);
}
/**
@@ -817,7 +815,7 @@ public final class Module implements AnnotatedElement {
* given package to the given module.
*/
boolean isReflectivelyOpened(String pn, Module other) {
- return isReflectivelyExportedOrOpen(pn, other, true);
+ return isReflectivelyExportedOrOpened(pn, other, true);
}
@@ -1033,50 +1031,38 @@ public final class Module implements AnnotatedElement {
}
}
- // add package name to exports if absent
- Map map = ReflectionData.exports
- .computeIfAbsent(this, other,
- (m1, m2) -> new ConcurrentHashMap<>());
- if (open) {
- map.put(pn, Boolean.TRUE); // may need to promote from FALSE to TRUE
- } else {
- map.putIfAbsent(pn, Boolean.FALSE);
- }
- }
-
- /**
- * Updates a module to open all packages in the given sets to all unnamed
- * modules.
- *
- * @apiNote Used during startup to open packages for illegal access.
- */
- void implAddOpensToAllUnnamed(Set concealedPkgs, Set exportedPkgs) {
- if (jdk.internal.misc.VM.isModuleSystemInited()) {
- throw new IllegalStateException("Module system already initialized");
- }
-
- // replace this module's openPackages map with a new map that opens
- // the packages to all unnamed modules.
- Map> openPackages = this.openPackages;
- if (openPackages == null) {
- openPackages = HashMap.newHashMap(concealedPkgs.size() + exportedPkgs.size());
- } else {
- openPackages = new HashMap<>(openPackages);
- }
- implAddOpensToAllUnnamed(concealedPkgs, openPackages);
- implAddOpensToAllUnnamed(exportedPkgs, openPackages);
- this.openPackages = openPackages;
- }
-
- private void implAddOpensToAllUnnamed(Set pkgs, Map> openPackages) {
- for (String pn : pkgs) {
- Set prev = openPackages.putIfAbsent(pn, ALL_UNNAMED_MODULE_SET);
- if (prev != null) {
- prev.add(ALL_UNNAMED_MODULE);
+ if (VM.isBooted()) {
+ // add package name to ReflectionData.exports if absent
+ Map map = ReflectionData.exports
+ .computeIfAbsent(this, other,
+ (m1, m2) -> new ConcurrentHashMap<>());
+ if (open) {
+ map.put(pn, Boolean.TRUE); // may need to promote from FALSE to TRUE
+ } else {
+ map.putIfAbsent(pn, Boolean.FALSE);
+ }
+ } else {
+ // export/open packages during startup (--add-exports and --add-opens)
+ Map> packageToTargets = (open) ? openPackages : exportedPackages;
+ if (packageToTargets != null) {
+ // copy existing map
+ packageToTargets = new HashMap<>(packageToTargets);
+ packageToTargets.compute(pn, (_, values) -> {
+ var targets = new HashSet();
+ if (values != null) {
+ targets.addAll(values);
+ }
+ targets.add(other);
+ return targets;
+ });
+ } else {
+ packageToTargets = Map.of(pn, Set.of(other));
+ }
+ if (open) {
+ this.openPackages = packageToTargets;
+ } else {
+ this.exportedPackages = packageToTargets;
}
-
- // update VM to export the package
- addExportsToAllUnnamed0(this, pn);
}
}
diff --git a/src/java.base/share/classes/java/lang/Short.java b/src/java.base/share/classes/java/lang/Short.java
index 57e88442b27..f0ae8b28e45 100644
--- a/src/java.base/share/classes/java/lang/Short.java
+++ b/src/java.base/share/classes/java/lang/Short.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2025, 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
@@ -352,7 +352,7 @@ public final class Short extends Number implements Comparable, Constable
* {@link #valueOf(short)} is generally a better choice, as it is
* likely to yield significantly better space and time performance.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Short(short value) {
this.value = value;
}
@@ -375,7 +375,7 @@ public final class Short extends Number implements Comparable, Constable
* {@code short} primitive, or use {@link #valueOf(String)}
* to convert a string to a {@code Short} object.
*/
- @Deprecated(since="9", forRemoval = true)
+ @Deprecated(since="9")
public Short(String s) throws NumberFormatException {
this.value = parseShort(s, 10);
}
diff --git a/src/java.base/share/classes/java/lang/StableValue.java b/src/java.base/share/classes/java/lang/StableValue.java
new file mode 100644
index 00000000000..b12d6f5e921
--- /dev/null
+++ b/src/java.base/share/classes/java/lang/StableValue.java
@@ -0,0 +1,757 @@
+/*
+ * Copyright (c) 2025, 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 java.lang;
+
+import jdk.internal.access.SharedSecrets;
+import jdk.internal.javac.PreviewFeature;
+import jdk.internal.lang.stable.StableEnumFunction;
+import jdk.internal.lang.stable.StableFunction;
+import jdk.internal.lang.stable.StableIntFunction;
+import jdk.internal.lang.stable.StableSupplier;
+import jdk.internal.lang.stable.StableUtil;
+import jdk.internal.lang.stable.StableValueImpl;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.RandomAccess;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.Supplier;
+
+/**
+ * A stable value is a holder of contents that can be set at most once.
+ *
+ * A {@code StableValue} is typically created using the factory method
+ * {@linkplain StableValue#of() {@code StableValue.of()}}. When created this way,
+ * the stable value is unset, which means it holds no contents.
+ * Its contents, of type {@code T}, can be set by calling
+ * {@linkplain #trySet(Object) trySet()}, {@linkplain #setOrThrow(Object) setOrThrow()},
+ * or {@linkplain #orElseSet(Supplier) orElseSet()}. Once set, the contents
+ * can never change and can be retrieved by calling {@linkplain #orElseThrow() orElseThrow()}
+ * , {@linkplain #orElse(Object) orElse()}, or {@linkplain #orElseSet(Supplier) orElseSet()}.
+ *
+ * Consider the following example where a stable value field "{@code logger}" is a
+ * shallowly immutable holder of contents of type {@code Logger} and that is initially
+ * created as unset, which means it holds no contents. Later in the example, the
+ * state of the "{@code logger}" field is checked and if it is still unset,
+ * the contents is set:
+ *
+ * {@snippet lang = java:
+ * public class Component {
+ *
+ * // Creates a new unset stable value with no contents
+ * // @link substring="of" target="#of" :
+ * private final StableValue logger = StableValue.of();
+ *
+ * private Logger getLogger() {
+ * if (!logger.isSet()) {
+ * logger.trySet(Logger.create(Component.class));
+ * }
+ * return logger.orElseThrow();
+ * }
+ *
+ * public void process() {
+ * getLogger().info("Process started");
+ * // ...
+ * }
+ * }
+ *}
+ *
+ * If {@code getLogger()} is called from several threads, several instances of
+ * {@code Logger} might be created. However, the contents can only be set at most once
+ * meaning the first writer wins.
+ *
+ * In order to guarantee that, even under races, only one instance of {@code Logger} is
+ * ever created, the {@linkplain #orElseSet(Supplier) orElseSet()} method can be used
+ * instead, where the contents are lazily computed, and atomically set, via a
+ * {@linkplain Supplier supplier}. In the example below, the supplier is provided in the
+ * form of a lambda expression:
+ *
+ * {@snippet lang = java:
+ * public class Component {
+ *
+ * // Creates a new unset stable value with no contents
+ * // @link substring="of" target="#of" :
+ * private final StableValue logger = StableValue.of();
+ *
+ * private Logger getLogger() {
+ * return logger.orElseSet( () -> Logger.create(Component.class) );
+ * }
+ *
+ * public void process() {
+ * getLogger().info("Process started");
+ * // ...
+ * }
+ * }
+ *}
+ *
+ * The {@code getLogger()} method calls {@code logger.orElseSet()} on the stable value to
+ * retrieve its contents. If the stable value is unset, then {@code orElseSet()}
+ * evaluates the given supplier, and sets the contents to the result; the result is then
+ * returned to the client. In other words, {@code orElseSet()} guarantees that a
+ * stable value's contents is set before it returns.
+ *
+ * Furthermore, {@code orElseSet()} guarantees that out of one or more suppliers provided,
+ * only at most one is ever evaluated, and that one is only ever evaluated once,
+ * even when {@code logger.orElseSet()} is invoked concurrently. This property is crucial
+ * as evaluation of the supplier may have side effects, for example, the call above to
+ * {@code Logger.create()} may result in storage resources being prepared.
+ *
+ *
Stable Functions
+ * Stable values provide the foundation for higher-level functional abstractions. A
+ * stable supplier is a supplier that computes a value and then caches it into
+ * a backing stable value storage for subsequent use. A stable supplier is created via the
+ * {@linkplain StableValue#supplier(Supplier) StableValue.supplier()} factory, by
+ * providing an underlying {@linkplain Supplier} which is invoked when the stable supplier
+ * is first accessed:
+ *
+ * {@snippet lang = java:
+ * public class Component {
+ *
+ * private final Supplier logger =
+ * // @link substring="supplier" target="#supplier(Supplier)" :
+ * StableValue.supplier( () -> Logger.getLogger(Component.class) );
+ *
+ * public void process() {
+ * logger.get().info("Process started");
+ * // ...
+ * }
+ * }
+ *}
+ * A stable supplier encapsulates access to its backing stable value storage. This means
+ * that code inside {@code Component} can obtain the logger object directly from the
+ * stable supplier, without having to go through an accessor method like {@code getLogger()}.
+ *
+ * A stable int function is a function that takes an {@code int} parameter and
+ * uses it to compute a result that is then cached by the backing stable value storage
+ * for that parameter value. A stable {@link IntFunction} is created via the
+ * {@linkplain StableValue#intFunction(int, IntFunction) StableValue.intFunction()}
+ * factory. Upon creation, the input range (i.e. {@code [0, size)}) is specified together
+ * with an underlying {@linkplain IntFunction} which is invoked at most once per input
+ * value. In effect, the stable int function will act like a cache for the underlying
+ * {@linkplain IntFunction}:
+ *
+ * {@snippet lang = java:
+ * final class PowerOf2Util {
+ *
+ * private PowerOf2Util() {}
+ *
+ * private static final int SIZE = 6;
+ * private static final IntFunction UNDERLYING_POWER_OF_TWO =
+ * v -> 1 << v;
+ *
+ * private static final IntFunction POWER_OF_TWO =
+ * // @link substring="intFunction" target="#intFunction(int,IntFunction)" :
+ * StableValue.intFunction(SIZE, UNDERLYING_POWER_OF_TWO);
+ *
+ * public static int powerOfTwo(int a) {
+ * return POWER_OF_TWO.apply(a);
+ * }
+ * }
+ *
+ * int result = PowerOf2Util.powerOfTwo(4); // May eventually constant fold to 16 at runtime
+ *
+ *}
+ * The {@code PowerOf2Util.powerOfTwo()} function is a partial function that only
+ * allows a subset {@code [0, 5]} of the underlying function's {@code UNDERLYING_POWER_OF_TWO}
+ * input range.
+ *
+ *
+ * A stable function is a function that takes a parameter (of type {@code T}) and
+ * uses it to compute a result (of type {@code R}) that is then cached by the backing
+ * stable value storage for that parameter value. A stable function is created via the
+ * {@linkplain StableValue#function(Set, Function) StableValue.function()} factory.
+ * Upon creation, the input {@linkplain Set} is specified together with an underlying
+ * {@linkplain Function} which is invoked at most once per input value. In effect, the
+ * stable function will act like a cache for the underlying {@linkplain Function}:
+ *
+ * {@snippet lang = java:
+ * class Log2Util {
+ *
+ * private Log2Util() {}
+ *
+ * private static final Set KEYS =
+ * Set.of(1, 2, 4, 8, 16, 32);
+ * private static final UnaryOperator UNDERLYING_LOG2 =
+ * i -> 31 - Integer.numberOfLeadingZeros(i);
+ *
+ * private static final Function LOG2 =
+ * // @link substring="function" target="#function(Set,Function)" :
+ * StableValue.function(KEYS, UNDERLYING_LOG2);
+ *
+ * public static int log2(int a) {
+ * return LOG2.apply(a);
+ * }
+ *
+ * }
+ *
+ * int result = Log2Util.log2(16); // May eventually constant fold to 4 at runtime
+ *}
+ *
+ * The {@code Log2Util.log2()} function is a partial function that only allows
+ * a subset {@code {1, 2, 4, 8, 16, 32}} of the underlying function's
+ * {@code UNDERLYING_LOG2} input range.
+ *
+ *
Stable Collections
+ * Stable values can also be used as backing storage for
+ * {@linkplain Collection##unmodifiable unmodifiable collections}. A stable list
+ * is an unmodifiable list, backed by an array of stable values. The stable list elements
+ * are computed when they are first accessed, using a provided {@linkplain IntFunction}:
+ *
+ * {@snippet lang = java:
+ * final class PowerOf2Util {
+ *
+ * private PowerOf2Util() {}
+ *
+ * private static final int SIZE = 6;
+ * private static final IntFunction UNDERLYING_POWER_OF_TWO =
+ * v -> 1 << v;
+ *
+ * private static final List POWER_OF_TWO =
+ * // @link substring="list" target="#list(int,IntFunction)" :
+ * StableValue.list(SIZE, UNDERLYING_POWER_OF_TWO);
+ *
+ * public static int powerOfTwo(int a) {
+ * return POWER_OF_TWO.get(a);
+ * }
+ * }
+ *
+ * int result = PowerOf2Util.powerOfTwo(4); // May eventually constant fold to 16 at runtime
+ *
+ * }
+ *
+ * Similarly, a stable map is an unmodifiable map whose keys are known at
+ * construction. The stable map values are computed when they are first accessed,
+ * using a provided {@linkplain Function}:
+ *
+ * {@snippet lang = java:
+ * class Log2Util {
+ *
+ * private Log2Util() {}
+ *
+ * private static final Set KEYS =
+ * Set.of(1, 2, 4, 8, 16, 32);
+ * private static final UnaryOperator UNDERLYING_LOG2 =
+ * i -> 31 - Integer.numberOfLeadingZeros(i);
+ *
+ * private static final Map LOG2 =
+ * // @link substring="map" target="#map(Set,Function)" :
+ * StableValue.map(CACHED_KEYS, UNDERLYING_LOG2);
+ *
+ * public static int log2(int a) {
+ * return LOG2.get(a);
+ * }
+ *
+ * }
+ *
+ * int result = Log2Util.log2(16); // May eventually constant fold to 4 at runtime
+ *
+ *}
+ *
+ *
Composing stable values
+ * A stable value can depend on other stable values, forming a dependency graph
+ * that can be lazily computed but where access to individual elements can still be
+ * performant. In the following example, a single {@code Foo} and a {@code Bar}
+ * instance (that is dependent on the {@code Foo} instance) are lazily created, both of
+ * which are held by stable values:
+ * {@snippet lang = java:
+ * public final class DependencyUtil {
+ *
+ * private DependencyUtil() {}
+ *
+ * public static class Foo {
+ * // ...
+ * }
+ *
+ * public static class Bar {
+ * public Bar(Foo foo) {
+ * // ...
+ * }
+ * }
+ *
+ * private static final Supplier FOO = StableValue.supplier(Foo::new);
+ * private static final Supplier BAR = StableValue.supplier(() -> new Bar(FOO.get()));
+ *
+ * public static Foo foo() {
+ * return FOO.get();
+ * }
+ *
+ * public static Bar bar() {
+ * return BAR.get();
+ * }
+ *
+ * }
+ *}
+ * Calling {@code bar()} will create the {@code Bar} singleton if it is not already
+ * created. Upon such a creation, the dependent {@code Foo} will first be created if
+ * the {@code Foo} does not already exist.
+ *
+ * Another example, which has a more complex dependency graph, is to compute the
+ * Fibonacci sequence lazily:
+ * {@snippet lang = java:
+ * public final class Fibonacci {
+ *
+ * private Fibonacci() {}
+ *
+ * private static final int MAX_SIZE_INT = 46;
+ *
+ * private static final IntFunction FIB =
+ * StableValue.intFunction(MAX_SIZE_INT, Fibonacci::fib);
+ *
+ * public static int fib(int n) {
+ * return n < 2
+ * ? n
+ * : FIB.apply(n - 1) + FIB.apply(n - 2);
+ * }
+ *
+ * }
+ *}
+ * Both {@code FIB} and {@code Fibonacci::fib} recurse into each other. Because the
+ * stable int function {@code FIB} caches intermediate results, the initial
+ * computational complexity is reduced from exponential to linear compared to a
+ * traditional non-caching recursive fibonacci method. Once computed, the VM is free to
+ * constant-fold expressions like {@code Fibonacci.fib(5)}.
+ *
+ * The fibonacci example above is a directed acyclic graph (i.e.,
+ * it has no circular dependencies and is therefore a dependency tree):
+ *{@snippet lang=text :
+ *
+ * ___________fib(5)____________
+ * / \
+ * ____fib(4)____ ____fib(3)____
+ * / \ / \
+ * fib(3) fib(2) fib(2) fib(1)
+ * / \ / \ / \
+ * fib(2) fib(1) fib(1) fib(0) fib(1) fib(0)
+ *}
+ *
+ * If there are circular dependencies in a dependency graph, a stable value will
+ * eventually throw an {@linkplain IllegalStateException} upon referencing elements in
+ * a circularity.
+ *
+ *
Thread Safety
+ * The contents of a stable value is guaranteed to be set at most once. If competing
+ * threads are racing to set a stable value, only one update succeeds, while the other
+ * updates are blocked until the stable value is set, whereafter the other updates
+ * observes the stable value is set and leave the stable value unchanged.
+ *
+ * The at-most-once write operation on a stable value that succeeds
+ * (e.g. {@linkplain #trySet(Object) trySet()})
+ * {@linkplain java.util.concurrent##MemoryVisibility happens-before}
+ * any successful read operation (e.g. {@linkplain #orElseThrow()}).
+ * A successful write operation can be either:
+ *
+ *
a {@link #trySet(Object)} that returns {@code true},
+ *
a {@link #setOrThrow(Object)} that does not throw, or
+ *
an {@link #orElseSet(Supplier)} that successfully runs the supplier
+ *
+ * A successful read operation can be either:
+ *
+ *
a {@link #orElseThrow()} that does not throw,
+ *
a {@link #orElse(Object) orElse(other)} that does not return the {@code other} value
+ *
an {@link #orElseSet(Supplier)} that does not {@code throw}, or
+ *
an {@link #isSet()} that returns {@code true}
+ *
+ *
+ * The method {@link #orElseSet(Supplier)} guarantees that the provided
+ * {@linkplain Supplier} is invoked successfully at most once, even under race.
+ * Invocations of {@link #setOrThrow(Object)} form a total order of zero or more
+ * exceptional invocations followed by zero (if the contents were already set) or one
+ * successful invocation. Since stable functions and stable collections are built on top
+ * of the same principles as {@linkplain StableValue#orElseSet(Supplier) orElseSet()} they
+ * too are thread safe and guarantee at-most-once-per-input invocation.
+ *
+ *
Performance
+ * As the contents of a stable value can never change after it has been set, a JVM
+ * implementation may, for a set stable value, elide all future reads of that
+ * stable value, and instead directly use any contents that it has previously observed.
+ * This is true if the reference to the stable value is a constant (e.g. in cases where
+ * the stable value itself is stored in a {@code static final} field). Stable functions
+ * and collections are built on top of StableValue. As such, they might also be eligible
+ * for the same JVM optimizations as for StableValue.
+ *
+ * @implSpec Implementing classes of {@code StableValue} are free to synchronize on
+ * {@code this} and consequently, it should be avoided to
+ * (directly or indirectly) synchronize on a {@code StableValue}. Hence,
+ * synchronizing on {@code this} may lead to deadlock.
+ *
+ * Except for a {@code StableValue}'s contents itself,
+ * an {@linkplain #orElse(Object) orElse(other)} parameter, and
+ * an {@linkplain #equals(Object) equals(obj)} parameter; all
+ * method parameters must be non-null or a {@link NullPointerException}
+ * will be thrown.
+ *
+ * @implNote A {@code StableValue} is mainly intended to be a non-public field in
+ * a class and is usually neither exposed directly via accessors nor passed as
+ * a method parameter.
+ *
+ * Stable functions and collections make reasonable efforts to provide
+ * {@link Object#toString()} operations that do not trigger evaluation
+ * of the internal stable values when called.
+ * Stable collections have {@link Object#equals(Object)} operations that try
+ * to minimize evaluation of the internal stable values when called.
+ *
+ * As objects can be set via stable values but never removed, this can be a
+ * source of unintended memory leaks. A stable value's contents are
+ * {@linkplain java.lang.ref##reachability strongly reachable}.
+ * Be advised that reachable stable values will hold their set contents until
+ * the stable value itself is collected.
+ *
+ * A {@code StableValue} that has a type parameter {@code T} that is an array
+ * type (of arbitrary rank) will only allow the JVM to treat the
+ * array reference as a stable value but not its components.
+ * Instead, a {@linkplain #list(int, IntFunction) a stable list} of arbitrary
+ * depth can be used, which provides stable components. More generally, a
+ * stable value can hold other stable values of arbitrary depth and still
+ * provide transitive constantness.
+ *
+ * Stable values, functions, and collections are not {@link Serializable}.
+ *
+ * @param type of the contents
+ *
+ * @since 25
+ */
+@PreviewFeature(feature = PreviewFeature.Feature.STABLE_VALUES)
+public sealed interface StableValue
+ permits StableValueImpl {
+
+ // Principal methods
+
+ /**
+ * Tries to set the contents of this StableValue to the provided {@code contents}.
+ * The contents of this StableValue can only be set once, implying this method only
+ * returns {@code true} once.
+ *
+ * When this method returns, the contents of this StableValue is always set.
+ *
+ * @return {@code true} if the contents of this StableValue was set to the
+ * provided {@code contents}, {@code false} otherwise
+ * @param contents to set
+ * @throws IllegalStateException if a supplier invoked by {@link #orElseSet(Supplier)}
+ * recursively attempts to set this stable value by calling this method
+ * directly or indirectly.
+ */
+ boolean trySet(T contents);
+
+ /**
+ * {@return the contents if set, otherwise, returns the provided {@code other} value}
+ *
+ * @param other to return if the contents is not set
+ */
+ T orElse(T other);
+
+ /**
+ * {@return the contents if set, otherwise, throws {@code NoSuchElementException}}
+ *
+ * @throws NoSuchElementException if no contents is set
+ */
+ T orElseThrow();
+
+ /**
+ * {@return {@code true} if the contents is set, {@code false} otherwise}
+ */
+ boolean isSet();
+
+ /**
+ * {@return the contents; if unset, first attempts to compute and set the
+ * contents using the provided {@code supplier}}
+ *
+ * The provided {@code supplier} is guaranteed to be invoked at most once if it
+ * completes without throwing an exception. If this method is invoked several times
+ * with different suppliers, only one of them will be invoked provided it completes
+ * without throwing an exception.
+ *
+ * If the supplier throws an (unchecked) exception, the exception is rethrown and no
+ * contents is set. The most common usage is to construct a new object serving
+ * as a lazily computed value or memoized result, as in:
+ *
+ * {@snippet lang=java:
+ * Value v = stable.orElseSet(Value::new);
+ * }
+ *
+ * When this method returns successfully, the contents is always set.
+ *
+ * The provided {@code supplier} will only be invoked once even if invoked from
+ * several threads unless the {@code supplier} throws an exception.
+ *
+ * @param supplier to be used for computing the contents, if not previously set
+ * @throws IllegalStateException if the provided {@code supplier} recursively
+ * attempts to set this stable value.
+ */
+ T orElseSet(Supplier extends T> supplier);
+
+ // Convenience methods
+
+ /**
+ * Sets the contents of this StableValue to the provided {@code contents}, or, if
+ * already set, throws {@code IllegalStateException}.
+ *
+ * When this method returns (or throws an exception), the contents is always set.
+ *
+ * @param contents to set
+ * @throws IllegalStateException if the contents was already set
+ */
+ void setOrThrow(T contents);
+
+ // Object methods
+
+ /**
+ * {@return {@code true} if {@code this == obj}, {@code false} otherwise}
+ *
+ * @param obj to check for equality
+ */
+ boolean equals(Object obj);
+
+ /**
+ * {@return the {@linkplain System#identityHashCode(Object) identity hash code} of
+ * {@code this} object}
+ */
+ int hashCode();
+
+ // Factories
+
+ /**
+ * {@return a new unset stable value}
+ *
+ * An unset stable value has no contents.
+ *
+ * @param type of the contents
+ */
+ static StableValue of() {
+ return StableValueImpl.of();
+ }
+
+ /**
+ * {@return a new pre-set stable value with the provided {@code contents}}
+ *
+ * @param contents to set
+ * @param type of the contents
+ */
+ static StableValue of(T contents) {
+ final StableValue stableValue = StableValue.of();
+ stableValue.trySet(contents);
+ return stableValue;
+ }
+
+ /**
+ * {@return a new stable supplier}
+ *
+ * The returned {@linkplain Supplier supplier} is a caching supplier that records
+ * the value of the provided {@code underlying} supplier upon being first accessed via
+ * the returned supplier's {@linkplain Supplier#get() get()} method.
+ *
+ * The provided {@code underlying} supplier is guaranteed to be successfully invoked
+ * at most once even in a multi-threaded environment. Competing threads invoking the
+ * returned supplier's {@linkplain Supplier#get() get()} method when a value is
+ * already under computation will block until a value is computed or an exception is
+ * thrown by the computing thread. The computing threads will then observe the newly
+ * computed value (if any) and will then never execute.
+ *
+ * If the provided {@code underlying} supplier throws an exception, it is rethrown
+ * to the initial caller and no contents is recorded.
+ *
+ * If the provided {@code underlying} supplier recursively calls the returned
+ * supplier, an {@linkplain IllegalStateException} will be thrown.
+ *
+ * @param underlying supplier used to compute a cached value
+ * @param the type of results supplied by the returned supplier
+ */
+ static Supplier supplier(Supplier extends T> underlying) {
+ Objects.requireNonNull(underlying);
+ return StableSupplier.of(underlying);
+ }
+
+ /**
+ * {@return a new stable {@linkplain IntFunction}}
+ *
+ * The returned function is a caching function that, for each allowed {@code int}
+ * input, records the values of the provided {@code underlying}
+ * function upon being first accessed via the returned function's
+ * {@linkplain IntFunction#apply(int) apply()} method. If the returned function is
+ * invoked with an input that is not in the range {@code [0, size)}, an
+ * {@link IllegalArgumentException} will be thrown.
+ *
+ * The provided {@code underlying} function is guaranteed to be successfully invoked
+ * at most once per allowed input, even in a multi-threaded environment. Competing
+ * threads invoking the returned function's
+ * {@linkplain IntFunction#apply(int) apply()} method when a value is already under
+ * computation will block until a value is computed or an exception is thrown by
+ * the computing thread.
+ *
+ * If invoking the provided {@code underlying} function throws an exception, it is
+ * rethrown to the initial caller and no contents is recorded.
+ *
+ * If the provided {@code underlying} function recursively calls the returned
+ * function for the same input, an {@linkplain IllegalStateException} will
+ * be thrown.
+ *
+ * @param size the size of the allowed inputs in the continuous
+ * interval {@code [0, size)}
+ * @param underlying IntFunction used to compute cached values
+ * @param the type of results delivered by the returned IntFunction
+ * @throws IllegalArgumentException if the provided {@code size} is negative.
+ */
+ static IntFunction intFunction(int size,
+ IntFunction extends R> underlying) {
+ StableUtil.assertSizeNonNegative(size);
+ Objects.requireNonNull(underlying);
+ return StableIntFunction.of(size, underlying);
+ }
+
+ /**
+ * {@return a new stable {@linkplain Function}}
+ *
+ * The returned function is a caching function that, for each allowed
+ * input in the given set of {@code inputs}, records the values of the provided
+ * {@code underlying} function upon being first accessed via the returned function's
+ * {@linkplain Function#apply(Object) apply()} method. If the returned function is
+ * invoked with an input that is not in {@code inputs}, an {@link IllegalArgumentException}
+ * will be thrown.
+ *
+ * The provided {@code underlying} function is guaranteed to be successfully invoked
+ * at most once per allowed input, even in a multi-threaded environment. Competing
+ * threads invoking the returned function's {@linkplain Function#apply(Object) apply()}
+ * method when a value is already under computation will block until a value is
+ * computed or an exception is thrown by the computing thread.
+ *
+ * If invoking the provided {@code underlying} function throws an exception, it is
+ * rethrown to the initial caller and no contents is recorded.
+ *
+ * If the provided {@code underlying} function recursively calls the returned
+ * function for the same input, an {@linkplain IllegalStateException} will
+ * be thrown.
+ *
+ * @param inputs the set of (non-null) allowed input values
+ * @param underlying {@code Function} used to compute cached values
+ * @param the type of the input to the returned Function
+ * @param the type of results delivered by the returned Function
+ * @throws NullPointerException if the provided set of {@code inputs} contains a
+ * {@code null} element.
+ */
+ static Function function(Set extends T> inputs,
+ Function super T, ? extends R> underlying) {
+ Objects.requireNonNull(inputs);
+ // Checking that the Set of inputs does not contain a `null` value is made in the
+ // implementing classes.
+ Objects.requireNonNull(underlying);
+ return inputs instanceof EnumSet> && !inputs.isEmpty()
+ ? StableEnumFunction.of(inputs, underlying)
+ : StableFunction.of(inputs, underlying);
+ }
+
+ /**
+ * {@return a new stable list with the provided {@code size}}
+ *
+ * The returned list is an {@linkplain Collection##unmodifiable unmodifiable} list
+ * with the provided {@code size}. The list's elements are computed via the
+ * provided {@code mapper} when they are first accessed
+ * (e.g. via {@linkplain List#get(int) List::get}).
+ *
+ * The provided {@code mapper} function is guaranteed to be successfully invoked
+ * at most once per list index, even in a multi-threaded environment. Competing
+ * threads accessing an element already under computation will block until an element
+ * is computed or an exception is thrown by the computing thread.
+ *
+ * If invoking the provided {@code mapper} function throws an exception, it
+ * is rethrown to the initial caller and no value for the element is recorded.
+ *
+ * Any direct {@link List#subList(int, int) subList} or {@link List#reversed()} views
+ * of the returned list are also stable.
+ *
+ * The returned list and its {@link List#subList(int, int) subList} or
+ * {@link List#reversed()} views implement the {@link RandomAccess} interface.
+ *
+ * The returned list is unmodifiable and does not implement the
+ * {@linkplain Collection##optional-operation optional operations} in the
+ * {@linkplain List} interface.
+ *
+ * If the provided {@code mapper} recursively calls the returned list for the
+ * same index, an {@linkplain IllegalStateException} will be thrown.
+ *
+ * @param size the size of the returned list
+ * @param mapper to invoke whenever an element is first accessed
+ * (may return {@code null})
+ * @param the type of elements in the returned list
+ * @throws IllegalArgumentException if the provided {@code size} is negative.
+ */
+ static List list(int size,
+ IntFunction extends E> mapper) {
+ StableUtil.assertSizeNonNegative(size);
+ Objects.requireNonNull(mapper);
+ return SharedSecrets.getJavaUtilCollectionAccess().stableList(size, mapper);
+ }
+
+ /**
+ * {@return a new stable map with the provided {@code keys}}
+ *
+ * The returned map is an {@linkplain Collection##unmodifiable unmodifiable} map whose
+ * keys are known at construction. The map's values are computed via the provided
+ * {@code mapper} when they are first accessed
+ * (e.g. via {@linkplain Map#get(Object) Map::get}).
+ *
+ * The provided {@code mapper} function is guaranteed to be successfully invoked
+ * at most once per key, even in a multi-threaded environment. Competing
+ * threads accessing a value already under computation will block until an element
+ * is computed or an exception is thrown by the computing thread.
+ *
+ * If invoking the provided {@code mapper} function throws an exception, it
+ * is rethrown to the initial caller and no value associated with the provided key
+ * is recorded.
+ *
+ * Any direct {@link Map#values()} or {@link Map#entrySet()} views
+ * of the returned map are also stable.
+ *
+ * The returned map is unmodifiable and does not implement the
+ * {@linkplain Collection##optional-operations optional operations} in the
+ * {@linkplain Map} interface.
+ *
+ * If the provided {@code mapper} recursively calls the returned map for
+ * the same key, an {@linkplain IllegalStateException} will be thrown.
+ *
+ * @param keys the (non-null) keys in the returned map
+ * @param mapper to invoke whenever an associated value is first accessed
+ * (may return {@code null})
+ * @param the type of keys maintained by the returned map
+ * @param the type of mapped values in the returned map
+ * @throws NullPointerException if the provided set of {@code inputs} contains a
+ * {@code null} element.
+ */
+ static Map map(Set keys,
+ Function super K, ? extends V> mapper) {
+ Objects.requireNonNull(keys);
+ // Checking that the Set of keys does not contain a `null` value is made in the
+ // implementing class.
+ Objects.requireNonNull(mapper);
+ return SharedSecrets.getJavaUtilCollectionAccess().stableMap(keys, mapper);
+ }
+
+}
diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java
index 903f6e34e2e..a60958f6f82 100644
--- a/src/java.base/share/classes/java/lang/System.java
+++ b/src/java.base/share/classes/java/lang/System.java
@@ -116,15 +116,23 @@ public final class System {
/**
* The "standard" input stream. This stream is already
- * open and ready to supply input data. Typically this stream
+ * open and ready to supply input data. This stream
* corresponds to keyboard input or another input source specified by
- * the host environment or user. In case this stream is wrapped
- * in a {@link java.io.InputStreamReader}, {@link Console#charset()}
- * should be used for the charset, or consider using
- * {@link Console#reader()}.
+ * the host environment or user. Applications should use the encoding
+ * specified by the {@link ##stdin.encoding stdin.encoding} property
+ * to convert input bytes to character data.
*
- * @see Console#charset()
- * @see Console#reader()
+ * @apiNote
+ * The typical approach to read character data is to wrap {@code System.in}
+ * within an {@link java.io.InputStreamReader InputStreamReader} or other object
+ * that handles character encoding. After this is done, subsequent reading should
+ * use only the wrapper object; operating directly on {@code System.in} results
+ * in unspecified behavior.
+ *
+ * For handling interactive input, consider using {@link Console}.
+ *
+ * @see Console
+ * @see ##stdin.encoding stdin.encoding
*/
public static final InputStream in = null;
@@ -575,17 +583,22 @@ public final class System {
*
{@systemProperty user.dir}
*
User's current working directory
*
{@systemProperty native.encoding}
- *
Character encoding name derived from the host environment and/or
- * the user's settings. Setting this system property has no effect.
+ *
Character encoding name derived from the host environment and
+ * the user's settings. Setting this system property on the command line
+ * has no effect.
+ *
{@systemProperty stdin.encoding}
+ *
Character encoding name for {@link System#in System.in}.
+ * The Java runtime can be started with the system property set to {@code UTF-8}.
+ * Starting it with the property set to another value results in unspecified behavior.
*
{@systemProperty stdout.encoding}
*
Character encoding name for {@link System#out System.out} and
* {@link System#console() System.console()}.
- * The Java runtime can be started with the system property set to {@code UTF-8},
- * starting it with the property set to another value leads to undefined behavior.
+ * The Java runtime can be started with the system property set to {@code UTF-8}.
+ * Starting it with the property set to another value results in unspecified behavior.
*
{@systemProperty stderr.encoding}
*
Character encoding name for {@link System#err System.err}.
- * The Java runtime can be started with the system property set to {@code UTF-8},
- * starting it with the property set to another value leads to undefined behavior.
+ * The Java runtime can be started with the system property set to {@code UTF-8}.
+ * Starting it with the property set to another value results in unspecified behavior.
*
*
*
@@ -639,7 +652,7 @@ public final class System {
* the value {@code COMPAT} then the value is replaced with the
* value of the {@code native.encoding} property during startup.
* Setting the property to a value other than {@code UTF-8} or
- * {@code COMPAT} leads to unspecified behavior.
+ * {@code COMPAT} results in unspecified behavior.
*
*
*
@@ -2004,6 +2017,9 @@ public final class System {
E[] getEnumConstantsShared(Class klass) {
return klass.getEnumConstantsShared();
}
+ public int classFileVersion(Class> clazz) {
+ return clazz.getClassFileVersion();
+ }
public void blockedOn(Interruptible b) {
Thread.currentThread().blockedOn(b);
}
@@ -2059,9 +2075,6 @@ public final class System {
public void addOpensToAllUnnamed(Module m, String pn) {
m.implAddOpensToAllUnnamed(pn);
}
- public void addOpensToAllUnnamed(Module m, Set concealedPackages, Set exportedPackages) {
- m.implAddOpensToAllUnnamed(concealedPackages, exportedPackages);
- }
public void addUses(Module m, Class> service) {
m.implAddUses(service);
}
diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java
index 5017838d68e..108c47c8089 100644
--- a/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java
+++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ClassEntry.java
@@ -104,8 +104,22 @@ public sealed interface ClassEntry
* returned descriptor is never {@linkplain ClassDesc#isPrimitive()
* primitive}.
*
+ * @apiNote
+ * If only symbol equivalence is desired, {@link #matches(ClassDesc)
+ * matches} should be used. It requires reduced parsing and can
+ * improve {@code class} file reading performance.
+ *
* @see ConstantPoolBuilder#classEntry(ClassDesc)
* ConstantPoolBuilder::classEntry(ClassDesc)
*/
ClassDesc asSymbol();
+
+ /**
+ * {@return whether this entry describes the given reference type} Returns
+ * {@code false} if {@code desc} is primitive.
+ *
+ * @param desc the reference type
+ * @since 25
+ */
+ boolean matches(ClassDesc desc);
}
diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java
index 5da36502678..2f56ce2e6ab 100644
--- a/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java
+++ b/src/java.base/share/classes/java/lang/classfile/constantpool/MethodTypeEntry.java
@@ -70,6 +70,19 @@ public sealed interface MethodTypeEntry
/**
* {@return a symbolic descriptor for the {@linkplain #descriptor() method
* type}}
+ *
+ * @apiNote
+ * If only symbol equivalence is desired, {@link #matches(MethodTypeDesc)
+ * matches} should be used. It requires reduced parsing and can
+ * improve {@code class} file reading performance.
*/
MethodTypeDesc asSymbol();
+
+ /**
+ * {@return whether this entry describes the given method type}
+ *
+ * @param desc the method type descriptor
+ * @since 25
+ */
+ boolean matches(MethodTypeDesc desc);
}
diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java
index fd920aa1231..169927868b6 100644
--- a/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java
+++ b/src/java.base/share/classes/java/lang/classfile/constantpool/ModuleEntry.java
@@ -55,6 +55,19 @@ public sealed interface ModuleEntry extends PoolEntry
/**
* {@return a symbolic descriptor for the {@linkplain #name() module name}}
+ *
+ * @apiNote
+ * If only symbol equivalence is desired, {@link #matches(ModuleDesc)
+ * matches} should be used. It requires reduced parsing and can
+ * improve {@code class} file reading performance.
*/
ModuleDesc asSymbol();
+
+ /**
+ * {@return whether this entry describes the given module}
+ *
+ * @param desc the module descriptor
+ * @since 25
+ */
+ boolean matches(ModuleDesc desc);
}
diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java
index ec56d0a4870..19f4560b5e6 100644
--- a/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java
+++ b/src/java.base/share/classes/java/lang/classfile/constantpool/PackageEntry.java
@@ -58,6 +58,19 @@ public sealed interface PackageEntry extends PoolEntry
/**
* {@return a symbolic descriptor for the {@linkplain #name() package name}}
+ *
+ * @apiNote
+ * If only symbol equivalence is desired, {@link #matches(PackageDesc)
+ * matches} should be used. It requires reduced parsing and can
+ * improve {@code class} file reading performance.
*/
PackageDesc asSymbol();
+
+ /**
+ * {@return whether this entry describes the given package}
+ *
+ * @param desc the package descriptor
+ * @since 25
+ */
+ boolean matches(PackageDesc desc);
}
diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java
index 8a0bbb4b015..b49e74df404 100644
--- a/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java
+++ b/src/java.base/share/classes/java/lang/classfile/constantpool/StringEntry.java
@@ -56,7 +56,22 @@ public sealed interface StringEntry
/**
* {@return the string value for this entry}
*
+ * @apiNote
+ * A {@code Utf8Entry} can be used directly as a {@link CharSequence} if
+ * {@code String} functionalities are not strictly desired. If only string
+ * equivalence is desired, {@link #equalsString(String) equalsString} should
+ * be used. Reduction of string processing can significantly improve {@code
+ * class} file reading performance.
+ *
* @see ConstantPoolBuilder#stringEntry(String)
*/
String stringValue();
+
+ /**
+ * {@return whether this entry describes the same string as the provided string}
+ *
+ * @param value the string to compare to
+ * @since 25
+ */
+ boolean equalsString(String value);
}
diff --git a/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java b/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java
index 1d885051b2b..81a4e973d3f 100644
--- a/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java
+++ b/src/java.base/share/classes/java/lang/classfile/constantpool/Utf8Entry.java
@@ -84,4 +84,22 @@ public sealed interface Utf8Entry
* @param s the string to compare to
*/
boolean equalsString(String s);
+
+ /**
+ * {@return whether this entry describes the descriptor string of this
+ * field type}
+ *
+ * @param desc the field type
+ * @since 25
+ */
+ boolean isFieldType(ClassDesc desc);
+
+ /**
+ * {@return whether this entry describes the descriptor string of this
+ * method type}
+ *
+ * @param desc the method type
+ * @since 25
+ */
+ boolean isMethodType(MethodTypeDesc desc);
}
diff --git a/src/java.base/share/classes/java/lang/foreign/Linker.java b/src/java.base/share/classes/java/lang/foreign/Linker.java
index 6e7aae9f72b..8f1cab22b86 100644
--- a/src/java.base/share/classes/java/lang/foreign/Linker.java
+++ b/src/java.base/share/classes/java/lang/foreign/Linker.java
@@ -859,10 +859,11 @@ public sealed interface Linker permits AbstractLinker {
* @see #captureStateLayout()
*/
static Option captureCallState(String... capturedState) {
- Set set = Stream.of(Objects.requireNonNull(capturedState))
+ int set = Stream.of(Objects.requireNonNull(capturedState))
.map(Objects::requireNonNull)
.map(CapturableState::forName)
- .collect(Collectors.toSet());
+ .mapToInt(state -> 1 << state.ordinal())
+ .sum();
return new LinkerOptions.CaptureCallState(set);
}
diff --git a/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java b/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java
index 0a943d253af..ad6387e8c9e 100644
--- a/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java
+++ b/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java
@@ -214,7 +214,6 @@ sealed class DirectMethodHandle extends MethodHandle {
which = LF_INVSPECIAL_IFC;
}
LambdaForm lform = preparedLambdaForm(mtype, which);
- maybeCompile(lform, m);
assert(lform.methodType().dropParameterTypes(0, 1)
.equals(m.getInvocationType().basicType()))
: Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
@@ -320,12 +319,6 @@ sealed class DirectMethodHandle extends MethodHandle {
return null;
}
- private static void maybeCompile(LambdaForm lform, MemberName m) {
- if (lform.vmentry == null && VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class))
- // Help along bootstrapping...
- lform.compileToBytecode();
- }
-
/** Static wrapper for DirectMethodHandle.internalMemberName. */
@ForceInline
/*non-public*/
@@ -621,10 +614,9 @@ sealed class DirectMethodHandle extends MethodHandle {
// Enumerate the different field kinds using Wrapper,
// with an extra case added for checked references.
static final int
- FT_LAST_WRAPPER = Wrapper.COUNT-1,
FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(),
- FT_CHECKED_REF = FT_LAST_WRAPPER+1,
- FT_LIMIT = FT_LAST_WRAPPER+2;
+ FT_CHECKED_REF = Wrapper.VOID.ordinal(),
+ FT_LIMIT = Wrapper.COUNT;
private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
return ((formOp * FT_LIMIT * 2)
+ (isVolatile ? FT_LIMIT : 0)
@@ -667,7 +659,6 @@ sealed class DirectMethodHandle extends MethodHandle {
formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
}
LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, ftype);
- maybeCompile(lform, m);
assert(lform.methodType().dropParameterTypes(0, 1)
.equals(m.getInvocationType().basicType()))
: Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
@@ -683,63 +674,69 @@ sealed class DirectMethodHandle extends MethodHandle {
return lform;
}
- private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
+ private static final @Stable Wrapper[] ALL_WRAPPERS = Wrapper.values();
- private static Kind getFieldKind(boolean isGetter, boolean isVolatile, Wrapper wrapper) {
- if (isGetter) {
- if (isVolatile) {
- switch (wrapper) {
- case BOOLEAN: return GET_BOOLEAN_VOLATILE;
- case BYTE: return GET_BYTE_VOLATILE;
- case SHORT: return GET_SHORT_VOLATILE;
- case CHAR: return GET_CHAR_VOLATILE;
- case INT: return GET_INT_VOLATILE;
- case LONG: return GET_LONG_VOLATILE;
- case FLOAT: return GET_FLOAT_VOLATILE;
- case DOUBLE: return GET_DOUBLE_VOLATILE;
- case OBJECT: return GET_REFERENCE_VOLATILE;
- }
+ // Names in kind may overload but differ from their basic type
+ private static Kind getFieldKind(boolean isVolatile, boolean needsInit, boolean needsCast, Wrapper wrapper) {
+ if (isVolatile) {
+ if (needsInit) {
+ return switch (wrapper) {
+ case BYTE -> VOLATILE_FIELD_ACCESS_INIT_B;
+ case CHAR -> VOLATILE_FIELD_ACCESS_INIT_C;
+ case SHORT -> VOLATILE_FIELD_ACCESS_INIT_S;
+ case BOOLEAN -> VOLATILE_FIELD_ACCESS_INIT_Z;
+ default -> needsCast ? VOLATILE_FIELD_ACCESS_INIT_CAST : VOLATILE_FIELD_ACCESS_INIT;
+ };
} else {
- switch (wrapper) {
- case BOOLEAN: return GET_BOOLEAN;
- case BYTE: return GET_BYTE;
- case SHORT: return GET_SHORT;
- case CHAR: return GET_CHAR;
- case INT: return GET_INT;
- case LONG: return GET_LONG;
- case FLOAT: return GET_FLOAT;
- case DOUBLE: return GET_DOUBLE;
- case OBJECT: return GET_REFERENCE;
- }
+ return switch (wrapper) {
+ case BYTE -> VOLATILE_FIELD_ACCESS_B;
+ case CHAR -> VOLATILE_FIELD_ACCESS_C;
+ case SHORT -> VOLATILE_FIELD_ACCESS_S;
+ case BOOLEAN -> VOLATILE_FIELD_ACCESS_Z;
+ default -> needsCast ? VOLATILE_FIELD_ACCESS_CAST : VOLATILE_FIELD_ACCESS;
+ };
}
} else {
- if (isVolatile) {
- switch (wrapper) {
- case BOOLEAN: return PUT_BOOLEAN_VOLATILE;
- case BYTE: return PUT_BYTE_VOLATILE;
- case SHORT: return PUT_SHORT_VOLATILE;
- case CHAR: return PUT_CHAR_VOLATILE;
- case INT: return PUT_INT_VOLATILE;
- case LONG: return PUT_LONG_VOLATILE;
- case FLOAT: return PUT_FLOAT_VOLATILE;
- case DOUBLE: return PUT_DOUBLE_VOLATILE;
- case OBJECT: return PUT_REFERENCE_VOLATILE;
- }
+ if (needsInit) {
+ return switch (wrapper) {
+ case BYTE -> FIELD_ACCESS_INIT_B;
+ case CHAR -> FIELD_ACCESS_INIT_C;
+ case SHORT -> FIELD_ACCESS_INIT_S;
+ case BOOLEAN -> FIELD_ACCESS_INIT_Z;
+ default -> needsCast ? FIELD_ACCESS_INIT_CAST : FIELD_ACCESS_INIT;
+ };
} else {
- switch (wrapper) {
- case BOOLEAN: return PUT_BOOLEAN;
- case BYTE: return PUT_BYTE;
- case SHORT: return PUT_SHORT;
- case CHAR: return PUT_CHAR;
- case INT: return PUT_INT;
- case LONG: return PUT_LONG;
- case FLOAT: return PUT_FLOAT;
- case DOUBLE: return PUT_DOUBLE;
- case OBJECT: return PUT_REFERENCE;
- }
+ return switch (wrapper) {
+ case BYTE -> FIELD_ACCESS_B;
+ case CHAR -> FIELD_ACCESS_C;
+ case SHORT -> FIELD_ACCESS_S;
+ case BOOLEAN -> FIELD_ACCESS_Z;
+ default -> needsCast ? FIELD_ACCESS_CAST : FIELD_ACCESS;
+ };
}
}
- throw new AssertionError("Invalid arguments");
+ }
+
+ private static String unsafeMethodName(boolean isGetter, boolean isVolatile, Wrapper wrapper) {
+ var name = switch (wrapper) {
+ case BOOLEAN -> "Boolean";
+ case BYTE -> "Byte";
+ case CHAR -> "Char";
+ case SHORT -> "Short";
+ case INT -> "Int";
+ case FLOAT -> "Float";
+ case LONG -> "Long";
+ case DOUBLE -> "Double";
+ case OBJECT -> "Reference";
+ case VOID -> throw new InternalError();
+ };
+ var sb = new StringBuilder(3 + name.length() + (isVolatile ? 8 : 0))
+ .append(isGetter ? "get" : "put")
+ .append(name);
+ if (isVolatile) {
+ sb.append("Volatile");
+ }
+ return sb.toString();
}
static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
@@ -752,14 +749,16 @@ sealed class DirectMethodHandle extends MethodHandle {
assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
// getObject, putIntVolatile, etc.
- Kind kind = getFieldKind(isGetter, isVolatile, fw);
+ String unsafeMethodName = unsafeMethodName(isGetter, isVolatile, fw);
+ // isGetter and isStatic is reflected in field type; basic type clash for subwords
+ Kind kind = getFieldKind(isVolatile, needsInit, needsCast, fw);
MethodType linkerType;
if (isGetter)
linkerType = MethodType.methodType(ft, Object.class, long.class);
else
linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
- MemberName linker = new MemberName(Unsafe.class, kind.methodName, linkerType, REF_invokeVirtual);
+ MemberName linker = new MemberName(Unsafe.class, unsafeMethodName, linkerType, REF_invokeVirtual);
try {
linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, LM_TRUSTED,
NoSuchMethodException.class);
@@ -817,18 +816,12 @@ sealed class DirectMethodHandle extends MethodHandle {
names[POST_CAST] = new Name(getFunction(NF_checkCast), names[DMH_THIS], names[LINKER_CALL]);
for (Name n : names) assert(n != null);
- LambdaForm form;
- if (needsCast || needsInit) {
- // can't use the pre-generated form when casting and/or initializing
- form = LambdaForm.create(ARG_LIMIT, names, RESULT);
- } else {
- form = LambdaForm.create(ARG_LIMIT, names, RESULT, kind);
- }
+ LambdaForm form = LambdaForm.create(ARG_LIMIT, names, RESULT, kind);
if (LambdaForm.debugNames()) {
// add some detail to the lambdaForm debugname,
// significant only for debugging
- StringBuilder nameBuilder = new StringBuilder(kind.methodName);
+ StringBuilder nameBuilder = new StringBuilder(unsafeMethodName);
if (isStatic) {
nameBuilder.append("Static");
} else {
@@ -842,6 +835,9 @@ sealed class DirectMethodHandle extends MethodHandle {
}
LambdaForm.associateWithDebugName(form, nameBuilder.toString());
}
+
+ // NF_UNSAFE uses field form, avoid circular dependency in interpreter
+ form.compileToBytecode();
return form;
}
diff --git a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java
index e52438544ae..561f9122398 100644
--- a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java
+++ b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java
@@ -430,24 +430,21 @@ class GenerateJLIClassesHelper {
names.add(form.kind.defaultLambdaName);
}
for (Wrapper wrapper : Wrapper.values()) {
- if (wrapper == Wrapper.VOID) {
- continue;
- }
+ int ftype = wrapper == Wrapper.VOID ? DirectMethodHandle.FT_CHECKED_REF : DirectMethodHandle.ftypeKind(wrapper.primitiveType());
for (byte b = DirectMethodHandle.AF_GETFIELD; b < DirectMethodHandle.AF_LIMIT; b++) {
- int ftype = DirectMethodHandle.ftypeKind(wrapper.primitiveType());
LambdaForm form = DirectMethodHandle
.makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype);
- if (form.kind != LambdaForm.Kind.GENERIC) {
- forms.add(form);
- names.add(form.kind.defaultLambdaName);
- }
+ if (form.kind == GENERIC)
+ throw new InternalError(b + " non-volatile " + ftype);
+ forms.add(form);
+ names.add(form.kind.defaultLambdaName);
// volatile
form = DirectMethodHandle
.makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype);
- if (form.kind != LambdaForm.Kind.GENERIC) {
- forms.add(form);
- names.add(form.kind.defaultLambdaName);
- }
+ if (form.kind == GENERIC)
+ throw new InternalError(b + " volatile " + ftype);
+ forms.add(form);
+ names.add(form.kind.defaultLambdaName);
}
}
return generateCodeBytesForLFs(className,
diff --git a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
index f5998c46aa1..b3d2ff2c880 100644
--- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
+++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
@@ -468,24 +468,30 @@ class InvokerBytecodeGenerator {
case LINK_TO_TARGET_METHOD: // fall-through
case GENERIC_INVOKER: // fall-through
case GENERIC_LINKER: return resolveFrom(name, invokerType, Invokers.Holder.class);
- case GET_REFERENCE: // fall-through
- case GET_BOOLEAN: // fall-through
- case GET_BYTE: // fall-through
- case GET_CHAR: // fall-through
- case GET_SHORT: // fall-through
- case GET_INT: // fall-through
- case GET_LONG: // fall-through
- case GET_FLOAT: // fall-through
- case GET_DOUBLE: // fall-through
- case PUT_REFERENCE: // fall-through
- case PUT_BOOLEAN: // fall-through
- case PUT_BYTE: // fall-through
- case PUT_CHAR: // fall-through
- case PUT_SHORT: // fall-through
- case PUT_INT: // fall-through
- case PUT_LONG: // fall-through
- case PUT_FLOAT: // fall-through
- case PUT_DOUBLE: // fall-through
+ case FIELD_ACCESS: // fall-through
+ case FIELD_ACCESS_INIT: // fall-through
+ case VOLATILE_FIELD_ACCESS: // fall-through
+ case VOLATILE_FIELD_ACCESS_INIT:// fall-through
+ case FIELD_ACCESS_B: // fall-through
+ case FIELD_ACCESS_INIT_B: // fall-through
+ case VOLATILE_FIELD_ACCESS_B: // fall-through
+ case VOLATILE_FIELD_ACCESS_INIT_B:// fall-through
+ case FIELD_ACCESS_C: // fall-through
+ case FIELD_ACCESS_INIT_C: // fall-through
+ case VOLATILE_FIELD_ACCESS_C: // fall-through
+ case VOLATILE_FIELD_ACCESS_INIT_C:// fall-through
+ case FIELD_ACCESS_S: // fall-through
+ case FIELD_ACCESS_INIT_S: // fall-through
+ case VOLATILE_FIELD_ACCESS_S: // fall-through
+ case VOLATILE_FIELD_ACCESS_INIT_S:// fall-through
+ case FIELD_ACCESS_Z: // fall-through
+ case FIELD_ACCESS_INIT_Z: // fall-through
+ case VOLATILE_FIELD_ACCESS_Z: // fall-through
+ case VOLATILE_FIELD_ACCESS_INIT_Z:// fall-through
+ case FIELD_ACCESS_CAST: // fall-through
+ case FIELD_ACCESS_INIT_CAST: // fall-through
+ case VOLATILE_FIELD_ACCESS_CAST: // fall-through
+ case VOLATILE_FIELD_ACCESS_INIT_CAST:// fall-through
case DIRECT_NEW_INVOKE_SPECIAL: // fall-through
case DIRECT_INVOKE_INTERFACE: // fall-through
case DIRECT_INVOKE_SPECIAL: // fall-through
diff --git a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java
index 7ba66a473fe..c1a07d8d0de 100644
--- a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java
@@ -263,42 +263,30 @@ class LambdaForm {
DIRECT_NEW_INVOKE_SPECIAL("DMH.newInvokeSpecial", "newInvokeSpecial"),
DIRECT_INVOKE_INTERFACE("DMH.invokeInterface", "invokeInterface"),
DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit", "invokeStaticInit"),
- GET_REFERENCE("getReference"),
- PUT_REFERENCE("putReference"),
- GET_REFERENCE_VOLATILE("getReferenceVolatile"),
- PUT_REFERENCE_VOLATILE("putReferenceVolatile"),
- GET_INT("getInt"),
- PUT_INT("putInt"),
- GET_INT_VOLATILE("getIntVolatile"),
- PUT_INT_VOLATILE("putIntVolatile"),
- GET_BOOLEAN("getBoolean"),
- PUT_BOOLEAN("putBoolean"),
- GET_BOOLEAN_VOLATILE("getBooleanVolatile"),
- PUT_BOOLEAN_VOLATILE("putBooleanVolatile"),
- GET_BYTE("getByte"),
- PUT_BYTE("putByte"),
- GET_BYTE_VOLATILE("getByteVolatile"),
- PUT_BYTE_VOLATILE("putByteVolatile"),
- GET_CHAR("getChar"),
- PUT_CHAR("putChar"),
- GET_CHAR_VOLATILE("getCharVolatile"),
- PUT_CHAR_VOLATILE("putCharVolatile"),
- GET_SHORT("getShort"),
- PUT_SHORT("putShort"),
- GET_SHORT_VOLATILE("getShortVolatile"),
- PUT_SHORT_VOLATILE("putShortVolatile"),
- GET_LONG("getLong"),
- PUT_LONG("putLong"),
- GET_LONG_VOLATILE("getLongVolatile"),
- PUT_LONG_VOLATILE("putLongVolatile"),
- GET_FLOAT("getFloat"),
- PUT_FLOAT("putFloat"),
- GET_FLOAT_VOLATILE("getFloatVolatile"),
- PUT_FLOAT_VOLATILE("putFloatVolatile"),
- GET_DOUBLE("getDouble"),
- PUT_DOUBLE("putDouble"),
- GET_DOUBLE_VOLATILE("getDoubleVolatile"),
- PUT_DOUBLE_VOLATILE("putDoubleVolatile"),
+ FIELD_ACCESS("fieldAccess"),
+ FIELD_ACCESS_INIT("fieldAccessInit"),
+ VOLATILE_FIELD_ACCESS("volatileFieldAccess"),
+ VOLATILE_FIELD_ACCESS_INIT("volatileFieldAccessInit"),
+ FIELD_ACCESS_B("fieldAccessB"),
+ FIELD_ACCESS_INIT_B("fieldAccessInitB"),
+ VOLATILE_FIELD_ACCESS_B("volatileFieldAccessB"),
+ VOLATILE_FIELD_ACCESS_INIT_B("volatileFieldAccessInitB"),
+ FIELD_ACCESS_C("fieldAccessC"),
+ FIELD_ACCESS_INIT_C("fieldAccessInitC"),
+ VOLATILE_FIELD_ACCESS_C("volatileFieldAccessC"),
+ VOLATILE_FIELD_ACCESS_INIT_C("volatileFieldAccessInitC"),
+ FIELD_ACCESS_S("fieldAccessS"),
+ FIELD_ACCESS_INIT_S("fieldAccessInitS"),
+ VOLATILE_FIELD_ACCESS_S("volatileFieldAccessS"),
+ VOLATILE_FIELD_ACCESS_INIT_S("volatileFieldAccessInitS"),
+ FIELD_ACCESS_Z("fieldAccessZ"),
+ FIELD_ACCESS_INIT_Z("fieldAccessInitZ"),
+ VOLATILE_FIELD_ACCESS_Z("volatileFieldAccessZ"),
+ VOLATILE_FIELD_ACCESS_INIT_Z("volatileFieldAccessInitZ"),
+ FIELD_ACCESS_CAST("fieldAccessCast"),
+ FIELD_ACCESS_INIT_CAST("fieldAccessInitCast"),
+ VOLATILE_FIELD_ACCESS_CAST("volatileFieldAccessCast"),
+ VOLATILE_FIELD_ACCESS_INIT_CAST("volatileFieldAccessInitCast"),
TRY_FINALLY("tryFinally"),
TABLE_SWITCH("tableSwitch"),
COLLECTOR("collector"),
diff --git a/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java b/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java
index 6a25bf9c0a8..471de5aa48f 100644
--- a/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java
@@ -38,7 +38,6 @@ import static java.lang.invoke.LambdaForm.BasicType.*;
import static java.lang.invoke.MethodHandleImpl.Intrinsic;
import static java.lang.invoke.MethodHandleImpl.NF_loop;
import static java.lang.invoke.MethodHandleImpl.makeIntrinsic;
-import static java.lang.invoke.MethodHandleNatives.USE_SOFT_CACHE;
/** Transforms on LFs.
* A lambda-form editor can derive new LFs from its base LF.
@@ -90,17 +89,12 @@ class LambdaFormEditor {
* Tightly coupled with the TransformKey class, which is used to lookup existing
* Transforms.
*/
- private static final class Transform {
- final Object cache;
+ private static final class Transform extends SoftReference {
final long packedBytes;
final byte[] fullBytes;
private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) {
- if (USE_SOFT_CACHE) {
- cache = new SoftReference(result);
- } else {
- cache = result;
- }
+ super(result);
this.packedBytes = packedBytes;
this.fullBytes = fullBytes;
}
@@ -141,15 +135,6 @@ class LambdaFormEditor {
}
return buf.toString();
}
-
- @SuppressWarnings("unchecked")
- public LambdaForm get() {
- if (cache instanceof LambdaForm lf) {
- return lf;
- } else {
- return ((SoftReference)cache).get();
- }
- }
}
/**
diff --git a/src/java.base/share/classes/java/lang/invoke/MemberName.java b/src/java.base/share/classes/java/lang/invoke/MemberName.java
index 35fd26331b1..918d1b10791 100644
--- a/src/java.base/share/classes/java/lang/invoke/MemberName.java
+++ b/src/java.base/share/classes/java/lang/invoke/MemberName.java
@@ -711,7 +711,7 @@ final class MemberName implements Member, Cloneable {
}
@Override
- @SuppressWarnings("removal")
+ @SuppressWarnings("deprecation")
public int hashCode() {
// Avoid autoboxing getReferenceKind(), since this is used early and will force
// early initialization of Byte$ByteCache
diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
index 9df7d25258d..0db7a6a8ddb 100644
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2025, 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
@@ -665,22 +665,4 @@ class MethodHandleNatives {
return (definingClass.isAssignableFrom(symbolicRefClass) || // Msym overrides Mdef
symbolicRefClass.isInterface()); // Mdef implements Msym
}
-
- //--- AOTCache support
-
- /**
- * In normal execution, this is set to true, so that LambdaFormEditor and MethodTypeForm will
- * use soft references to allow class unloading.
- *
- * When dumping the AOTCache, this is set to false so that no cached heap objects will
- * contain soft references (which are not yet supported by AOTCache - see JDK-8341587). AOTCache
- * only stores LambdaFormEditors and MethodTypeForms for classes in the boot/platform/app loaders.
- * Such classes will never be unloaded, so it's OK to use hard references.
- */
- static final boolean USE_SOFT_CACHE;
-
- static {
- USE_SOFT_CACHE = Boolean.parseBoolean(
- System.getProperty("java.lang.invoke.MethodHandleNatives.USE_SOFT_CACHE", "true"));
- }
}
diff --git a/src/java.base/share/classes/java/lang/invoke/MethodType.java b/src/java.base/share/classes/java/lang/invoke/MethodType.java
index 5e1c0f8581c..3d15ce68710 100644
--- a/src/java.base/share/classes/java/lang/invoke/MethodType.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2025, 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
@@ -31,8 +31,6 @@ import java.lang.constant.MethodTypeDesc;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.Supplier;
-import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -42,7 +40,6 @@ import java.util.concurrent.ConcurrentHashMap;
import jdk.internal.util.ReferencedKeySet;
import jdk.internal.util.ReferenceKey;
-import jdk.internal.misc.CDS;
import jdk.internal.vm.annotation.Stable;
import sun.invoke.util.BytecodeDescriptor;
import sun.invoke.util.VerifyType;
@@ -394,17 +391,6 @@ class MethodType
ptypes = NO_PTYPES; trusted = true;
}
MethodType primordialMT = new MethodType(rtype, ptypes);
- if (archivedMethodTypes != null) {
- // If this JVM process reads from archivedMethodTypes, it never
- // modifies the table. So there's no need for synchronization.
- // See copyInternTable() below.
- assert CDS.isUsingArchive();
- MethodType mt = archivedMethodTypes.get(primordialMT);
- if (mt != null) {
- return mt;
- }
- }
-
MethodType mt = internTable.get(primordialMT);
if (mt != null)
return mt;
@@ -425,7 +411,6 @@ class MethodType
}
private static final @Stable MethodType[] objectOnlyTypes = new MethodType[20];
- private static @Stable HashMap archivedMethodTypes;
/**
* Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
@@ -1397,29 +1382,9 @@ s.writeObject(this.parameterArray());
return mt;
}
- static HashMap copyInternTable() {
- HashMap copy = new HashMap<>();
-
- for (Iterator i = internTable.iterator(); i.hasNext(); ) {
- MethodType t = i.next();
- copy.put(t, t);
- }
-
- return copy;
- }
-
// This is called from C code, at the very end of Java code execution
// during the AOT cache assembly phase.
- static void createArchivedObjects() {
- // After the archivedMethodTypes field is assigned, this table
- // is never modified. So we don't need synchronization when reading from
- // it (which happens only in a future JVM process, never in the current process).
- //
- // @implNote CDS.isDumpingStaticArchive() is mutually exclusive with
- // CDS.isUsingArchive(); at most one of them can return true for any given JVM
- // process.
- assert CDS.isDumpingStaticArchive();
- archivedMethodTypes = copyInternTable();
- internTable.clear();
+ private static void assemblySetup() {
+ internTable.prepareForAOTCache();
}
}
diff --git a/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java b/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java
index 8bbc4dd5f72..d5272337585 100644
--- a/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java
@@ -30,7 +30,6 @@ import sun.invoke.util.Wrapper;
import java.lang.ref.SoftReference;
import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
-import static java.lang.invoke.MethodHandleNatives.USE_SOFT_CACHE;
/**
* Shared information for a group of method types, which differ
@@ -52,7 +51,7 @@ final class MethodTypeForm {
final MethodType basicType; // the canonical erasure, with primitives simplified
// Cached adapter information:
- private final Object[] methodHandles;
+ private final SoftReference[] methodHandles;
// Indexes into methodHandles:
static final int
@@ -62,7 +61,7 @@ final class MethodTypeForm {
MH_LIMIT = 3;
// Cached lambda form information, for basic types only:
- private final Object[] lambdaForms;
+ private final SoftReference[] lambdaForms;
private SoftReference interpretEntry;
@@ -111,16 +110,9 @@ final class MethodTypeForm {
return basicType;
}
- @SuppressWarnings("unchecked")
public MethodHandle cachedMethodHandle(int which) {
- Object entry = methodHandles[which];
- if (entry == null) {
- return null;
- } else if (entry instanceof MethodHandle mh) {
- return mh;
- } else {
- return ((SoftReference)entry).get();
- }
+ SoftReference entry = methodHandles[which];
+ return (entry != null) ? entry.get() : null;
}
public synchronized MethodHandle setCachedMethodHandle(int which, MethodHandle mh) {
@@ -129,24 +121,13 @@ final class MethodTypeForm {
if (prev != null) {
return prev;
}
- if (USE_SOFT_CACHE) {
- methodHandles[which] = new SoftReference<>(mh);
- } else {
- methodHandles[which] = mh;
- }
+ methodHandles[which] = new SoftReference<>(mh);
return mh;
}
- @SuppressWarnings("unchecked")
public LambdaForm cachedLambdaForm(int which) {
- Object entry = lambdaForms[which];
- if (entry == null) {
- return null;
- } else if (entry instanceof LambdaForm lf) {
- return lf;
- } else {
- return ((SoftReference)entry).get();
- }
+ SoftReference entry = lambdaForms[which];
+ return (entry != null) ? entry.get() : null;
}
public synchronized LambdaForm setCachedLambdaForm(int which, LambdaForm form) {
@@ -155,11 +136,7 @@ final class MethodTypeForm {
if (prev != null) {
return prev;
}
- if (USE_SOFT_CACHE) {
- lambdaForms[which] = new SoftReference<>(form);
- } else {
- lambdaForms[which] = form;
- }
+ lambdaForms[which] = new SoftReference<>(form);
return form;
}
@@ -181,6 +158,7 @@ final class MethodTypeForm {
* This MTF will stand for that type and all un-erased variations.
* Eagerly compute some basic properties of the type, common to all variations.
*/
+ @SuppressWarnings({"rawtypes", "unchecked"})
protected MethodTypeForm(MethodType erasedType) {
this.erasedType = erasedType;
@@ -221,8 +199,8 @@ final class MethodTypeForm {
this.primitiveCount = primitiveCount;
this.parameterSlotCount = (short)pslotCount;
- this.lambdaForms = new Object[LF_LIMIT];
- this.methodHandles = new Object[MH_LIMIT];
+ this.lambdaForms = new SoftReference[LF_LIMIT];
+ this.methodHandles = new SoftReference[MH_LIMIT];
} else {
this.basicType = MethodType.methodType(basicReturnType, basicPtypes, true);
// fill in rest of data from the basic type:
diff --git a/src/java.base/share/classes/java/lang/ref/Reference.java b/src/java.base/share/classes/java/lang/ref/Reference.java
index 13ba76e5dd2..e109b974adc 100644
--- a/src/java.base/share/classes/java/lang/ref/Reference.java
+++ b/src/java.base/share/classes/java/lang/ref/Reference.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2025, 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
@@ -76,10 +76,10 @@ public abstract sealed class Reference
* indicate end of list.
*
* Dequeued: Added to the associated queue and then removed.
- * queue = ReferenceQueue.NULL; next = this.
+ * queue = ReferenceQueue.NULL_QUEUE; next = this.
*
* Unregistered: Not associated with a queue when created.
- * queue = ReferenceQueue.NULL.
+ * queue = ReferenceQueue.NULL_QUEUE.
*
* The collector only needs to examine the referent field and the
* discovered field to determine whether a (non-FinalReference) Reference
@@ -161,8 +161,8 @@ public abstract sealed class Reference
*
* When registered: the queue with which this reference is registered.
* enqueued: ReferenceQueue.ENQUEUE
- * dequeued: ReferenceQueue.NULL
- * unregistered: ReferenceQueue.NULL
+ * dequeued: ReferenceQueue.NULL_QUEUE
+ * unregistered: ReferenceQueue.NULL_QUEUE
*/
volatile ReferenceQueue super T> queue;
@@ -232,7 +232,7 @@ public abstract sealed class Reference
*/
private void enqueueFromPending() {
var q = queue;
- if (q != ReferenceQueue.NULL) q.enqueue(this);
+ if (q != ReferenceQueue.NULL_QUEUE) q.enqueue(this);
}
private static final Object processPendingLock = new Object();
@@ -306,7 +306,12 @@ public abstract sealed class Reference
handler.start();
}
+ // Called from JVM when loading an AOT cache
static {
+ runtimeSetup();
+ }
+
+ private static void runtimeSetup() {
// provide access in SharedSecrets
SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {
@Override
@@ -540,7 +545,7 @@ public abstract sealed class Reference
Reference(T referent, ReferenceQueue super T> queue) {
this.referent = referent;
- this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
+ this.queue = (queue == null) ? ReferenceQueue.NULL_QUEUE : queue;
}
/**
diff --git a/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java b/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java
index 07110a19fa1..4dcaf796e25 100644
--- a/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java
+++ b/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2025, 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
@@ -55,7 +55,7 @@ public class ReferenceQueue {
}
}
- static final ReferenceQueue