Test framework. The top directory, which contains both
googletest and googlemock directories, should
be specified via --with-gtest. The minimum supported
-version of Google Test is 1.13.0, whose source code can be obtained:
+version of Google Test is 1.14.0, whose source code can be obtained:
by downloading and unpacking the source bundle from here
-
or by checking out v1.13.0 tag of
+href="https://github.com/google/googletest/releases/tag/v1.14.0">here
+
or by checking out v1.14.0 tag of
googletest project:
-git clone -b v1.13.0 https://github.com/google/googletest
diff --git a/doc/building.md b/doc/building.md
index e2504d12b4a44..1274810c2d5c4 100644
--- a/doc/building.md
+++ b/doc/building.md
@@ -884,11 +884,11 @@ Download the latest `.tar.gz` file, unpack it, and point `--with-jtreg` to the
Building of Hotspot Gtest suite requires the source code of Google
Test framework. The top directory, which contains both `googletest`
and `googlemock` directories, should be specified via `--with-gtest`.
-The minimum supported version of Google Test is 1.13.0, whose source
+The minimum supported version of Google Test is 1.14.0, whose source
code can be obtained:
- * by downloading and unpacking the source bundle from [here](https://github.com/google/googletest/releases/tag/v1.13.0)
- * or by checking out `v1.13.0` tag of `googletest` project: `git clone -b v1.13.0 https://github.com/google/googletest`
+ * by downloading and unpacking the source bundle from [here](https://github.com/google/googletest/releases/tag/v1.14.0)
+ * or by checking out `v1.14.0` tag of `googletest` project: `git clone -b v1.14.0 https://github.com/google/googletest`
To execute the most basic tests (tier 1), use:
```
diff --git a/make/Docs.gmk b/make/Docs.gmk
index 183318ec4352e..a9985ffa4d864 100644
--- a/make/Docs.gmk
+++ b/make/Docs.gmk
@@ -67,7 +67,6 @@ MODULES_SOURCE_PATH := $(call PathList, $(call GetModuleSrcPath) )
# ordering of tags as the tags are otherwise ordered in order of definition.
JAVADOC_TAGS := \
-tag beaninfo:X \
- -tag revised:X \
-tag since.unbundled:X \
-tag Note:X \
-tag ToDo:X \
diff --git a/make/Main.gmk b/make/Main.gmk
index e13e6f47386ba..94d6610650721 100644
--- a/make/Main.gmk
+++ b/make/Main.gmk
@@ -967,11 +967,15 @@ else
jdk.compiler-gendata: $(GENSRC_MODULEINFO_TARGETS)
# Declare dependencies between jmod targets.
- # java.base jmod needs jrt-fs.jar and access to the other jmods to be built.
+ # java.base jmod needs jrt-fs.jar and access to the jmods for all non
+ # upgradeable modules and their transitive dependencies.
# When creating the BUILDJDK, we don't need to add hashes to java.base, thus
# we don't need to depend on all other jmods
ifneq ($(CREATING_BUILDJDK), true)
- java.base-jmod: jrtfs-jar $(filter-out java.base-jmod, $(JMOD_TARGETS))
+ java.base-jmod: jrtfs-jar $(addsuffix -jmod, $(filter-out java.base, $(sort \
+ $(foreach m, $(filter-out $(call FindAllUpgradeableModules), $(JMOD_MODULES)), \
+ $m $(call FindTransitiveDepsForModules, $m) \
+ ))))
endif
# If not already set, set the JVM target so that the JVM will be built.
diff --git a/make/autoconf/flags-ldflags.m4 b/make/autoconf/flags-ldflags.m4
index b63a8727a34e6..195c1d341595f 100644
--- a/make/autoconf/flags-ldflags.m4
+++ b/make/autoconf/flags-ldflags.m4
@@ -60,7 +60,8 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
# Add -z,defs, to forbid undefined symbols in object files.
# add -z,relro (mark relocations read only) for all libs
# add -z,now ("full relro" - more of the Global Offset Table GOT is marked read only)
- BASIC_LDFLAGS="-Wl,-z,defs -Wl,-z,relro -Wl,-z,now"
+ # add --no-as-needed to disable default --as-needed link flag on some GCC toolchains
+ BASIC_LDFLAGS="-Wl,-z,defs -Wl,-z,relro -Wl,-z,now -Wl,--no-as-needed"
# Linux : remove unused code+data in link step
if test "x$ENABLE_LINKTIME_GC" = xtrue; then
if test "x$OPENJDK_TARGET_CPU" = xs390x; then
diff --git a/make/autoconf/lib-tests.m4 b/make/autoconf/lib-tests.m4
index 3db1737eb1319..aecea86b74474 100644
--- a/make/autoconf/lib-tests.m4
+++ b/make/autoconf/lib-tests.m4
@@ -28,8 +28,8 @@
################################################################################
# Minimum supported versions
-JTREG_MINIMUM_VERSION=7.3
-GTEST_MINIMUM_VERSION=1.13.0
+JTREG_MINIMUM_VERSION=7.3.1
+GTEST_MINIMUM_VERSION=1.14.0
###############################################################################
#
diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk
index 8609fc4ca00d1..e97d8767ce238 100644
--- a/make/common/NativeCompilation.gmk
+++ b/make/common/NativeCompilation.gmk
@@ -215,7 +215,21 @@ DEPENDENCY_TARGET_SED_PATTERN := \
# The fix-deps-file macro is used to adjust the contents of the generated make
# dependency files to contain paths compatible with make.
#
+REWRITE_PATHS_RELATIVE = false
ifeq ($(ALLOW_ABSOLUTE_PATHS_IN_OUTPUT)-$(FILE_MACRO_CFLAGS), false-)
+ REWRITE_PATHS_RELATIVE = true
+endif
+
+# CCACHE_BASEDIR needs fix-deps-file as makefiles use absolute filenames for
+# object files while CCACHE_BASEDIR will make ccache relativize all paths for
+# its compiler. The compiler then produces relative dependency files.
+# make does not know a relative and absolute filename is the same so it will
+# ignore such dependencies.
+ifneq ($(CCACHE), )
+ REWRITE_PATHS_RELATIVE = true
+endif
+
+ifeq ($(REWRITE_PATHS_RELATIVE), true)
# Need to handle -I flags as both '-Ifoo' and '-I foo'.
MakeCommandRelative = \
$(CD) $(WORKSPACE_ROOT) && \
diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf
index 2dfc9b534899c..f10095daa6c9c 100644
--- a/make/conf/github-actions.conf
+++ b/make/conf/github-actions.conf
@@ -25,8 +25,8 @@
# Versions and download locations for dependencies used by GitHub Actions (GHA)
-GTEST_VERSION=1.13.0
-JTREG_VERSION=7.3+1
+GTEST_VERSION=1.14.0
+JTREG_VERSION=7.3.1+1
LINUX_X64_BOOT_JDK_EXT=tar.gz
LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk20/bdc68b4b9cbc4ebcb30745c85038d91d/36/GPL/openjdk-20_linux-x64_bin.tar.gz
diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js
index 665c350a7a397..043b935f361f3 100644
--- a/make/conf/jib-profiles.js
+++ b/make/conf/jib-profiles.js
@@ -1188,9 +1188,9 @@ var getJibProfilesDependencies = function (input, common) {
jtreg: {
server: "jpg",
product: "jtreg",
- version: "7.3",
+ version: "7.3.1",
build_number: "1",
- file: "bundles/jtreg-7.3+1.zip",
+ file: "bundles/jtreg-7.3.1+1.zip",
environment_name: "JT_HOME",
environment_path: input.get("jtreg", "home_path") + "/bin",
configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"),
@@ -1199,7 +1199,7 @@ var getJibProfilesDependencies = function (input, common) {
jmh: {
organization: common.organization,
ext: "tar.gz",
- revision: "1.35+1.0"
+ revision: "1.37+1.0"
},
jcov: {
@@ -1270,7 +1270,7 @@ var getJibProfilesDependencies = function (input, common) {
gtest: {
organization: common.organization,
ext: "tar.gz",
- revision: "1.13.0+1.0"
+ revision: "1.14.0+1.0"
},
libffi: {
diff --git a/make/devkit/createJMHBundle.sh b/make/devkit/createJMHBundle.sh
index af29a0917d606..c3c97947dabf0 100644
--- a/make/devkit/createJMHBundle.sh
+++ b/make/devkit/createJMHBundle.sh
@@ -26,8 +26,8 @@
# Create a bundle in the build directory, containing what's needed to
# build and run JMH microbenchmarks from the OpenJDK build.
-JMH_VERSION=1.36
-COMMONS_MATH3_VERSION=3.2
+JMH_VERSION=1.37
+COMMONS_MATH3_VERSION=3.6.1
JOPT_SIMPLE_VERSION=5.0.4
BUNDLE_NAME=jmh-$JMH_VERSION.tar.gz
diff --git a/make/hotspot/lib/JvmMapfile.gmk b/make/hotspot/lib/JvmMapfile.gmk
index 2808ac2af0372..b2199e7d17c6f 100644
--- a/make/hotspot/lib/JvmMapfile.gmk
+++ b/make/hotspot/lib/JvmMapfile.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -118,7 +118,7 @@ else ifeq ($(call isTargetOs, windows), true)
FILTER_SYMBOLS_AWK_SCRIPT := \
'{ \
- if ($$7 ~ /??_7.*@@6B@/ && $$7 !~ /type_info/ && $$7 !~ /lambda/) print $$7; \
+ if ($$7 ~ /\?\?_7.*@@6B@/ && $$7 !~ /type_info/ && $$7 !~ /lambda/) print $$7; \
}'
else
diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad
index d8e7a977a5472..9de1f841e9be1 100644
--- a/src/hotspot/cpu/aarch64/aarch64.ad
+++ b/src/hotspot/cpu/aarch64/aarch64.ad
@@ -2289,7 +2289,6 @@ bool Matcher::match_rule_supported(int opcode) {
if (!has_match_rule(opcode))
return false;
- bool ret_value = true;
switch (opcode) {
case Op_OnSpinWait:
return VM_Version::supports_on_spin_wait();
@@ -2297,18 +2296,26 @@ bool Matcher::match_rule_supported(int opcode) {
case Op_CacheWBPreSync:
case Op_CacheWBPostSync:
if (!VM_Version::supports_data_cache_line_flush()) {
- ret_value = false;
+ return false;
}
break;
case Op_ExpandBits:
case Op_CompressBits:
if (!VM_Version::supports_svebitperm()) {
- ret_value = false;
+ return false;
+ }
+ break;
+ case Op_FmaF:
+ case Op_FmaD:
+ case Op_FmaVF:
+ case Op_FmaVD:
+ if (!UseFMA) {
+ return false;
}
break;
}
- return ret_value; // Per default match rules are supported.
+ return true; // Per default match rules are supported.
}
const RegMask* Matcher::predicate_reg_mask(void) {
@@ -14321,12 +14328,12 @@ instruct mulD_reg_reg(vRegD dst, vRegD src1, vRegD src2) %{
// src1 * src2 + src3
instruct maddF_reg_reg(vRegF dst, vRegF src1, vRegF src2, vRegF src3) %{
- predicate(UseFMA);
match(Set dst (FmaF src3 (Binary src1 src2)));
format %{ "fmadds $dst, $src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmadds(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -14338,12 +14345,12 @@ instruct maddF_reg_reg(vRegF dst, vRegF src1, vRegF src2, vRegF src3) %{
// src1 * src2 + src3
instruct maddD_reg_reg(vRegD dst, vRegD src1, vRegD src2, vRegD src3) %{
- predicate(UseFMA);
match(Set dst (FmaD src3 (Binary src1 src2)));
format %{ "fmaddd $dst, $src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmaddd(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -14353,15 +14360,15 @@ instruct maddD_reg_reg(vRegD dst, vRegD src1, vRegD src2, vRegD src3) %{
ins_pipe(pipe_class_default);
%}
-// -src1 * src2 + src3
+// src1 * (-src2) + src3
+// "(-src1) * src2 + src3" has been idealized to "src2 * (-src1) + src3"
instruct msubF_reg_reg(vRegF dst, vRegF src1, vRegF src2, vRegF src3) %{
- predicate(UseFMA);
- match(Set dst (FmaF src3 (Binary (NegF src1) src2)));
match(Set dst (FmaF src3 (Binary src1 (NegF src2))));
format %{ "fmsubs $dst, $src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmsubs(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -14371,15 +14378,15 @@ instruct msubF_reg_reg(vRegF dst, vRegF src1, vRegF src2, vRegF src3) %{
ins_pipe(pipe_class_default);
%}
-// -src1 * src2 + src3
+// src1 * (-src2) + src3
+// "(-src1) * src2 + src3" has been idealized to "src2 * (-src1) + src3"
instruct msubD_reg_reg(vRegD dst, vRegD src1, vRegD src2, vRegD src3) %{
- predicate(UseFMA);
- match(Set dst (FmaD src3 (Binary (NegD src1) src2)));
match(Set dst (FmaD src3 (Binary src1 (NegD src2))));
format %{ "fmsubd $dst, $src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmsubd(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -14389,15 +14396,15 @@ instruct msubD_reg_reg(vRegD dst, vRegD src1, vRegD src2, vRegD src3) %{
ins_pipe(pipe_class_default);
%}
-// -src1 * src2 - src3
+// src1 * (-src2) - src3
+// "(-src1) * src2 - src3" has been idealized to "src2 * (-src1) - src3"
instruct mnaddF_reg_reg(vRegF dst, vRegF src1, vRegF src2, vRegF src3) %{
- predicate(UseFMA);
- match(Set dst (FmaF (NegF src3) (Binary (NegF src1) src2)));
match(Set dst (FmaF (NegF src3) (Binary src1 (NegF src2))));
format %{ "fnmadds $dst, $src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fnmadds(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -14407,15 +14414,15 @@ instruct mnaddF_reg_reg(vRegF dst, vRegF src1, vRegF src2, vRegF src3) %{
ins_pipe(pipe_class_default);
%}
-// -src1 * src2 - src3
+// src1 * (-src2) - src3
+// "(-src1) * src2 - src3" has been idealized to "src2 * (-src1) - src3"
instruct mnaddD_reg_reg(vRegD dst, vRegD src1, vRegD src2, vRegD src3) %{
- predicate(UseFMA);
- match(Set dst (FmaD (NegD src3) (Binary (NegD src1) src2)));
match(Set dst (FmaD (NegD src3) (Binary src1 (NegD src2))));
format %{ "fnmaddd $dst, $src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fnmaddd(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -14427,12 +14434,12 @@ instruct mnaddD_reg_reg(vRegD dst, vRegD src1, vRegD src2, vRegD src3) %{
// src1 * src2 - src3
instruct mnsubF_reg_reg(vRegF dst, vRegF src1, vRegF src2, vRegF src3, immF0 zero) %{
- predicate(UseFMA);
match(Set dst (FmaF (NegF src3) (Binary src1 src2)));
format %{ "fnmsubs $dst, $src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fnmsubs(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -14444,13 +14451,13 @@ instruct mnsubF_reg_reg(vRegF dst, vRegF src1, vRegF src2, vRegF src3, immF0 zer
// src1 * src2 - src3
instruct mnsubD_reg_reg(vRegD dst, vRegD src1, vRegD src2, vRegD src3, immD0 zero) %{
- predicate(UseFMA);
match(Set dst (FmaD (NegD src3) (Binary src1 src2)));
format %{ "fnmsubd $dst, $src1, $src2, $src3" %}
ins_encode %{
- // n.b. insn name should be fnmsubd
+ assert(UseFMA, "Needs FMA instructions support.");
+ // n.b. insn name should be fnmsubd
__ fnmsub(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
diff --git a/src/hotspot/cpu/aarch64/aarch64_vector.ad b/src/hotspot/cpu/aarch64/aarch64_vector.ad
index bd669e9943552..a0df8fc3c973c 100644
--- a/src/hotspot/cpu/aarch64/aarch64_vector.ad
+++ b/src/hotspot/cpu/aarch64/aarch64_vector.ad
@@ -2131,14 +2131,14 @@ instruct vmla_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
%}
// vector fmla
-// dst_src1 = dst_src1 + src2 * src3
+// dst_src1 = src2 * src3 + dst_src1
instruct vfmla(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
match(Set dst_src1 (FmaVF dst_src1 (Binary src2 src3)));
match(Set dst_src1 (FmaVD dst_src1 (Binary src2 src3)));
format %{ "vfmla $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
if (VM_Version::use_neon_for_vector(length_in_bytes)) {
__ fmla($dst_src1$$FloatRegister, get_arrangement(this),
@@ -2157,11 +2157,12 @@ instruct vfmla(vReg dst_src1, vReg src2, vReg src3) %{
// dst_src1 = dst_src1 * src2 + src3
instruct vfmad_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
- predicate(UseFMA && UseSVE > 0);
+ predicate(UseSVE > 0);
match(Set dst_src1 (FmaVF (Binary dst_src1 src2) (Binary src3 pg)));
match(Set dst_src1 (FmaVD (Binary dst_src1 src2) (Binary src3 pg)));
format %{ "vfmad_masked $dst_src1, $pg, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ sve_fmad($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
$pg$$PRegister, $src2$$FloatRegister, $src3$$FloatRegister);
@@ -2221,34 +2222,14 @@ instruct vmls_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
// vector fmls
-// dst_src1 = dst_src1 + -src2 * src3
-instruct vfmls1(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
- match(Set dst_src1 (FmaVF dst_src1 (Binary (NegVF src2) src3)));
- match(Set dst_src1 (FmaVD dst_src1 (Binary (NegVD src2) src3)));
- format %{ "vfmls1 $dst_src1, $src2, $src3" %}
- ins_encode %{
- uint length_in_bytes = Matcher::vector_length_in_bytes(this);
- if (VM_Version::use_neon_for_vector(length_in_bytes)) {
- __ fmls($dst_src1$$FloatRegister, get_arrangement(this),
- $src2$$FloatRegister, $src3$$FloatRegister);
- } else {
- assert(UseSVE > 0, "must be sve");
- BasicType bt = Matcher::vector_element_basic_type(this);
- __ sve_fmls($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
- ptrue, $src2$$FloatRegister, $src3$$FloatRegister);
- }
- %}
- ins_pipe(pipe_slow);
-%}
-
-// dst_src1 = dst_src1 + src2 * -src3
-instruct vfmls2(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
+// dst_src1 = src2 * (-src3) + dst_src1
+// "(-src2) * src3 + dst_src1" has been idealized to "src3 * (-src2) + dst_src1"
+instruct vfmls(vReg dst_src1, vReg src2, vReg src3) %{
match(Set dst_src1 (FmaVF dst_src1 (Binary src2 (NegVF src3))));
match(Set dst_src1 (FmaVD dst_src1 (Binary src2 (NegVD src3))));
- format %{ "vfmls2 $dst_src1, $src2, $src3" %}
+ format %{ "vfmls $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
if (VM_Version::use_neon_for_vector(length_in_bytes)) {
__ fmls($dst_src1$$FloatRegister, get_arrangement(this),
@@ -2265,13 +2246,14 @@ instruct vfmls2(vReg dst_src1, vReg src2, vReg src3) %{
// vector fmsb - predicated
-// dst_src1 = dst_src1 * -src2 + src3
+// dst_src1 = dst_src1 * (-src2) + src3
instruct vfmsb_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
- predicate(UseFMA && UseSVE > 0);
+ predicate(UseSVE > 0);
match(Set dst_src1 (FmaVF (Binary dst_src1 (NegVF src2)) (Binary src3 pg)));
match(Set dst_src1 (FmaVD (Binary dst_src1 (NegVD src2)) (Binary src3 pg)));
format %{ "vfmsb_masked $dst_src1, $pg, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ sve_fmsb($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
$pg$$PRegister, $src2$$FloatRegister, $src3$$FloatRegister);
@@ -2281,27 +2263,15 @@ instruct vfmsb_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
// vector fnmla (sve)
-// dst_src1 = -dst_src1 + -src2 * src3
-instruct vfnmla1(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA && UseSVE > 0);
- match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary (NegVF src2) src3)));
- match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary (NegVD src2) src3)));
- format %{ "vfnmla1 $dst_src1, $src2, $src3" %}
- ins_encode %{
- BasicType bt = Matcher::vector_element_basic_type(this);
- __ sve_fnmla($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
- ptrue, $src2$$FloatRegister, $src3$$FloatRegister);
- %}
- ins_pipe(pipe_slow);
-%}
-
-// dst_src1 = -dst_src1 + src2 * -src3
-instruct vfnmla2(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA && UseSVE > 0);
+// dst_src1 = src2 * (-src3) - dst_src1
+// "(-src2) * src3 - dst_src1" has been idealized to "src3 * (-src2) - dst_src1"
+instruct vfnmla(vReg dst_src1, vReg src2, vReg src3) %{
+ predicate(UseSVE > 0);
match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 (NegVF src3))));
match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 (NegVD src3))));
- format %{ "vfnmla2 $dst_src1, $src2, $src3" %}
+ format %{ "vfnmla $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ sve_fnmla($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
ptrue, $src2$$FloatRegister, $src3$$FloatRegister);
@@ -2311,13 +2281,14 @@ instruct vfnmla2(vReg dst_src1, vReg src2, vReg src3) %{
// vector fnmad - predicated
-// dst_src1 = -src3 + dst_src1 * -src2
+// dst_src1 = dst_src1 * (-src2) - src3
instruct vfnmad_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
- predicate(UseFMA && UseSVE > 0);
+ predicate(UseSVE > 0);
match(Set dst_src1 (FmaVF (Binary dst_src1 (NegVF src2)) (Binary (NegVF src3) pg)));
match(Set dst_src1 (FmaVD (Binary dst_src1 (NegVD src2)) (Binary (NegVD src3) pg)));
format %{ "vfnmad_masked $dst_src1, $pg, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ sve_fnmad($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
$pg$$PRegister, $src2$$FloatRegister, $src3$$FloatRegister);
@@ -2327,13 +2298,14 @@ instruct vfnmad_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
// vector fnmls (sve)
-// dst_src1 = -dst_src1 + src2 * src3
+// dst_src1 = src2 * src3 - dst_src1
instruct vfnmls(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA && UseSVE > 0);
+ predicate(UseSVE > 0);
match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 src3)));
match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 src3)));
format %{ "vfnmls $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ sve_fnmls($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
ptrue, $src2$$FloatRegister, $src3$$FloatRegister);
@@ -2343,13 +2315,14 @@ instruct vfnmls(vReg dst_src1, vReg src2, vReg src3) %{
// vector fnmsb - predicated
-// dst_src1 = -src3 + dst_src1 * src2
+// dst_src1 = dst_src1 * src2 - src3
instruct vfnmsb_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
- predicate(UseFMA && UseSVE > 0);
+ predicate(UseSVE > 0);
match(Set dst_src1 (FmaVF (Binary dst_src1 src2) (Binary (NegVF src3) pg)));
match(Set dst_src1 (FmaVD (Binary dst_src1 src2) (Binary (NegVD src3) pg)));
format %{ "vfnmsb_masked $dst_src1, $pg, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ sve_fnmsb($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
$pg$$PRegister, $src2$$FloatRegister, $src3$$FloatRegister);
diff --git a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4
index 4a2c5947d1a0e..cb22e96dc8f03 100644
--- a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4
+++ b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4
@@ -1173,14 +1173,14 @@ instruct vmla_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
%}
// vector fmla
-// dst_src1 = dst_src1 + src2 * src3
+// dst_src1 = src2 * src3 + dst_src1
instruct vfmla(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
match(Set dst_src1 (FmaVF dst_src1 (Binary src2 src3)));
match(Set dst_src1 (FmaVD dst_src1 (Binary src2 src3)));
format %{ "vfmla $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
if (VM_Version::use_neon_for_vector(length_in_bytes)) {
__ fmla($dst_src1$$FloatRegister, get_arrangement(this),
@@ -1199,11 +1199,12 @@ instruct vfmla(vReg dst_src1, vReg src2, vReg src3) %{
// dst_src1 = dst_src1 * src2 + src3
instruct vfmad_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
- predicate(UseFMA && UseSVE > 0);
+ predicate(UseSVE > 0);
match(Set dst_src1 (FmaVF (Binary dst_src1 src2) (Binary src3 pg)));
match(Set dst_src1 (FmaVD (Binary dst_src1 src2) (Binary src3 pg)));
format %{ "vfmad_masked $dst_src1, $pg, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ sve_fmad($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
$pg$$PRegister, $src2$$FloatRegister, $src3$$FloatRegister);
@@ -1263,34 +1264,14 @@ instruct vmls_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
// vector fmls
-// dst_src1 = dst_src1 + -src2 * src3
-instruct vfmls1(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
- match(Set dst_src1 (FmaVF dst_src1 (Binary (NegVF src2) src3)));
- match(Set dst_src1 (FmaVD dst_src1 (Binary (NegVD src2) src3)));
- format %{ "vfmls1 $dst_src1, $src2, $src3" %}
- ins_encode %{
- uint length_in_bytes = Matcher::vector_length_in_bytes(this);
- if (VM_Version::use_neon_for_vector(length_in_bytes)) {
- __ fmls($dst_src1$$FloatRegister, get_arrangement(this),
- $src2$$FloatRegister, $src3$$FloatRegister);
- } else {
- assert(UseSVE > 0, "must be sve");
- BasicType bt = Matcher::vector_element_basic_type(this);
- __ sve_fmls($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
- ptrue, $src2$$FloatRegister, $src3$$FloatRegister);
- }
- %}
- ins_pipe(pipe_slow);
-%}
-
-// dst_src1 = dst_src1 + src2 * -src3
-instruct vfmls2(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
+// dst_src1 = src2 * (-src3) + dst_src1
+// "(-src2) * src3 + dst_src1" has been idealized to "src3 * (-src2) + dst_src1"
+instruct vfmls(vReg dst_src1, vReg src2, vReg src3) %{
match(Set dst_src1 (FmaVF dst_src1 (Binary src2 (NegVF src3))));
match(Set dst_src1 (FmaVD dst_src1 (Binary src2 (NegVD src3))));
- format %{ "vfmls2 $dst_src1, $src2, $src3" %}
+ format %{ "vfmls $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
if (VM_Version::use_neon_for_vector(length_in_bytes)) {
__ fmls($dst_src1$$FloatRegister, get_arrangement(this),
@@ -1307,13 +1288,14 @@ instruct vfmls2(vReg dst_src1, vReg src2, vReg src3) %{
// vector fmsb - predicated
-// dst_src1 = dst_src1 * -src2 + src3
+// dst_src1 = dst_src1 * (-src2) + src3
instruct vfmsb_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
- predicate(UseFMA && UseSVE > 0);
+ predicate(UseSVE > 0);
match(Set dst_src1 (FmaVF (Binary dst_src1 (NegVF src2)) (Binary src3 pg)));
match(Set dst_src1 (FmaVD (Binary dst_src1 (NegVD src2)) (Binary src3 pg)));
format %{ "vfmsb_masked $dst_src1, $pg, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ sve_fmsb($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
$pg$$PRegister, $src2$$FloatRegister, $src3$$FloatRegister);
@@ -1323,27 +1305,15 @@ instruct vfmsb_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
// vector fnmla (sve)
-// dst_src1 = -dst_src1 + -src2 * src3
-instruct vfnmla1(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA && UseSVE > 0);
- match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary (NegVF src2) src3)));
- match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary (NegVD src2) src3)));
- format %{ "vfnmla1 $dst_src1, $src2, $src3" %}
- ins_encode %{
- BasicType bt = Matcher::vector_element_basic_type(this);
- __ sve_fnmla($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
- ptrue, $src2$$FloatRegister, $src3$$FloatRegister);
- %}
- ins_pipe(pipe_slow);
-%}
-
-// dst_src1 = -dst_src1 + src2 * -src3
-instruct vfnmla2(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA && UseSVE > 0);
+// dst_src1 = src2 * (-src3) - dst_src1
+// "(-src2) * src3 - dst_src1" has been idealized to "src3 * (-src2) - dst_src1"
+instruct vfnmla(vReg dst_src1, vReg src2, vReg src3) %{
+ predicate(UseSVE > 0);
match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 (NegVF src3))));
match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 (NegVD src3))));
- format %{ "vfnmla2 $dst_src1, $src2, $src3" %}
+ format %{ "vfnmla $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ sve_fnmla($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
ptrue, $src2$$FloatRegister, $src3$$FloatRegister);
@@ -1353,13 +1323,14 @@ instruct vfnmla2(vReg dst_src1, vReg src2, vReg src3) %{
// vector fnmad - predicated
-// dst_src1 = -src3 + dst_src1 * -src2
+// dst_src1 = dst_src1 * (-src2) - src3
instruct vfnmad_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
- predicate(UseFMA && UseSVE > 0);
+ predicate(UseSVE > 0);
match(Set dst_src1 (FmaVF (Binary dst_src1 (NegVF src2)) (Binary (NegVF src3) pg)));
match(Set dst_src1 (FmaVD (Binary dst_src1 (NegVD src2)) (Binary (NegVD src3) pg)));
format %{ "vfnmad_masked $dst_src1, $pg, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ sve_fnmad($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
$pg$$PRegister, $src2$$FloatRegister, $src3$$FloatRegister);
@@ -1369,13 +1340,14 @@ instruct vfnmad_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
// vector fnmls (sve)
-// dst_src1 = -dst_src1 + src2 * src3
+// dst_src1 = src2 * src3 - dst_src1
instruct vfnmls(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA && UseSVE > 0);
+ predicate(UseSVE > 0);
match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 src3)));
match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 src3)));
format %{ "vfnmls $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ sve_fnmls($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
ptrue, $src2$$FloatRegister, $src3$$FloatRegister);
@@ -1385,13 +1357,14 @@ instruct vfnmls(vReg dst_src1, vReg src2, vReg src3) %{
// vector fnmsb - predicated
-// dst_src1 = -src3 + dst_src1 * src2
+// dst_src1 = dst_src1 * src2 - src3
instruct vfnmsb_masked(vReg dst_src1, vReg src2, vReg src3, pRegGov pg) %{
- predicate(UseFMA && UseSVE > 0);
+ predicate(UseSVE > 0);
match(Set dst_src1 (FmaVF (Binary dst_src1 src2) (Binary (NegVF src3) pg)));
match(Set dst_src1 (FmaVD (Binary dst_src1 src2) (Binary (NegVD src3) pg)));
format %{ "vfnmsb_masked $dst_src1, $pg, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ sve_fnmsb($dst_src1$$FloatRegister, __ elemType_to_regVariant(bt),
$pg$$PRegister, $src2$$FloatRegister, $src3$$FloatRegister);
diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp
index ad052fe912877..e50f72a630296 100644
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp
@@ -28,6 +28,7 @@
#include "asm/register.hpp"
#include "metaprogramming/enableIf.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
diff --git a/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp
index 4e4aa95e1717a..23a5ad710259c 100644
--- a/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp
+++ b/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp
@@ -83,7 +83,7 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
intptr_t *sp, *fp; // sp is really our unextended_sp
if (FKind::interpreted) {
assert((intptr_t*)f.at(frame::interpreter_frame_last_sp_offset) == nullptr
- || f.unextended_sp() == (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset), "");
+ || f.unextended_sp() == (intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset), "");
intptr_t locals_offset = *f.addr_at(frame::interpreter_frame_locals_offset);
// If the caller.is_empty(), i.e. we're freezing into an empty chunk, then we set
// the chunk's argsize in finalize_freeze and make room for it above the unextended_sp
@@ -123,7 +123,7 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
assert((f.at(frame::interpreter_frame_last_sp_offset) != 0) || (f.unextended_sp() == f.sp()), "");
- intptr_t* real_unextended_sp = (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset);
+ intptr_t* real_unextended_sp = (intptr_t*)f.at_relative_or_null(frame::interpreter_frame_last_sp_offset);
if (real_unextended_sp != nullptr) {
f.set_unextended_sp(real_unextended_sp); // can be null at a safepoint
}
@@ -149,8 +149,8 @@ inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, co
// because we freeze the padding word (see recurse_freeze_interpreted_frame) in order to keep the same relativized
// locals value, we don't need to change the locals value here.
- // at(frame::interpreter_frame_last_sp_offset) can be null at safepoint preempts
- *hf.addr_at(frame::interpreter_frame_last_sp_offset) = hf.unextended_sp() - hf.fp();
+ // Make sure that last_sp is already relativized.
+ assert((intptr_t*)hf.at_relative(frame::interpreter_frame_last_sp_offset) == hf.unextended_sp(), "");
relativize_one(vfp, hfp, frame::interpreter_frame_initial_sp_offset); // == block_top == block_bottom
relativize_one(vfp, hfp, frame::interpreter_frame_extended_sp_offset);
@@ -290,7 +290,9 @@ static inline void derelativize_one(intptr_t* const fp, int offset) {
inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
intptr_t* vfp = f.fp();
- derelativize_one(vfp, frame::interpreter_frame_last_sp_offset);
+ // Make sure that last_sp is kept relativized.
+ assert((intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset) == f.unextended_sp(), "");
+
derelativize_one(vfp, frame::interpreter_frame_initial_sp_offset);
derelativize_one(vfp, frame::interpreter_frame_extended_sp_offset);
}
diff --git a/src/hotspot/cpu/aarch64/continuationHelper_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/continuationHelper_aarch64.inline.hpp
index 7d673eb8d0d29..380053832486c 100644
--- a/src/hotspot/cpu/aarch64/continuationHelper_aarch64.inline.hpp
+++ b/src/hotspot/cpu/aarch64/continuationHelper_aarch64.inline.hpp
@@ -125,7 +125,8 @@ inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f,
assert(res == (intptr_t*)f.interpreter_frame_monitor_end() - expression_stack_sz, "");
assert(res >= f.unextended_sp(),
"res: " INTPTR_FORMAT " initial_sp: " INTPTR_FORMAT " last_sp: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " expression_stack_size: %d",
- p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at(frame::interpreter_frame_last_sp_offset), p2i(f.unextended_sp()), expression_stack_sz);
+ p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at_relative_or_null(frame::interpreter_frame_last_sp_offset),
+ p2i(f.unextended_sp()), expression_stack_sz);
return res;
}
diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp
index 2357721ed3d4c..4ceae831e669a 100644
--- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp
@@ -355,7 +355,9 @@ void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
// Used by template based interpreter deoptimization
void frame::interpreter_frame_set_last_sp(intptr_t* sp) {
- *((intptr_t**)addr_at(interpreter_frame_last_sp_offset)) = sp;
+ assert(is_interpreted_frame(), "interpreted frame expected");
+ // set relativized last_sp
+ ptr_at_put(interpreter_frame_last_sp_offset, sp != nullptr ? (sp - fp()) : 0);
}
// Used by template based interpreter deoptimization
diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp
index 5fc5fe9248e0c..c0ae3cdf2aca3 100644
--- a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp
+++ b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp
@@ -262,7 +262,9 @@ inline intptr_t* frame::interpreter_frame_locals() const {
}
inline intptr_t* frame::interpreter_frame_last_sp() const {
- return (intptr_t*)at(interpreter_frame_last_sp_offset);
+ intptr_t n = *addr_at(interpreter_frame_last_sp_offset);
+ assert(n <= 0, "n: " INTPTR_FORMAT, n);
+ return n != 0 ? &fp()[n] : nullptr;
}
inline intptr_t* frame::interpreter_frame_bcp_addr() const {
diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp
index a86cc40ab5055..823e481178ee5 100644
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp
@@ -430,7 +430,9 @@ void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
// set sender sp
mov(r19_sender_sp, sp);
// record last_sp
- str(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
+ sub(rscratch1, esp, rfp);
+ asr(rscratch1, rscratch1, Interpreter::logStackElementSize);
+ str(rscratch1, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
}
// Jump to from_interpreted entry of a call unless single stepping is possible
diff --git a/src/hotspot/cpu/aarch64/register_aarch64.hpp b/src/hotspot/cpu/aarch64/register_aarch64.hpp
index 286dd83d68750..44892e61e2afd 100644
--- a/src/hotspot/cpu/aarch64/register_aarch64.hpp
+++ b/src/hotspot/cpu/aarch64/register_aarch64.hpp
@@ -27,6 +27,7 @@
#define CPU_AARCH64_REGISTER_AARCH64_HPP
#include "asm/register.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/powerOfTwo.hpp"
class VMRegImpl;
diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
index c08b3c420d708..8d35e20da90c7 100644
--- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
@@ -51,6 +51,7 @@
#include "runtime/stubCodeGenerator.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/powerOfTwo.hpp"
#ifdef COMPILER2
diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
index 0f03c5f9b6fbe..6435e1f8b0766 100644
--- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp
@@ -53,6 +53,7 @@
#include "runtime/synchronizer.hpp"
#include "runtime/timer.hpp"
#include "runtime/vframeArray.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/powerOfTwo.hpp"
#include
@@ -465,7 +466,8 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
address entry = __ pc();
// Restore stack bottom in case i2c adjusted stack
- __ ldr(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ ldr(rscratch1, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ lea(esp, Address(rfp, rscratch1, Address::lsl(Interpreter::logStackElementSize)));
// and null it as marker that esp is now tos until next java call
__ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
__ restore_bcp();
@@ -521,7 +523,8 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
__ restore_sp_after_call(); // Restore SP to extended SP
// Restore expression stack pointer
- __ ldr(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ ldr(rscratch1, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ lea(esp, Address(rfp, rscratch1, Address::lsl(Interpreter::logStackElementSize)));
// null last_sp until next java call
__ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
@@ -1867,7 +1870,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
/* notify_jvmdi */ false);
// Restore the last_sp and null it out
- __ ldr(esp, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ ldr(rscratch1, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ lea(esp, Address(rfp, rscratch1, Address::lsl(Interpreter::logStackElementSize)));
__ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
__ restore_bcp();
diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
index 6c764a1cc2dce..73f8a6c854f86 100644
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
@@ -2205,6 +2205,18 @@ void TemplateTable::_return(TosState state)
if (_desc->bytecode() == Bytecodes::_return)
__ membar(MacroAssembler::StoreStore);
+ if (_desc->bytecode() != Bytecodes::_return_register_finalizer) {
+ Label no_safepoint;
+ __ ldr(rscratch1, Address(rthread, JavaThread::polling_word_offset()));
+ __ tbz(rscratch1, log2i_exact(SafepointMechanism::poll_bit()), no_safepoint);
+ __ push(state);
+ __ push_cont_fastpath(rthread);
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint));
+ __ pop_cont_fastpath(rthread);
+ __ pop(state);
+ __ bind(no_safepoint);
+ }
+
// Narrow result if state is itos but result type is smaller.
// Need to narrow in the return bytecode rather than in generate_return_entry
// since compiled code callers expect the result to already be narrowed.
diff --git a/src/hotspot/cpu/arm/templateTable_arm.cpp b/src/hotspot/cpu/arm/templateTable_arm.cpp
index 263ff4f9e8b66..b8f1fdeebda6e 100644
--- a/src/hotspot/cpu/arm/templateTable_arm.cpp
+++ b/src/hotspot/cpu/arm/templateTable_arm.cpp
@@ -2492,6 +2492,16 @@ void TemplateTable::_return(TosState state) {
__ bind(skip_register_finalizer);
}
+ if (_desc->bytecode() != Bytecodes::_return_register_finalizer) {
+ Label no_safepoint;
+ __ ldr(Rtemp, Address(Rthread, JavaThread::polling_word_offset()));
+ __ tbz(Rtemp, exact_log2(SafepointMechanism::poll_bit()), no_safepoint);
+ __ push(state);
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint));
+ __ pop(state);
+ __ bind(no_safepoint);
+ }
+
// Narrow result if state is itos but result type is smaller.
// Need to narrow in the return bytecode rather than in generate_return_entry
// since compiled code callers expect the result to already be narrowed.
diff --git a/src/hotspot/cpu/ppc/continuationFreezeThaw_ppc.inline.hpp b/src/hotspot/cpu/ppc/continuationFreezeThaw_ppc.inline.hpp
index c72a4c8a54ded..888b0870fe625 100644
--- a/src/hotspot/cpu/ppc/continuationFreezeThaw_ppc.inline.hpp
+++ b/src/hotspot/cpu/ppc/continuationFreezeThaw_ppc.inline.hpp
@@ -89,7 +89,7 @@ inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, co
relativize_one(vfp, hfp, ijava_idx(monitors));
relativize_one(vfp, hfp, ijava_idx(esp));
- relativize_one(vfp, hfp, ijava_idx(top_frame_sp));
+ // top_frame_sp is already relativized
// hfp == hf.sp() + (f.fp() - f.sp()) is not true on ppc because the stack frame has room for
// the maximal expression stack and the expression stack in the heap frame is trimmed.
@@ -544,7 +544,7 @@ inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, c
derelativize_one(vfp, ijava_idx(monitors));
derelativize_one(vfp, ijava_idx(esp));
- derelativize_one(vfp, ijava_idx(top_frame_sp));
+ // Keep top_frame_sp relativized.
}
inline void ThawBase::patch_pd(frame& f, const frame& caller) {
diff --git a/src/hotspot/cpu/ppc/continuationHelper_ppc.inline.hpp b/src/hotspot/cpu/ppc/continuationHelper_ppc.inline.hpp
index 3f4ddd6472311..528f1f8ad962a 100644
--- a/src/hotspot/cpu/ppc/continuationHelper_ppc.inline.hpp
+++ b/src/hotspot/cpu/ppc/continuationHelper_ppc.inline.hpp
@@ -86,7 +86,7 @@ inline void ContinuationHelper::InterpretedFrame::patch_sender_sp(frame& f, cons
intptr_t* sp = caller.unextended_sp();
if (!f.is_heap_frame() && caller.is_interpreted_frame()) {
// See diagram "Interpreter Calling Procedure on PPC" at the end of continuationFreezeThaw_ppc.inline.hpp
- sp = (intptr_t*)caller.at(ijava_idx(top_frame_sp));
+ sp = (intptr_t*)caller.at_relative(ijava_idx(top_frame_sp));
}
assert(f.is_interpreted_frame(), "");
assert(f.is_heap_frame() || is_aligned(sp, frame::alignment_in_bytes), "");
diff --git a/src/hotspot/cpu/ppc/frame_ppc.inline.hpp b/src/hotspot/cpu/ppc/frame_ppc.inline.hpp
index c59aed8d77ba9..bad713fac841a 100644
--- a/src/hotspot/cpu/ppc/frame_ppc.inline.hpp
+++ b/src/hotspot/cpu/ppc/frame_ppc.inline.hpp
@@ -231,7 +231,13 @@ inline intptr_t* frame::interpreter_frame_esp() const {
inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* end) { get_ijava_state()->monitors = (intptr_t) end;}
inline void frame::interpreter_frame_set_cpcache(ConstantPoolCache* cp) { *interpreter_frame_cache_addr() = cp; }
inline void frame::interpreter_frame_set_esp(intptr_t* esp) { get_ijava_state()->esp = (intptr_t) esp; }
-inline void frame::interpreter_frame_set_top_frame_sp(intptr_t* top_frame_sp) { get_ijava_state()->top_frame_sp = (intptr_t) top_frame_sp; }
+
+inline void frame::interpreter_frame_set_top_frame_sp(intptr_t* top_frame_sp) {
+ assert(is_interpreted_frame(), "interpreted frame expected");
+ // set relativized top_frame_sp
+ get_ijava_state()->top_frame_sp = (intptr_t) (top_frame_sp - fp());
+}
+
inline void frame::interpreter_frame_set_sender_sp(intptr_t* sender_sp) { get_ijava_state()->sender_sp = (intptr_t) sender_sp; }
inline intptr_t* frame::interpreter_frame_expression_stack() const {
diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
index 2873fc2eca03c..4dd289c74be9f 100644
--- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
+++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp
@@ -1241,6 +1241,9 @@ void InterpreterMacroAssembler::call_from_interpreter(Register Rtarget_method, R
save_interpreter_state(Rscratch2);
#ifdef ASSERT
ld(Rscratch1, _ijava_state_neg(top_frame_sp), Rscratch2); // Rscratch2 contains fp
+ sldi(Rscratch1, Rscratch1, Interpreter::logStackElementSize);
+ add(Rscratch1, Rscratch1, Rscratch2); // Rscratch2 contains fp
+ // Compare sender_sp with the derelativized top_frame_sp
cmpd(CCR0, R21_sender_SP, Rscratch1);
asm_assert_eq("top_frame_sp incorrect");
#endif
@@ -2015,7 +2018,10 @@ void InterpreterMacroAssembler::add_monitor_to_stack(bool stack_is_empty, Regist
"size of a monitor must respect alignment of SP");
resize_frame(-monitor_size, /*temp*/esp); // Allocate space for new monitor
- std(R1_SP, _ijava_state_neg(top_frame_sp), esp); // esp contains fp
+ subf(Rtemp2, esp, R1_SP); // esp contains fp
+ sradi(Rtemp2, Rtemp2, Interpreter::logStackElementSize);
+ // Store relativized top_frame_sp
+ std(Rtemp2, _ijava_state_neg(top_frame_sp), esp); // esp contains fp
// Shuffle expression stack down. Recall that stack_base points
// just above the new expression stack bottom. Old_tos and new_tos
@@ -2251,6 +2257,9 @@ void InterpreterMacroAssembler::restore_interpreter_state(Register scratch, bool
Register tfsp = R18_locals;
Register scratch2 = R26_monitor;
ld(tfsp, _ijava_state_neg(top_frame_sp), scratch);
+ // Derelativize top_frame_sp
+ sldi(tfsp, tfsp, Interpreter::logStackElementSize);
+ add(tfsp, tfsp, scratch);
resize_frame_absolute(tfsp, scratch2, R0);
}
ld(R14_bcp, _ijava_state_neg(bcp), scratch); // Changed by VM code (exception).
diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad
index c8f8bf35f229e..89ce51e997ecd 100644
--- a/src/hotspot/cpu/ppc/ppc.ad
+++ b/src/hotspot/cpu/ppc/ppc.ad
@@ -2148,6 +2148,9 @@ bool Matcher::match_rule_supported(int opcode) {
return SuperwordUseVSX;
case Op_PopCountVI:
return (SuperwordUseVSX && UsePopCountInstruction);
+ case Op_FmaF:
+ case Op_FmaD:
+ return UseFMA;
case Op_FmaVF:
case Op_FmaVD:
return (SuperwordUseVSX && UseFMA);
@@ -9652,6 +9655,7 @@ instruct maddF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
format %{ "FMADDS $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmadds($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
@@ -9664,58 +9668,63 @@ instruct maddD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
format %{ "FMADD $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmadd($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
-// -src1 * src2 + src3 = -(src1*src2-src3)
+// src1 * (-src2) + src3 = -(src1*src2-src3)
+// "(-src1) * src2 + src3" has been idealized to "src2 * (-src1) + src3"
instruct mnsubF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
- match(Set dst (FmaF src3 (Binary (NegF src1) src2)));
match(Set dst (FmaF src3 (Binary src1 (NegF src2))));
format %{ "FNMSUBS $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fnmsubs($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
-// -src1 * src2 + src3 = -(src1*src2-src3)
+// src1 * (-src2) + src3 = -(src1*src2-src3)
+// "(-src1) * src2 + src3" has been idealized to "src2 * (-src1) + src3"
instruct mnsubD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
- match(Set dst (FmaD src3 (Binary (NegD src1) src2)));
match(Set dst (FmaD src3 (Binary src1 (NegD src2))));
format %{ "FNMSUB $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fnmsub($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
-// -src1 * src2 - src3 = -(src1*src2+src3)
+// src1 * (-src2) - src3 = -(src1*src2+src3)
+// "(-src1) * src2 - src3" has been idealized to "src2 * (-src1) - src3"
instruct mnaddF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
- match(Set dst (FmaF (NegF src3) (Binary (NegF src1) src2)));
match(Set dst (FmaF (NegF src3) (Binary src1 (NegF src2))));
format %{ "FNMADDS $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fnmadds($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
-// -src1 * src2 - src3 = -(src1*src2+src3)
+// src1 * (-src2) - src3 = -(src1*src2+src3)
+// "(-src1) * src2 - src3" has been idealized to "src2 * (-src1) - src3"
instruct mnaddD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
- match(Set dst (FmaD (NegD src3) (Binary (NegD src1) src2)));
match(Set dst (FmaD (NegD src3) (Binary src1 (NegD src2))));
format %{ "FNMADD $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fnmadd($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
@@ -9728,6 +9737,7 @@ instruct msubF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
format %{ "FMSUBS $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmsubs($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
@@ -9740,6 +9750,7 @@ instruct msubD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
format %{ "FMSUB $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmsub($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
@@ -14057,7 +14068,7 @@ instruct vpopcnt_reg(vecX dst, vecX src) %{
%}
// --------------------------------- FMA --------------------------------------
-// dst + src1 * src2
+// src1 * src2 + dst
instruct vfma4F(vecX dst, vecX src1, vecX src2) %{
match(Set dst (FmaVF dst (Binary src1 src2)));
predicate(n->as_Vector()->length() == 4);
@@ -14066,14 +14077,15 @@ instruct vfma4F(vecX dst, vecX src1, vecX src2) %{
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ xvmaddasp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
%}
ins_pipe(pipe_class_default);
%}
-// dst - src1 * src2
+// src1 * (-src2) + dst
+// "(-src1) * src2 + dst" has been idealized to "src2 * (-src1) + dst"
instruct vfma4F_neg1(vecX dst, vecX src1, vecX src2) %{
- match(Set dst (FmaVF dst (Binary (NegVF src1) src2)));
match(Set dst (FmaVF dst (Binary src1 (NegVF src2))));
predicate(n->as_Vector()->length() == 4);
@@ -14081,12 +14093,13 @@ instruct vfma4F_neg1(vecX dst, vecX src1, vecX src2) %{
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ xvnmsubasp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
%}
ins_pipe(pipe_class_default);
%}
-// - dst + src1 * src2
+// src1 * src2 - dst
instruct vfma4F_neg2(vecX dst, vecX src1, vecX src2) %{
match(Set dst (FmaVF (NegVF dst) (Binary src1 src2)));
predicate(n->as_Vector()->length() == 4);
@@ -14095,12 +14108,13 @@ instruct vfma4F_neg2(vecX dst, vecX src1, vecX src2) %{
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ xvmsubasp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
%}
ins_pipe(pipe_class_default);
%}
-// dst + src1 * src2
+// src1 * src2 + dst
instruct vfma2D(vecX dst, vecX src1, vecX src2) %{
match(Set dst (FmaVD dst (Binary src1 src2)));
predicate(n->as_Vector()->length() == 2);
@@ -14109,14 +14123,15 @@ instruct vfma2D(vecX dst, vecX src1, vecX src2) %{
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ xvmaddadp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
%}
ins_pipe(pipe_class_default);
%}
-// dst - src1 * src2
+// src1 * (-src2) + dst
+// "(-src1) * src2 + dst" has been idealized to "src2 * (-src1) + dst"
instruct vfma2D_neg1(vecX dst, vecX src1, vecX src2) %{
- match(Set dst (FmaVD dst (Binary (NegVD src1) src2)));
match(Set dst (FmaVD dst (Binary src1 (NegVD src2))));
predicate(n->as_Vector()->length() == 2);
@@ -14124,12 +14139,13 @@ instruct vfma2D_neg1(vecX dst, vecX src1, vecX src2) %{
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ xvnmsubadp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
%}
ins_pipe(pipe_class_default);
%}
-// - dst + src1 * src2
+// src1 * src2 - dst
instruct vfma2D_neg2(vecX dst, vecX src1, vecX src2) %{
match(Set dst (FmaVD (NegVD dst) (Binary src1 src2)));
predicate(n->as_Vector()->length() == 2);
@@ -14138,6 +14154,7 @@ instruct vfma2D_neg2(vecX dst, vecX src1, vecX src2) %{
size(4);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ xvmsubadp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister);
%}
ins_pipe(pipe_class_default);
diff --git a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp
index 50d43a46d4041..e3a8b3fbd9425 100644
--- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp
+++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp
@@ -1061,8 +1061,10 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Regist
__ std(R0, _ijava_state_neg(oop_tmp), R1_SP); // only used for native_call
// Store sender's SP and this frame's top SP.
- __ subf(R12_scratch2, Rtop_frame_size, R1_SP);
__ std(R21_sender_SP, _ijava_state_neg(sender_sp), R1_SP);
+ __ neg(R12_scratch2, Rtop_frame_size);
+ __ sradi(R12_scratch2, R12_scratch2, Interpreter::logStackElementSize);
+ // Store relativized top_frame_sp
__ std(R12_scratch2, _ijava_state_neg(top_frame_sp), R1_SP);
// Push top frame.
diff --git a/src/hotspot/cpu/ppc/vmstorage_ppc.hpp b/src/hotspot/cpu/ppc/vmstorage_ppc.hpp
index b569e3deb15da..bfff78a5cb6c7 100644
--- a/src/hotspot/cpu/ppc/vmstorage_ppc.hpp
+++ b/src/hotspot/cpu/ppc/vmstorage_ppc.hpp
@@ -28,6 +28,7 @@
#include
#include "asm/register.hpp"
+#include "utilities/checkedCast.hpp"
// keep in sync with jdk/internal/foreign/abi/ppc64/PPC64Architecture
enum class StorageType : int8_t {
diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp
index f96984003f06a..2d4e2c8d9785f 100644
--- a/src/hotspot/cpu/riscv/assembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp
@@ -27,6 +27,7 @@
#ifndef CPU_RISCV_ASSEMBLER_RISCV_HPP
#define CPU_RISCV_ASSEMBLER_RISCV_HPP
+#include "asm/assembler.hpp"
#include "asm/register.hpp"
#include "code/codeCache.hpp"
#include "metaprogramming/enableIf.hpp"
diff --git a/src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp b/src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp
index 5bfa1a8756c89..c581871fd8e90 100644
--- a/src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp
+++ b/src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp
@@ -82,7 +82,7 @@ template frame FreezeBase::new_heap_frame(frame& f, frame& calle
intptr_t *sp, *fp; // sp is really our unextended_sp
if (FKind::interpreted) {
assert((intptr_t*)f.at(frame::interpreter_frame_last_sp_offset) == nullptr
- || f.unextended_sp() == (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset), "");
+ || f.unextended_sp() == (intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset), "");
intptr_t locals_offset = *f.addr_at(frame::interpreter_frame_locals_offset);
// If the caller.is_empty(), i.e. we're freezing into an empty chunk, then we set
// the chunk's argsize in finalize_freeze and make room for it above the unextended_sp
@@ -121,7 +121,7 @@ template frame FreezeBase::new_heap_frame(frame& f, frame& calle
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
assert((f.at(frame::interpreter_frame_last_sp_offset) != 0) || (f.unextended_sp() == f.sp()), "");
- intptr_t* real_unextended_sp = (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset);
+ intptr_t* real_unextended_sp = (intptr_t*)f.at_relative_or_null(frame::interpreter_frame_last_sp_offset);
if (real_unextended_sp != nullptr) {
f.set_unextended_sp(real_unextended_sp); // can be null at a safepoint
}
@@ -147,8 +147,8 @@ inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, co
// because we freeze the padding word (see recurse_freeze_interpreted_frame) in order to keep the same relativized
// locals value, we don't need to change the locals value here.
- // at(frame::interpreter_frame_last_sp_offset) can be null at safepoint preempts
- *hf.addr_at(frame::interpreter_frame_last_sp_offset) = hf.unextended_sp() - hf.fp();
+ // Make sure that last_sp is already relativized.
+ assert((intptr_t*)hf.at_relative(frame::interpreter_frame_last_sp_offset) == hf.unextended_sp(), "");
relativize_one(vfp, hfp, frame::interpreter_frame_initial_sp_offset); // == block_top == block_bottom
relativize_one(vfp, hfp, frame::interpreter_frame_extended_sp_offset);
@@ -292,7 +292,9 @@ static inline void derelativize_one(intptr_t* const fp, int offset) {
inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
intptr_t* vfp = f.fp();
- derelativize_one(vfp, frame::interpreter_frame_last_sp_offset);
+ // Make sure that last_sp is kept relativized.
+ assert((intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset) == f.unextended_sp(), "");
+
derelativize_one(vfp, frame::interpreter_frame_initial_sp_offset);
derelativize_one(vfp, frame::interpreter_frame_extended_sp_offset);
}
diff --git a/src/hotspot/cpu/riscv/continuationHelper_riscv.inline.hpp b/src/hotspot/cpu/riscv/continuationHelper_riscv.inline.hpp
index 58ca64f23e7c9..4e96a8231b137 100644
--- a/src/hotspot/cpu/riscv/continuationHelper_riscv.inline.hpp
+++ b/src/hotspot/cpu/riscv/continuationHelper_riscv.inline.hpp
@@ -125,7 +125,8 @@ inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f,
assert(res == (intptr_t*)f.interpreter_frame_monitor_end() - expression_stack_sz, "");
assert(res >= f.unextended_sp(),
"res: " INTPTR_FORMAT " initial_sp: " INTPTR_FORMAT " last_sp: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " expression_stack_size: %d",
- p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at(frame::interpreter_frame_last_sp_offset), p2i(f.unextended_sp()), expression_stack_sz);
+ p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at_relative_or_null(frame::interpreter_frame_last_sp_offset),
+ p2i(f.unextended_sp()), expression_stack_sz);
return res;
}
diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp
index f1518724608a5..e91b722bd02a1 100644
--- a/src/hotspot/cpu/riscv/frame_riscv.cpp
+++ b/src/hotspot/cpu/riscv/frame_riscv.cpp
@@ -331,7 +331,9 @@ void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
// Used by template based interpreter deoptimization
void frame::interpreter_frame_set_last_sp(intptr_t* last_sp) {
- *((intptr_t**)addr_at(interpreter_frame_last_sp_offset)) = last_sp;
+ assert(is_interpreted_frame(), "interpreted frame expected");
+ // set relativized last_sp
+ ptr_at_put(interpreter_frame_last_sp_offset, last_sp != nullptr ? (last_sp - fp()) : 0);
}
void frame::interpreter_frame_set_extended_sp(intptr_t* sp) {
diff --git a/src/hotspot/cpu/riscv/frame_riscv.inline.hpp b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp
index 40455805984ef..dfec388019216 100644
--- a/src/hotspot/cpu/riscv/frame_riscv.inline.hpp
+++ b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp
@@ -253,7 +253,9 @@ inline intptr_t* frame::interpreter_frame_locals() const {
}
inline intptr_t* frame::interpreter_frame_last_sp() const {
- return (intptr_t*)at(interpreter_frame_last_sp_offset);
+ intptr_t n = *addr_at(interpreter_frame_last_sp_offset);
+ assert(n <= 0, "n: " INTPTR_FORMAT, n);
+ return n != 0 ? &fp()[n] : nullptr;
}
inline intptr_t* frame::interpreter_frame_bcp_addr() const {
diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp
index b8e155ccbba0a..96bbd6a3f302c 100644
--- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp
+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp
@@ -491,7 +491,9 @@ void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
// set sender sp
mv(x19_sender_sp, sp);
// record last_sp
- sd(esp, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
+ sub(t0, esp, fp);
+ srai(t0, t0, Interpreter::logStackElementSize);
+ sd(t0, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
}
// Jump to from_interpreted entry of a call unless single stepping is possible
diff --git a/src/hotspot/cpu/riscv/register_riscv.hpp b/src/hotspot/cpu/riscv/register_riscv.hpp
index bc632e05715c7..7c9139392fd52 100644
--- a/src/hotspot/cpu/riscv/register_riscv.hpp
+++ b/src/hotspot/cpu/riscv/register_riscv.hpp
@@ -27,6 +27,7 @@
#define CPU_RISCV_REGISTER_RISCV_HPP
#include "asm/register.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/powerOfTwo.hpp"
#define CSR_FFLAGS 0x001 // Floating-Point Accrued Exceptions.
diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad
index 6016c5fe2827e..d03dc843c2b0b 100644
--- a/src/hotspot/cpu/riscv/riscv.ad
+++ b/src/hotspot/cpu/riscv/riscv.ad
@@ -1907,6 +1907,11 @@ bool Matcher::match_rule_supported(int opcode) {
case Op_CountTrailingZerosI:
case Op_CountTrailingZerosL:
return UseZbb;
+ case Op_FmaF:
+ case Op_FmaD:
+ case Op_FmaVF:
+ case Op_FmaVD:
+ return UseFMA;
}
return true; // Per default match rules are supported.
@@ -7271,13 +7276,13 @@ instruct mulD_reg_reg(fRegD dst, fRegD src1, fRegD src2) %{
// src1 * src2 + src3
instruct maddF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{
- predicate(UseFMA);
match(Set dst (FmaF src3 (Binary src1 src2)));
ins_cost(FMUL_SINGLE_COST);
format %{ "fmadd.s $dst, $src1, $src2, $src3\t#@maddF_reg_reg" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmadd_s(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -7289,13 +7294,13 @@ instruct maddF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{
// src1 * src2 + src3
instruct maddD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{
- predicate(UseFMA);
match(Set dst (FmaD src3 (Binary src1 src2)));
ins_cost(FMUL_DOUBLE_COST);
format %{ "fmadd.d $dst, $src1, $src2, $src3\t#@maddD_reg_reg" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmadd_d(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -7307,13 +7312,13 @@ instruct maddD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{
// src1 * src2 - src3
instruct msubF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{
- predicate(UseFMA);
match(Set dst (FmaF (NegF src3) (Binary src1 src2)));
ins_cost(FMUL_SINGLE_COST);
format %{ "fmsub.s $dst, $src1, $src2, $src3\t#@msubF_reg_reg" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmsub_s(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -7325,13 +7330,13 @@ instruct msubF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{
// src1 * src2 - src3
instruct msubD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{
- predicate(UseFMA);
match(Set dst (FmaD (NegD src3) (Binary src1 src2)));
ins_cost(FMUL_DOUBLE_COST);
format %{ "fmsub.d $dst, $src1, $src2, $src3\t#@msubD_reg_reg" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmsub_d(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -7341,16 +7346,16 @@ instruct msubD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{
ins_pipe(pipe_class_default);
%}
-// -src1 * src2 + src3
+// src1 * (-src2) + src3
+// "(-src1) * src2 + src3" has been idealized to "src2 * (-src1) + src3"
instruct nmsubF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{
- predicate(UseFMA);
- match(Set dst (FmaF src3 (Binary (NegF src1) src2)));
match(Set dst (FmaF src3 (Binary src1 (NegF src2))));
ins_cost(FMUL_SINGLE_COST);
format %{ "fnmsub.s $dst, $src1, $src2, $src3\t#@nmsubF_reg_reg" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fnmsub_s(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -7360,16 +7365,16 @@ instruct nmsubF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{
ins_pipe(pipe_class_default);
%}
-// -src1 * src2 + src3
+// src1 * (-src2) + src3
+// "(-src1) * src2 + src3" has been idealized to "src2 * (-src1) + src3"
instruct nmsubD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{
- predicate(UseFMA);
- match(Set dst (FmaD src3 (Binary (NegD src1) src2)));
match(Set dst (FmaD src3 (Binary src1 (NegD src2))));
ins_cost(FMUL_DOUBLE_COST);
format %{ "fnmsub.d $dst, $src1, $src2, $src3\t#@nmsubD_reg_reg" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fnmsub_d(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -7379,16 +7384,16 @@ instruct nmsubD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{
ins_pipe(pipe_class_default);
%}
-// -src1 * src2 - src3
+// src1 * (-src2) - src3
+// "(-src1) * src2 - src3" has been idealized to "src2 * (-src1) - src3"
instruct nmaddF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{
- predicate(UseFMA);
- match(Set dst (FmaF (NegF src3) (Binary (NegF src1) src2)));
match(Set dst (FmaF (NegF src3) (Binary src1 (NegF src2))));
ins_cost(FMUL_SINGLE_COST);
format %{ "fnmadd.s $dst, $src1, $src2, $src3\t#@nmaddF_reg_reg" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fnmadd_s(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
@@ -7398,16 +7403,16 @@ instruct nmaddF_reg_reg(fRegF dst, fRegF src1, fRegF src2, fRegF src3) %{
ins_pipe(pipe_class_default);
%}
-// -src1 * src2 - src3
+// src1 * (-src2) - src3
+// "(-src1) * src2 - src3" has been idealized to "src2 * (-src1) - src3"
instruct nmaddD_reg_reg(fRegD dst, fRegD src1, fRegD src2, fRegD src3) %{
- predicate(UseFMA);
- match(Set dst (FmaD (NegD src3) (Binary (NegD src1) src2)));
match(Set dst (FmaD (NegD src3) (Binary src1 (NegD src2))));
ins_cost(FMUL_DOUBLE_COST);
format %{ "fnmadd.d $dst, $src1, $src2, $src3\t#@nmaddD_reg_reg" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fnmadd_d(as_FloatRegister($dst$$reg),
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg),
diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad
index 268a51c327f4b..a3e0b50f50108 100644
--- a/src/hotspot/cpu/riscv/riscv_v.ad
+++ b/src/hotspot/cpu/riscv/riscv_v.ad
@@ -1,6 +1,6 @@
//
-// Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
-// Copyright (c) 2020, Arm Limited. All rights reserved.
+// Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2020, 2023, Arm Limited. All rights reserved.
// Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
@@ -693,14 +693,14 @@ instruct vmin_fp_masked(vReg dst_src1, vReg src2, vRegMask vmask, vReg tmp1, vRe
// vector fmla
-// dst_src1 = dst_src1 + src2 * src3
+// dst_src1 = src2 * src3 + dst_src1
instruct vfmla(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
match(Set dst_src1 (FmaVF dst_src1 (Binary src2 src3)));
match(Set dst_src1 (FmaVD dst_src1 (Binary src2 src3)));
ins_cost(VEC_COST);
format %{ "vfmla $dst_src1, $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
__ vfmacc_vv(as_VectorRegister($dst_src1$$reg),
@@ -713,11 +713,11 @@ instruct vfmla(vReg dst_src1, vReg src2, vReg src3) %{
// dst_src1 = dst_src1 * src2 + src3
instruct vfmadd_masked(vReg dst_src1, vReg src2, vReg src3, vRegMask_V0 v0) %{
- predicate(UseFMA);
match(Set dst_src1 (FmaVF (Binary dst_src1 src2) (Binary src3 v0)));
match(Set dst_src1 (FmaVD (Binary dst_src1 src2) (Binary src3 v0)));
format %{ "vfmadd_masked $dst_src1, $dst_src1, $src2, $src3, $v0" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
__ vfmadd_vv(as_VectorRegister($dst_src1$$reg), as_VectorRegister($src2$$reg),
@@ -728,15 +728,14 @@ instruct vfmadd_masked(vReg dst_src1, vReg src2, vReg src3, vRegMask_V0 v0) %{
// vector fmls
-// dst_src1 = dst_src1 + -src2 * src3
-// dst_src1 = dst_src1 + src2 * -src3
+// dst_src1 = src2 * (-src3) + dst_src1
+// "(-src2) * src3 + dst_src1" has been idealized to "src3 * (-src2) + dst_src1"
instruct vfmlsF(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
- match(Set dst_src1 (FmaVF dst_src1 (Binary (NegVF src2) src3)));
match(Set dst_src1 (FmaVF dst_src1 (Binary src2 (NegVF src3))));
ins_cost(VEC_COST);
format %{ "vfmlsF $dst_src1, $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ vsetvli_helper(T_FLOAT, Matcher::vector_length(this));
__ vfnmsac_vv(as_VectorRegister($dst_src1$$reg),
as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg));
@@ -744,15 +743,14 @@ instruct vfmlsF(vReg dst_src1, vReg src2, vReg src3) %{
ins_pipe(pipe_slow);
%}
-// dst_src1 = dst_src1 + -src2 * src3
-// dst_src1 = dst_src1 + src2 * -src3
+// dst_src1 = src2 * (-src3) + dst_src1
+// "(-src2) * src3 + dst_src1" has been idealized to "src3 * (-src2) + dst_src1"
instruct vfmlsD(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
- match(Set dst_src1 (FmaVD dst_src1 (Binary (NegVD src2) src3)));
match(Set dst_src1 (FmaVD dst_src1 (Binary src2 (NegVD src3))));
ins_cost(VEC_COST);
format %{ "vfmlsD $dst_src1, $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ vsetvli_helper(T_DOUBLE, Matcher::vector_length(this));
__ vfnmsac_vv(as_VectorRegister($dst_src1$$reg),
as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg));
@@ -762,13 +760,13 @@ instruct vfmlsD(vReg dst_src1, vReg src2, vReg src3) %{
// vector fnmsub - predicated
-// dst_src1 = dst_src1 * -src2 + src3
+// dst_src1 = dst_src1 * (-src2) + src3
instruct vfnmsub_masked(vReg dst_src1, vReg src2, vReg src3, vRegMask_V0 v0) %{
- predicate(UseFMA);
match(Set dst_src1 (FmaVF (Binary dst_src1 (NegVF src2)) (Binary src3 v0)));
match(Set dst_src1 (FmaVD (Binary dst_src1 (NegVD src2)) (Binary src3 v0)));
format %{ "vfnmsub_masked $dst_src1, $dst_src1, $src2, $src3, $v0" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
__ vfnmsub_vv(as_VectorRegister($dst_src1$$reg), as_VectorRegister($src2$$reg),
@@ -779,15 +777,14 @@ instruct vfnmsub_masked(vReg dst_src1, vReg src2, vReg src3, vRegMask_V0 v0) %{
// vector fnmla
-// dst_src1 = -dst_src1 + -src2 * src3
-// dst_src1 = -dst_src1 + src2 * -src3
+// dst_src1 = src2 * (-src3) - dst_src1
+// "(-src2) * src3 - dst_src1" has been idealized to "src3 * (-src2) - dst_src1"
instruct vfnmlaF(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
- match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary (NegVF src2) src3)));
match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 (NegVF src3))));
ins_cost(VEC_COST);
format %{ "vfnmlaF $dst_src1, $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ vsetvli_helper(T_FLOAT, Matcher::vector_length(this));
__ vfnmacc_vv(as_VectorRegister($dst_src1$$reg),
as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg));
@@ -795,15 +792,14 @@ instruct vfnmlaF(vReg dst_src1, vReg src2, vReg src3) %{
ins_pipe(pipe_slow);
%}
-// dst_src1 = -dst_src1 + -src2 * src3
-// dst_src1 = -dst_src1 + src2 * -src3
+// dst_src1 = src2 * (-src3) - dst_src1
+// "(-src2) * src3 - dst_src1" has been idealized to "src3 * (-src2) - dst_src1"
instruct vfnmlaD(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
- match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary (NegVD src2) src3)));
match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 (NegVD src3))));
ins_cost(VEC_COST);
format %{ "vfnmlaD $dst_src1, $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ vsetvli_helper(T_DOUBLE, Matcher::vector_length(this));
__ vfnmacc_vv(as_VectorRegister($dst_src1$$reg),
as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg));
@@ -813,13 +809,13 @@ instruct vfnmlaD(vReg dst_src1, vReg src2, vReg src3) %{
// vector fnmadd - predicated
-// dst_src1 = -src3 + dst_src1 * -src2
+// dst_src1 = dst_src1 * (-src2) - src3
instruct vfnmadd_masked(vReg dst_src1, vReg src2, vReg src3, vRegMask_V0 v0) %{
- predicate(UseFMA);
match(Set dst_src1 (FmaVF (Binary dst_src1 (NegVF src2)) (Binary (NegVF src3) v0)));
match(Set dst_src1 (FmaVD (Binary dst_src1 (NegVD src2)) (Binary (NegVD src3) v0)));
format %{ "vfnmadd_masked $dst_src1, $dst_src1, $src2, $src3, $v0" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
__ vfnmadd_vv(as_VectorRegister($dst_src1$$reg), as_VectorRegister($src2$$reg),
@@ -830,13 +826,13 @@ instruct vfnmadd_masked(vReg dst_src1, vReg src2, vReg src3, vRegMask_V0 v0) %{
// vector fnmls
-// dst_src1 = -dst_src1 + src2 * src3
+// dst_src1 = src2 * src3 - dst_src1
instruct vfnmlsF(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 src3)));
ins_cost(VEC_COST);
format %{ "vfnmlsF $dst_src1, $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ vsetvli_helper(T_FLOAT, Matcher::vector_length(this));
__ vfmsac_vv(as_VectorRegister($dst_src1$$reg),
as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg));
@@ -846,11 +842,11 @@ instruct vfnmlsF(vReg dst_src1, vReg src2, vReg src3) %{
// dst_src1 = -dst_src1 + src2 * src3
instruct vfnmlsD(vReg dst_src1, vReg src2, vReg src3) %{
- predicate(UseFMA);
match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 src3)));
ins_cost(VEC_COST);
format %{ "vfnmlsD $dst_src1, $dst_src1, $src2, $src3" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ vsetvli_helper(T_DOUBLE, Matcher::vector_length(this));
__ vfmsac_vv(as_VectorRegister($dst_src1$$reg),
as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg));
@@ -860,13 +856,13 @@ instruct vfnmlsD(vReg dst_src1, vReg src2, vReg src3) %{
// vector vfmsub - predicated
-// dst_src1 = -src3 + dst_src1 * src2
+// dst_src1 = dst_src1 * src2 - src3
instruct vfmsub_masked(vReg dst_src1, vReg src2, vReg src3, vRegMask_V0 v0) %{
- predicate(UseFMA);
match(Set dst_src1 (FmaVF (Binary dst_src1 src2) (Binary (NegVF src3) v0)));
match(Set dst_src1 (FmaVD (Binary dst_src1 src2) (Binary (NegVD src3) v0)));
format %{ "vfmsub_masked $dst_src1, $dst_src1, $src2, $src3, $v0" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
__ vfmsub_vv(as_VectorRegister($dst_src1$$reg), as_VectorRegister($src2$$reg),
@@ -884,7 +880,7 @@ instruct vmla(vReg dst_src1, vReg src2, vReg src3) %{
match(Set dst_src1 (AddVI dst_src1 (MulVI src2 src3)));
match(Set dst_src1 (AddVL dst_src1 (MulVL src2 src3)));
ins_cost(VEC_COST);
- format %{ "vmla $dst_src1, $dst_src1, src2, src3" %}
+ format %{ "vmla $dst_src1, $dst_src1, $src2, $src3" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
@@ -920,7 +916,7 @@ instruct vmls(vReg dst_src1, vReg src2, vReg src3) %{
match(Set dst_src1 (SubVI dst_src1 (MulVI src2 src3)));
match(Set dst_src1 (SubVL dst_src1 (MulVL src2 src3)));
ins_cost(VEC_COST);
- format %{ "vmls $dst_src1, $dst_src1, src2, src3" %}
+ format %{ "vmls $dst_src1, $dst_src1, $src2, $src3" %}
ins_encode %{
BasicType bt = Matcher::vector_element_basic_type(this);
__ vsetvli_helper(bt, Matcher::vector_length(this));
diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp
index aeb9d58f6704b..b668cd58d26ed 100644
--- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp
+++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp
@@ -53,6 +53,7 @@
#include "runtime/synchronizer.hpp"
#include "runtime/timer.hpp"
#include "runtime/vframeArray.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/powerOfTwo.hpp"
#include
@@ -426,7 +427,8 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
address entry = __ pc();
// Restore stack bottom in case i2c adjusted stack
- __ ld(esp, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ ld(t0, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ shadd(esp, t0, fp, t0, LogBytesPerWord);
// and null it as marker that esp is now tos until next java call
__ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
__ restore_bcp();
@@ -483,7 +485,8 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
__ restore_sp_after_call(); // Restore SP to extended SP
// Restore expression stack pointer
- __ ld(esp, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ ld(t0, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ shadd(esp, t0, fp, t0, LogBytesPerWord);
// null last_sp until next java call
__ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
@@ -1604,7 +1607,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
/* notify_jvmdi */ false);
// Restore the last_sp and null it out
- __ ld(esp, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ ld(t0, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ shadd(esp, t0, fp, t0, LogBytesPerWord);
__ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize));
__ restore_bcp();
diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp
index 87efd3522d91e..c85f2b97b1afe 100644
--- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp
+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp
@@ -2114,6 +2114,19 @@ void TemplateTable::_return(TosState state) {
__ membar(MacroAssembler::StoreStore);
}
+ if (_desc->bytecode() != Bytecodes::_return_register_finalizer) {
+ Label no_safepoint;
+ __ ld(t0, Address(xthread, JavaThread::polling_word_offset()));
+ __ test_bit(t0, t0, exact_log2(SafepointMechanism::poll_bit()));
+ __ beqz(t0, no_safepoint);
+ __ push(state);
+ __ push_cont_fastpath(xthread);
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint));
+ __ pop_cont_fastpath(xthread);
+ __ pop(state);
+ __ bind(no_safepoint);
+ }
+
// Narrow result if state is itos but result type is smaller.
// Need to narrow in the return bytecode rather than in generate_return_entry
// since compiled code callers expect the result to already be narrowed.
diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp
index 83f6f38d2534b..cf64e08ebc8e1 100644
--- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp
+++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp
@@ -267,8 +267,8 @@ void VM_Version::c2_initialize() {
if (MaxVectorSize > _initial_vector_length) {
warning("Current system only supports max RVV vector length %d. Set MaxVectorSize to %d",
_initial_vector_length, _initial_vector_length);
+ MaxVectorSize = _initial_vector_length;
}
- MaxVectorSize = _initial_vector_length;
} else {
vm_exit_during_initialization(err_msg("Unsupported MaxVectorSize: %d", (int)MaxVectorSize));
}
diff --git a/src/hotspot/cpu/s390/downcallLinker_s390.cpp b/src/hotspot/cpu/s390/downcallLinker_s390.cpp
index baee7d7a043d7..f831da9075599 100644
--- a/src/hotspot/cpu/s390/downcallLinker_s390.cpp
+++ b/src/hotspot/cpu/s390/downcallLinker_s390.cpp
@@ -23,8 +23,76 @@
*/
#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "code/codeBlob.hpp"
+#include "code/codeCache.hpp"
+#include "code/vmreg.inline.hpp"
+#include "compiler/oopMap.hpp"
+#include "logging/logStream.hpp"
+#include "memory/resourceArea.hpp"
#include "prims/downcallLinker.hpp"
-#include "utilities/debug.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/stubCodeGenerator.hpp"
+
+#define __ _masm->
+
+class DowncallStubGenerator : public StubCodeGenerator {
+ BasicType* _signature;
+ int _num_args;
+ BasicType _ret_bt;
+ const ABIDescriptor& _abi;
+
+ const GrowableArray& _input_registers;
+ const GrowableArray& _output_registers;
+
+ bool _needs_return_buffer;
+ int _captured_state_mask;
+ bool _needs_transition;
+
+ int _frame_complete;
+ int _frame_size_slots;
+ OopMapSet* _oop_maps;
+ public:
+ DowncallStubGenerator(CodeBuffer* buffer,
+ BasicType* signature,
+ int num_args,
+ BasicType ret_bt,
+ const ABIDescriptor& abi,
+ const GrowableArray& input_registers,
+ const GrowableArray& output_registers,
+ bool needs_return_buffer,
+ int captured_state_mask,
+ bool needs_transition)
+ :StubCodeGenerator(buffer, PrintMethodHandleStubs),
+ _signature(signature),
+ _num_args(num_args),
+ _ret_bt(ret_bt),
+ _abi(abi),
+ _input_registers(input_registers),
+ _output_registers(output_registers),
+ _needs_return_buffer(needs_return_buffer),
+ _captured_state_mask(captured_state_mask),
+ _needs_transition(needs_transition),
+ _frame_complete(0),
+ _frame_size_slots(0),
+ _oop_maps(nullptr) {
+ }
+ void generate();
+ int frame_complete() const {
+ return _frame_complete;
+ }
+
+ int framesize() const {
+ return (_frame_size_slots >> (LogBytesPerWord - LogBytesPerInt));
+ }
+
+ OopMapSet* oop_maps() const {
+ return _oop_maps;
+ }
+};
+
+static const int native_invoker_code_base_size = 512;
+static const int native_invoker_size_per_args = 8;
RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature,
int num_args,
@@ -35,6 +103,197 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature,
bool needs_return_buffer,
int captured_state_mask,
bool needs_transition) {
- Unimplemented();
- return nullptr;
+
+ int code_size = native_invoker_code_base_size + (num_args * native_invoker_size_per_args);
+ int locs_size = 1; //must be non zero
+ CodeBuffer code("nep_invoker_blob", code_size, locs_size);
+
+ DowncallStubGenerator g(&code, signature, num_args, ret_bt, abi,
+ input_registers, output_registers,
+ needs_return_buffer, captured_state_mask,
+ needs_transition);
+ g.generate();
+ code.log_section_sizes("nep_invoker_blob");
+
+ RuntimeStub* stub =
+ RuntimeStub::new_runtime_stub("nep_invoker_blob",
+ &code,
+ g.frame_complete(),
+ g.framesize(),
+ g.oop_maps(), false);
+
+#ifndef PRODUCT
+ LogTarget(Trace, foreign, downcall) lt;
+ if (lt.is_enabled()) {
+ ResourceMark rm;
+ LogStream ls(lt);
+ stub->print_on(&ls);
+ }
+#endif
+
+ return stub;
+}
+
+void DowncallStubGenerator::generate() {
+ Register call_target_address = Z_R1_scratch,
+ tmp = Z_R0_scratch;
+
+ VMStorage shuffle_reg = _abi._scratch1;
+
+ JavaCallingConvention in_conv;
+ NativeCallingConvention out_conv(_input_registers);
+ ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shuffle_reg);
+
+#ifndef PRODUCT
+ LogTarget(Trace, foreign, downcall) lt;
+ if (lt.is_enabled()) {
+ ResourceMark rm;
+ LogStream ls(lt);
+ arg_shuffle.print_on(&ls);
+ }
+#endif
+
+ assert(_abi._shadow_space_bytes == frame::z_abi_160_size, "expected space according to ABI");
+ int allocated_frame_size = _abi._shadow_space_bytes;
+ allocated_frame_size += arg_shuffle.out_arg_bytes();
+
+ assert(!_needs_return_buffer, "unexpected needs_return_buffer");
+ RegSpiller out_reg_spiller(_output_registers);
+ int spill_offset = allocated_frame_size;
+ allocated_frame_size += BytesPerWord;
+
+ StubLocations locs;
+ locs.set(StubLocations::TARGET_ADDRESS, _abi._scratch2);
+
+ if (_captured_state_mask != 0) {
+ __ block_comment("{ _captured_state_mask is set");
+ locs.set_frame_data(StubLocations::CAPTURED_STATE_BUFFER, allocated_frame_size);
+ allocated_frame_size += BytesPerWord;
+ __ block_comment("} _captured_state_mask is set");
+ }
+
+ allocated_frame_size = align_up(allocated_frame_size, StackAlignmentInBytes);
+ _frame_size_slots = allocated_frame_size >> LogBytesPerInt;
+
+ _oop_maps = _needs_transition ? new OopMapSet() : nullptr;
+ address start = __ pc();
+
+ __ save_return_pc();
+ __ push_frame(allocated_frame_size, Z_R11); // Create a new frame for the wrapper.
+
+ _frame_complete = __ pc() - start; // frame build complete.
+
+ if (_needs_transition) {
+ __ block_comment("{ thread java2native");
+ __ get_PC(Z_R1_scratch);
+ address the_pc = __ pc();
+ __ set_last_Java_frame(Z_SP, Z_R1_scratch);
+
+ OopMap* map = new OopMap(_frame_size_slots, 0);
+ _oop_maps->add_gc_map(the_pc - start, map);
+
+ // State transition
+ __ set_thread_state(_thread_in_native);
+ __ block_comment("} thread java2native");
+ }
+ __ block_comment("{ argument shuffle");
+ arg_shuffle.generate(_masm, shuffle_reg, frame::z_jit_out_preserve_size, _abi._shadow_space_bytes, locs);
+ __ block_comment("} argument shuffle");
+
+ __ call(as_Register(locs.get(StubLocations::TARGET_ADDRESS)));
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ if (_captured_state_mask != 0) {
+ __ block_comment("{ save thread local");
+
+ out_reg_spiller.generate_spill(_masm, spill_offset);
+
+ __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, DowncallLinker::capture_state));
+ __ z_lg(Z_ARG1, Address(Z_SP, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER)));
+ __ load_const_optimized(Z_ARG2, _captured_state_mask);
+ __ call(call_target_address);
+
+ out_reg_spiller.generate_fill(_masm, spill_offset);
+
+ __ block_comment("} save thread local");
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ Label L_after_safepoint_poll;
+ Label L_safepoint_poll_slow_path;
+ Label L_reguard;
+ Label L_after_reguard;
+
+ if (_needs_transition) {
+ __ block_comment("{ thread native2java");
+ __ set_thread_state(_thread_in_native_trans);
+
+ if (!UseSystemMemoryBarrier) {
+ __ z_fence(); // Order state change wrt. safepoint poll.
+ }
+
+ __ safepoint_poll(L_safepoint_poll_slow_path, tmp);
+
+ __ load_and_test_int(tmp, Address(Z_thread, JavaThread::suspend_flags_offset()));
+ __ z_brne(L_safepoint_poll_slow_path);
+
+ __ bind(L_after_safepoint_poll);
+
+ // change thread state
+ __ set_thread_state(_thread_in_Java);
+
+ __ block_comment("reguard stack check");
+ __ z_cli(Address(Z_thread, JavaThread::stack_guard_state_offset() + in_ByteSize(sizeof(StackOverflow::StackGuardState) - 1)),
+ StackOverflow::stack_guard_yellow_reserved_disabled);
+ __ z_bre(L_reguard);
+ __ bind(L_after_reguard);
+
+ __ reset_last_Java_frame();
+ __ block_comment("} thread native2java");
+ }
+
+ __ pop_frame();
+ __ restore_return_pc(); // This is the way back to the caller.
+ __ z_br(Z_R14);
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ if (_needs_transition) {
+ __ block_comment("{ L_safepoint_poll_slow_path");
+ __ bind(L_safepoint_poll_slow_path);
+
+ // Need to save the native result registers around any runtime calls.
+ out_reg_spiller.generate_spill(_masm, spill_offset);
+
+ __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, JavaThread::check_special_condition_for_native_trans));
+ __ z_lgr(Z_ARG1, Z_thread);
+ __ call(call_target_address);
+
+ out_reg_spiller.generate_fill(_masm, spill_offset);
+
+ __ z_bru(L_after_safepoint_poll);
+ __ block_comment("} L_safepoint_poll_slow_path");
+
+ //////////////////////////////////////////////////////////////////////////////
+ __ block_comment("{ L_reguard");
+ __ bind(L_reguard);
+
+ // Need to save the native result registers around any runtime calls.
+ out_reg_spiller.generate_spill(_masm, spill_offset);
+
+ __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, SharedRuntime::reguard_yellow_pages));
+ __ call(call_target_address);
+
+ out_reg_spiller.generate_fill(_masm, spill_offset);
+
+ __ z_bru(L_after_reguard);
+
+ __ block_comment("} L_reguard");
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ __ flush();
}
diff --git a/src/hotspot/cpu/s390/foreignGlobals_s390.cpp b/src/hotspot/cpu/s390/foreignGlobals_s390.cpp
index d3a318536bd7b..9796ab4ffe4d8 100644
--- a/src/hotspot/cpu/s390/foreignGlobals_s390.cpp
+++ b/src/hotspot/cpu/s390/foreignGlobals_s390.cpp
@@ -23,34 +23,209 @@
*/
#include "precompiled.hpp"
-#include "code/vmreg.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "code/vmreg.inline.hpp"
+#include "runtime/jniHandles.hpp"
+#include "runtime/jniHandles.inline.hpp"
+#include "oops/typeArrayOop.inline.hpp"
+#include "oops/oopCast.inline.hpp"
#include "prims/foreignGlobals.hpp"
-#include "utilities/debug.hpp"
+#include "prims/foreignGlobals.inline.hpp"
+#include "prims/vmstorage.hpp"
+#include "utilities/formatBuffer.hpp"
-class MacroAssembler;
+#define __ masm->
+
+bool ABIDescriptor::is_volatile_reg(Register reg) const {
+ return _integer_volatile_registers.contains(reg);
+}
+
+bool ABIDescriptor::is_volatile_reg(FloatRegister reg) const {
+ return _float_argument_registers.contains(reg)
+ || _float_additional_volatile_registers.contains(reg);
+}
bool ForeignGlobals::is_foreign_linker_supported() {
- return false;
+ return true;
}
const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) {
- Unimplemented();
- return {};
+ oop abi_oop = JNIHandles::resolve_non_null(jabi);
+ ABIDescriptor abi;
+
+ objArrayOop inputStorage = jdk_internal_foreign_abi_ABIDescriptor::inputStorage(abi_oop);
+ parse_register_array(inputStorage, StorageType::INTEGER, abi._integer_argument_registers, as_Register);
+ parse_register_array(inputStorage, StorageType::FLOAT, abi._float_argument_registers, as_FloatRegister);
+
+ objArrayOop outputStorage = jdk_internal_foreign_abi_ABIDescriptor::outputStorage(abi_oop);
+ parse_register_array(outputStorage, StorageType::INTEGER, abi._integer_return_registers, as_Register);
+ parse_register_array(outputStorage, StorageType::FLOAT, abi._float_return_registers, as_FloatRegister);
+
+ objArrayOop volatileStorage = jdk_internal_foreign_abi_ABIDescriptor::volatileStorage(abi_oop);
+ parse_register_array(volatileStorage, StorageType::INTEGER, abi._integer_volatile_registers, as_Register);
+ parse_register_array(volatileStorage, StorageType::FLOAT, abi._float_additional_volatile_registers, as_FloatRegister);
+
+ abi._stack_alignment_bytes = jdk_internal_foreign_abi_ABIDescriptor::stackAlignment(abi_oop);
+ abi._shadow_space_bytes = jdk_internal_foreign_abi_ABIDescriptor::shadowSpace(abi_oop);
+
+ abi._scratch1 = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::scratch1(abi_oop));
+ abi._scratch2 = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::scratch2(abi_oop));
+
+ return abi;
}
int RegSpiller::pd_reg_size(VMStorage reg) {
- Unimplemented();
- return -1;
+ if (reg.type() == StorageType::INTEGER || reg.type() == StorageType::FLOAT) {
+ return 8;
+ }
+ return 0; // stack and BAD
}
void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) {
- Unimplemented();
+ if (reg.type() == StorageType::INTEGER) {
+ __ reg2mem_opt(as_Register(reg), Address(Z_SP, offset), true);
+ } else if (reg.type() == StorageType::FLOAT) {
+ __ freg2mem_opt(as_FloatRegister(reg), Address(Z_SP, offset), true);
+ } else {
+ // stack and BAD
+ }
}
void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) {
- Unimplemented();
+ if (reg.type() == StorageType::INTEGER) {
+ __ mem2reg_opt(as_Register(reg), Address(Z_SP, offset), true);
+ } else if (reg.type() == StorageType::FLOAT) {
+ __ mem2freg_opt(as_FloatRegister(reg), Address(Z_SP, offset), true);
+ } else {
+ // stack and BAD
+ }
+}
+
+static int reg2offset(VMStorage vms, int stk_bias) {
+ assert(!vms.is_reg(), "wrong usage");
+ return vms.index_or_offset() + stk_bias;
+}
+
+static void move_reg(MacroAssembler* masm, int out_stk_bias,
+ VMStorage from_reg, VMStorage to_reg) {
+ int out_bias = 0;
+ switch (to_reg.type()) {
+ case StorageType::INTEGER:
+ if (to_reg.segment_mask() == REG64_MASK && from_reg.segment_mask() == REG32_MASK ) {
+ // see CCallingConventionRequiresIntsAsLongs
+ __ z_lgfr(as_Register(to_reg), as_Register(from_reg));
+ } else {
+ __ lgr_if_needed(as_Register(to_reg), as_Register(from_reg));
+ }
+ break;
+ case StorageType::STACK:
+ out_bias = out_stk_bias; //fallthrough
+ case StorageType::FRAME_DATA: {
+ // Integer types always get a 64 bit slot in C.
+ if (from_reg.segment_mask() == REG32_MASK) {
+ // see CCallingConventionRequiresIntsAsLongs
+ __ z_lgfr(as_Register(from_reg), as_Register(from_reg));
+ }
+ switch (to_reg.stack_size()) {
+ case 8: __ reg2mem_opt(as_Register(from_reg), Address(Z_SP, reg2offset(to_reg, out_bias)), true); break;
+ case 4: __ reg2mem_opt(as_Register(from_reg), Address(Z_SP, reg2offset(to_reg, out_bias)), false); break;
+ default: ShouldNotReachHere();
+ }
+ } break;
+ default: ShouldNotReachHere();
+ }
+}
+
+static void move_float(MacroAssembler* masm, int out_stk_bias,
+ VMStorage from_reg, VMStorage to_reg) {
+ switch (to_reg.type()) {
+ case StorageType::FLOAT:
+ if (from_reg.segment_mask() == REG64_MASK)
+ __ move_freg_if_needed(as_FloatRegister(to_reg), T_DOUBLE, as_FloatRegister(from_reg), T_DOUBLE);
+ else
+ __ move_freg_if_needed(as_FloatRegister(to_reg), T_FLOAT, as_FloatRegister(from_reg), T_FLOAT);
+ break;
+ case StorageType::STACK:
+ if (from_reg.segment_mask() == REG64_MASK) {
+ assert(to_reg.stack_size() == 8, "size should match");
+ __ freg2mem_opt(as_FloatRegister(from_reg), Address(Z_SP, reg2offset(to_reg, out_stk_bias)), true);
+ } else {
+ assert(to_reg.stack_size() == 4, "size should match");
+ __ freg2mem_opt(as_FloatRegister(from_reg), Address(Z_SP, reg2offset(to_reg, out_stk_bias)), false);
+ }
+ break;
+ default: ShouldNotReachHere();
+ }
+}
+
+static void move_stack(MacroAssembler* masm, Register tmp_reg, int in_stk_bias, int out_stk_bias,
+ VMStorage from_reg, VMStorage to_reg) {
+ int out_bias = 0;
+ Address from_addr(Z_R11, reg2offset(from_reg, in_stk_bias));
+ switch (to_reg.type()) {
+ case StorageType::INTEGER:
+ switch (from_reg.stack_size()) {
+ case 8: __ mem2reg_opt(as_Register(to_reg), from_addr, true);break;
+ case 4: __ mem2reg_opt(as_Register(to_reg), from_addr, false);break;
+ default: ShouldNotReachHere();
+ }
+ break;
+ case StorageType::FLOAT:
+ switch (from_reg.stack_size()) {
+ case 8: __ mem2freg_opt(as_FloatRegister(to_reg), from_addr, true);break;
+ case 4: __ mem2freg_opt(as_FloatRegister(to_reg), from_addr, false);break;
+ default: ShouldNotReachHere();
+ }
+ break;
+ case StorageType::STACK:
+ out_bias = out_stk_bias; // fallthrough
+ case StorageType::FRAME_DATA: {
+ switch (from_reg.stack_size()) {
+ case 8: __ mem2reg_opt(tmp_reg, from_addr, true); break;
+ case 4: if (to_reg.stack_size() == 8) {
+ __ mem2reg_signed_opt(tmp_reg, from_addr);
+ } else {
+ __ mem2reg_opt(tmp_reg, from_addr, false);
+ }
+ break;
+ default: ShouldNotReachHere();
+ }
+ switch (to_reg.stack_size()) {
+ case 8: __ reg2mem_opt(tmp_reg, Address (Z_SP, reg2offset(to_reg, out_bias)), true); break;
+ case 4: __ reg2mem_opt(tmp_reg, Address (Z_SP, reg2offset(to_reg, out_bias)), false); break;
+ default: ShouldNotReachHere();
+ }
+ } break;
+ default: ShouldNotReachHere();
+ }
}
void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const {
- Unimplemented();
+ Register tmp_reg = as_Register(tmp);
+ for (int i = 0; i < _moves.length(); i++) {
+ Move move = _moves.at(i);
+ VMStorage from_reg = move.from;
+ VMStorage to_reg = move.to;
+
+ // replace any placeholders
+ if (from_reg.type() == StorageType::PLACEHOLDER) {
+ from_reg = locs.get(from_reg);
+ }
+ if (to_reg.type() == StorageType::PLACEHOLDER) {
+ to_reg = locs.get(to_reg);
+ }
+
+ switch (from_reg.type()) {
+ case StorageType::INTEGER:
+ move_reg(masm, out_stk_bias, from_reg, to_reg);
+ break;
+ case StorageType::FLOAT:
+ move_float(masm, out_stk_bias, from_reg, to_reg);
+ break;
+ case StorageType::STACK:
+ move_stack(masm, tmp_reg, in_stk_bias, out_stk_bias, from_reg, to_reg);
+ break;
+ default: ShouldNotReachHere();
+ }
+ }
}
diff --git a/src/hotspot/cpu/s390/foreignGlobals_s390.hpp b/src/hotspot/cpu/s390/foreignGlobals_s390.hpp
index 8b86a2b06a601..4ff3b3e40b4ff 100644
--- a/src/hotspot/cpu/s390/foreignGlobals_s390.hpp
+++ b/src/hotspot/cpu/s390/foreignGlobals_s390.hpp
@@ -24,6 +24,23 @@
#ifndef CPU_S390_VM_FOREIGN_GLOBALS_S390_HPP
#define CPU_S390_VM_FOREIGN_GLOBALS_S390_HPP
-class ABIDescriptor {};
+struct ABIDescriptor {
+ GrowableArray _integer_argument_registers;
+ GrowableArray _integer_return_registers;
+ GrowableArray _float_argument_registers;
+ GrowableArray _float_return_registers;
+
+ GrowableArray _integer_volatile_registers;
+ GrowableArray _float_additional_volatile_registers;
+
+ int32_t _stack_alignment_bytes;
+ int32_t _shadow_space_bytes;
+
+ VMStorage _scratch1;
+ VMStorage _scratch2;
+
+ bool is_volatile_reg(Register reg) const;
+ bool is_volatile_reg(FloatRegister reg) const;
+};
#endif // CPU_S390_VM_FOREIGN_GLOBALS_S390_HPP
diff --git a/src/hotspot/cpu/s390/frame_s390.cpp b/src/hotspot/cpu/s390/frame_s390.cpp
index 23547fa6617b4..ac24e43f00ce4 100644
--- a/src/hotspot/cpu/s390/frame_s390.cpp
+++ b/src/hotspot/cpu/s390/frame_s390.cpp
@@ -218,13 +218,32 @@ frame frame::sender_for_entry_frame(RegisterMap *map) const {
}
UpcallStub::FrameData* UpcallStub::frame_data_for_frame(const frame& frame) const {
- ShouldNotCallThis();
- return nullptr;
+ assert(frame.is_upcall_stub_frame(), "wrong frame");
+ // need unextended_sp here, since normal sp is wrong for interpreter callees
+ return reinterpret_cast(
+ reinterpret_cast(frame.unextended_sp()) + in_bytes(_frame_data_offset));
}
bool frame::upcall_stub_frame_is_first() const {
- ShouldNotCallThis();
- return false;
+ assert(is_upcall_stub_frame(), "must be optimized entry frame");
+ UpcallStub* blob = _cb->as_upcall_stub();
+ JavaFrameAnchor* jfa = blob->jfa_for_frame(*this);
+ return jfa->last_Java_sp() == nullptr;
+}
+
+frame frame::sender_for_upcall_stub_frame(RegisterMap* map) const {
+ assert(map != nullptr, "map must be set");
+ UpcallStub* blob = _cb->as_upcall_stub();
+ // Java frame called from C; skip all C frames and return top C
+ // frame of that chunk as the sender
+ JavaFrameAnchor* jfa = blob->jfa_for_frame(*this);
+ assert(!upcall_stub_frame_is_first(), "must have a frame anchor to go back to");
+ assert(jfa->last_Java_sp() > sp(), "must be above this frame on stack");
+ map->clear();
+ assert(map->include_argument_oops(), "should be set by clear");
+ frame fr(jfa->last_Java_sp(), jfa->last_Java_pc());
+
+ return fr;
}
frame frame::sender_for_interpreter_frame(RegisterMap *map) const {
diff --git a/src/hotspot/cpu/s390/frame_s390.inline.hpp b/src/hotspot/cpu/s390/frame_s390.inline.hpp
index 271305e37d1d3..33cdf7d7432cf 100644
--- a/src/hotspot/cpu/s390/frame_s390.inline.hpp
+++ b/src/hotspot/cpu/s390/frame_s390.inline.hpp
@@ -350,12 +350,10 @@ inline frame frame::sender(RegisterMap* map) const {
// update it accordingly.
map->set_include_argument_oops(false);
- if (is_entry_frame()) {
- return sender_for_entry_frame(map);
- }
- if (is_interpreted_frame()) {
- return sender_for_interpreter_frame(map);
- }
+ if (is_entry_frame()) return sender_for_entry_frame(map);
+ if (is_upcall_stub_frame()) return sender_for_upcall_stub_frame(map);
+ if (is_interpreted_frame()) return sender_for_interpreter_frame(map);
+
assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
if (_cb != nullptr) return sender_for_compiled_frame(map);
diff --git a/src/hotspot/cpu/s390/globalDefinitions_s390.hpp b/src/hotspot/cpu/s390/globalDefinitions_s390.hpp
index 32a6ff39fb400..39baf5bf0478e 100644
--- a/src/hotspot/cpu/s390/globalDefinitions_s390.hpp
+++ b/src/hotspot/cpu/s390/globalDefinitions_s390.hpp
@@ -28,7 +28,7 @@
#define ShortenBranches true
-const int StackAlignmentInBytes = 16;
+const int StackAlignmentInBytes = 8;
// All faults on s390x give the address only on page granularity.
// Set Pdsegfault_address to minimum one page address.
diff --git a/src/hotspot/cpu/s390/methodHandles_s390.cpp b/src/hotspot/cpu/s390/methodHandles_s390.cpp
index 6392ba45a6c6e..ef8722f2499c0 100644
--- a/src/hotspot/cpu/s390/methodHandles_s390.cpp
+++ b/src/hotspot/cpu/s390/methodHandles_s390.cpp
@@ -349,7 +349,16 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
void MethodHandles::jump_to_native_invoker(MacroAssembler* _masm, Register nep_reg, Register temp_target) {
BLOCK_COMMENT("jump_to_native_invoker {");
- __ should_not_reach_here();
+ assert(nep_reg != noreg, "required register");
+
+ // Load the invoker, as NEP -> .invoker
+ __ verify_oop(nep_reg);
+
+ __ z_lg(temp_target, Address(nep_reg,
+ NONZERO(jdk_internal_foreign_abi_NativeEntryPoint::downcall_stub_address_offset_in_bytes())));
+
+ __ z_br(temp_target);
+
BLOCK_COMMENT("} jump_to_native_invoker");
}
diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad
index 6982349b3b542..ffac6b70a584b 100644
--- a/src/hotspot/cpu/s390/s390.ad
+++ b/src/hotspot/cpu/s390/s390.ad
@@ -1505,6 +1505,9 @@ bool Matcher::match_rule_supported(int opcode) {
case Op_PopCountL:
// PopCount supported by H/W from z/Architecture G5 (z196) on.
return (UsePopCountInstruction && VM_Version::has_PopCount());
+ case Op_FmaF:
+ case Op_FmaD:
+ return UseFMA;
}
return true; // Per default match rules are supported.
@@ -7160,6 +7163,7 @@ instruct maddF_reg_reg(regF dst, regF src1, regF src2) %{
size(4);
format %{ "MAEBR $dst, $src1, $src2" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ z_maebr($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
%}
ins_pipe(pipe_class_dummy);
@@ -7173,6 +7177,7 @@ instruct maddD_reg_reg(regD dst, regD src1, regD src2) %{
size(4);
format %{ "MADBR $dst, $src1, $src2" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ z_madbr($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
%}
ins_pipe(pipe_class_dummy);
@@ -7186,6 +7191,7 @@ instruct msubF_reg_reg(regF dst, regF src1, regF src2) %{
size(4);
format %{ "MSEBR $dst, $src1, $src2" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ z_msebr($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
%}
ins_pipe(pipe_class_dummy);
@@ -7199,6 +7205,7 @@ instruct msubD_reg_reg(regD dst, regD src1, regD src2) %{
size(4);
format %{ "MSDBR $dst, $src1, $src2" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ z_msdbr($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister);
%}
ins_pipe(pipe_class_dummy);
@@ -7212,6 +7219,7 @@ instruct maddF_reg_mem(regF dst, regF src1, memoryRX src2) %{
size(6);
format %{ "MAEB $dst, $src1, $src2" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ z_maeb($dst$$FloatRegister, $src1$$FloatRegister,
Address(reg_to_register_object($src2$$base), $src2$$index$$Register, $src2$$disp));
%}
@@ -7226,6 +7234,7 @@ instruct maddD_reg_mem(regD dst, regD src1, memoryRX src2) %{
size(6);
format %{ "MADB $dst, $src1, $src2" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ z_madb($dst$$FloatRegister, $src1$$FloatRegister,
Address(reg_to_register_object($src2$$base), $src2$$index$$Register, $src2$$disp));
%}
@@ -7240,6 +7249,7 @@ instruct msubF_reg_mem(regF dst, regF src1, memoryRX src2) %{
size(6);
format %{ "MSEB $dst, $src1, $src2" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ z_mseb($dst$$FloatRegister, $src1$$FloatRegister,
Address(reg_to_register_object($src2$$base), $src2$$index$$Register, $src2$$disp));
%}
@@ -7254,6 +7264,7 @@ instruct msubD_reg_mem(regD dst, regD src1, memoryRX src2) %{
size(6);
format %{ "MSDB $dst, $src1, $src2" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ z_msdb($dst$$FloatRegister, $src1$$FloatRegister,
Address(reg_to_register_object($src2$$base), $src2$$index$$Register, $src2$$disp));
%}
@@ -7268,6 +7279,7 @@ instruct maddF_mem_reg(regF dst, memoryRX src1, regF src2) %{
size(6);
format %{ "MAEB $dst, $src1, $src2" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ z_maeb($dst$$FloatRegister, $src2$$FloatRegister,
Address(reg_to_register_object($src1$$base), $src1$$index$$Register, $src1$$disp));
%}
@@ -7282,6 +7294,7 @@ instruct maddD_mem_reg(regD dst, memoryRX src1, regD src2) %{
size(6);
format %{ "MADB $dst, $src1, $src2" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ z_madb($dst$$FloatRegister, $src2$$FloatRegister,
Address(reg_to_register_object($src1$$base), $src1$$index$$Register, $src1$$disp));
%}
@@ -7296,6 +7309,7 @@ instruct msubF_mem_reg(regF dst, memoryRX src1, regF src2) %{
size(6);
format %{ "MSEB $dst, $src1, $src2" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ z_mseb($dst$$FloatRegister, $src2$$FloatRegister,
Address(reg_to_register_object($src1$$base), $src1$$index$$Register, $src1$$disp));
%}
@@ -7310,6 +7324,7 @@ instruct msubD_mem_reg(regD dst, memoryRX src1, regD src2) %{
size(6);
format %{ "MSDB $dst, $src1, $src2" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ z_msdb($dst$$FloatRegister, $src2$$FloatRegister,
Address(reg_to_register_object($src1$$base), $src1$$index$$Register, $src1$$disp));
%}
diff --git a/src/hotspot/cpu/s390/upcallLinker_s390.cpp b/src/hotspot/cpu/s390/upcallLinker_s390.cpp
index 3e1fb04218b51..b748ec547ccf1 100644
--- a/src/hotspot/cpu/s390/upcallLinker_s390.cpp
+++ b/src/hotspot/cpu/s390/upcallLinker_s390.cpp
@@ -22,15 +22,287 @@
*/
#include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "logging/logStream.hpp"
+#include "memory/resourceArea.hpp"
#include "prims/upcallLinker.hpp"
-#include "utilities/debug.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "runtime/signature.hpp"
+#include "runtime/stubRoutines.hpp"
+#include "utilities/formatBuffer.hpp"
+#include "utilities/globalDefinitions.hpp"
+#define __ _masm->
+
+// for callee saved regs, according to the caller's ABI
+static int compute_reg_save_area_size(const ABIDescriptor& abi) {
+ int size = 0;
+ for (int i = 0; i < Register::number_of_registers; i++) {
+ Register reg = as_Register(i);
+ // Z_SP saved/restored by prologue/epilogue
+ if (reg == Z_SP) continue;
+ if (!abi.is_volatile_reg(reg)) {
+ size += 8; // bytes
+ }
+ }
+
+ for (int i = 0; i < FloatRegister::number_of_registers; i++) {
+ FloatRegister reg = as_FloatRegister(i);
+ if (!abi.is_volatile_reg(reg)) {
+ size += 8; // bytes
+ }
+ }
+
+ return size;
+}
+
+static void preserve_callee_saved_registers(MacroAssembler* _masm, const ABIDescriptor& abi, int reg_save_area_offset) {
+ // 1. iterate all registers in the architecture
+ // - check if they are volatile or not for the given abi
+ // - if NOT, we need to save it here
+
+ int offset = reg_save_area_offset;
+
+ __ block_comment("{ preserve_callee_saved_regs ");
+ for (int i = 0; i < Register::number_of_registers; i++) {
+ Register reg = as_Register(i);
+ // Z_SP saved/restored by prologue/epilogue
+ if (reg == Z_SP) continue;
+ if (!abi.is_volatile_reg(reg)) {
+ __ z_stg(reg, Address(Z_SP, offset));
+ offset += 8;
+ }
+ }
+
+ for (int i = 0; i < FloatRegister::number_of_registers; i++) {
+ FloatRegister reg = as_FloatRegister(i);
+ if (!abi.is_volatile_reg(reg)) {
+ __ z_std(reg, Address(Z_SP, offset));
+ offset += 8;
+ }
+ }
+
+ __ block_comment("} preserve_callee_saved_regs ");
+}
+
+static void restore_callee_saved_registers(MacroAssembler* _masm, const ABIDescriptor& abi, int reg_save_area_offset) {
+ // 1. iterate all registers in the architecture
+ // - check if they are volatile or not for the given abi
+ // - if NOT, we need to restore it here
+
+ int offset = reg_save_area_offset;
+
+ __ block_comment("{ restore_callee_saved_regs ");
+ for (int i = 0; i < Register::number_of_registers; i++) {
+ Register reg = as_Register(i);
+ // Z_SP saved/restored by prologue/epilogue
+ if (reg == Z_SP) continue;
+ if (!abi.is_volatile_reg(reg)) {
+ __ z_lg(reg, Address(Z_SP, offset));
+ offset += 8;
+ }
+ }
+
+ for (int i = 0; i < FloatRegister::number_of_registers; i++) {
+ FloatRegister reg = as_FloatRegister(i);
+ if (!abi.is_volatile_reg(reg)) {
+ __ z_ld(reg, Address(Z_SP, offset));
+ offset += 8;
+ }
+ }
+
+ __ block_comment("} restore_callee_saved_regs ");
+}
+
+static const int upcall_stub_code_base_size = 1024; // depends on GC (resolve_jobject)
+static const int upcall_stub_size_per_arg = 16; // arg save & restore + move
address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry,
BasicType* in_sig_bt, int total_in_args,
BasicType* out_sig_bt, int total_out_args,
BasicType ret_type,
jobject jabi, jobject jconv,
bool needs_return_buffer, int ret_buf_size) {
- ShouldNotCallThis();
- return nullptr;
+ ResourceMark rm;
+ const ABIDescriptor abi = ForeignGlobals::parse_abi_descriptor(jabi);
+ const CallRegs call_regs = ForeignGlobals::parse_call_regs(jconv);
+ int code_size = upcall_stub_code_base_size + (total_in_args * upcall_stub_size_per_arg);
+ CodeBuffer buffer("upcall_stub", code_size, /* locs_size = */ 0);
+
+ Register call_target_address = Z_R1_scratch;
+
+ VMStorage shuffle_reg = abi._scratch1;
+ JavaCallingConvention out_conv;
+ NativeCallingConvention in_conv(call_regs._arg_regs);
+ ArgumentShuffle arg_shuffle(in_sig_bt, total_in_args, out_sig_bt, total_out_args, &in_conv, &out_conv, shuffle_reg);
+
+ // The Java call uses the JIT ABI, but we also call C.
+ int out_arg_area = MAX2(frame::z_jit_out_preserve_size + arg_shuffle.out_arg_bytes(), (int)frame::z_abi_160_size);
+
+#ifndef PRODUCT
+ LogTarget(Trace, foreign, upcall) lt;
+ if (lt.is_enabled()) {
+ ResourceMark rm;
+ LogStream ls(lt);
+ arg_shuffle.print_on(&ls);
+ }
+#endif
+
+
+ int reg_save_area_size = compute_reg_save_area_size(abi);
+ RegSpiller arg_spiller(call_regs._arg_regs);
+ RegSpiller result_spiller(call_regs._ret_regs);
+
+ int res_save_area_offset = out_arg_area;
+ int arg_save_area_offset = res_save_area_offset + result_spiller.spill_size_bytes();
+ int reg_save_area_offset = arg_save_area_offset + arg_spiller.spill_size_bytes();
+ int frame_data_offset = reg_save_area_offset + reg_save_area_size;
+ int frame_bottom_offset = frame_data_offset + sizeof(UpcallStub::FrameData);
+
+ int frame_size = align_up(frame_bottom_offset, StackAlignmentInBytes);
+ StubLocations locs;
+
+ // The space we have allocated will look like:
+ //
+ //
+ // FP-> | |
+ // |---------------------| = frame_bottom_offset = frame_size
+ // | |
+ // | FrameData |
+ // |---------------------| = frame_data_offset
+ // | |
+ // | reg_save_area |
+ // |---------------------| = reg_save_are_offset
+ // | |
+ // | arg_save_area |
+ // |---------------------| = arg_save_are_offset
+ // | |
+ // | res_save_area |
+ // |---------------------| = res_save_are_offset
+ // | |
+ // SP-> | out_arg_area | needs to be at end for shadow space
+ //
+ //
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ MacroAssembler* _masm = new MacroAssembler(&buffer);
+ address start = __ pc();
+
+ __ save_return_pc();
+ assert((abi._stack_alignment_bytes % StackAlignmentInBytes) == 0, "must be 8 byte aligned");
+ // allocate frame (frame_size is also aligned, so stack is still aligned)
+ __ push_frame(frame_size);
+
+ // we have to always spill args since we need to do a call to get the thread
+ // (and maybe attach it).
+ arg_spiller.generate_spill(_masm, arg_save_area_offset);
+ // Java methods won't preserve them, so save them here:
+ preserve_callee_saved_registers(_masm, abi, reg_save_area_offset);
+
+ __ block_comment("{ on_entry");
+ __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, UpcallLinker::on_entry));
+ __ z_aghik(Z_ARG1, Z_SP, frame_data_offset);
+ __ call(call_target_address);
+ __ z_lgr(Z_thread, Z_RET);
+ __ block_comment("} on_entry");
+
+ arg_spiller.generate_fill(_masm, arg_save_area_offset);
+ __ block_comment("{ argument shuffle");
+ arg_shuffle.generate(_masm, shuffle_reg, abi._shadow_space_bytes, frame::z_jit_out_preserve_size, locs);
+ __ block_comment("} argument shuffle");
+
+ __ block_comment("{ receiver ");
+ __ load_const_optimized(Z_ARG1, (intptr_t)receiver);
+ __ resolve_jobject(Z_ARG1, Z_tmp_1, Z_tmp_2);
+ __ block_comment("} receiver ");
+
+ __ load_const_optimized(Z_method, (intptr_t)entry);
+ __ z_stg(Z_method, Address(Z_thread, in_bytes(JavaThread::callee_target_offset())));
+
+ __ z_lg(call_target_address, Address(Z_method, in_bytes(Method::from_compiled_offset())));
+ __ call(call_target_address);
+
+ // return value shuffle
+ assert(!needs_return_buffer, "unexpected needs_return_buffer");
+ // CallArranger can pick a return type that goes in the same reg for both CCs.
+ if (call_regs._ret_regs.length() > 0) { // 0 or 1
+ VMStorage ret_reg = call_regs._ret_regs.at(0);
+ // Check if the return reg is as expected.
+ switch (ret_type) {
+ case T_BOOLEAN:
+ case T_BYTE:
+ case T_SHORT:
+ case T_CHAR:
+ case T_INT:
+ __ z_lgfr(Z_RET, Z_RET); // Clear garbage in high half.
+ // fallthrough
+ case T_LONG:
+ assert(as_Register(ret_reg) == Z_RET, "unexpected result register");
+ break;
+ case T_FLOAT:
+ case T_DOUBLE:
+ assert(as_FloatRegister(ret_reg) == Z_FRET, "unexpected result register");
+ break;
+ default:
+ fatal("unexpected return type: %s", type2name(ret_type));
+ }
+ }
+
+ result_spiller.generate_spill(_masm, res_save_area_offset);
+
+ __ block_comment("{ on_exit");
+ __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, UpcallLinker::on_exit));
+ __ z_aghik(Z_ARG1, Z_SP, frame_data_offset);
+ __ call(call_target_address);
+ __ block_comment("} on_exit");
+
+ restore_callee_saved_registers(_masm, abi, reg_save_area_offset);
+
+ result_spiller.generate_fill(_masm, res_save_area_offset);
+
+ __ pop_frame();
+ __ restore_return_pc();
+ __ z_br(Z_R14);
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ __ block_comment("{ exception handler");
+
+ intptr_t exception_handler_offset = __ pc() - start;
+
+ // Native caller has no idea how to handle exceptions,
+ // so we just crash here. Up to callee to catch exceptions.
+ __ verify_oop(Z_ARG1);
+ __ load_const_optimized(call_target_address, CAST_FROM_FN_PTR(uint64_t, UpcallLinker::handle_uncaught_exception));
+ __ call_c(call_target_address);
+ __ should_not_reach_here();
+
+ __ block_comment("} exception handler");
+
+ _masm->flush();
+
+#ifndef PRODUCT
+ stringStream ss;
+ ss.print("upcall_stub_%s", entry->signature()->as_C_string());
+ const char* name = _masm->code_string(ss.as_string());
+#else // PRODUCT
+ const char* name = "upcall_stub";
+#endif // PRODUCT
+
+ buffer.log_section_sizes(name);
+ UpcallStub* blob
+ = UpcallStub::create(name,
+ &buffer,
+ exception_handler_offset,
+ receiver,
+ in_ByteSize(frame_data_offset));
+#ifndef PRODUCT
+ if (lt.is_enabled()) {
+ ResourceMark rm;
+ LogStream ls(lt);
+ blob->print_on(&ls);
+ }
+#endif
+
+ return blob->code_begin();
}
diff --git a/src/hotspot/cpu/s390/vmstorage_s390.hpp b/src/hotspot/cpu/s390/vmstorage_s390.hpp
index 192159adc4cc5..44a2e91e920c5 100644
--- a/src/hotspot/cpu/s390/vmstorage_s390.hpp
+++ b/src/hotspot/cpu/s390/vmstorage_s390.hpp
@@ -27,26 +27,82 @@
#include
#include "asm/register.hpp"
+#include "utilities/checkedCast.hpp"
enum class StorageType : int8_t {
- STACK = 0,
- PLACEHOLDER = 1,
-// special locations used only by native code
- FRAME_DATA = PLACEHOLDER + 1,
+ INTEGER = 0,
+ FLOAT = 1,
+ STACK = 2,
+ PLACEHOLDER = 3,
+ // special locations used only by native code
+ FRAME_DATA = 4,
INVALID = -1
};
// need to define this before constructing VMStorage (below)
constexpr inline bool VMStorage::is_reg(StorageType type) {
- return false;
+ return type == StorageType::INTEGER || type == StorageType::FLOAT;
}
constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; }
constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; }
constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; }
+// Needs to be consistent with S390Architecture.java.
+constexpr uint16_t REG32_MASK = 0b0000000000000001;
+constexpr uint16_t REG64_MASK = 0b0000000000000011;
+
+inline Register as_Register(VMStorage vms) {
+ assert(vms.type() == StorageType::INTEGER, "not the right type");
+ return ::as_Register(vms.index());
+}
+
+inline FloatRegister as_FloatRegister(VMStorage vms) {
+ assert(vms.type() == StorageType::FLOAT, "not the right type");
+ return ::as_FloatRegister(vms.index());
+}
+
+inline VMStorage as_VMStorage(Register reg, uint16_t segment_mask = REG64_MASK) {
+ return VMStorage::reg_storage(StorageType::INTEGER, segment_mask, reg->encoding());
+}
+
+inline VMStorage as_VMStorage(FloatRegister reg, uint16_t segment_mask = REG64_MASK) {
+ return VMStorage::reg_storage(StorageType::FLOAT, segment_mask, reg->encoding());
+}
+
inline VMStorage as_VMStorage(VMReg reg, BasicType bt) {
+ if (reg->is_Register()) {
+ uint16_t segment_mask = 0;
+ switch (bt) {
+ case T_BOOLEAN:
+ case T_CHAR :
+ case T_BYTE :
+ case T_SHORT :
+ case T_INT : segment_mask = REG32_MASK; break;
+ default : segment_mask = REG64_MASK; break;
+ }
+ return as_VMStorage(reg->as_Register(), segment_mask);
+ } else if (reg->is_FloatRegister()) {
+ // FP regs always use double format. However, we need the correct format for loads /stores.
+ return as_VMStorage(reg->as_FloatRegister(), (bt == T_FLOAT) ? REG32_MASK : REG64_MASK);
+ } else if (reg->is_stack()) {
+ uint16_t size = 0;
+ switch (bt) {
+ case T_BOOLEAN:
+ case T_CHAR :
+ case T_BYTE :
+ case T_SHORT :
+ case T_INT :
+ case T_FLOAT : size = 4; break;
+ default : size = 8; break;
+ }
+ return VMStorage(StorageType::STACK, size,
+ checked_cast(reg->reg2stack() * VMRegImpl::stack_slot_size));
+ } else if (!reg->is_valid()) {
+ return VMStorage::invalid();
+ }
+
ShouldNotReachHere();
return VMStorage::invalid();
}
-#endif // CPU_S390_VMSTORAGE_S390_INLINE_HPP
\ No newline at end of file
+#endif // CPU_S390_VMSTORAGE_S390_INLINE_HPP
diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp
index 5d6335691bcc9..6c1440f1ca02d 100644
--- a/src/hotspot/cpu/x86/assembler_x86.cpp
+++ b/src/hotspot/cpu/x86/assembler_x86.cpp
@@ -35,6 +35,7 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/vm_version.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/macros.hpp"
#ifdef PRODUCT
diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp
index b86bea3805eb9..c12045c6c5f23 100644
--- a/src/hotspot/cpu/x86/assembler_x86.hpp
+++ b/src/hotspot/cpu/x86/assembler_x86.hpp
@@ -26,6 +26,7 @@
#define CPU_X86_ASSEMBLER_X86_HPP
#include "asm/register.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/powerOfTwo.hpp"
// Contains all the definitions needed for x86 assembly code generation.
diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
index 0b42929f925fd..14a6279c5b181 100644
--- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
@@ -37,6 +37,7 @@
#include "runtime/os.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
+#include "utilities/checkedCast.hpp"
int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register tmp, Label& slow_case) {
const int aligned_mask = BytesPerWord -1;
diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
index 993a1cf02cd1d..1cc22366a0e64 100644
--- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
@@ -35,6 +35,7 @@
#include "opto/subnode.hpp"
#include "runtime/objectMonitor.hpp"
#include "runtime/stubRoutines.hpp"
+#include "utilities/checkedCast.hpp"
#ifdef PRODUCT
#define BLOCK_COMMENT(str) /* nothing */
diff --git a/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp b/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp
index 08b1b28565157..8630a4670dbf0 100644
--- a/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp
+++ b/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp
@@ -79,8 +79,8 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
intptr_t *sp, *fp; // sp is really our unextended_sp
if (FKind::interpreted) {
- assert((intptr_t*)f.at(frame::interpreter_frame_last_sp_offset) == nullptr
- || f.unextended_sp() == (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset), "");
+ assert((intptr_t*)f.at_relative_or_null(frame::interpreter_frame_last_sp_offset) == nullptr
+ || f.unextended_sp() == (intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset), "");
intptr_t locals_offset = *f.addr_at(frame::interpreter_frame_locals_offset);
// If the caller.is_empty(), i.e. we're freezing into an empty chunk, then we set
// the chunk's argsize in finalize_freeze and make room for it above the unextended_sp
@@ -120,7 +120,7 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
assert((f.at(frame::interpreter_frame_last_sp_offset) != 0) || (f.unextended_sp() == f.sp()), "");
- intptr_t* real_unextended_sp = (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset);
+ intptr_t* real_unextended_sp = (intptr_t*)f.at_relative_or_null(frame::interpreter_frame_last_sp_offset);
if (real_unextended_sp != nullptr) {
f.set_unextended_sp(real_unextended_sp); // can be null at a safepoint
}
@@ -141,8 +141,8 @@ inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, co
|| (f.unextended_sp() == f.sp()), "");
assert(f.fp() > (intptr_t*)f.at(frame::interpreter_frame_initial_sp_offset), "");
- // at(frame::interpreter_frame_last_sp_offset) can be null at safepoint preempts
- *hf.addr_at(frame::interpreter_frame_last_sp_offset) = hf.unextended_sp() - hf.fp();
+ // Make sure that last_sp is already relativized.
+ assert((intptr_t*)hf.at_relative(frame::interpreter_frame_last_sp_offset) == hf.unextended_sp(), "");
// Make sure that locals is already relativized.
assert((*hf.addr_at(frame::interpreter_frame_locals_offset) == frame::sender_sp_offset + f.interpreter_frame_method()->max_locals() - 1), "");
@@ -282,7 +282,9 @@ static inline void derelativize_one(intptr_t* const fp, int offset) {
inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
intptr_t* vfp = f.fp();
- derelativize_one(vfp, frame::interpreter_frame_last_sp_offset);
+ // Make sure that last_sp is kept relativized.
+ assert((intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset) == f.unextended_sp(), "");
+
derelativize_one(vfp, frame::interpreter_frame_initial_sp_offset);
}
diff --git a/src/hotspot/cpu/x86/continuationHelper_x86.inline.hpp b/src/hotspot/cpu/x86/continuationHelper_x86.inline.hpp
index 0b226b4b5817f..55794f9ac7e80 100644
--- a/src/hotspot/cpu/x86/continuationHelper_x86.inline.hpp
+++ b/src/hotspot/cpu/x86/continuationHelper_x86.inline.hpp
@@ -125,7 +125,8 @@ inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f,
assert(res == (intptr_t*)f.interpreter_frame_monitor_end() - expression_stack_sz, "");
assert(res >= f.unextended_sp(),
"res: " INTPTR_FORMAT " initial_sp: " INTPTR_FORMAT " last_sp: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " expression_stack_size: %d",
- p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at(frame::interpreter_frame_last_sp_offset), p2i(f.unextended_sp()), expression_stack_sz);
+ p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at_relative_or_null(frame::interpreter_frame_last_sp_offset),
+ p2i(f.unextended_sp()), expression_stack_sz);
return res;
}
diff --git a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp
index 68fe831f48c4a..2da44a4e308c5 100644
--- a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp
+++ b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp
@@ -201,7 +201,9 @@ void DowncallStubGenerator::generate() {
__ enter();
// return address and rbp are already in place
- __ subptr(rsp, allocated_frame_size); // prolog
+ if (allocated_frame_size > 0) {
+ __ subptr(rsp, allocated_frame_size); // prolog
+ }
_frame_complete = __ pc() - start;
diff --git a/src/hotspot/cpu/x86/frame_x86.cpp b/src/hotspot/cpu/x86/frame_x86.cpp
index 7e4b24e097d5e..0fc674ec69ba8 100644
--- a/src/hotspot/cpu/x86/frame_x86.cpp
+++ b/src/hotspot/cpu/x86/frame_x86.cpp
@@ -352,7 +352,9 @@ void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
// Used by template based interpreter deoptimization
void frame::interpreter_frame_set_last_sp(intptr_t* sp) {
- *((intptr_t**)addr_at(interpreter_frame_last_sp_offset)) = sp;
+ assert(is_interpreted_frame(), "interpreted frame expected");
+ // set relativized last_sp
+ ptr_at_put(interpreter_frame_last_sp_offset, sp != nullptr ? (sp - fp()) : 0);
}
frame frame::sender_for_entry_frame(RegisterMap* map) const {
diff --git a/src/hotspot/cpu/x86/frame_x86.inline.hpp b/src/hotspot/cpu/x86/frame_x86.inline.hpp
index d7862afc292fb..67e5a1e0c43fe 100644
--- a/src/hotspot/cpu/x86/frame_x86.inline.hpp
+++ b/src/hotspot/cpu/x86/frame_x86.inline.hpp
@@ -250,7 +250,9 @@ inline intptr_t* frame::interpreter_frame_locals() const {
}
inline intptr_t* frame::interpreter_frame_last_sp() const {
- return (intptr_t*)at(interpreter_frame_last_sp_offset);
+ intptr_t n = *addr_at(interpreter_frame_last_sp_offset);
+ assert(n <= 0, "n: " INTPTR_FORMAT, n);
+ return n != 0 ? &fp()[n] : nullptr;
}
inline intptr_t* frame::interpreter_frame_bcp_addr() const {
diff --git a/src/hotspot/cpu/x86/interp_masm_x86.cpp b/src/hotspot/cpu/x86/interp_masm_x86.cpp
index caa07857f03dc..e5b5aeebeca4e 100644
--- a/src/hotspot/cpu/x86/interp_masm_x86.cpp
+++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp
@@ -795,7 +795,10 @@ void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
// set sender sp
lea(_bcp_register, Address(rsp, wordSize));
// record last_sp
- movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), _bcp_register);
+ mov(rcx, _bcp_register);
+ subptr(rcx, rbp);
+ sarptr(rcx, LogBytesPerWord);
+ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rcx);
}
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
index ade4b5226857b..904ac3ca42454 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp
@@ -52,6 +52,7 @@
#include "runtime/safepointMechanism.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/macros.hpp"
#ifdef PRODUCT
diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
index 8ad042acedcf7..9ffda6fa0d5c0 100644
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp
@@ -32,6 +32,7 @@
#include "utilities/macros.hpp"
#include "runtime/rtmLocking.hpp"
#include "runtime/vm_version.hpp"
+#include "utilities/checkedCast.hpp"
// MacroAssembler extends Assembler by frequently used macros.
//
diff --git a/src/hotspot/cpu/x86/register_x86.hpp b/src/hotspot/cpu/x86/register_x86.hpp
index 8c7b1d92c087c..2cfc3ec58ede5 100644
--- a/src/hotspot/cpu/x86/register_x86.hpp
+++ b/src/hotspot/cpu/x86/register_x86.hpp
@@ -27,6 +27,7 @@
#include "asm/register.hpp"
#include "runtime/globals.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/count_leading_zeros.hpp"
#include "utilities/powerOfTwo.hpp"
diff --git a/src/hotspot/cpu/x86/relocInfo_x86.cpp b/src/hotspot/cpu/x86/relocInfo_x86.cpp
index 8a6da79442155..db806419b51d4 100644
--- a/src/hotspot/cpu/x86/relocInfo_x86.cpp
+++ b/src/hotspot/cpu/x86/relocInfo_x86.cpp
@@ -33,6 +33,7 @@
#include "oops/oop.inline.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/safepointMechanism.hpp"
+#include "utilities/checkedCast.hpp"
void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
index 20495135c642e..5a4174f29146d 100644
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
+++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
@@ -57,6 +57,7 @@
#include "runtime/vframeArray.hpp"
#include "runtime/vm_version.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/formatBuffer.hpp"
#include "vmreg_x86.inline.hpp"
#ifdef COMPILER1
diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp
index 6bf129a2b34ae..f365d9d910b5a 100644
--- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp
+++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp
@@ -51,6 +51,7 @@
#include "runtime/synchronizer.hpp"
#include "runtime/timer.hpp"
#include "runtime/vframeArray.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/macros.hpp"
@@ -206,7 +207,8 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
#endif // _LP64
// Restore stack bottom in case i2c adjusted stack
- __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ movptr(rcx, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ lea(rsp, Address(rbp, rcx, Address::times_ptr));
// and null it as marker that esp is now tos until next java call
__ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD);
@@ -1616,6 +1618,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
#ifndef _LP64
__ mov(rax, rsp);
__ movptr(rbx, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ lea(rbx, Address(rbp, rbx, Address::times_ptr));
__ get_thread(thread);
// PC must point into interpreter here
__ set_last_Java_frame(thread, noreg, rbp, __ pc(), noreg);
@@ -1624,6 +1627,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
#else
__ mov(c_rarg1, rsp);
__ movptr(c_rarg2, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ lea(c_rarg2, Address(rbp, c_rarg2, Address::times_ptr));
// PC must point into interpreter here
__ set_last_Java_frame(noreg, rbp, __ pc(), rscratch1);
__ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), r15_thread, c_rarg1, c_rarg2);
@@ -1631,7 +1635,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
__ reset_last_Java_frame(thread, true);
// Restore the last_sp and null it out
- __ movptr(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ movptr(rcx, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize));
+ __ lea(rsp, Address(rbp, rcx, Address::times_ptr));
__ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD);
__ restore_bcp();
diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp
index dbb4e69303dca..45a110f3ccab5 100644
--- a/src/hotspot/cpu/x86/vm_version_x86.cpp
+++ b/src/hotspot/cpu/x86/vm_version_x86.cpp
@@ -38,6 +38,7 @@
#include "runtime/os.inline.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "runtime/vm_version.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/powerOfTwo.hpp"
#include "utilities/virtualizationSupport.hpp"
@@ -1913,9 +1914,9 @@ void VM_Version::get_processor_features() {
}
}
if (AllocatePrefetchLines > 1) {
- log->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize);
+ log->print_cr(" at distance %d, %d lines of %d bytes", AllocatePrefetchDistance, AllocatePrefetchLines, AllocatePrefetchStepSize);
} else {
- log->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize);
+ log->print_cr(" at distance %d, one line of %d bytes", AllocatePrefetchDistance, AllocatePrefetchStepSize);
}
}
@@ -3169,7 +3170,7 @@ bool VM_Version::is_intel_tsc_synched_at_init() {
return false;
}
-intx VM_Version::allocate_prefetch_distance(bool use_watermark_prefetch) {
+int VM_Version::allocate_prefetch_distance(bool use_watermark_prefetch) {
// Hardware prefetching (distance/size in bytes):
// Pentium 3 - 64 / 32
// Pentium 4 - 256 / 128
diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp
index cb9e806999b88..078f14221dd9b 100644
--- a/src/hotspot/cpu/x86/vm_version_x86.hpp
+++ b/src/hotspot/cpu/x86/vm_version_x86.hpp
@@ -750,7 +750,7 @@ class VM_Version : public Abstract_VM_Version {
static bool supports_compare_and_exchange() { return true; }
- static intx allocate_prefetch_distance(bool use_watermark_prefetch);
+ static int allocate_prefetch_distance(bool use_watermark_prefetch);
// SSE2 and later processors implement a 'pause' instruction
// that can be used for efficient implementation of
diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad
index 3147857d24938..61ab92326b20c 100644
--- a/src/hotspot/cpu/x86/x86.ad
+++ b/src/hotspot/cpu/x86/x86.ad
@@ -1566,6 +1566,8 @@ bool Matcher::match_rule_supported(int opcode) {
return false;
}
break;
+ case Op_FmaF:
+ case Op_FmaD:
case Op_FmaVD:
case Op_FmaVF:
if (!UseFMA) {
@@ -3960,11 +3962,11 @@ instruct onspinwait() %{
// a * b + c
instruct fmaD_reg(regD a, regD b, regD c) %{
- predicate(UseFMA);
match(Set c (FmaD c (Binary a b)));
format %{ "fmasd $a,$b,$c\t# $c = $a * $b + $c" %}
ins_cost(150);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmad($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister);
%}
ins_pipe( pipe_slow );
@@ -3972,11 +3974,11 @@ instruct fmaD_reg(regD a, regD b, regD c) %{
// a * b + c
instruct fmaF_reg(regF a, regF b, regF c) %{
- predicate(UseFMA);
match(Set c (FmaF c (Binary a b)));
format %{ "fmass $a,$b,$c\t# $c = $a * $b + $c" %}
ins_cost(150);
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
__ fmaf($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister);
%}
ins_pipe( pipe_slow );
@@ -9864,6 +9866,7 @@ instruct vfma_reg_masked(vec dst, vec src2, vec src3, kReg mask) %{
match(Set dst (FmaVD (Binary dst src2) (Binary src3 mask)));
format %{ "vfma_masked $dst, $src2, $src3, $mask \t! vfma masked operation" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
int vlen_enc = vector_length_encoding(this);
BasicType bt = Matcher::vector_element_basic_type(this);
int opc = this->ideal_Opcode();
@@ -9878,6 +9881,7 @@ instruct vfma_mem_masked(vec dst, vec src2, memory src3, kReg mask) %{
match(Set dst (FmaVD (Binary dst src2) (Binary (LoadVector src3) mask)));
format %{ "vfma_masked $dst, $src2, $src3, $mask \t! vfma masked operation" %}
ins_encode %{
+ assert(UseFMA, "Needs FMA instructions support.");
int vlen_enc = vector_length_encoding(this);
BasicType bt = Matcher::vector_element_basic_type(this);
int opc = this->ideal_Opcode();
diff --git a/src/hotspot/os/aix/attachListener_aix.cpp b/src/hotspot/os/aix/attachListener_aix.cpp
index 02bf4727194ef..2e079c9b3a18b 100644
--- a/src/hotspot/os/aix/attachListener_aix.cpp
+++ b/src/hotspot/os/aix/attachListener_aix.cpp
@@ -29,6 +29,7 @@
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/os.inline.hpp"
#include "services/attachListener.hpp"
+#include "utilities/checkedCast.hpp"
#include
#include
@@ -108,7 +109,7 @@ class AixAttachListener: AllStatic {
static bool is_shutdown() { return _shutdown; }
// write the given buffer to a socket
- static int write_fully(int s, char* buf, int len);
+ static int write_fully(int s, char* buf, size_t len);
static AixAttachOperation* dequeue();
};
@@ -276,7 +277,7 @@ AixAttachOperation* AixAttachListener::read_request(int s) {
// where is the protocol version (1), is the command
// name ("load", "datadump", ...), and is an argument
int expected_str_count = 2 + AttachOperation::arg_count_max;
- const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
+ const size_t max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1);
char buf[max_len];
@@ -285,15 +286,15 @@ AixAttachOperation* AixAttachListener::read_request(int s) {
// Read until all (expected) strings have been read, the buffer is
// full, or EOF.
- int off = 0;
- int left = max_len;
+ size_t off = 0;
+ size_t left = max_len;
do {
- int n;
+ ssize_t n;
// Don't block on interrupts because this will
// hang in the clean-up when shutting down.
n = read(s, buf+off, left);
- assert(n <= left, "buffer was too small, impossible!");
+ assert(n <= checked_cast(left), "buffer was too small, impossible!");
buf[max_len - 1] = '\0';
if (n == -1) {
return nullptr; // reset by peer or other error
@@ -414,9 +415,9 @@ AixAttachOperation* AixAttachListener::dequeue() {
}
// write the given buffer to the socket
-int AixAttachListener::write_fully(int s, char* buf, int len) {
+int AixAttachListener::write_fully(int s, char* buf, size_t len) {
do {
- int n = ::write(s, buf, len);
+ ssize_t n = ::write(s, buf, len);
if (n == -1) {
if (errno != EINTR) return -1;
} else {
@@ -579,15 +580,6 @@ void AttachListener::pd_data_dump() {
os::signal_notify(SIGQUIT);
}
-AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) {
- return nullptr;
-}
-
-jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) {
- out->print_cr("flag '%s' cannot be changed", op->arg(0));
- return JNI_ERR;
-}
-
void AttachListener::pd_detachall() {
// Cleanup server socket to detach clients.
listener_cleanup();
diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp
index 98b689d453016..f373ab12bd01d 100644
--- a/src/hotspot/os/aix/os_aix.cpp
+++ b/src/hotspot/os/aix/os_aix.cpp
@@ -74,6 +74,7 @@
#include "services/runtimeService.hpp"
#include "signals_posix.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/decoder.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/events.hpp"
@@ -2947,29 +2948,22 @@ void os::Aix::initialize_libperfstat() {
/////////////////////////////////////////////////////////////////////////////
// thread stack
-// Get the current stack base from the OS (actually, the pthread library).
-// Note: usually not page aligned.
-address os::current_stack_base() {
- AixMisc::stackbounds_t bounds;
- bool rc = AixMisc::query_stack_bounds_for_current_thread(&bounds);
- guarantee(rc, "Unable to retrieve stack bounds.");
- return bounds.base;
-}
-
-// Get the current stack size from the OS (actually, the pthread library).
+// Get the current stack base and size from the OS (actually, the pthread library).
+// Note: base usually not page aligned.
// Returned size is such that (base - size) is always aligned to page size.
-size_t os::current_stack_size() {
+void os::current_stack_base_and_size(address* stack_base, size_t* stack_size) {
AixMisc::stackbounds_t bounds;
bool rc = AixMisc::query_stack_bounds_for_current_thread(&bounds);
guarantee(rc, "Unable to retrieve stack bounds.");
- // Align the returned stack size such that the stack low address
+ *stack_base = bounds.base;
+
+ // Align the reported stack size such that the stack low address
// is aligned to page size (Note: base is usually not and we do not care).
// We need to do this because caller code will assume stack low address is
// page aligned and will place guard pages without checking.
address low = bounds.base - bounds.size;
address low_aligned = (address)align_up(low, os::vm_page_size());
- size_t s = bounds.base - low_aligned;
- return s;
+ *stack_size = bounds.base - low_aligned;
}
// Get the default path to the core file
@@ -2985,7 +2979,7 @@ int os::get_core_path(char* buffer, size_t bufferSize) {
jio_snprintf(buffer, bufferSize, "%s/core or core.%d",
p, current_process_id());
- return strlen(buffer);
+ return checked_cast(strlen(buffer));
}
bool os::start_debugging(char *buf, int buflen) {
@@ -3023,7 +3017,7 @@ static inline time_t get_mtime(const char* filename) {
int os::compare_file_modified_times(const char* file1, const char* file2) {
time_t t1 = get_mtime(file1);
time_t t2 = get_mtime(file2);
- return t1 - t2;
+ return primitive_compare(t1, t2);
}
bool os::supports_map_sync() {
diff --git a/src/hotspot/os/aix/os_perf_aix.cpp b/src/hotspot/os/aix/os_perf_aix.cpp
index bdb70250a76a9..e1719df48c331 100644
--- a/src/hotspot/os/aix/os_perf_aix.cpp
+++ b/src/hotspot/os/aix/os_perf_aix.cpp
@@ -77,7 +77,7 @@ static bool read_psinfo(const u_longlong_t& pid, psinfo_t& psinfo) {
FILE* fp;
char buf[BUF_LENGTH];
- int len;
+ size_t len;
jio_snprintf(buf, BUF_LENGTH, "/proc/%llu/psinfo", pid);
fp = fopen(buf, "r");
diff --git a/src/hotspot/os/bsd/attachListener_bsd.cpp b/src/hotspot/os/bsd/attachListener_bsd.cpp
index a790ed617c5bb..2b7e93e33ed16 100644
--- a/src/hotspot/os/bsd/attachListener_bsd.cpp
+++ b/src/hotspot/os/bsd/attachListener_bsd.cpp
@@ -28,6 +28,7 @@
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/os.inline.hpp"
#include "services/attachListener.hpp"
+#include "utilities/checkedCast.hpp"
#include
#include
@@ -102,7 +103,7 @@ class BsdAttachListener: AllStatic {
static int listener() { return _listener; }
// write the given buffer to a socket
- static int write_fully(int s, char* buf, int len);
+ static int write_fully(int s, char* buf, size_t len);
static BsdAttachOperation* dequeue();
};
@@ -257,7 +258,7 @@ BsdAttachOperation* BsdAttachListener::read_request(int s) {
// where is the protocol version (1), is the command
// name ("load", "datadump", ...), and is an argument
int expected_str_count = 2 + AttachOperation::arg_count_max;
- const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
+ const size_t max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1);
char buf[max_len];
@@ -266,13 +267,13 @@ BsdAttachOperation* BsdAttachListener::read_request(int s) {
// Read until all (expected) strings have been read, the buffer is
// full, or EOF.
- int off = 0;
- int left = max_len;
+ size_t off = 0;
+ size_t left = max_len;
do {
- int n;
+ ssize_t n;
RESTARTABLE(read(s, buf+off, left), n);
- assert(n <= left, "buffer was too small, impossible!");
+ assert(n <= checked_cast(left), "buffer was too small, impossible!");
buf[max_len - 1] = '\0';
if (n == -1) {
return nullptr; // reset by peer or other error
@@ -280,7 +281,7 @@ BsdAttachOperation* BsdAttachListener::read_request(int s) {
if (n == 0) {
break;
}
- for (int i=0; iprint_cr("flag '%s' cannot be changed", op->arg(0));
- return JNI_ERR;
-}
-
void AttachListener::pd_detachall() {
// do nothing for now
}
diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp
index 6e0fca59e9187..ae4bc6e42a953 100644
--- a/src/hotspot/os/bsd/os_bsd.cpp
+++ b/src/hotspot/os/bsd/os_bsd.cpp
@@ -2208,9 +2208,9 @@ static inline struct timespec get_mtime(const char* filename) {
int os::compare_file_modified_times(const char* file1, const char* file2) {
struct timespec filetime1 = get_mtime(file1);
struct timespec filetime2 = get_mtime(file2);
- int diff = filetime1.tv_sec - filetime2.tv_sec;
+ int diff = primitive_compare(filetime1.tv_sec, filetime2.tv_sec);
if (diff == 0) {
- return filetime1.tv_nsec - filetime2.tv_nsec;
+ diff = primitive_compare(filetime1.tv_nsec, filetime2.tv_nsec);
}
return diff;
}
diff --git a/src/hotspot/os/linux/attachListener_linux.cpp b/src/hotspot/os/linux/attachListener_linux.cpp
index 63c5bfef12594..41a24c450073f 100644
--- a/src/hotspot/os/linux/attachListener_linux.cpp
+++ b/src/hotspot/os/linux/attachListener_linux.cpp
@@ -29,6 +29,7 @@
#include "runtime/os.inline.hpp"
#include "os_posix.hpp"
#include "services/attachListener.hpp"
+#include "utilities/checkedCast.hpp"
#include
#include
@@ -103,7 +104,7 @@ class LinuxAttachListener: AllStatic {
static int listener() { return _listener; }
// write the given buffer to a socket
- static int write_fully(int s, char* buf, int len);
+ static int write_fully(int s, char* buf, size_t len);
static LinuxAttachOperation* dequeue();
};
@@ -257,7 +258,7 @@ LinuxAttachOperation* LinuxAttachListener::read_request(int s) {
// where is the protocol version (1), is the command
// name ("load", "datadump", ...), and is an argument
int expected_str_count = 2 + AttachOperation::arg_count_max;
- const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
+ const size_t max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1);
char buf[max_len];
@@ -266,13 +267,13 @@ LinuxAttachOperation* LinuxAttachListener::read_request(int s) {
// Read until all (expected) strings have been read, the buffer is
// full, or EOF.
- int off = 0;
- int left = max_len;
+ size_t off = 0;
+ size_t left = max_len;
do {
- int n;
+ ssize_t n;
RESTARTABLE(read(s, buf+off, left), n);
- assert(n <= left, "buffer was too small, impossible!");
+ assert(n <= checked_cast(left), "buffer was too small, impossible!");
buf[max_len - 1] = '\0';
if (n == -1) {
return nullptr; // reset by peer or other error
@@ -280,7 +281,7 @@ LinuxAttachOperation* LinuxAttachListener::read_request(int s) {
if (n == 0) {
break;
}
- for (int i=0; iprint_cr("flag '%s' cannot be changed", op->arg(0));
- return JNI_ERR;
-}
-
void AttachListener::pd_detachall() {
// do nothing for now
}
diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp
index a8fc37e709efa..c8aba7e54fb83 100644
--- a/src/hotspot/os/linux/os_linux.cpp
+++ b/src/hotspot/os/linux/os_linux.cpp
@@ -69,6 +69,7 @@
#include "services/memTracker.hpp"
#include "services/runtimeService.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/decoder.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/events.hpp"
@@ -401,7 +402,7 @@ bool os::Linux::get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu
// Returns the kernel thread id of the currently running thread. Kernel
// thread id is used to access /proc.
pid_t os::Linux::gettid() {
- int rslt = syscall(SYS_gettid);
+ long rslt = syscall(SYS_gettid);
assert(rslt != -1, "must be."); // old linuxthreads implementation?
return (pid_t)rslt;
}
@@ -423,7 +424,7 @@ static const char *unstable_chroot_error = "/proc file system not found.\n"
"environment on Linux when /proc filesystem is not mounted.";
void os::Linux::initialize_system_info() {
- set_processor_count(sysconf(_SC_NPROCESSORS_CONF));
+ set_processor_count((int)sysconf(_SC_NPROCESSORS_CONF));
if (processor_count() == 1) {
pid_t pid = os::Linux::gettid();
char fname[32];
@@ -742,7 +743,7 @@ static void *thread_native_entry(Thread *thread) {
OSThread* osthread = thread->osthread();
Monitor* sync = osthread->startThread_lock();
- osthread->set_thread_id(os::current_thread_id());
+ osthread->set_thread_id(checked_cast(os::current_thread_id()));
if (UseNUMA) {
int lgrp_id = os::numa_get_group_id();
@@ -1265,7 +1266,7 @@ void os::Linux::capture_initial_stack(size_t max_size) {
// by email from Hans Boehm. /proc/self/stat begins with current pid,
// followed by command name surrounded by parentheses, state, etc.
char stat[2048];
- int statlen;
+ size_t statlen;
fp = os::fopen("/proc/self/stat", "r");
if (fp) {
@@ -1474,7 +1475,7 @@ bool os::dll_address_to_function_name(address addr, char *buf,
if (!(demangle && Decoder::demangle(dlinfo.dli_sname, buf, buflen))) {
jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname);
}
- if (offset != nullptr) *offset = addr - (address)dlinfo.dli_saddr;
+ if (offset != nullptr) *offset = pointer_delta_as_int(addr, (address)dlinfo.dli_saddr);
return true;
}
// no matching symbol so try for just file info
@@ -1502,7 +1503,7 @@ bool os::dll_address_to_library_name(address addr, char* buf,
jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname);
}
if (dlinfo.dli_fbase != nullptr && offset != nullptr) {
- *offset = addr - (address)dlinfo.dli_fbase;
+ *offset = pointer_delta_as_int(addr, (address)dlinfo.dli_fbase);
}
return true;
}
@@ -1601,14 +1602,14 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
}
Elf32_Ehdr elf_head;
- int diag_msg_max_length=ebuflen-strlen(ebuf);
- char* diag_msg_buf=ebuf+strlen(ebuf);
-
- if (diag_msg_max_length==0) {
+ size_t prefix_len = strlen(ebuf);
+ ssize_t diag_msg_max_length = ebuflen - prefix_len;
+ if (diag_msg_max_length <= 0) {
// No more space in ebuf for additional diagnostics message
return nullptr;
}
+ char* diag_msg_buf = ebuf + prefix_len;
int file_descriptor= ::open(filename, O_RDONLY | O_NONBLOCK);
@@ -1891,7 +1892,7 @@ static bool _print_ascii_file(const char* filename, outputStream* st, unsigned*
}
char buf[33];
- int bytes;
+ ssize_t bytes;
buf[32] = '\0';
unsigned lines = 0;
while ((bytes = ::read(fd, buf, sizeof(buf)-1)) > 0) {
@@ -2382,7 +2383,7 @@ void os::Linux::print_steal_info(outputStream* st) {
uint64_t total_ticks_difference = pticks.total - initial_total_ticks;
double steal_ticks_perc = 0.0;
if (total_ticks_difference != 0) {
- steal_ticks_perc = (double) steal_ticks_difference / total_ticks_difference;
+ steal_ticks_perc = (double) steal_ticks_difference / (double)total_ticks_difference;
}
st->print_cr("Steal ticks since vm start: " UINT64_FORMAT, steal_ticks_difference);
st->print_cr("Steal ticks percentage since vm start:%7.3f", steal_ticks_perc);
@@ -2424,7 +2425,7 @@ static bool print_model_name_and_flags(outputStream* st, char* buf, size_t bufle
if (fp) {
bool model_name_printed = false;
while (!feof(fp)) {
- if (fgets(buf, buflen, fp)) {
+ if (fgets(buf, (int)buflen, fp)) {
// Assume model name comes before flags
if (strstr(buf, "model name") != nullptr) {
if (!model_name_printed) {
@@ -2667,7 +2668,7 @@ void os::jvm_path(char *buf, jint buflen) {
// determine if this is a legacy image or modules image
// modules image doesn't have "jre" subdirectory
- len = strlen(buf);
+ len = checked_cast(strlen(buf));
assert(len < buflen, "Ran out of buffer room");
jrelib_p = buf + len;
snprintf(jrelib_p, buflen-len, "/jre/lib");
@@ -2677,7 +2678,7 @@ void os::jvm_path(char *buf, jint buflen) {
if (0 == access(buf, F_OK)) {
// Use current module name "libjvm.so"
- len = strlen(buf);
+ len = (int)strlen(buf);
snprintf(buf + len, buflen-len, "/hotspot/libjvm.so");
} else {
// Go back to path of .so
@@ -2830,6 +2831,16 @@ void os::pd_commit_memory_or_exit(char* addr, size_t size, bool exec,
#define MADV_HUGEPAGE 14
#endif
+// Note that the value for MAP_FIXED_NOREPLACE differs between architectures, but all architectures
+// supported by OpenJDK share the same flag value.
+#define MAP_FIXED_NOREPLACE_value 0x100000
+#ifndef MAP_FIXED_NOREPLACE
+ #define MAP_FIXED_NOREPLACE MAP_FIXED_NOREPLACE_value
+#else
+ // Sanity-check our assumed default value if we build with a new enough libc.
+ static_assert(MAP_FIXED_NOREPLACE == MAP_FIXED_NOREPLACE_value);
+#endif
+
int os::Linux::commit_memory_impl(char* addr, size_t size,
size_t alignment_hint, bool exec) {
int err = os::Linux::commit_memory_impl(addr, size, exec);
@@ -2970,7 +2981,7 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected,
int os::Linux::sched_getcpu_syscall(void) {
unsigned int cpu = 0;
- int retval = -1;
+ long retval = -1;
#if defined(IA32)
#ifndef SYS_getcpu
@@ -2989,7 +3000,7 @@ int os::Linux::sched_getcpu_syscall(void) {
retval = vgetcpu(&cpu, nullptr, nullptr);
#endif
- return (retval == -1) ? retval : cpu;
+ return (retval == -1) ? -1 : cpu;
}
void os::Linux::sched_getcpu_init() {
@@ -3142,30 +3153,30 @@ void os::Linux::rebuild_nindex_to_node_map() {
// rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id.
// The table is later used in get_node_by_cpu().
void os::Linux::rebuild_cpu_to_node_map() {
- const size_t NCPUS = 32768; // Since the buffer size computation is very obscure
- // in libnuma (possible values are starting from 16,
- // and continuing up with every other power of 2, but less
- // than the maximum number of CPUs supported by kernel), and
- // is a subject to change (in libnuma version 2 the requirements
- // are more reasonable) we'll just hardcode the number they use
- // in the library.
- const size_t BitsPerCLong = sizeof(long) * CHAR_BIT;
-
- size_t cpu_num = processor_count();
- size_t cpu_map_size = NCPUS / BitsPerCLong;
- size_t cpu_map_valid_size =
+ const int NCPUS = 32768; // Since the buffer size computation is very obscure
+ // in libnuma (possible values are starting from 16,
+ // and continuing up with every other power of 2, but less
+ // than the maximum number of CPUs supported by kernel), and
+ // is a subject to change (in libnuma version 2 the requirements
+ // are more reasonable) we'll just hardcode the number they use
+ // in the library.
+ constexpr int BitsPerCLong = (int)sizeof(long) * CHAR_BIT;
+
+ int cpu_num = processor_count();
+ int cpu_map_size = NCPUS / BitsPerCLong;
+ int cpu_map_valid_size =
MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size);
cpu_to_node()->clear();
cpu_to_node()->at_grow(cpu_num - 1);
- size_t node_num = get_existing_num_nodes();
+ int node_num = get_existing_num_nodes();
int distance = 0;
int closest_distance = INT_MAX;
int closest_node = 0;
unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size, mtInternal);
- for (size_t i = 0; i < node_num; i++) {
+ for (int i = 0; i < node_num; i++) {
// Check if node is configured (not a memory-less node). If it is not, find
// the closest configured node. Check also if node is bound, i.e. it's allowed
// to allocate memory from the node. If it's not allowed, map cpus in that node
@@ -3176,7 +3187,7 @@ void os::Linux::rebuild_cpu_to_node_map() {
// Check distance from all remaining nodes in the system. Ignore distance
// from itself, from another non-configured node, and from another non-bound
// node.
- for (size_t m = 0; m < node_num; m++) {
+ for (int m = 0; m < node_num; m++) {
if (m != i &&
is_node_in_configured_nodes(nindex_to_node()->at(m)) &&
is_node_in_bound_nodes(nindex_to_node()->at(m))) {
@@ -3198,10 +3209,10 @@ void os::Linux::rebuild_cpu_to_node_map() {
// Get cpus from the original node and map them to the closest node. If node
// is a configured node (not a memory-less node), then original node and
// closest node are the same.
- if (numa_node_to_cpus(nindex_to_node()->at(i), cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) {
- for (size_t j = 0; j < cpu_map_valid_size; j++) {
+ if (numa_node_to_cpus(nindex_to_node()->at(i), cpu_map, cpu_map_size * (int)sizeof(unsigned long)) != -1) {
+ for (int j = 0; j < cpu_map_valid_size; j++) {
if (cpu_map[j] != 0) {
- for (size_t k = 0; k < BitsPerCLong; k++) {
+ for (int k = 0; k < BitsPerCLong; k++) {
if (cpu_map[j] & (1UL << k)) {
int cpu_index = j * BitsPerCLong + k;
@@ -3286,7 +3297,7 @@ static address get_stack_commited_bottom(address bottom, size_t size) {
address ntop = bottom + size;
size_t page_sz = os::vm_page_size();
- unsigned pages = size / page_sz;
+ unsigned pages = checked_cast(size / page_sz);
unsigned char vec[1];
unsigned imin = 1, imax = pages + 1, imid;
@@ -3336,21 +3347,21 @@ bool os::committed_in_range(address start, size_t size, address& committed_start
vec[stripe] = 'X';
const size_t page_sz = os::vm_page_size();
- size_t pages = size / page_sz;
+ uintx pages = size / page_sz;
assert(is_aligned(start, page_sz), "Start address must be page aligned");
assert(is_aligned(size, page_sz), "Size must be page aligned");
committed_start = nullptr;
- int loops = (pages + stripe - 1) / stripe;
+ int loops = checked_cast((pages + stripe - 1) / stripe);
int committed_pages = 0;
address loop_base = start;
bool found_range = false;
for (int index = 0; index < loops && !found_range; index ++) {
assert(pages > 0, "Nothing to do");
- int pages_to_query = (pages >= stripe) ? stripe : pages;
+ uintx pages_to_query = (pages >= stripe) ? stripe : pages;
pages -= pages_to_query;
// Get stable read
@@ -3366,7 +3377,7 @@ bool os::committed_in_range(address start, size_t size, address& committed_start
assert(vec[stripe] == 'X', "overflow guard");
assert(mincore_return_value == 0, "Range must be valid");
// Process this stripe
- for (int vecIdx = 0; vecIdx < pages_to_query; vecIdx ++) {
+ for (uintx vecIdx = 0; vecIdx < pages_to_query; vecIdx ++) {
if ((vec[vecIdx] & 0x01) == 0) { // not committed
// End of current contiguous region
if (committed_start != nullptr) {
@@ -3470,8 +3481,23 @@ bool os::remove_stack_guard_pages(char* addr, size_t size) {
// may not start from the requested address. Unlike Linux mmap(), this
// function returns null to indicate failure.
static char* anon_mmap(char* requested_addr, size_t bytes) {
- // MAP_FIXED is intentionally left out, to leave existing mappings intact.
- const int flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS;
+ // If a requested address was given:
+ //
+ // The POSIX-conforming way is to *omit* MAP_FIXED. This will leave existing mappings intact.
+ // If the requested mapping area is blocked by a pre-existing mapping, the kernel will map
+ // somewhere else. On Linux, that alternative address appears to have no relation to the
+ // requested address.
+ // Unfortunately, this is not what we need - if we requested a specific address, we'd want
+ // to map there and nowhere else. Therefore we will unmap the block again, which means we
+ // just executed a needless mmap->munmap cycle.
+ // Since Linux 4.17, the kernel offers MAP_FIXED_NOREPLACE. With this flag, if a pre-
+ // existing mapping exists, the kernel will not map at an alternative point but instead
+ // return an error. We can therefore save that unnecessary mmap-munmap cycle.
+ //
+ // Backward compatibility: Older kernels will ignore the unknown flag; so mmap will behave
+ // as in mode (a).
+ const int flags = MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS |
+ ((requested_addr != nullptr) ? MAP_FIXED_NOREPLACE : 0);
// Map reserved/uncommitted pages PROT_NONE so we fail early if we
// touch an uncommitted page. Otherwise, the read/write might
@@ -3793,15 +3819,17 @@ void os::large_page_init() {
return;
}
- // 2) check if large pages are configured
- if ( ( UseTransparentHugePages && HugePages::supports_thp() == false) ||
- (!UseTransparentHugePages && HugePages::supports_static_hugepages() == false) ) {
- // No large pages configured, return.
+ // 2) check if the OS supports THPs resp. static hugepages.
+ if (UseTransparentHugePages && !HugePages::supports_thp()) {
+ if (!FLAG_IS_DEFAULT(UseTransparentHugePages)) {
+ log_warning(pagesize)("UseTransparentHugePages disabled, transparent huge pages are not supported by the operating system.");
+ }
+ UseLargePages = UseTransparentHugePages = UseHugeTLBFS = UseSHM = false;
+ return;
+ }
+ if (!UseTransparentHugePages && !HugePages::supports_static_hugepages()) {
warn_no_large_pages_configured();
- UseLargePages = false;
- UseTransparentHugePages = false;
- UseHugeTLBFS = false;
- UseSHM = false;
+ UseLargePages = UseTransparentHugePages = UseHugeTLBFS = UseSHM = false;
return;
}
@@ -4209,6 +4237,7 @@ char* os::pd_attempt_reserve_memory_at(char* requested_addr, size_t bytes, bool
if (addr != nullptr) {
// mmap() is successful but it fails to reserve at the requested address
+ log_trace(os, map)("Kernel rejected " PTR_FORMAT ", offered " PTR_FORMAT ".", p2i(requested_addr), p2i(addr));
anon_munmap(addr, bytes);
}
@@ -4393,13 +4422,13 @@ static void check_pax(void) {
void os::init(void) {
char dummy; // used to get a guess on initial stack address
- clock_tics_per_sec = sysconf(_SC_CLK_TCK);
- int sys_pg_size = sysconf(_SC_PAGESIZE);
+ 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)",
os::strerror(errno));
}
- size_t page_size = (size_t) sys_pg_size;
+ size_t page_size = sys_pg_size;
OSInfo::set_vm_page_size(page_size);
OSInfo::set_vm_allocation_granularity(page_size);
if (os::vm_page_size() == 0) {
@@ -4743,7 +4772,7 @@ static int get_active_processor_count() {
// Note: keep this function, with its CPU_xx macros, *outside* the os namespace (see JDK-8289477).
cpu_set_t cpus; // can represent at most 1024 (CPU_SETSIZE) processors
cpu_set_t* cpus_p = &cpus;
- int cpus_size = sizeof(cpu_set_t);
+ size_t cpus_size = sizeof(cpu_set_t);
int configured_cpus = os::processor_count(); // upper bound on available cpus
int cpu_count = 0;
@@ -4767,7 +4796,7 @@ static int get_active_processor_count() {
}
else {
// failed to allocate so fallback to online cpus
- int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN);
+ int online_cpus = checked_cast(::sysconf(_SC_NPROCESSORS_ONLN));
log_trace(os)("active_processor_count: "
"CPU_ALLOC failed (%s) - using "
"online processor count: %d",
@@ -4799,7 +4828,7 @@ static int get_active_processor_count() {
log_trace(os)("active_processor_count: sched_getaffinity processor count: %d", cpu_count);
}
else {
- cpu_count = ::sysconf(_SC_NPROCESSORS_ONLN);
+ cpu_count = checked_cast(::sysconf(_SC_NPROCESSORS_ONLN));
warning("sched_getaffinity failed (%s)- using online processor count (%d) "
"which may exceed available processors", os::strerror(errno), cpu_count);
}
@@ -5161,7 +5190,7 @@ static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
pid_t tid = thread->osthread()->thread_id();
char *s;
char stat[2048];
- int statlen;
+ size_t statlen;
char proc_name[64];
int count;
long sys_time, user_time;
@@ -5307,7 +5336,7 @@ int os::get_core_path(char* buffer, size_t bufferSize) {
}
}
- return strlen(buffer);
+ return checked_cast(strlen(buffer));
}
bool os::start_debugging(char *buf, int buflen) {
@@ -5367,19 +5396,22 @@ bool os::start_debugging(char *buf, int buflen) {
// | |/
// P2 +------------------------+ Thread::stack_base()
//
-// ** P1 (aka bottom) and size (P2 = P1 - size) are the address and stack size
+// ** P1 (aka bottom) and size are the address and stack size
// returned from pthread_attr_getstack().
+// ** P2 (aka stack top or base) = P1 + size
// ** If adjustStackSizeForGuardPages() is true the guard pages have been taken
// out of the stack size given in pthread_attr. We work around this for
// threads created by the VM. We adjust bottom to be P1 and size accordingly.
//
#ifndef ZERO
-static void current_stack_region(address * bottom, size_t * size) {
+void os::current_stack_base_and_size(address* base, size_t* size) {
+ address bottom;
if (os::is_primordial_thread()) {
// primordial thread needs special handling because pthread_getattr_np()
// may return bogus value.
- *bottom = os::Linux::initial_thread_stack_bottom();
- *size = os::Linux::initial_thread_stack_size();
+ bottom = os::Linux::initial_thread_stack_bottom();
+ *size = os::Linux::initial_thread_stack_size();
+ *base = bottom + *size;
} else {
pthread_attr_t attr;
@@ -5394,42 +5426,28 @@ static void current_stack_region(address * bottom, size_t * size) {
}
}
- if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
+ if (pthread_attr_getstack(&attr, (void **)&bottom, size) != 0) {
fatal("Cannot locate current stack attributes!");
}
+ *base = bottom + *size;
+
if (os::Linux::adjustStackSizeForGuardPages()) {
size_t guard_size = 0;
rslt = pthread_attr_getguardsize(&attr, &guard_size);
if (rslt != 0) {
fatal("pthread_attr_getguardsize failed with error = %d", rslt);
}
- *bottom += guard_size;
- *size -= guard_size;
+ bottom += guard_size;
+ *size -= guard_size;
}
pthread_attr_destroy(&attr);
-
}
- assert(os::current_stack_pointer() >= *bottom &&
- os::current_stack_pointer() < *bottom + *size, "just checking");
+ assert(os::current_stack_pointer() >= bottom &&
+ os::current_stack_pointer() < *base, "just checking");
}
-address os::current_stack_base() {
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return (bottom + size);
-}
-
-size_t os::current_stack_size() {
- // This stack size includes the usable stack and HotSpot guard pages
- // (for the threads that have Hotspot guard pages).
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return size;
-}
#endif
static inline struct timespec get_mtime(const char* filename) {
@@ -5442,9 +5460,9 @@ static inline struct timespec get_mtime(const char* filename) {
int os::compare_file_modified_times(const char* file1, const char* file2) {
struct timespec filetime1 = get_mtime(file1);
struct timespec filetime2 = get_mtime(file2);
- int diff = filetime1.tv_sec - filetime2.tv_sec;
+ int diff = primitive_compare(filetime1.tv_sec, filetime2.tv_sec);
if (diff == 0) {
- return filetime1.tv_nsec - filetime2.tv_nsec;
+ diff = primitive_compare(filetime1.tv_nsec, filetime2.tv_nsec);
}
return diff;
}
diff --git a/src/hotspot/os/linux/os_perf_linux.cpp b/src/hotspot/os/linux/os_perf_linux.cpp
index ff416d47eb07f..cca41a12ee199 100644
--- a/src/hotspot/os/linux/os_perf_linux.cpp
+++ b/src/hotspot/os/linux/os_perf_linux.cpp
@@ -232,7 +232,7 @@ static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, dou
*/
static int SCANF_ARGS(2, 0) vread_statdata(const char* procfile, _SCANFMT_ const char* fmt, va_list args) {
FILE*f;
- int n;
+ ssize_t n;
char buf[2048];
if ((f = os::fopen(procfile, "r")) == nullptr) {
@@ -382,12 +382,12 @@ static double get_cpu_load(int which_logical_cpu, CPUPerfCounters* counters, dou
} else if (tdiff < (udiff + kdiff)) {
tdiff = udiff + kdiff;
}
- *pkernelLoad = (kdiff / (double)tdiff);
+ *pkernelLoad = ((double)kdiff / (double)tdiff);
// BUG9044876, normalize return values to sane values
*pkernelLoad = MAX2(*pkernelLoad, 0.0);
*pkernelLoad = MIN2(*pkernelLoad, 1.0);
- user_load = (udiff / (double)tdiff);
+ user_load = ((double)udiff / (double)tdiff);
user_load = MAX2(user_load, 0.0);
user_load = MIN2(user_load, 1.0);
@@ -473,7 +473,7 @@ static int perf_context_switch_rate(double* rate) {
if (d == 0) {
*rate = lastRate;
} else if (get_noof_context_switches(&sw) == 0) {
- *rate = ( (double)(sw - lastSwitches) / d ) * 1000;
+ *rate = ( (double)(sw - lastSwitches) / (double)d ) * 1000;
lastRate = *rate;
lastSwitches = sw;
if (bootTime != 0) {
diff --git a/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp b/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp
index afa17e0ade80b..446449a40e094 100644
--- a/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp
+++ b/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp
@@ -56,12 +56,12 @@ enum membarrier_cmd {
MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED = (1 << 4),
};
-static int membarrier(int cmd, unsigned int flags, int cpu_id) {
+static long membarrier(int cmd, unsigned int flags, int cpu_id) {
return syscall(SYS_membarrier, cmd, flags, cpu_id); // cpu_id only on >= 5.10
}
bool LinuxSystemMemoryBarrier::initialize() {
- int ret = membarrier(MEMBARRIER_CMD_QUERY, 0, 0);
+ long ret = membarrier(MEMBARRIER_CMD_QUERY, 0, 0);
if (ret < 0) {
log_info(os)("MEMBARRIER_CMD_QUERY unsupported");
return false;
@@ -78,6 +78,6 @@ bool LinuxSystemMemoryBarrier::initialize() {
}
void LinuxSystemMemoryBarrier::emit() {
- int s = membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED, 0, 0);
+ long s = membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED, 0, 0);
guarantee_with_errno(s >= 0, "MEMBARRIER_CMD_PRIVATE_EXPEDITED failed");
}
diff --git a/src/hotspot/os/linux/waitBarrier_linux.cpp b/src/hotspot/os/linux/waitBarrier_linux.cpp
index de36dd60e4930..2be31ce8366bb 100644
--- a/src/hotspot/os/linux/waitBarrier_linux.cpp
+++ b/src/hotspot/os/linux/waitBarrier_linux.cpp
@@ -37,7 +37,7 @@
#endif
#endif
-static int futex(volatile int *addr, int futex_op, int op_arg) {
+static long futex(volatile int *addr, int futex_op, int op_arg) {
return syscall(SYS_futex, addr, futex_op, op_arg, nullptr, nullptr, 0);
}
@@ -51,9 +51,9 @@ void LinuxWaitBarrier::arm(int barrier_tag) {
void LinuxWaitBarrier::disarm() {
assert(_futex_barrier != 0, "Should be armed/non-zero.");
_futex_barrier = 0;
- int s = futex(&_futex_barrier,
- FUTEX_WAKE_PRIVATE,
- INT_MAX /* wake a max of this many threads */);
+ long s = futex(&_futex_barrier,
+ FUTEX_WAKE_PRIVATE,
+ INT_MAX /* wake a max of this many threads */);
guarantee_with_errno(s > -1, "futex FUTEX_WAKE failed");
}
@@ -65,9 +65,9 @@ void LinuxWaitBarrier::wait(int barrier_tag) {
return;
}
do {
- int s = futex(&_futex_barrier,
- FUTEX_WAIT_PRIVATE,
- barrier_tag /* should be this tag */);
+ long s = futex(&_futex_barrier,
+ FUTEX_WAIT_PRIVATE,
+ barrier_tag /* should be this tag */);
guarantee_with_errno((s == 0) ||
(s == -1 && errno == EAGAIN) ||
(s == -1 && errno == EINTR),
diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp
index 74929c982a634..c302a5d031ca3 100644
--- a/src/hotspot/os/posix/os_posix.cpp
+++ b/src/hotspot/os/posix/os_posix.cpp
@@ -42,6 +42,7 @@
#include "runtime/park.hpp"
#include "runtime/perfMemory.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/events.hpp"
@@ -49,6 +50,10 @@
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include "utilities/vmError.hpp"
+#if INCLUDE_JFR
+#include "jfr/jfrEvents.hpp"
+#endif
+
#ifdef AIX
#include "loadlib_aix.hpp"
#endif
@@ -445,7 +450,7 @@ void os::Posix::print_load_average(outputStream* st) {
// for reboot at least on my test machines
void os::Posix::print_uptime_info(outputStream* st) {
int bootsec = -1;
- int currsec = time(nullptr);
+ time_t currsec = time(nullptr);
struct utmpx* ent;
setutxent();
while ((ent = getutxent())) {
@@ -456,7 +461,7 @@ void os::Posix::print_uptime_info(outputStream* st) {
}
if (bootsec != -1) {
- os::print_dhm(st, "OS uptime:", (long) (currsec-bootsec));
+ os::print_dhm(st, "OS uptime:", currsec-bootsec);
}
}
@@ -714,6 +719,7 @@ void os::dll_unload(void *lib) {
// calling dlclose the dynamic loader may free the memory containing the string, thus we need to
// copy the string to be able to reference it after dlclose.
const char* l_path = nullptr;
+
#ifdef LINUX
char* l_pathdup = nullptr;
l_path = os::Linux::dll_path(lib);
@@ -721,6 +727,12 @@ void os::dll_unload(void *lib) {
l_path = l_pathdup = os::strdup(l_path);
}
#endif // LINUX
+
+#if INCLUDE_JFR
+ EventNativeLibraryUnload event;
+ event.set_name(l_path);
+#endif
+
if (l_path == nullptr) {
l_path = "";
}
@@ -730,6 +742,11 @@ void os::dll_unload(void *lib) {
Events::log_dll_message(nullptr, "Unloaded shared library \"%s\" [" INTPTR_FORMAT "]",
l_path, p2i(lib));
log_info(os)("Unloaded shared library \"%s\" [" INTPTR_FORMAT "]", l_path, p2i(lib));
+#if INCLUDE_JFR
+ event.set_success(true);
+ event.set_errorMessage(nullptr);
+ event.commit();
+#endif
} else {
const char* error_report = ::dlerror();
if (error_report == nullptr) {
@@ -740,6 +757,11 @@ void os::dll_unload(void *lib) {
l_path, p2i(lib), error_report);
log_info(os)("Attempt to unload shared library \"%s\" [" INTPTR_FORMAT "] failed, %s",
l_path, p2i(lib), error_report);
+#if INCLUDE_JFR
+ event.set_success(false);
+ event.set_errorMessage(error_report);
+ event.commit();
+#endif
}
// Update the dll cache
AIX_ONLY(LoadedLibraries::reload());
@@ -799,20 +821,20 @@ int os::socket_close(int fd) {
return ::close(fd);
}
-int os::recv(int fd, char* buf, size_t nBytes, uint flags) {
- RESTARTABLE_RETURN_INT(::recv(fd, buf, nBytes, flags));
+ssize_t os::recv(int fd, char* buf, size_t nBytes, uint flags) {
+ RESTARTABLE_RETURN_SSIZE_T(::recv(fd, buf, nBytes, flags));
}
-int os::send(int fd, char* buf, size_t nBytes, uint flags) {
- RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, flags));
+ssize_t os::send(int fd, char* buf, size_t nBytes, uint flags) {
+ RESTARTABLE_RETURN_SSIZE_T(::send(fd, buf, nBytes, flags));
}
-int os::raw_send(int fd, char* buf, size_t nBytes, uint flags) {
+ssize_t os::raw_send(int fd, char* buf, size_t nBytes, uint flags) {
return os::send(fd, buf, nBytes, flags);
}
-int os::connect(int fd, struct sockaddr* him, socklen_t len) {
- RESTARTABLE_RETURN_INT(::connect(fd, him, len));
+ssize_t os::connect(int fd, struct sockaddr* him, socklen_t len) {
+ RESTARTABLE_RETURN_SSIZE_T(::connect(fd, him, len));
}
void os::exit(int num) {
@@ -1208,7 +1230,7 @@ void os::Posix::init(void) {
#if defined(_ALLBSD_SOURCE)
clock_tics_per_sec = CLK_TCK;
#else
- clock_tics_per_sec = sysconf(_SC_CLK_TCK);
+ clock_tics_per_sec = checked_cast(sysconf(_SC_CLK_TCK));
#endif
// NOTE: no logging available when this is called. Put logging
// statements in init_2().
@@ -1332,7 +1354,7 @@ static jlong millis_to_nanos_bounded(jlong millis) {
static void to_abstime(timespec* abstime, jlong timeout,
bool isAbsolute, bool isRealtime) {
- DEBUG_ONLY(int max_secs = MAX_SECS;)
+ DEBUG_ONLY(time_t max_secs = MAX_SECS;)
if (timeout < 0) {
timeout = 0;
@@ -1414,7 +1436,7 @@ void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
// Time since start-up in seconds to a fine granularity.
double os::elapsedTime() {
- return ((double)os::elapsed_counter()) / os::elapsed_frequency(); // nanosecond resolution
+ return ((double)os::elapsed_counter()) / (double)os::elapsed_frequency(); // nanosecond resolution
}
jlong os::elapsed_counter() {
diff --git a/src/hotspot/os/posix/os_posix.hpp b/src/hotspot/os/posix/os_posix.hpp
index 051b23d51bdb7..8c71516f70b8f 100644
--- a/src/hotspot/os/posix/os_posix.hpp
+++ b/src/hotspot/os/posix/os_posix.hpp
@@ -44,8 +44,8 @@
_result = _cmd; \
} while(((int)_result == OS_ERR) && (errno == EINTR))
-#define RESTARTABLE_RETURN_INT(_cmd) do { \
- int _result; \
+#define RESTARTABLE_RETURN_SSIZE_T(_cmd) do { \
+ ssize_t _result; \
RESTARTABLE(_cmd, _result); \
return _result; \
} while(false)
diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp
index 285e69ba150cd..eaadb36731518 100644
--- a/src/hotspot/os/posix/signals_posix.cpp
+++ b/src/hotspot/os/posix/signals_posix.cpp
@@ -42,8 +42,10 @@
#include "runtime/threadCrashProtection.hpp"
#include "signals_posix.hpp"
#include "suspendResume_posix.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/events.hpp"
#include "utilities/ostream.hpp"
+#include "utilities/parseInteger.hpp"
#include "utilities/vmError.hpp"
#include
@@ -681,7 +683,7 @@ static void UserHandler(int sig, siginfo_t* siginfo, void* context) {
static void print_signal_handler_name(outputStream* os, address handler, char* buf, size_t buflen) {
// We demangle, but omit arguments - signal handlers should have always the same prototype.
- os::print_function_and_library_name(os, handler, buf, buflen,
+ os::print_function_and_library_name(os, handler, buf, checked_cast(buflen),
true, // shorten_path
true, // demangle
true // omit arguments
@@ -1726,13 +1728,14 @@ int SR_initialize() {
char *s;
// Get signal number to use for suspend/resume
if ((s = ::getenv("_JAVA_SR_SIGNUM")) != 0) {
- int sig = ::strtol(s, 0, 10);
- if (sig > MAX2(SIGSEGV, SIGBUS) && // See 4355769.
+ int sig;
+ bool result = parse_integer(s, &sig);
+ if (result && sig > MAX2(SIGSEGV, SIGBUS) && // See 4355769.
sig < NSIG) { // Must be legal signal and fit into sigflags[].
PosixSignals::SR_signum = sig;
} else {
- warning("You set _JAVA_SR_SIGNUM=%d. It must be in range [%d, %d]. Using %d instead.",
- sig, MAX2(SIGSEGV, SIGBUS)+1, NSIG-1, PosixSignals::SR_signum);
+ warning("You set _JAVA_SR_SIGNUM=%s. It must be a number in range [%d, %d]. Using %d instead.",
+ s, MAX2(SIGSEGV, SIGBUS)+1, NSIG-1, PosixSignals::SR_signum);
}
}
diff --git a/src/hotspot/os/windows/attachListener_windows.cpp b/src/hotspot/os/windows/attachListener_windows.cpp
index 8cd4d8d671575..da3b6c56739f0 100644
--- a/src/hotspot/os/windows/attachListener_windows.cpp
+++ b/src/hotspot/os/windows/attachListener_windows.cpp
@@ -391,15 +391,6 @@ void AttachListener::pd_data_dump() {
os::signal_notify(SIGBREAK);
}
-AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) {
- return nullptr;
-}
-
-jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) {
- out->print_cr("flag '%s' cannot be changed", op->arg(0));
- return JNI_ERR;
-}
-
void AttachListener::pd_detachall() {
// do nothing for now
}
diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp
index 0a417bda1d380..ad88e714bfc40 100644
--- a/src/hotspot/os/windows/os_windows.cpp
+++ b/src/hotspot/os/windows/os_windows.cpp
@@ -425,40 +425,31 @@ int os::get_native_stack(address* stack, int frames, int toSkip) {
return captured;
}
-// os::current_stack_base()
-//
// Returns the base of the stack, which is the stack's
// starting address. This function must be called
// while running on the stack of the thread being queried.
-address os::current_stack_base() {
+void os::current_stack_base_and_size(address* stack_base, size_t* stack_size) {
MEMORY_BASIC_INFORMATION minfo;
address stack_bottom;
- size_t stack_size;
+ size_t size;
VirtualQuery(&minfo, &minfo, sizeof(minfo));
- stack_bottom = (address)minfo.AllocationBase;
- stack_size = minfo.RegionSize;
+ stack_bottom = (address)minfo.AllocationBase;
+ size = minfo.RegionSize;
// Add up the sizes of all the regions with the same
// AllocationBase.
while (1) {
- VirtualQuery(stack_bottom+stack_size, &minfo, sizeof(minfo));
+ VirtualQuery(stack_bottom + size, &minfo, sizeof(minfo));
if (stack_bottom == (address)minfo.AllocationBase) {
- stack_size += minfo.RegionSize;
+ size += minfo.RegionSize;
} else {
break;
}
}
- return stack_bottom + stack_size;
-}
-
-size_t os::current_stack_size() {
- size_t sz;
- MEMORY_BASIC_INFORMATION minfo;
- VirtualQuery(&minfo, &minfo, sizeof(minfo));
- sz = (size_t)os::current_stack_base() - (size_t)minfo.AllocationBase;
- return sz;
+ *stack_base = stack_bottom + size;
+ *stack_size = size;
}
bool os::committed_in_range(address start, size_t size, address& committed_start, size_t& committed_size) {
@@ -1254,13 +1245,34 @@ void os::dll_unload(void *lib) {
if (::GetModuleFileName((HMODULE)lib, name, sizeof(name)) == 0) {
snprintf(name, MAX_PATH, "");
}
+
+#if INCLUDE_JFR
+ EventNativeLibraryUnload event;
+ event.set_name(name);
+#endif
+
if (::FreeLibrary((HMODULE)lib)) {
Events::log_dll_message(nullptr, "Unloaded dll \"%s\" [" INTPTR_FORMAT "]", name, p2i(lib));
log_info(os)("Unloaded dll \"%s\" [" INTPTR_FORMAT "]", name, p2i(lib));
+#if INCLUDE_JFR
+ event.set_success(true);
+ event.set_errorMessage(nullptr);
+ event.commit();
+#endif
} else {
const DWORD errcode = ::GetLastError();
+ char buf[500];
+ size_t tl = os::lasterror(buf, sizeof(buf));
Events::log_dll_message(nullptr, "Attempt to unload dll \"%s\" [" INTPTR_FORMAT "] failed (error code %d)", name, p2i(lib), errcode);
log_info(os)("Attempt to unload dll \"%s\" [" INTPTR_FORMAT "] failed (error code %d)", name, p2i(lib), errcode);
+#if INCLUDE_JFR
+ event.set_success(false);
+ if (tl == 0) {
+ os::snprintf(buf, sizeof(buf), "Attempt to unload dll failed (error code %d)", (int) errcode);
+ }
+ event.set_errorMessage(buf);
+ event.commit();
+#endif
}
}
@@ -1762,7 +1774,7 @@ static inline time_t get_mtime(const char* filename) {
int os::compare_file_modified_times(const char* file1, const char* file2) {
time_t t1 = get_mtime(file1);
time_t t2 = get_mtime(file2);
- return t1 - t2;
+ return primitive_compare(t1, t2);
}
void os::print_os_info_brief(outputStream* st) {
@@ -5608,19 +5620,19 @@ int os::socket_close(int fd) {
return ::closesocket(fd);
}
-int os::connect(int fd, struct sockaddr* him, socklen_t len) {
+ssize_t os::connect(int fd, struct sockaddr* him, socklen_t len) {
return ::connect(fd, him, len);
}
-int os::recv(int fd, char* buf, size_t nBytes, uint flags) {
+ssize_t os::recv(int fd, char* buf, size_t nBytes, uint flags) {
return ::recv(fd, buf, (int)nBytes, flags);
}
-int os::send(int fd, char* buf, size_t nBytes, uint flags) {
+ssize_t os::send(int fd, char* buf, size_t nBytes, uint flags) {
return ::send(fd, buf, (int)nBytes, flags);
}
-int os::raw_send(int fd, char* buf, size_t nBytes, uint flags) {
+ssize_t os::raw_send(int fd, char* buf, size_t nBytes, uint flags) {
return ::send(fd, buf, (int)nBytes, flags);
}
diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
index 3882ed6770389..2ade1c7153be9 100644
--- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
+++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp
@@ -463,7 +463,7 @@ void os::print_tos_pc(outputStream *st, const void *context) {
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
- print_instructions(st, pc, /*instrsize=*/4);
+ print_instructions(st, pc);
st->cr();
// Try to decode the instructions.
diff --git a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp
index ae5d249a5db08..ff84024088e75 100644
--- a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp
+++ b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp
@@ -354,13 +354,13 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M);
return s;
}
-
-static void current_stack_region(address * bottom, size_t * size) {
+void os::current_stack_base_and_size(address* base, size_t* size) {
+ address bottom;
#ifdef __APPLE__
pthread_t self = pthread_self();
- void *stacktop = pthread_get_stackaddr_np(self);
+ *base = (address) pthread_get_stackaddr_np(self);
*size = pthread_get_stacksize_np(self);
- *bottom = (address) stacktop - *size;
+ bottom = *base - *size;
#elif defined(__OpenBSD__)
stack_t ss;
int rslt = pthread_stackseg_np(pthread_self(), &ss);
@@ -368,8 +368,9 @@ static void current_stack_region(address * bottom, size_t * size) {
if (rslt != 0)
fatal("pthread_stackseg_np failed with error = %d", rslt);
- *bottom = (address)((char *)ss.ss_sp - ss.ss_size);
- *size = ss.ss_size;
+ *base = (address) ss.ss_sp;
+ *size = ss.ss_size;
+ bottom = *base - *size;
#else
pthread_attr_t attr;
@@ -384,30 +385,17 @@ static void current_stack_region(address * bottom, size_t * size) {
if (rslt != 0)
fatal("pthread_attr_get_np failed with error = %d", rslt);
- if (pthread_attr_getstackaddr(&attr, (void **)bottom) != 0 ||
- pthread_attr_getstacksize(&attr, size) != 0) {
+ if (pthread_attr_getstackaddr(&attr, (void **)&bottom) != 0 ||
+ pthread_attr_getstacksize(&attr, size) != 0) {
fatal("Can not locate current stack attributes!");
}
+ *base = bottom + *size;
+
pthread_attr_destroy(&attr);
#endif
- assert(os::current_stack_pointer() >= *bottom &&
- os::current_stack_pointer() < *bottom + *size, "just checking");
-}
-
-address os::current_stack_base() {
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return (bottom + size);
-}
-
-size_t os::current_stack_size() {
- // stack size includes normal stack and HotSpot guard pages
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return size;
+ assert(os::current_stack_pointer() >= bottom &&
+ os::current_stack_pointer() < *base, "just checking");
}
/////////////////////////////////////////////////////////////////////////////
@@ -477,7 +465,7 @@ void os::print_tos_pc(outputStream *st, const void *context) {
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
- print_instructions(st, pc, 4/*native instruction size*/);
+ print_instructions(st, pc);
st->cr();
}
diff --git a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp
index 961464fa38dea..37b92bc7ffd48 100644
--- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp
+++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp
@@ -79,7 +79,7 @@
# include
#endif
-// needed by current_stack_region() workaround for Mavericks
+// needed by current_stack_base_and_size() workaround for Mavericks
#if defined(__APPLE__)
# include
# include
@@ -709,13 +709,15 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
// | |/
// P2 +------------------------+ Thread::stack_base()
//
-// ** P1 (aka bottom) and size ( P2 = P1 - size) are the address and stack size returned from
-// pthread_attr_getstack()
+// ** P1 (aka bottom) and size are the address and stack size
+// returned from pthread_attr_getstack().
+// ** P2 (aka stack top or base) = P1 + size
-static void current_stack_region(address * bottom, size_t * size) {
+void os::current_stack_base_and_size(address* base, size_t* size) {
+ address bottom;
#ifdef __APPLE__
pthread_t self = pthread_self();
- void *stacktop = pthread_get_stackaddr_np(self);
+ *base = (address) pthread_get_stackaddr_np(self);
*size = pthread_get_stacksize_np(self);
// workaround for OS X 10.9.0 (Mavericks)
// pthread_get_stacksize_np returns 128 pages even though the actual size is 2048 pages
@@ -738,7 +740,7 @@ static void current_stack_region(address * bottom, size_t * size) {
}
}
}
- *bottom = (address) stacktop - *size;
+ bottom = *base - *size;
#elif defined(__OpenBSD__)
stack_t ss;
int rslt = pthread_stackseg_np(pthread_self(), &ss);
@@ -746,8 +748,9 @@ static void current_stack_region(address * bottom, size_t * size) {
if (rslt != 0)
fatal("pthread_stackseg_np failed with error = %d", rslt);
- *bottom = (address)((char *)ss.ss_sp - ss.ss_size);
- *size = ss.ss_size;
+ *base = (address) ss.ss_sp;
+ *size = ss.ss_size;
+ bottom = *base - *size;
#else
pthread_attr_t attr;
@@ -762,30 +765,17 @@ static void current_stack_region(address * bottom, size_t * size) {
if (rslt != 0)
fatal("pthread_attr_get_np failed with error = %d", rslt);
- if (pthread_attr_getstackaddr(&attr, (void **)bottom) != 0 ||
- pthread_attr_getstacksize(&attr, size) != 0) {
+ if (pthread_attr_getstackaddr(&attr, (void **)&bottom) != 0 ||
+ pthread_attr_getstacksize(&attr, size) != 0) {
fatal("Can not locate current stack attributes!");
}
+ *base = bottom + *size;
+
pthread_attr_destroy(&attr);
#endif
- assert(os::current_stack_pointer() >= *bottom &&
- os::current_stack_pointer() < *bottom + *size, "just checking");
-}
-
-address os::current_stack_base() {
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return (bottom + size);
-}
-
-size_t os::current_stack_size() {
- // stack size includes normal stack and HotSpot guard pages
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return size;
+ assert(os::current_stack_pointer() >= bottom &&
+ os::current_stack_pointer() < *base, "just checking");
}
/////////////////////////////////////////////////////////////////////////////
@@ -854,7 +844,7 @@ void os::print_tos_pc(outputStream *st, const void *context) {
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
- print_instructions(st, pc, sizeof(char));
+ print_instructions(st, pc);
st->cr();
}
diff --git a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
index 55b5efd5f6efc..7e28a000af08e 100644
--- a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
+++ b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp
@@ -176,26 +176,24 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
return s;
}
-static void current_stack_region(address *bottom, size_t *size) {
- address stack_bottom;
- address stack_top;
- size_t stack_bytes;
+void os::current_stack_base_and_size(address* base, size_t* size)
+ address bottom;
#ifdef __APPLE__
pthread_t self = pthread_self();
- stack_top = (address) pthread_get_stackaddr_np(self);
- stack_bytes = pthread_get_stacksize_np(self);
- stack_bottom = stack_top - stack_bytes;
+ *base = (address) pthread_get_stackaddr_np(self);
+ *size = pthread_get_stacksize_np(self);
+ bottom = *base - *size;
#elif defined(__OpenBSD__)
stack_t ss;
int rslt = pthread_stackseg_np(pthread_self(), &ss);
if (rslt != 0)
- fatal("pthread_stackseg_np failed with error = " INT32_FORMAT, rslt);
+ fatal("pthread_stackseg_np failed with error = %d", rslt);
- stack_top = (address) ss.ss_sp;
- stack_bytes = ss.ss_size;
- stack_bottom = stack_top - stack_bytes;
+ *base = (address) ss.ss_sp;
+ *size = ss.ss_size;
+ bottom = *base - *size;
#else
pthread_attr_t attr;
@@ -203,43 +201,25 @@ static void current_stack_region(address *bottom, size_t *size) {
// JVM needs to know exact stack location, abort if it fails
if (rslt != 0)
- fatal("pthread_attr_init failed with error = " INT32_FORMAT, rslt);
+ fatal("pthread_attr_init failed with error = %d", rslt);
rslt = pthread_attr_get_np(pthread_self(), &attr);
if (rslt != 0)
- fatal("pthread_attr_get_np failed with error = " INT32_FORMAT, rslt);
+ fatal("pthread_attr_get_np failed with error = %d", rslt);
- if (pthread_attr_getstackaddr(&attr, (void **) &stack_bottom) != 0 ||
- pthread_attr_getstacksize(&attr, &stack_bytes) != 0) {
+ if (pthread_attr_getstackaddr(&attr, (void **) &bottom) != 0 ||
+ pthread_attr_getstacksize(&attr, size) != 0) {
fatal("Can not locate current stack attributes!");
}
+ *base = bottom + *size;
+
pthread_attr_destroy(&attr);
- stack_top = stack_bottom + stack_bytes;
#endif
-
- assert(os::current_stack_pointer() >= stack_bottom, "should do");
- assert(os::current_stack_pointer() < stack_top, "should do");
-
- *bottom = stack_bottom;
- *size = stack_top - stack_bottom;
-}
-
-address os::current_stack_base() {
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return bottom + size;
-}
-
-size_t os::current_stack_size() {
- // stack size includes normal stack and HotSpot guard pages
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return size;
+ assert(os::current_stack_pointer() >= bottom &&
+ os::current_stack_pointer() < *base, "just checking");
}
/////////////////////////////////////////////////////////////////////////////
diff --git a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
index 28e17385d4339..70581166cf1df 100644
--- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
+++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
@@ -355,7 +355,7 @@ void os::print_tos_pc(outputStream *st, const void *context) {
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::fetch_frame_from_context(uc).pc();
- print_instructions(st, pc, 4/*native instruction size*/);
+ print_instructions(st, pc);
st->cr();
}
diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
index 3bbe93fe798e4..86e8ed25618c1 100644
--- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
+++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
@@ -483,7 +483,7 @@ void os::print_tos_pc(outputStream *st, const void *context) {
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
- print_instructions(st, pc, Assembler::InstructionSize);
+ print_instructions(st, pc);
st->cr();
}
diff --git a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
index e5837af0a73f5..2e603ac06909b 100644
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
+++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
@@ -477,7 +477,7 @@ void os::print_tos_pc(outputStream *st, const void *context) {
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
- print_instructions(st, pc, /*instrsize=*/4);
+ print_instructions(st, pc);
st->cr();
}
diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp
index 814ae19d639fe..6eeb76acbbfc4 100644
--- a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp
+++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp
@@ -367,7 +367,7 @@ void os::print_tos_pc(outputStream *st, const void *context) {
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::fetch_frame_from_context(uc).pc();
- print_instructions(st, pc, UseRVC ? sizeof(char) : (int)NativeInstruction::instruction_size);
+ print_instructions(st, pc);
st->cr();
}
diff --git a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp
index 206573b078ae5..033ea14ead6a4 100644
--- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp
+++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp
@@ -456,7 +456,7 @@ void os::print_tos_pc(outputStream *st, const void *context) {
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
- print_instructions(st, pc, /*intrsize=*/4);
+ print_instructions(st, pc);
st->cr();
}
diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
index 930cf3f2657d5..db5e1ed4bf212 100644
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
@@ -463,7 +463,7 @@ juint os::cpu_microcode_revision() {
fp = os::fopen("/proc/cpuinfo", "r");
if (fp) {
char data[2048] = {0}; // lines should fit in 2K buf
- size_t len = sizeof(data);
+ int len = (int)sizeof(data);
while (!feof(fp)) {
if (fgets(data, len, fp)) {
if (strstr(data, "microcode") != nullptr) {
@@ -571,7 +571,7 @@ void os::print_tos_pc(outputStream *st, const void *context) {
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::fetch_frame_from_context(uc).pc();
- print_instructions(st, pc, sizeof(char));
+ print_instructions(st, pc);
st->cr();
}
diff --git a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
index 101dbdcb4d10b..26a620cc81906 100644
--- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
+++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp
@@ -306,89 +306,68 @@ size_t os::Posix::default_stack_size(os::ThreadType thr_type) {
return s;
}
-static void current_stack_region(address *bottom, size_t *size) {
+void os::current_stack_base_and_size(address* base, size_t* size) {
+ address bottom;
if (os::is_primordial_thread()) {
// primordial thread needs special handling because pthread_getattr_np()
// may return bogus value.
- address stack_bottom = os::Linux::initial_thread_stack_bottom();
- size_t stack_bytes = os::Linux::initial_thread_stack_size();
+ bottom = os::Linux::initial_thread_stack_bottom();
+ *size = os::Linux::initial_thread_stack_size();
+ *base = bottom + *size;
+ } else {
- assert(os::current_stack_pointer() >= stack_bottom, "should do");
- assert(os::current_stack_pointer() < stack_bottom + stack_bytes, "should do");
+ pthread_attr_t attr;
- *bottom = stack_bottom;
- *size = stack_bytes;
- return;
- }
+ int rslt = pthread_getattr_np(pthread_self(), &attr);
- pthread_attr_t attr;
- int res = pthread_getattr_np(pthread_self(), &attr);
- if (res != 0) {
- if (res == ENOMEM) {
- vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
+ // JVM needs to know exact stack location, abort if it fails
+ if (rslt != 0) {
+ if (rslt == ENOMEM) {
+ vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np");
+ } else {
+ fatal("pthread_getattr_np failed with error = %d", rslt);
+ }
}
- else {
- fatal("pthread_getattr_np failed with error = %d", res);
+
+ if (pthread_attr_getstack(&attr, (void **)&bottom, size) != 0) {
+ fatal("Cannot locate current stack attributes!");
}
- }
- address stack_bottom;
- size_t stack_bytes;
- res = pthread_attr_getstack(&attr, (void **) &stack_bottom, &stack_bytes);
- if (res != 0) {
- fatal("pthread_attr_getstack failed with error = %d", res);
- }
- address stack_top = stack_bottom + stack_bytes;
+ *base = bottom + *size;
- // The block of memory returned by pthread_attr_getstack() includes
- // guard pages where present. We need to trim these off.
- size_t page_bytes = os::vm_page_size();
- assert(((intptr_t) stack_bottom & (page_bytes - 1)) == 0, "unaligned stack");
+ // The block of memory returned by pthread_attr_getstack() includes
+ // guard pages where present. We need to trim these off.
+ size_t page_bytes = os::vm_page_size();
+ assert(((intptr_t) bottom & (page_bytes - 1)) == 0, "unaligned stack");
- size_t guard_bytes;
- res = pthread_attr_getguardsize(&attr, &guard_bytes);
- if (res != 0) {
- fatal("pthread_attr_getguardsize failed with errno = %d", res);
- }
- int guard_pages = align_up(guard_bytes, page_bytes) / page_bytes;
- assert(guard_bytes == guard_pages * page_bytes, "unaligned guard");
+ size_t guard_bytes;
+ rslt = pthread_attr_getguardsize(&attr, &guard_bytes);
+ if (rslt != 0) {
+ fatal("pthread_attr_getguardsize failed with errno = %d", rslt);
+ }
+ int guard_pages = align_up(guard_bytes, page_bytes) / page_bytes;
+ assert(guard_bytes == guard_pages * page_bytes, "unaligned guard");
#ifdef IA64
- // IA64 has two stacks sharing the same area of memory, a normal
- // stack growing downwards and a register stack growing upwards.
- // Guard pages, if present, are in the centre. This code splits
- // the stack in two even without guard pages, though in theory
- // there's nothing to stop us allocating more to the normal stack
- // or more to the register stack if one or the other were found
- // to grow faster.
- int total_pages = align_down(stack_bytes, page_bytes) / page_bytes;
- stack_bottom += (total_pages - guard_pages) / 2 * page_bytes;
+ // IA64 has two stacks sharing the same area of memory, a normal
+ // stack growing downwards and a register stack growing upwards.
+ // Guard pages, if present, are in the centre. This code splits
+ // the stack in two even without guard pages, though in theory
+ // there's nothing to stop us allocating more to the normal stack
+ // or more to the register stack if one or the other were found
+ // to grow faster.
+ int total_pages = align_down(stack_bytes, page_bytes) / page_bytes;
+ bottom += (total_pages - guard_pages) / 2 * page_bytes;
#endif // IA64
- stack_bottom += guard_bytes;
+ bottom += guard_bytes;
+ *size = *base - bottom;
- pthread_attr_destroy(&attr);
-
- assert(os::current_stack_pointer() >= stack_bottom, "should do");
- assert(os::current_stack_pointer() < stack_top, "should do");
-
- *bottom = stack_bottom;
- *size = stack_top - stack_bottom;
-}
-
-address os::current_stack_base() {
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return bottom + size;
-}
+ pthread_attr_destroy(&attr);
+ }
-size_t os::current_stack_size() {
- // stack size includes normal stack and HotSpot guard pages
- address bottom;
- size_t size;
- current_stack_region(&bottom, &size);
- return size;
+ assert(os::current_stack_pointer() >= bottom &&
+ os::current_stack_pointer() < *base, "just checking");
}
/////////////////////////////////////////////////////////////////////////////
@@ -409,7 +388,7 @@ void os::print_tos_pc(outputStream *st, const void* ucVoid) {
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::Posix::ucontext_get_pc(uc);
- print_instructions(st, pc, sizeof(char));
+ print_instructions(st, pc);
st->cr();
}
diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp
index d92e089f02bab..4e18334315a37 100644
--- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp
+++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp
@@ -469,7 +469,7 @@ void os::print_tos_pc(outputStream *st, const void *context) {
// point to garbage if entry point in an nmethod is corrupted. Leave
// this at the end, and hope for the best.
address pc = os::fetch_frame_from_context(uc).pc();
- print_instructions(st, pc, sizeof(char));
+ print_instructions(st, pc);
st->cr();
}
diff --git a/src/hotspot/share/asm/assembler.cpp b/src/hotspot/share/asm/assembler.cpp
index f65890860da64..4e19effff61ac 100644
--- a/src/hotspot/share/asm/assembler.cpp
+++ b/src/hotspot/share/asm/assembler.cpp
@@ -32,6 +32,7 @@
#include "runtime/icache.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/os.hpp"
+#include "utilities/checkedCast.hpp"
// Implementation of AbstractAssembler
//
diff --git a/src/hotspot/share/asm/assembler.hpp b/src/hotspot/share/asm/assembler.hpp
index e38b87ff5095c..7b7dbd4ede7dd 100644
--- a/src/hotspot/share/asm/assembler.hpp
+++ b/src/hotspot/share/asm/assembler.hpp
@@ -30,6 +30,7 @@
#include "code/oopRecorder.hpp"
#include "code/relocInfo.hpp"
#include "memory/allocation.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp
index ec06cbb1b41e7..567cd5fa8b5d3 100644
--- a/src/hotspot/share/c1/c1_Compiler.cpp
+++ b/src/hotspot/share/c1/c1_Compiler.cpp
@@ -104,7 +104,10 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) {
// C1 does not support intrinsification of synchronized methods.
return false;
}
+ return Compiler::is_intrinsic_supported(id);
+}
+bool Compiler::is_intrinsic_supported(vmIntrinsics::ID id) {
switch (id) {
case vmIntrinsics::_compareAndSetLong:
if (!VM_Version::supports_cx8()) return false;
diff --git a/src/hotspot/share/c1/c1_Compiler.hpp b/src/hotspot/share/c1/c1_Compiler.hpp
index 8f2afa85dbaab..9095a13297eed 100644
--- a/src/hotspot/share/c1/c1_Compiler.hpp
+++ b/src/hotspot/share/c1/c1_Compiler.hpp
@@ -56,6 +56,9 @@ class Compiler: public AbstractCompiler {
// Check if the C1 compiler supports an intrinsic for 'method'.
virtual bool is_intrinsic_supported(const methodHandle& method);
+ // Return true if the intrinsic `id` is supported by C1
+ static bool is_intrinsic_supported(vmIntrinsics::ID id);
+
// Size of the code buffer
static int code_buffer_size();
};
diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp
index 964926f4e9b3c..4571f8f5adb92 100644
--- a/src/hotspot/share/c1/c1_GraphBuilder.cpp
+++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp
@@ -45,6 +45,7 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/vm_version.hpp"
#include "utilities/bitMap.inline.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/powerOfTwo.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_JFR
diff --git a/src/hotspot/share/cds/archiveHeapWriter.cpp b/src/hotspot/share/cds/archiveHeapWriter.cpp
index 76db688ac233c..3799664e1b51d 100644
--- a/src/hotspot/share/cds/archiveHeapWriter.cpp
+++ b/src/hotspot/share/cds/archiveHeapWriter.cpp
@@ -467,7 +467,7 @@ void ArchiveHeapWriter::update_header_for_requested_obj(oop requested_obj, oop s
// identity_hash for all shared objects, so they are less likely to be written
// into during run time, increasing the potential of memory sharing.
if (src_obj != nullptr) {
- int src_hash = src_obj->identity_hash();
+ intptr_t src_hash = src_obj->identity_hash();
if (UseCompactObjectHeaders) {
fake_oop->set_mark(markWord::prototype().set_narrow_klass(nk).copy_set_hash(src_hash));
} else {
@@ -475,8 +475,8 @@ void ArchiveHeapWriter::update_header_for_requested_obj(oop requested_obj, oop s
}
assert(fake_oop->mark().is_unlocked(), "sanity");
- DEBUG_ONLY(int archived_hash = fake_oop->identity_hash());
- assert(src_hash == archived_hash, "Different hash codes: original %x, archived %x", src_hash, archived_hash);
+ DEBUG_ONLY(intptr_t archived_hash = fake_oop->identity_hash());
+ assert(src_hash == archived_hash, "Different hash codes: original " INTPTR_FORMAT ", archived " INTPTR_FORMAT, src_hash, archived_hash);
}
}
diff --git a/src/hotspot/share/cds/classListParser.cpp b/src/hotspot/share/cds/classListParser.cpp
index 9c269aecf3294..e2099620a7761 100644
--- a/src/hotspot/share/cds/classListParser.cpp
+++ b/src/hotspot/share/cds/classListParser.cpp
@@ -73,6 +73,7 @@ ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) : _id2k
vm_exit_during_initialization("Loading classlist failed", errmsg);
}
_line_no = 0;
+ _token = _line;
_interfaces = new (mtClass) GrowableArray(10, mtClass);
_indy_items = new (mtClass) GrowableArray(9, mtClass);
_parse_mode = parse_mode;
@@ -413,7 +414,7 @@ void ClassListParser::print_actual_interfaces(InstanceKlass* ik) {
void ClassListParser::error(const char* msg, ...) {
va_list ap;
va_start(ap, msg);
- int error_index = _token - _line;
+ int error_index = pointer_delta_as_int(_token, _line);
if (error_index >= _line_len) {
error_index = _line_len - 1;
}
diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp
index 987ab6a0afc1a..08a366325e935 100644
--- a/src/hotspot/share/cds/filemap.cpp
+++ b/src/hotspot/share/cds/filemap.cpp
@@ -224,8 +224,8 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment,
_app_class_paths_start_index = ClassLoaderExt::app_class_paths_start_index();
_app_module_paths_start_index = ClassLoaderExt::app_module_paths_start_index();
- _num_module_paths = ClassLoader::num_module_path_entries();
_max_used_path_index = ClassLoaderExt::max_used_path_index();
+ _num_module_paths = ClassLoader::num_module_path_entries();
_verify_local = BytecodeVerificationLocal;
_verify_remote = BytecodeVerificationRemote;
@@ -356,7 +356,7 @@ void SharedClassPathEntry::copy_from(SharedClassPathEntry* ent, ClassLoaderData*
_from_class_path_attr = ent->_from_class_path_attr;
set_name(ent->name(), CHECK);
- if (ent->is_jar() && !ent->is_signed() && ent->manifest() != nullptr) {
+ if (ent->is_jar() && ent->manifest() != nullptr) {
Array* buf = MetadataFactory::new_array(loader_data,
ent->manifest_size(),
CHECK);
@@ -610,29 +610,6 @@ class ManifestStream: public ResourceObj {
buf[len] = 0;
return buf;
}
-
- // The return value indicates if the JAR is signed or not
- bool check_is_signed() {
- u1* attr = _current;
- bool isSigned = false;
- while (_current < _buffer_end) {
- if (*_current == '\n') {
- *_current = '\0';
- u1* value = (u1*)strchr((char*)attr, ':');
- if (value != nullptr) {
- assert(*(value+1) == ' ', "Unrecognized format" );
- if (strstr((char*)attr, "-Digest") != nullptr) {
- isSigned = true;
- break;
- }
- }
- *_current = '\n'; // restore
- attr = _current + 1;
- }
- _current ++;
- }
- return isSigned;
- }
};
void FileMapInfo::update_jar_manifest(ClassPathEntry *cpe, SharedClassPathEntry* ent, TRAPS) {
@@ -645,18 +622,14 @@ void FileMapInfo::update_jar_manifest(ClassPathEntry *cpe, SharedClassPathEntry*
if (manifest != nullptr) {
ManifestStream* stream = new ManifestStream((u1*)manifest,
manifest_size);
- if (stream->check_is_signed()) {
- ent->set_is_signed();
- } else {
- // Copy the manifest into the shared archive
- manifest = ClassLoaderExt::read_raw_manifest(THREAD, cpe, &manifest_size);
- Array* buf = MetadataFactory::new_array(loader_data,
- manifest_size,
- CHECK);
- char* p = (char*)(buf->data());
- memcpy(p, manifest, manifest_size);
- ent->set_manifest(buf);
- }
+ // Copy the manifest into the shared archive
+ manifest = ClassLoaderExt::read_raw_manifest(THREAD, cpe, &manifest_size);
+ Array* buf = MetadataFactory::new_array(loader_data,
+ manifest_size,
+ CHECK);
+ char* p = (char*)(buf->data());
+ memcpy(p, manifest, manifest_size);
+ ent->set_manifest(buf);
}
}
diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp
index 9012f6c336a8c..f1c1389c7fc88 100644
--- a/src/hotspot/share/cds/filemap.hpp
+++ b/src/hotspot/share/cds/filemap.hpp
@@ -53,7 +53,6 @@ class SharedClassPathEntry : public MetaspaceObj {
enum {
modules_image_entry,
jar_entry,
- signed_jar_entry,
dir_entry,
non_existent_entry,
unknown_entry
@@ -90,10 +89,6 @@ class SharedClassPathEntry : public MetaspaceObj {
bool is_dir() const { return _type == dir_entry; }
bool is_modules_image() const { return _type == modules_image_entry; }
bool is_jar() const { return _type == jar_entry; }
- bool is_signed() const { return _type == signed_jar_entry; }
- void set_is_signed() {
- _type = signed_jar_entry;
- }
bool from_class_path_attr() { return _from_class_path_attr; }
time_t timestamp() const { return _timestamp; }
const char* name() const;
@@ -218,8 +213,8 @@ class FileMapHeader: private CDSFileMapHeaderBase {
jshort _app_class_paths_start_index; // Index of first app classpath entry
jshort _app_module_paths_start_index; // Index of first module path entry
- jshort _num_module_paths; // number of module path entries
jshort _max_used_path_index; // max path index referenced during CDS dump
+ int _num_module_paths; // number of module path entries
bool _verify_local; // BytecodeVerificationLocal setting
bool _verify_remote; // BytecodeVerificationRemote setting
bool _has_platform_or_app_classes; // Archive contains app classes
@@ -278,7 +273,7 @@ class FileMapHeader: private CDSFileMapHeaderBase {
jshort max_used_path_index() const { return _max_used_path_index; }
jshort app_module_paths_start_index() const { return _app_module_paths_start_index; }
jshort app_class_paths_start_index() const { return _app_class_paths_start_index; }
- jshort num_module_paths() const { return _num_module_paths; }
+ int num_module_paths() const { return _num_module_paths; }
void set_has_platform_or_app_classes(bool v) { _has_platform_or_app_classes = v; }
void set_cloned_vtables(char* p) { set_as_offset(p, &_cloned_vtables_offset); }
diff --git a/src/hotspot/share/classfile/bytecodeAssembler.cpp b/src/hotspot/share/classfile/bytecodeAssembler.cpp
index 3a8faf43804b3..0ddc6282806c2 100644
--- a/src/hotspot/share/classfile/bytecodeAssembler.cpp
+++ b/src/hotspot/share/classfile/bytecodeAssembler.cpp
@@ -31,6 +31,7 @@
#include "oops/constantPool.hpp"
#include "runtime/handles.inline.hpp"
#include "utilities/bytes.hpp"
+#include "utilities/checkedCast.hpp"
u2 BytecodeConstantPool::find_or_add(BytecodeCPEntry const& bcpe, TRAPS) {
diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp
index a4c1c3c5a335d..02cd8ec852dc4 100644
--- a/src/hotspot/share/classfile/classFileParser.cpp
+++ b/src/hotspot/share/classfile/classFileParser.cpp
@@ -75,6 +75,7 @@
#include "services/threadService.hpp"
#include "utilities/align.hpp"
#include "utilities/bitMap.inline.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/copy.hpp"
#include "utilities/formatBuffer.hpp"
#include "utilities/exceptions.hpp"
diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp
index de06f1b94c77c..ab59b39126218 100644
--- a/src/hotspot/share/classfile/classLoader.cpp
+++ b/src/hotspot/share/classfile/classLoader.cpp
@@ -73,6 +73,7 @@
#include "runtime/vm_version.hpp"
#include "services/management.hpp"
#include "services/threadService.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/classpathStream.hpp"
#include "utilities/events.hpp"
#include "utilities/macros.hpp"
diff --git a/src/hotspot/share/classfile/classLoaderExt.cpp b/src/hotspot/share/classfile/classLoaderExt.cpp
index f2c3d70c59af4..25c63bfb921e9 100644
--- a/src/hotspot/share/classfile/classLoaderExt.cpp
+++ b/src/hotspot/share/classfile/classLoaderExt.cpp
@@ -48,6 +48,7 @@
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/os.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/stringUtils.hpp"
jshort ClassLoaderExt::_app_class_paths_start_index = ClassLoaderExt::max_classpath_index;
diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp
index f60d426f5fbce..f1f02e11d8133 100644
--- a/src/hotspot/share/classfile/dictionary.cpp
+++ b/src/hotspot/share/classfile/dictionary.cpp
@@ -229,11 +229,13 @@ class DictionaryLookup : StackObj {
uintx get_hash() const {
return _name->identity_hash();
}
- bool equals(DictionaryEntry** value, bool* is_dead) {
+ bool equals(DictionaryEntry** value) {
DictionaryEntry *entry = *value;
- *is_dead = false;
return (entry->instance_klass()->name() == _name);
}
+ bool is_dead(DictionaryEntry** value) {
+ return false;
+ }
};
// Add a loaded class to the dictionary.
diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp
index c36c66a909c29..95210a57b4dd4 100644
--- a/src/hotspot/share/classfile/javaClasses.cpp
+++ b/src/hotspot/share/classfile/javaClasses.cpp
@@ -86,6 +86,7 @@
#include "runtime/vframe.inline.hpp"
#include "runtime/vm_version.hpp"
#include "utilities/align.hpp"
+#include "utilities/globalDefinitions.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/preserveException.hpp"
#include "utilities/utf8.hpp"
@@ -4711,7 +4712,7 @@ class UnsafeConstantsFixup : public FieldClosure {
UnsafeConstantsFixup() {
// round up values for all static final fields
_address_size = sizeof(void*);
- _page_size = (int)os::vm_page_size();
+ _page_size = AIX_ONLY(sysconf(_SC_PAGESIZE)) NOT_AIX((int)os::vm_page_size());
_big_endian = LITTLE_ENDIAN_ONLY(false) BIG_ENDIAN_ONLY(true);
_use_unaligned_access = UseUnalignedAccesses;
_data_cache_line_flush_size = (int)VM_Version::data_cache_line_flush_size();
diff --git a/src/hotspot/share/classfile/stackMapTableFormat.hpp b/src/hotspot/share/classfile/stackMapTableFormat.hpp
index 33b92e34ee6ef..2b89c53278a5c 100644
--- a/src/hotspot/share/classfile/stackMapTableFormat.hpp
+++ b/src/hotspot/share/classfile/stackMapTableFormat.hpp
@@ -26,6 +26,7 @@
#define SHARE_CLASSFILE_STACKMAPTABLEFORMAT_HPP
#include "classfile/verificationType.hpp"
+#include "utilities/checkedCast.hpp"
// These classes represent the stack-map substructures described in the JVMS
// (hence the non-conforming naming scheme).
diff --git a/src/hotspot/share/classfile/stringTable.cpp b/src/hotspot/share/classfile/stringTable.cpp
index 2751148dff388..66b9ca4ff02ee 100644
--- a/src/hotspot/share/classfile/stringTable.cpp
+++ b/src/hotspot/share/classfile/stringTable.cpp
@@ -176,11 +176,9 @@ class StringTableLookupJchar : StackObj {
uintx get_hash() const {
return _hash;
}
- bool equals(WeakHandle* value, bool* is_dead) {
+ bool equals(WeakHandle* value) {
oop val_oop = value->peek();
if (val_oop == nullptr) {
- // dead oop, mark this hash dead for cleaning
- *is_dead = true;
return false;
}
bool equals = java_lang_String::equals(val_oop, _str, _len);
@@ -191,6 +189,10 @@ class StringTableLookupJchar : StackObj {
_found = Handle(_thread, value->resolve());
return true;
}
+ bool is_dead(WeakHandle* value) {
+ oop val_oop = value->peek();
+ return val_oop == nullptr;
+ }
};
class StringTableLookupOop : public StackObj {
@@ -208,11 +210,9 @@ class StringTableLookupOop : public StackObj {
return _hash;
}
- bool equals(WeakHandle* value, bool* is_dead) {
+ bool equals(WeakHandle* value) {
oop val_oop = value->peek();
if (val_oop == nullptr) {
- // dead oop, mark this hash dead for cleaning
- *is_dead = true;
return false;
}
bool equals = java_lang_String::equals(_find(), val_oop);
@@ -223,6 +223,11 @@ class StringTableLookupOop : public StackObj {
_found = Handle(_thread, value->resolve());
return true;
}
+
+ bool is_dead(WeakHandle* value) {
+ oop val_oop = value->peek();
+ return val_oop == nullptr;
+ }
};
void StringTable::create_table() {
diff --git a/src/hotspot/share/classfile/symbolTable.cpp b/src/hotspot/share/classfile/symbolTable.cpp
index a6fb48ac54782..6162be7c0fea1 100644
--- a/src/hotspot/share/classfile/symbolTable.cpp
+++ b/src/hotspot/share/classfile/symbolTable.cpp
@@ -374,7 +374,11 @@ class SymbolTableLookup : StackObj {
uintx get_hash() const {
return _hash;
}
- bool equals(Symbol* value, bool* is_dead) {
+ // Note: When equals() returns "true", the symbol's refcount is incremented. This is
+ // needed to ensure that the symbol is kept alive before equals() returns to the caller,
+ // so that another thread cannot clean the symbol up concurrently. The caller is
+ // responsible for decrementing the refcount, when the symbol is no longer needed.
+ bool equals(Symbol* value) {
assert(value != nullptr, "expected valid value");
Symbol *sym = value;
if (sym->equals(_str, _len)) {
@@ -383,14 +387,15 @@ class SymbolTableLookup : StackObj {
return true;
} else {
assert(sym->refcount() == 0, "expected dead symbol");
- *is_dead = true;
return false;
}
} else {
- *is_dead = (sym->refcount() == 0);
return false;
}
}
+ bool is_dead(Symbol* value) {
+ return value->refcount() == 0;
+ }
};
class SymbolTableGet : public StackObj {
diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp
index f43ab838ae686..da167a19c6eb2 100644
--- a/src/hotspot/share/classfile/systemDictionaryShared.hpp
+++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp
@@ -155,7 +155,7 @@ class SystemDictionaryShared: public SystemDictionary {
};
public:
- enum {
+ enum : char {
FROM_FIELD_IS_PROTECTED = 1 << 0,
FROM_IS_ARRAY = 1 << 1,
FROM_IS_OBJECT = 1 << 2
diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp
index f74969a9401f6..6c2eecf7ae7ee 100644
--- a/src/hotspot/share/classfile/vmIntrinsics.cpp
+++ b/src/hotspot/share/classfile/vmIntrinsics.cpp
@@ -29,6 +29,7 @@
#include "jvm_constants.h"
#include "jvm_io.h"
#include "runtime/vm_version.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/tribool.hpp"
#include "utilities/xmlstream.hpp"
diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp
index 4dbf4c9caf108..d2e70fbd6db02 100644
--- a/src/hotspot/share/code/relocInfo.cpp
+++ b/src/hotspot/share/code/relocInfo.cpp
@@ -34,6 +34,7 @@
#include "runtime/flags/flagSetting.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/copy.hpp"
#include
diff --git a/src/hotspot/share/code/relocInfo.hpp b/src/hotspot/share/code/relocInfo.hpp
index c5dc706beced2..77e24708bb143 100644
--- a/src/hotspot/share/code/relocInfo.hpp
+++ b/src/hotspot/share/code/relocInfo.hpp
@@ -28,6 +28,7 @@
#include "memory/allocation.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/osInfo.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
diff --git a/src/hotspot/share/code/stubs.cpp b/src/hotspot/share/code/stubs.cpp
index a1d79de796427..007c9708c467f 100644
--- a/src/hotspot/share/code/stubs.cpp
+++ b/src/hotspot/share/code/stubs.cpp
@@ -30,6 +30,7 @@
#include "oops/oop.inline.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
// Implementation of StubQueue
diff --git a/src/hotspot/share/code/vmreg.hpp b/src/hotspot/share/code/vmreg.hpp
index ddac0c68f7fba..78f52b8d57af5 100644
--- a/src/hotspot/share/code/vmreg.hpp
+++ b/src/hotspot/share/code/vmreg.hpp
@@ -28,6 +28,7 @@
#include "asm/register.hpp"
#include "code/vmregTypes.hpp"
#include "runtime/globals.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
diff --git a/src/hotspot/share/code/vtableStubs.hpp b/src/hotspot/share/code/vtableStubs.hpp
index f993571b58fe0..60225d777686b 100644
--- a/src/hotspot/share/code/vtableStubs.hpp
+++ b/src/hotspot/share/code/vtableStubs.hpp
@@ -28,6 +28,7 @@
#include "asm/macroAssembler.hpp"
#include "code/vmreg.hpp"
#include "memory/allStatic.hpp"
+#include "utilities/checkedCast.hpp"
// A VtableStub holds an individual code stub for a pair (vtable index, #args) for either itables or vtables
// There's a one-to-one relationship between a VtableStub and such a pair.
diff --git a/src/hotspot/share/compiler/abstractCompiler.hpp b/src/hotspot/share/compiler/abstractCompiler.hpp
index 724c0412db5d4..d61ae639c3f0c 100644
--- a/src/hotspot/share/compiler/abstractCompiler.hpp
+++ b/src/hotspot/share/compiler/abstractCompiler.hpp
@@ -151,6 +151,9 @@ class AbstractCompiler : public CHeapObj {
bool is_jvmci() const { return _type == compiler_jvmci; }
CompilerType type() const { return _type; }
+ // Compiler threads are hidden by default.
+ virtual bool is_hidden_from_external_view() const { return true; }
+
// Customization
virtual void initialize () = 0;
diff --git a/src/hotspot/share/compiler/compilerThread.cpp b/src/hotspot/share/compiler/compilerThread.cpp
index 8fadda27aa192..ddd49fec175b6 100644
--- a/src/hotspot/share/compiler/compilerThread.cpp
+++ b/src/hotspot/share/compiler/compilerThread.cpp
@@ -61,3 +61,8 @@ void CompilerThread::thread_entry(JavaThread* thread, TRAPS) {
bool CompilerThread::can_call_java() const {
return _compiler != nullptr && _compiler->is_jvmci();
}
+
+// Hide native compiler threads from external view.
+bool CompilerThread::is_hidden_from_external_view() const {
+ return _compiler == nullptr || _compiler->is_hidden_from_external_view();
+}
diff --git a/src/hotspot/share/compiler/compilerThread.hpp b/src/hotspot/share/compiler/compilerThread.hpp
index 179ab7d25a2b2..3ae4bef3dadf0 100644
--- a/src/hotspot/share/compiler/compilerThread.hpp
+++ b/src/hotspot/share/compiler/compilerThread.hpp
@@ -72,8 +72,9 @@ class CompilerThread : public JavaThread {
virtual bool can_call_java() const;
- // Hide native compiler threads from external view.
- bool is_hidden_from_external_view() const { return !can_call_java(); }
+ // Returns true if this CompilerThread is hidden from JVMTI and FlightRecorder. C1 and C2 are
+ // always hidden but JVMCI compiler threads might be hidden.
+ virtual bool is_hidden_from_external_view() const;
void set_compiler(AbstractCompiler* c) { _compiler = c; }
AbstractCompiler* compiler() const { return _compiler; }
diff --git a/src/hotspot/share/compiler/oopMap.hpp b/src/hotspot/share/compiler/oopMap.hpp
index a52b85e7885e5..0af9b1abaa9e2 100644
--- a/src/hotspot/share/compiler/oopMap.hpp
+++ b/src/hotspot/share/compiler/oopMap.hpp
@@ -30,6 +30,7 @@
#include "memory/allocation.hpp"
#include "memory/iterator.hpp"
#include "oops/oopsHierarchy.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/growableArray.hpp"
// Interface for generating the frame map for compiled code. A frame map
diff --git a/src/hotspot/share/gc/g1/g1CardSet.cpp b/src/hotspot/share/gc/g1/g1CardSet.cpp
index 4e3f08ddc9d21..58ae441f51ff1 100644
--- a/src/hotspot/share/gc/g1/g1CardSet.cpp
+++ b/src/hotspot/share/gc/g1/g1CardSet.cpp
@@ -110,7 +110,7 @@ G1CardSetConfiguration::G1CardSetConfiguration(uint inline_ptr_bits_per_card,
_max_cards_in_howl_bitmap(G1CardSetHowl::bitmap_size(_max_cards_in_card_set, _num_buckets_in_howl)),
_cards_in_howl_bitmap_threshold(_max_cards_in_howl_bitmap * cards_in_bitmap_threshold_percent),
_log2_max_cards_in_howl_bitmap(log2i_exact(_max_cards_in_howl_bitmap)),
- _bitmap_hash_mask(~(~(0) << _log2_max_cards_in_howl_bitmap)),
+ _bitmap_hash_mask((1U << _log2_max_cards_in_howl_bitmap) - 1),
_log2_card_regions_per_heap_region(log2_card_regions_per_heap_region),
_log2_cards_per_card_region(log2i_exact(_max_cards_in_card_set)) {
@@ -258,10 +258,13 @@ class G1CardSetHashTable : public CHeapObj {
uintx get_hash() const { return G1CardSetHashTable::get_hash(_region_idx); }
- bool equals(G1CardSetHashTableValue* value, bool* is_dead) {
- *is_dead = false;
+ bool equals(G1CardSetHashTableValue* value) {
return value->_region_idx == _region_idx;
}
+
+ bool is_dead(G1CardSetHashTableValue*) {
+ return false;
+ }
};
class G1CardSetHashTableFound : public StackObj {
diff --git a/src/hotspot/share/gc/g1/g1CardSet.hpp b/src/hotspot/share/gc/g1/g1CardSet.hpp
index 5511ebee256bb..a9f1859d5c79b 100644
--- a/src/hotspot/share/gc/g1/g1CardSet.hpp
+++ b/src/hotspot/share/gc/g1/g1CardSet.hpp
@@ -55,7 +55,7 @@ class G1CardSetConfiguration {
uint _max_cards_in_howl_bitmap;
uint _cards_in_howl_bitmap_threshold;
uint _log2_max_cards_in_howl_bitmap;
- size_t _bitmap_hash_mask;
+ uint _bitmap_hash_mask;
uint _log2_card_regions_per_heap_region;
uint _log2_cards_per_card_region;
diff --git a/src/hotspot/share/gc/g1/g1CardSetContainers.hpp b/src/hotspot/share/gc/g1/g1CardSetContainers.hpp
index 3d9ac2180b5d0..16ec6b59a6d0d 100644
--- a/src/hotspot/share/gc/g1/g1CardSetContainers.hpp
+++ b/src/hotspot/share/gc/g1/g1CardSetContainers.hpp
@@ -78,7 +78,7 @@ class G1CardSetInlinePtr : public StackObj {
static const uintptr_t SizeFieldMask = (((uint)1 << SizeFieldLen) - 1) << SizeFieldPos;
- static uint8_t card_pos_for(uint const idx, uint const bits_per_card) {
+ static uint card_pos_for(uint const idx, uint const bits_per_card) {
return (idx * bits_per_card + HeaderSize);
}
diff --git a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp
index 32e3cd5f37025..35abc09230622 100644
--- a/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp
+++ b/src/hotspot/share/gc/g1/g1CardSetContainers.inline.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
#include "gc/g1/g1CardSetContainers.hpp"
#include "gc/g1/g1GCPhaseTimes.hpp"
#include "utilities/bitMap.inline.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/spinYield.hpp"
@@ -35,7 +36,7 @@ inline G1CardSetInlinePtr::ContainerPtr G1CardSetInlinePtr::merge(ContainerPtr o
assert((idx & (SizeFieldMask >> SizeFieldPos)) == idx, "Index %u too large to fit into size field", idx);
assert(card_in_region < ((uint)1 << bits_per_card), "Card %u too large to fit into card value field", card_in_region);
- uint8_t card_pos = card_pos_for(idx, bits_per_card);
+ uint card_pos = card_pos_for(idx, bits_per_card);
assert(card_pos + bits_per_card < BitsInValue, "Putting card at pos %u with %u bits would extend beyond pointer", card_pos, bits_per_card);
// Check that we do not touch any fields we do not own.
@@ -144,7 +145,7 @@ inline G1CardSetArray::G1CardSetArray(uint card_in_region, EntryCountType num_ca
_num_entries(1) {
assert(_size > 0, "CardSetArray of size 0 not supported.");
assert(_size < LockBitMask, "Only support CardSetArray of size %u or smaller.", LockBitMask - 1);
- _data[0] = card_in_region;
+ _data[0] = checked_cast(card_in_region);
}
inline G1CardSetArray::G1CardSetArrayLocker::G1CardSetArrayLocker(EntryCountType volatile* num_entries_addr) :
@@ -195,7 +196,7 @@ inline G1AddCardResult G1CardSetArray::add(uint card_idx) {
return Overflow;
}
- _data[num_entries] = card_idx;
+ _data[num_entries] = checked_cast(card_idx);
x.inc_num_entries();
diff --git a/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp b/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp
index 76e795b880c5f..660ccbf1c0feb 100644
--- a/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp
+++ b/src/hotspot/share/gc/g1/g1CardTableEntryClosure.hpp
@@ -39,9 +39,10 @@ class G1CardTableEntryClosure: public CHeapObj {
virtual void do_card_ptr(CardValue* card_ptr, uint worker_id) = 0;
// Process all the card_ptrs in node.
- void apply_to_buffer(BufferNode* node, size_t buffer_capacity, uint worker_id) {
+ void apply_to_buffer(BufferNode* node, uint worker_id) {
void** buffer = BufferNode::make_buffer_from_node(node);
- for (size_t i = node->index(); i < buffer_capacity; ++i) {
+ size_t capacity = node->capacity();
+ for (size_t i = node->index(); i < capacity; ++i) {
CardValue* card_ptr = static_cast(buffer[i]);
do_card_ptr(card_ptr, worker_id);
}
diff --git a/src/hotspot/share/gc/g1/g1CollectionSetChooser.cpp b/src/hotspot/share/gc/g1/g1CollectionSetChooser.cpp
index 8cd05ae311329..28132ea172b1a 100644
--- a/src/hotspot/share/gc/g1/g1CollectionSetChooser.cpp
+++ b/src/hotspot/share/gc/g1/g1CollectionSetChooser.cpp
@@ -131,14 +131,11 @@ class G1BuildCandidateRegionsTask : public WorkerTask {
assert(_cur_chunk_idx < _cur_chunk_end, "Must be");
_array->set(_cur_chunk_idx, hr);
-
_cur_chunk_idx++;
_regions_added++;
}
- bool should_add(HeapRegion* hr) { return G1CollectionSetChooser::should_add(hr); }
-
public:
G1BuildCandidateRegionsClosure(G1BuildCandidateArray* array) :
_array(array),
@@ -147,20 +144,32 @@ class G1BuildCandidateRegionsTask : public WorkerTask {
_regions_added(0) { }
bool do_heap_region(HeapRegion* r) {
- // We will skip any region that's currently used as an old GC
- // alloc region (we should not consider those for collection
- // before we fill them up).
- if (should_add(r) && !G1CollectedHeap::heap()->is_old_gc_alloc_region(r)) {
- assert(r->rem_set()->is_complete(), "must be %u", r->hrm_index());
+ // Candidates from marking are always old; also keep regions that are already
+ // collection set candidates (some retained regions) in that list.
+ if (!r->is_old() || r->is_collection_set_candidate()) {
+ // Keep remembered sets and everything for these regions.
+ return false;
+ }
+
+ // Can not add a region without a remembered set to the candidates.
+ assert(!r->rem_set()->is_updating(), "must be");
+ if (!r->rem_set()->is_complete()) {
+ return false;
+ }
+
+ // Skip any region that is currently used as an old GC alloc region. We should
+ // not consider those for collection before we fill them up as the effective
+ // gain from them is small. I.e. we only actually reclaim from the filled part,
+ // as the remainder is still eligible for allocation. These objects are also
+ // likely to have already survived a few collections, so they might be longer
+ // lived anyway.
+ // Otherwise the Old region must satisfy the liveness condition.
+ bool should_add = !G1CollectedHeap::heap()->is_old_gc_alloc_region(r) &&
+ G1CollectionSetChooser::region_occupancy_low_enough_for_evac(r->live_bytes());
+ if (should_add) {
add_region(r);
- } else if (r->is_old() && !r->is_collection_set_candidate()) {
- // Keep remembered sets for humongous regions and collection set candidates,
- // otherwise clean them out.
- r->rem_set()->clear(true /* only_cardset */);
} else {
- assert(r->is_collection_set_candidate() || !r->is_old() || !r->rem_set()->is_tracked(),
- "Missed to clear unused remembered set of region %u (%s) that is %s",
- r->hrm_index(), r->get_type_str(), r->rem_set()->get_state_str());
+ r->rem_set()->clear(true /* only_cardset */);
}
return false;
}
@@ -252,17 +261,6 @@ uint G1CollectionSetChooser::calculate_work_chunk_size(uint num_workers, uint nu
return MAX2(num_regions / num_workers, 1U);
}
-bool G1CollectionSetChooser::should_add(HeapRegion* hr) {
- return !hr->is_young() &&
- !hr->is_humongous() &&
- // A region might have been retained (after evacuation failure) and already put
- // into the candidates list during concurrent marking. These should keep being
- // considered as retained regions.
- !hr->is_collection_set_candidate() &&
- region_occupancy_low_enough_for_evac(hr->live_bytes()) &&
- hr->rem_set()->is_complete();
-}
-
void G1CollectionSetChooser::build(WorkerThreads* workers, uint max_num_regions, G1CollectionSetCandidates* candidates) {
uint num_workers = workers->active_workers();
uint chunk_size = calculate_work_chunk_size(num_workers, max_num_regions);
diff --git a/src/hotspot/share/gc/g1/g1CollectionSetChooser.hpp b/src/hotspot/share/gc/g1/g1CollectionSetChooser.hpp
index b11d507c226ef..5b005205551b3 100644
--- a/src/hotspot/share/gc/g1/g1CollectionSetChooser.hpp
+++ b/src/hotspot/share/gc/g1/g1CollectionSetChooser.hpp
@@ -47,11 +47,6 @@ class G1CollectionSetChooser : public AllStatic {
return live_bytes < mixed_gc_live_threshold_bytes();
}
- // Determine whether to add the given region to the collection set candidates from
- // marking or not. Currently, we skip regions whose live bytes are over the threshold.
- // Regions also need a complete remembered set to be a candidate.
- static bool should_add(HeapRegion* hr);
-
// Build and return set of collection set candidates sorted by decreasing gc
// efficiency.
static void build(WorkerThreads* workers, uint max_num_regions, G1CollectionSetCandidates* candidates);
diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp
index aeaedf8b0effd..5bef45fb15292 100644
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp
@@ -436,11 +436,11 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h,
log_debug(gc)("ConcGCThreads: %u offset %u", ConcGCThreads, _worker_id_offset);
log_debug(gc)("ParallelGCThreads: %u", ParallelGCThreads);
- _num_concurrent_workers = ConcGCThreads;
- _max_concurrent_workers = _num_concurrent_workers;
+ _max_concurrent_workers = ConcGCThreads;
_concurrent_workers = new WorkerThreads("G1 Conc", _max_concurrent_workers);
_concurrent_workers->initialize_workers();
+ _num_concurrent_workers = _concurrent_workers->active_workers();
if (!_global_mark_stack.initialize(MarkStackSize, MarkStackSizeMax)) {
vm_exit_during_initialization("Failed to allocate initial concurrent mark overflow mark stack.");
@@ -976,17 +976,14 @@ void G1ConcurrentMark::scan_root_regions() {
if (root_regions()->scan_in_progress()) {
assert(!has_aborted(), "Aborting before root region scanning is finished not supported.");
- _num_concurrent_workers = MIN2(calc_active_marking_workers(),
- // We distribute work on a per-region basis, so starting
- // more threads than that is useless.
- root_regions()->num_root_regions());
- assert(_num_concurrent_workers <= _max_concurrent_workers,
- "Maximum number of marking threads exceeded");
+ // Assign one worker to each root-region but subject to the max constraint.
+ const uint num_workers = MIN2(root_regions()->num_root_regions(),
+ _max_concurrent_workers);
G1CMRootRegionScanTask task(this);
log_debug(gc, ergo)("Running %s using %u workers for %u work units.",
- task.name(), _num_concurrent_workers, root_regions()->num_root_regions());
- _concurrent_workers->run_task(&task, _num_concurrent_workers);
+ task.name(), num_workers, root_regions()->num_root_regions());
+ _concurrent_workers->run_task(&task, num_workers);
// It's possible that has_aborted() is true here without actually
// aborting the survivor scan earlier. This is OK as it's
@@ -1046,9 +1043,7 @@ void G1ConcurrentMark::concurrent_cycle_end(bool mark_cycle_completed) {
void G1ConcurrentMark::mark_from_roots() {
_restart_for_overflow = false;
- _num_concurrent_workers = calc_active_marking_workers();
-
- uint active_workers = MAX2(1U, _num_concurrent_workers);
+ uint active_workers = calc_active_marking_workers();
// Setting active workers is not guaranteed since fewer
// worker threads may currently exist and more may not be
@@ -1056,6 +1051,8 @@ void G1ConcurrentMark::mark_from_roots() {
active_workers = _concurrent_workers->set_active_workers(active_workers);
log_info(gc, task)("Using %u workers of %u for marking", active_workers, _concurrent_workers->max_workers());
+ _num_concurrent_workers = active_workers;
+
// Parallel task terminator is set in "set_concurrency_and_phase()"
set_concurrency_and_phase(active_workers, true /* concurrent */);
diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp b/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp
index bb7db02c3224b..8cf7601d65a25 100644
--- a/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRebuildAndScrub.cpp
@@ -88,12 +88,11 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
}
// Yield if enough has been processed; returns if the concurrent marking cycle
- // has been aborted for any reason. Yielded is set if there has been an actual
- // yield for a pause.
- bool yield_if_necessary(bool& yielded) {
+ // has been aborted for any reason.
+ bool yield_if_necessary() {
if (_processed_words >= ProcessingYieldLimitInWords) {
reset_processed_words();
- yielded = _cm->do_yield_check();
+ _cm->do_yield_check();
}
return _cm->has_aborted();
}
@@ -123,13 +122,12 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
// Update processed words and yield, for humongous objects we will yield
// after each chunk.
add_processed_words(mr.word_size());
- bool yielded;
- bool mark_aborted = yield_if_necessary(yielded);
+ bool mark_aborted = yield_if_necessary();
if (mark_aborted) {
return true;
- } else if (yielded && !should_rebuild_or_scrub(hr)) {
+ } else if (!should_rebuild_or_scrub(hr)) {
// We need to check should_rebuild_or_scrub() again because the region might
- // have been reclaimed during the yield.
+ // have been reclaimed during above yield/safepoint.
log_trace(gc, marking)("Rebuild aborted for reclaimed region: %u", hr->hrm_index());
return false;
}
@@ -192,12 +190,12 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
start = scrub_to_next_live(hr, start, limit);
}
- bool yielded;
- bool mark_aborted = yield_if_necessary(yielded);
+ bool mark_aborted = yield_if_necessary();
if (mark_aborted) {
return true;
- } else if (yielded && !should_rebuild_or_scrub(hr)) {
- // Region has been reclaimed while yielding. Exit continuing with the next region.
+ } else if (!should_rebuild_or_scrub(hr)) {
+ // We need to check should_rebuild_or_scrub() again because the region might
+ // have been reclaimed during above yield/safepoint.
log_trace(gc, marking)("Scan and scrub aborted for reclaimed region: %u", hr->hrm_index());
return false;
}
@@ -212,11 +210,12 @@ class G1RebuildRSAndScrubTask : public WorkerTask {
while (start < limit) {
start += scan_object(hr, start);
// Avoid stalling safepoints and stop iteration if mark cycle has been aborted.
- bool yielded = true;
- bool mark_aborted = yield_if_necessary(yielded);
+ bool mark_aborted = yield_if_necessary();
if (mark_aborted) {
return true;
- } else if (yielded && !should_rebuild_or_scrub(hr)) {
+ } else if (!should_rebuild_or_scrub(hr)) {
+ // We need to check should_rebuild_or_scrub() again because the region might
+ // have been reclaimed during above yield/safepoint.
log_trace(gc, marking)("Scan aborted for reclaimed region: %u", hr->hrm_index());
return false;
}
diff --git a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp
index 2d1d0f5490abc..e34927c0b0a0f 100644
--- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp
+++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.cpp
@@ -86,7 +86,7 @@ uint G1DirtyCardQueueSet::num_par_ids() {
void G1DirtyCardQueueSet::flush_queue(G1DirtyCardQueue& queue) {
if (queue.buffer() != nullptr) {
G1ConcurrentRefineStats* stats = queue.refinement_stats();
- stats->inc_dirtied_cards(buffer_capacity() - queue.index());
+ stats->inc_dirtied_cards(queue.size());
}
PtrQueueSet::flush_queue(queue);
}
@@ -104,8 +104,9 @@ void G1DirtyCardQueueSet::handle_zero_index(G1DirtyCardQueue& queue) {
assert(queue.index() == 0, "precondition");
BufferNode* old_node = exchange_buffer_with_new(queue);
if (old_node != nullptr) {
+ assert(old_node->index() == 0, "invariant");
G1ConcurrentRefineStats* stats = queue.refinement_stats();
- stats->inc_dirtied_cards(buffer_capacity());
+ stats->inc_dirtied_cards(old_node->capacity());
handle_completed_buffer(old_node, stats);
}
}
@@ -123,7 +124,7 @@ void G1DirtyCardQueueSet::enqueue_completed_buffer(BufferNode* cbn) {
assert(cbn != nullptr, "precondition");
// Increment _num_cards before adding to queue, so queue removal doesn't
// need to deal with _num_cards possibly going negative.
- Atomic::add(&_num_cards, buffer_capacity() - cbn->index());
+ Atomic::add(&_num_cards, cbn->size());
// Perform push in CS. The old tail may be popped while the push is
// observing it (attaching it to the new buffer). We need to ensure it
// can't be reused until the push completes, to avoid ABA problems.
@@ -159,7 +160,7 @@ BufferNode* G1DirtyCardQueueSet::get_completed_buffer() {
result = dequeue_completed_buffer();
if (result == nullptr) return nullptr;
}
- Atomic::sub(&_num_cards, buffer_capacity() - result->index());
+ Atomic::sub(&_num_cards, result->size());
return result;
}
@@ -169,7 +170,7 @@ void G1DirtyCardQueueSet::verify_num_cards() const {
for (BufferNode* cur = _completed.first();
!_completed.is_end(cur);
cur = cur->next()) {
- actual += buffer_capacity() - cur->index();
+ actual += cur->size();
}
assert(actual == Atomic::load(&_num_cards),
"Num entries in completed buffers should be " SIZE_FORMAT " but are " SIZE_FORMAT,
@@ -285,7 +286,7 @@ void G1DirtyCardQueueSet::record_paused_buffer(BufferNode* node) {
// notification checking after the coming safepoint if it doesn't GC.
// Note that this means the queue's _num_cards differs from the number
// of cards in the queued buffers when there are paused buffers.
- Atomic::add(&_num_cards, buffer_capacity() - node->index());
+ Atomic::add(&_num_cards, node->size());
_paused.add(node);
}
@@ -422,12 +423,11 @@ class G1RefineBufferedCards : public StackObj {
public:
G1RefineBufferedCards(BufferNode* node,
- size_t node_buffer_capacity,
uint worker_id,
G1ConcurrentRefineStats* stats) :
_node(node),
_node_buffer(reinterpret_cast(BufferNode::make_buffer_from_node(node))),
- _node_buffer_capacity(node_buffer_capacity),
+ _node_buffer_capacity(node->capacity()),
_worker_id(worker_id),
_stats(stats),
_g1rs(G1CollectedHeap::heap()->rem_set()) {}
@@ -456,10 +456,7 @@ bool G1DirtyCardQueueSet::refine_buffer(BufferNode* node,
uint worker_id,
G1ConcurrentRefineStats* stats) {
Ticks start_time = Ticks::now();
- G1RefineBufferedCards buffered_cards(node,
- buffer_capacity(),
- worker_id,
- stats);
+ G1RefineBufferedCards buffered_cards(node, worker_id, stats);
bool result = buffered_cards.refine();
stats->inc_refinement_time(Ticks::now() - start_time);
return result;
@@ -468,12 +465,11 @@ bool G1DirtyCardQueueSet::refine_buffer(BufferNode* node,
void G1DirtyCardQueueSet::handle_refined_buffer(BufferNode* node,
bool fully_processed) {
if (fully_processed) {
- assert(node->index() == buffer_capacity(),
- "Buffer not fully consumed: index: " SIZE_FORMAT ", size: " SIZE_FORMAT,
- node->index(), buffer_capacity());
+ assert(node->is_empty(), "Buffer not fully consumed: index: %zu, size: %zu",
+ node->index(), node->capacity());
deallocate_buffer(node);
} else {
- assert(node->index() < buffer_capacity(), "Buffer fully consumed.");
+ assert(!node->is_empty(), "Buffer fully consumed.");
// Buffer incompletely processed because there is a pending safepoint.
// Record partially processed buffer, to be finished later.
record_paused_buffer(node);
@@ -575,8 +571,7 @@ G1ConcurrentRefineStats G1DirtyCardQueueSet::concatenate_log_and_stats(Thread* t
G1DirtyCardQueue& queue = G1ThreadLocalData::dirty_card_queue(thread);
// Flush the buffer if non-empty. Flush before accumulating and
// resetting stats, since flushing may modify the stats.
- if ((queue.buffer() != nullptr) &&
- (queue.index() != buffer_capacity())) {
+ if (!queue.is_empty()) {
flush_queue(queue);
}
diff --git a/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp b/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp
index 70d0084d7b26a..216024615e252 100644
--- a/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp
+++ b/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.cpp
@@ -46,7 +46,7 @@ G1RedirtyCardsLocalQueueSet::~G1RedirtyCardsLocalQueueSet() {
#endif // ASSERT
void G1RedirtyCardsLocalQueueSet::enqueue_completed_buffer(BufferNode* node) {
- _buffers._entry_count += buffer_capacity() - node->index();
+ _buffers._entry_count += node->size();
node->set_next(_buffers._head);
_buffers._head = node;
if (_buffers._tail == nullptr) {
@@ -130,7 +130,7 @@ void G1RedirtyCardsQueueSet::update_tail(BufferNode* node) {
void G1RedirtyCardsQueueSet::enqueue_completed_buffer(BufferNode* node) {
assert(_collecting, "precondition");
- Atomic::add(&_entry_count, buffer_capacity() - node->index());
+ Atomic::add(&_entry_count, node->size());
_list.push(*node);
update_tail(node);
}
diff --git a/src/hotspot/share/gc/g1/g1RemSet.cpp b/src/hotspot/share/gc/g1/g1RemSet.cpp
index d17e6fdd46da6..07acd9dd5b54c 100644
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp
@@ -1264,9 +1264,8 @@ class G1MergeHeapRootsTask : public WorkerTask {
void apply_closure_to_dirty_card_buffers(G1MergeLogBufferCardsClosure* cl, uint worker_id) {
G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
- size_t buffer_capacity = dcqs.buffer_capacity();
while (BufferNode* node = _dirty_card_buffers.pop()) {
- cl->apply_to_buffer(node, buffer_capacity, worker_id);
+ cl->apply_to_buffer(node, worker_id);
dcqs.deallocate_buffer(node);
}
}
diff --git a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp
index b0231f4d29e2b..798e6f3c604b6 100644
--- a/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp
+++ b/src/hotspot/share/gc/g1/g1YoungGCPostEvacuateTasks.cpp
@@ -414,13 +414,12 @@ class G1PostEvacuateCollectionSetCleanupTask2::RedirtyLoggedCardsTask : public G
void do_work(uint worker_id) override {
RedirtyLoggedCardTableEntryClosure cl(G1CollectedHeap::heap(), _evac_failure_regions);
- const size_t buffer_capacity = _rdcqs->buffer_capacity();
BufferNode* next = Atomic::load(&_nodes);
while (next != nullptr) {
BufferNode* node = next;
next = Atomic::cmpxchg(&_nodes, node, node->next());
if (next == node) {
- cl.apply_to_buffer(node, buffer_capacity, worker_id);
+ cl.apply_to_buffer(node, worker_id);
next = node->next();
}
}
diff --git a/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp b/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp
index 7e6dd42e97e2f..d3a6436e432f5 100644
--- a/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp
+++ b/src/hotspot/share/gc/g1/g1YoungGCPreEvacuateTasks.cpp
@@ -167,12 +167,10 @@ static void verify_empty_dirty_card_logs() {
ResourceMark rm;
struct Verifier : public ThreadClosure {
- size_t _buffer_capacity;
- Verifier() : _buffer_capacity(G1BarrierSet::dirty_card_queue_set().buffer_capacity()) {}
+ Verifier() {}
void do_thread(Thread* t) override {
G1DirtyCardQueue& queue = G1ThreadLocalData::dirty_card_queue(t);
- assert((queue.buffer() == nullptr) || (queue.index() == _buffer_capacity),
- "non-empty dirty card queue for thread %s", t->name());
+ assert(queue.is_empty(), "non-empty dirty card queue for thread %s", t->name());
}
} verifier;
Threads::threads_do(&verifier);
diff --git a/src/hotspot/share/gc/g1/g1_globals.hpp b/src/hotspot/share/gc/g1/g1_globals.hpp
index c9f0750324211..e4b6f259e4940 100644
--- a/src/hotspot/share/gc/g1/g1_globals.hpp
+++ b/src/hotspot/share/gc/g1/g1_globals.hpp
@@ -146,7 +146,7 @@
\
product(size_t, G1SATBBufferSize, 1*K, \
"Number of entries in an SATB log buffer.") \
- range(1, max_uintx) \
+ constraint(G1SATBBufferSizeConstraintFunc, AtParse) \
\
develop(intx, G1SATBProcessCompletedThreshold, 20, \
"Number of completed buffers that triggers log processing.") \
@@ -166,7 +166,7 @@
\
product(size_t, G1UpdateBufferSize, 256, \
"Size of an update buffer") \
- range(1, NOT_LP64(32*M) LP64_ONLY(1*G)) \
+ constraint(G1UpdateBufferSizeConstraintFunc, AtParse) \
\
product(intx, G1RSetUpdatingPauseTimePercent, 10, \
"A target percentage of time that is allowed to be spend on " \
diff --git a/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.cpp b/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.cpp
index 889af717deb62..88b5b204f5ac3 100644
--- a/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.cpp
+++ b/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.cpp
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "gc/g1/heapRegionBounds.inline.hpp"
#include "gc/g1/jvmFlagConstraintsG1.hpp"
+#include "gc/shared/ptrQueue.hpp"
#include "runtime/globals_extension.hpp"
#include "utilities/globalDefinitions.hpp"
@@ -180,3 +181,32 @@ JVMFlag::Error NewSizeConstraintFuncG1(size_t value, bool verbose) {
size_t MaxSizeForHeapAlignmentG1() {
return HeapRegionBounds::max_size();
}
+
+static JVMFlag::Error buffer_size_constraint_helper(JVMFlagsEnum flagid,
+ size_t value,
+ bool verbose) {
+ if (UseG1GC) {
+ const size_t min_size = 1;
+ const size_t max_size = BufferNode::max_size();
+ JVMFlag* flag = JVMFlag::flag_from_enum(flagid);
+ if ((value < min_size) || (value > max_size)) {
+ JVMFlag::printError(verbose,
+ "%s (%zu) must be in range [%zu, %zu]\n",
+ flag->name(), value, min_size, max_size);
+ return JVMFlag::OUT_OF_BOUNDS;
+ }
+ }
+ return JVMFlag::SUCCESS;
+}
+
+JVMFlag::Error G1SATBBufferSizeConstraintFunc(size_t value, bool verbose) {
+ return buffer_size_constraint_helper(FLAG_MEMBER_ENUM(G1SATBBufferSize),
+ value,
+ verbose);
+}
+
+JVMFlag::Error G1UpdateBufferSizeConstraintFunc(size_t value, bool verbose) {
+ return buffer_size_constraint_helper(FLAG_MEMBER_ENUM(G1UpdateBufferSize),
+ value,
+ verbose);
+}
diff --git a/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp b/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp
index d0de64ac561d0..a424a58b560fd 100644
--- a/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp
+++ b/src/hotspot/share/gc/g1/jvmFlagConstraintsG1.hpp
@@ -43,7 +43,12 @@
/* G1 Subconstraints */ \
f(uintx, MaxGCPauseMillisConstraintFuncG1) \
f(uintx, GCPauseIntervalMillisConstraintFuncG1) \
- f(size_t, NewSizeConstraintFuncG1)
+ f(size_t, NewSizeConstraintFuncG1) \
+ \
+ /* G1 PtrQueue buffer size constraints */ \
+ f(size_t, G1SATBBufferSizeConstraintFunc) \
+ f(size_t, G1UpdateBufferSizeConstraintFunc) \
+ /* */
G1_GC_CONSTRAINTS(DECLARE_CONSTRAINT)
diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp
index 90fae8c358841..41bd15ab0000f 100644
--- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp
+++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp
@@ -675,8 +675,15 @@ void BarrierSetC2::clone(GraphKit* kit, Node* src_base, Node* dst_base, Node* si
Node* payload_size = size;
Node* offset = kit->MakeConX(base_off);
payload_size = kit->gvn().transform(new SubXNode(payload_size, offset));
+ if (is_array) {
+ // Ensure the array payload size is rounded up to the next BytesPerLong
+ // multiple when converting to double-words. This is necessary because array
+ // size does not include object alignment padding, so it might not be a
+ // multiple of BytesPerLong for sub-long element types.
+ payload_size = kit->gvn().transform(new AddXNode(payload_size, kit->MakeConX(BytesPerLong - 1)));
+ }
payload_size = kit->gvn().transform(new URShiftXNode(payload_size, kit->intcon(LogBytesPerLong)));
- ArrayCopyNode* ac = ArrayCopyNode::make(kit, false, src_base, offset, dst_base, offset, payload_size, true, false);
+ ArrayCopyNode* ac = ArrayCopyNode::make(kit, false, src_base, offset, dst_base, offset, payload_size, true, false);
if (is_array) {
ac->set_clone_array();
} else {
diff --git a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp
index 2e876f94e896b..8ac9a3fc783d7 100644
--- a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp
+++ b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -156,11 +156,11 @@ JVMFlag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose) {
}
}
-JVMFlag::Error MinMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose) {
+JVMFlag::Error MinMetaspaceFreeRatioConstraintFunc(uint value, bool verbose) {
if (value > MaxMetaspaceFreeRatio) {
JVMFlag::printError(verbose,
- "MinMetaspaceFreeRatio (" UINTX_FORMAT ") must be "
- "less than or equal to MaxMetaspaceFreeRatio (" UINTX_FORMAT ")\n",
+ "MinMetaspaceFreeRatio (%u) must be "
+ "less than or equal to MaxMetaspaceFreeRatio (%u)\n",
value, MaxMetaspaceFreeRatio);
return JVMFlag::VIOLATES_CONSTRAINT;
} else {
@@ -168,11 +168,11 @@ JVMFlag::Error MinMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose) {
}
}
-JVMFlag::Error MaxMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose) {
+JVMFlag::Error MaxMetaspaceFreeRatioConstraintFunc(uint value, bool verbose) {
if (value < MinMetaspaceFreeRatio) {
JVMFlag::printError(verbose,
- "MaxMetaspaceFreeRatio (" UINTX_FORMAT ") must be "
- "greater than or equal to MinMetaspaceFreeRatio (" UINTX_FORMAT ")\n",
+ "MaxMetaspaceFreeRatio (%u) must be "
+ "greater than or equal to MinMetaspaceFreeRatio (%u)\n",
value, MinMetaspaceFreeRatio);
return JVMFlag::VIOLATES_CONSTRAINT;
} else {
diff --git a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp
index 12a6abd1f5796..591838c071753 100644
--- a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp
+++ b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,8 +47,8 @@
f(uintx, MaxHeapFreeRatioConstraintFunc) \
f(intx, SoftRefLRUPolicyMSPerMBConstraintFunc) \
f(size_t, MarkStackSizeConstraintFunc) \
- f(uintx, MinMetaspaceFreeRatioConstraintFunc) \
- f(uintx, MaxMetaspaceFreeRatioConstraintFunc) \
+ f(uint, MinMetaspaceFreeRatioConstraintFunc) \
+ f(uint, MaxMetaspaceFreeRatioConstraintFunc) \
f(uintx, InitialTenuringThresholdConstraintFunc) \
f(uintx, MaxTenuringThresholdConstraintFunc) \
\
diff --git a/src/hotspot/share/gc/shared/ptrQueue.cpp b/src/hotspot/share/gc/shared/ptrQueue.cpp
index b267cc818fc6e..20cc1b944ea71 100644
--- a/src/hotspot/share/gc/shared/ptrQueue.cpp
+++ b/src/hotspot/share/gc/shared/ptrQueue.cpp
@@ -30,7 +30,6 @@
PtrQueue::PtrQueue(PtrQueueSet* qset) :
_index(0),
- _capacity_in_bytes(index_to_byte_index(qset->buffer_capacity())),
_buf(nullptr)
{}
@@ -38,10 +37,23 @@ PtrQueue::~PtrQueue() {
assert(_buf == nullptr, "queue must be flushed before delete");
}
-BufferNode::AllocatorConfig::AllocatorConfig(size_t size) : _buffer_capacity(size) {}
+size_t PtrQueue::current_capacity() const {
+ if (_buf == nullptr) {
+ return 0;
+ } else {
+ return BufferNode::make_node_from_buffer(_buf)->capacity();
+ }
+}
+
+BufferNode::AllocatorConfig::AllocatorConfig(size_t size)
+ : _buffer_capacity(size)
+{
+ assert(size >= 1, "Invalid buffer capacity %zu", size);
+ assert(size <= max_size(), "Invalid buffer capacity %zu", size);
+}
void* BufferNode::AllocatorConfig::allocate() {
- size_t byte_size = _buffer_capacity * sizeof(void*);
+ size_t byte_size = buffer_capacity() * sizeof(void*);
return NEW_C_HEAP_ARRAY(char, buffer_offset() + byte_size, mtGC);
}
@@ -53,21 +65,22 @@ void BufferNode::AllocatorConfig::deallocate(void* node) {
BufferNode::Allocator::Allocator(const char* name, size_t buffer_capacity) :
_config(buffer_capacity),
_free_list(name, &_config)
-{
-
-}
+{}
size_t BufferNode::Allocator::free_count() const {
return _free_list.free_count();
}
BufferNode* BufferNode::Allocator::allocate() {
- return ::new (_free_list.allocate()) BufferNode();
+ auto internal_capacity = static_cast(buffer_capacity());
+ return ::new (_free_list.allocate()) BufferNode(internal_capacity);
}
void BufferNode::Allocator::release(BufferNode* node) {
assert(node != nullptr, "precondition");
assert(node->next() == nullptr, "precondition");
+ assert(node->capacity() == buffer_capacity(),
+ "Wrong size %zu, expected %zu", node->capacity(), buffer_capacity());
node->~BufferNode();
_free_list.release(node);
}
@@ -79,9 +92,7 @@ PtrQueueSet::PtrQueueSet(BufferNode::Allocator* allocator) :
PtrQueueSet::~PtrQueueSet() {}
void PtrQueueSet::reset_queue(PtrQueue& queue) {
- if (queue.buffer() != nullptr) {
- queue.set_index(buffer_capacity());
- }
+ queue.set_index(queue.current_capacity());
}
void PtrQueueSet::flush_queue(PtrQueue& queue) {
@@ -91,7 +102,7 @@ void PtrQueueSet::flush_queue(PtrQueue& queue) {
queue.set_buffer(nullptr);
queue.set_index(0);
BufferNode* node = BufferNode::make_node_from_buffer(buffer, index);
- if (index == buffer_capacity()) {
+ if (index == node->capacity()) {
deallocate_buffer(node);
} else {
enqueue_completed_buffer(node);
@@ -128,8 +139,9 @@ BufferNode* PtrQueueSet::exchange_buffer_with_new(PtrQueue& queue) {
}
void PtrQueueSet::install_new_buffer(PtrQueue& queue) {
- queue.set_buffer(allocate_buffer());
- queue.set_index(buffer_capacity());
+ BufferNode* node = _allocator->allocate();
+ queue.set_buffer(BufferNode::make_buffer_from_node(node));
+ queue.set_index(node->capacity());
}
void** PtrQueueSet::allocate_buffer() {
diff --git a/src/hotspot/share/gc/shared/ptrQueue.hpp b/src/hotspot/share/gc/shared/ptrQueue.hpp
index 81969d078df4d..69a12c547f5c9 100644
--- a/src/hotspot/share/gc/shared/ptrQueue.hpp
+++ b/src/hotspot/share/gc/shared/ptrQueue.hpp
@@ -32,6 +32,7 @@
#include "utilities/globalDefinitions.hpp"
#include "utilities/lockFreeStack.hpp"
#include "utilities/sizes.hpp"
+#include
// There are various techniques that require threads to be able to log
// addresses. For example, a generational write barrier might log
@@ -50,18 +51,8 @@ class PtrQueue {
// Value is always pointer-size aligned.
size_t _index;
- // Size of the current buffer, in bytes.
- // Value is always pointer-size aligned.
- size_t _capacity_in_bytes;
-
static const size_t _element_size = sizeof(void*);
- // Get the capacity, in bytes. The capacity must have been set.
- size_t capacity_in_bytes() const {
- assert(_capacity_in_bytes > 0, "capacity not set");
- return _capacity_in_bytes;
- }
-
static size_t byte_index_to_index(size_t ind) {
assert(is_aligned(ind, _element_size), "precondition");
return ind / _element_size;
@@ -92,17 +83,19 @@ class PtrQueue {
}
void set_index(size_t new_index) {
- assert(new_index <= capacity(), "precondition");
+ assert(new_index <= current_capacity(), "precondition");
_index = index_to_byte_index(new_index);
}
- size_t capacity() const {
- return byte_index_to_index(capacity_in_bytes());
- }
+ // Returns the capacity of the buffer, or 0 if the queue doesn't currently
+ // have a buffer.
+ size_t current_capacity() const;
- // To support compiler.
+ bool is_empty() const { return index() == current_capacity(); }
+ size_t size() const { return current_capacity() - index(); }
protected:
+ // To support compiler.
template
static ByteSize byte_offset_of_index() {
return byte_offset_of(Derived, _index);
@@ -119,12 +112,19 @@ class PtrQueue {
};
class BufferNode {
- size_t _index;
+ using InternalSizeType = LP64_ONLY(uint32_t) NOT_LP64(uint16_t);
+ static_assert(sizeof(InternalSizeType) <= sizeof(size_t), "assumption");
+
+ InternalSizeType _index;
+ InternalSizeType _capacity;
BufferNode* volatile _next;
void* _buffer[1]; // Pseudo flexible array member.
- BufferNode() : _index(0), _next(nullptr) { }
- ~BufferNode() { }
+ BufferNode(InternalSizeType capacity)
+ : _index(capacity), _capacity(capacity), _next(nullptr)
+ {}
+
+ ~BufferNode() = default;
NONCOPYABLE(BufferNode);
@@ -133,19 +133,36 @@ class BufferNode {
}
public:
+ static constexpr size_t max_size() {
+ return std::numeric_limits::max();
+ }
+
static BufferNode* volatile* next_ptr(BufferNode& bn) { return &bn._next; }
typedef LockFreeStack Stack;
BufferNode* next() const { return _next; }
void set_next(BufferNode* n) { _next = n; }
size_t index() const { return _index; }
- void set_index(size_t i) { _index = i; }
+
+ void set_index(size_t i) {
+ assert(i <= capacity(), "precondition");
+ _index = static_cast(i);
+ }
+
+ size_t capacity() const { return _capacity; }
+
+ bool is_empty() const { return index() == capacity(); }
+ size_t size() const { return capacity() - index(); }
+
+ // Return the BufferNode containing the buffer, WITHOUT setting its index.
+ static BufferNode* make_node_from_buffer(void** buffer) {
+ char* base = reinterpret_cast(buffer) - buffer_offset();
+ return reinterpret_cast(base);
+ }
// Return the BufferNode containing the buffer, after setting its index.
static BufferNode* make_node_from_buffer(void** buffer, size_t index) {
- BufferNode* node =
- reinterpret_cast(
- reinterpret_cast(buffer) - buffer_offset());
+ BufferNode* node = make_node_from_buffer(buffer);
node->set_index(index);
return node;
}
@@ -166,6 +183,7 @@ class BufferNode {
// FreeListAllocator.
class BufferNode::AllocatorConfig : public FreeListConfig {
const size_t _buffer_capacity;
+
public:
explicit AllocatorConfig(size_t size);
diff --git a/src/hotspot/share/gc/shared/satbMarkQueue.cpp b/src/hotspot/share/gc/shared/satbMarkQueue.cpp
index 051e6fa9e448f..a0efcc8e66ae8 100644
--- a/src/hotspot/share/gc/shared/satbMarkQueue.cpp
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.cpp
@@ -60,7 +60,7 @@ static void print_satb_buffer(const char* name,
}
void SATBMarkQueue::print(const char* name) {
- print_satb_buffer(name, _buf, index(), capacity());
+ print_satb_buffer(name, _buf, index(), current_capacity());
}
#endif // PRODUCT
@@ -193,10 +193,10 @@ void SATBMarkQueueSet::set_active_all_threads(bool active, bool expected_active)
_qset(qset), _active(active) {}
virtual void do_thread(Thread* t) {
SATBMarkQueue& queue = _qset->satb_queue_for_thread(t);
- if (queue.buffer() != nullptr) {
- assert(!_active || queue.index() == _qset->buffer_capacity(),
- "queues should be empty when activated");
- queue.set_index(_qset->buffer_capacity());
+ if (_active) {
+ assert(queue.is_empty(), "queues should be empty when activated");
+ } else {
+ queue.set_index(queue.current_capacity());
}
queue.set_active(_active);
}
@@ -208,10 +208,7 @@ bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl)
BufferNode* nd = get_completed_buffer();
if (nd != nullptr) {
void **buf = BufferNode::make_buffer_from_node(nd);
- size_t index = nd->index();
- size_t size = buffer_capacity();
- assert(index <= size, "invariant");
- cl->do_buffer(buf + index, size - index);
+ cl->do_buffer(buf + nd->index(), nd->size());
deallocate_buffer(nd);
return true;
} else {
@@ -250,14 +247,15 @@ void SATBMarkQueueSet::handle_zero_index(SATBMarkQueue& queue) {
}
bool SATBMarkQueueSet::should_enqueue_buffer(SATBMarkQueue& queue) {
+ assert(queue.buffer() != nullptr, "precondition");
// Keep the current buffer if filtered index >= threshold.
size_t threshold = buffer_enqueue_threshold();
// Ensure we'll enqueue completely full buffers.
assert(threshold > 0, "enqueue threshold = 0");
// Ensure we won't enqueue empty buffers.
- assert(threshold <= buffer_capacity(),
+ assert(threshold <= queue.current_capacity(),
"enqueue threshold %zu exceeds capacity %zu",
- threshold, buffer_capacity());
+ threshold, queue.current_capacity());
return queue.index() < threshold;
}
@@ -310,7 +308,7 @@ void SATBMarkQueueSet::print_all(const char* msg) {
while (nd != nullptr) {
void** buf = BufferNode::make_buffer_from_node(nd);
os::snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Enqueued: %d", i);
- print_satb_buffer(buffer, buf, nd->index(), buffer_capacity());
+ print_satb_buffer(buffer, buf, nd->index(), nd->capacity());
nd = nd->next();
i += 1;
}
diff --git a/src/hotspot/share/gc/shared/satbMarkQueue.hpp b/src/hotspot/share/gc/shared/satbMarkQueue.hpp
index 0e89220ccdae2..d92523d7e4f78 100644
--- a/src/hotspot/share/gc/shared/satbMarkQueue.hpp
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.hpp
@@ -175,13 +175,13 @@ inline void SATBMarkQueueSet::apply_filter(Filter filter_out, SATBMarkQueue& que
void** buf = queue.buffer();
if (buf == nullptr) {
- // nothing to do
+ // Nothing to do, and avoid pointer arithmetic on nullptr below.
return;
}
// Two-fingered compaction toward the end.
- void** src = &buf[queue.index()];
- void** dst = &buf[buffer_capacity()];
+ void** src = buf + queue.index();
+ void** dst = buf + queue.current_capacity();
assert(src <= dst, "invariant");
for ( ; src < dst; ++src) {
// Search low to high for an entry to keep.
diff --git a/src/hotspot/share/gc/x/xPage.inline.hpp b/src/hotspot/share/gc/x/xPage.inline.hpp
index 8407d6be6fc00..d9b0fd2039dc1 100644
--- a/src/hotspot/share/gc/x/xPage.inline.hpp
+++ b/src/hotspot/share/gc/x/xPage.inline.hpp
@@ -35,6 +35,7 @@
#include "runtime/atomic.hpp"
#include "runtime/os.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
inline uint8_t XPage::type_from_size(size_t size) const {
diff --git a/src/hotspot/share/gc/z/zPage.inline.hpp b/src/hotspot/share/gc/z/zPage.inline.hpp
index 40ab533f84a0e..ff5fe0bbd6c87 100644
--- a/src/hotspot/share/gc/z/zPage.inline.hpp
+++ b/src/hotspot/share/gc/z/zPage.inline.hpp
@@ -39,6 +39,7 @@
#include "runtime/atomic.hpp"
#include "runtime/os.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
inline ZPageType ZPage::type_from_size(size_t size) const {
diff --git a/src/hotspot/share/gc/z/zRootsIterator.cpp b/src/hotspot/share/gc/z/zRootsIterator.cpp
index 130ab5e4627a8..086d90781dd63 100644
--- a/src/hotspot/share/gc/z/zRootsIterator.cpp
+++ b/src/hotspot/share/gc/z/zRootsIterator.cpp
@@ -101,7 +101,7 @@ void ZParallelApply::apply(ClosureType* cl) {
}
void ZOopStorageSetIteratorStrong::apply(OopClosure* cl) {
- ZRootStatTimer timer(ZSubPhaseConcurrentWeakRootsOopStorageSet, _generation);
+ ZRootStatTimer timer(ZSubPhaseConcurrentRootsOopStorageSet, _generation);
_iter.oops_do(cl);
}
diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp
index 9251e027994ab..ddbdb0929376a 100644
--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp
+++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp
@@ -73,6 +73,7 @@
#include "runtime/synchronizer.hpp"
#include "runtime/threadCritical.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/copy.hpp"
#include "utilities/events.hpp"
#ifdef COMPILER2
@@ -1333,7 +1334,7 @@ void SignatureHandlerLibrary::add(const methodHandle& method) {
ResourceMark rm;
ptrdiff_t align_offset = align_up(_buffer, CodeEntryAlignment) - (address)_buffer;
CodeBuffer buffer((address)(_buffer + align_offset),
- SignatureHandlerLibrary::buffer_size - align_offset);
+ checked_cast(SignatureHandlerLibrary::buffer_size - align_offset));
InterpreterRuntime::SignatureHandlerGenerator(method, &buffer).generate(fingerprint);
// copy into code heap
address handler = set_handler(&buffer);
diff --git a/src/hotspot/share/interpreter/rewriter.cpp b/src/hotspot/share/interpreter/rewriter.cpp
index 9ffa587cb81b2..1de0a1be366b2 100644
--- a/src/hotspot/share/interpreter/rewriter.cpp
+++ b/src/hotspot/share/interpreter/rewriter.cpp
@@ -38,6 +38,7 @@
#include "runtime/arguments.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/handles.inline.hpp"
+#include "utilities/checkedCast.hpp"
// Computes a CPC map (new_index -> original_index) for constant pool entries
// that are referred to by the interpreter at runtime via the constant pool cache.
diff --git a/src/hotspot/share/interpreter/templateInterpreter.cpp b/src/hotspot/share/interpreter/templateInterpreter.cpp
index 5982763e1a201..8f8abd30288e7 100644
--- a/src/hotspot/share/interpreter/templateInterpreter.cpp
+++ b/src/hotspot/share/interpreter/templateInterpreter.cpp
@@ -34,6 +34,7 @@
#include "prims/jvmtiExport.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/timerTrace.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/copy.hpp"
# define __ _masm->
@@ -50,7 +51,7 @@ void TemplateInterpreter::initialize_stub() {
// 270+ interpreter codelets are generated and each of them is aligned to HeapWordSize,
// plus their code section is aligned to CodeEntryAlignement. So we need additional size due to alignment.
int max_aligned_codelets = 280;
- int max_aligned_bytes = max_aligned_codelets * (HeapWordSize + CodeEntryAlignment);
+ int max_aligned_bytes = checked_cast(max_aligned_codelets * (HeapWordSize + CodeEntryAlignment));
_code = new StubQueue(new InterpreterCodeletInterface, code_size + max_aligned_bytes, nullptr,
"Interpreter");
}
diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml
index 70715294a5e87..f8fc4e5bccdfd 100644
--- a/src/hotspot/share/jfr/metadata/metadata.xml
+++ b/src/hotspot/share/jfr/metadata/metadata.xml
@@ -946,6 +946,13 @@
+
+
+
+
+
+
diff --git a/src/hotspot/share/jvmci/jvmciCompiler.hpp b/src/hotspot/share/jvmci/jvmciCompiler.hpp
index c1229a0b141ed..bdb50cfc26a89 100644
--- a/src/hotspot/share/jvmci/jvmciCompiler.hpp
+++ b/src/hotspot/share/jvmci/jvmciCompiler.hpp
@@ -103,6 +103,9 @@ class JVMCICompiler : public AbstractCompiler {
bool is_c1 () { return false; }
bool is_c2 () { return false; }
+ virtual bool is_hidden_from_external_view() const { return UseJVMCINativeLibrary && LibJVMCICompilerThreadHidden; }
+
+
bool needs_stubs () { return false; }
// Initialization
diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
index 14c36a4dc1328..a33a5bd6790ec 100644
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
@@ -622,10 +622,7 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU
}
if (resolve) {
- resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_NULL);
- if (resolved_klass == nullptr) {
- JVMCI_THROW_MSG_NULL(NoClassDefFoundError, str);
- }
+ resolved_klass = SystemDictionary::resolve_or_fail(class_name, class_loader, protection_domain, true, CHECK_NULL);
} else {
if (Signature::has_envelope(class_name)) {
// This is a name from a signature. Strip off the trimmings.
@@ -911,9 +908,9 @@ C2V_VMENTRY_NULL(jobject, lookupKlassInPool, (JNIEnv* env, jobject, ARGUMENT_PAI
return JVMCIENV->get_jobject(result);
C2V_END
-C2V_VMENTRY_NULL(jobject, lookupAppendixInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
+C2V_VMENTRY_NULL(jobject, lookupAppendixInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint which))
constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
- oop appendix_oop = ConstantPool::appendix_at_if_loaded(cp, index);
+ oop appendix_oop = ConstantPool::appendix_at_if_loaded(cp, which);
return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(appendix_oop));
C2V_END
@@ -1625,6 +1622,14 @@ C2V_VMENTRY_0(int, decodeIndyIndexToCPIndex, (JNIEnv* env, jobject, ARGUMENT_PAI
return cp->resolved_indy_entry_at(indy_index)->constant_pool_index();
C2V_END
+C2V_VMENTRY_0(int, decodeFieldIndexToCPIndex, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint field_index))
+ constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
+ if (field_index < 0 || field_index >= cp->resolved_field_entries_length()) {
+ JVMCI_THROW_MSG_0(IllegalStateException, err_msg("invalid field index %d", field_index));
+ }
+ return cp->resolved_field_entry_at(field_index)->constant_pool_index();
+C2V_END
+
C2V_VMENTRY(void, resolveInvokeHandleInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
Klass* holder = cp->klass_ref_at(index, Bytecodes::_invokehandle, CHECK);
@@ -3148,6 +3153,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "getUncachedStringInPool", CC "(" HS_CONSTANT_POOL2 "I)" JAVACONSTANT, FN_PTR(getUncachedStringInPool)},
{CC "resolveTypeInPool", CC "(" HS_CONSTANT_POOL2 "I)" HS_KLASS, FN_PTR(resolveTypeInPool)},
{CC "resolveFieldInPool", CC "(" HS_CONSTANT_POOL2 "I" HS_METHOD2 "B[I)" HS_KLASS, FN_PTR(resolveFieldInPool)},
+ {CC "decodeFieldIndexToCPIndex", CC "(" HS_CONSTANT_POOL2 "I)I", FN_PTR(decodeFieldIndexToCPIndex)},
{CC "decodeIndyIndexToCPIndex", CC "(" HS_CONSTANT_POOL2 "IZ)I", FN_PTR(decodeIndyIndexToCPIndex)},
{CC "resolveInvokeHandleInPool", CC "(" HS_CONSTANT_POOL2 "I)V", FN_PTR(resolveInvokeHandleInPool)},
{CC "isResolvedInvokeHandleInPool", CC "(" HS_CONSTANT_POOL2 "I)I", FN_PTR(isResolvedInvokeHandleInPool)},
diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
index 64d28617b7887..881f46e86c72d 100644
--- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
@@ -22,6 +22,9 @@
*/
// no precompiled headers
+#ifdef COMPILER1
+#include "c1/c1_Compiler.hpp"
+#endif
#include "ci/ciUtilities.hpp"
#include "compiler/compiler_globals.hpp"
#include "compiler/oopMap.hpp"
@@ -42,6 +45,9 @@
#include "memory/universe.hpp"
#include "oops/compressedOops.hpp"
#include "oops/klass.inline.hpp"
+#ifdef COMPILER2
+#include "opto/c2compiler.hpp"
+#endif
#include "runtime/flags/jvmFlag.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
@@ -223,6 +229,22 @@ void CompilerToVM::Data::initialize(JVMCI_TRAPS) {
#undef SET_TRIGFUNC
}
+static jboolean is_c1_supported(vmIntrinsics::ID id){
+ jboolean supported = false;
+#ifdef COMPILER1
+ supported = (jboolean) Compiler::is_intrinsic_supported(id);
+#endif
+ return supported;
+}
+
+static jboolean is_c2_supported(vmIntrinsics::ID id){
+ jboolean supported = false;
+#ifdef COMPILER2
+ supported = (jboolean) C2Compiler::is_intrinsic_supported(id);
+#endif
+ return supported;
+}
+
JVMCIObjectArray CompilerToVM::initialize_intrinsics(JVMCI_TRAPS) {
int len = vmIntrinsics::number_of_intrinsics() - 1; // Exclude vmIntrinsics::_none, which is 0
JVMCIObjectArray vmIntrinsics = JVMCIENV->new_VMIntrinsicMethod_array(len, JVMCI_CHECK_NULL);
@@ -239,7 +261,10 @@ JVMCIObjectArray CompilerToVM::initialize_intrinsics(JVMCI_TRAPS) {
} \
JVMCIObject name_str = VM_SYMBOL_TO_STRING(name); \
JVMCIObject sig_str = VM_SYMBOL_TO_STRING(sig); \
- JVMCIObject vmIntrinsicMethod = JVMCIENV->new_VMIntrinsicMethod(kls_str, name_str, sig_str, (jint) vmIntrinsics::id, JVMCI_CHECK_NULL); \
+ JVMCIObject vmIntrinsicMethod = JVMCIENV->new_VMIntrinsicMethod(kls_str, name_str, sig_str, (jint) vmIntrinsics::id, \
+ (jboolean) vmIntrinsics::is_intrinsic_available(vmIntrinsics::id), \
+ is_c1_supported(vmIntrinsics::id), \
+ is_c2_supported(vmIntrinsics::id), JVMCI_CHECK_NULL); \
JVMCIENV->put_object_at(vmIntrinsics, index++, vmIntrinsicMethod); \
}
@@ -253,12 +278,12 @@ JVMCIObjectArray CompilerToVM::initialize_intrinsics(JVMCI_TRAPS) {
}
#define PREDEFINED_CONFIG_FLAGS(do_bool_flag, do_int_flag, do_intx_flag, do_uintx_flag) \
- do_intx_flag(AllocateInstancePrefetchLines) \
- do_intx_flag(AllocatePrefetchDistance) \
+ do_int_flag(AllocateInstancePrefetchLines) \
+ do_int_flag(AllocatePrefetchDistance) \
do_intx_flag(AllocatePrefetchInstr) \
- do_intx_flag(AllocatePrefetchLines) \
- do_intx_flag(AllocatePrefetchStepSize) \
- do_intx_flag(AllocatePrefetchStyle) \
+ do_int_flag(AllocatePrefetchLines) \
+ do_int_flag(AllocatePrefetchStepSize) \
+ do_int_flag(AllocatePrefetchStyle) \
do_intx_flag(BciProfileWidth) \
do_bool_flag(BootstrapJVMCI) \
do_bool_flag(CITime) \
@@ -286,7 +311,7 @@ JVMCIObjectArray CompilerToVM::initialize_intrinsics(JVMCI_TRAPS) {
do_uintx_flag(TLABWasteIncrement) \
do_intx_flag(TypeProfileWidth) \
do_bool_flag(UseAESIntrinsics) \
- X86_ONLY(do_int_flag(UseAVX)) \
+ X86_ONLY(do_int_flag(UseAVX)) \
do_bool_flag(UseCRC32Intrinsics) \
do_bool_flag(UseAdler32Intrinsics) \
do_bool_flag(UseCompressedClassPointers) \
@@ -306,7 +331,7 @@ JVMCIObjectArray CompilerToVM::initialize_intrinsics(JVMCI_TRAPS) {
do_bool_flag(UseSHA1Intrinsics) \
do_bool_flag(UseSHA256Intrinsics) \
do_bool_flag(UseSHA512Intrinsics) \
- X86_ONLY(do_int_flag(UseSSE)) \
+ X86_ONLY(do_int_flag(UseSSE)) \
COMPILER2_PRESENT(do_bool_flag(UseSquareToLenIntrinsic)) \
do_bool_flag(UseTLAB) \
do_bool_flag(VerifyOops) \
diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp
index e70f278542681..d61cc26987450 100644
--- a/src/hotspot/share/jvmci/jvmciEnv.cpp
+++ b/src/hotspot/share/jvmci/jvmciEnv.cpp
@@ -1459,7 +1459,7 @@ JVMCIObject JVMCIEnv::new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject
}
}
-JVMCIObject JVMCIEnv::new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, JVMCI_TRAPS) {
+JVMCIObject JVMCIEnv::new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, jboolean isAvailable, jboolean c1Supported, jboolean c2Supported, JVMCI_TRAPS) {
JavaThread* THREAD = JavaThread::current(); // For exception macros.
if (is_hotspot()) {
HotSpotJVMCI::VMIntrinsicMethod::klass()->initialize(CHECK_(JVMCIObject()));
@@ -1468,12 +1468,15 @@ JVMCIObject JVMCIEnv::new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObj
HotSpotJVMCI::VMIntrinsicMethod::set_name(this, obj, HotSpotJVMCI::resolve(name));
HotSpotJVMCI::VMIntrinsicMethod::set_descriptor(this, obj, HotSpotJVMCI::resolve(descriptor));
HotSpotJVMCI::VMIntrinsicMethod::set_id(this, obj, id);
+ HotSpotJVMCI::VMIntrinsicMethod::set_isAvailable(this, obj, isAvailable);
+ HotSpotJVMCI::VMIntrinsicMethod::set_c1Supported(this, obj, c1Supported);
+ HotSpotJVMCI::VMIntrinsicMethod::set_c2Supported(this, obj, c2Supported);
return wrap(obj);
} else {
JNIAccessMark jni(this, THREAD);
jobject result = jni()->NewObject(JNIJVMCI::VMIntrinsicMethod::clazz(),
JNIJVMCI::VMIntrinsicMethod::constructor(),
- get_jobject(declaringClass), get_jobject(name), get_jobject(descriptor), id);
+ get_jobject(declaringClass), get_jobject(name), get_jobject(descriptor), id, isAvailable, c1Supported, c2Supported);
return wrap(result);
}
}
diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp
index ca76d6501f2df..345504affb80b 100644
--- a/src/hotspot/share/jvmci/jvmciEnv.hpp
+++ b/src/hotspot/share/jvmci/jvmciEnv.hpp
@@ -406,7 +406,7 @@ class JVMCIEnv : public ResourceObj {
JVMCIObject new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS);
JVMCIObject new_VMField(JVMCIObject name, JVMCIObject type, jlong offset, jlong address, JVMCIObject value, JVMCI_TRAPS);
JVMCIObject new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject value, JVMCI_TRAPS);
- JVMCIObject new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, JVMCI_TRAPS);
+ JVMCIObject new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, jboolean isAvailable, jboolean c1Supported, jboolean c2Supported, JVMCI_TRAPS);
JVMCIObject new_HotSpotStackFrameReference(JVMCI_TRAPS);
JVMCIObject new_JVMCIError(JVMCI_TRAPS);
JVMCIObject new_FieldInfo(FieldInfo* fieldinfo, JVMCI_TRAPS);
diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp
index 9bd87009b1161..3561093caaa25 100644
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp
@@ -131,7 +131,10 @@
object_field(VMIntrinsicMethod, name, "Ljava/lang/String;") \
object_field(VMIntrinsicMethod, descriptor, "Ljava/lang/String;") \
int_field(VMIntrinsicMethod, id) \
- jvmci_constructor(VMIntrinsicMethod, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V") \
+ boolean_field(VMIntrinsicMethod, isAvailable) \
+ boolean_field(VMIntrinsicMethod, c1Supported) \
+ boolean_field(VMIntrinsicMethod, c2Supported) \
+ jvmci_constructor(VMIntrinsicMethod, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZZZ)V") \
end_class \
start_class(HotSpotCompilationRequestResult, jdk_vm_ci_hotspot_HotSpotCompilationRequestResult) \
object_field(HotSpotCompilationRequestResult, failureMessage, "Ljava/lang/String;") \
diff --git a/src/hotspot/share/jvmci/jvmci_globals.cpp b/src/hotspot/share/jvmci/jvmci_globals.cpp
index f1c60bf1a9cf6..48b04e4f44870 100644
--- a/src/hotspot/share/jvmci/jvmci_globals.cpp
+++ b/src/hotspot/share/jvmci/jvmci_globals.cpp
@@ -73,10 +73,11 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() {
JVMCI_FLAG_CHECKED(EnableJVMCIProduct)
JVMCI_FLAG_CHECKED(UseGraalJIT)
- CHECK_NOT_SET(BootstrapJVMCI, UseJVMCICompiler)
- CHECK_NOT_SET(PrintBootstrap, UseJVMCICompiler)
- CHECK_NOT_SET(JVMCIThreads, UseJVMCICompiler)
- CHECK_NOT_SET(JVMCIHostThreads, UseJVMCICompiler)
+ CHECK_NOT_SET(BootstrapJVMCI, UseJVMCICompiler)
+ CHECK_NOT_SET(PrintBootstrap, UseJVMCICompiler)
+ CHECK_NOT_SET(JVMCIThreads, UseJVMCICompiler)
+ CHECK_NOT_SET(JVMCIHostThreads, UseJVMCICompiler)
+ CHECK_NOT_SET(LibJVMCICompilerThreadHidden, UseJVMCICompiler)
if (UseJVMCICompiler) {
if (FLAG_IS_DEFAULT(UseJVMCINativeLibrary) && !UseJVMCINativeLibrary) {
@@ -129,6 +130,9 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() {
CHECK_NOT_SET(JVMCILibDumpJNIConfig, EnableJVMCI)
#ifndef COMPILER2
+ JVMCI_FLAG_CHECKED(EnableVectorAggressiveReboxing)
+ JVMCI_FLAG_CHECKED(EnableVectorReboxing)
+ JVMCI_FLAG_CHECKED(EnableVectorSupport)
JVMCI_FLAG_CHECKED(MaxVectorSize)
JVMCI_FLAG_CHECKED(ReduceInitialCardMarks)
JVMCI_FLAG_CHECKED(UseMultiplyToLenIntrinsic)
@@ -136,6 +140,7 @@ 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
#ifndef PRODUCT
@@ -185,6 +190,7 @@ bool JVMCIGlobals::enable_jvmci_product_mode(JVMFlagOrigin origin, bool use_graa
"UseJVMCINativeLibrary",
"JVMCINativeLibraryThreadFraction",
"JVMCINativeLibraryErrorFile",
+ "LibJVMCICompilerThreadHidden",
nullptr
};
diff --git a/src/hotspot/share/jvmci/jvmci_globals.hpp b/src/hotspot/share/jvmci/jvmci_globals.hpp
index 7ab29bc718993..3eab6f1e7c450 100644
--- a/src/hotspot/share/jvmci/jvmci_globals.hpp
+++ b/src/hotspot/share/jvmci/jvmci_globals.hpp
@@ -157,6 +157,11 @@ class fileStream;
"error data to this file" \
"[default: ./" LIBJVMCI_ERR_FILE "] (%p replaced with pid)") \
\
+ product(bool, LibJVMCICompilerThreadHidden, true, EXPERIMENTAL, \
+ "If true then native JVMCI compiler threads are hidden from " \
+ "JVMTI and FlightRecorder. This must be set to false if you " \
+ "wish to use a Java debugger against JVMCI threads.") \
+ \
NOT_COMPILER2(product(bool, UseMultiplyToLenIntrinsic, false, DIAGNOSTIC, \
"Enables intrinsification of BigInteger.multiplyToLen()")) \
\
@@ -170,7 +175,19 @@ class fileStream;
"Enables intrinsification of BigInteger.montgomeryMultiply()")) \
\
NOT_COMPILER2(product(bool, UseMontgomerySquareIntrinsic, false, DIAGNOSTIC, \
- "Enables intrinsification of BigInteger.montgomerySquare()"))
+ "Enables intrinsification of BigInteger.montgomerySquare()")) \
+ \
+ NOT_COMPILER2(product(bool, EnableVectorSupport, false, EXPERIMENTAL, \
+ "Enables VectorSupport intrinsics")) \
+ \
+ NOT_COMPILER2(product(bool, EnableVectorReboxing, false, EXPERIMENTAL, \
+ "Enables reboxing of vectors")) \
+ \
+ 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")) \
// end of JVMCI_FLAGS
diff --git a/src/hotspot/share/logging/logOutput.cpp b/src/hotspot/share/logging/logOutput.cpp
index 3ff6554380d3d..17d0e8b555d60 100644
--- a/src/hotspot/share/logging/logOutput.cpp
+++ b/src/hotspot/share/logging/logOutput.cpp
@@ -65,8 +65,8 @@ void LogOutput::add_to_config_string(const LogSelection& selection) {
}
-static int tag_cmp(const void *a, const void *b) {
- return static_cast(a) - static_cast(b);
+static int tag_cmp(const LogTagType *a, const LogTagType *b) {
+ return primitive_compare(a, b);
}
static void sort_tags(LogTagType tags[LogTag::MaxTags]) {
@@ -74,7 +74,7 @@ static void sort_tags(LogTagType tags[LogTag::MaxTags]) {
while (tags[ntags] != LogTag::__NO_TAG) {
ntags++;
}
- qsort(tags, ntags, sizeof(*tags), tag_cmp);
+ qsort(tags, ntags, sizeof(*tags), (_sort_Fn)tag_cmp);
}
static const size_t MaxSubsets = 1 << LogTag::MaxTags;
diff --git a/src/hotspot/share/logging/logSelection.cpp b/src/hotspot/share/logging/logSelection.cpp
index 26a13dded9a27..16c6c6f63ca40 100644
--- a/src/hotspot/share/logging/logSelection.cpp
+++ b/src/hotspot/share/logging/logSelection.cpp
@@ -226,7 +226,7 @@ double LogSelection::similarity(const LogSelection& other) const {
}
}
}
- return 2.0 * intersecting / (_ntags + other._ntags);
+ return 2.0 * (double)intersecting / (double)(_ntags + other._ntags);
}
// Comparator used for sorting LogSelections based on their similarity to a specific LogSelection.
diff --git a/src/hotspot/share/memory/heap.cpp b/src/hotspot/share/memory/heap.cpp
index 396faf99fde61..8d0bb12f5e90b 100644
--- a/src/hotspot/share/memory/heap.cpp
+++ b/src/hotspot/share/memory/heap.cpp
@@ -29,6 +29,7 @@
#include "runtime/mutexLocker.hpp"
#include "services/memTracker.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/powerOfTwo.hpp"
// Implementation of Heap
diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp
index 718be07d372ee..a149deedd2355 100644
--- a/src/hotspot/share/memory/metaspace.cpp
+++ b/src/hotspot/share/memory/metaspace.cpp
@@ -430,7 +430,7 @@ void MetaspaceGC::compute_new_size() {
// Including the chunk free lists in the definition of "in use" is therefore
// necessary. Not including the chunk free lists can cause capacity_until_GC to
// shrink below committed_bytes() and this has caused serious bugs in the past.
- const size_t used_after_gc = MetaspaceUtils::committed_bytes();
+ const double used_after_gc = (double)MetaspaceUtils::committed_bytes();
const size_t capacity_until_GC = MetaspaceGC::capacity_until_GC();
const double minimum_free_percentage = MinMetaspaceFreeRatio / 100.0;
@@ -464,10 +464,10 @@ void MetaspaceGC::compute_new_size() {
new_capacity_until_GC,
MetaspaceGCThresholdUpdater::ComputeNewSize);
log_trace(gc, metaspace)(" expanding: minimum_desired_capacity: %6.1fKB expand_bytes: %6.1fKB MinMetaspaceExpansion: %6.1fKB new metaspace HWM: %6.1fKB",
- minimum_desired_capacity / (double) K,
- expand_bytes / (double) K,
- MinMetaspaceExpansion / (double) K,
- new_capacity_until_GC / (double) K);
+ (double) minimum_desired_capacity / (double) K,
+ (double) expand_bytes / (double) K,
+ (double) MinMetaspaceExpansion / (double) K,
+ (double) new_capacity_until_GC / (double) K);
}
return;
}
@@ -490,7 +490,7 @@ void MetaspaceGC::compute_new_size() {
log_trace(gc, metaspace)(" maximum_free_percentage: %6.2f minimum_used_percentage: %6.2f",
maximum_free_percentage, minimum_used_percentage);
log_trace(gc, metaspace)(" minimum_desired_capacity: %6.1fKB maximum_desired_capacity: %6.1fKB",
- minimum_desired_capacity / (double) K, maximum_desired_capacity / (double) K);
+ (double) minimum_desired_capacity / (double) K, (double) maximum_desired_capacity / (double) K);
assert(minimum_desired_capacity <= maximum_desired_capacity,
"sanity check");
@@ -517,9 +517,9 @@ void MetaspaceGC::compute_new_size() {
_shrink_factor = MIN2(current_shrink_factor * 4, (uint) 100);
}
log_trace(gc, metaspace)(" shrinking: initThreshold: %.1fK maximum_desired_capacity: %.1fK",
- MetaspaceSize / (double) K, maximum_desired_capacity / (double) K);
+ (double) MetaspaceSize / (double) K, (double) maximum_desired_capacity / (double) K);
log_trace(gc, metaspace)(" shrink_bytes: %.1fK current_shrink_factor: %d new shrink factor: %d MinMetaspaceExpansion: %.1fK",
- shrink_bytes / (double) K, current_shrink_factor, _shrink_factor, MinMetaspaceExpansion / (double) K);
+ (double) shrink_bytes / (double) K, current_shrink_factor, _shrink_factor, (double) MinMetaspaceExpansion / (double) K);
}
}
@@ -708,7 +708,7 @@ void Metaspace::ergo_initialize() {
// class space : non class space usage is about 1:6. With many small classes,
// it can get as low as 1:2. It is not a big deal though since ccs is only
// reserved and will be committed on demand only.
- size_t max_ccs_size = MaxMetaspaceSize * 0.8;
+ size_t max_ccs_size = 8 * (MaxMetaspaceSize / 10);
size_t adjusted_ccs_size = MIN2(CompressedClassSpaceSize, max_ccs_size);
// CCS must be aligned to root chunk size, and be at least the size of one
diff --git a/src/hotspot/share/memory/metaspace/binList.hpp b/src/hotspot/share/memory/metaspace/binList.hpp
index 6d3a25f701a6b..76cd9e155aa2d 100644
--- a/src/hotspot/share/memory/metaspace/binList.hpp
+++ b/src/hotspot/share/memory/metaspace/binList.hpp
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020 SAP SE. All rights reserved.
+ * Copyright (c) 2023 Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,12 +39,8 @@ namespace metaspace {
// (only a few words). It is used to manage deallocated blocks - see
// class FreeBlocks.
-// Memory blocks are kept in linked lists. Each list
-// contains blocks of only one size. There is a list for blocks of two words,
-// for blocks of three words, etc. The list heads are kept in a vector,
-// ordered by block size.
+// Memory blocks are kept in a vector of linked lists of equi-sized blocks:
//
-
// wordsize
//
// +---+ +---+ +---+ +---+
@@ -73,32 +70,28 @@ namespace metaspace {
// This structure is a bit expensive in memory costs (we pay one pointer per managed
// block size) so we only use it for a small number of sizes.
-template
+template
class BinListImpl {
struct Block {
Block* const _next;
- const size_t _word_size;
- Block(Block* next, size_t word_size) :
- _next(next),
- _word_size(word_size)
- {}
+ Block(Block* next) : _next(next) {}
};
-#define BLOCK_FORMAT "Block @" PTR_FORMAT ": size: " SIZE_FORMAT ", next: " PTR_FORMAT
-#define BLOCK_FORMAT_ARGS(b) p2i(b), (b)->_word_size, p2i((b)->_next)
+#define BLOCK_FORMAT "Block @" PTR_FORMAT ": size: " SIZE_FORMAT ", next: " PTR_FORMAT
+#define BLOCK_FORMAT_ARGS(b, sz) p2i(b), (sz), p2i((b)->_next)
- // Smallest block size must be large enough to hold a Block structure.
- STATIC_ASSERT(smallest_word_size * sizeof(MetaWord) >= sizeof(Block));
+ // Block size must be exactly one word size.
+ STATIC_ASSERT(sizeof(Block) == BytesPerWord);
STATIC_ASSERT(num_lists > 0);
public:
// Minimal word size a block must have to be manageable by this structure.
- const static size_t MinWordSize = smallest_word_size;
+ const static size_t MinWordSize = 1;
// Maximal (incl) word size a block can have to be manageable by this structure.
- const static size_t MaxWordSize = MinWordSize + num_lists - 1;
+ const static size_t MaxWordSize = num_lists;
private:
@@ -106,15 +99,17 @@ class BinListImpl {
MemRangeCounter _counter;
+ // Given a word size, returns the index of the list holding blocks of that size
static int index_for_word_size(size_t word_size) {
int index = (int)(word_size - MinWordSize);
assert(index >= 0 && index < num_lists, "Invalid index %d", index);
return index;
}
+ // Given an index of a list, return the word size that list serves
static size_t word_size_for_index(int index) {
assert(index >= 0 && index < num_lists, "Invalid index %d", index);
- return MinWordSize + index;
+ return index + MinWordSize;
}
// Search the range [index, _num_lists) for the smallest non-empty list. Returns -1 on fail.
@@ -127,6 +122,19 @@ class BinListImpl {
return i2 == num_lists ? -1 : i2;
}
+#ifdef ASSERT
+ static const uintptr_t canary = 0xFFEEFFEE;
+ static void write_canary(MetaWord* p, size_t word_size) {
+ if (word_size > 1) { // 1-word-sized blocks have no space for a canary
+ ((uintptr_t*)p)[word_size - 1] = canary;
+ }
+ }
+ static bool check_canary(const Block* b, size_t word_size) {
+ return word_size == 1 || // 1-word-sized blocks have no space for a canary
+ ((const uintptr_t*)b)[word_size - 1] == canary;
+ }
+#endif
+
public:
BinListImpl() {
@@ -138,9 +146,10 @@ class BinListImpl {
void add_block(MetaWord* p, size_t word_size) {
assert(word_size >= MinWordSize &&
word_size <= MaxWordSize, "bad block size");
+ DEBUG_ONLY(write_canary(p, word_size);)
const int index = index_for_word_size(word_size);
Block* old_head = _blocks[index];
- Block* new_head = new(p)Block(old_head, word_size);
+ Block* new_head = new (p) Block(old_head);
_blocks[index] = new_head;
_counter.add(word_size);
}
@@ -156,9 +165,8 @@ class BinListImpl {
Block* b = _blocks[index];
const size_t real_word_size = word_size_for_index(index);
assert(b != nullptr, "Sanity");
- assert(b->_word_size >= word_size &&
- b->_word_size == real_word_size,
- "bad block size in list[%d] (" BLOCK_FORMAT ")", index, BLOCK_FORMAT_ARGS(b));
+ assert(check_canary(b, real_word_size),
+ "bad block in list[%d] (" BLOCK_FORMAT ")", index, BLOCK_FORMAT_ARGS(b, real_word_size));
_blocks[index] = b->_next;
_counter.sub(real_word_size);
*p_real_word_size = real_word_size;
@@ -181,12 +189,10 @@ class BinListImpl {
void verify() const {
MemRangeCounter local_counter;
for (int i = 0; i < num_lists; i++) {
- const size_t s = MinWordSize + i;
+ const size_t s = word_size_for_index(i);
int pos = 0;
for (Block* b = _blocks[i]; b != nullptr; b = b->_next, pos++) {
- assert(b->_word_size == s,
- "bad block size in list[%d] at pos %d (" BLOCK_FORMAT ")",
- i, pos, BLOCK_FORMAT_ARGS(b));
+ assert(check_canary(b, s), "");
local_counter.add(s);
}
}
@@ -196,7 +202,7 @@ class BinListImpl {
};
-typedef BinListImpl<2, 32> BinList32;
+typedef BinListImpl<32> BinList32;
} // namespace metaspace
diff --git a/src/hotspot/share/memory/metaspace/blockTree.hpp b/src/hotspot/share/memory/metaspace/blockTree.hpp
index b9713f59a7616..c5dd48926ac36 100644
--- a/src/hotspot/share/memory/metaspace/blockTree.hpp
+++ b/src/hotspot/share/memory/metaspace/blockTree.hpp
@@ -41,8 +41,7 @@ namespace metaspace {
// memory blocks themselves are the nodes, with the block size being the key.
//
// We store node pointer information in these blocks when storing them. That
-// imposes a minimum size to the managed memory blocks.
-// See get_raw_word_size_for_requested_word_size() (msCommon.hpp).
+// imposes a minimum size to the managed memory blocks (1 word)
//
// We want to manage many memory blocks of the same size, but we want
// to prevent the tree from blowing up and degenerating into a list. Therefore
diff --git a/src/hotspot/share/memory/metaspace/freeBlocks.cpp b/src/hotspot/share/memory/metaspace/freeBlocks.cpp
index df18529750e72..b6a281f0db7c0 100644
--- a/src/hotspot/share/memory/metaspace/freeBlocks.cpp
+++ b/src/hotspot/share/memory/metaspace/freeBlocks.cpp
@@ -31,7 +31,6 @@
namespace metaspace {
void FreeBlocks::add_block(MetaWord* p, size_t word_size) {
- assert(word_size >= MinWordSize, "sanity (" SIZE_FORMAT ")", word_size);
if (word_size > MaxSmallBlocksWordSize) {
_tree.add_block(p, word_size);
} else {
@@ -40,8 +39,6 @@ void FreeBlocks::add_block(MetaWord* p, size_t word_size) {
}
MetaWord* FreeBlocks::remove_block(size_t requested_word_size) {
- assert(requested_word_size >= MinWordSize,
- "requested_word_size too small (" SIZE_FORMAT ")", requested_word_size);
size_t real_size = 0;
MetaWord* p = nullptr;
if (requested_word_size > MaxSmallBlocksWordSize) {
@@ -53,7 +50,7 @@ MetaWord* FreeBlocks::remove_block(size_t requested_word_size) {
// Blocks which are larger than a certain threshold are split and
// the remainder is handed back to the manager.
const size_t waste = real_size - requested_word_size;
- if (waste > MinWordSize) {
+ if (waste >= MinWordSize) {
add_block(p + requested_word_size, waste);
}
}
diff --git a/src/hotspot/share/memory/metaspace/metaspaceArena.cpp b/src/hotspot/share/memory/metaspace/metaspaceArena.cpp
index ce7445260b833..64c2cc0b2b5d0 100644
--- a/src/hotspot/share/memory/metaspace/metaspaceArena.cpp
+++ b/src/hotspot/share/memory/metaspace/metaspaceArena.cpp
@@ -60,7 +60,7 @@ chunklevel_t MetaspaceArena::next_chunk_level() const {
void MetaspaceArena::salvage_chunk(Metachunk* c) {
assert_lock_strong(lock());
size_t remaining_words = c->free_below_committed_words();
- if (remaining_words > FreeBlocks::MinWordSize) {
+ if (remaining_words >= FreeBlocks::MinWordSize) {
UL2(trace, "salvaging chunk " METACHUNK_FULL_FORMAT ".", METACHUNK_FULL_FORMAT_ARGS(c));
@@ -101,6 +101,10 @@ Metachunk* MetaspaceArena::allocate_new_chunk(size_t requested_word_size) {
}
void MetaspaceArena::add_allocation_to_fbl(MetaWord* p, size_t word_size) {
+ assert(p != nullptr, "p is null");
+ assert_is_aligned_metaspace_pointer(p);
+ assert(word_size > 0, "zero sized");
+
if (_fbl == nullptr) {
_fbl = new FreeBlocks(); // Create only on demand
}
@@ -131,7 +135,7 @@ MetaspaceArena::~MetaspaceArena() {
#ifdef ASSERT
SOMETIMES(verify();)
if (Settings::use_allocation_guard()) {
- SOMETIMES(verify_allocation_guards();)
+ verify_allocation_guards();
}
#endif
@@ -224,15 +228,16 @@ MetaWord* MetaspaceArena::allocate(size_t requested_word_size) {
UL2(trace, "requested " SIZE_FORMAT " words.", requested_word_size);
MetaWord* p = nullptr;
- const size_t raw_word_size = get_raw_word_size_for_requested_word_size(requested_word_size);
+ const size_t aligned_word_size = get_raw_word_size_for_requested_word_size(requested_word_size);
// Before bothering the arena proper, attempt to re-use a block from the free blocks list
if (_fbl != nullptr && !_fbl->is_empty()) {
- p = _fbl->remove_block(raw_word_size);
+ p = _fbl->remove_block(aligned_word_size);
if (p != nullptr) {
DEBUG_ONLY(InternalStats::inc_num_allocs_from_deallocated_blocks();)
- UL2(trace, "taken from fbl (now: %d, " SIZE_FORMAT ").",
- _fbl->count(), _fbl->total_size());
+ UL2(trace, "returning " PTR_FORMAT " - taken from fbl (now: %d, " SIZE_FORMAT ").",
+ p2i(p), _fbl->count(), _fbl->total_size());
+ assert_is_aligned_metaspace_pointer(p);
// Note: free blocks in freeblock dictionary still count as "used" as far as statistics go;
// therefore we have no need to adjust any usage counters (see epilogue of allocate_inner())
// and can just return here.
@@ -241,7 +246,7 @@ MetaWord* MetaspaceArena::allocate(size_t requested_word_size) {
}
// Primary allocation
- p = allocate_inner(requested_word_size);
+ p = allocate_inner(aligned_word_size);
#ifdef ASSERT
// Fence allocation
@@ -264,11 +269,11 @@ MetaWord* MetaspaceArena::allocate(size_t requested_word_size) {
}
// Allocate from the arena proper, once dictionary allocations and fencing are sorted out.
-MetaWord* MetaspaceArena::allocate_inner(size_t requested_word_size) {
+MetaWord* MetaspaceArena::allocate_inner(size_t word_size) {
assert_lock_strong(lock());
+ assert_is_aligned(word_size, metaspace::AllocationAlignmentWordSize);
- const size_t raw_word_size = get_raw_word_size_for_requested_word_size(requested_word_size);
MetaWord* p = nullptr;
bool current_chunk_too_small = false;
bool commit_failure = false;
@@ -279,8 +284,8 @@ MetaWord* MetaspaceArena::allocate_inner(size_t requested_word_size) {
// If the current chunk is too small to hold the requested size, attempt to enlarge it.
// If that fails, retire the chunk.
- if (current_chunk()->free_words() < raw_word_size) {
- if (!attempt_enlarge_current_chunk(raw_word_size)) {
+ if (current_chunk()->free_words() < word_size) {
+ if (!attempt_enlarge_current_chunk(word_size)) {
current_chunk_too_small = true;
} else {
DEBUG_ONLY(InternalStats::inc_num_chunks_enlarged();)
@@ -292,15 +297,15 @@ MetaWord* MetaspaceArena::allocate_inner(size_t requested_word_size) {
// hit a limit (either GC threshold or MaxMetaspaceSize). In that case retire the
// chunk.
if (!current_chunk_too_small) {
- if (!current_chunk()->ensure_committed_additional(raw_word_size)) {
- UL2(info, "commit failure (requested size: " SIZE_FORMAT ")", raw_word_size);
+ if (!current_chunk()->ensure_committed_additional(word_size)) {
+ UL2(info, "commit failure (requested size: " SIZE_FORMAT ")", word_size);
commit_failure = true;
}
}
// Allocate from the current chunk. This should work now.
if (!current_chunk_too_small && !commit_failure) {
- p = current_chunk()->allocate(raw_word_size);
+ p = current_chunk()->allocate(word_size);
assert(p != nullptr, "Allocation from chunk failed.");
}
}
@@ -310,12 +315,12 @@ MetaWord* MetaspaceArena::allocate_inner(size_t requested_word_size) {
assert(current_chunk() == nullptr ||
current_chunk_too_small || commit_failure, "Sanity");
- Metachunk* new_chunk = allocate_new_chunk(raw_word_size);
+ Metachunk* new_chunk = allocate_new_chunk(word_size);
if (new_chunk != nullptr) {
UL2(debug, "allocated new chunk " METACHUNK_FORMAT " for requested word size " SIZE_FORMAT ".",
- METACHUNK_FORMAT_ARGS(new_chunk), requested_word_size);
+ METACHUNK_FORMAT_ARGS(new_chunk), word_size);
- assert(new_chunk->free_below_committed_words() >= raw_word_size, "Sanity");
+ assert(new_chunk->free_below_committed_words() >= word_size, "Sanity");
// We have a new chunk. Before making it the current chunk, retire the old one.
if (current_chunk() != nullptr) {
@@ -326,10 +331,10 @@ MetaWord* MetaspaceArena::allocate_inner(size_t requested_word_size) {
_chunks.add(new_chunk);
// Now, allocate from that chunk. That should work.
- p = current_chunk()->allocate(raw_word_size);
+ p = current_chunk()->allocate(word_size);
assert(p != nullptr, "Allocation from chunk failed.");
} else {
- UL2(info, "failed to allocate new chunk for requested word size " SIZE_FORMAT ".", requested_word_size);
+ UL2(info, "failed to allocate new chunk for requested word size " SIZE_FORMAT ".", word_size);
}
}
@@ -337,7 +342,7 @@ MetaWord* MetaspaceArena::allocate_inner(size_t requested_word_size) {
InternalStats::inc_num_allocs_failed_limit();
} else {
DEBUG_ONLY(InternalStats::inc_num_allocs();)
- _total_used_words_counter->increment_by(raw_word_size);
+ _total_used_words_counter->increment_by(word_size);
}
SOMETIMES(verify_locked();)
@@ -349,6 +354,9 @@ MetaWord* MetaspaceArena::allocate_inner(size_t requested_word_size) {
_chunks.count(), METACHUNK_FULL_FORMAT_ARGS(current_chunk()));
UL2(trace, "returning " PTR_FORMAT ".", p2i(p));
}
+
+ assert_is_aligned_metaspace_pointer(p);
+
return p;
}
@@ -365,7 +373,13 @@ void MetaspaceArena::deallocate_locked(MetaWord* p, size_t word_size) {
UL2(trace, "deallocating " PTR_FORMAT ", word size: " SIZE_FORMAT ".",
p2i(p), word_size);
+ // Only blocks that had been allocated via MetaspaceArena::allocate(size) must be handed in
+ // to MetaspaceArena::deallocate(), and only with the same size that had been original used for allocation.
+ // Therefore the pointer must be aligned correctly, and size can be alignment-adjusted (the latter
+ // only matters on 32-bit):
+ assert_is_aligned_metaspace_pointer(p);
size_t raw_word_size = get_raw_word_size_for_requested_word_size(word_size);
+
add_allocation_to_fbl(p, raw_word_size);
SOMETIMES(verify_locked();)
diff --git a/src/hotspot/share/memory/metaspace/metaspaceArena.hpp b/src/hotspot/share/memory/metaspace/metaspaceArena.hpp
index 925d05fc9629d..b77e943ee9d42 100644
--- a/src/hotspot/share/memory/metaspace/metaspaceArena.hpp
+++ b/src/hotspot/share/memory/metaspace/metaspaceArena.hpp
@@ -119,6 +119,7 @@ class MetaspaceArena : public CHeapObj {
// Two eyecatchers to easily spot a corrupted _next pointer
const uintx _eye1;
const Fence* const _next;
+ NOT_LP64(uintx _dummy;)
const uintx _eye2;
public:
Fence(const Fence* next) : _eye1(EyeCatcher), _next(next), _eye2(EyeCatcher) {}
diff --git a/src/hotspot/share/memory/metaspace/metaspaceCommon.cpp b/src/hotspot/share/memory/metaspace/metaspaceCommon.cpp
index 8a8c43e604abf..aec656201fe81 100644
--- a/src/hotspot/share/memory/metaspace/metaspaceCommon.cpp
+++ b/src/hotspot/share/memory/metaspace/metaspaceCommon.cpp
@@ -103,7 +103,7 @@ void print_human_readable_size(outputStream* st, size_t byte_size, size_t scale,
st->print(SIZE_FORMAT " words", byte_size / BytesPerWord);
} else {
const char* display_unit = display_unit_for_scale(scale);
- float display_value = (float) byte_size / scale;
+ float display_value = (float) byte_size / (float)scale;
// Prevent very small but non-null values showing up as 0.00.
if (byte_size > 0 && display_value < 0.01f) {
st->print("<0.01 %s", display_unit);
@@ -118,7 +118,7 @@ void print_human_readable_size(outputStream* st, size_t byte_size, size_t scale,
st->print("%*" PRIuPTR " words", width, byte_size / BytesPerWord);
} else {
const char* display_unit = display_unit_for_scale(scale);
- float display_value = (float) byte_size / scale;
+ float display_value = (float) byte_size / (float)scale;
// Since we use width to display a number with two trailing digits, increase it a bit.
width += 3;
// Prevent very small but non-null values showing up as 0.00.
@@ -142,7 +142,7 @@ void print_percentage(outputStream* st, size_t total, size_t part) {
st->print("100%%");
} else {
// Note: clearly print very-small-but-not-0% and very-large-but-not-100% percentages.
- float p = ((float)part / total) * 100.0f;
+ float p = ((float)part / (float)total) * 100.0f;
if (p < 1.0f) {
st->print(" <1%%");
} else if (p > 99.0f){
@@ -168,23 +168,5 @@ void print_number_of_classes(outputStream* out, uintx classes, uintx classes_sha
}
}
-// Given a net allocation word size, return the raw word size we actually allocate.
-// Note: externally visible for gtests.
-//static
-size_t get_raw_word_size_for_requested_word_size(size_t word_size) {
- size_t byte_size = word_size * BytesPerWord;
-
- // Deallocated metablocks are kept in a binlist which limits their minimal
- // size to at least the size of a binlist item (2 words).
- byte_size = MAX2(byte_size, FreeBlocks::MinWordSize * BytesPerWord);
-
- // Metaspace allocations are aligned to word size.
- byte_size = align_up(byte_size, AllocationAlignmentByteSize);
-
- size_t raw_word_size = byte_size / BytesPerWord;
- assert(raw_word_size * BytesPerWord == byte_size, "Sanity");
- return raw_word_size;
-}
-
} // namespace metaspace
diff --git a/src/hotspot/share/memory/metaspace/metaspaceCommon.hpp b/src/hotspot/share/memory/metaspace/metaspaceCommon.hpp
index a13ef1b325156..eae75e8194cc4 100644
--- a/src/hotspot/share/memory/metaspace/metaspaceCommon.hpp
+++ b/src/hotspot/share/memory/metaspace/metaspaceCommon.hpp
@@ -38,24 +38,27 @@ namespace metaspace {
// Metaspace allocation alignment:
-// 1) Metaspace allocations have to be aligned such that 64bit values are aligned
-// correctly.
+// Metaspace allocations have to be aligned such that 64-bit values are aligned
+// correctly. We currently don't hold members with a larger alignment requirement
+// than 64-bit inside MetaData, so 8-byte alignment is enough.
//
-// 2) Klass* structures allocated from Metaspace have to be aligned to KlassAlignmentInBytes.
+// Klass* structures need to be aligned to KlassAlignmentInBytes, but since that is
+// 64-bit, we don't need special handling for allocating Klass*.
//
-// At the moment LogKlassAlignmentInBytes is 3, so KlassAlignmentInBytes == 8,
-// so (1) and (2) can both be fulfilled with an alignment of 8. Should we increase
-// KlassAlignmentInBytes at any time this will increase the necessary alignment as well. In
-// that case we may think about introducing a separate alignment just for the class space
-// since that alignment would only be needed for Klass structures.
+// On 64-bit platforms, we align to word size; on 32-bit, we align to two words.
static const size_t AllocationAlignmentByteSize = 8;
STATIC_ASSERT(AllocationAlignmentByteSize == (size_t)KlassAlignmentInBytes);
static const size_t AllocationAlignmentWordSize = AllocationAlignmentByteSize / BytesPerWord;
-// Returns the raw word size allocated for a given net allocation
-size_t get_raw_word_size_for_requested_word_size(size_t word_size);
+// Returns the raw word size allocated for a given net allocation. This only matters on 32-bit, where
+// allocations have to be 64-bit aligned too and therefore must be 2-word-aligned.
+inline size_t get_raw_word_size_for_requested_word_size(size_t word_size) {
+ LP64_ONLY(STATIC_ASSERT(AllocationAlignmentWordSize == 1)); // rewrite if this does not hold true anymore
+ return LP64_ONLY(word_size) // no-op on 64-bit
+ NOT_LP64(align_up(word_size, AllocationAlignmentWordSize));
+}
// Utility functions
@@ -81,8 +84,11 @@ void print_percentage(outputStream* st, size_t total, size_t part);
assert(is_aligned((value), (alignment)), \
SIZE_FORMAT_X " is not aligned to " \
SIZE_FORMAT_X, (size_t)(uintptr_t)value, (size_t)(alignment))
+#define assert_is_aligned_metaspace_pointer(p) \
+ assert_is_aligned((p), metaspace::AllocationAlignmentByteSize);
#else
#define assert_is_aligned(value, alignment)
+#define assert_is_aligned_metaspace_pointer(pointer)
#endif
// Pretty printing helpers
diff --git a/src/hotspot/share/oops/constMethod.cpp b/src/hotspot/share/oops/constMethod.cpp
index c6f6095bccbff..8b4b509323f3c 100644
--- a/src/hotspot/share/oops/constMethod.cpp
+++ b/src/hotspot/share/oops/constMethod.cpp
@@ -32,6 +32,7 @@
#include "runtime/safepointVerifiers.hpp"
#include "runtime/signature.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
// Static initialization
const u2 ConstMethod::MAX_IDNUM = 0xFFFE;
diff --git a/src/hotspot/share/oops/constMethod.hpp b/src/hotspot/share/oops/constMethod.hpp
index 87042cfbd99c1..5f0c49f9319b2 100644
--- a/src/hotspot/share/oops/constMethod.hpp
+++ b/src/hotspot/share/oops/constMethod.hpp
@@ -28,6 +28,7 @@
#include "oops/constMethodFlags.hpp"
#include "oops/oop.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
// An ConstMethod represents portions of a Java method which are not written to after
// the classfile is parsed(*see below). This part of the method can be shared across
diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp
index 907c5d5c00a2c..97b863a42dca9 100644
--- a/src/hotspot/share/oops/constantPool.cpp
+++ b/src/hotspot/share/oops/constantPool.cpp
@@ -64,6 +64,7 @@
#include "runtime/javaThread.hpp"
#include "runtime/signature.hpp"
#include "runtime/vframe.inline.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/copy.hpp"
ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) {
diff --git a/src/hotspot/share/oops/fieldInfo.inline.hpp b/src/hotspot/share/oops/fieldInfo.inline.hpp
index 9c336400f053d..2e6727f1fb9f1 100644
--- a/src/hotspot/share/oops/fieldInfo.inline.hpp
+++ b/src/hotspot/share/oops/fieldInfo.inline.hpp
@@ -31,6 +31,7 @@
#include "oops/constantPool.hpp"
#include "oops/symbol.hpp"
#include "runtime/atomic.hpp"
+#include "utilities/checkedCast.hpp"
inline Symbol* FieldInfo::name(ConstantPool* cp) const {
int index = _name_index;
diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp
index a1c7eae402a4f..d157229d22d60 100644
--- a/src/hotspot/share/oops/instanceKlass.cpp
+++ b/src/hotspot/share/oops/instanceKlass.cpp
@@ -1778,7 +1778,6 @@ void InstanceKlass::print_nonstatic_fields(FieldClosure* cl) {
if (i > 0) {
int length = i;
assert(length == fields_sorted.length(), "duh");
- // _sort_Fn is defined in growableArray.hpp.
fields_sorted.sort(compare_fields_by_offset);
for (int i = 0; i < length; i++) {
fd.reinitialize(this, fields_sorted.at(i).second);
diff --git a/src/hotspot/share/oops/methodData.cpp b/src/hotspot/share/oops/methodData.cpp
index 5a2a1e2284318..a9f56a7a3dd91 100644
--- a/src/hotspot/share/oops/methodData.cpp
+++ b/src/hotspot/share/oops/methodData.cpp
@@ -43,6 +43,7 @@
#include "runtime/safepointVerifiers.hpp"
#include "runtime/signature.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/copy.hpp"
// ==================================================================
diff --git a/src/hotspot/share/oops/objArrayKlass.cpp b/src/hotspot/share/oops/objArrayKlass.cpp
index 229981dd9e10e..a505d6cd05225 100644
--- a/src/hotspot/share/oops/objArrayKlass.cpp
+++ b/src/hotspot/share/oops/objArrayKlass.cpp
@@ -453,7 +453,7 @@ void ObjArrayKlass::oop_print_on(oop obj, outputStream* st) {
ArrayKlass::oop_print_on(obj, st);
assert(obj->is_objArray(), "must be objArray");
objArrayOop oa = objArrayOop(obj);
- int print_len = MIN2((intx) oa->length(), MaxElementPrintSize);
+ int print_len = MIN2(oa->length(), MaxElementPrintSize);
for(int index = 0; index < print_len; index++) {
st->print(" - %3d : ", index);
if (oa->obj_at(index) != nullptr) {
diff --git a/src/hotspot/share/oops/resolvedFieldEntry.hpp b/src/hotspot/share/oops/resolvedFieldEntry.hpp
index ae61433efc9d0..3a66d0efb4d75 100644
--- a/src/hotspot/share/oops/resolvedFieldEntry.hpp
+++ b/src/hotspot/share/oops/resolvedFieldEntry.hpp
@@ -28,6 +28,7 @@
#include "interpreter/bytecodes.hpp"
#include "oops/instanceKlass.hpp"
#include "runtime/atomic.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/sizes.hpp"
// ResolvedFieldEntry contains the resolution information for field related bytecodes like
diff --git a/src/hotspot/share/oops/typeArrayKlass.cpp b/src/hotspot/share/oops/typeArrayKlass.cpp
index 38b4b55efcae3..e20e722c481c1 100644
--- a/src/hotspot/share/oops/typeArrayKlass.cpp
+++ b/src/hotspot/share/oops/typeArrayKlass.cpp
@@ -344,7 +344,7 @@ void TypeArrayKlass::oop_print_on(oop obj, outputStream* st) {
}
void TypeArrayKlass::oop_print_elements_on(typeArrayOop ta, outputStream* st) {
- int print_len = MIN2((intx) ta->length(), MaxElementPrintSize);
+ int print_len = MIN2(ta->length(), MaxElementPrintSize);
switch (element_type()) {
case T_BOOLEAN: print_boolean_array(ta, print_len, st); break;
case T_CHAR: print_char_array(ta, print_len, st); break;
diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp
index 54a23890486cf..ea56e30ed8725 100644
--- a/src/hotspot/share/opto/c2compiler.cpp
+++ b/src/hotspot/share/opto/c2compiler.cpp
@@ -190,6 +190,10 @@ void C2Compiler::print_timers() {
bool C2Compiler::is_intrinsic_supported(const methodHandle& method) {
vmIntrinsics::ID id = method->intrinsic_id();
+ return C2Compiler::is_intrinsic_supported(id);
+}
+
+bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) {
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
if (id < vmIntrinsics::FIRST_ID || id > vmIntrinsics::LAST_COMPILER_INLINE) {
@@ -225,6 +229,21 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method) {
case vmIntrinsics::_copyMemory:
if (StubRoutines::unsafe_arraycopy() == nullptr) return false;
break;
+ case vmIntrinsics::_electronicCodeBook_encryptAESCrypt:
+ if (StubRoutines::electronicCodeBook_encryptAESCrypt() == nullptr) return false;
+ break;
+ case vmIntrinsics::_electronicCodeBook_decryptAESCrypt:
+ if (StubRoutines::electronicCodeBook_decryptAESCrypt() == nullptr) return false;
+ break;
+ case vmIntrinsics::_galoisCounterMode_AESCrypt:
+ if (StubRoutines::galoisCounterMode_AESCrypt() == nullptr) return false;
+ break;
+ case vmIntrinsics::_bigIntegerRightShiftWorker:
+ if (StubRoutines::bigIntegerRightShift() == nullptr) return false;
+ break;
+ case vmIntrinsics::_bigIntegerLeftShiftWorker:
+ if (StubRoutines::bigIntegerLeftShift() == nullptr) return false;
+ break;
case vmIntrinsics::_encodeAsciiArray:
if (!Matcher::match_rule_supported(Op_EncodeISOArray) || !Matcher::supports_encode_ascii_array) return false;
break;
@@ -483,10 +502,10 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method) {
if (!Matcher::match_rule_supported(Op_OnSpinWait)) return false;
break;
case vmIntrinsics::_fmaD:
- if (!UseFMA || !Matcher::match_rule_supported(Op_FmaD)) return false;
+ if (!Matcher::match_rule_supported(Op_FmaD)) return false;
break;
case vmIntrinsics::_fmaF:
- if (!UseFMA || !Matcher::match_rule_supported(Op_FmaF)) return false;
+ if (!Matcher::match_rule_supported(Op_FmaF)) return false;
break;
case vmIntrinsics::_isDigit:
if (!Matcher::match_rule_supported(Op_Digit)) return false;
@@ -716,10 +735,7 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method) {
case vmIntrinsics::_aescrypt_decryptBlock:
case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
- case vmIntrinsics::_electronicCodeBook_encryptAESCrypt:
- case vmIntrinsics::_electronicCodeBook_decryptAESCrypt:
case vmIntrinsics::_counterMode_AESCrypt:
- case vmIntrinsics::_galoisCounterMode_AESCrypt:
case vmIntrinsics::_md5_implCompress:
case vmIntrinsics::_sha_implCompress:
case vmIntrinsics::_sha2_implCompress:
@@ -731,8 +747,6 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method) {
case vmIntrinsics::_mulAdd:
case vmIntrinsics::_montgomeryMultiply:
case vmIntrinsics::_montgomerySquare:
- case vmIntrinsics::_bigIntegerRightShiftWorker:
- case vmIntrinsics::_bigIntegerLeftShiftWorker:
case vmIntrinsics::_vectorizedMismatch:
case vmIntrinsics::_ghash_processBlocks:
case vmIntrinsics::_chacha20Block:
@@ -752,7 +766,6 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method) {
case vmIntrinsics::_Preconditions_checkLongIndex:
case vmIntrinsics::_getObjectSize:
break;
-
case vmIntrinsics::_VectorCompressExpand:
case vmIntrinsics::_VectorUnaryOp:
case vmIntrinsics::_VectorBinaryOp:
diff --git a/src/hotspot/share/opto/c2compiler.hpp b/src/hotspot/share/opto/c2compiler.hpp
index 415688cdad481..bfc335c486942 100644
--- a/src/hotspot/share/opto/c2compiler.hpp
+++ b/src/hotspot/share/opto/c2compiler.hpp
@@ -63,6 +63,8 @@ class C2Compiler : public AbstractCompiler {
// Return false otherwise.
virtual bool is_intrinsic_supported(const methodHandle& method);
+ // Return true if the intrinsic `id` is supported by C2
+ static bool is_intrinsic_supported(vmIntrinsics::ID id);
// Initial size of the code buffer (may be increased at runtime)
static int initial_code_buffer_size(int const_size = initial_const_capacity);
};
diff --git a/src/hotspot/share/opto/castnode.cpp b/src/hotspot/share/opto/castnode.cpp
index d0d05b5bb98f0..8d67f4db00f81 100644
--- a/src/hotspot/share/opto/castnode.cpp
+++ b/src/hotspot/share/opto/castnode.cpp
@@ -32,6 +32,7 @@
#include "opto/subnode.hpp"
#include "opto/type.hpp"
#include "castnode.hpp"
+#include "utilities/checkedCast.hpp"
//=============================================================================
// If input is already higher or equal to cast type, then this is an identity.
diff --git a/src/hotspot/share/opto/convertnode.cpp b/src/hotspot/share/opto/convertnode.cpp
index 54d8ecc4a5465..122195f108c9b 100644
--- a/src/hotspot/share/opto/convertnode.cpp
+++ b/src/hotspot/share/opto/convertnode.cpp
@@ -32,6 +32,7 @@
#include "opto/phaseX.hpp"
#include "opto/subnode.hpp"
#include "runtime/stubRoutines.hpp"
+#include "utilities/checkedCast.hpp"
//=============================================================================
//------------------------------Identity---------------------------------------
diff --git a/src/hotspot/share/opto/doCall.cpp b/src/hotspot/share/opto/doCall.cpp
index a2d321c3260a5..9a3baf0ac4866 100644
--- a/src/hotspot/share/opto/doCall.cpp
+++ b/src/hotspot/share/opto/doCall.cpp
@@ -30,6 +30,10 @@
#include "compiler/compileBroker.hpp"
#include "compiler/compileLog.hpp"
#include "interpreter/linkResolver.hpp"
+#include "logging/log.hpp"
+#include "logging/logLevel.hpp"
+#include "logging/logMessage.hpp"
+#include "logging/logStream.hpp"
#include "opto/addnode.hpp"
#include "opto/callGenerator.hpp"
#include "opto/castnode.hpp"
@@ -46,7 +50,15 @@
#include "jfr/jfr.hpp"
#endif
-void trace_type_profile(Compile* C, ciMethod *method, int depth, int bci, ciMethod *prof_method, ciKlass *prof_klass, int site_count, int receiver_count) {
+void print_trace_type_profile(outputStream* out, int depth, ciKlass* prof_klass, int site_count, int receiver_count) {
+ CompileTask::print_inline_indent(depth, out);
+ out->print(" \\-> TypeProfile (%d/%d counts) = ", receiver_count, site_count);
+ prof_klass->name()->print_symbol_on(out);
+ out->cr();
+}
+
+void trace_type_profile(Compile* C, ciMethod* method, int depth, int bci, ciMethod* prof_method,
+ ciKlass* prof_klass, int site_count, int receiver_count) {
if (TraceTypeProfile || C->print_inlining()) {
outputStream* out = tty;
if (!C->print_inlining()) {
@@ -58,12 +70,13 @@ void trace_type_profile(Compile* C, ciMethod *method, int depth, int bci, ciMeth
} else {
out = C->print_inlining_stream();
}
- CompileTask::print_inline_indent(depth, out);
- out->print(" \\-> TypeProfile (%d/%d counts) = ", receiver_count, site_count);
- stringStream ss;
- prof_klass->name()->print_symbol_on(&ss);
- out->print("%s", ss.freeze());
- out->cr();
+ print_trace_type_profile(out, depth, prof_klass, site_count, receiver_count);
+ }
+
+ LogTarget(Debug, jit, inlining) lt;
+ if (lt.is_enabled()) {
+ LogStream ls(lt);
+ print_trace_type_profile(&ls, depth, prof_klass, site_count, receiver_count);
}
}
@@ -984,6 +997,8 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
if (PrintOpto && WizardMode) {
tty->print_cr(" Catching every inline exception bci:%d -> handler_bci:%d", bci(), handler_bci);
}
+ // If this is a backwards branch in the bytecodes, add safepoint
+ maybe_add_safepoint(handler_bci);
merge_exception(handler_bci); // jump to handler
return; // No more handling to be done here!
}
@@ -1015,6 +1030,8 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
klass->print_name();
tty->cr();
}
+ // If this is a backwards branch in the bytecodes, add safepoint
+ maybe_add_safepoint(handler_bci);
merge_exception(handler_bci);
}
set_control(not_subtype_ctrl);
diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp
index 179dd97c1193a..8d68d18b638f5 100644
--- a/src/hotspot/share/opto/graphKit.cpp
+++ b/src/hotspot/share/opto/graphKit.cpp
@@ -3728,7 +3728,10 @@ Node* GraphKit::new_instance(Node* klass_node,
//-------------------------------new_array-------------------------------------
// helper for both newarray and anewarray
// The 'length' parameter is (obviously) the length of the array.
-// See comments on new_instance for the meaning of the other arguments.
+// The optional arguments are for specialized use by intrinsics:
+// - If 'return_size_val', report the non-padded array size (sum of header size
+// and array body) to the caller.
+// - deoptimize_on_exception controls how Java exceptions are handled (rethrow vs deoptimize)
Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
Node* length, // number of array elements
int nargs, // number of arguments to push back for uncommon trap
@@ -3779,25 +3782,21 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
// The rounding mask is strength-reduced, if possible.
int round_mask = MinObjAlignmentInBytes - 1;
Node* header_size = nullptr;
- int header_size_min = arrayOopDesc::base_offset_in_bytes(T_BYTE);
// (T_BYTE has the weakest alignment and size restrictions...)
if (layout_is_con) {
int hsize = Klass::layout_helper_header_size(layout_con);
int eshift = Klass::layout_helper_log2_element_size(layout_con);
- BasicType etype = Klass::layout_helper_element_type(layout_con);
if ((round_mask & ~right_n_bits(eshift)) == 0)
round_mask = 0; // strength-reduce it if it goes away completely
assert((hsize & right_n_bits(eshift)) == 0, "hsize is pre-rounded");
+ int header_size_min = arrayOopDesc::base_offset_in_bytes(T_BYTE);
assert(header_size_min <= hsize, "generic minimum is smallest");
- header_size_min = hsize;
- header_size = intcon(hsize + round_mask);
+ header_size = intcon(hsize);
} else {
Node* hss = intcon(Klass::_lh_header_size_shift);
Node* hsm = intcon(Klass::_lh_header_size_mask);
- Node* hsize = _gvn.transform( new URShiftINode(layout_val, hss) );
- hsize = _gvn.transform( new AndINode(hsize, hsm) );
- Node* mask = intcon(round_mask);
- header_size = _gvn.transform( new AddINode(hsize, mask) );
+ header_size = _gvn.transform(new URShiftINode(layout_val, hss));
+ header_size = _gvn.transform(new AndINode(header_size, hsm));
}
Node* elem_shift = nullptr;
@@ -3849,25 +3848,30 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
}
#endif
- // Combine header size (plus rounding) and body size. Then round down.
- // This computation cannot overflow, because it is used only in two
- // places, one where the length is sharply limited, and the other
- // after a successful allocation.
+ // Combine header size and body size for the array copy part, then align (if
+ // necessary) for the allocation part. This computation cannot overflow,
+ // because it is used only in two places, one where the length is sharply
+ // limited, and the other after a successful allocation.
Node* abody = lengthx;
- if (elem_shift != nullptr)
- abody = _gvn.transform( new LShiftXNode(lengthx, elem_shift) );
- Node* size = _gvn.transform( new AddXNode(headerx, abody) );
- if (round_mask != 0) {
- Node* mask = MakeConX(~round_mask);
- size = _gvn.transform( new AndXNode(size, mask) );
+ if (elem_shift != nullptr) {
+ abody = _gvn.transform(new LShiftXNode(lengthx, elem_shift));
}
- // else if round_mask == 0, the size computation is self-rounding
+ Node* non_rounded_size = _gvn.transform(new AddXNode(headerx, abody));
if (return_size_val != nullptr) {
// This is the size
- (*return_size_val) = size;
+ (*return_size_val) = non_rounded_size;
}
+ Node* size = non_rounded_size;
+ if (round_mask != 0) {
+ Node* mask1 = MakeConX(round_mask);
+ size = _gvn.transform(new AddXNode(size, mask1));
+ Node* mask2 = MakeConX(~round_mask);
+ size = _gvn.transform(new AndXNode(size, mask2));
+ }
+ // else if round_mask == 0, the size computation is self-rounding
+
// Now generate allocation code
// The entire memory state is needed for slow path of the allocation
diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp
index 1e59e4a59d5f0..4b930d71ac864 100644
--- a/src/hotspot/share/opto/library_call.cpp
+++ b/src/hotspot/share/opto/library_call.cpp
@@ -5021,8 +5021,8 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
PreserveJVMState pjvms(this);
set_control(array_ctl);
Node* obj_length = load_array_length(obj);
- Node* obj_size = nullptr;
- Node* alloc_obj = new_array(obj_klass, obj_length, 0, &obj_size, /*deoptimize_on_exception=*/true);
+ Node* array_size = nullptr; // Size of the array without object alignment padding.
+ Node* alloc_obj = new_array(obj_klass, obj_length, 0, &array_size, /*deoptimize_on_exception=*/true);
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
if (bs->array_copy_requires_gc_barriers(true, T_OBJECT, true, false, BarrierSetC2::Parsing)) {
@@ -5055,7 +5055,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
// the object.)
if (!stopped()) {
- copy_to_clone(obj, alloc_obj, obj_size, true);
+ copy_to_clone(obj, alloc_obj, array_size, true);
// Present the results of the copy.
result_reg->init_req(_array_path, control());
@@ -5095,7 +5095,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
if (!stopped()) {
// It's an instance, and it passed the slow-path tests.
PreserveJVMState pjvms(this);
- Node* obj_size = nullptr;
+ Node* obj_size = nullptr; // Total object size, including object alignment padding.
// Need to deoptimize on exception from allocation since Object.clone intrinsic
// is reexecuted if deoptimization occurs and there could be problems when merging
// exception state between multiple Object.clone versions (reexecute=true vs reexecute=false).
diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp
index 906af75091a4e..6c655e6f13774 100644
--- a/src/hotspot/share/opto/loopPredicate.cpp
+++ b/src/hotspot/share/opto/loopPredicate.cpp
@@ -445,9 +445,8 @@ void PhaseIdealLoop::clone_loop_predication_predicates_to_unswitched_loop(IdealL
Deoptimization::DeoptReason reason,
IfProjNode*& iffast_pred,
IfProjNode*& ifslow_pred) {
- if (predicate_block->is_non_empty()) {
+ if (predicate_block->has_parse_predicate()) {
clone_parse_predicate_to_unswitched_loops(predicate_block, reason, iffast_pred, ifslow_pred);
-
clone_assertion_predicates_to_unswitched_loop(loop, old_new, reason, predicate_block->parse_predicate_success_proj(),
iffast_pred, ifslow_pred);
}
@@ -456,6 +455,7 @@ void PhaseIdealLoop::clone_loop_predication_predicates_to_unswitched_loop(IdealL
void PhaseIdealLoop::clone_parse_predicate_to_unswitched_loops(const PredicateBlock* predicate_block,
Deoptimization::DeoptReason reason,
IfProjNode*& iffast_pred, IfProjNode*& ifslow_pred) {
+ assert(predicate_block->has_parse_predicate(), "must have parse predicate");
ParsePredicateSuccessProj* parse_predicate_proj = predicate_block->parse_predicate_success_proj();
iffast_pred = clone_parse_predicate_to_unswitched_loop(parse_predicate_proj, iffast_pred, reason, false);
check_cloned_parse_predicate_for_unswitching(iffast_pred, true);
diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp
index a3f59e2bb9caa..270cc16f8c7c2 100644
--- a/src/hotspot/share/opto/loopTransform.cpp
+++ b/src/hotspot/share/opto/loopTransform.cpp
@@ -2073,18 +2073,23 @@ void PhaseIdealLoop::initialize_assertion_predicates_for_peeled_loop(const Predi
Node* stride, IdealLoopTree* outer_loop,
const uint idx_before_clone,
const Node_List &old_new) {
- if (!predicate_block->has_runtime_predicates()) {
+ if (!predicate_block->has_parse_predicate()) {
return;
}
Node* control = outer_loop_head->in(LoopNode::EntryControl);
Node* input_proj = control;
+ const Node* parse_predicate_uncommon_trap = predicate_block->parse_predicate()->uncommon_trap();
Node* next_regular_predicate_proj = predicate_block->skip_parse_predicate();
while (next_regular_predicate_proj->is_IfProj()) {
IfNode* iff = next_regular_predicate_proj->in(0)->as_If();
+ ProjNode* uncommon_proj = iff->proj_out(1 - next_regular_predicate_proj->as_Proj()->_con);
+ if (uncommon_proj->unique_ctrl_out() != parse_predicate_uncommon_trap) {
+ // Does not belong to this Predicate Block anymore.
+ break;
+ }
if (iff->in(1)->Opcode() == Op_Opaque4) {
assert(assertion_predicate_has_loop_opaque_node(iff), "unexpected");
- ProjNode* uncommon_proj = iff->proj_out(1 - next_regular_predicate_proj->as_Proj()->_con);
input_proj = clone_assertion_predicate_and_initialize(iff, init, stride, next_regular_predicate_proj, uncommon_proj, control,
outer_loop, input_proj);
diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp
index 7285e66d65048..393456b8eec86 100644
--- a/src/hotspot/share/opto/loopnode.cpp
+++ b/src/hotspot/share/opto/loopnode.cpp
@@ -47,6 +47,7 @@
#include "opto/runtime.hpp"
#include "opto/superword.hpp"
#include "runtime/sharedRuntime.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/powerOfTwo.hpp"
//=============================================================================
diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp
index a28d91a35b343..b238de71a9556 100644
--- a/src/hotspot/share/opto/loopnode.hpp
+++ b/src/hotspot/share/opto/loopnode.hpp
@@ -30,6 +30,7 @@
#include "opto/phaseX.hpp"
#include "opto/subnode.hpp"
#include "opto/type.hpp"
+#include "utilities/checkedCast.hpp"
class CmpNode;
class BaseCountedLoopEndNode;
diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp
index e74e088c5ef93..89b723bf92c73 100644
--- a/src/hotspot/share/opto/loopopts.cpp
+++ b/src/hotspot/share/opto/loopopts.cpp
@@ -1642,7 +1642,7 @@ void PhaseIdealLoop::try_sink_out_of_loop(Node* n) {
// Find control for 'x' next to use but not inside inner loops.
x_ctrl = place_outside_loop(x_ctrl, n_loop);
// Replace all uses
- if (u->is_ConstraintCast() && u->bottom_type()->higher_equal(_igvn.type(n)) && u->in(0) == x_ctrl) {
+ if (u->is_ConstraintCast() && _igvn.type(n)->higher_equal(u->bottom_type()) && u->in(0) == x_ctrl) {
// If we're sinking a chain of data nodes, we might have inserted a cast to pin the use which is not necessary
// anymore now that we're going to pin n as well
_igvn.replace_node(u, x);
diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp
index e79492a62e8a6..6709f8314478f 100644
--- a/src/hotspot/share/opto/mulnode.cpp
+++ b/src/hotspot/share/opto/mulnode.cpp
@@ -1711,6 +1711,20 @@ const Type* URShiftLNode::Value(PhaseGVN* phase) const {
return TypeLong::LONG; // Give up
}
+//=============================================================================
+//------------------------------Ideal------------------------------------------
+Node* FmaNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ // We canonicalize the node by converting "(-a)*b+c" into "b*(-a)+c"
+ // This reduces the number of rules in the matcher, as we only need to check
+ // for negations on the second argument, and not the symmetric case where
+ // the first argument is negated.
+ if (in(1)->is_Neg() && !in(2)->is_Neg()) {
+ swap_edges(1, 2);
+ return this;
+ }
+ return nullptr;
+}
+
//=============================================================================
//------------------------------Value------------------------------------------
const Type* FmaDNode::Value(PhaseGVN* phase) const {
diff --git a/src/hotspot/share/opto/mulnode.hpp b/src/hotspot/share/opto/mulnode.hpp
index 84307fb00fb6c..d04648ee61a8d 100644
--- a/src/hotspot/share/opto/mulnode.hpp
+++ b/src/hotspot/share/opto/mulnode.hpp
@@ -357,24 +357,34 @@ class URShiftLNode : public Node {
virtual uint ideal_reg() const { return Op_RegL; }
};
+//------------------------------FmaNode--------------------------------------
+// fused-multiply-add
+class FmaNode : public Node {
+public:
+ FmaNode(Node* c, Node* in1, Node* in2, Node* in3) : Node(c, in1, in2, in3) {
+ assert(UseFMA, "Needs FMA instructions support.");
+ }
+ virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
//------------------------------FmaDNode--------------------------------------
// fused-multiply-add double
-class FmaDNode : public Node {
+class FmaDNode : public FmaNode {
public:
- FmaDNode(Node *c, Node *in1, Node *in2, Node *in3) : Node(c, in1, in2, in3) {}
+ FmaDNode(Node* c, Node* in1, Node* in2, Node* in3) : FmaNode(c, in1, in2, in3) {}
virtual int Opcode() const;
- const Type *bottom_type() const { return Type::DOUBLE; }
+ const Type* bottom_type() const { return Type::DOUBLE; }
virtual uint ideal_reg() const { return Op_RegD; }
virtual const Type* Value(PhaseGVN* phase) const;
};
//------------------------------FmaFNode--------------------------------------
// fused-multiply-add float
-class FmaFNode : public Node {
+class FmaFNode : public FmaNode {
public:
- FmaFNode(Node *c, Node *in1, Node *in2, Node *in3) : Node(c, in1, in2, in3) {}
+ FmaFNode(Node* c, Node* in1, Node* in2, Node* in3) : FmaNode(c, in1, in2, in3) {}
virtual int Opcode() const;
- const Type *bottom_type() const { return Type::FLOAT; }
+ const Type* bottom_type() const { return Type::FLOAT; }
virtual uint ideal_reg() const { return Op_RegF; }
virtual const Type* Value(PhaseGVN* phase) const;
};
diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp
index 755374e18a921..50134fe0e02d3 100644
--- a/src/hotspot/share/opto/node.hpp
+++ b/src/hotspot/share/opto/node.hpp
@@ -129,6 +129,8 @@ class MoveNode;
class MulNode;
class MultiNode;
class MultiBranchNode;
+class NegNode;
+class NegVNode;
class NeverBranchNode;
class Opaque1Node;
class OuterStripMinedLoopNode;
@@ -725,6 +727,7 @@ class Node {
DEFINE_CLASS_ID(CompressM, Vector, 6)
DEFINE_CLASS_ID(Reduction, Vector, 7)
DEFINE_CLASS_ID(UnorderedReduction, Reduction, 0)
+ DEFINE_CLASS_ID(NegV, Vector, 8)
DEFINE_CLASS_ID(Con, Type, 8)
DEFINE_CLASS_ID(ConI, Con, 0)
DEFINE_CLASS_ID(SafePointScalarMerge, Type, 9)
@@ -780,8 +783,9 @@ class Node {
DEFINE_CLASS_ID(Opaque1, Node, 16)
DEFINE_CLASS_ID(Move, Node, 17)
DEFINE_CLASS_ID(LShift, Node, 18)
+ DEFINE_CLASS_ID(Neg, Node, 19)
- _max_classes = ClassMask_LShift
+ _max_classes = ClassMask_Neg
};
#undef DEFINE_CLASS_ID
@@ -941,6 +945,8 @@ class Node {
DEFINE_CLASS_QUERY(Mul)
DEFINE_CLASS_QUERY(Multi)
DEFINE_CLASS_QUERY(MultiBranch)
+ DEFINE_CLASS_QUERY(Neg)
+ DEFINE_CLASS_QUERY(NegV)
DEFINE_CLASS_QUERY(NeverBranch)
DEFINE_CLASS_QUERY(Opaque1)
DEFINE_CLASS_QUERY(OuterStripMinedLoop)
diff --git a/src/hotspot/share/opto/subnode.hpp b/src/hotspot/share/opto/subnode.hpp
index a4edeb4053f66..f424e258db2cf 100644
--- a/src/hotspot/share/opto/subnode.hpp
+++ b/src/hotspot/share/opto/subnode.hpp
@@ -430,7 +430,9 @@ class CmpLTMaskNode : public Node {
//------------------------------NegNode----------------------------------------
class NegNode : public Node {
public:
- NegNode( Node *in1 ) : Node(0,in1) {}
+ NegNode(Node* in1) : Node(0, in1) {
+ init_class_id(Class_Neg);
+ }
};
//------------------------------NegINode---------------------------------------
diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp
index 3e78b5580c50e..8cd3e46dcf5b2 100644
--- a/src/hotspot/share/opto/superword.cpp
+++ b/src/hotspot/share/opto/superword.cpp
@@ -1270,6 +1270,7 @@ bool SuperWord::isomorphic(Node* s1, Node* s2) {
if (s1->Opcode() != s2->Opcode()) return false;
if (s1->req() != s2->req()) return false;
if (!same_velt_type(s1, s2)) return false;
+ if (s1->is_Bool() && s1->as_Bool()->_test._test != s2->as_Bool()->_test._test) return false;
Node* s1_ctrl = s1->in(0);
Node* s2_ctrl = s2->in(0);
// If the control nodes are equivalent, no further checks are required to test for isomorphism.
@@ -2656,6 +2657,14 @@ bool SuperWord::output() {
Node_List* p_bol = my_pack(bol);
assert(p_bol != nullptr, "CMove must have matching Bool pack");
+#ifdef ASSERT
+ for (uint j = 0; j < p_bol->size(); j++) {
+ Node* m = p_bol->at(j);
+ assert(m->as_Bool()->_test._test == bol_test,
+ "all bool nodes must have same test");
+ }
+#endif
+
CmpNode* cmp = bol->in(1)->as_Cmp();
assert(cmp != nullptr, "must have cmp above CMove");
Node_List* p_cmp = my_pack(cmp);
diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp
index 8229c64494225..a9a2dc14bbab1 100644
--- a/src/hotspot/share/opto/type.cpp
+++ b/src/hotspot/share/opto/type.cpp
@@ -39,6 +39,7 @@
#include "opto/node.hpp"
#include "opto/opcodes.hpp"
#include "opto/type.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/powerOfTwo.hpp"
#include "utilities/stringUtils.hpp"
diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp
index 00926f6ab2fef..8b6ba1f5cb97d 100644
--- a/src/hotspot/share/opto/vectornode.cpp
+++ b/src/hotspot/share/opto/vectornode.cpp
@@ -1876,6 +1876,21 @@ Node* VectorLongToMaskNode::Ideal(PhaseGVN* phase, bool can_reshape) {
return nullptr;
}
+Node* FmaVNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ // We canonicalize the node by converting "(-a)*b+c" into "b*(-a)+c"
+ // This reduces the number of rules in the matcher, as we only need to check
+ // for negations on the second argument, and not the symmetric case where
+ // the first argument is negated.
+ // We cannot do this if the FmaV is masked, since the inactive lanes have to return
+ // the first input (i.e. "-a"). If we were to swap the inputs, the inactive lanes would
+ // incorrectly return "b".
+ if (!is_predicated_vector() && in(1)->is_NegV() && !in(2)->is_NegV()) {
+ swap_edges(1, 2);
+ return this;
+ }
+ return nullptr;
+}
+
// Generate other vector nodes to implement the masked/non-masked vector negation.
Node* NegVNode::degenerate_integral_negate(PhaseGVN* phase, bool is_predicated) {
const TypeVect* vt = vect_type();
diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp
index 3ac54c5d5352c..fbe9b939991e2 100644
--- a/src/hotspot/share/opto/vectornode.hpp
+++ b/src/hotspot/share/opto/vectornode.hpp
@@ -376,19 +376,29 @@ class MulAddVS2VINode : public VectorNode {
virtual int Opcode() const;
};
+//------------------------------FmaVNode--------------------------------------
+// Vector fused-multiply-add
+class FmaVNode : public VectorNode {
+public:
+ FmaVNode(Node* in1, Node* in2, Node* in3, const TypeVect* vt) : VectorNode(in1, in2, in3, vt) {
+ assert(UseFMA, "Needs FMA instructions support.");
+ }
+ virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
//------------------------------FmaVDNode--------------------------------------
-// Vector multiply double
-class FmaVDNode : public VectorNode {
+// Vector fused-multiply-add double
+class FmaVDNode : public FmaVNode {
public:
- FmaVDNode(Node* in1, Node* in2, Node* in3, const TypeVect* vt) : VectorNode(in1, in2, in3, vt) {}
+ FmaVDNode(Node* in1, Node* in2, Node* in3, const TypeVect* vt) : FmaVNode(in1, in2, in3, vt) {}
virtual int Opcode() const;
};
//------------------------------FmaVFNode--------------------------------------
-// Vector multiply float
-class FmaVFNode : public VectorNode {
+// Vector fused-multiply-add float
+class FmaVFNode : public FmaVNode {
public:
- FmaVFNode(Node* in1, Node* in2, Node* in3, const TypeVect* vt) : VectorNode(in1, in2, in3, vt) {}
+ FmaVFNode(Node* in1, Node* in2, Node* in3, const TypeVect* vt) : FmaVNode(in1, in2, in3, vt) {}
virtual int Opcode() const;
};
@@ -508,7 +518,9 @@ class AbsVDNode : public VectorNode {
// Vector Neg parent class (not for code generation).
class NegVNode : public VectorNode {
public:
- NegVNode(Node* in, const TypeVect* vt) : VectorNode(in, vt) {}
+ NegVNode(Node* in, const TypeVect* vt) : VectorNode(in, vt) {
+ init_class_id(Class_NegV);
+ }
virtual int Opcode() const = 0;
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
diff --git a/src/hotspot/share/prims/forte.cpp b/src/hotspot/share/prims/forte.cpp
index e45d7d4a0166c..53dbc3caee00f 100644
--- a/src/hotspot/share/prims/forte.cpp
+++ b/src/hotspot/share/prims/forte.cpp
@@ -35,6 +35,7 @@
#include "runtime/javaThread.inline.hpp"
#include "runtime/vframe.inline.hpp"
#include "runtime/vframeArray.hpp"
+#include "utilities/checkedCast.hpp"
// call frame copied from old .h file and renamed
typedef struct {
diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp
index 250f642604d8f..685db6b939a05 100644
--- a/src/hotspot/share/prims/jvm.cpp
+++ b/src/hotspot/share/prims/jvm.cpp
@@ -95,6 +95,7 @@
#include "services/attachListener.hpp"
#include "services/management.hpp"
#include "services/threadService.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/copy.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/dtrace.hpp"
diff --git a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp
index 699c97c713997..96937554b3063 100644
--- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp
+++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp
@@ -34,6 +34,7 @@
#include "runtime/handles.inline.hpp"
#include "runtime/signature.hpp"
#include "utilities/bytes.hpp"
+#include "utilities/checkedCast.hpp"
// FIXME: add Deprecated attribute
// FIXME: fix Synthetic attribute
diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
index 6505a58b9f067..fad6b2901f0aa 100644
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp
@@ -62,6 +62,7 @@
#include "runtime/relocator.hpp"
#include "runtime/safepointVerifiers.hpp"
#include "utilities/bitMap.inline.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/events.hpp"
Array* VM_RedefineClasses::_old_methods = nullptr;
diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp
index fbcbd2b15907e..c10fe1f66010c 100644
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp
@@ -126,11 +126,9 @@ class ResolvedMethodTableLookup : StackObj {
uintx get_hash() const {
return _hash;
}
- bool equals(WeakHandle* value, bool* is_dead) {
+ bool equals(WeakHandle* value) {
oop val_oop = value->peek();
if (val_oop == nullptr) {
- // dead oop, mark this hash dead for cleaning
- *is_dead = true;
return false;
}
bool equals = _method == java_lang_invoke_ResolvedMethodName::vmtarget(val_oop);
@@ -141,6 +139,10 @@ class ResolvedMethodTableLookup : StackObj {
_found = Handle(_thread, value->resolve());
return true;
}
+ bool is_dead(WeakHandle* value) {
+ oop val_oop = value->peek();
+ return val_oop == nullptr;
+ }
};
diff --git a/src/hotspot/share/prims/upcallLinker.cpp b/src/hotspot/share/prims/upcallLinker.cpp
index 7be41f7447f80..1576c0115254d 100644
--- a/src/hotspot/share/prims/upcallLinker.cpp
+++ b/src/hotspot/share/prims/upcallLinker.cpp
@@ -31,6 +31,7 @@
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jniHandles.inline.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/globalDefinitions.hpp"
#define FOREIGN_ABI "jdk/internal/foreign/abi/"
diff --git a/src/hotspot/share/prims/vmstorage.hpp b/src/hotspot/share/prims/vmstorage.hpp
index a99f5d389af76..a50f95ffc56ee 100644
--- a/src/hotspot/share/prims/vmstorage.hpp
+++ b/src/hotspot/share/prims/vmstorage.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
#include
#include "code/vmreg.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/ostream.hpp"
diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp
index a9064792a56ec..c64f6981cad22 100644
--- a/src/hotspot/share/prims/whitebox.cpp
+++ b/src/hotspot/share/prims/whitebox.cpp
@@ -93,6 +93,7 @@
#include "services/memoryService.hpp"
#include "services/memTracker.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/elfFile.hpp"
#include "utilities/exceptions.hpp"
diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp
index a9384c3bb804c..f872d0eb4a404 100644
--- a/src/hotspot/share/runtime/arguments.cpp
+++ b/src/hotspot/share/runtime/arguments.cpp
@@ -60,6 +60,7 @@
#include "services/management.hpp"
#include "services/nmtCommon.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/macros.hpp"
diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp
index c825b955b1f64..d643714a3f7a2 100644
--- a/src/hotspot/share/runtime/deoptimization.cpp
+++ b/src/hotspot/share/runtime/deoptimization.cpp
@@ -89,6 +89,7 @@
#include "runtime/vframeArray.hpp"
#include "runtime/vframe_hp.hpp"
#include "runtime/vmOperations.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/events.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp
index cd3566f193c97..1c02e92911309 100644
--- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp
+++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp
@@ -65,10 +65,10 @@ JVMFlag::Error ContendedPaddingWidthConstraintFunc(int value, bool verbose) {
}
}
-JVMFlag::Error PerfDataSamplingIntervalFunc(intx value, bool verbose) {
+JVMFlag::Error PerfDataSamplingIntervalFunc(int value, bool verbose) {
if ((value % PeriodicTask::interval_gran != 0)) {
JVMFlag::printError(verbose,
- "PerfDataSamplingInterval (" INTX_FORMAT ") must be "
+ "PerfDataSamplingInterval (%d) must be "
"evenly divisible by PeriodicTask::interval_gran (%d)\n",
value, PeriodicTask::interval_gran);
return JVMFlag::VIOLATES_CONSTRAINT;
diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp
index 68cac4bad9c57..cbe28456b8ae9 100644
--- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp
+++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp
@@ -36,7 +36,7 @@
#define RUNTIME_CONSTRAINTS(f) \
f(int, ObjectAlignmentInBytesConstraintFunc) \
f(int, ContendedPaddingWidthConstraintFunc) \
- f(intx, PerfDataSamplingIntervalFunc) \
+ f(int, PerfDataSamplingIntervalFunc) \
f(uintx, VMPageSizeConstraintFunc) \
f(size_t, NUMAInterleaveGranularityConstraintFunc)
diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp
index c0d6238f05308..f4893bae5db95 100644
--- a/src/hotspot/share/runtime/frame.cpp
+++ b/src/hotspot/share/runtime/frame.cpp
@@ -1612,10 +1612,10 @@ void FrameValues::print_on(stackChunkOop chunk, outputStream* st) {
while (!(start <= v0 && v0 <= end)) v0 = _values.at(++min_index).location;
while (!(start <= v1 && v1 <= end)) v1 = _values.at(--max_index).location;
- print_on(st, min_index, max_index, v0, v1, true /* on_heap */);
+ print_on(st, min_index, max_index, v0, v1);
}
-void FrameValues::print_on(outputStream* st, int min_index, int max_index, intptr_t* v0, intptr_t* v1, bool on_heap) {
+void FrameValues::print_on(outputStream* st, int min_index, int max_index, intptr_t* v0, intptr_t* v1) {
intptr_t* min = MIN2(v0, v1);
intptr_t* max = MAX2(v0, v1);
intptr_t* cur = max;
@@ -1630,8 +1630,7 @@ void FrameValues::print_on(outputStream* st, int min_index, int max_index, intpt
const char* spacer = " " LP64_ONLY(" ");
st->print_cr(" %s %s %s", spacer, spacer, fv.description);
} else {
- if (on_heap
- && *fv.location != 0 && *fv.location > -100 && *fv.location < 100
+ if (*fv.location != 0 && *fv.location > -100 && *fv.location < 100
#if !defined(PPC64)
&& (strncmp(fv.description, "interpreter_frame_", 18) == 0 || strstr(fv.description, " method "))
#else // !defined(PPC64)
diff --git a/src/hotspot/share/runtime/frame.hpp b/src/hotspot/share/runtime/frame.hpp
index fcfb51c008b69..042464c8d4f30 100644
--- a/src/hotspot/share/runtime/frame.hpp
+++ b/src/hotspot/share/runtime/frame.hpp
@@ -30,6 +30,7 @@
#include "oops/oopsHierarchy.hpp"
#include "runtime/basicLock.hpp"
#include "runtime/monitorChunk.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#ifdef ZERO
@@ -249,6 +250,12 @@ class frame {
// Interpreter frames in continuation stacks are on the heap, and internal addresses are relative to fp.
intptr_t at_relative(int index) const { return (intptr_t)(fp() + fp()[index]); }
+ intptr_t at_relative_or_null(int index) const {
+ return (fp()[index] != 0)
+ ? (intptr_t)(fp() + fp()[index])
+ : 0;
+ }
+
intptr_t at(int index) const {
return _on_heap ? at_relative(index) : at_absolute(index);
}
@@ -519,8 +526,7 @@ class FrameValues {
return checked_cast(a->location - b->location);
}
- void print_on(outputStream* out, int min_index, int max_index, intptr_t* v0, intptr_t* v1,
- bool on_heap = false);
+ void print_on(outputStream* out, int min_index, int max_index, intptr_t* v0, intptr_t* v1);
public:
// Used by frame functions to describe locations.
diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp
index a8e47234ff18e..6e69c2ddd039a 100644
--- a/src/hotspot/share/runtime/globals.hpp
+++ b/src/hotspot/share/runtime/globals.hpp
@@ -447,7 +447,7 @@ const int ObjectAlignmentInBytes = 8;
product(bool, LogEvents, true, DIAGNOSTIC, \
"Enable the various ring buffer event logs") \
\
- product(uintx, LogEventsBufferEntries, 20, DIAGNOSTIC, \
+ product(int, LogEventsBufferEntries, 20, DIAGNOSTIC, \
"Number of ring buffer event logs") \
range(1, NOT_LP64(1*K) LP64_ONLY(1*M)) \
\
@@ -557,7 +557,7 @@ const int ObjectAlignmentInBytes = 8;
"directory) of the dump file (defaults to java_pid.hprof " \
"in the working directory)") \
\
- product(intx, HeapDumpGzipLevel, 0, MANAGEABLE, \
+ product(int, HeapDumpGzipLevel, 0, MANAGEABLE, \
"When HeapDumpOnOutOfMemoryError is on, the gzip compression " \
"level of the dump file. 0 (the default) disables gzip " \
"compression. Otherwise the level must be between 1 and 9.") \
@@ -1105,7 +1105,7 @@ const int ObjectAlignmentInBytes = 8;
notproduct(bool, CollectIndexSetStatistics, false, \
"Collect information about IndexSets") \
\
- develop(intx, FastAllocateSizeLimit, 128*K, \
+ develop(int, FastAllocateSizeLimit, 128*K, \
/* Note: This value is zero mod 1<<13 for a cheap sparc set. */ \
"Inline allocations larger than this in doublewords must go slow")\
\
@@ -1238,28 +1238,28 @@ const int ObjectAlignmentInBytes = 8;
"When using recompilation, never interpret methods " \
"containing loops") \
\
- product(intx, AllocatePrefetchStyle, 1, \
+ product(int, AllocatePrefetchStyle, 1, \
"0 = no prefetch, " \
"1 = generate prefetch instructions for each allocation, " \
"2 = use TLAB watermark to gate allocation prefetch, " \
"3 = generate one prefetch instruction per cache line") \
range(0, 3) \
\
- product(intx, AllocatePrefetchDistance, -1, \
+ product(int, AllocatePrefetchDistance, -1, \
"Distance to prefetch ahead of allocation pointer. " \
"-1: use system-specific value (automatically determined") \
range(-1, 512) \
\
- product(intx, AllocatePrefetchLines, 3, \
+ product(int, AllocatePrefetchLines, 3, \
"Number of lines to prefetch ahead of array allocation pointer") \
range(1, 64) \
\
- product(intx, AllocateInstancePrefetchLines, 1, \
+ product(int, AllocateInstancePrefetchLines, 1, \
"Number of lines to prefetch ahead of instance allocation " \
"pointer") \
range(1, 64) \
\
- product(intx, AllocatePrefetchStepSize, 16, \
+ product(int, AllocatePrefetchStepSize, 16, \
"Step size in bytes of sequential prefetch instructions") \
range(1, 512) \
constraint(AllocatePrefetchStepSizeConstraintFunc,AfterMemoryInit)\
@@ -1312,14 +1312,14 @@ const int ObjectAlignmentInBytes = 8;
develop(intx, MallocCatchPtr, -1, \
"Hit breakpoint when mallocing/freeing this pointer") \
\
- develop(intx, StackPrintLimit, 100, \
+ develop(int, StackPrintLimit, 100, \
"number of stack frames to print in VM-level stack dump") \
\
product(int, ErrorLogPrintCodeLimit, 3, DIAGNOSTIC, \
"max number of compiled code units to print in error log") \
range(0, VMError::max_error_log_print_code) \
\
- notproduct(intx, MaxElementPrintSize, 256, \
+ notproduct(int, MaxElementPrintSize, 256, \
"maximum number of elements to print") \
\
notproduct(intx, MaxSubklassPrintSize, 4, \
@@ -1461,13 +1461,13 @@ const int ObjectAlignmentInBytes = 8;
"The minimum expansion of Metaspace (in bytes)") \
range(0, max_uintx) \
\
- product(uintx, MaxMetaspaceFreeRatio, 70, \
+ product(uint, MaxMetaspaceFreeRatio, 70, \
"The maximum percentage of Metaspace free after GC to avoid " \
"shrinking") \
range(0, 100) \
constraint(MaxMetaspaceFreeRatioConstraintFunc,AfterErgo) \
\
- product(uintx, MinMetaspaceFreeRatio, 40, \
+ product(uint, MinMetaspaceFreeRatio, 40, \
"The minimum percentage of Metaspace free after GC to avoid " \
"expansion") \
range(0, 99) \
@@ -1746,7 +1746,7 @@ const int ObjectAlignmentInBytes = 8;
"The string %p in the file name (if present) " \
"will be replaced by pid") \
\
- product(intx, PerfDataSamplingInterval, 50, \
+ product(int, PerfDataSamplingInterval, 50, \
"Data sampling interval (in milliseconds)") \
range(PeriodicTask::min_interval, max_jint) \
constraint(PerfDataSamplingIntervalFunc, AfterErgo) \
diff --git a/src/hotspot/share/runtime/handshake.cpp b/src/hotspot/share/runtime/handshake.cpp
index b4534837cad37..e3ecc2be6fd06 100644
--- a/src/hotspot/share/runtime/handshake.cpp
+++ b/src/hotspot/share/runtime/handshake.cpp
@@ -497,8 +497,17 @@ HandshakeOperation* HandshakeState::get_op_for_self(bool allow_suspend, bool che
}
bool HandshakeState::has_operation(bool allow_suspend, bool check_async_exception) {
- MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag);
- return get_op_for_self(allow_suspend, check_async_exception) != nullptr;
+ // We must not block here as that could lead to deadlocks if we already hold an
+ // "external" mutex. If the try_lock fails then we assume that there is an operation
+ // and force the caller to check more carefully in a safer context. If we can't get
+ // the lock it means another thread is trying to handshake with us, so it can't
+ // happen during thread termination and destruction.
+ bool ret = true;
+ if (_lock.try_lock()) {
+ ret = get_op_for_self(allow_suspend, check_async_exception) != nullptr;
+ _lock.unlock();
+ }
+ return ret;
}
bool HandshakeState::has_async_exception_operation() {
diff --git a/src/hotspot/share/runtime/jfieldIDWorkaround.hpp b/src/hotspot/share/runtime/jfieldIDWorkaround.hpp
index 19336e0d5953c..e44fb0648134c 100644
--- a/src/hotspot/share/runtime/jfieldIDWorkaround.hpp
+++ b/src/hotspot/share/runtime/jfieldIDWorkaround.hpp
@@ -25,6 +25,8 @@
#ifndef SHARE_RUNTIME_JFIELDIDWORKAROUND_HPP
#define SHARE_RUNTIME_JFIELDIDWORKAROUND_HPP
+#include "utilities/checkedCast.hpp"
+
class jfieldIDWorkaround: AllStatic {
// This workaround is because JVMTI doesn't have distinct entry points
// for methods that use static jfieldIDs and instance jfieldIDs.
diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp
index c78f73f40fc6b..59f5a5d9da057 100644
--- a/src/hotspot/share/runtime/objectMonitor.hpp
+++ b/src/hotspot/share/runtime/objectMonitor.hpp
@@ -30,6 +30,7 @@
#include "oops/markWord.hpp"
#include "oops/weakHandle.hpp"
#include "runtime/perfDataTypes.hpp"
+#include "utilities/checkedCast.hpp"
class ObjectMonitor;
class ParkEvent;
diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp
index 965fd5603bade..c698a48ffb215 100644
--- a/src/hotspot/share/runtime/os.cpp
+++ b/src/hotspot/share/runtime/os.cpp
@@ -70,6 +70,7 @@
#include "services/nmtCommon.hpp"
#include "services/threadService.hpp"
#include "utilities/align.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/count_trailing_zeros.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/events.hpp"
@@ -942,6 +943,7 @@ ATTRIBUTE_NO_ASAN static bool read_safely_from(intptr_t* p, intptr_t* result) {
}
static void print_hex_location(outputStream* st, address p, int unitsize) {
+ assert(is_aligned(p, unitsize), "Unaligned");
address pa = align_down(p, sizeof(intptr_t));
#ifndef _LP64
// Special handling for printing qwords on 32-bit platforms
@@ -961,10 +963,14 @@ static void print_hex_location(outputStream* st, address p, int unitsize) {
#endif // 32-bit, qwords
intptr_t i = 0;
if (read_safely_from((intptr_t*)pa, &i)) {
+ // bytes: CA FE BA BE DE AD C0 DE
+ // bytoff: 0 1 2 3 4 5 6 7
+ // LE bits: 0 8 16 24 32 40 48 56
+ // BE bits: 56 48 40 32 24 16 8 0
const int offset = (int)(p - (address)pa);
const int bitoffset =
LITTLE_ENDIAN_ONLY(offset * BitsPerByte)
- BIG_ENDIAN_ONLY((int)(sizeof(intptr_t) - 1 - offset) * BitsPerByte);
+ BIG_ENDIAN_ONLY((int)((sizeof(intptr_t) - unitsize - offset) * BitsPerByte));
const int bitfieldsize = unitsize * BitsPerByte;
intptr_t value = bitfield(i, bitoffset, bitfieldsize);
switch (unitsize) {
diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp
index 1d704e29ac7ad..e13ce72e886b9 100644
--- a/src/hotspot/share/runtime/os.hpp
+++ b/src/hotspot/share/runtime/os.hpp
@@ -596,8 +596,7 @@ class os: AllStatic {
static bool start_debugging(char *buf, int buflen);
static address current_stack_pointer();
- static address current_stack_base();
- static size_t current_stack_size();
+ static void current_stack_base_and_size(address* base, size_t* size);
static void verify_stack_alignment() PRODUCT_RETURN;
@@ -772,7 +771,7 @@ class os: AllStatic {
static void print_context(outputStream* st, const void* context);
static void print_tos_pc(outputStream* st, const void* context);
static void print_tos(outputStream* st, address sp);
- static void print_instructions(outputStream* st, address pc, int unitsize);
+ static void print_instructions(outputStream* st, address pc, int unitsize = 1);
static void print_register_info(outputStream* st, const void* context, int& continuation);
static void print_register_info(outputStream* st, const void* context);
static bool signal_sent_by_kill(const void* siginfo);
@@ -886,10 +885,10 @@ class os: AllStatic {
// SocketInterface (ex HPI SocketInterface )
static int socket_close(int fd);
- static int recv(int fd, char* buf, size_t nBytes, uint flags);
- static int send(int fd, char* buf, size_t nBytes, uint flags);
- static int raw_send(int fd, char* buf, size_t nBytes, uint flags);
- static int connect(int fd, struct sockaddr* him, socklen_t len);
+ static ssize_t recv(int fd, char* buf, size_t nBytes, uint flags);
+ static ssize_t send(int fd, char* buf, size_t nBytes, uint flags);
+ static ssize_t raw_send(int fd, char* buf, size_t nBytes, uint flags);
+ static ssize_t connect(int fd, struct sockaddr* him, socklen_t len);
// Support for signals
static void initialize_jdk_signal_support(TRAPS);
diff --git a/src/hotspot/share/runtime/relocator.cpp b/src/hotspot/share/runtime/relocator.cpp
index da4da8a9e8d4a..5b5ff2b83e60f 100644
--- a/src/hotspot/share/runtime/relocator.cpp
+++ b/src/hotspot/share/runtime/relocator.cpp
@@ -31,6 +31,7 @@
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/relocator.hpp"
+#include "utilities/checkedCast.hpp"
#define MAX_METHOD_LENGTH 65535
diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp
index c65e12ad1f49e..9ab2b8cedd04d 100644
--- a/src/hotspot/share/runtime/sharedRuntime.cpp
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp
@@ -1872,7 +1872,8 @@ methodHandle SharedRuntime::reresolve_call_site(TRAPS) {
// nmethod could be deoptimized by the time we get here
// so no update to the caller is needed.
- if (caller.is_compiled_frame() && !caller.is_deoptimized_frame()) {
+ if ((caller.is_compiled_frame() && !caller.is_deoptimized_frame()) ||
+ (caller.is_native_frame() && ((CompiledMethod*)caller.cb())->method()->is_continuation_enter_intrinsic())) {
address pc = caller.pc();
diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp
index 1f6ad8d7cc288..1023ab8bac2ae 100644
--- a/src/hotspot/share/runtime/thread.cpp
+++ b/src/hotspot/share/runtime/thread.cpp
@@ -169,8 +169,11 @@ void Thread::record_stack_base_and_size() {
// any members being initialized. Do not rely on Thread::current() being set.
// If possible, refrain from doing anything which may crash or assert since
// quite probably those crash dumps will be useless.
- set_stack_base(os::current_stack_base());
- set_stack_size(os::current_stack_size());
+ address base;
+ size_t size;
+ os::current_stack_base_and_size(&base, &size);
+ set_stack_base(base);
+ set_stack_size(size);
// Set stack limits after thread is initialized.
if (is_Java_thread()) {
diff --git a/src/hotspot/share/runtime/threadHeapSampler.cpp b/src/hotspot/share/runtime/threadHeapSampler.cpp
index 03c845d6c2e10..4bdfedb31b0c8 100644
--- a/src/hotspot/share/runtime/threadHeapSampler.cpp
+++ b/src/hotspot/share/runtime/threadHeapSampler.cpp
@@ -31,6 +31,7 @@
#include "runtime/handles.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/threadHeapSampler.hpp"
+#include "utilities/checkedCast.hpp"
// Cheap random number generator.
uint64_t ThreadHeapSampler::_rnd;
diff --git a/src/hotspot/share/services/attachListener.cpp b/src/hotspot/share/services/attachListener.cpp
index a8f7256763a82..630ceb8e99861 100644
--- a/src/hotspot/share/services/attachListener.cpp
+++ b/src/hotspot/share/services/attachListener.cpp
@@ -319,13 +319,10 @@ static jint set_flag(AttachOperation* op, outputStream* out) {
int ret = WriteableFlags::set_flag(op->arg(0), op->arg(1), JVMFlagOrigin::ATTACH_ON_DEMAND, err_msg);
if (ret != JVMFlag::SUCCESS) {
if (ret == JVMFlag::NON_WRITABLE) {
- // if the flag is not manageable try to change it through
- // the platform dependent implementation
- return AttachListener::pd_set_flag(op, out);
+ out->print_cr("flag '%s' cannot be changed", op->arg(0));
} else {
out->print_cr("%s", err_msg.buffer());
}
-
return JNI_ERR;
}
return JNI_OK;
@@ -411,11 +408,6 @@ void AttachListenerThread::thread_entry(JavaThread* thread, TRAPS) {
}
}
- // check for platform dependent attach operation
- if (info == nullptr) {
- info = AttachListener::pd_find_operation(op->name());
- }
-
if (info != nullptr) {
// dispatch to the function that implements this operation
res = (info->func)(op, &st);
diff --git a/src/hotspot/share/services/attachListener.hpp b/src/hotspot/share/services/attachListener.hpp
index 5cf32cc51ffac..c49f996cdb438 100644
--- a/src/hotspot/share/services/attachListener.hpp
+++ b/src/hotspot/share/services/attachListener.hpp
@@ -121,12 +121,6 @@ class AttachListener: AllStatic {
// platform specific initialization
static int pd_init();
- // platform specific operation
- static AttachOperationFunctionInfo* pd_find_operation(const char* name);
-
- // platform specific flag change
- static jint pd_set_flag(AttachOperation* op, outputStream* out);
-
// platform specific detachall
static void pd_detachall();
diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp
index 2ef389d6a9507..8d346a5ea48c6 100644
--- a/src/hotspot/share/services/diagnosticCommand.cpp
+++ b/src/hotspot/share/services/diagnosticCommand.cpp
@@ -63,6 +63,7 @@
#include "utilities/events.hpp"
#include "utilities/formatBuffer.hpp"
#include "utilities/macros.hpp"
+#include "utilities/parseInteger.hpp"
#ifdef LINUX
#include "trimCHeapDCmd.hpp"
#include "mallocInfoDcmd.hpp"
@@ -878,11 +879,11 @@ EventLogDCmd::EventLogDCmd(outputStream* output, bool heap) :
void EventLogDCmd::execute(DCmdSource source, TRAPS) {
const char* max_value = _max.value();
- long max = -1;
+ int max = -1;
if (max_value != nullptr) {
char* endptr = nullptr;
- max = ::strtol(max_value, &endptr, 10);
- if (max == 0 && max_value == endptr) {
+ int max;
+ if (!parse_integer(max_value, &max)) {
output()->print_cr("Invalid max option: \"%s\".", max_value);
return;
}
diff --git a/src/hotspot/share/services/finalizerService.cpp b/src/hotspot/share/services/finalizerService.cpp
index 202a1af08011a..ecd9168cd65d3 100644
--- a/src/hotspot/share/services/finalizerService.cpp
+++ b/src/hotspot/share/services/finalizerService.cpp
@@ -137,11 +137,14 @@ class FinalizerEntryLookup : StackObj {
public:
FinalizerEntryLookup(const InstanceKlass* ik) : _ik(ik) {}
uintx get_hash() const { return hash_function(_ik); }
- bool equals(FinalizerEntry** value, bool* is_dead) {
+ bool equals(FinalizerEntry** value) {
assert(value != nullptr, "invariant");
assert(*value != nullptr, "invariant");
return (*value)->klass() == _ik;
}
+ bool is_dead(FinalizerEntry** value) {
+ return false;
+ }
};
class FinalizerTableConfig : public AllStatic {
diff --git a/src/hotspot/share/services/heapDumper.cpp b/src/hotspot/share/services/heapDumper.cpp
index 2a3650f850a69..23e83939bd35f 100644
--- a/src/hotspot/share/services/heapDumper.cpp
+++ b/src/hotspot/share/services/heapDumper.cpp
@@ -59,6 +59,7 @@
#include "services/heapDumper.hpp"
#include "services/heapDumperCompression.hpp"
#include "services/threadService.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
@@ -967,7 +968,7 @@ u4 DumperSupport::get_static_fields_size(InstanceKlass* ik, u2& field_count) {
}
// We write the value itself plus a name and a one byte type tag per field.
- return size + field_count * (sizeof(address) + 1);
+ return checked_cast(size + field_count * (sizeof(address) + 1));
}
// dumps static fields of the given class
@@ -1080,7 +1081,7 @@ void DumperSupport::dump_instance_class(AbstractDumpWriter* writer, Klass* k) {
u4 static_size = get_static_fields_size(ik, static_fields_count);
u2 instance_fields_count = get_instance_fields_count(ik);
u4 instance_fields_size = instance_fields_count * (sizeof(address) + 1);
- u4 size = 1 + sizeof(address) + 4 + 6 * sizeof(address) + 4 + 2 + 2 + static_size + 2 + instance_fields_size;
+ u4 size = checked_cast(1 + sizeof(address) + 4 + 6 * sizeof(address) + 4 + 2 + 2 + static_size + 2 + instance_fields_size);
writer->start_sub_record(HPROF_GC_CLASS_DUMP, size);
@@ -1190,7 +1191,7 @@ void DumperSupport::dump_object_array(AbstractDumpWriter* writer, objArrayOop ar
// sizeof(u1) + 2 * sizeof(u4) + sizeof(objectID) + sizeof(classID)
short header_size = 1 + 2 * 4 + 2 * sizeof(address);
int length = calculate_array_max_length(writer, array, header_size);
- u4 size = header_size + length * sizeof(address);
+ u4 size = checked_cast(header_size + length * sizeof(address));
writer->start_sub_record(HPROF_GC_OBJ_ARRAY_DUMP, size);
writer->write_objectID(array);
@@ -2153,7 +2154,7 @@ void VM_HeapDumper::dump_stack_traces() {
depth += extra_frames;
// write HPROF_TRACE record for one thread
- DumperSupport::write_header(writer(), HPROF_TRACE, 3*sizeof(u4) + depth*oopSize);
+ DumperSupport::write_header(writer(), HPROF_TRACE, checked_cast(3*sizeof(u4) + depth*oopSize));
int stack_serial_num = _num_threads + STACK_TRACE_ID;
writer()->write_u4(stack_serial_num); // stack trace serial number
writer()->write_u4((u4) _num_threads); // thread serial number
diff --git a/src/hotspot/share/services/mallocSiteTable.cpp b/src/hotspot/share/services/mallocSiteTable.cpp
index 29eac09b77ede..2780e86d8924e 100644
--- a/src/hotspot/share/services/mallocSiteTable.cpp
+++ b/src/hotspot/share/services/mallocSiteTable.cpp
@@ -229,7 +229,7 @@ void MallocSiteTable::print_tuning_statistics(outputStream* st) {
st->print_cr("Malloc allocation site table:");
st->print_cr("\tTotal entries: %d", total_entries);
st->print_cr("\tEmpty entries (no outstanding mallocs): %d (%2.2f%%)",
- empty_entries, ((float)empty_entries * 100) / total_entries);
+ empty_entries, ((float)empty_entries * 100) / (float)total_entries);
st->cr();
qsort(lengths, table_size, sizeof(uint16_t), qsort_helper);
diff --git a/src/hotspot/share/services/memReporter.cpp b/src/hotspot/share/services/memReporter.cpp
index 4c2a5b898dcbe..e1fb2b7a32f20 100644
--- a/src/hotspot/share/services/memReporter.cpp
+++ b/src/hotspot/share/services/memReporter.cpp
@@ -226,7 +226,7 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag,
const VirtualMemory* thread_stack_usage =
_vm_snapshot->by_type(mtThreadStack);
// report thread count
- out->print_cr("%27s (thread #" SIZE_FORMAT ")", " ", ThreadStackTracker::thread_count());
+ out->print_cr("%27s (threads #" SIZE_FORMAT ")", " ", ThreadStackTracker::thread_count());
out->print("%27s (stack: ", " ");
print_total(thread_stack_usage->reserved(), thread_stack_usage->committed());
} else {
@@ -234,7 +234,7 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag,
const char* scale = current_scale();
// report thread count
assert(ThreadStackTracker::thread_count() == 0, "Not used");
- out->print_cr("%27s (thread #" SIZE_FORMAT ")", " ", thread_stack_memory->malloc_count());
+ out->print_cr("%27s (threads #" SIZE_FORMAT ")", " ", thread_stack_memory->malloc_count());
out->print("%27s (Stack: " SIZE_FORMAT "%s", " ",
amount_in_current_scale(thread_stack_memory->malloc_size()), scale);
}
@@ -282,7 +282,7 @@ void MemSummaryReporter::report_metadata(Metaspace::MetadataType type) const {
const MetaspaceStats stats = MetaspaceUtils::get_statistics(type);
size_t waste = stats.committed() - stats.used();
- float waste_percentage = stats.committed() > 0 ? (((float)waste * 100)/stats.committed()) : 0.0f;
+ float waste_percentage = stats.committed() > 0 ? (((float)waste * 100)/(float)stats.committed()) : 0.0f;
out->print_cr("%27s ( %s)", " ", name);
out->print("%27s ( ", " ");
@@ -595,7 +595,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag,
} else if (flag == mtThread) {
// report thread count
- out->print("%27s (thread #" SIZE_FORMAT "", " ", _current_baseline.thread_count());
+ out->print("%27s (threads #" SIZE_FORMAT "", " ", _current_baseline.thread_count());
const ssize_t thread_count_diff = counter_diff(_current_baseline.thread_count(), _early_baseline.thread_count());
if (thread_count_diff != 0) {
out->print(" " SSIZE_PLUS_FORMAT, thread_count_diff);
@@ -713,7 +713,7 @@ void MemSummaryDiffReporter::print_metaspace_diff(const char* header,
// Diff waste
const float waste_percentage = current_stats.committed() == 0 ? 0.0f :
- (current_waste * 100.0f) / current_stats.committed();
+ ((float)current_waste * 100.0f) / (float)current_stats.committed();
out->print("%27s ( waste=" SIZE_FORMAT "%s =%2.2f%%", " ",
amount_in_current_scale(current_waste), scale, waste_percentage);
if (diff_waste != 0) {
diff --git a/src/hotspot/share/services/nmtPreInit.hpp b/src/hotspot/share/services/nmtPreInit.hpp
index c6c504e99cda0..7705c5180d38c 100644
--- a/src/hotspot/share/services/nmtPreInit.hpp
+++ b/src/hotspot/share/services/nmtPreInit.hpp
@@ -31,6 +31,7 @@
#include "runtime/atomic.hpp"
#endif
#include "services/memTracker.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
@@ -162,7 +163,7 @@ class NMTPreInitAllocationTable {
static index_t index_for_key(const void* p) {
const uint64_t hash = calculate_hash(p);
// "table_size" is a Mersenne prime, so "modulo" is all we need here.
- return hash % table_size;
+ return checked_cast(hash % table_size);
}
const NMTPreInitAllocation* const * find_entry(const void* p) const {
diff --git a/src/hotspot/share/services/threadIdTable.cpp b/src/hotspot/share/services/threadIdTable.cpp
index ba0e6bdd4fdba..0a9c123397174 100644
--- a/src/hotspot/share/services/threadIdTable.cpp
+++ b/src/hotspot/share/services/threadIdTable.cpp
@@ -1,6 +1,6 @@
/*
-* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -131,7 +131,7 @@ void ThreadIdTable::item_removed() {
}
double ThreadIdTable::get_load_factor() {
- return ((double)_items_count) / _current_size;
+ return ((double)_items_count) / (double)_current_size;
}
size_t ThreadIdTable::table_size() {
@@ -187,13 +187,16 @@ class ThreadIdTableLookup : public StackObj {
uintx get_hash() const {
return _hash;
}
- bool equals(ThreadIdTableEntry** value, bool* is_dead) {
+ bool equals(ThreadIdTableEntry** value) {
bool equals = primitive_equals(_tid, (*value)->tid());
if (!equals) {
return false;
}
return true;
}
+ bool is_dead(ThreadIdTableEntry** value) {
+ return false;
+ }
};
class ThreadGet : public StackObj {
diff --git a/src/hotspot/share/services/threadService.hpp b/src/hotspot/share/services/threadService.hpp
index ce0ab3c50279c..484741ad9350b 100644
--- a/src/hotspot/share/services/threadService.hpp
+++ b/src/hotspot/share/services/threadService.hpp
@@ -103,8 +103,8 @@ class ThreadService : public AllStatic {
static jlong get_total_thread_count() { return _total_threads_count->get_value(); }
static jlong get_peak_thread_count() { return _peak_threads_count->get_value(); }
- static jlong get_live_thread_count() { return _atomic_threads_count; }
- static jlong get_daemon_thread_count() { return _atomic_daemon_threads_count; }
+ static int get_live_thread_count() { return _atomic_threads_count; }
+ static int get_daemon_thread_count() { return _atomic_daemon_threads_count; }
static jlong exited_allocated_bytes() { return Atomic::load(&_exited_allocated_bytes); }
static void incr_exited_allocated_bytes(jlong size) {
diff --git a/src/hotspot/share/services/threadStackTracker.cpp b/src/hotspot/share/services/threadStackTracker.cpp
index afed620bb8890..14616e1046990 100644
--- a/src/hotspot/share/services/threadStackTracker.cpp
+++ b/src/hotspot/share/services/threadStackTracker.cpp
@@ -43,7 +43,7 @@ bool ThreadStackTracker::initialize(NMT_TrackingLevel level) {
}
int ThreadStackTracker::compare_thread_stack_base(const SimpleThreadStackSite& s1, const SimpleThreadStackSite& s2) {
- return s1.base() - s2.base();
+ return primitive_compare(s1.base(), s2.base());
}
void ThreadStackTracker::new_thread_stack(void* base, size_t size, const NativeCallStack& stack) {
diff --git a/src/hotspot/share/services/virtualMemoryTracker.hpp b/src/hotspot/share/services/virtualMemoryTracker.hpp
index de1a72f65aab7..af9f8bdbfc059 100644
--- a/src/hotspot/share/services/virtualMemoryTracker.hpp
+++ b/src/hotspot/share/services/virtualMemoryTracker.hpp
@@ -333,6 +333,7 @@ class ReservedMemoryRegion : public VirtualMemoryRegion {
_stack = *other.call_stack();
_flag = other.flag();
+ _committed_regions.clear();
CommittedRegionIterator itr = other.iterate_committed_regions();
const CommittedMemoryRegion* rgn = itr.next();
diff --git a/src/hotspot/share/utilities/align.hpp b/src/hotspot/share/utilities/align.hpp
index 1414d91a19d8a..4640f05e4d079 100644
--- a/src/hotspot/share/utilities/align.hpp
+++ b/src/hotspot/share/utilities/align.hpp
@@ -26,6 +26,7 @@
#define SHARE_UTILITIES_ALIGN_HPP
#include "metaprogramming/enableIf.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/powerOfTwo.hpp"
diff --git a/src/hotspot/share/utilities/checkedCast.hpp b/src/hotspot/share/utilities/checkedCast.hpp
new file mode 100644
index 0000000000000..290028f99e3a8
--- /dev/null
+++ b/src/hotspot/share/utilities/checkedCast.hpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_UTILITIES_CHECKEDCAST_HPP
+#define SHARE_UTILITIES_CHECKEDCAST_HPP
+
+#include "utilities/debug.hpp"
+
+// In many places we've added C-style casts to silence compiler
+// warnings, for example when truncating a size_t to an int when we
+// know the size_t is a small struct. Such casts are risky because
+// they effectively disable useful compiler warnings. We can make our
+// lives safer with this function, which ensures that any cast is
+// reversible without loss of information. It doesn't check
+// everything: it isn't intended to make sure that pointer types are
+// compatible, for example.
+template
+constexpr T2 checked_cast(T1 thing) {
+ T2 result = static_cast(thing);
+ assert(static_cast(result) == thing, "must be");
+ return result;
+}
+
+#endif // SHARE_UTILITIES_CHECKEDCAST_HPP
+
diff --git a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp
index 0d62a9f162e29..b222d379b722b 100644
--- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp
+++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp
@@ -455,9 +455,8 @@ inline bool ConcurrentHashTable::
assert(bucket->is_locked(), "Must be locked.");
Node* const volatile * rem_n_prev = bucket->first_ptr();
Node* rem_n = bucket->first();
- bool have_dead = false;
while (rem_n != nullptr) {
- if (lookup_f.equals(rem_n->value(), &have_dead)) {
+ if (lookup_f.equals(rem_n->value())) {
bucket->release_assign_node_ptr(rem_n_prev, rem_n->next());
break;
} else {
@@ -546,9 +545,7 @@ inline void ConcurrentHashTable::
Node* const volatile * rem_n_prev = bucket->first_ptr();
Node* rem_n = bucket->first();
while (rem_n != nullptr) {
- bool is_dead = false;
- lookup_f.equals(rem_n->value(), &is_dead);
- if (is_dead) {
+ if (lookup_f.is_dead(rem_n->value())) {
ndel[dels++] = rem_n;
Node* next_node = rem_n->next();
bucket->release_assign_node_ptr(rem_n_prev, next_node);
@@ -626,12 +623,11 @@ ConcurrentHashTable::
size_t loop_count = 0;
Node* node = bucket->first();
while (node != nullptr) {
- bool is_dead = false;
++loop_count;
- if (lookup_f.equals(node->value(), &is_dead)) {
+ if (lookup_f.equals(node->value())) {
break;
}
- if (is_dead && !(*have_dead)) {
+ if (!(*have_dead) && lookup_f.is_dead(node->value())) {
*have_dead = true;
}
node = node->next();
diff --git a/src/hotspot/share/utilities/copy.cpp b/src/hotspot/share/utilities/copy.cpp
index ef9840af6d4b3..9ead75f2ceb90 100644
--- a/src/hotspot/share/utilities/copy.cpp
+++ b/src/hotspot/share/utilities/copy.cpp
@@ -236,7 +236,7 @@ void Copy::fill_to_memory_atomic(void* to, size_t size, jubyte value) {
}
} else if (bits % sizeof(jshort) == 0) {
jshort fill = (jushort)( (jubyte)value ); // zero-extend
- fill += fill << 8;
+ fill += (jshort)(fill << 8);
//Copy::fill_to_jshorts_atomic((jshort*) dst, size / sizeof(jshort));
for (uintptr_t off = 0; off < size; off += sizeof(jshort)) {
*(jshort*)(dst + off) = fill;
diff --git a/src/hotspot/share/utilities/copy.hpp b/src/hotspot/share/utilities/copy.hpp
index c16a62729b188..3c2756169ae3c 100644
--- a/src/hotspot/share/utilities/copy.hpp
+++ b/src/hotspot/share/utilities/copy.hpp
@@ -41,7 +41,6 @@ extern "C" {
void _Copy_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count);
void _Copy_conjoint_jints_atomic (const jint* from, jint* to, size_t count);
void _Copy_conjoint_jlongs_atomic (const jlong* from, jlong* to, size_t count);
- void _Copy_conjoint_oops_atomic (const oop* from, oop* to, size_t count);
void _Copy_arrayof_conjoint_bytes (const HeapWord* from, HeapWord* to, size_t count);
void _Copy_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count);
diff --git a/src/hotspot/share/utilities/elfFile.cpp b/src/hotspot/share/utilities/elfFile.cpp
index 2e26feec9a643..b10d338a5fef4 100644
--- a/src/hotspot/share/utilities/elfFile.cpp
+++ b/src/hotspot/share/utilities/elfFile.cpp
@@ -29,6 +29,7 @@
#include "jvm_io.h"
#include "logging/log.hpp"
#include "memory/allocation.inline.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/decoder.hpp"
#include "utilities/elfFile.hpp"
#include "utilities/elfFuncDescTable.hpp"
@@ -789,7 +790,7 @@ bool DwarfFile::DebugAranges::read_set_header(DebugArangesSetHeader& header) {
// We must align to twice the address size.
uint8_t alignment = DwarfFile::ADDRESS_SIZE * 2;
- uint8_t padding = alignment - (_reader.get_position() - _section_start_address) % alignment;
+ long padding = alignment - (_reader.get_position() - _section_start_address) % alignment;
return _reader.move_position(padding);
}
@@ -1423,7 +1424,7 @@ bool DwarfFile::LineNumberProgram::apply_extended_opcode() {
// Must be an unsigned integer as specified in section 6.2.2 of the DWARF 4 spec for the discriminator register.
return false;
}
- _state->_discriminator = discriminator;
+ _state->_discriminator = static_cast(discriminator);
break;
default:
assert(false, "Unknown extended opcode");
@@ -1446,11 +1447,12 @@ bool DwarfFile::LineNumberProgram::apply_standard_opcode(const uint8_t opcode) {
}
break;
case DW_LNS_advance_pc: { // 1 operand
- uint64_t operation_advance;
- if (!_reader.read_uleb128(&operation_advance, 4)) {
+ uint64_t adv;
+ if (!_reader.read_uleb128(&adv, 4)) {
// Must be at most 4 bytes because the index register is only 4 bytes wide.
return false;
}
+ uint32_t operation_advance = checked_cast(adv);
_state->add_to_address_register(operation_advance, _header);
if (_state->_dwarf_version == 4) {
_state->set_index_register(operation_advance, _header);
@@ -1464,7 +1466,7 @@ bool DwarfFile::LineNumberProgram::apply_standard_opcode(const uint8_t opcode) {
// line register is 4 bytes wide.
return false;
}
- _state->_line += line;
+ _state->_line += static_cast(line);
DWARF_LOG_TRACE(" DW_LNS_advance_line (%d)", _state->_line);
break;
case DW_LNS_set_file: // 1 operand
@@ -1473,7 +1475,7 @@ bool DwarfFile::LineNumberProgram::apply_standard_opcode(const uint8_t opcode) {
// file register is 4 bytes wide.
return false;
}
- _state->_file = file;
+ _state->_file = static_cast(file);
DWARF_LOG_TRACE(" DW_LNS_set_file (%u)", _state->_file);
break;
case DW_LNS_set_column: // 1 operand
@@ -1482,7 +1484,7 @@ bool DwarfFile::LineNumberProgram::apply_standard_opcode(const uint8_t opcode) {
// column register is 4 bytes wide.
return false;
}
- _state->_column = column;
+ _state->_column = static_cast(column);
DWARF_LOG_TRACE(" DW_LNS_set_column (%u)", _state->_column);
break;
case DW_LNS_negate_stmt: // No operands
@@ -1528,7 +1530,7 @@ bool DwarfFile::LineNumberProgram::apply_standard_opcode(const uint8_t opcode) {
// isa register is 4 bytes wide.
return false;
}
- _state->_isa = isa;
+ _state->_isa = static_cast(isa); // only save 4 bytes
DWARF_LOG_TRACE(" DW_LNS_set_isa (%u)", _state->_isa);
break;
default:
diff --git a/src/hotspot/share/utilities/elfFile.hpp b/src/hotspot/share/utilities/elfFile.hpp
index 1b572fca400dc..0caafc7645eb6 100644
--- a/src/hotspot/share/utilities/elfFile.hpp
+++ b/src/hotspot/share/utilities/elfFile.hpp
@@ -70,6 +70,7 @@ typedef Elf32_Sym Elf_Sym;
#include "jvm_md.h"
#include "globalDefinitions.hpp"
#include "memory/allocation.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/decoder.hpp"
#ifdef ASSERT
@@ -483,7 +484,7 @@ class DwarfFile : public ElfFile {
DwarfFile* _dwarf_file;
MarkedDwarfFileReader _reader;
- uint32_t _section_start_address;
+ uintptr_t _section_start_address;
// a calculated end position
long _entry_end;
diff --git a/src/hotspot/share/utilities/elfFuncDescTable.cpp b/src/hotspot/share/utilities/elfFuncDescTable.cpp
index 28ffd754b14e1..bd9beb202c6ee 100644
--- a/src/hotspot/share/utilities/elfFuncDescTable.cpp
+++ b/src/hotspot/share/utilities/elfFuncDescTable.cpp
@@ -46,7 +46,7 @@ ElfFuncDescTable::ElfFuncDescTable(FILE* file, Elf_Shdr shdr, int index) :
ElfFuncDescTable::~ElfFuncDescTable() {
}
-address ElfFuncDescTable::lookup(Elf_Word index) {
+address ElfFuncDescTable::lookup(Elf_Addr index) {
if (NullDecoder::is_error(_status)) {
return nullptr;
}
diff --git a/src/hotspot/share/utilities/elfFuncDescTable.hpp b/src/hotspot/share/utilities/elfFuncDescTable.hpp
index dbfd2a9ee4e26..a0e6761155425 100644
--- a/src/hotspot/share/utilities/elfFuncDescTable.hpp
+++ b/src/hotspot/share/utilities/elfFuncDescTable.hpp
@@ -133,7 +133,7 @@ class ElfFuncDescTable: public CHeapObj {
~ElfFuncDescTable();
// return the function address for the function descriptor at 'index' or null on error
- address lookup(Elf_Word index);
+ address lookup(Elf_Addr index);
int get_index() const { return _index; };
diff --git a/src/hotspot/share/utilities/elfSymbolTable.cpp b/src/hotspot/share/utilities/elfSymbolTable.cpp
index 868457418ebfc..9c6d90d3e8ce7 100644
--- a/src/hotspot/share/utilities/elfSymbolTable.cpp
+++ b/src/hotspot/share/utilities/elfSymbolTable.cpp
@@ -27,6 +27,7 @@
#if !defined(_WINDOWS) && !defined(__APPLE__)
#include "memory/allocation.inline.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/elfFuncDescTable.hpp"
#include "utilities/elfSymbolTable.hpp"
@@ -48,7 +49,7 @@ ElfSymbolTable::~ElfSymbolTable() {
bool ElfSymbolTable::compare(const Elf_Sym* sym, address addr, int* stringtableIndex, int* posIndex, int* offset, ElfFuncDescTable* funcDescTable) {
if (STT_FUNC == ELF_ST_TYPE(sym->st_info)) {
- Elf_Word st_size = sym->st_size;
+ Elf64_Xword st_size = sym->st_size;
const Elf_Shdr* shdr = _section.section_header();
address sym_addr;
if (funcDescTable != nullptr && funcDescTable->get_index() == sym->st_shndx) {
@@ -77,7 +78,7 @@ bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex,
}
size_t sym_size = sizeof(Elf_Sym);
- int count = _section.section_header()->sh_size / sym_size;
+ int count = checked_cast(_section.section_header()->sh_size / sym_size);
Elf_Sym* symbols = (Elf_Sym*)_section.section_data();
if (symbols != nullptr) {
diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp
index a374b9cdc932b..719992de62c6b 100644
--- a/src/hotspot/share/utilities/globalDefinitions.hpp
+++ b/src/hotspot/share/utilities/globalDefinitions.hpp
@@ -50,7 +50,7 @@ class oopDesc;
#endif
#ifndef ATTRIBUTE_ALIGNED
-#define ATTRIBUTE_ALIGNED(x)
+#define ATTRIBUTE_ALIGNED(x) alignas(x)
#endif
#ifndef ATTRIBUTE_FLATTEN
@@ -475,6 +475,16 @@ inline size_t pointer_delta(const MetaWord* left, const MetaWord* right) {
return pointer_delta(left, right, sizeof(MetaWord));
}
+// pointer_delta_as_int is called to do pointer subtraction for nearby pointers that
+// returns a non-negative int, usually used as a size of a code buffer range.
+// This scales to sizeof(T).
+template
+inline int pointer_delta_as_int(const volatile T* left, const volatile T* right) {
+ size_t delta = pointer_delta(left, right, sizeof(T));
+ assert(delta <= size_t(INT_MAX), "pointer delta out of range: %zu", delta);
+ return static_cast(delta);
+}
+
//
// ANSI C++ does not allow casting from one pointer type to a function pointer
// directly without at best a warning. This macro accomplishes it silently
@@ -491,29 +501,6 @@ inline size_t pointer_delta(const MetaWord* left, const MetaWord* right) {
#define CAST_TO_FN_PTR(func_type, value) (reinterpret_cast(value))
#define CAST_FROM_FN_PTR(new_type, func_ptr) ((new_type)((uintptr_t)(func_ptr)))
-// In many places we've added C-style casts to silence compiler
-// warnings, for example when truncating a size_t to an int when we
-// know the size_t is a small struct. Such casts are risky because
-// they effectively disable useful compiler warnings. We can make our
-// lives safer with this function, which ensures that any cast is
-// reversible without loss of information. It doesn't check
-// everything: it isn't intended to make sure that pointer types are
-// compatible, for example.
-template
-constexpr T2 checked_cast(T1 thing) {
- T2 result = static_cast(thing);
- assert(static_cast(result) == thing, "must be");
- return result;
-}
-
-// pointer_delta_as_int is called to do pointer subtraction for nearby pointers that
-// returns a non-negative int, usually used as a size of a code buffer range.
-// This scales to sizeof(T).
-template
-inline int pointer_delta_as_int(const volatile T* left, const volatile T* right) {
- return checked_cast(pointer_delta(left, right, sizeof(T)));
-}
-
// Need the correct linkage to call qsort without warnings
extern "C" {
typedef int (*_sort_Fn)(const void *, const void *);
diff --git a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp
index 0d7b1164a6d6a..7ea877062d8b3 100644
--- a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp
+++ b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp
@@ -141,7 +141,7 @@ inline int g_isfinite(jdouble f) { return isfinite(f); }
// temporarily disabled.
#define offset_of(klass,field) \
([]() { \
- char space[sizeof (klass)] ATTRIBUTE_ALIGNED(16); \
+ alignas(16) char space[sizeof (klass)]; \
klass* dummyObj = (klass*)space; \
char* c = (char*)(void*)&dummyObj->field; \
return (size_t)(c - space); \
@@ -160,8 +160,4 @@ inline int g_isfinite(jdouble f) { return isfinite(f); }
#define ALWAYSINLINE inline __attribute__ ((always_inline))
#define ATTRIBUTE_FLATTEN __attribute__ ((flatten))
-// Alignment
-//
-#define ATTRIBUTE_ALIGNED(x) __attribute__((aligned(x)))
-
#endif // SHARE_UTILITIES_GLOBALDEFINITIONS_GCC_HPP
diff --git a/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp b/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp
index 25f3ec8cbafa8..3b28328d7dd40 100644
--- a/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp
+++ b/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp
@@ -115,9 +115,6 @@ inline int g_isfinite(jdouble f) { return _finite(f); }
#define NOINLINE __declspec(noinline)
#define ALWAYSINLINE __forceinline
-// Alignment
-#define ATTRIBUTE_ALIGNED(x) __declspec(align(x))
-
#ifdef _M_ARM64
#define USE_VECTORED_EXCEPTION_HANDLING
#endif
diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp
index 1dd413e63aa7f..4f641e54ecd0d 100644
--- a/src/hotspot/share/utilities/ostream.cpp
+++ b/src/hotspot/share/utilities/ostream.cpp
@@ -1096,15 +1096,15 @@ networkStream::networkStream() : bufferedStream(1024*10, 1024*10) {
}
}
-int networkStream::read(char *buf, size_t len) {
- return os::recv(_socket, buf, (int)len, 0);
+ssize_t networkStream::read(char *buf, size_t len) {
+ return os::recv(_socket, buf, len, 0);
}
void networkStream::flush() {
if (size() != 0) {
- int result = os::raw_send(_socket, (char *)base(), size(), 0);
+ ssize_t result = os::raw_send(_socket, (char *)base(), size(), 0);
assert(result != -1, "connection error");
- assert(result == (int)size(), "didn't send enough data");
+ assert(result >= 0 && (size_t)result == size(), "didn't send enough data");
}
reset();
}
@@ -1143,9 +1143,9 @@ bool networkStream::connect(const char *host, short port) {
return false;
}
- ret = os::connect(_socket, addr_info->ai_addr, (socklen_t)addr_info->ai_addrlen);
+ ssize_t conn = os::connect(_socket, addr_info->ai_addr, (socklen_t)addr_info->ai_addrlen);
freeaddrinfo(addr_info);
- return (ret >= 0);
+ return (conn >= 0);
}
#endif
diff --git a/src/hotspot/share/utilities/ostream.hpp b/src/hotspot/share/utilities/ostream.hpp
index 1b2a041a6baa4..fd0bb3a3db54a 100644
--- a/src/hotspot/share/utilities/ostream.hpp
+++ b/src/hotspot/share/utilities/ostream.hpp
@@ -321,7 +321,7 @@ class networkStream : public bufferedStream {
bool connect(const char *host, short port);
bool is_open() const { return _socket != -1; }
- int read(char *buf, size_t len);
+ ssize_t read(char *buf, size_t len);
void close();
virtual void flush();
};
diff --git a/src/hotspot/share/utilities/population_count.hpp b/src/hotspot/share/utilities/population_count.hpp
index df4dc335215d7..97c5ce2a3684e 100644
--- a/src/hotspot/share/utilities/population_count.hpp
+++ b/src/hotspot/share/utilities/population_count.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
#define SHARE_UTILITIES_POPULATION_COUNT_HPP
#include "metaprogramming/enableIf.hpp"
+#include "utilities/checkedCast.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
@@ -64,7 +65,7 @@ inline unsigned population_count(T x) {
// The preceding multiply by z_ones is the only place where the intermediate
// calculations can exceed the range of T. We need to discard any such excess
// before the right-shift, hence the conversion back to T.
- return static_cast(r) >> (((sizeof(T) - 1) * BitsPerByte));
+ return checked_cast(static_cast(r) >> (((sizeof(T) - 1) * BitsPerByte)));
}
#endif // SHARE_UTILITIES_POPULATION_COUNT_HPP
diff --git a/src/hotspot/share/utilities/tableStatistics.cpp b/src/hotspot/share/utilities/tableStatistics.cpp
index 32692d2b45a1a..9d207dc74ac4a 100644
--- a/src/hotspot/share/utilities/tableStatistics.cpp
+++ b/src/hotspot/share/utilities/tableStatistics.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -74,11 +74,11 @@ void TableRateStatistics::stamp() {
}
float TableRateStatistics::get_add_rate() {
- return (float)((_added_items_stamp - _added_items_stamp_prev) / _seconds_stamp);
+ return (float)(((double)_added_items_stamp - (double)_added_items_stamp_prev) / _seconds_stamp);
}
float TableRateStatistics::get_remove_rate() {
- return (float)((_removed_items_stamp - _removed_items_stamp_prev) / _seconds_stamp);
+ return (float)(_removed_items_stamp - _removed_items_stamp_prev) / (float)_seconds_stamp;
}
TableStatistics::TableStatistics() :
@@ -101,12 +101,12 @@ TableStatistics::TableStatistics(NumberSeq summary, size_t literal_bytes, size_t
_add_rate(0), _remove_rate(0) {
_number_of_buckets = summary.num();
- _number_of_entries = summary.sum();
+ _number_of_entries = (size_t)summary.sum();
- _maximum_bucket_size = summary.maximum();
- _average_bucket_size = summary.avg();
- _variance_of_bucket_size = summary.variance();
- _stddev_of_bucket_size = summary.sd();
+ _maximum_bucket_size = (size_t)summary.maximum();
+ _average_bucket_size = (float)summary.avg();
+ _variance_of_bucket_size = (float)summary.variance();
+ _stddev_of_bucket_size = (float)summary.sd();
_bucket_bytes = _number_of_buckets * bucket_bytes;
_entry_bytes = _number_of_entries * node_bytes;
@@ -140,7 +140,7 @@ void TableStatistics::print(outputStream* st, const char *table_name) {
" bytes, each " SIZE_FORMAT,
_number_of_entries, _entry_bytes, _entry_size);
if (_literal_bytes != 0) {
- float literal_avg = (_number_of_entries <= 0) ? 0 : (_literal_bytes / _number_of_entries);
+ float literal_avg = (_number_of_entries <= 0) ? 0.0f : (float)(_literal_bytes / _number_of_entries);
st->print_cr("Number of literals : %9" PRIuPTR " = %9" PRIuPTR
" bytes, avg %7.3f",
_number_of_entries, _literal_bytes, literal_avg);
diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp
index 0e2a15a71da25..e9b4fcb2434fd 100644
--- a/src/hotspot/share/utilities/vmError.cpp
+++ b/src/hotspot/share/utilities/vmError.cpp
@@ -178,7 +178,10 @@ static void print_bug_submit_message(outputStream *out, Thread *thread) {
}
static bool stack_has_headroom(size_t headroom) {
- const size_t stack_size = os::current_stack_size();
+ size_t stack_size = 0;
+ address stack_base = nullptr;
+ os::current_stack_base_and_size(&stack_base, &stack_size);
+
const size_t guard_size = StackOverflow::stack_guard_zone_size();
const size_t unguarded_stack_size = stack_size - guard_size;
@@ -186,7 +189,6 @@ static bool stack_has_headroom(size_t headroom) {
return false;
}
- const address stack_base = os::current_stack_base();
const address unguarded_stack_end = stack_base - unguarded_stack_size;
const address stack_pointer = os::current_stack_pointer();
@@ -199,9 +201,11 @@ PRAGMA_INFINITE_RECURSION_IGNORED
void VMError::reattempt_test_hit_stack_limit(outputStream* st) {
if (stack_has_headroom(_reattempt_required_stack_headroom)) {
// Use all but (_reattempt_required_stack_headroom - K) unguarded stack space.
- const size_t stack_size = os::current_stack_size();
+ size_t stack_size = 0;
+ address stack_base = nullptr;
+ os::current_stack_base_and_size(&stack_base, &stack_size);
+
const size_t guard_size = StackOverflow::stack_guard_zone_size();
- const address stack_base = os::current_stack_base();
const address stack_pointer = os::current_stack_pointer();
const size_t unguarded_stack_size = stack_size - guard_size;
@@ -450,7 +454,7 @@ void VMError::print_native_stack(outputStream* st, frame fr, Thread* t, bool pri
// see if it's a valid frame
if (fr.pc()) {
st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)");
- const int limit = max_frames == -1 ? StackPrintLimit : MIN2(max_frames, (int)StackPrintLimit);
+ const int limit = max_frames == -1 ? StackPrintLimit : MIN2(max_frames, StackPrintLimit);
int count = 0;
while (count++ < limit) {
fr.print_on_error(st, buf, buf_size);
@@ -975,8 +979,7 @@ void VMError::report(outputStream* st, bool _verbose) {
stack_top = _thread->stack_base();
stack_size = _thread->stack_size();
} else {
- stack_top = os::current_stack_base();
- stack_size = os::current_stack_size();
+ os::current_stack_base_and_size(&stack_top, &stack_size);
}
address stack_bottom = stack_top - stack_size;
diff --git a/src/hotspot/share/utilities/xmlstream.cpp b/src/hotspot/share/utilities/xmlstream.cpp
index 081b53f9fa139..82cd6beb43a5d 100644
--- a/src/hotspot/share/utilities/xmlstream.cpp
+++ b/src/hotspot/share/utilities/xmlstream.cpp
@@ -160,7 +160,7 @@ void xmlStream::see_tag(const char* tag, bool push) {
char* old_low = _element_close_stack_low;
char* push_ptr = old_ptr - (tag_len+1);
if (push_ptr < old_low) {
- int old_len = _element_close_stack_high - old_ptr;
+ int old_len = pointer_delta_as_int(_element_close_stack_high, old_ptr);
int new_len = old_len * 2;
if (new_len < 100) new_len = 100;
char* new_low = NEW_C_HEAP_ARRAY(char, new_len, mtInternal);
diff --git a/src/java.base/aix/native/libnio/MappedMemoryUtils.c b/src/java.base/aix/native/libnio/MappedMemoryUtils.c
new file mode 100644
index 0000000000000..51763e89082f3
--- /dev/null
+++ b/src/java.base/aix/native/libnio/MappedMemoryUtils.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+#include "java_nio_MappedMemoryUtils.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+typedef char mincore_vec_t;
+
+static long calculate_number_of_pages_in_range(void* address, size_t len, size_t pagesize) {
+ uintptr_t address_unaligned = (uintptr_t) address;
+ uintptr_t address_aligned = address_unaligned & (~(pagesize - 1));
+ size_t len2 = len + (address_unaligned - address_aligned);
+ long numPages = (len2 + pagesize - 1) / pagesize;
+ return numPages;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_java_nio_MappedMemoryUtils_isLoaded0(JNIEnv *env, jobject obj, jlong address,
+ jlong len, jlong numPages)
+{
+ jboolean loaded = JNI_TRUE;
+ int result = 0;
+ long i = 0;
+ void *a = (void *) jlong_to_ptr(address);
+ mincore_vec_t* vec = NULL;
+
+ /* See JDK-8186665 */
+ size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
+ if ((long)pagesize == -1) {
+ return JNI_FALSE;
+ }
+ numPages = (jlong) calculate_number_of_pages_in_range(a, len, pagesize);
+
+ /* Include space for one sentinel byte at the end of the buffer
+ * to catch overflows. */
+ vec = (mincore_vec_t*) malloc(numPages + 1);
+
+ if (vec == NULL) {
+ JNU_ThrowOutOfMemoryError(env, NULL);
+ return JNI_FALSE;
+ }
+
+ vec[numPages] = '\x7f'; /* Write sentinel. */
+ result = mincore(a, (size_t)len, vec);
+ assert(vec[numPages] == '\x7f'); /* Check sentinel. */
+
+ if (result == -1) {
+ JNU_ThrowIOExceptionWithLastError(env, "mincore failed");
+ free(vec);
+ return JNI_FALSE;
+ }
+
+ for (i=0; ipr_mflags & MA_SHARED) {
+ // MA_SHARED => MAP_SHARED => !MAP_PRIVATE. This error is valid and should be thrown.
+ JNU_ThrowIOExceptionWithMessageAndLastError(env, "msync with parameter MS_SYNC failed (MAP_SHARED)");
+ return;
+ } else {
+ // O.W. MAP_PRIVATE or no flag was specified and EINVAL is the expected behaviour.
+ return;
+ }
+}
+
+static void check_proc_map_array(JNIEnv* env, FILE* proc_file, prmap_t* map_entry, void* end_address)
+{
+ while (!feof(proc_file)) {
+ memset(map_entry, '\0', sizeof(prmap_t));
+ fread((char*)map_entry, sizeof(prmap_t), 1, proc_file);
+ if (ferror(proc_file)) {
+ JNU_ThrowIOExceptionWithMessageAndLastError(env,
+ "msync with parameter MS_SYNC failed (could not read /proc//map)");
+ return;
+ } else if (map_entry->pr_vaddr <= end_address &&
+ (uint64_t)end_address <= (uint64_t)map_entry->pr_vaddr + map_entry->pr_size) {
+ set_error_if_shared(env, map_entry);
+ return;
+ }
+ }
+ JNU_ThrowIOExceptionWithMessageAndLastError(env,
+ "msync with parameter MS_SYNC failed (address not found)");
+}
+
+// '/proc/' + + '/map' + '\0'
+#define PFNAME_LEN 32
+static void check_aix_einval(JNIEnv* env, void* end_address)
+{
+ // If EINVAL is set for a mmap address on AIX, additional validation is required.
+ // AIX will set EINVAL when msync is called on a mmap address that didn't receive MAP_SHARED
+ // as a flag (since MAP_PRIVATE is the default).
+ // https://www.ibm.com/docs/en/aix/7.2?topic=m-msync-subroutine
+
+ FILE* proc_file;
+ {
+ char* fname = (char*) malloc(sizeof(char) * PFNAME_LEN);
+ pid_t the_pid = getpid();
+ jio_snprintf(fname, PFNAME_LEN, "/proc/%d/map", the_pid);
+ proc_file = fopen(fname, "r");
+ free(fname);
+ }
+ if (!proc_file) {
+ JNU_ThrowIOExceptionWithMessageAndLastError(env,
+ "msync with parameter MS_SYNC failed (could not open /proc//map)");
+ return;
+ }
+ {
+ prmap_t* map_entry = (prmap_t*) malloc(sizeof(prmap_t));
+ check_proc_map_array(env, proc_file, map_entry, end_address);
+ free(map_entry);
+ }
+ fclose(proc_file);
+}
+
+// Normally we would just let msync handle this, but since we'll be (potentially) ignoring
+// the error code returned by msync, we check the args before the call instead.
+static int validate_msync_address(size_t address)
+{
+ size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
+ if (address % pagesize != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_java_nio_MappedMemoryUtils_force0(JNIEnv *env, jobject obj, jobject fdo,
+ jlong address, jlong len)
+{
+ void* a = (void *)jlong_to_ptr(address);
+ if (validate_msync_address((size_t)a) > 0) {
+ JNU_ThrowIOExceptionWithMessageAndLastError(env,
+ "msync with parameter MS_SYNC failed (arguments invalid)");
+ return;
+ }
+ int result = msync(a, (size_t)len, MS_SYNC);
+ if (result == -1) {
+ void* end_address = (void*)jlong_to_ptr(address + len);
+ if (errno == EINVAL) {
+ check_aix_einval(env, end_address);
+ return;
+ }
+ JNU_ThrowIOExceptionWithMessageAndLastError(env, "msync with parameter MS_SYNC failed");
+ }
+}
diff --git a/src/java.base/macosx/classes/apple/security/KeychainStore.java b/src/java.base/macosx/classes/apple/security/KeychainStore.java
index 83c4265423a26..0b60399990c00 100644
--- a/src/java.base/macosx/classes/apple/security/KeychainStore.java
+++ b/src/java.base/macosx/classes/apple/security/KeychainStore.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -181,7 +181,7 @@ public Key engineGetKey(String alias, char[] password)
password = Long.toString(random.nextLong()).toCharArray();
}
- Object entry = entries.get(alias.toLowerCase());
+ Object entry = entries.get(alias.toLowerCase(Locale.ROOT));
if (!(entry instanceof KeyEntry keyEntry)) {
return null;
@@ -271,7 +271,7 @@ public Key engineGetKey(String alias, char[] password)
public Certificate[] engineGetCertificateChain(String alias) {
permissionCheck();
- Object entry = entries.get(alias.toLowerCase());
+ Object entry = entries.get(alias.toLowerCase(Locale.ROOT));
if (entry instanceof KeyEntry keyEntry) {
if (keyEntry.chain == null) {
@@ -302,7 +302,7 @@ public Certificate[] engineGetCertificateChain(String alias) {
public Certificate engineGetCertificate(String alias) {
permissionCheck();
- Object entry = entries.get(alias.toLowerCase());
+ Object entry = entries.get(alias.toLowerCase(Locale.ROOT));
if (entry != null) {
if (entry instanceof TrustedCertEntry) {
@@ -337,7 +337,7 @@ public String getValue() {
public KeyStore.Entry engineGetEntry(String alias, KeyStore.ProtectionParameter protParam)
throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableEntryException {
if (engineIsCertificateEntry(alias)) {
- Object entry = entries.get(alias.toLowerCase());
+ Object entry = entries.get(alias.toLowerCase(Locale.ROOT));
if (entry instanceof TrustedCertEntry tEntry) {
return new KeyStore.TrustedCertificateEntry(
tEntry.cert, Set.of(
@@ -359,7 +359,7 @@ public KeyStore.Entry engineGetEntry(String alias, KeyStore.ProtectionParameter
public Date engineGetCreationDate(String alias) {
permissionCheck();
- Object entry = entries.get(alias.toLowerCase());
+ Object entry = entries.get(alias.toLowerCase(Locale.ROOT));
if (entry != null) {
if (entry instanceof TrustedCertEntry) {
@@ -427,7 +427,7 @@ public void engineSetKeyEntry(String alias, Key key, char[] password,
entry.chainRefs = new long[entry.chain.length];
}
- String lowerAlias = alias.toLowerCase();
+ String lowerAlias = alias.toLowerCase(Locale.ROOT);
if (entries.get(lowerAlias) != null) {
deletedEntries.put(lowerAlias, entries.get(lowerAlias));
}
@@ -491,7 +491,7 @@ public void engineSetKeyEntry(String alias, byte[] key,
entry.chainRefs = new long[entry.chain.length];
}
- String lowerAlias = alias.toLowerCase();
+ String lowerAlias = alias.toLowerCase(Locale.ROOT);
if (entries.get(lowerAlias) != null) {
deletedEntries.put(lowerAlias, entries.get(alias));
}
@@ -521,9 +521,10 @@ public void engineDeleteEntry(String alias)
{
permissionCheck();
+ String lowerAlias = alias.toLowerCase(Locale.ROOT);
synchronized(entries) {
- Object entry = entries.remove(alias.toLowerCase());
- deletedEntries.put(alias.toLowerCase(), entry);
+ Object entry = entries.remove(lowerAlias);
+ deletedEntries.put(lowerAlias, entry);
}
}
@@ -546,7 +547,7 @@ public Enumeration engineAliases() {
*/
public boolean engineContainsAlias(String alias) {
permissionCheck();
- return entries.containsKey(alias.toLowerCase());
+ return entries.containsKey(alias.toLowerCase(Locale.ROOT));
}
/**
@@ -568,7 +569,7 @@ public int engineSize() {
*/
public boolean engineIsKeyEntry(String alias) {
permissionCheck();
- Object entry = entries.get(alias.toLowerCase());
+ Object entry = entries.get(alias.toLowerCase(Locale.ROOT));
return entry instanceof KeyEntry;
}
@@ -581,7 +582,7 @@ public boolean engineIsKeyEntry(String alias) {
*/
public boolean engineIsCertificateEntry(String alias) {
permissionCheck();
- Object entry = entries.get(alias.toLowerCase());
+ Object entry = entries.get(alias.toLowerCase(Locale.ROOT));
return entry instanceof TrustedCertEntry;
}
@@ -806,10 +807,10 @@ private void createTrustedCertEntry(String alias, List inputTrust,
// Check whether a certificate with same alias already exists and is the same
// If yes, we can return here - the existing entry must have the same
// properties and trust settings
- if (entries.contains(alias.toLowerCase())) {
+ if (entries.contains(alias.toLowerCase(Locale.ROOT))) {
int uniqueVal = 1;
String originalAlias = alias;
- var co = entries.get(alias.toLowerCase());
+ var co = entries.get(alias.toLowerCase(Locale.ROOT));
while (co != null) {
if (co instanceof TrustedCertEntry tco) {
if (tco.cert.equals(tce.cert)) {
@@ -817,7 +818,7 @@ private void createTrustedCertEntry(String alias, List inputTrust,
}
}
alias = originalAlias + " " + uniqueVal++;
- co = entries.get(alias.toLowerCase());
+ co = entries.get(alias.toLowerCase(Locale.ROOT));
}
}
@@ -900,7 +901,7 @@ private void createTrustedCertEntry(String alias, List inputTrust,
else
tce.date = new Date();
- entries.put(alias.toLowerCase(), tce);
+ entries.put(alias.toLowerCase(Locale.ROOT), tce);
} catch (Exception e) {
// The certificate will be skipped.
System.err.println("KeychainStore Ignored Exception: " + e);
@@ -971,12 +972,12 @@ private void createKeyEntry(String alias, long creationDate, long secKeyRef,
int uniqueVal = 1;
String originalAlias = alias;
- while (entries.containsKey(alias.toLowerCase())) {
+ while (entries.containsKey(alias.toLowerCase(Locale.ROOT))) {
alias = originalAlias + " " + uniqueVal;
uniqueVal++;
}
- entries.put(alias.toLowerCase(), ke);
+ entries.put(alias.toLowerCase(Locale.ROOT), ke);
}
private static class CertKeychainItemPair {
diff --git a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java
index f676c4dd1a669..03b481af6c2f4 100644
--- a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java
+++ b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java
@@ -1572,6 +1572,13 @@ public int doFinal(ByteBuffer src, ByteBuffer dst)
len += buffer.remaining();
}
+ // Check that input data is long enough to fit the expected tag.
+ if (len < 0) {
+ throw new AEADBadTagException("Input data too short to " +
+ "contain an expected tag length of " + tagLenBytes +
+ "bytes");
+ }
+
checkDataLength(len);
// Verify dst is large enough
diff --git a/src/java.base/share/classes/java/io/FileInputStream.java b/src/java.base/share/classes/java/io/FileInputStream.java
index 2c4e8812b1802..3a95f237e6570 100644
--- a/src/java.base/share/classes/java/io/FileInputStream.java
+++ b/src/java.base/share/classes/java/io/FileInputStream.java
@@ -499,8 +499,6 @@ public int available() throws IOException {
* this method should be prepared to handle possible reentrant invocation.
*
* @throws IOException {@inheritDoc}
- *
- * @revised 1.4
*/
@Override
public void close() throws IOException {
diff --git a/src/java.base/share/classes/java/io/FileOutputStream.java b/src/java.base/share/classes/java/io/FileOutputStream.java
index c596d98b3cedb..90bab607f708c 100644
--- a/src/java.base/share/classes/java/io/FileOutputStream.java
+++ b/src/java.base/share/classes/java/io/FileOutputStream.java
@@ -392,8 +392,6 @@ public void write(byte[] b, int off, int len) throws IOException {
* this method should be prepared to handle possible reentrant invocation.
*
* @throws IOException if an I/O error occurs.
- *
- * @revised 1.4
*/
@Override
public void close() throws IOException {
diff --git a/src/java.base/share/classes/java/io/InputStreamReader.java b/src/java.base/share/classes/java/io/InputStreamReader.java
index 95234cc303b82..b61c48ddf1572 100644
--- a/src/java.base/share/classes/java/io/InputStreamReader.java
+++ b/src/java.base/share/classes/java/io/InputStreamReader.java
@@ -157,8 +157,6 @@ public InputStreamReader(InputStream in, CharsetDecoder dec) {
* {@code null} if the stream has been closed
*
* @see Charset
- *
- * @revised 1.4
*/
public String getEncoding() {
return sd.getEncoding();
diff --git a/src/java.base/share/classes/java/io/OutputStreamWriter.java b/src/java.base/share/classes/java/io/OutputStreamWriter.java
index bcb132e690c2d..b84c3b50391cf 100644
--- a/src/java.base/share/classes/java/io/OutputStreamWriter.java
+++ b/src/java.base/share/classes/java/io/OutputStreamWriter.java
@@ -176,8 +176,6 @@ public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {
* {@code null} if the stream has been closed
*
* @see Charset
- *
- * @revised 1.4
*/
public String getEncoding() {
return se.getEncoding();
diff --git a/src/java.base/share/classes/java/io/RandomAccessFile.java b/src/java.base/share/classes/java/io/RandomAccessFile.java
index 0be326b0a4424..2df78b901e618 100644
--- a/src/java.base/share/classes/java/io/RandomAccessFile.java
+++ b/src/java.base/share/classes/java/io/RandomAccessFile.java
@@ -92,7 +92,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
/**
* Creates a random access file stream to read from, and optionally
- * to write to, a file with the specified name. A new
+ * to write to, a file with the specified pathname. A new
* {@link FileDescriptor} object is created to represent the
* connection to the file.
*
@@ -103,25 +103,25 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
*
*
* If there is a security manager, its {@code checkRead} method
- * is called with the {@code name} argument
+ * is called with the {@code pathname} argument
* as its argument to see if read access to the file is allowed.
* If the mode allows writing, the security manager's
* {@code checkWrite} method
- * is also called with the {@code name} argument
+ * is also called with the {@code pathname} argument
* as its argument to see if write access to the file is allowed.
*
- * @param name the system-dependent filename
- * @param mode the access mode
+ * @param pathname the system-dependent pathname string
+ * @param mode the access mode
* @throws IllegalArgumentException if the mode argument is not equal
* to one of {@code "r"}, {@code "rw"}, {@code "rws"}, or
* {@code "rwd"}
* @throws FileNotFoundException
- * if the mode is {@code "r"} but the given string does not
+ * if the mode is {@code "r"} but the given pathname string does not
* denote an existing regular file, or if the mode begins with
- * {@code "rw"} but the given string does not denote an
+ * {@code "rw"} but the given pathname string does not denote an
* existing, writable regular file and a new regular file of
- * that name cannot be created, or if some other error occurs
- * while opening or creating the file
+ * that pathname cannot be created, or if some other error
+ * occurs while opening or creating the file
* @throws SecurityException if a security manager exists and its
* {@code checkRead} method denies read access to the file
* or the mode is {@code "rw"} and the security manager's
@@ -129,12 +129,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
* @see java.lang.SecurityException
* @see java.lang.SecurityManager#checkRead(java.lang.String)
* @see java.lang.SecurityManager#checkWrite(java.lang.String)
- * @revised 1.4
*/
- public RandomAccessFile(String name, String mode)
+ public RandomAccessFile(String pathname, String mode)
throws FileNotFoundException
{
- this(name != null ? new File(name) : null, mode);
+ this(pathname != null ? new File(pathname) : null, mode);
}
/**
@@ -192,8 +191,8 @@ public RandomAccessFile(String name, String mode)
* called with the pathname of the {@code file} argument as its
* argument to see if read access to the file is allowed. If the mode
* allows writing, the security manager's {@code checkWrite} method is
- * also called with the path argument to see if write access to the file is
- * allowed.
+ * also called with the pathname of the {@code file} argument to see if
+ * write access to the file is allowed.
*
* @param file the file object
* @param mode the access mode, as described
@@ -206,8 +205,8 @@ public RandomAccessFile(String name, String mode)
* not denote an existing regular file, or if the mode begins
* with {@code "rw"} but the given file object does not denote
* an existing, writable regular file and a new regular file of
- * that name cannot be created, or if some other error occurs
- * while opening or creating the file
+ * that pathname cannot be created, or if some other error
+ * occurs while opening or creating the file
* @throws SecurityException if a security manager exists and its
* {@code checkRead} method denies read access to the file
* or the mode is {@code "rw"} and the security manager's
@@ -215,7 +214,6 @@ public RandomAccessFile(String name, String mode)
* @see java.lang.SecurityManager#checkRead(java.lang.String)
* @see java.lang.SecurityManager#checkWrite(java.lang.String)
* @see java.nio.channels.FileChannel#force(boolean)
- * @revised 1.4
*/
public RandomAccessFile(File file, String mode)
throws FileNotFoundException
@@ -703,8 +701,6 @@ public void setLength(long newLength) throws IOException {
* this method should be prepared to handle possible reentrant invocation.
*
* @throws IOException if an I/O error occurs.
- *
- * @revised 1.4
*/
public void close() throws IOException {
if (closed) {
diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java
index bfbe4d9ae6c9b..991c8bcf64644 100644
--- a/src/java.base/share/classes/java/lang/Class.java
+++ b/src/java.base/share/classes/java/lang/Class.java
@@ -1168,7 +1168,6 @@ public Type getGenericSuperclass() {
* this method returns {@code null}.
*
* @return the package of this class.
- * @revised 9
*/
public Package getPackage() {
if (isPrimitive() || isArray()) {
@@ -3029,7 +3028,6 @@ public Constructor getDeclaredConstructor(Class>... parameterTypes)
*
* @see Module#getResourceAsStream(String)
* @since 1.1
- * @revised 9
*/
@CallerSensitive
public InputStream getResourceAsStream(String name) {
@@ -3125,7 +3123,6 @@ public InputStream getResourceAsStream(String name) {
* manager.
* @throws NullPointerException If {@code name} is {@code null}
* @since 1.1
- * @revised 9
*/
@CallerSensitive
public URL getResource(String name) {
diff --git a/src/java.base/share/classes/java/lang/ClassLoader.java b/src/java.base/share/classes/java/lang/ClassLoader.java
index 079a40accdeb6..c68681f35a251 100644
--- a/src/java.base/share/classes/java/lang/ClassLoader.java
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java
@@ -227,7 +227,6 @@
* @jls 13.1 The Form of a Binary
* @see #resolveClass(Class)
* @since 1.0
- * @revised 9
*/
public abstract class ClassLoader {
@@ -881,7 +880,6 @@ protected final Class> defineClass(byte[] b, int off, int len)
* @see java.security.SecureClassLoader
*
* @since 1.1
- * @revised 9
*/
protected final Class> defineClass(String name, byte[] b, int off, int len)
throws ClassFormatError
@@ -1015,8 +1013,6 @@ private void postDefineClass(Class> c, ProtectionDomain pd) {
* certificates than this class, or if {@code name} begins with
* "{@code java.}" and this class loader is not the platform
* class loader or its ancestor.
- *
- * @revised 9
*/
protected final Class> defineClass(String name, byte[] b, int off, int len,
ProtectionDomain protectionDomain)
@@ -1091,7 +1087,6 @@ protected final Class> defineClass(String name, byte[] b, int off, int len,
* @see #defineClass(String, byte[], int, int, ProtectionDomain)
*
* @since 1.5
- * @revised 9
*/
protected final Class> defineClass(String name, java.nio.ByteBuffer b,
ProtectionDomain protectionDomain)
@@ -1404,7 +1399,6 @@ protected URL findResource(String moduleName, String name) throws IOException {
* @throws NullPointerException If {@code name} is {@code null}
*
* @since 1.1
- * @revised 9
*/
public URL getResource(String name) {
Objects.requireNonNull(name);
@@ -1469,7 +1463,6 @@ public URL getResource(String name) {
* @throws NullPointerException If {@code name} is {@code null}
*
* @since 1.2
- * @revised 9
*/
public Enumeration getResources(String name) throws IOException {
Objects.requireNonNull(name);
@@ -1567,7 +1560,6 @@ public Stream resources(String name) {
* denied by the security manager.
*
* @since 1.2
- * @revised 9
*/
protected URL findResource(String name) {
return null;
@@ -1602,7 +1594,6 @@ protected URL findResource(String name) {
* If I/O errors occur
*
* @since 1.2
- * @revised 9
*/
protected Enumeration findResources(String name) throws IOException {
return Collections.emptyEnumeration();
@@ -1687,7 +1678,6 @@ public final boolean isRegisteredAsParallelCapable() {
* denied by the security manager.
*
* @since 1.1
- * @revised 9
*/
public static URL getSystemResource(String name) {
return getSystemClassLoader().getResource(name);
@@ -1723,7 +1713,6 @@ public static URL getSystemResource(String name) {
* If I/O errors occur
*
* @since 1.2
- * @revised 9
*/
public static Enumeration getSystemResources(String name)
throws IOException
@@ -1755,7 +1744,6 @@ public static Enumeration getSystemResources(String name)
* @throws NullPointerException If {@code name} is {@code null}
*
* @since 1.1
- * @revised 9
*/
public InputStream getResourceAsStream(String name) {
Objects.requireNonNull(name);
@@ -1788,7 +1776,6 @@ public InputStream getResourceAsStream(String name) {
* denied by the security manager.
*
* @since 1.1
- * @revised 9
*/
public static InputStream getSystemResourceAsStream(String name) {
URL url = getSystemResource(name);
@@ -1948,9 +1935,6 @@ public static ClassLoader getPlatformClassLoader() {
* exception is thrown by that constructor when it is invoked. The
* underlying cause of the error can be retrieved via the
* {@link Throwable#getCause()} method.
- *
- * @revised 1.4
- * @revised 9
*/
@CallerSensitive
public static ClassLoader getSystemClassLoader() {
@@ -2217,7 +2201,6 @@ private Package toPackage(String name, NamedPackage p, Module m) {
*
*
* @since 1.2
- * @revised 9
*
* @jvms 5.3 Creation and Loading
* @see
@@ -2326,7 +2309,6 @@ public final Package[] getDefinedPackages() {
* @see ClassLoader#getDefinedPackage(String)
*
* @since 1.2
- * @revised 9
*/
@Deprecated(since="9")
protected Package getPackage(String name) {
@@ -2361,7 +2343,6 @@ protected Package getPackage(String name) {
* @see ClassLoader#getDefinedPackages()
*
* @since 1.2
- * @revised 9
*/
protected Package[] getPackages() {
Stream pkgs = packages();
diff --git a/src/java.base/share/classes/java/lang/Math.java b/src/java.base/share/classes/java/lang/Math.java
index 67a0e3bc0cdbb..c851630b95a5e 100644
--- a/src/java.base/share/classes/java/lang/Math.java
+++ b/src/java.base/share/classes/java/lang/Math.java
@@ -55,44 +55,46 @@
*
@@ -119,7 +121,6 @@
* @see
* IEEE Standard for Floating-Point Arithmetic
*
- * @author Joseph D. Darcy
* @since 1.0
*/
diff --git a/src/java.base/share/classes/java/lang/Package.java b/src/java.base/share/classes/java/lang/Package.java
index 22a32c3689462..d48320a66cf52 100644
--- a/src/java.base/share/classes/java/lang/Package.java
+++ b/src/java.base/share/classes/java/lang/Package.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -114,7 +114,6 @@
* @see ClassLoader#definePackage(String, String, String, String, String, String, String, URL)
*
* @since 1.2
- * @revised 9
*/
public class Package extends NamedPackage implements java.lang.reflect.AnnotatedElement {
/**
@@ -211,8 +210,6 @@ public String getImplementationVersion() {
* is returned if it is not known.
* @return the vendor that implemented this package, {@code null}
* is returned if it is not known.
- *
- * @revised 9
*/
public String getImplementationVendor() {
return versionInfo.implVendor;
@@ -355,8 +352,6 @@ public boolean isCompatibleWith(String desired)
* a {@code Package} for the specified class loader.
*
* @see ClassLoader#getDefinedPackage
- *
- * @revised 9
*/
@CallerSensitive
@Deprecated(since="9")
@@ -379,8 +374,6 @@ public static Package getPackage(String name) {
* class loader and its ancestors
*
* @see ClassLoader#getDefinedPackages
- *
- * @revised 9
*/
@CallerSensitive
public static Package[] getPackages() {
diff --git a/src/java.base/share/classes/java/lang/StackTraceElement.java b/src/java.base/share/classes/java/lang/StackTraceElement.java
index fc39291b31679..ed8d47a4e5095 100644
--- a/src/java.base/share/classes/java/lang/StackTraceElement.java
+++ b/src/java.base/share/classes/java/lang/StackTraceElement.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -102,8 +102,9 @@ public final class StackTraceElement implements java.io.Serializable {
* #getModuleVersion module version} of the stack trace element will
* be {@code null}.
*
- * @param declaringClass the fully qualified name of the class containing
- * the execution point represented by the stack trace element
+ * @param declaringClass the {@linkplain ClassLoader##binary-name binary name}
+ * of the class containing the execution point represented by
+ * the stack trace element
* @param methodName the name of the method containing the execution point
* represented by the stack trace element
* @param fileName the name of the file containing the execution point
@@ -117,7 +118,6 @@ public final class StackTraceElement implements java.io.Serializable {
* @throws NullPointerException if {@code declaringClass} or
* {@code methodName} is null
* @since 1.5
- * @revised 9
*/
public StackTraceElement(String declaringClass, String methodName,
String fileName, int lineNumber) {
@@ -137,8 +137,9 @@ public StackTraceElement(String declaringClass, String methodName,
* @param moduleVersion the module version if the class containing the
* execution point represented by the stack trace is in a named
* module that has a version; otherwise {@code null}
- * @param declaringClass the fully qualified name of the class containing
- * the execution point represented by the stack trace element
+ * @param declaringClass the {@linkplain ClassLoader##binary-name binary name}
+ * of the class containing the execution point represented by
+ * the stack trace element
* @param methodName the name of the method containing the execution point
* represented by the stack trace element
* @param fileName the name of the file containing the execution point
@@ -249,11 +250,9 @@ public String getClassLoaderName() {
}
/**
- * Returns the fully qualified name of the class containing the
- * execution point represented by this stack trace element.
- *
- * @return the fully qualified name of the {@code Class} containing
- * the execution point represented by this stack trace element.
+ * {@return the {@linkplain ClassLoader##binary-name binary name}
+ * of the {@code Class} containing the execution point represented
+ * by this stack trace element}
*/
public String getClassName() {
return declaringClass;
@@ -332,7 +331,7 @@ public boolean isNativeMethod() {
* the name of the class loader. The second element "{@code foo@9.0}"
* is the module name and version. The third element is the method
* containing the execution point; "{@code com.foo.Main"}" is the
- * fully-qualified class name and "{@code run}" is the name of the method.
+ * binary name and "{@code run}" is the name of the method.
* "{@code Main.java}" is the source file name and "{@code 101}" is
* the line number.
*
@@ -355,7 +354,6 @@ public boolean isNativeMethod() {
* {@link java.lang.StackWalker.StackFrame}, where an implementation may
* choose to omit some element in the returned string.
*
- * @revised 9
* @see Throwable#printStackTrace()
*/
@Override
@@ -426,8 +424,6 @@ private static int length(String s) {
* @return true if the specified object is another
* {@code StackTraceElement} instance representing the same
* execution point as this instance.
- *
- * @revised 9
*/
public boolean equals(Object obj) {
if (obj==this)
diff --git a/src/java.base/share/classes/java/lang/Thread.java b/src/java.base/share/classes/java/lang/Thread.java
index dc6a989f3ef7e..199a6be60239f 100644
--- a/src/java.base/share/classes/java/lang/Thread.java
+++ b/src/java.base/share/classes/java/lang/Thread.java
@@ -1693,8 +1693,6 @@ public final void stop() {
*
* @throws SecurityException
* if the current thread cannot modify this thread
- *
- * @revised 6.0, 14
*/
public void interrupt() {
if (this != Thread.currentThread()) {
@@ -1726,7 +1724,6 @@ public void interrupt() {
* @return {@code true} if the current thread has been interrupted;
* {@code false} otherwise.
* @see #isInterrupted()
- * @revised 6.0, 14
*/
public static boolean interrupted() {
return currentThread().getAndClearInterrupt();
@@ -1739,7 +1736,6 @@ public static boolean interrupted() {
* @return {@code true} if this thread has been interrupted;
* {@code false} otherwise.
* @see #interrupted()
- * @revised 6.0, 14
*/
public boolean isInterrupted() {
return interrupted;
diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java
index 5d6965d3caa6b..37d092e20118b 100644
--- a/src/java.base/share/classes/java/lang/VirtualThread.java
+++ b/src/java.base/share/classes/java/lang/VirtualThread.java
@@ -630,10 +630,8 @@ void parkNanos(long nanos) {
// park on carrier thread for remaining time when pinned
if (!yielded) {
- long deadline = startTime + nanos;
- if (deadline < 0L)
- deadline = Long.MAX_VALUE;
- parkOnCarrierThread(true, deadline - System.nanoTime());
+ long remainingNanos = nanos - (System.nanoTime() - startTime);
+ parkOnCarrierThread(true, remainingNanos);
}
}
}
diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index 3e61b179e7c4c..c55f08564aedc 100644
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -175,8 +175,6 @@ private static Lookup lookup(Class> caller) {
* Also, it cannot access
* caller sensitive methods.
* @return a lookup object which is trusted minimally
- *
- * @revised 9
*/
public static Lookup publicLookup() {
return Lookup.PUBLIC_LOOKUP;
@@ -1437,8 +1435,6 @@ public static T reflectAs(Class expected, MethodHandle tar
* so that there can be a secure foundation for lookups.
* Nearly all other methods in the JSR 292 API rely on lookup
* objects to check access requests.
- *
- * @revised 9
*/
public static final
class Lookup {
@@ -1621,8 +1617,6 @@ private Class> lookupClassOrNull() {
* @return the lookup modes, which limit the kinds of access performed by this lookup object
* @see #in
* @see #dropLookupMode
- *
- * @revised 9
*/
public int lookupModes() {
return allowedModes & ALL_MODES;
@@ -1703,7 +1697,6 @@ private static Lookup newLookup(Class> lookupClass, Class> prevLookupClass,
* @throws IllegalArgumentException if {@code requestedLookupClass} is a primitive type or void or array class
* @throws NullPointerException if the argument is null
*
- * @revised 9
* @see #accessClass(Class)
* @see Cross-module lookups
*/
@@ -2599,8 +2592,6 @@ private static void checkUnprivilegedlookupClass(Class> lookupClass) {
* because it requires a direct subclass relationship between
* caller and callee.)
* @see #in
- *
- * @revised 9
*/
@Override
public String toString() {
diff --git a/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java b/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java
index 3972084eca2b8..b38d1b0cc87a0 100644
--- a/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java
+++ b/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java
@@ -847,26 +847,25 @@ private Provides(String service, List providers, boolean unused) {
}
/**
- * Returns the fully qualified class name of the service type.
- *
- * @return The fully qualified class name of the service type
+ * {@return the {@linkplain ClassLoader##binary-name binary name} of the service type}
*/
public String service() { return service; }
/**
- * Returns the list of the fully qualified class names of the providers
- * or provider factories.
+ * Returns the list of the {@linkplain ClassLoader##binary-name binary names}
+ * of the providers or provider factories.
*
- * @return A non-empty and unmodifiable list of the fully qualified class
- * names of the providers or provider factories
+ * @return A non-empty and unmodifiable list of the {@linkplain ClassLoader##binary-name
+ * binary names} of the providers or provider factories
*/
public List providers() { return providers; }
/**
* Compares this {@code Provides} to another.
*
- *
Two {@code Provides} objects are compared by comparing the fully
- * qualified class name of the service type lexicographically. Where the
+ *
Two {@code Provides} objects are compared by comparing the
+ * {@linkplain ClassLoader##binary-name binary name}
+ * of the service type lexicographically. Where the
* class names are equal then the list of the provider class names are
* compared by comparing the corresponding elements of both lists
* lexicographically and in sequence. Where the lists differ in size,
@@ -1446,8 +1445,8 @@ public Set opens() {
*
If this module is an automatic module then the set of service
* dependences is empty.
*
- * @return A possibly-empty unmodifiable set of the fully qualified class
- * names of the service types used
+ * @return A possibly-empty unmodifiable set of the {@linkplain ClassLoader##binary-name
+ * binary names} of the service types used
*/
public Set uses() {
return uses;
@@ -1510,7 +1509,7 @@ public String toNameAndVersion() {
/**
*
Returns the module main class.
*
- * @return The fully qualified class name of the module's main class
+ * @return The {@linkplain ClassLoader##binary-name binary name} of the module's main class
*/
public Optional mainClass() {
return Optional.ofNullable(mainClass);
diff --git a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
index 1b1c2924e4f02..d0b50047031c1 100644
--- a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
+++ b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
@@ -74,7 +74,6 @@
* @spec jni/index.html Java Native Interface Specification
* @jls 6.6 Access Control
* @since 1.2
- * @revised 9
*/
public class AccessibleObject implements AnnotatedElement {
static {
@@ -119,7 +118,6 @@ static void checkPermission() {
* java.lang.Class}
* @see SecurityManager#checkPermission
* @see ReflectPermission
- * @revised 9
*/
@CallerSensitive
public static void setAccessible(AccessibleObject[] array, boolean flag) {
@@ -207,7 +205,6 @@ public static void setAccessible(AccessibleObject[] array, boolean flag) {
* @spec jni/index.html Java Native Interface Specification
* @see #trySetAccessible
* @see java.lang.invoke.MethodHandles#privateLookupIn
- * @revised 9
*/
@CallerSensitive // overrides in Method/Field/Constructor are @CS
public void setAccessible(boolean flag) {
@@ -424,8 +421,6 @@ String toShortString() {
* This method may return {@code false} on a reflected object that is
* accessible to the caller. To test if this reflected object is accessible,
* it should use {@link #canAccess(Object)}.
- *
- * @revised 9
*/
@Deprecated(since="9")
public boolean isAccessible() {
diff --git a/src/java.base/share/classes/java/lang/reflect/Proxy.java b/src/java.base/share/classes/java/lang/reflect/Proxy.java
index a638c6ef53751..3c37153b875ae 100644
--- a/src/java.base/share/classes/java/lang/reflect/Proxy.java
+++ b/src/java.base/share/classes/java/lang/reflect/Proxy.java
@@ -292,7 +292,6 @@
* @author Peter Jones
* @see InvocationHandler
* @since 1.3
- * @revised 9
*/
public class Proxy implements java.io.Serializable {
@java.io.Serial
@@ -382,7 +381,6 @@ protected Proxy(InvocationHandler h) {
* to create a proxy instance instead.
*
* @see Package and Module Membership of Proxy Class
- * @revised 9
*/
@Deprecated
@CallerSensitive
@@ -1015,7 +1013,6 @@ private static Module getDynamicModule(ClassLoader loader) {
* {@code null}
*
* @see Package and Module Membership of Proxy Class
- * @revised 9
*/
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
@@ -1100,8 +1097,6 @@ private static ClassLoader getLoader(Module m) {
* @return {@code true} if the class is a proxy class and
* {@code false} otherwise
* @throws NullPointerException if {@code cl} is {@code null}
- *
- * @revised 9
*/
public static boolean isProxyClass(Class> cl) {
return Proxy.class.isAssignableFrom(cl) && ProxyBuilder.isProxyClass(cl);
diff --git a/src/java.base/share/classes/java/lang/reflect/package-info.java b/src/java.base/share/classes/java/lang/reflect/package-info.java
index bdf42ee7e8c00..a71eb2d962152 100644
--- a/src/java.base/share/classes/java/lang/reflect/package-info.java
+++ b/src/java.base/share/classes/java/lang/reflect/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -94,6 +94,5 @@
* @jvms 5.3.1 Loading Using the Bootstrap Class Loader
* @jvms 5.3.2 Loading Using a User-defined Class Loader
* @since 1.1
- * @revised 9
*/
package java.lang.reflect;
diff --git a/src/java.base/share/classes/java/net/DatagramSocket.java b/src/java.base/share/classes/java/net/DatagramSocket.java
index 9a104349e4a39..26220feac2c1a 100644
--- a/src/java.base/share/classes/java/net/DatagramSocket.java
+++ b/src/java.base/share/classes/java/net/DatagramSocket.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -656,7 +656,6 @@ public SocketAddress getLocalSocketAddress() {
* @see java.net.DatagramPacket
* @see SecurityManager#checkMulticast(InetAddress)
* @see SecurityManager#checkConnect
- * @revised 1.4
*/
public void send(DatagramPacket p) throws IOException {
delegate().send(p);
@@ -708,7 +707,6 @@ public void send(DatagramPacket p) throws IOException {
* and the channel is in non-blocking mode.
* @see java.net.DatagramPacket
* @see java.net.DatagramSocket
- * @revised 1.4
*/
public void receive(DatagramPacket p) throws IOException {
delegate().receive(p);
@@ -1082,8 +1080,6 @@ public int getTrafficClass() throws SocketException {
*
*
If this socket has an associated channel then the channel is closed
* as well.
- *
- * @revised 1.4
*/
public void close() {
delegate().close();
diff --git a/src/java.base/share/classes/java/net/ProxySelector.java b/src/java.base/share/classes/java/net/ProxySelector.java
index b9b800a532899..f29c6738c52d4 100644
--- a/src/java.base/share/classes/java/net/ProxySelector.java
+++ b/src/java.base/share/classes/java/net/ProxySelector.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,8 @@
import java.io.IOException;
import java.util.List;
+import java.util.Locale;
+
import sun.security.util.SecurityConstants;
/**
@@ -210,7 +212,7 @@ public void connectFailed(URI uri, SocketAddress sa, IOException e) {
@Override
public synchronized List select(URI uri) {
- String scheme = uri.getScheme().toLowerCase();
+ String scheme = uri.getScheme().toLowerCase(Locale.ROOT);
if (scheme.equals("http") || scheme.equals("https")) {
return list;
} else {
diff --git a/src/java.base/share/classes/java/net/ServerSocket.java b/src/java.base/share/classes/java/net/ServerSocket.java
index e3aa92a846b25..6e38ed4447db6 100644
--- a/src/java.base/share/classes/java/net/ServerSocket.java
+++ b/src/java.base/share/classes/java/net/ServerSocket.java
@@ -125,7 +125,6 @@ private static Void checkPermission() {
* Creates an unbound server socket.
*
* @throws IOException IO error when opening the socket.
- * @revised 1.4
*/
public ServerSocket() throws IOException {
this.impl = createImpl();
@@ -532,7 +531,6 @@ public SocketAddress getLocalSocketAddress() {
*
* @return the new Socket
* @see SecurityManager#checkAccept
- * @revised 1.4
*/
public Socket accept() throws IOException {
if (isClosed())
@@ -575,7 +573,6 @@ public Socket accept() throws IOException {
* to accept a connection with the given socket
*
* @since 1.1
- * @revised 1.4
*/
protected final void implAccept(Socket s) throws IOException {
SocketImpl si = s.impl();
@@ -741,7 +738,6 @@ private void ensureCompatible(SocketImpl si) throws IOException {
* as well.
*
* @throws IOException if an I/O error occurs when closing the socket.
- * @revised 1.4
*/
public void close() throws IOException {
synchronized (socketLock) {
diff --git a/src/java.base/share/classes/java/net/Socket.java b/src/java.base/share/classes/java/net/Socket.java
index bd65f634363e8..82a7a42badff1 100644
--- a/src/java.base/share/classes/java/net/Socket.java
+++ b/src/java.base/share/classes/java/net/Socket.java
@@ -176,7 +176,6 @@ private Socket(Void unused, SocketImpl impl) {
* socket implementation is created.
*
* @since 1.1
- * @revised 1.4
*/
public Socket() {
this.impl = createImpl();
@@ -1051,8 +1050,6 @@ public SocketChannel getChannel() {
* input stream, the socket is closed, the socket is
* not connected, or the socket input has been shutdown
* using {@link #shutdownInput()}
- *
- * @revised 1.4
*/
public InputStream getInputStream() throws IOException {
int s = state;
@@ -1149,7 +1146,6 @@ public void close() throws IOException {
* @return an output stream for writing bytes to this socket.
* @throws IOException if an I/O error occurs when creating the
* output stream or if the socket is not connected.
- * @revised 1.4
*/
public OutputStream getOutputStream() throws IOException {
int s = state;
@@ -1717,7 +1713,6 @@ public boolean getReuseAddress() throws SocketException {
* as well.
*
* @throws IOException if an I/O error occurs when closing this socket.
- * @revised 1.4
* @see #isClosed
*/
public void close() throws IOException {
diff --git a/src/java.base/share/classes/java/net/URLClassLoader.java b/src/java.base/share/classes/java/net/URLClassLoader.java
index 97c95bc9f597b..724ead583e4a8 100644
--- a/src/java.base/share/classes/java/net/URLClassLoader.java
+++ b/src/java.base/share/classes/java/net/URLClassLoader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -539,8 +539,6 @@ private Class> defineClass(String name, Resource res) throws IOException {
* @throws IllegalArgumentException if the package name is
* already defined by this class loader
* @return the newly defined {@code Package} object
- *
- * @revised 9
*/
protected Package definePackage(String name, Manifest man, URL url) {
String specTitle = null, specVersion = null, specVendor = null;
diff --git a/src/java.base/share/classes/java/nio/Direct-X-Buffer-bin.java.template b/src/java.base/share/classes/java/nio/Direct-X-Buffer-bin.java.template
index 4a28145388627..edfdaa218bf1e 100644
--- a/src/java.base/share/classes/java/nio/Direct-X-Buffer-bin.java.template
+++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer-bin.java.template
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -58,8 +58,8 @@ class XXX {
#end[rw]
- private ByteBuffer put$Type$(long a, $type$ x) {
#if[rw]
+ private ByteBuffer put$Type$(long a, $type$ x) {
try {
$memtype$ y = $toBits$(x);
SCOPED_MEMORY_ACCESS.put$Memtype$Unaligned(session(), null, a, y, bigEndian);
@@ -67,10 +67,8 @@ class XXX {
Reference.reachabilityFence(this);
}
return this;
-#else[rw]
- throw new ReadOnlyBufferException();
-#end[rw]
}
+#end[rw]
public ByteBuffer put$Type$($type$ x) {
#if[rw]
diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java
index 2ff8819af1010..444a22bc0a402 100644
--- a/src/java.base/share/classes/java/nio/file/Files.java
+++ b/src/java.base/share/classes/java/nio/file/Files.java
@@ -1531,7 +1531,8 @@ public static FileStore getFileStore(Path path) throws IOException {
* @throws SecurityException
* In the case of the default provider, and a security manager is
* installed, the {@link SecurityManager#checkRead(String) checkRead}
- * method is invoked to check read access to both files.
+ * method is invoked to check read access to both files when the
+ * two paths are not equal
*
* @see java.nio.file.attribute.BasicFileAttributes#fileKey
*/
@@ -1571,6 +1572,9 @@ public static boolean isSameFile(Path path, Path path2) throws IOException {
* and {@code g}, {@code mismatch(f,g)} will return the same value as
* {@code mismatch(g,f)}).
*
+ *
If both {@code Path} objects are equal, then this method returns
+ * {@code true} without checking if the file exists.
+ *
* @param path
* the path to the first file
* @param path2
@@ -1583,7 +1587,8 @@ public static boolean isSameFile(Path path, Path path2) throws IOException {
* @throws SecurityException
* In the case of the default provider, and a security manager is
* installed, the {@link SecurityManager#checkRead(String) checkRead}
- * method is invoked to check read access to both files.
+ * method is invoked to check read access to both files when the
+ * two paths are not equal
*
* @since 12
*/
diff --git a/src/java.base/share/classes/java/security/KeyStore.java b/src/java.base/share/classes/java/security/KeyStore.java
index 01edb885726c7..9b0db30abba0e 100644
--- a/src/java.base/share/classes/java/security/KeyStore.java
+++ b/src/java.base/share/classes/java/security/KeyStore.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -817,7 +817,7 @@ protected KeyStore(KeyStoreSpi keyStoreSpi, Provider provider, String type)
this.type = type;
if (!skipDebug && pdebug != null) {
- pdebug.println("KeyStore." + type.toUpperCase() + " type from: " +
+ pdebug.println("KeyStore." + type.toUpperCase(Locale.ROOT) + " type from: " +
getProviderName());
}
}
diff --git a/src/java.base/share/classes/java/security/Security.java b/src/java.base/share/classes/java/security/Security.java
index 671529f71a1cb..0cdd22340dfbf 100644
--- a/src/java.base/share/classes/java/security/Security.java
+++ b/src/java.base/share/classes/java/security/Security.java
@@ -296,7 +296,10 @@ public static String getAlgorithmProperty(String algName,
* Adds a new provider, at a specified position. The position is
* the preference order in which providers are searched for
* requested algorithms. The position is 1-based, that is,
- * 1 is most preferred, followed by 2, and so on.
+ * 1 is most preferred, followed by 2, and so on. If the position
+ * is less than 1 or greater than n, where n is the number of installed
+ * providers, the provider (if not already installed) is inserted at
+ * the end of the list, or at the n + 1 position.
*
*
If the given provider is installed at the requested position,
* the provider that used to be at that position, and all providers
diff --git a/src/java.base/share/classes/java/text/DigitList.java b/src/java.base/share/classes/java/text/DigitList.java
index e574cafe0a660..fde0e93214ad2 100644
--- a/src/java.base/share/classes/java/text/DigitList.java
+++ b/src/java.base/share/classes/java/text/DigitList.java
@@ -112,12 +112,21 @@ final class DigitList implements Cloneable {
* Return true if the represented number is zero.
*/
boolean isZero() {
- for (int i=0; i < count; ++i) {
+ return !nonZeroAfterIndex(0);
+ }
+
+
+ /**
+ * Return true if there exists a non-zero digit in the digit list
+ * from the given index until the end.
+ */
+ private boolean nonZeroAfterIndex(int index) {
+ for (int i=index; i < count; ++i) {
if (digits[i] != '0') {
- return false;
+ return true;
}
}
- return true;
+ return false;
}
/**
@@ -190,9 +199,7 @@ public final long getLong() {
StringBuilder temp = getStringBuilder();
temp.append(digits, 0, count);
- for (int i = count; i < decimalAt; ++i) {
- temp.append('0');
- }
+ temp.append("0".repeat(Math.max(0, decimalAt - count)));
return Long.parseLong(temp.toString());
}
@@ -392,6 +399,17 @@ private void set(boolean isNegative, String s,
}
+ /**
+ * Round the representation to the given number of digits.
+ * @param maximumDigits The maximum number of digits to be shown.
+ *
+ * Upon return, count will be less than or equal to maximumDigits.
+ */
+ private void roundInt(int maximumDigits) {
+ // Integers do not need to worry about double rounding
+ round(maximumDigits, false, true);
+ }
+
/**
* Round the representation to the given number of digits.
* @param maximumDigits The maximum number of digits to be shown.
@@ -408,25 +426,8 @@ private final void round(int maximumDigits,
// Round up if appropriate.
if (maximumDigits >= 0 && maximumDigits < count) {
if (shouldRoundUp(maximumDigits, alreadyRounded, valueExactAsDecimal)) {
- // Rounding up involved incrementing digits from LSD to MSD.
- // In most cases this is simple, but in a worst case situation
- // (9999..99) we have to adjust the decimalAt value.
- for (;;) {
- --maximumDigits;
- if (maximumDigits < 0) {
- // We have all 9's, so we increment to a single digit
- // of one and adjust the exponent.
- digits[0] = '1';
- ++decimalAt;
- maximumDigits = 0; // Adjust the count
- break;
- }
-
- ++digits[maximumDigits];
- if (digits[maximumDigits] <= '9') break;
- // digits[maximumDigits] = '0'; // Unnecessary since we'll truncate this
- }
- ++maximumDigits; // Increment for use as count
+ // Rounding can adjust the max digits
+ maximumDigits = roundUp(maximumDigits);
}
count = maximumDigits;
@@ -508,94 +509,44 @@ private boolean shouldRoundUp(int maximumDigits,
switch(roundingMode) {
case UP:
- for (int i=maximumDigits; i '5') {
- // Value is above tie ==> must round up
- return true;
- } else if (digits[maximumDigits] == '5') {
- // Digit at rounding position is a '5'. Tie cases.
- if (maximumDigits != (count - 1)) {
- // There are remaining digits. Above tie => must round up
- return true;
- } else {
- // Digit at rounding position is the last one !
- if (valueExactAsDecimal) {
- // Exact binary representation. On the tie.
- // Apply rounding given by roundingMode.
- return roundingMode == RoundingMode.HALF_UP;
- } else {
- // Not an exact binary representation.
- // Digit sequence either rounded up or truncated.
- // Round up only if it was truncated.
- return !alreadyRounded;
- }
- }
- }
- // Digit at rounding position is < '5' ==> no round up.
- // Just let do the default, which is no round up (thus break).
- break;
case HALF_EVEN:
- // Implement IEEE half-even rounding
+ // Above tie, round up for all cases
if (digits[maximumDigits] > '5') {
return true;
+ // At tie, consider UP, DOWN, and EVEN logic
} else if (digits[maximumDigits] == '5' ) {
+ // Rounding position is the last index, there are 3 Cases.
if (maximumDigits == (count - 1)) {
- // the rounding position is exactly the last index :
- if (alreadyRounded)
- // If FloatingDecimal rounded up (value was below tie),
- // then we should not round up again.
- return false;
-
- if (!valueExactAsDecimal)
- // Otherwise if the digits don't represent exact value,
- // value was above tie and FloatingDecimal truncated
- // digits to tie. We must round up.
- return true;
- else {
- // This is an exact tie value, and FloatingDecimal
- // provided all of the exact digits. We thus apply
- // HALF_EVEN rounding rule.
- return ((maximumDigits > 0) &&
- (digits[maximumDigits-1] % 2 != 0));
+ // When exact, consider specific contract logic
+ if (valueExactAsDecimal) {
+ return (roundingMode == RoundingMode.HALF_UP) ||
+ (roundingMode == RoundingMode.HALF_EVEN
+ && (maximumDigits > 0) && (digits[maximumDigits - 1] % 2 != 0));
+ // If already rounded, do not round again, otherwise round up
+ } else {
+ return !alreadyRounded;
}
+ // Rounding position is not the last index
+ // If any further digits have a non-zero value, round up
} else {
- // Rounds up if it gives a non null digit after '5'
- for (int i=maximumDigits+1; i '9');
+
+ return ++maximumDigits; // Increment for use as count
+ }
+
/**
* Utility routine to set the value of the digit list from a long
*/
@@ -649,12 +627,16 @@ final void set(boolean isNegative, long source, int maximumDigits) {
decimalAt = MAX_COUNT - left;
// Don't copy trailing zeros. We are guaranteed that there is at
// least one non-zero digit, so we don't have to check lower bounds.
- for (right = MAX_COUNT - 1; digits[right] == '0'; --right)
- ;
+ right = MAX_COUNT - 1;
+ while (digits[right] == '0') {
+ --right;
+ }
count = right - left + 1;
System.arraycopy(digits, left, digits, 0, count);
}
- if (maximumDigits > 0) round(maximumDigits, false, true);
+ if (maximumDigits > 0) {
+ roundInt(maximumDigits);
+ }
}
/**
@@ -692,13 +674,14 @@ final void set(boolean isNegative, BigInteger source, int maximumDigits) {
s.getChars(0, len, digits, 0);
decimalAt = len;
- int right;
- for (right = len - 1; right >= 0 && digits[right] == '0'; --right)
- ;
+ int right = len - 1;
+ while (right >= 0 && digits[right] == '0') {
+ --right;
+ }
count = right + 1;
if (maximumDigits > 0) {
- round(maximumDigits, false, true);
+ roundInt(maximumDigits);
}
}
diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
index b55d0232a18d2..edd5e16f8a555 100644
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
+++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
@@ -4725,7 +4725,7 @@ public int parse(DateTimeParseContext context, CharSequence text, int position)
* @return the position after the parse
*/
private int parseOffsetBased(DateTimeParseContext context, CharSequence text, int prefixPos, int position, OffsetIdPrinterParser parser) {
- String prefix = text.subSequence(prefixPos, position).toString().toUpperCase();
+ String prefix = text.subSequence(prefixPos, position).toString().toUpperCase(Locale.ROOT);
if (position >= text.length()) {
context.setParsed(ZoneId.of(prefix));
return position;
diff --git a/src/java.base/share/classes/java/util/ResourceBundle.java b/src/java.base/share/classes/java/util/ResourceBundle.java
index 147f098aac9d1..026a9b8082055 100644
--- a/src/java.base/share/classes/java/util/ResourceBundle.java
+++ b/src/java.base/share/classes/java/util/ResourceBundle.java
@@ -373,7 +373,6 @@
* @see MissingResourceException
* @see ResourceBundleProvider
* @since 1.1
- * @revised 9
*/
public abstract class ResourceBundle {
@@ -894,7 +893,6 @@ public static final ResourceBundle getBundle(String baseName)
* @throws UnsupportedOperationException
* if this method is called in a named module
* @since 1.6
- * @revised 9
*/
@CallerSensitive
public static final ResourceBundle getBundle(String baseName,
@@ -1054,7 +1052,6 @@ public static ResourceBundle getBundle(String baseName, Locale targetLocale, Mod
* @throws UnsupportedOperationException
* if this method is called in a named module
* @since 1.6
- * @revised 9
*/
@CallerSensitive
public static final ResourceBundle getBundle(String baseName, Locale targetLocale,
@@ -1267,7 +1264,6 @@ public static final ResourceBundle getBundle(String baseName, Locale targetLocal
* @throws MissingResourceException
* if no resource bundle for the specified base name can be found
* @since 1.2
- * @revised 9
* @see Resource Bundles and Named Modules
*/
@CallerSensitive
@@ -1492,7 +1488,6 @@ public static ResourceBundle getBundle(String baseName, Locale locale,
* @throws UnsupportedOperationException
* if this method is called in a named module
* @since 1.6
- * @revised 9
*/
@CallerSensitive
public static ResourceBundle getBundle(String baseName, Locale targetLocale,
@@ -2235,7 +2230,6 @@ private static void setExpirationTime(CacheKey cacheKey, Control control) {
* by the caller's module.
*
* @since 1.6
- * @revised 9
* @see ResourceBundle.Control#getTimeToLive(String,Locale)
*/
@CallerSensitive
@@ -2524,7 +2518,6 @@ protected Set handleKeySet() {
* of {@link ResourceBundleControlProvider} are ignored in named modules.
*
* @since 1.6
- * @revised 9
* @see java.util.spi.ResourceBundleProvider
*/
public static class Control {
@@ -3150,7 +3143,6 @@ public Locale getFallbackLocale(String baseName, Locale locale) {
* if an error occurred when reading resources using
* any I/O operations
* @see java.util.spi.ResourceBundleProvider#getBundle(String, Locale)
- * @revised 9
*/
public ResourceBundle newBundle(String baseName, Locale locale, String format,
ClassLoader loader, boolean reload)
diff --git a/src/java.base/share/classes/java/util/Scanner.java b/src/java.base/share/classes/java/util/Scanner.java
index f270a46cc498e..e5ad20f95d73f 100644
--- a/src/java.base/share/classes/java/util/Scanner.java
+++ b/src/java.base/share/classes/java/util/Scanner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,17 +25,34 @@
package java.util;
-import java.io.*;
-import java.math.*;
-import java.nio.*;
-import java.nio.channels.*;
-import java.nio.charset.*;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.nio.CharBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Path;
import java.nio.file.Files;
-import java.text.*;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
import java.text.spi.NumberFormatProvider;
import java.util.function.Consumer;
-import java.util.regex.*;
+import java.util.regex.MatchResult;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import sun.util.locale.provider.LocaleProviderAdapter;
@@ -317,13 +334,13 @@ public final class Scanner implements Iterator, Closeable {
private CharBuffer buf;
// Size of internal character buffer
- private static final int BUFFER_SIZE = 1024; // change to 1024;
+ private static final int BUFFER_SIZE = 1024;
// The index into the buffer currently held by the Scanner
private int position;
// Internal matcher used for finding delimiters
- private Matcher matcher;
+ private final Matcher matcher;
// Pattern used to delimit tokens
private Pattern delimPattern;
@@ -371,7 +388,7 @@ public final class Scanner implements Iterator, Closeable {
private Locale locale = null;
// A cache of the last few recently used Patterns
- private PatternLRUCache patternCache = new PatternLRUCache(7);
+ private final PatternLRUCache patternCache = new PatternLRUCache(7);
// A holder of the last IOException encountered
private IOException lastException;
@@ -382,14 +399,14 @@ public final class Scanner implements Iterator, Closeable {
int modCount;
// A pattern for java whitespace
- private static Pattern WHITESPACE_PATTERN = Pattern.compile(
+ private static final Pattern WHITESPACE_PATTERN = Pattern.compile(
"\\p{javaWhitespace}+");
// A pattern for any token
- private static Pattern FIND_ANY_PATTERN = Pattern.compile("(?s).*");
+ private static final Pattern FIND_ANY_PATTERN = Pattern.compile("(?s).*");
// A pattern for non-ASCII digits
- private static Pattern NON_ASCII_DIGIT = Pattern.compile(
+ private static final Pattern NON_ASCII_DIGIT = Pattern.compile(
"[\\p{javaDigit}&&[^0-9]]");
// Fields and methods to support scanning primitive types
@@ -423,9 +440,9 @@ private static Pattern boolPattern() {
* Fields and methods to match bytes, shorts, ints, and longs
*/
private Pattern integerPattern;
- private String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
- private String non0Digit = "[\\p{javaDigit}&&[^0]]";
- private int SIMPLE_GROUP_INDEX = 5;
+ private static final String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+ private static final String non0Digit = "[\\p{javaDigit}&&[^0]]";
+ private static final int SIMPLE_GROUP_INDEX = 5;
private String buildIntegerPatternString() {
String radixDigits = digits.substring(0, radix);
// \\p{javaDigit} is not guaranteed to be appropriate
diff --git a/src/java.base/share/classes/java/util/ServiceLoader.java b/src/java.base/share/classes/java/util/ServiceLoader.java
index e1db818816254..d4858e7582ac6 100644
--- a/src/java.base/share/classes/java/util/ServiceLoader.java
+++ b/src/java.base/share/classes/java/util/ServiceLoader.java
@@ -386,7 +386,6 @@
*
* @author Mark Reinhold
* @since 1.6
- * @revised 9
*/
public final class ServiceLoader
@@ -1355,8 +1354,6 @@ public Provider next() {
*
* @return An iterator that lazily loads providers for this loader's
* service
- *
- * @revised 9
*/
public Iterator iterator() {
@@ -1640,8 +1637,6 @@ static ServiceLoader load(Class service,
* if the service type is not accessible to the caller or the
* caller is in an explicit module and its module descriptor does
* not declare that it uses {@code service}
- *
- * @revised 9
*/
@CallerSensitive
@SuppressWarnings("doclint:reference") // cross-module links
@@ -1686,8 +1681,6 @@ public static ServiceLoader load(Class service,
* if the service type is not accessible to the caller or the
* caller is in an explicit module and its module descriptor does
* not declare that it uses {@code service}
- *
- * @revised 9
*/
@CallerSensitive
public static ServiceLoader load(Class service) {
@@ -1721,8 +1714,6 @@ public static ServiceLoader load(Class service) {
* if the service type is not accessible to the caller or the
* caller is in an explicit module and its module descriptor does
* not declare that it uses {@code service}
- *
- * @revised 9
*/
@CallerSensitive
public static ServiceLoader loadInstalled(Class service) {
diff --git a/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java b/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java
index 4d9f8cb45b9ea..f4e624c585265 100644
--- a/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java
+++ b/src/java.base/share/classes/java/util/concurrent/StructuredTaskScope.java
@@ -576,8 +576,6 @@ public Subtask fork(Callable extends U> task) {
}
SubtaskImpl subtask = new SubtaskImpl<>(this, task, round);
- boolean started = false;
-
if (s < SHUTDOWN) {
// create thread to run task
Thread thread = factory.newThread(subtask);
@@ -588,15 +586,14 @@ public Subtask fork(Callable extends U> task) {
// attempt to start the thread
try {
flock.start(thread);
- started = true;
} catch (IllegalStateException e) {
// shutdown by another thread, or underlying flock is shutdown due
// to unstructured use
}
}
- // force owner to join if thread started
- if (started && Thread.currentThread() == flock.owner() && round > forkRound) {
+ // force owner to join if this is the first fork in the round
+ if (Thread.currentThread() == flock.owner() && round > forkRound) {
forkRound = round;
}
@@ -756,6 +753,12 @@ private boolean implShutdown() {
* {@code join} or {@code joinUntil} will return immediately.
*
*
+ *
The {@linkplain Subtask.State state} of unfinished subtasks that complete at
+ * around the time that the task scope is shutdown is not defined. A subtask that
+ * completes successfully with a result, or fails with an exception, at around
+ * the time that the task scope is shutdown may or may not transition to a
+ * terminal state.
+ *
*
This method may only be invoked by the task scope owner or threads contained
* in the task scope.
*
@@ -933,7 +936,8 @@ public T get() {
T r = (T) result;
return r;
}
- throw new IllegalStateException("Subtask not completed or did not complete successfully");
+ throw new IllegalStateException(
+ "Result is unavailable or subtask did not complete successfully");
}
@Override
@@ -943,7 +947,8 @@ public Throwable exception() {
if (result instanceof AltResult alt && alt.state() == State.FAILED) {
return alt.exception();
}
- throw new IllegalStateException("Subtask not completed or did not complete with exception");
+ throw new IllegalStateException(
+ "Exception is unavailable or subtask did not complete with exception");
}
@Override
diff --git a/src/java.base/share/classes/java/util/random/RandomGenerator.java b/src/java.base/share/classes/java/util/random/RandomGenerator.java
index 9574fd185945f..b38c4eee8f0cc 100644
--- a/src/java.base/share/classes/java/util/random/RandomGenerator.java
+++ b/src/java.base/share/classes/java/util/random/RandomGenerator.java
@@ -293,7 +293,7 @@ default DoubleStream doubles(long streamSize, double randomNumberOrigin,
* or {@code right} is not finite, or if the specified interval
* is empty.
*
- * @since 21
+ * @since 22
*/
default DoubleStream equiDoubles(double left, double right,
boolean isLeftIncluded, boolean isRightIncluded) {
diff --git a/src/java.base/share/classes/java/util/regex/Matcher.java b/src/java.base/share/classes/java/util/regex/Matcher.java
index 8bc07ba0347ff..4d48e702cdcc9 100644
--- a/src/java.base/share/classes/java/util/regex/Matcher.java
+++ b/src/java.base/share/classes/java/util/regex/Matcher.java
@@ -247,8 +247,7 @@ public final class Matcher implements MatchResult {
this.text = text;
// Allocate state storage
- int parentGroupCount = Math.max(parent.capturingGroupCount, 10);
- groups = new int[parentGroupCount * 2];
+ groups = new int[parent.capturingGroupCount * 2];
locals = new int[parent.localCount];
localsPos = new IntHashSet[parent.localTCNCount];
@@ -422,8 +421,7 @@ public Matcher usePattern(Pattern newPattern) {
namedGroups = null;
// Reallocate state storage
- int parentGroupCount = Math.max(newPattern.capturingGroupCount, 10);
- groups = new int[parentGroupCount * 2];
+ groups = new int[newPattern.capturingGroupCount * 2];
locals = new int[newPattern.localCount];
for (int i = 0; i < groups.length; i++)
groups[i] = -1;
diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java
index 45c48ddab542f..054ad4d9da05d 100644
--- a/src/java.base/share/classes/java/util/regex/Pattern.java
+++ b/src/java.base/share/classes/java/util/regex/Pattern.java
@@ -5187,6 +5187,12 @@ static class BackRef extends Node {
groupIndex = groupCount + groupCount;
}
boolean match(Matcher matcher, int i, CharSequence seq) {
+ // reference to not existing group must never match
+ // group does not exist if matcher didn't allocate space for it
+ if (groupIndex >= matcher.groups.length) {
+ return false;
+ }
+
int j = matcher.groups[groupIndex];
int k = matcher.groups[groupIndex+1];
@@ -5223,6 +5229,12 @@ static class CIBackRef extends Node {
this.doUnicodeCase = doUnicodeCase;
}
boolean match(Matcher matcher, int i, CharSequence seq) {
+ // reference to not existing group must never match
+ // group does not exist if matcher didn't allocate space for it
+ if (groupIndex >= matcher.groups.length) {
+ return false;
+ }
+
int j = matcher.groups[groupIndex];
int k = matcher.groups[groupIndex+1];
diff --git a/src/java.base/share/classes/java/util/spi/ResourceBundleControlProvider.java b/src/java.base/share/classes/java/util/spi/ResourceBundleControlProvider.java
index 30e0225f531b5..fc9a3960e7e6e 100644
--- a/src/java.base/share/classes/java/util/spi/ResourceBundleControlProvider.java
+++ b/src/java.base/share/classes/java/util/spi/ResourceBundleControlProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,6 @@
*
* @author Masayoshi Okutsu
* @since 1.8
- * @revised 9
* @see ResourceBundle#getBundle(String, java.util.Locale, ClassLoader, ResourceBundle.Control)
* ResourceBundle.getBundle
* @see java.util.ServiceLoader#load(Class)
diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java
index 52d975005e05f..cb9070fc885d3 100644
--- a/src/java.base/share/classes/java/util/zip/ZipFile.java
+++ b/src/java.base/share/classes/java/util/zip/ZipFile.java
@@ -69,7 +69,7 @@
import jdk.internal.vm.annotation.Stable;
import sun.nio.cs.UTF_8;
import sun.nio.fs.DefaultFileSystemProvider;
-import sun.security.action.GetBooleanAction;
+import sun.security.action.GetPropertyAction;
import sun.security.util.SignatureFileVerifier;
import static java.util.zip.ZipConstants64.*;
@@ -123,11 +123,12 @@ public class ZipFile implements ZipConstants, Closeable {
public static final int OPEN_DELETE = 0x4;
/**
- * Flag which specifies whether the validation of the Zip64 extra
- * fields should be disabled
+ * Flag to specify whether the Extra ZIP64 validation should be
+ * disabled.
*/
- private static final boolean disableZip64ExtraFieldValidation =
- GetBooleanAction.privilegedGetProperty("jdk.util.zip.disableZip64ExtraFieldValidation");
+ private static final boolean DISABLE_ZIP64_EXTRA_VALIDATION =
+ getDisableZip64ExtraFieldValidation();
+
/**
* Opens a zip file for reading.
*
@@ -1092,6 +1093,22 @@ private int[] getMetaInfVersions() {
}
}
+ /**
+ * Returns the value of the System property which indicates whether the
+ * Extra ZIP64 validation should be disabled.
+ */
+ static boolean getDisableZip64ExtraFieldValidation() {
+ boolean result;
+ String value = GetPropertyAction.privilegedGetProperty(
+ "jdk.util.zip.disableZip64ExtraFieldValidation");
+ if (value == null) {
+ result = false;
+ } else {
+ result = value.isEmpty() || value.equalsIgnoreCase("true");
+ }
+ return result;
+ }
+
static {
SharedSecrets.setJavaUtilZipFileAccess(
new JavaUtilZipFileAccess() {
@@ -1208,7 +1225,7 @@ private int checkAndAddEntry(int pos, int index)
}
int elen = CENEXT(cen, pos);
- if (elen > 0 && !disableZip64ExtraFieldValidation) {
+ if (elen > 0 && !DISABLE_ZIP64_EXTRA_VALIDATION) {
long extraStartingOffset = pos + CENHDR + nlen;
if ((int)extraStartingOffset != extraStartingOffset) {
zerror("invalid CEN header (bad extra offset)");
@@ -1260,25 +1277,32 @@ private void checkExtraFields(int cenPos, int startingOffset,
zerror("Invalid CEN header (extra data field size too long)");
}
int currentOffset = startingOffset;
- while (currentOffset < extraEndOffset) {
+ // Walk through each Extra Header. Each Extra Header Must consist of:
+ // Header ID - 2 bytes
+ // Data Size - 2 bytes:
+ while (currentOffset + Integer.BYTES <= extraEndOffset) {
int tag = get16(cen, currentOffset);
currentOffset += Short.BYTES;
int tagBlockSize = get16(cen, currentOffset);
+ currentOffset += Short.BYTES;
int tagBlockEndingOffset = currentOffset + tagBlockSize;
// The ending offset for this tag block should not go past the
// offset for the end of the extra field
if (tagBlockEndingOffset > extraEndOffset) {
- zerror("Invalid CEN header (invalid zip64 extra data field size)");
+ zerror(String.format(
+ "Invalid CEN header (invalid extra data field size for " +
+ "tag: 0x%04x at %d)",
+ tag, cenPos));
}
- currentOffset += Short.BYTES;
if (tag == ZIP64_EXTID) {
// Get the compressed size;
long csize = CENSIZ(cen, cenPos);
// Get the uncompressed size;
long size = CENLEN(cen, cenPos);
+
checkZip64ExtraFieldValues(currentOffset, tagBlockSize,
csize, size);
}
@@ -1302,6 +1326,16 @@ private void checkZip64ExtraFieldValues(int off, int blockSize, long csize,
long size)
throws ZipException {
byte[] cen = this.cen;
+ // if ZIP64_EXTID blocksize == 0, which may occur with some older
+ // versions of Apache Ant and Commons Compress, validate csize and size
+ // to make sure neither field == ZIP64_MAGICVAL
+ if (blockSize == 0) {
+ if (csize == ZIP64_MAGICVAL || size == ZIP64_MAGICVAL) {
+ zerror("Invalid CEN header (invalid zip64 extra data field size)");
+ }
+ // Only validate the ZIP64_EXTID data if the block size > 0
+ return;
+ }
// Validate the Zip64 Extended Information Extra Field (0x0001)
// length.
if (!isZip64ExtBlockSizeValid(blockSize)) {
diff --git a/src/java.base/share/classes/jdk/internal/classfile/attribute/StackMapTableAttribute.java b/src/java.base/share/classes/jdk/internal/classfile/attribute/StackMapTableAttribute.java
index fa9f3e2841c3b..6f7cc69b9783d 100644
--- a/src/java.base/share/classes/jdk/internal/classfile/attribute/StackMapTableAttribute.java
+++ b/src/java.base/share/classes/jdk/internal/classfile/attribute/StackMapTableAttribute.java
@@ -3,18 +3,18 @@
* 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 License version 2 only, as
+ * 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 License
+ * 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 License version
+ * 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.
*
diff --git a/src/java.base/share/classes/jdk/internal/classfile/constantpool/ConstantPool.java b/src/java.base/share/classes/jdk/internal/classfile/constantpool/ConstantPool.java
index 703b42a4cadc7..9c2ca4b939362 100644
--- a/src/java.base/share/classes/jdk/internal/classfile/constantpool/ConstantPool.java
+++ b/src/java.base/share/classes/jdk/internal/classfile/constantpool/ConstantPool.java
@@ -3,18 +3,18 @@
* 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 License version 2 only, as
+ * 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 License
+ * 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 License version
+ * 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.
*
diff --git a/src/java.base/share/classes/jdk/internal/foreign/CABI.java b/src/java.base/share/classes/jdk/internal/foreign/CABI.java
index eee4ae6745790..d376a19633397 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/CABI.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/CABI.java
@@ -41,6 +41,7 @@ public enum CABI {
WIN_AARCH_64,
LINUX_PPC_64_LE,
LINUX_RISCV_64,
+ LINUX_S390,
FALLBACK,
UNSUPPORTED;
@@ -81,7 +82,11 @@ private static CABI computeCurrent() {
if (OperatingSystem.isLinux()) {
return LINUX_RISCV_64;
}
- }
+ } else if (arch.equals("s390x")) {
+ if (OperatingSystem.isLinux()) {
+ return LINUX_S390;
+ }
+ }
} else if (FallbackLinker.isSupported()) {
return FALLBACK; // fallback linker
}
diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java
index b5eb1029ff5ef..8a322cdcf7a89 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java
@@ -32,6 +32,7 @@
import jdk.internal.foreign.abi.fallback.FallbackLinker;
import jdk.internal.foreign.abi.ppc64.linux.LinuxPPC64leLinker;
import jdk.internal.foreign.abi.riscv64.linux.LinuxRISCV64Linker;
+import jdk.internal.foreign.abi.s390.linux.LinuxS390Linker;
import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker;
import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker;
import jdk.internal.foreign.layout.AbstractLayout;
@@ -60,7 +61,8 @@
public abstract sealed class AbstractLinker implements Linker permits LinuxAArch64Linker, MacOsAArch64Linker,
SysVx64Linker, WindowsAArch64Linker,
Windowsx64Linker, LinuxPPC64leLinker,
- LinuxRISCV64Linker, FallbackLinker {
+ LinuxRISCV64Linker, LinuxS390Linker,
+ FallbackLinker {
public interface UpcallStubFactory {
MemorySegment makeStub(MethodHandle target, Arena arena);
diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java
index 1e41724554346..92d10a1dbdfec 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java
@@ -35,6 +35,7 @@
import jdk.internal.foreign.abi.fallback.FallbackLinker;
import jdk.internal.foreign.abi.ppc64.linux.LinuxPPC64leLinker;
import jdk.internal.foreign.abi.riscv64.linux.LinuxRISCV64Linker;
+import jdk.internal.foreign.abi.s390.linux.LinuxS390Linker;
import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker;
import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker;
import jdk.internal.vm.annotation.ForceInline;
@@ -242,6 +243,7 @@ public static Linker getSystemLinker() {
case WIN_AARCH_64 -> WindowsAArch64Linker.getInstance();
case LINUX_PPC_64_LE -> LinuxPPC64leLinker.getInstance();
case LINUX_RISCV_64 -> LinuxRISCV64Linker.getInstance();
+ case LINUX_S390 -> LinuxS390Linker.getInstance();
case FALLBACK -> FallbackLinker.getInstance();
case UNSUPPORTED -> throw new UnsupportedOperationException("Platform does not support native linker");
};
diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/s390/S390Architecture.java b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/S390Architecture.java
new file mode 100644
index 0000000000000..bbafef2f3dc76
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/S390Architecture.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023 IBM Corp. 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 jdk.internal.foreign.abi.s390;
+
+import jdk.internal.foreign.abi.ABIDescriptor;
+import jdk.internal.foreign.abi.Architecture;
+import jdk.internal.foreign.abi.StubLocations;
+import jdk.internal.foreign.abi.VMStorage;
+
+public final class S390Architecture implements Architecture {
+ public static final Architecture INSTANCE = new S390Architecture();
+
+ // Needs to be consistent with vmstorage_s390.hpp.
+ public static final short REG32_MASK = 0b0000_0000_0000_0001;
+ public static final short REG64_MASK = 0b0000_0000_0000_0011;
+
+ private static final int INTEGER_REG_SIZE = 8;
+ private static final int FLOAT_REG_SIZE = 8;
+ private static final int STACK_SLOT_SIZE = 8;
+
+ // Suppresses default constructor, ensuring non-instantiability.
+ private S390Architecture() {
+ }
+
+ @Override
+ public boolean isStackType(int cls) {
+ return cls == StorageType.STACK;
+ }
+
+ @Override
+ public int typeSize(int cls) {
+ switch (cls) {
+ case StorageType.INTEGER:
+ return INTEGER_REG_SIZE;
+ case StorageType.FLOAT:
+ return FLOAT_REG_SIZE;
+ // STACK is deliberately omitted
+ }
+
+ throw new IllegalArgumentException("Invalid Storage Class: " + cls);
+ }
+
+ public interface StorageType {
+ byte INTEGER = 0;
+ byte FLOAT = 1;
+ byte STACK = 2;
+ byte PLACEHOLDER = 3;
+ }
+
+ public static class Regs { // break circular dependency
+ public static final VMStorage r0 = integerRegister(0);
+ public static final VMStorage r1 = integerRegister(1);
+ public static final VMStorage r2 = integerRegister(2);
+ public static final VMStorage r3 = integerRegister(3);
+ public static final VMStorage r4 = integerRegister(4);
+ public static final VMStorage r5 = integerRegister(5);
+ public static final VMStorage r6 = integerRegister(6);
+ public static final VMStorage r7 = integerRegister(7);
+ public static final VMStorage r8 = integerRegister(8);
+ public static final VMStorage r9 = integerRegister(9);
+ public static final VMStorage r10 = integerRegister(10);
+ public static final VMStorage r11 = integerRegister(11);
+ public static final VMStorage r12 = integerRegister(12);
+ public static final VMStorage r13 = integerRegister(13);
+ public static final VMStorage r14 = integerRegister(14);
+ public static final VMStorage r15 = integerRegister(15);
+
+ public static final VMStorage f0 = floatRegister(0);
+ public static final VMStorage f1 = floatRegister(1);
+ public static final VMStorage f2 = floatRegister(2);
+ public static final VMStorage f3 = floatRegister(3);
+ public static final VMStorage f4 = floatRegister(4);
+ public static final VMStorage f5 = floatRegister(5);
+ public static final VMStorage f6 = floatRegister(6);
+ public static final VMStorage f7 = floatRegister(7);
+ public static final VMStorage f8 = floatRegister(8);
+ public static final VMStorage f9 = floatRegister(9);
+ public static final VMStorage f10 = floatRegister(10);
+ public static final VMStorage f11 = floatRegister(11);
+ public static final VMStorage f12 = floatRegister(12);
+ public static final VMStorage f13 = floatRegister(13);
+ public static final VMStorage f14 = floatRegister(14);
+ public static final VMStorage f15 = floatRegister(15);
+ }
+
+ private static VMStorage integerRegister(int index) {
+ return new VMStorage(StorageType.INTEGER, REG64_MASK, index, "r" + index);
+ }
+
+ private static VMStorage floatRegister(int index) {
+ return new VMStorage(StorageType.FLOAT, REG64_MASK, index, "f" + index);
+ }
+
+ public static VMStorage stackStorage(short size, int byteOffset) {
+ return new VMStorage(StorageType.STACK, size, byteOffset);
+ }
+
+ public static ABIDescriptor abiFor(VMStorage[] inputIntRegs,
+ VMStorage[] inputFloatRegs,
+ VMStorage[] outputIntRegs,
+ VMStorage[] outputFloatRegs,
+ VMStorage[] volatileIntRegs,
+ VMStorage[] volatileFloatRegs,
+ int stackAlignment,
+ int shadowSpace,
+ VMStorage scratch1, VMStorage scratch2) {
+ return new ABIDescriptor(
+ INSTANCE,
+ new VMStorage[][] {
+ inputIntRegs,
+ inputFloatRegs,
+ },
+ new VMStorage[][] {
+ outputIntRegs,
+ outputFloatRegs,
+ },
+ new VMStorage[][] {
+ volatileIntRegs,
+ volatileFloatRegs,
+ },
+ stackAlignment,
+ shadowSpace,
+ scratch1, scratch2,
+ StubLocations.TARGET_ADDRESS.storage(StorageType.PLACEHOLDER),
+ StubLocations.RETURN_BUFFER.storage(StorageType.PLACEHOLDER),
+ StubLocations.CAPTURED_STATE_BUFFER.storage(StorageType.PLACEHOLDER));
+ }
+}
diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390CallArranger.java
new file mode 100644
index 0000000000000..84392e4508991
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390CallArranger.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023 IBM Corp. 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 jdk.internal.foreign.abi.s390.linux;
+
+import java.lang.foreign.AddressLayout;
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import jdk.internal.foreign.abi.ABIDescriptor;
+import jdk.internal.foreign.abi.AbstractLinker.UpcallStubFactory;
+import jdk.internal.foreign.abi.Binding;
+import jdk.internal.foreign.abi.CallingSequence;
+import jdk.internal.foreign.abi.CallingSequenceBuilder;
+import jdk.internal.foreign.abi.DowncallLinker;
+import jdk.internal.foreign.abi.LinkerOptions;
+import jdk.internal.foreign.abi.UpcallLinker;
+import jdk.internal.foreign.abi.SharedUtils;
+import jdk.internal.foreign.abi.VMStorage;
+import jdk.internal.foreign.Utils;
+
+import java.lang.foreign.ValueLayout;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static jdk.internal.foreign.abi.s390.linux.TypeClass.*;
+import static jdk.internal.foreign.abi.s390.S390Architecture.*;
+import static jdk.internal.foreign.abi.s390.S390Architecture.Regs.*;
+
+/**
+ * For the S390 C ABI specifically, this class uses CallingSequenceBuilder
+ * to translate a C FunctionDescriptor into a CallingSequence, which can then be turned into a MethodHandle.
+ *
+ * This includes taking care of synthetic arguments like pointers to return buffers for 'in-memory' returns.
+ */
+public class LinuxS390CallArranger {
+
+ private static final int STACK_SLOT_SIZE = 8;
+ public static final int MAX_REGISTER_ARGUMENTS = 5;
+ public static final int MAX_FLOAT_REGISTER_ARGUMENTS = 4;
+
+ private static final ABIDescriptor CLinux = abiFor(
+ new VMStorage[] { r2, r3, r4, r5, r6, }, // GP input
+ new VMStorage[] { f0, f2, f4, f6 }, // FP input
+ new VMStorage[] { r2, }, // GP output
+ new VMStorage[] { f0, }, // FP output
+ new VMStorage[] { r0, r1, r2, r3, r4, r5, r14 }, // volatile GP
+ new VMStorage[] { f1, f3, f5, f7 }, // volatile FP (excluding argument registers)
+ 8, // Stack is always 8 byte aligned on S390
+ 160, // ABI header
+ r0, r1 // scratch reg r0 & r1
+ );
+
+ public record Bindings(CallingSequence callingSequence, boolean isInMemoryReturn) {}
+
+ public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) {
+ return getBindings(mt, cDesc, forUpcall, LinkerOptions.empty());
+ }
+
+ public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall, LinkerOptions options) {
+ CallingSequenceBuilder csb = new CallingSequenceBuilder(CLinux, forUpcall, options);
+
+ BindingCalculator argCalc = forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true);
+ BindingCalculator retCalc = forUpcall ? new UnboxBindingCalculator(false) : new BoxBindingCalculator(false);
+
+ boolean returnInMemory = isInMemoryReturn(cDesc.returnLayout());
+ if (returnInMemory) {
+ Class> carrier = MemorySegment.class;
+ MemoryLayout layout =SharedUtils.C_POINTER;
+ csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout));
+ } else if (cDesc.returnLayout().isPresent()) {
+ Class> carrier = mt.returnType();
+ MemoryLayout layout = cDesc.returnLayout().get();
+ csb.setReturnBindings(carrier, layout, retCalc.getBindings(carrier, layout));
+ }
+
+ for (int i = 0; i < mt.parameterCount(); i++) {
+ Class> carrier = mt.parameterType(i);
+ MemoryLayout layout = cDesc.argumentLayouts().get(i);
+ csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout));
+ }
+
+ return new Bindings(csb.build(), returnInMemory);
+ }
+
+ public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc, LinkerOptions options) {
+ Bindings bindings = getBindings(mt, cDesc, false, options);
+
+ MethodHandle handle = new DowncallLinker(CLinux, bindings.callingSequence).getBoundMethodHandle();
+
+ if (bindings.isInMemoryReturn) {
+ handle = SharedUtils.adaptDowncallForIMR(handle, cDesc, bindings.callingSequence);
+ }
+
+ return handle;
+ }
+
+ public static UpcallStubFactory arrangeUpcall(MethodType mt, FunctionDescriptor cDesc, LinkerOptions options) {
+ Bindings bindings = getBindings(mt, cDesc, true, options);
+
+ final boolean dropReturn = true; /* drop return, since we don't have bindings for it */
+ return SharedUtils.arrangeUpcallHelper(mt, bindings.isInMemoryReturn, dropReturn, CLinux,
+ bindings.callingSequence);
+ }
+
+ private static boolean isInMemoryReturn(Optional returnLayout) {
+ return returnLayout
+ .filter(layout -> layout instanceof GroupLayout)
+ .isPresent();
+ }
+
+ static class StorageCalculator {
+ private final boolean forArguments;
+
+ private final int[] nRegs = new int[] { 0, 0 };
+ private long stackOffset = 0;
+
+ public StorageCalculator(boolean forArguments) {
+ this.forArguments = forArguments;
+ }
+
+ VMStorage stackAlloc(long size, long alignment) {
+ long alignedStackOffset = Utils.alignUp(stackOffset, alignment);
+
+ short encodedSize = (short) size;
+ assert (encodedSize & 0xFFFF) == size;
+
+ VMStorage storage = stackStorage(encodedSize, (int) alignedStackOffset);
+ stackOffset = alignedStackOffset + size;
+ return storage;
+ }
+
+ VMStorage regAlloc(int type) {
+ int gpRegCnt = (type == StorageType.INTEGER) ? 1 : 0;
+ int fpRegCnt = (type == StorageType.FLOAT) ? 1 : 0;
+
+ // Use stack if not enough registers available.
+ if ((type == StorageType.FLOAT && (nRegs[StorageType.FLOAT] + fpRegCnt) > MAX_FLOAT_REGISTER_ARGUMENTS)
+ || (type == StorageType.INTEGER && (nRegs[StorageType.INTEGER] + gpRegCnt) > MAX_REGISTER_ARGUMENTS)) return null;
+
+ VMStorage[] source = (forArguments ? CLinux.inputStorage : CLinux.outputStorage)[type];
+ VMStorage result = source[nRegs[type]];
+
+ nRegs[StorageType.INTEGER] += gpRegCnt;
+ nRegs[StorageType.FLOAT] += fpRegCnt;
+ return result;
+
+ }
+ VMStorage getStorage(int type, boolean is32Bit) {
+ VMStorage reg = regAlloc(type);
+ if (reg != null) {
+ if (is32Bit) {
+ reg = new VMStorage(reg.type(), REG32_MASK, reg.indexOrOffset());
+ }
+ return reg;
+ }
+ VMStorage stack;
+ if (is32Bit) {
+ stackAlloc(4, STACK_SLOT_SIZE); // Skip first half of stack slot.
+ stack = stackAlloc(4, 4);
+ } else
+ stack = stackAlloc(8, STACK_SLOT_SIZE);
+
+ return stack;
+ }
+ }
+
+ abstract static class BindingCalculator {
+ protected final StorageCalculator storageCalculator;
+
+ protected BindingCalculator(boolean forArguments) {
+ this.storageCalculator = new LinuxS390CallArranger.StorageCalculator(forArguments);
+ }
+
+ abstract List getBindings(Class> carrier, MemoryLayout layout);
+ }
+
+ // Compute recipe for transferring arguments / return values to C from Java.
+ static class UnboxBindingCalculator extends BindingCalculator {
+ UnboxBindingCalculator(boolean forArguments) {
+ super(forArguments);
+ }
+
+ @Override
+ List getBindings(Class> carrier, MemoryLayout layout) {
+ TypeClass argumentClass = TypeClass.classifyLayout(layout);
+ Binding.Builder bindings = Binding.builder();
+ switch (argumentClass) {
+ case STRUCT_REGISTER -> {
+ assert carrier == MemorySegment.class;
+ VMStorage storage = storageCalculator.getStorage(StorageType.INTEGER, false);
+ Class> type = SharedUtils.primitiveCarrierForSize(layout.byteSize(), false);
+ bindings.bufferLoad(0, type)
+ .vmStore(storage, type);
+ }
+ case STRUCT_SFA -> {
+ assert carrier == MemorySegment.class;
+ VMStorage storage = storageCalculator.getStorage(StorageType.FLOAT, layout.byteSize() == 4);
+ Class> type = SharedUtils.primitiveCarrierForSize(layout.byteSize(), true);
+ bindings.bufferLoad(0, type)
+ .vmStore(storage, type);
+ }
+ case STRUCT_REFERENCE -> {
+ assert carrier == MemorySegment.class;
+ bindings.copy(layout)
+ .unboxAddress();
+ VMStorage storage = storageCalculator.getStorage(StorageType.INTEGER, false);
+ bindings.vmStore(storage, long.class);
+ }
+ case POINTER -> {
+ VMStorage storage = storageCalculator.getStorage(StorageType.INTEGER, false);
+ bindings.unboxAddress()
+ .vmStore(storage, long.class);
+ }
+ case INTEGER -> {
+ // ABI requires all int types to get extended to 64 bit.
+ VMStorage storage = storageCalculator.getStorage(StorageType.INTEGER, false);
+ bindings.vmStore(storage, carrier);
+ }
+ case FLOAT -> {
+ VMStorage storage = storageCalculator.getStorage(StorageType.FLOAT, carrier == float.class);
+ bindings.vmStore(storage, carrier);
+ }
+ default -> throw new UnsupportedOperationException("Unhandled class " + argumentClass);
+ }
+ return bindings.build();
+ }
+ }
+
+ // Compute recipe for transferring arguments / return values from C to Java.
+ static class BoxBindingCalculator extends BindingCalculator {
+ BoxBindingCalculator(boolean forArguments) {
+ super(forArguments);
+ }
+
+ @Override
+ List getBindings(Class> carrier, MemoryLayout layout) {
+ TypeClass argumentClass = TypeClass.classifyLayout(layout);
+ Binding.Builder bindings = Binding.builder();
+ switch (argumentClass) {
+ case STRUCT_REGISTER -> {
+ assert carrier == MemorySegment.class;
+ bindings.allocate(layout)
+ .dup();
+ VMStorage storage = storageCalculator.getStorage(StorageType.INTEGER, false);
+ Class> type = SharedUtils.primitiveCarrierForSize(layout.byteSize(), false);
+ bindings.vmLoad(storage, type)
+ .bufferStore(0, type);
+ }
+ case STRUCT_SFA -> {
+ assert carrier == MemorySegment.class;
+ bindings.allocate(layout)
+ .dup();
+ VMStorage storage = storageCalculator.getStorage(StorageType.FLOAT, layout.byteSize() == 4);
+ Class> type = SharedUtils.primitiveCarrierForSize(layout.byteSize(), true);
+ bindings.vmLoad(storage, type)
+ .bufferStore(0, type);
+ }
+ case STRUCT_REFERENCE -> {
+ assert carrier == MemorySegment.class;
+ VMStorage storage = storageCalculator.getStorage(StorageType.INTEGER, false);
+ bindings.vmLoad(storage, long.class)
+ .boxAddress(layout);
+ }
+ case POINTER -> {
+ AddressLayout addressLayout = (AddressLayout) layout;
+ VMStorage storage = storageCalculator.getStorage(StorageType.INTEGER, false);
+ bindings.vmLoad(storage, long.class)
+ .boxAddressRaw(Utils.pointeeByteSize(addressLayout), Utils.pointeeByteAlign(addressLayout));
+ }
+ case INTEGER -> {
+ // We could use carrier != long.class for BoxBindingCalculator, but C always uses 64 bit slots.
+ VMStorage storage = storageCalculator.getStorage(StorageType.INTEGER, false);
+ bindings.vmLoad(storage, carrier);
+ }
+ case FLOAT -> {
+ VMStorage storage = storageCalculator.getStorage(StorageType.FLOAT, carrier == float.class);
+ bindings.vmLoad(storage, carrier);
+ }
+ default -> throw new UnsupportedOperationException("Unhandled class " + argumentClass);
+ }
+ return bindings.build();
+ }
+ }
+}
diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390Linker.java
new file mode 100644
index 0000000000000..ac004b9e1e0eb
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/LinuxS390Linker.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023 IBM Corp. 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 jdk.internal.foreign.abi.s390.linux;
+
+import jdk.internal.foreign.abi.AbstractLinker;
+import jdk.internal.foreign.abi.LinkerOptions;
+
+import java.lang.foreign.FunctionDescriptor;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.nio.ByteOrder;
+
+public final class LinuxS390Linker extends AbstractLinker {
+
+ public static LinuxS390Linker getInstance() {
+ final class Holder {
+ private static final LinuxS390Linker INSTANCE = new LinuxS390Linker();
+ }
+
+ return Holder.INSTANCE;
+ }
+
+ private LinuxS390Linker() {
+ // Ensure there is only one instance
+ }
+
+ @Override
+ protected MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function, LinkerOptions options) {
+ return LinuxS390CallArranger.arrangeDowncall(inferredMethodType, function, options);
+ }
+
+ @Override
+ protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor function, LinkerOptions options) {
+ return LinuxS390CallArranger.arrangeUpcall(targetType, function, options);
+ }
+
+ @Override
+ protected ByteOrder linkerByteOrder() {
+ return ByteOrder.BIG_ENDIAN;
+ }
+}
diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/TypeClass.java b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/TypeClass.java
new file mode 100644
index 0000000000000..095cb2c08a8e1
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/foreign/abi/s390/linux/TypeClass.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023 IBM Corp. 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 jdk.internal.foreign.abi.s390.linux;
+
+import java.lang.foreign.GroupLayout;
+import java.lang.foreign.MemoryLayout;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.SequenceLayout;
+import java.lang.foreign.ValueLayout;
+import java.util.List;
+import java.util.ArrayList;
+
+public enum TypeClass {
+ STRUCT_REGISTER,
+ STRUCT_SFA, // Single Float Aggregate
+ STRUCT_REFERENCE,
+ POINTER,
+ INTEGER,
+ FLOAT;
+
+ private static TypeClass classifyValueType(ValueLayout type) {
+ Class> carrier = type.carrier();
+ if (carrier == boolean.class || carrier == byte.class || carrier == char.class ||
+ carrier == short.class || carrier == int.class || carrier == long.class) {
+ return INTEGER;
+ } else if (carrier == float.class || carrier == double.class) {
+ return FLOAT;
+ } else if (carrier == MemorySegment.class) {
+ return POINTER;
+ } else {
+ throw new IllegalStateException("Cannot get here: " + carrier.getName());
+ }
+ }
+
+ private static boolean isRegisterAggregate(MemoryLayout type) {
+ long byteSize = type.byteSize();
+ if (byteSize > 8 || byteSize == 3 || byteSize == 5 || byteSize == 6 || byteSize == 7)
+ return false;
+ return true;
+ }
+
+ static List scalarLayouts(GroupLayout gl) {
+ List out = new ArrayList<>();
+ scalarLayoutsInternal(out, gl);
+ return out;
+ }
+
+ private static void scalarLayoutsInternal(List out, GroupLayout gl) {
+ for (MemoryLayout member : gl.memberLayouts()) {
+ if (member instanceof GroupLayout memberGl) {
+ scalarLayoutsInternal(out, memberGl);
+ } else if (member instanceof SequenceLayout memberSl) {
+ for (long i = 0; i < memberSl.elementCount(); i++) {
+ out.add(memberSl.elementLayout());
+ }
+ } else {
+ // padding or value layouts
+ out.add(member);
+ }
+ }
+ }
+
+ static boolean isSingleFloatAggregate(MemoryLayout type) {
+ List scalarLayouts = scalarLayouts((GroupLayout) type);
+
+ final int numElements = scalarLayouts.size();
+ if (numElements > 1 || numElements == 0)
+ return false;
+
+ MemoryLayout baseType = scalarLayouts.get(0);
+
+ if (!(baseType instanceof ValueLayout))
+ return false;
+
+ TypeClass baseArgClass = classifyValueType((ValueLayout) baseType);
+ if (baseArgClass != FLOAT)
+ return false;
+
+ return true;
+ }
+
+ private static TypeClass classifyStructType(MemoryLayout layout) {
+
+ if (!isRegisterAggregate(layout)) {
+ return TypeClass.STRUCT_REFERENCE;
+ }
+
+ if (isSingleFloatAggregate(layout)) {
+ return TypeClass.STRUCT_SFA;
+ }
+ return TypeClass.STRUCT_REGISTER;
+ }
+
+ public static TypeClass classifyLayout(MemoryLayout type) {
+ if (type instanceof ValueLayout) {
+ return classifyValueType((ValueLayout) type);
+ } else if (type instanceof GroupLayout) {
+ return classifyStructType(type);
+ } else {
+ throw new IllegalArgumentException("Unsupported layout: " + type);
+ }
+ }
+}
diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java
index 0a2669c3726d6..59224022e7468 100644
--- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java
+++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java
@@ -116,7 +116,7 @@ public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, bool
csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout));
}
- if (!forUpcall) {
+ if (!forUpcall && options.isVariadicFunction()) {
//add extra binding for number of used vector registers (used for variadic calls)
csb.addArgumentBindings(long.class, C_LONG,
List.of(vmStore(rax, long.class)));
@@ -129,7 +129,9 @@ public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDe
Bindings bindings = getBindings(mt, cDesc, false, options);
MethodHandle handle = new DowncallLinker(CSysV, bindings.callingSequence).getBoundMethodHandle();
- handle = MethodHandles.insertArguments(handle, handle.type().parameterCount() - 1, bindings.nVectorArgs);
+ if (options.isVariadicFunction()) {
+ handle = MethodHandles.insertArguments(handle, handle.type().parameterCount() - 1, bindings.nVectorArgs);
+ }
if (bindings.isInMemoryReturn) {
handle = SharedUtils.adaptDowncallForIMR(handle, cDesc, bindings.callingSequence);
diff --git a/src/java.base/share/classes/jdk/internal/util/xml/impl/Attrs.java b/src/java.base/share/classes/jdk/internal/util/xml/impl/Attrs.java
index 55fc7e165f47f..15cbf1c6dce0b 100644
--- a/src/java.base/share/classes/jdk/internal/util/xml/impl/Attrs.java
+++ b/src/java.base/share/classes/jdk/internal/util/xml/impl/Attrs.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,16 +41,12 @@ public class Attrs implements Attributes {
* Number of attributes in the attributes string array.
*/
private char mLength;
- /**
- * current index
- */
- private char mAttrIdx = 0;
/**
* Constructor.
*/
public Attrs() {
- // The default number of attributies capacity is 8.
+ // The default number of attributes capacity is 8.
mItems = new String[(8 << 3)];
}
@@ -136,7 +132,7 @@ public String getQName(int index) {
*
*
If the parser has not read a declaration for the attribute, or if the
* parser does not report attribute types, then it must return the value
- * "CDATA" as stated in the XML 1.0 Recommentation (clause 3.3.3,
+ * "CDATA" as stated in the XML 1.0 Recommendation (clause 3.3.3,
* "Attribute-Value Normalization").
*
*
For an enumerated attribute that is not a notation, the parser will
diff --git a/src/java.base/share/classes/jdk/internal/util/xml/impl/Parser.java b/src/java.base/share/classes/jdk/internal/util/xml/impl/Parser.java
index 4a6ab3d86a0a9..36ec2ae42a502 100644
--- a/src/java.base/share/classes/jdk/internal/util/xml/impl/Parser.java
+++ b/src/java.base/share/classes/jdk/internal/util/xml/impl/Parser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import jdk.internal.org.xml.sax.InputSource;
import jdk.internal.org.xml.sax.SAXException;
@@ -1601,7 +1602,7 @@ private void pi() throws Exception {
// PI target name may not be empty string [#2.6]
// PI target name 'XML' is reserved [#2.6]
if ((str.isEmpty())
- || (mXml.name.equals(str.toLowerCase()) == true)) {
+ || (mXml.name.equals(str.toLowerCase(Locale.ROOT)) == true)) {
panic(FAULT);
}
// This is processing instruction
@@ -2858,7 +2859,7 @@ protected void setinp(InputSource is)
String expenc;
if (is.getEncoding() != null) {
// Ignore encoding in the xml text decl.
- expenc = is.getEncoding().toUpperCase();
+ expenc = is.getEncoding().toUpperCase(Locale.ROOT);
if (expenc.equals("UTF-16")) {
reader = bom(is.getByteStream(), 'U'); // UTF-16 [#4.3.3]
} else {
@@ -3156,7 +3157,7 @@ private String xml(Reader reader)
case 'A':
case '_':
bkch();
- str = name(false).toLowerCase();
+ str = name(false).toLowerCase(Locale.ROOT);
if ("version".equals(str) == true) {
if (st != 1) {
panic(FAULT);
@@ -3170,7 +3171,7 @@ private String xml(Reader reader)
if (st != 2) {
panic(FAULT);
}
- mInp.xmlenc = eqstr('=').toUpperCase();
+ mInp.xmlenc = eqstr('=').toUpperCase(Locale.ROOT);
enc = mInp.xmlenc;
st = 3;
} else if ("standalone".equals(str) == true) {
@@ -3178,7 +3179,7 @@ private String xml(Reader reader)
{
panic(FAULT);
}
- str = eqstr('=').toLowerCase();
+ str = eqstr('=').toLowerCase(Locale.ROOT);
// Check the 'standalone' value and use it [#5.1]
if (str.equals("yes") == true) {
mIsSAlone = true;
diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java
index 0ff9416cb2317..d30f61d9e2b00 100644
--- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java
+++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java
@@ -1315,7 +1315,7 @@ public int compare(ModuleReference a, ModuleReference b) {
}
private static Stream toStringStream(Set s) {
- return s.stream().map(e -> e.toString().toLowerCase());
+ return s.stream().map(e -> e.toString().toLowerCase(Locale.ROOT));
}
private static boolean isJrt(ModuleReference mref) {
diff --git a/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java b/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java
index fcc4a4862d66c..c944bef91e7be 100644
--- a/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java
+++ b/src/java.base/share/classes/sun/net/spi/DefaultProxySelector.java
@@ -377,7 +377,7 @@ static Pattern toPattern(String mask) {
if (disjunct.isEmpty())
continue;
disjunctionEmpty = false;
- String regex = disjunctToRegex(disjunct.toLowerCase());
+ String regex = disjunctToRegex(disjunct.toLowerCase(Locale.ROOT));
joiner.add(regex);
}
return disjunctionEmpty ? null : Pattern.compile(joiner.toString());
diff --git a/src/java.base/share/classes/sun/net/www/MimeTable.java b/src/java.base/share/classes/sun/net/www/MimeTable.java
index 926fe7d60b3ff..9da69d58aa750 100644
--- a/src/java.base/share/classes/sun/net/www/MimeTable.java
+++ b/src/java.base/share/classes/sun/net/www/MimeTable.java
@@ -45,10 +45,10 @@ public class MimeTable implements FileNameMap {
private static final int HASH_MARK = '#';
/** Keyed by content type, returns MimeEntries */
- private Hashtable entries = new Hashtable<>();
+ private final Hashtable entries = new Hashtable<>();
/** Keyed by file extension (with the .), returns MimeEntries */
- private Hashtable extensionMap = new Hashtable<>();
+ private final Hashtable extensionMap = new Hashtable<>();
// Will be reset if in the platform-specific data file
@SuppressWarnings("removal")
diff --git a/src/java.base/share/classes/sun/net/www/URLConnection.java b/src/java.base/share/classes/sun/net/www/URLConnection.java
index 6851367ad670c..66005ab9b2afe 100644
--- a/src/java.base/share/classes/sun/net/www/URLConnection.java
+++ b/src/java.base/share/classes/sun/net/www/URLConnection.java
@@ -261,7 +261,7 @@ public void close() {
url = null;
}
- private static HashMap proxiedHosts = new HashMap<>();
+ private static final HashMap proxiedHosts = new HashMap<>();
public static synchronized void setProxiedHost(String host) {
proxiedHosts.put(host.toLowerCase(Locale.ROOT), null);
diff --git a/src/java.base/share/classes/sun/net/www/http/ChunkedInputStream.java b/src/java.base/share/classes/sun/net/www/http/ChunkedInputStream.java
index b5809aaa86c48..f229cf3a6eb35 100644
--- a/src/java.base/share/classes/sun/net/www/http/ChunkedInputStream.java
+++ b/src/java.base/share/classes/sun/net/www/http/ChunkedInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,13 +50,13 @@ public class ChunkedInputStream extends InputStream implements Hurryable {
* The HttpClient that should be notified when the chunked stream has
* completed.
*/
- private HttpClient hc;
+ private final HttpClient hc;
/**
* The MessageHeader that is populated with any optional trailer
* that appear after the last chunk.
*/
- private MessageHeader responses;
+ private final MessageHeader responses;
/**
* The size, in bytes, of the chunk that is currently being read.
diff --git a/src/java.base/share/classes/sun/net/www/http/ChunkedOutputStream.java b/src/java.base/share/classes/sun/net/www/http/ChunkedOutputStream.java
index 4cf485cc33e83..93584e641b4e1 100644
--- a/src/java.base/share/classes/sun/net/www/http/ChunkedOutputStream.java
+++ b/src/java.base/share/classes/sun/net/www/http/ChunkedOutputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,7 @@ public class ChunkedOutputStream extends OutputStream {
private static final int EMPTY_CHUNK_HEADER_SIZE = getHeaderSize(0);
/* internal buffer */
- private byte buf[];
+ private final byte[] buf;
/* size of data (excluding footers and headers) already stored in buf */
private int size;
/* current index in buf (i.e. buf[count] */
@@ -59,11 +59,11 @@ public class ChunkedOutputStream extends OutputStream {
private PrintStream out;
/* the chunk size we use */
- private int preferredChunkDataSize;
- private int preferedHeaderSize;
- private int preferredChunkGrossSize;
+ private final int preferredChunkDataSize;
+ private final int preferredHeaderSize;
+ private final int preferredChunkGrossSize;
/* header for a complete Chunk */
- private byte[] completeHeader;
+ private final byte[] completeHeader;
private final Lock writeLock = new ReentrantLock();
@@ -119,8 +119,8 @@ public ChunkedOutputStream(PrintStream o, int size) {
getHeaderSize(DEFAULT_CHUNK_SIZE) - FOOTER_SIZE;
}
- preferedHeaderSize = getHeaderSize(preferredChunkDataSize);
- preferredChunkGrossSize = preferedHeaderSize + preferredChunkDataSize
+ preferredHeaderSize = getHeaderSize(preferredChunkDataSize);
+ preferredChunkGrossSize = preferredHeaderSize + preferredChunkDataSize
+ FOOTER_SIZE;
completeHeader = getHeader(preferredChunkDataSize);
@@ -151,7 +151,7 @@ private void flush(boolean flushAll) {
/* adjust a header start index in case the header of the last
* chunk is shorter then preferedHeaderSize */
- int adjustedHeaderStartIndex = preferedHeaderSize -
+ int adjustedHeaderStartIndex = preferredHeaderSize -
getHeaderSize(size);
/* write header */
@@ -277,7 +277,7 @@ public void write(int _b) throws IOException {
public void reset() {
writeLock.lock();
try {
- count = preferedHeaderSize;
+ count = preferredHeaderSize;
size = 0;
spaceInCurrentChunk = preferredChunkDataSize;
} finally {
diff --git a/src/java.base/share/classes/sun/net/www/http/HttpCapture.java b/src/java.base/share/classes/sun/net/www/http/HttpCapture.java
index 1d2732e0473ab..ba7e5af6cdfc8 100644
--- a/src/java.base/share/classes/sun/net/www/http/HttpCapture.java
+++ b/src/java.base/share/classes/sun/net/www/http/HttpCapture.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -56,7 +56,7 @@
public class HttpCapture {
// HttpCapture does blocking I/O operations while holding monitors.
// This is not a concern because it is rarely used.
- private File file;
+ private final File file;
private boolean incoming = true;
private BufferedWriter out;
private static boolean initialized;
diff --git a/src/java.base/share/classes/sun/net/www/http/HttpClient.java b/src/java.base/share/classes/sun/net/www/http/HttpClient.java
index a1c9e9729902e..01c341401d808 100644
--- a/src/java.base/share/classes/sun/net/www/http/HttpClient.java
+++ b/src/java.base/share/classes/sun/net/www/http/HttpClient.java
@@ -98,13 +98,13 @@ private static int getDefaultPort(String proto) {
protected int port;
/* where we cache currently open, persistent connections */
- protected static KeepAliveCache kac = new KeepAliveCache();
+ protected static final KeepAliveCache kac = new KeepAliveCache();
- private static boolean keepAliveProp = true;
+ private static final boolean keepAliveProp;
// retryPostProp is true by default so as to preserve behavior
// from previous releases.
- private static boolean retryPostProp = true;
+ private static final boolean retryPostProp;
/* Value of the system property jdk.ntlm.cache;
if false, then NTLM connections will not be cached.
diff --git a/src/java.base/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java b/src/java.base/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java
index cc0b0cce0e9b0..79bdb8cc64f9a 100644
--- a/src/java.base/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java
+++ b/src/java.base/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,10 +51,10 @@ class KeepAliveStreamCleaner
implements Runnable
{
// maximum amount of remaining data that we will try to cleanup
- protected static int MAX_DATA_REMAINING = 512;
+ protected static final int MAX_DATA_REMAINING;
// maximum amount of KeepAliveStreams to be queued
- protected static int MAX_CAPACITY = 10;
+ protected static final int MAX_CAPACITY;
// timeout for both socket and poll on the queue
protected static final int TIMEOUT = 5000;
@@ -68,7 +68,7 @@ class KeepAliveStreamCleaner
int maxData = AccessController.doPrivileged(
new PrivilegedAction() {
public Integer run() {
- return NetProperties.getInteger(maxDataKey, MAX_DATA_REMAINING);
+ return NetProperties.getInteger(maxDataKey, 512);
}}).intValue() * 1024;
MAX_DATA_REMAINING = maxData;
@@ -77,7 +77,7 @@ public Integer run() {
int maxCapacity = AccessController.doPrivileged(
new PrivilegedAction() {
public Integer run() {
- return NetProperties.getInteger(maxCapacityKey, MAX_CAPACITY);
+ return NetProperties.getInteger(maxCapacityKey, 10);
}}).intValue();
MAX_CAPACITY = maxCapacity;
diff --git a/src/java.base/share/classes/sun/net/www/protocol/file/FileURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/file/FileURLConnection.java
index 545dc4b69e54a..a27a6137a37ab 100644
--- a/src/java.base/share/classes/sun/net/www/protocol/file/FileURLConnection.java
+++ b/src/java.base/share/classes/sun/net/www/protocol/file/FileURLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,10 +42,10 @@
public class FileURLConnection extends URLConnection {
- static String CONTENT_LENGTH = "content-length";
- static String CONTENT_TYPE = "content-type";
- static String TEXT_PLAIN = "text/plain";
- static String LAST_MODIFIED = "last-modified";
+ private static final String CONTENT_LENGTH = "content-length";
+ private static final String CONTENT_TYPE = "content-type";
+ private static final String TEXT_PLAIN = "text/plain";
+ private static final String LAST_MODIFIED = "last-modified";
String contentType;
InputStream is;
diff --git a/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java
index ecc17ea85ec46..f559cc5b820f9 100644
--- a/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java
+++ b/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,10 +23,6 @@
* questions.
*/
-/**
- * FTP stream opener.
- */
-
package sun.net.www.protocol.ftp;
import java.io.IOException;
@@ -84,7 +80,7 @@ public class FtpURLConnection extends URLConnection {
// In case we have to use proxies, we use HttpURLConnection
HttpURLConnection http = null;
- private Proxy instProxy;
+ private final Proxy instProxy;
InputStream is = null;
OutputStream os = null;
diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java b/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java
index bf237259e1839..8083fb36f3984 100644
--- a/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java
+++ b/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java
@@ -91,14 +91,14 @@ public class AuthenticationHeader {
// When set true, do not use Negotiate even if the response
// headers suggest so.
boolean dontUseNegotiate = false;
- static String authPref=null;
+ private static final String authPref;
public String toString() {
return "AuthenticationHeader: prefer " + preferred_r;
}
static {
- authPref = GetPropertyAction.privilegedGetProperty("http.auth.preference");
+ String pref = GetPropertyAction.privilegedGetProperty("http.auth.preference");
// http.auth.preference can be set to SPNEGO or Kerberos.
// In fact they means "Negotiate with SPNEGO" and "Negotiate with
@@ -106,12 +106,13 @@ public String toString() {
// Negotiate. Read NegotiateAuthentication.java to see how they
// were used later.
- if (authPref != null) {
- authPref = authPref.toLowerCase(Locale.ROOT);
- if(authPref.equals("spnego") || authPref.equals("kerberos")) {
- authPref = "negotiate";
+ if (pref != null) {
+ pref = pref.toLowerCase(Locale.ROOT);
+ if (pref.equals("spnego") || pref.equals("kerberos")) {
+ pref = "negotiate";
}
}
+ authPref = pref;
}
String hdrname; // Name of the header to look for
diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java b/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java
index 66e78c866b7fd..faee05b4dfd10 100644
--- a/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java
+++ b/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java
@@ -171,11 +171,7 @@ static class Parameters implements java.io.Serializable {
private static final int cnoncelen = 40; /* number of characters in cnonce */
- private static Random random;
-
- static {
- random = new Random();
- }
+ private static final Random random = new Random();
Parameters () {
serverQop = false;
diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
index cbd24ee2f0bb9..f505ea4a59fb7 100644
--- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
+++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
@@ -162,15 +162,15 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
/* Should we enable buffering of error streams? */
- private static boolean enableESBuffer = false;
+ private static final boolean enableESBuffer;
/* timeout waiting for read for buffered error stream;
*/
- private static int timeout4ESBuffer = 0;
+ private static final int timeout4ESBuffer;
/* buffer size for buffered error stream;
*/
- private static int bufSize4ES = 0;
+ private static final int bufSize4ES;
/*
* Restrict setting of request headers through the public api
@@ -264,17 +264,19 @@ private static Set schemesListToSet(String list) {
enableESBuffer = Boolean.parseBoolean(
props.getProperty("sun.net.http.errorstream.enableBuffering"));
- timeout4ESBuffer = GetIntegerAction.privilegedGetProperty(
+ int esBufferTimeout = GetIntegerAction.privilegedGetProperty(
"sun.net.http.errorstream.timeout", 300);
- if (timeout4ESBuffer <= 0) {
- timeout4ESBuffer = 300; // use the default
+ if (esBufferTimeout <= 0) {
+ esBufferTimeout = 300; // use the default
}
+ timeout4ESBuffer = esBufferTimeout;
- bufSize4ES = GetIntegerAction.privilegedGetProperty(
+ int esBufSize = GetIntegerAction.privilegedGetProperty(
"sun.net.http.errorstream.bufferSize", 4096);
- if (bufSize4ES <= 0) {
- bufSize4ES = 4096; // use the default
+ if (esBufSize <= 0) {
+ esBufSize = 4096; // use the default
}
+ bufSize4ES = esBufSize;
allowRestrictedHeaders = Boolean.parseBoolean(
props.getProperty("sun.net.http.allowRestrictedHeaders"));
@@ -349,7 +351,7 @@ private static Set schemesListToSet(String list) {
/* The headers actually set by the user are recorded here also
*/
- private MessageHeader userHeaders;
+ private final MessageHeader userHeaders;
/* Headers and request method cannot be changed
* once this flag is set in :-
diff --git a/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java b/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java
index 47ac1f130643f..c5216d87e6c2d 100644
--- a/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java
+++ b/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -246,7 +246,7 @@ public static void setCallBack(URLJarFileCallBack cb)
private class URLJarFileEntry extends JarEntry {
- private JarEntry je;
+ private final JarEntry je;
URLJarFileEntry(JarEntry je) {
super(je);
diff --git a/src/java.base/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java b/src/java.base/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java
index 4751cdea3d305..0c15c1a64390d 100644
--- a/src/java.base/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java
+++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousChannelGroupImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -59,7 +59,7 @@ abstract class AsynchronousChannelGroupImpl
private final AtomicInteger threadCount = new AtomicInteger();
// associated Executor for timeouts
- private ScheduledThreadPoolExecutor timeoutExecutor;
+ private final ScheduledThreadPoolExecutor timeoutExecutor;
// task queue for when using a fixed thread pool. In that case, a thread
// waiting on I/O events must be awoken to poll tasks from this queue.
diff --git a/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java
index 8ce7ef1f98682..cdc3a883734a4 100644
--- a/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java
+++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,7 @@ abstract class AsynchronousServerSocketChannelImpl
private final Object stateLock = new Object();
// close support
- private ReadWriteLock closeLock = new ReentrantReadWriteLock();
+ private final ReadWriteLock closeLock = new ReentrantReadWriteLock();
private volatile boolean closed;
// set true when accept operation is cancelled
diff --git a/src/java.base/share/classes/sun/nio/ch/FileLockTable.java b/src/java.base/share/classes/sun/nio/ch/FileLockTable.java
index 9b7b7081f94cc..4b820a63d1de0 100644
--- a/src/java.base/share/classes/sun/nio/ch/FileLockTable.java
+++ b/src/java.base/share/classes/sun/nio/ch/FileLockTable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,7 +49,7 @@ class FileLockTable {
* FileLock (and FileChannel) alive.
*/
private static class FileLockReference extends WeakReference {
- private FileKey fileKey;
+ private final FileKey fileKey;
FileLockReference(FileLock referent,
ReferenceQueue queue,
@@ -66,11 +66,11 @@ FileKey fileKey() {
// The system-wide map is a ConcurrentHashMap that is keyed on the FileKey.
// The map value is a list of file locks represented by FileLockReferences.
// All access to the list must be synchronized on the list.
- private static ConcurrentHashMap> lockMap =
- new ConcurrentHashMap>();
+ private static final ConcurrentHashMap> lockMap =
+ new ConcurrentHashMap<>();
// reference queue for cleared refs
- private static ReferenceQueue queue = new ReferenceQueue();
+ private static final ReferenceQueue queue = new ReferenceQueue<>();
// The connection to which this table is connected
private final Channel channel;
diff --git a/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java b/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java
index a2319d23e0e90..d33d7f55d0ba2 100644
--- a/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java
+++ b/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,7 @@ class IOVecWrapper {
final long address;
// Address size in bytes
- static int addressSize;
+ static final int addressSize;
private static class Deallocator implements Runnable {
private final AllocatedNativeObject obj;
diff --git a/src/java.base/share/classes/sun/nio/ch/OptionKey.java b/src/java.base/share/classes/sun/nio/ch/OptionKey.java
index ebb272aea447b..1b8a58e1d05a7 100644
--- a/src/java.base/share/classes/sun/nio/ch/OptionKey.java
+++ b/src/java.base/share/classes/sun/nio/ch/OptionKey.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,8 +30,8 @@
*/
class OptionKey {
- private int level;
- private int name;
+ private final int level;
+ private final int name;
OptionKey(int level, int name) {
this.level = level;
diff --git a/src/java.base/share/classes/sun/nio/ch/Util.java b/src/java.base/share/classes/sun/nio/ch/Util.java
index 1f30a11936039..bf9fc0c0f7c6b 100644
--- a/src/java.base/share/classes/sun/nio/ch/Util.java
+++ b/src/java.base/share/classes/sun/nio/ch/Util.java
@@ -53,7 +53,7 @@ public class Util {
private static final long MAX_CACHED_BUFFER_SIZE = getMaxCachedBufferSize();
// Per-carrier-thread cache of temporary direct buffers
- private static TerminatingThreadLocal bufferCache = new TerminatingThreadLocal<>() {
+ private static final TerminatingThreadLocal bufferCache = new TerminatingThreadLocal<>() {
@Override
protected BufferCache initialValue() {
return new BufferCache();
@@ -112,7 +112,7 @@ private static boolean isBufferTooLarge(ByteBuffer buf) {
*/
private static class BufferCache {
// the array of buffers
- private ByteBuffer[] buffers;
+ private final ByteBuffer[] buffers;
// the number of buffers in the cache
private int count;
@@ -378,7 +378,7 @@ public boolean addAll(Collection extends E> coll) {
// -- Unsafe access --
- private static Unsafe unsafe = Unsafe.getUnsafe();
+ private static final Unsafe unsafe = Unsafe.getUnsafe();
private static byte _get(long a) {
return unsafe.getByte(a);
diff --git a/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java b/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java
index 6ed5281855c24..7f2829eda2004 100644
--- a/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java
+++ b/src/java.base/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java
@@ -210,8 +210,6 @@ public AnnotatedType[] getAnnotatedBounds() {
typeVarIndex());
}
- private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
-
// Helpers for annotation methods
private int typeVarIndex() {
TypeVariable>[] tVars = getGenericDeclaration().getTypeParameters();
diff --git a/src/java.base/share/classes/sun/security/pkcs/PKCS7.java b/src/java.base/share/classes/sun/security/pkcs/PKCS7.java
index cb27840209465..10bf8fd7c34e3 100644
--- a/src/java.base/share/classes/sun/security/pkcs/PKCS7.java
+++ b/src/java.base/share/classes/sun/security/pkcs/PKCS7.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -557,17 +557,6 @@ public SignerInfo[] verify(byte[] bytes)
return null;
}
- /**
- * Returns all signerInfos which self-verify.
- *
- * @exception NoSuchAlgorithmException on unrecognized algorithms.
- * @exception SignatureException on signature handling errors.
- */
- public SignerInfo[] verify()
- throws NoSuchAlgorithmException, SignatureException {
- return verify(null);
- }
-
/**
* Returns the version number of this PKCS7 block.
* @return the version or null if version is not specified
diff --git a/src/java.base/unix/classes/sun/net/PortConfig.java b/src/java.base/unix/classes/sun/net/PortConfig.java
index 4e9deeb90fbf2..428870c922204 100644
--- a/src/java.base/unix/classes/sun/net/PortConfig.java
+++ b/src/java.base/unix/classes/sun/net/PortConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,13 +35,14 @@
public final class PortConfig {
- private static int defaultUpper, defaultLower;
private static final int upper, lower;
private PortConfig() {}
static {
jdk.internal.loader.BootLoader.loadLibrary("net");
+ int defaultUpper;
+ int defaultLower;
switch (OperatingSystem.current()) {
case LINUX:
defaultLower = 32768;
diff --git a/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
index 72ef34c5f0fac..050e12e35946e 100644
--- a/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
+++ b/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
@@ -34,6 +34,7 @@
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Base64;
+import java.util.Locale;
import java.util.Objects;
import java.util.Properties;
@@ -149,7 +150,7 @@ private void init (PasswordAuthentication pw) {
username = s;
ntdomain = defaultDomain;
} else {
- ntdomain = s.substring (0, i).toUpperCase();
+ ntdomain = s.substring (0, i).toUpperCase(Locale.ROOT);
username = s.substring (i+1);
}
password = pw.getPassword();
diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java
index f35541a9e19f2..94e0f91e81216 100644
--- a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
import java.util.concurrent.TimeUnit;
import java.io.IOException;
+import static sun.nio.fs.UnixConstants.*;
import static sun.nio.fs.UnixNativeDispatcher.*;
class UnixFileAttributeViews {
@@ -262,19 +263,44 @@ public UnixFileAttributes readAttributes() throws IOException {
// chmod
final void setMode(int mode) throws IOException {
checkWriteExtended();
- try {
- if (followLinks) {
+
+ if (followLinks) {
+ try {
chmod(file, mode);
- } else {
- int fd = file.openForAttributeAccess(false);
+ } catch (UnixException e) {
+ e.rethrowAsIOException(file);
+ }
+ return;
+ }
+
+ if (O_NOFOLLOW == 0) {
+ throw new IOException("NOFOLLOW_LINKS is not supported on this platform");
+ }
+
+ int fd = -1;
+ try {
+ fd = open(file, O_RDONLY, O_NOFOLLOW);
+ } catch (UnixException e1) {
+ if (e1.errno() == EACCES) {
+ // retry with write access if there is no read permission
try {
- fchmod(fd, mode);
- } finally {
- close(fd);
+ fd = open(file, O_WRONLY, O_NOFOLLOW);
+ } catch (UnixException e2) {
+ e2.rethrowAsIOException(file);
}
+ } else {
+ e1.rethrowAsIOException(file);
}
- } catch (UnixException x) {
- x.rethrowAsIOException(file);
+ }
+
+ try {
+ try {
+ fchmod(fd, mode);
+ } finally {
+ close(fd);
+ }
+ } catch (UnixException e) {
+ e.rethrowAsIOException(file);
}
}
diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java
index 7f9348a81cb77..6704a588d1094 100644
--- a/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java
@@ -288,7 +288,7 @@ public Properties run() {
if (value != null) {
String[] values = value.split("\\s");
for (String s: values) {
- s = s.trim().toLowerCase();
+ s = s.trim().toLowerCase(Locale.ROOT);
if (s.equals(feature)) {
return FeatureStatus.PRESENT;
}
diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java
index 7cab6d3169078..9a93a69d7890d 100644
--- a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java
@@ -32,6 +32,7 @@
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
+import java.nio.file.FileSystemException;
import java.nio.file.LinkOption;
import java.nio.file.LinkPermission;
import java.nio.file.Path;
@@ -519,6 +520,8 @@ private void copyDirectory(UnixPath source,
try {
mkdir(target, attrs.mode());
} catch (UnixException x) {
+ if (x.errno() == EEXIST && flags.replaceExisting)
+ throw new FileSystemException(target.toString());
x.rethrowAsIOException(target);
}
@@ -665,6 +668,8 @@ void copyFile(UnixPath source,
O_EXCL),
attrs.mode());
} catch (UnixException x) {
+ if (x.errno() == EEXIST && flags.replaceExisting)
+ throw new FileSystemException(target.toString());
x.rethrowAsIOException(target);
}
@@ -783,6 +788,8 @@ private void copyLink(UnixPath source,
}
}
} catch (UnixException x) {
+ if (x.errno() == EEXIST && flags.replaceExisting)
+ throw new FileSystemException(target.toString());
x.rethrowAsIOException(target);
}
}
@@ -797,6 +804,8 @@ private void copySpecial(UnixPath source,
try {
mknod(target, attrs.mode(), attrs.rdev());
} catch (UnixException x) {
+ if (x.errno() == EEXIST && flags.replaceExisting)
+ throw new FileSystemException(target.toString());
x.rethrowAsIOException(target);
}
boolean done = false;
diff --git a/src/java.base/unix/native/libnio/MappedMemoryUtils.c b/src/java.base/unix/native/libnio/MappedMemoryUtils.c
index 4c9b72e51ad3d..cdd8edff22a6c 100644
--- a/src/java.base/unix/native/libnio/MappedMemoryUtils.c
+++ b/src/java.base/unix/native/libnio/MappedMemoryUtils.c
@@ -33,10 +33,6 @@
#include
#include
-#ifdef _AIX
-#include
-#endif
-
/* Output type for mincore(2) */
#ifdef __linux__
typedef unsigned char mincore_vec_t;
@@ -44,16 +40,6 @@ typedef unsigned char mincore_vec_t;
typedef char mincore_vec_t;
#endif
-#ifdef _AIX
-static long calculate_number_of_pages_in_range(void* address, size_t len, size_t pagesize) {
- uintptr_t address_unaligned = (uintptr_t) address;
- uintptr_t address_aligned = address_unaligned & (~(pagesize - 1));
- size_t len2 = len + (address_unaligned - address_aligned);
- long numPages = (len2 + pagesize - 1) / pagesize;
- return numPages;
-}
-#endif
-
JNIEXPORT jboolean JNICALL
Java_java_nio_MappedMemoryUtils_isLoaded0(JNIEnv *env, jobject obj, jlong address,
jlong len, jlong numPages)
@@ -64,15 +50,6 @@ Java_java_nio_MappedMemoryUtils_isLoaded0(JNIEnv *env, jobject obj, jlong addres
void *a = (void *) jlong_to_ptr(address);
mincore_vec_t* vec = NULL;
-#ifdef _AIX
- /* See JDK-8186665 */
- size_t pagesize = (size_t)sysconf(_SC_PAGESIZE);
- if ((long)pagesize == -1) {
- return JNI_FALSE;
- }
- numPages = (jlong) calculate_number_of_pages_in_range(a, len, pagesize);
-#endif
-
/* Include space for one sentinel byte at the end of the buffer
* to catch overflows. */
vec = (mincore_vec_t*) malloc(numPages + 1);
diff --git a/src/java.base/windows/classes/java/lang/ProcessImpl.java b/src/java.base/windows/classes/java/lang/ProcessImpl.java
index dccc1a6089174..a01d1db6ddce4 100644
--- a/src/java.base/windows/classes/java/lang/ProcessImpl.java
+++ b/src/java.base/windows/classes/java/lang/ProcessImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -393,7 +393,7 @@ private boolean isExe(String executablePath) {
// Old version that can be bypassed
private boolean isShellFile(String executablePath) {
- String upPath = executablePath.toUpperCase();
+ String upPath = executablePath.toUpperCase(Locale.ROOT);
return (upPath.endsWith(".CMD") || upPath.endsWith(".BAT"));
}
diff --git a/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
index d9eaabe2b4f10..d3b60daad7440 100644
--- a/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
+++ b/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
@@ -30,6 +30,7 @@
import java.net.PasswordAuthentication;
import java.net.UnknownHostException;
import java.net.URL;
+import java.util.Locale;
import java.util.Objects;
import java.util.Properties;
import sun.net.NetProperties;
@@ -95,7 +96,7 @@ private void init0() {
public String run() {
String localhost;
try {
- localhost = InetAddress.getLocalHost().getHostName().toUpperCase();
+ localhost = InetAddress.getLocalHost().getHostName().toUpperCase(Locale.ROOT);
} catch (UnknownHostException e) {
localhost = "localhost";
}
@@ -136,7 +137,7 @@ private void init (PasswordAuthentication pw) {
username = s;
ntdomain = defaultDomain;
} else {
- ntdomain = s.substring (0, i).toUpperCase();
+ ntdomain = s.substring (0, i).toUpperCase(Locale.ROOT);
username = s.substring (i+1);
}
password = new String (pw.getPassword());
diff --git a/src/java.base/windows/classes/sun/nio/ch/PollArrayWrapper.java b/src/java.base/windows/classes/sun/nio/ch/PollArrayWrapper.java
index fac5cfd9de93d..1a33d47d27c17 100644
--- a/src/java.base/windows/classes/sun/nio/ch/PollArrayWrapper.java
+++ b/src/java.base/windows/classes/sun/nio/ch/PollArrayWrapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,7 @@ class PollArrayWrapper {
@Native private static final short FD_OFFSET = 0; // fd offset in pollfd
@Native private static final short EVENT_OFFSET = 4; // events offset in pollfd
- static short SIZE_POLLFD = 8; // sizeof pollfd struct
+ static final short SIZE_POLLFD = 8; // sizeof pollfd struct
private int size; // Size of the pollArray
diff --git a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java
index 22cdcfa17cc88..20fdfc46ae312 100644
--- a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java
+++ b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,10 +45,9 @@ class WindowsAsynchronousSocketChannelImpl
extends AsynchronousSocketChannelImpl implements Iocp.OverlappedChannel
{
private static final Unsafe unsafe = Unsafe.getUnsafe();
- private static int addressSize = unsafe.addressSize();
private static int dependsArch(int value32, int value64) {
- return (addressSize == 4) ? value32 : value64;
+ return (unsafe.addressSize() == 4) ? value32 : value64;
}
/*
diff --git a/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java b/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
index df26857c04be0..977a1653fdd31 100644
--- a/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
+++ b/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,14 +49,13 @@
class WindowsSelectorImpl extends SelectorImpl {
private static final Unsafe unsafe = Unsafe.getUnsafe();
- private static int addressSize = unsafe.addressSize();
private static int dependsArch(int value32, int value64) {
- return (addressSize == 4) ? value32 : value64;
+ return (unsafe.addressSize() == 4) ? value32 : value64;
}
// Initial capacity of the poll array
- private final int INIT_CAP = 8;
+ private static final int INIT_CAP = 8;
// Maximum number of sockets for select().
// Should be INIT_CAP times a power of 2
private static final int MAX_SELECTABLE_FDS = 1024;
@@ -74,7 +73,7 @@ private static int dependsArch(int value32, int value64) {
private SelectionKeyImpl[] channelArray = new SelectionKeyImpl[INIT_CAP];
// The global native poll array holds file descriptors and event masks
- private PollArrayWrapper pollWrapper;
+ private final PollArrayWrapper pollWrapper;
// The number of valid entries in poll array, including entries occupied
// by wakeup socket handle.
diff --git a/src/java.compiler/share/classes/javax/lang/model/element/Element.java b/src/java.compiler/share/classes/javax/lang/model/element/Element.java
index 473e428d9ad59..150be74c7e116 100644
--- a/src/java.compiler/share/classes/javax/lang/model/element/Element.java
+++ b/src/java.compiler/share/classes/javax/lang/model/element/Element.java
@@ -153,7 +153,6 @@ public interface Element extends AnnotatedConstruct {
* @see VariableElement#getSimpleName
* @see ModuleElement#getSimpleName
* @see RecordComponentElement#getSimpleName
- * @revised 9
*/
Name getSimpleName();
@@ -194,7 +193,6 @@ public interface Element extends AnnotatedConstruct {
*
* @return the enclosing element, or {@code null} if there is none
* @see Elements#getPackageOf
- * @revised 9
*/
Element getEnclosingElement();
@@ -231,7 +229,6 @@ public interface Element extends AnnotatedConstruct {
* @jls 8.8.9 Default Constructor
* @jls 8.9 Enum Classes
* @jls 8.10 Record Classes
- * @revised 9
*/
List extends Element> getEnclosedElements();
diff --git a/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java b/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java
index fd373436b3314..651bbe70eeece 100644
--- a/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java
+++ b/src/java.compiler/share/classes/javax/lang/model/element/PackageElement.java
@@ -127,8 +127,6 @@ public interface PackageElement extends Element, QualifiedNameable {
* processing environment configured for a {@linkplain
* javax.annotation.processing.ProcessingEnvironment#getSourceVersion
* source version} without modules.
- *
- * @revised 9
*/
@Override
Element getEnclosingElement();
diff --git a/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java b/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java
index 48bc4132eeac4..b99903a03fe4d 100644
--- a/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java
+++ b/src/java.compiler/share/classes/javax/lang/model/element/TypeElement.java
@@ -88,7 +88,7 @@
public interface TypeElement extends Element, Parameterizable, QualifiedNameable {
/**
* Returns the type defined by this class or interface element,
- * returning the prototypical type for an element
+ * returning the {@index "prototypical type"} for an element
* representing a generic type.
*
*
A generic element defines a family of types, not just one.
@@ -98,6 +98,12 @@ public interface TypeElement extends Element, Parameterizable, QualifiedNameable
* For example,
* for the generic class element {@code C},
* the parameterized type {@code C} is returned.
+ * Otherwise, for a non-generic class or interface, the
+ * prototypical type mirror corresponds to a use of the type.
+ * None of the components of the prototypical type are annotated,
+ * including the prototypical type itself.
+ *
+ * @apiNote
* The {@link Types} utility interface has more general methods
* for obtaining the full range of types defined by an element.
*
diff --git a/src/java.compiler/share/classes/javax/lang/model/element/package-info.java b/src/java.compiler/share/classes/javax/lang/model/element/package-info.java
index 6e9b92bb80626..1c3bc9292e1e3 100644
--- a/src/java.compiler/share/classes/javax/lang/model/element/package-info.java
+++ b/src/java.compiler/share/classes/javax/lang/model/element/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -110,6 +110,7 @@
* a {@code NullPointerException} if given a {@code null} argument.
*
* @see javax.lang.model.util.Elements
+ * @see javax.lang.model##elementsAndTypes Elements and Types
* @see
* JSR 269: Pluggable Annotation Processing API
* @jls 6.1 Declarations
diff --git a/src/java.compiler/share/classes/javax/lang/model/package-info.java b/src/java.compiler/share/classes/javax/lang/model/package-info.java
index 44a31977bd013..9df3e7f3b0a3d 100644
--- a/src/java.compiler/share/classes/javax/lang/model/package-info.java
+++ b/src/java.compiler/share/classes/javax/lang/model/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
/**
* Types and hierarchies of packages comprising a {@index "Java language
- * model"}, a model of the declarations and types of the Java
+ * model"}, a reflective API that models the declarations and types of the Java
* programming language.
*
* The members of this package and its subpackages are for use in
@@ -52,6 +52,85 @@
*
Unless otherwise specified, methods in this package will throw
* a {@code NullPointerException} if given a {@code null} argument.
*
+ *
+ *
+ * In broad terms the {@link javax.lang.model.element element} package
+ * models the declarations, that is the definitions, of elements while
+ * the {@link javax.lang.model.type type} package models uses
+ * of types. In general, distinct uses can have individualized
+ * information separate from the information associated with the
+ * definition. In some sense, the information in the definition is
+ * shared by all the uses.
+
+ *
For example, consider the uses of {@code
+ * java.lang.String} in the string processing method {@code
+ * identityOrEmpty} below:
+ *
+ * {@snippet lang=java :
+ * // Return the argument if it is non-null and the empty string otherwise.
+ * public static @DefinitelyNotNull String identityOrEmpty(@MightBeNull String argument) {
+ * ...
+ * }
+ * }
+ *
+ * The return type of the method is a {@code String} annotated with
+ * a {@code @DefinitelyNotNull} type annotation while the type of
+ * the parameter is a {@code String} annotated with a {@code
+ * @MightBeNull} type annotation. In a reflective API, since the set
+ * of annotations is different for the two uses of {@code
+ * String} as a type, the return type and argument type would need to
+ * be represented by different objects to distinguish between these two
+ * cases. The definition of {@code java.lang.String} itself
+ * is annotated with neither of the type annotations in question.
+ *
+ *
Another example, consider the declaration of the generic
+ * interface (JLS {@jls 9.1.2}) {@code java.util.Set} which has one
+ * type parameter. This declaration captures commonality between the
+ * many parameterized types (JLS {@jls 4.5}) derived from that
+ * declaration such as {@code java.util.Set}, {@code
+ * java.util.Set}, {@code java.util.Set>}, and also the raw type
+ * (JLS {@jls 4.8}) {@code java.util.Set}.
+ *
+ *
+ *
+ * While distinct concepts, there are bidirectional (partial) mappings
+ * between elements and types, between definitions and uses. For
+ * example, roughly speaking, information that would be invariant for
+ * all uses of a type can be retrieved from the element defining a
+ * type. For example, consider a {@link
+ * javax.lang.model.type.DeclaredType DeclaredType} type mirror
+ * modeling a use of {@code java.lang.String}. Calling {@link
+ * javax.lang.model.type.DeclaredType#asElement()} would return the
+ * {@link javax.lang.model.element.TypeElement} for {@code
+ * java.lang.String}. From the {@code TypeElement}, common information
+ * such as {@linkplain
+ * javax.lang.model.element.TypeElement#getSimpleName() name} and
+ * {@linkplain javax.lang.model.element.TypeElement#getModifiers()
+ * modifiers} can be retrieved.
+ *
+ *
All elements can be {@linkplain
+ * javax.lang.model.element.Element#asType() mapped to} some type.
+ * The elements for classes and interfaces get {@linkplain
+ * javax.lang.model.element.TypeElement#asType() mapped to} a
+ * {@linkplain javax.lang.model.element.TypeElement#asType() prototypical type}.
+ * Conversely, in general, many types can map to the same
+ * {@linkplain javax.lang.model.element.TypeElement type element}. For
+ * example, the type mirror for the raw type {@code java.util.Set},
+ * the prototypical type {@code java.util.Set}, and the type {@code
+ * java.util.Set} would all {@linkplain
+ * javax.lang.model.type.DeclaredType#asElement() map to} the type
+ * element for {@code java.util.Set}. Several kinds of types can be
+ * mapped to elements, but other kinds of types do not have
+ * an {@linkplain javax.lang.model.util.Types#asElement(TypeMirror)
+ * element mapping}. For example, the type mirror of an {@linkplain
+ * javax.lang.model.type.ExecutableType executable type} does
+ * not have an element mapping while a {@linkplain
+ * javax.lang.model.type.DeclaredType declared type} would map to a
+ * {@linkplain javax.lang.model.element.TypeElement type element}, as
+ * discussed above.
+ *
* @since 1.6
*
* @see
diff --git a/src/java.compiler/share/classes/javax/lang/model/type/package-info.java b/src/java.compiler/share/classes/javax/lang/model/type/package-info.java
index 712cfe0f217ea..945ada682846a 100644
--- a/src/java.compiler/share/classes/javax/lang/model/type/package-info.java
+++ b/src/java.compiler/share/classes/javax/lang/model/type/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,7 @@
* a {@code NullPointerException} if given a {@code null} argument.
*
* @see javax.lang.model.util.Types
+ * @see javax.lang.model##elementsAndTypes Elements and Types
* @see
* JSR 269: Pluggable Annotation Processing API
* @jls 4.1 The Kinds of Types and Values
diff --git a/src/java.compiler/share/classes/javax/tools/StandardLocation.java b/src/java.compiler/share/classes/javax/tools/StandardLocation.java
index 2a9079f572459..389f3410f4e34 100644
--- a/src/java.compiler/share/classes/javax/tools/StandardLocation.java
+++ b/src/java.compiler/share/classes/javax/tools/StandardLocation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -120,8 +120,6 @@ public enum StandardLocation implements Location {
*
* @param name a name
* @return a location
- *
- * @revised 9
*/
public static Location locationFor(final String name) {
if (locations.isEmpty()) {
diff --git a/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java b/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java
index a207d69c3551a..6447e654f600e 100644
--- a/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java
+++ b/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLClassLoader;
+import java.security.AccessController;
import java.util.ArrayList;
import java.util.Objects;
@@ -40,6 +41,7 @@
import javax.sound.midi.spi.SoundbankReader;
import sun.reflect.misc.ReflectUtil;
+import sun.security.action.GetBooleanAction;
/**
* JarSoundbankReader is used to read soundbank object from jar files.
@@ -48,12 +50,15 @@
*/
public final class JARSoundbankReader extends SoundbankReader {
- /*
- * Name of the system property that enables the Jar soundbank loading
- * true if jar sound bank is allowed to be loaded
- * default is false
+ /**
+ * Value of the system property that enables the Jar soundbank loading
+ * {@code true} if jar sound bank is allowed to be loaded default is
+ * {@code false}.
*/
- private final static String JAR_SOUNDBANK_ENABLED = "jdk.sound.jarsoundbank";
+ @SuppressWarnings("removal")
+ private static final boolean JAR_SOUNDBANK_ENABLED =
+ AccessController.doPrivileged(
+ new GetBooleanAction("jdk.sound.jarsoundbank"));
private static boolean isZIP(URL url) {
boolean ok = false;
@@ -78,7 +83,7 @@ private static boolean isZIP(URL url) {
public Soundbank getSoundbank(URL url)
throws InvalidMidiDataException, IOException {
Objects.requireNonNull(url);
- if (!Boolean.getBoolean(JAR_SOUNDBANK_ENABLED) || !isZIP(url))
+ if (!JAR_SOUNDBANK_ENABLED || !isZIP(url))
return null;
ArrayList soundbanks = new ArrayList<>();
diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java b/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java
index 7a73cc86c9ce7..a20eca94a3f05 100644
--- a/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java
+++ b/src/java.desktop/share/classes/java/awt/color/ICC_ColorSpace.java
@@ -93,12 +93,12 @@ public class ICC_ColorSpace extends ColorSpace {
private ICC_Profile thisProfile;
/**
- * The maximum normalized component values.
+ * The minimum normalized component values.
*/
private float[] minVal;
/**
- * The minimum normalized component values.
+ * The maximum normalized component values.
*/
private float[] maxVal;
diff --git a/src/java.desktop/share/classes/javax/swing/BoxLayout.java b/src/java.desktop/share/classes/javax/swing/BoxLayout.java
index fe11a08bc6411..cbc2bbd30928c 100644
--- a/src/java.desktop/share/classes/javax/swing/BoxLayout.java
+++ b/src/java.desktop/share/classes/javax/swing/BoxLayout.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,9 +38,9 @@
* arranged when the frame is resized.
*
*
Example:
- *
+ * width="160" height="160">
*
*
* Nesting multiple panels with different combinations of horizontal and
diff --git a/src/java.desktop/share/classes/javax/swing/doc-files/BoxLayout-1.gif b/src/java.desktop/share/classes/javax/swing/doc-files/BoxLayout-1.gif
deleted file mode 100644
index 8493ab8ec14bd..0000000000000
Binary files a/src/java.desktop/share/classes/javax/swing/doc-files/BoxLayout-1.gif and /dev/null differ
diff --git a/src/java.desktop/share/classes/javax/swing/doc-files/BoxLayout-1.svg b/src/java.desktop/share/classes/javax/swing/doc-files/BoxLayout-1.svg
new file mode 100644
index 0000000000000..84235395ae686
--- /dev/null
+++ b/src/java.desktop/share/classes/javax/swing/doc-files/BoxLayout-1.svg
@@ -0,0 +1,74 @@
+
+
+
+
+
diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSeparatorUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSeparatorUI.java
index 0580765e1c0ea..eea9e9589a6d9 100644
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSeparatorUI.java
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSeparatorUI.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,12 +25,12 @@
package javax.swing.plaf.basic;
-import javax.swing.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
-import java.awt.Insets;
-import java.awt.Rectangle;
+import javax.swing.JComponent;
+import javax.swing.JSeparator;
+import javax.swing.LookAndFeel;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.SeparatorUI;
@@ -152,5 +152,13 @@ public Dimension getPreferredSize( JComponent c )
}
public Dimension getMinimumSize( JComponent c ) { return null; }
- public Dimension getMaximumSize( JComponent c ) { return null; }
+
+ public Dimension getMaximumSize( JComponent c ) {
+ Dimension d = getPreferredSize(c);
+ if (((JSeparator)c).getOrientation() == JSeparator.VERTICAL) {
+ return new Dimension(d.width, Short.MAX_VALUE);
+ } else {
+ return new Dimension(Short.MAX_VALUE, d.height);
+ }
+ }
}
diff --git a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c
index 8f5f66fe09f99..21ac280f0fb0b 100644
--- a/src/java.desktop/share/native/libfontmanager/freetypeScaler.c
+++ b/src/java.desktop/share/native/libfontmanager/freetypeScaler.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -548,7 +548,8 @@ Java_sun_font_FreetypeFontScaler_createScalerContextNative(
if ((aa != TEXT_AA_ON) && (fm != TEXT_FM_ON) &&
!context->doBold && !context->doItalize &&
(context->transform.yx == 0) && (context->transform.xy == 0) &&
- (context->transform.xx > 0) && (context->transform.yy > 0))
+ (context->transform.xx > 0) && (context->transform.yy > 0) &&
+ (context->transform.xx == context->transform.yy))
{
context->useSbits = 1;
}
diff --git a/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java b/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java
index e61fd1a90e6f6..6a19b9fab87aa 100644
--- a/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java
+++ b/src/java.desktop/unix/classes/sun/awt/screencast/ScreencastHelper.java
@@ -35,6 +35,8 @@
import java.util.Arrays;
import java.util.List;
import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
import java.util.stream.IntStream;
/**
@@ -54,6 +56,13 @@ public class ScreencastHelper {
private static final int DENIED = -11;
private static final int OUT_OF_BOUNDS = -12;
+ private static final int DELAY_BEFORE_SESSION_CLOSE = 2000;
+
+ private static volatile TimerTask timerTask = null;
+ private static final Timer timerCloseSession
+ = new Timer("auto-close screencast session", true);
+
+
private ScreencastHelper() {
}
@@ -105,11 +114,30 @@ private static List getSystemScreensBounds() {
).toList();
}
+ private static synchronized native void closeSession();
+
+ private static void timerCloseSessionRestart() {
+ if (timerTask != null) {
+ timerTask.cancel();
+ }
+
+ timerTask = new TimerTask() {
+ @Override
+ public void run() {
+ closeSession();
+ }
+ };
+
+ timerCloseSession.schedule(timerTask, DELAY_BEFORE_SESSION_CLOSE);
+ }
+
public static synchronized void getRGBPixels(
int x, int y, int width, int height, int[] pixelArray
) {
if (!IS_NATIVE_LOADED) return;
+ timerCloseSessionRestart();
+
Rectangle captureArea = new Rectangle(x, y, width, height);
List affectedScreenBounds = getSystemScreensBounds()
diff --git a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java
index 022ca5e7dbb41..d39f7943c29fb 100644
--- a/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java
+++ b/src/java.desktop/unix/classes/sun/awt/screencast/TokenStorage.java
@@ -324,6 +324,10 @@ static Set getTokens(List affectedScreenBounds) {
return tokenItem;
})
.filter(Objects::nonNull)
+ .sorted((t1, t2) -> //Token with more screens preferred
+ t2.allowedScreensBounds.size()
+ - t1.allowedScreensBounds.size()
+ )
.toList();
}
diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c
index 206a91132bc29..4c690db2e67f1 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c
@@ -604,6 +604,7 @@ GtkApi* gtk3_load(JNIEnv *env, const char* lib_name)
fp_g_string_new = dl_symbol("g_string_new");
fp_g_string_erase = dl_symbol("g_string_erase");
+ fp_g_string_set_size = dl_symbol("g_string_set_size");
fp_g_string_free = dl_symbol("g_string_free");
glib_version_2_68 = !fp_glib_check_version(2, 68, 0);
@@ -3110,6 +3111,7 @@ static void gtk3_init(GtkApi* gtk) {
gtk->g_string_new = fp_g_string_new;
gtk->g_string_erase = fp_g_string_erase;
+ gtk->g_string_set_size = fp_g_string_set_size;
gtk->g_string_free = fp_g_string_free;
gtk->g_string_replace = fp_g_string_replace;
gtk->g_string_printf = fp_g_string_printf;
diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h
index 0a3c8364e7973..b858d5e680802 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h
@@ -758,6 +758,9 @@ static GString *(*fp_g_string_erase)(GString *string,
gssize pos,
gssize len);
+static GString *(*fp_g_string_set_size)(GString* string,
+ gsize len);
+
static gchar *(*fp_g_string_free)(GString *string,
gboolean free_segment);
diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h
index 9c8c5743f7aac..1ddc239d9b23d 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h
@@ -716,6 +716,10 @@ typedef struct GtkApi {
gssize pos,
gssize len);
+ GString *(*g_string_set_size)(GString* string,
+ gsize len);
+
+
gchar *(*g_string_free)(GString *string,
gboolean free_segment);
diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
index a5443784e003a..132ccd0b7c44f 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_pipewire.c
@@ -43,6 +43,9 @@ int DEBUG_SCREENCAST_ENABLED = FALSE;
(*env)->ExceptionDescribe(env); \
}
+static volatile gboolean sessionClosed = TRUE;
+static GString *activeSessionToken;
+
struct ScreenSpace screenSpace = {0};
static struct PwLoopData pw = {0};
@@ -89,8 +92,8 @@ static void doCleanup() {
struct ScreenProps *screenProps = &screenSpace.screens[i];
if (screenProps->data) {
if (screenProps->data->stream) {
- fp_pw_thread_loop_lock(pw.loop);
fp_pw_stream_disconnect(screenProps->data->stream);
+ fp_pw_thread_loop_lock(pw.loop);
fp_pw_stream_destroy(screenProps->data->stream);
fp_pw_thread_loop_unlock(pw.loop);
screenProps->data->stream = NULL;
@@ -123,7 +126,11 @@ static void doCleanup() {
if (screenSpace.screens) {
free(screenSpace.screens);
screenSpace.screens = NULL;
+ screenSpace.screenCount = 0;
}
+
+ gtk->g_string_set_size(activeSessionToken, 0);
+ sessionClosed = TRUE;
}
/**
@@ -132,6 +139,24 @@ static void doCleanup() {
static gboolean initScreencast(const gchar *token,
GdkRectangle *affectedBounds,
gint affectedBoundsLength) {
+ gboolean isSameToken = !token
+ ? FALSE
+ : strcmp(token, activeSessionToken->str) == 0;
+
+ if (!sessionClosed) {
+ if (isSameToken) {
+ DEBUG_SCREENCAST("Reusing active session.\n", NULL);
+ return TRUE;
+ } else {
+ DEBUG_SCREENCAST(
+ "Active session has a different token |%s| -> |%s|,"
+ " closing current session.\n",
+ activeSessionToken->str, token
+ );
+ doCleanup();
+ }
+ }
+
fp_pw_init(NULL, NULL);
pw.pwFd = RESULT_ERROR;
@@ -145,6 +170,8 @@ static gboolean initScreencast(const gchar *token,
return FALSE;
}
+ gtk->g_string_printf(activeSessionToken, "%s", token);
+ sessionClosed = FALSE;
return TRUE;
}
@@ -386,8 +413,19 @@ static gboolean connectStream(int index) {
data->screenProps = &screenSpace.screens[index];
- data->hasFormat = FALSE;
+ if (!sessionClosed && data->stream) {
+ fp_pw_thread_loop_lock(pw.loop);
+ int result = fp_pw_stream_set_active(data->stream, TRUE);
+ fp_pw_thread_loop_unlock(pw.loop);
+
+ DEBUG_SCREEN_PREFIX(data->screenProps,
+ "stream %p: activate result |%i|\n",
+ data->stream, result);
+
+ return result == 0; // 0 - success
+ };
+ data->hasFormat = FALSE;
data->stream = fp_pw_stream_new(
pw.core,
@@ -505,60 +543,64 @@ static const struct pw_core_events coreEvents = {
* @return TRUE on success
*/
static gboolean doLoop(GdkRectangle requestedArea) {
- pw.loop = fp_pw_thread_loop_new("AWT Pipewire Thread", NULL);
-
- if (!pw.loop) {
- DEBUG_SCREENCAST("!!! Could not create a loop\n", NULL);
- doCleanup();
- return FALSE;
- }
-
- pw.context = fp_pw_context_new(
- fp_pw_thread_loop_get_loop(pw.loop),
- NULL,
- 0
- );
+ if (!pw.loop && !sessionClosed) {
+ pw.loop = fp_pw_thread_loop_new("AWT Pipewire Thread", NULL);
- if (!pw.context) {
- DEBUG_SCREENCAST("!!! Could not create a pipewire context\n", NULL);
- doCleanup();
- return FALSE;
- }
+ if (!pw.loop) {
+ DEBUG_SCREENCAST("!!! Could not create a loop\n", NULL);
+ doCleanup();
+ return FALSE;
+ }
- if (fp_pw_thread_loop_start(pw.loop) != 0) {
- DEBUG_SCREENCAST("!!! Could not start pipewire thread loop\n", NULL);
- doCleanup();
- return FALSE;
- }
+ pw.context = fp_pw_context_new(
+ fp_pw_thread_loop_get_loop(pw.loop),
+ NULL,
+ 0
+ );
- fp_pw_thread_loop_lock(pw.loop);
+ if (!pw.context) {
+ DEBUG_SCREENCAST("!!! Could not create a pipewire context\n", NULL);
+ doCleanup();
+ return FALSE;
+ }
- pw.core = fp_pw_context_connect_fd(
- pw.context,
- pw.pwFd,
- NULL,
- 0
- );
+ if (fp_pw_thread_loop_start(pw.loop) != 0) {
+ DEBUG_SCREENCAST("!!! Could not start pipewire thread loop\n", NULL);
+ doCleanup();
+ return FALSE;
+ }
- if (!pw.core) {
- DEBUG_SCREENCAST("!!! Could not create pipewire core\n", NULL);
- goto fail;
- }
+ fp_pw_thread_loop_lock(pw.loop);
- pw_core_add_listener(pw.core, &pw.coreListener, &coreEvents, NULL);
+ pw.core = fp_pw_context_connect_fd(
+ pw.context,
+ pw.pwFd,
+ NULL,
+ 0
+ );
- for (int i = 0; i < screenSpace.screenCount; ++i) {
- struct PwStreamData *data =
- (struct PwStreamData*) malloc(sizeof (struct PwStreamData));
- if (!data) {
- ERR("failed to allocate memory\n");
+ if (!pw.core) {
+ DEBUG_SCREENCAST("!!! Could not create pipewire core\n", NULL);
goto fail;
}
- memset(data, 0, sizeof (struct PwStreamData));
+ pw_core_add_listener(pw.core, &pw.coreListener, &coreEvents, NULL);
+ }
+ for (int i = 0; i < screenSpace.screenCount; ++i) {
struct ScreenProps *screen = &screenSpace.screens[i];
- screen->data = data;
+ if (!screen->data && !sessionClosed) {
+ struct PwStreamData *data =
+ (struct PwStreamData*) malloc(sizeof (struct PwStreamData));
+ if (!data) {
+ ERR("failed to allocate memory\n");
+ goto fail;
+ }
+
+ memset(data, 0, sizeof (struct PwStreamData));
+
+ screen->data = data;
+ }
DEBUG_SCREEN_PREFIX(screen, "@@@ adding screen %i\n", i);
if (checkScreen(i, requestedArea)) {
@@ -746,6 +788,8 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_screencast_ScreencastHelper_loadPipewire
return JNI_FALSE;
}
+ activeSessionToken = gtk->g_string_new("");
+
gboolean usable = initXdgDesktopPortal();
portalScreenCastCleanup();
return usable;
@@ -783,6 +827,17 @@ static void arrayToRectangles(JNIEnv *env,
(*env)->ReleaseIntArrayElements(env, boundsArray, body, 0);
}
+/*
+ * Class: sun_awt_screencast_ScreencastHelper
+ * Method: closeSession
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_sun_awt_screencast_ScreencastHelper_closeSession(JNIEnv *env, jclass cls) {
+ DEBUG_SCREENCAST("closing screencast session\n\n", NULL);
+ doCleanup();
+}
+
/*
* Class: sun_awt_screencast_ScreencastHelper
* Method: getRGBPixelsImpl
@@ -805,7 +860,7 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_getRGBPixelsImpl
boundsLen = (*env)->GetArrayLength(env, affectedScreensBoundsArray);
EXCEPTION_CHECK_DESCRIBE();
if (boundsLen % 4 != 0) {
- DEBUG_SCREENCAST("%s:%i incorrect array length\n", __FUNCTION__, __LINE__);
+ DEBUG_SCREENCAST("incorrect array length\n", NULL);
return RESULT_ERROR;
}
affectedBoundsLength = boundsLen / 4;
@@ -896,11 +951,12 @@ JNIEXPORT jint JNICALL Java_sun_awt_screencast_ScreencastHelper_getRGBPixelsImpl
fp_pw_thread_loop_lock(pw.loop);
fp_pw_stream_set_active(screenProps->data->stream, FALSE);
- fp_pw_stream_disconnect(screenProps->data->stream);
fp_pw_thread_loop_unlock(pw.loop);
+
+ screenProps->captureDataReady = FALSE;
}
}
- doCleanup();
+
releaseToken(env, jtoken, token);
return 0;
}
diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c
index e314359a32543..8590cf27da20f 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/screencast_portal.c
@@ -777,6 +777,10 @@ int portalScreenCastOpenPipewireRemote() {
}
void portalScreenCastCleanup() {
+ if (!portal) {
+ return;
+ }
+
if (portal->screenCastSessionHandle) {
gtk->g_dbus_connection_call_sync(
portal->connection,
@@ -796,9 +800,6 @@ void portalScreenCastCleanup() {
portal->screenCastSessionHandle = NULL;
}
- if (!portal) {
- return;
- }
if (portal->connection) {
gtk->g_object_unref(portal->connection);
portal->connection = NULL;
diff --git a/src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.java b/src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.java
index 6df7a2ae69750..d4c17f1cfdcf7 100644
--- a/src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.java
+++ b/src/java.instrument/share/classes/java/lang/instrument/ClassFileTransformer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -190,8 +190,6 @@ public interface ClassFileTransformer {
* if the input does not represent a well-formed class file
* @return a well-formed class file buffer (the result of the transform),
* or {@code null} if no transform is performed
- *
- * @revised 9
*/
default byte[]
transform( ClassLoader loader,
diff --git a/src/java.instrument/share/classes/java/lang/instrument/package-info.java b/src/java.instrument/share/classes/java/lang/instrument/package-info.java
index 4219d51f05f52..fe0ffc91a06f0 100644
--- a/src/java.instrument/share/classes/java/lang/instrument/package-info.java
+++ b/src/java.instrument/share/classes/java/lang/instrument/package-info.java
@@ -327,8 +327,6 @@
* transformed classes to read the unnamed module of both class loaders.
*
* @since 1.5
- * @revised 1.6
- * @revised 9
*/
package java.lang.instrument;
diff --git a/src/java.management/share/classes/java/lang/management/ThreadInfo.java b/src/java.management/share/classes/java/lang/management/ThreadInfo.java
index 9701e1ae0d80b..18c29d90e92bc 100644
--- a/src/java.management/share/classes/java/lang/management/ThreadInfo.java
+++ b/src/java.management/share/classes/java/lang/management/ThreadInfo.java
@@ -885,8 +885,6 @@ public String toString() {
* @return a {@code ThreadInfo} object represented
* by {@code cd} if {@code cd} is not {@code null};
* {@code null} otherwise.
- *
- * @revised 9
*/
public static ThreadInfo from(CompositeData cd) {
if (cd == null) {
diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java b/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java
index 80d788d937a88..33e4df43325c2 100644
--- a/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java
+++ b/src/java.naming/share/classes/com/sun/jndi/ldap/Connection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -280,79 +280,79 @@ private InetSocketAddress createInetSocketAddress(String host, int port) {
private Socket createSocket(String host, int port, String socketFactory,
int connectTimeout) throws Exception {
- Socket socket = null;
-
- if (socketFactory != null) {
+ SocketFactory factory = getSocketFactory(socketFactory);
+ assert factory != null;
+ Socket socket = createConnectionSocket(host, port, factory, connectTimeout);
- // create the factory
+ // the handshake for SSL connection with server and reset timeout for the socket
+ if (socket instanceof SSLSocket sslSocket) {
+ try {
+ initialSSLHandshake(sslSocket, connectTimeout);
+ } catch (Exception e) {
+ // 8314063 the socket is not closed after the failure of handshake
+ // close the socket while the error happened
+ closeOpenedSocket(socket);
+ throw e;
+ }
+ }
+ return socket;
+ }
+ private SocketFactory getSocketFactory(String socketFactoryName) throws Exception {
+ if (socketFactoryName == null) {
+ if (debug) {
+ System.err.println("Connection: using default SocketFactory");
+ }
+ return SocketFactory.getDefault();
+ } else {
+ if (debug) {
+ System.err.println("Connection: loading supplied SocketFactory: " + socketFactoryName);
+ }
@SuppressWarnings("unchecked")
Class extends SocketFactory> socketFactoryClass =
- (Class extends SocketFactory>)Obj.helper.loadClass(socketFactory);
+ (Class extends SocketFactory>) Obj.helper.loadClass(socketFactoryName);
Method getDefault =
- socketFactoryClass.getMethod("getDefault", new Class>[]{});
+ socketFactoryClass.getMethod("getDefault");
SocketFactory factory = (SocketFactory) getDefault.invoke(null, new Object[]{});
+ return factory;
+ }
+ }
- // create the socket
-
- if (connectTimeout > 0) {
-
- InetSocketAddress endpoint =
- createInetSocketAddress(host, port);
-
- // unconnected socket
- socket = factory.createSocket();
-
- if (debug) {
- System.err.println("Connection: creating socket with " +
- "a timeout using supplied socket factory");
- }
-
- // connected socket
- socket.connect(endpoint, connectTimeout);
- }
-
- // continue (but ignore connectTimeout)
- if (socket == null) {
- if (debug) {
- System.err.println("Connection: creating socket using " +
- "supplied socket factory");
- }
- // connected socket
- socket = factory.createSocket(host, port);
- }
- } else {
-
- if (connectTimeout > 0) {
-
- InetSocketAddress endpoint = createInetSocketAddress(host, port);
-
- socket = new Socket();
+ private Socket createConnectionSocket(String host, int port, SocketFactory factory,
+ int connectTimeout) throws Exception {
+ Socket socket = null;
- if (debug) {
- System.err.println("Connection: creating socket with " +
- "a timeout");
- }
- socket.connect(endpoint, connectTimeout);
+ if (connectTimeout > 0) {
+ // create unconnected socket and then connect it if timeout
+ // is supplied
+ InetSocketAddress endpoint =
+ createInetSocketAddress(host, port);
+ // unconnected socket
+ socket = factory.createSocket();
+ // connect socket with a timeout
+ socket.connect(endpoint, connectTimeout);
+ if (debug) {
+ System.err.println("Connection: creating socket with " +
+ "a connect timeout");
}
-
- // continue (but ignore connectTimeout)
-
- if (socket == null) {
- if (debug) {
- System.err.println("Connection: creating socket");
- }
- // connected socket
- socket = new Socket(host, port);
+ }
+ if (socket == null) {
+ // create connected socket
+ socket = factory.createSocket(host, port);
+ if (debug) {
+ System.err.println("Connection: creating connected socket with" +
+ " no connect timeout");
}
}
+ return socket;
+ }
+
+ // For LDAP connect timeouts on LDAP over SSL connections must treat
+ // the SSL handshake following socket connection as part of the timeout.
+ // So explicitly set a socket read timeout, trigger the SSL handshake,
+ // then reset the timeout.
+ private void initialSSLHandshake(SSLSocket sslSocket , int connectTimeout) throws Exception {
- // For LDAP connect timeouts on LDAP over SSL connections must treat
- // the SSL handshake following socket connection as part of the timeout.
- // So explicitly set a socket read timeout, trigger the SSL handshake,
- // then reset the timeout.
- if (socket instanceof SSLSocket) {
- SSLSocket sslSocket = (SSLSocket) socket;
if (!IS_HOSTNAME_VERIFICATION_DISABLED) {
SSLParameters param = sslSocket.getSSLParameters();
param.setEndpointIdentificationAlgorithm("LDAPS");
@@ -365,8 +365,6 @@ private Socket createSocket(String host, int port, String socketFactory,
sslSocket.startHandshake();
sslSocket.setSoTimeout(socketTimeout);
}
- }
- return socket;
}
////////////////////////////////////////////////////////////////////////////
@@ -643,14 +641,12 @@ void cleanup(Control[] reqCtls, boolean notifyParent) {
ldapUnbind(reqCtls);
}
} finally {
- try {
- outStream.flush();
- sock.close();
- unpauseReader();
- } catch (IOException ie) {
- if (debug)
- System.err.println("Connection: problem closing socket: " + ie);
- }
+
+ flushAndCloseOutputStream();
+ // 8313657 socket is not closed until GC is run
+ closeOpenedSocket(sock);
+ tryUnpauseReader();
+
if (!notifyParent) {
LdapRequest ldr = pendingRequests;
while (ldr != null) {
@@ -684,6 +680,44 @@ void cleanup(Control[] reqCtls, boolean notifyParent) {
}
}
+ // flush and close output stream
+ private void flushAndCloseOutputStream() {
+ try {
+ outStream.flush();
+ } catch (IOException ioEx) {
+ if (debug)
+ System.err.println("Connection.flushOutputStream: OutputStream flush problem " + ioEx);
+ }
+ try {
+ outStream.close();
+ } catch (IOException ioEx) {
+ if (debug)
+ System.err.println("Connection.closeOutputStream: OutputStream close problem " + ioEx);
+ }
+ }
+
+ // close socket
+ private void closeOpenedSocket(Socket socket) {
+ try {
+ if (socket != null && !socket.isClosed())
+ socket.close();
+ } catch (IOException ioEx) {
+ if (debug) {
+ System.err.println("Connection.closeConnectionSocket: Socket close problem: " + ioEx);
+ System.err.println("Socket isClosed: " + sock.isClosed());
+ }
+ }
+ }
+
+ // unpause reader
+ private void tryUnpauseReader() {
+ try {
+ unpauseReader();
+ } catch (IOException ioEx) {
+ if (debug)
+ System.err.println("Connection.tryUnpauseReader: unpauseReader problem " + ioEx);
+ }
+ }
// Assume everything is "quiet"
// "synchronize" might lead to deadlock so don't synchronize method
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java
index 6a58fe18fc9de..fe10ef58d0944 100644
--- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java
@@ -538,8 +538,8 @@ public int available() throws IOException {
if (available != 0) return available;
Iterator> iterator = currentListItr;
if (iterator != null && iterator.hasNext()) return 1;
- if (buffers.isEmpty()) return 0;
- return 1;
+ if (!buffers.isEmpty() && buffers.peek() != LAST_LIST ) return 1;
+ return available;
}
@Override
diff --git a/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c b/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c
index c591f04d30a8f..4e15ddd6e015d 100644
--- a/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c
+++ b/src/java.prefs/unix/native/libprefs/FileSystemPreferences.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -71,7 +71,7 @@ Java_java_util_prefs_FileSystemPreferences_lockFile0(JNIEnv *env,
jclass thisclass, jstring java_fname, jint permission, jboolean shared) {
const char *fname = JNU_GetStringPlatformChars(env, java_fname, NULL);
int fd, rc;
- int result[2];
+ int result[2] = {0, 0};
jintArray javaResult = NULL;
int old_umask;
FLOCK fl;
@@ -90,6 +90,7 @@ Java_java_util_prefs_FileSystemPreferences_lockFile0(JNIEnv *env,
if (shared == JNI_TRUE) {
fd = open(fname, O_RDONLY, 0);
+ result[1] = errno;
} else {
old_umask = umask(0);
fd = open(fname, O_WRONLY|O_CREAT, permission);
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
index 06d3939293898..b60694744a15c 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
@@ -4609,6 +4609,19 @@ void checkSwitchCaseStructure(List cases) {
if (!allUnderscore) {
log.error(c.labels.tail.head.pos(), Errors.FlowsThroughFromPattern);
}
+
+ boolean allPatternCaseLabels = c.labels.stream().allMatch(p -> p instanceof JCPatternCaseLabel);
+
+ if (allPatternCaseLabels) {
+ preview.checkSourceLevel(c.labels.tail.head.pos(), Feature.UNNAMED_VARIABLES);
+ }
+
+ for (JCCaseLabel label : c.labels.tail) {
+ if (label instanceof JCConstantCaseLabel) {
+ log.error(label.pos(), Errors.InvalidCaseLabelCombination);
+ break;
+ }
+ }
}
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
index 7780321e7a700..f6368c48b08c8 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
@@ -3310,6 +3310,8 @@ PatternResult analyzePattern(int lookahead) {
} else {
pendingResult = PatternResult.PATTERN;
}
+ } else if (typeDepth == 0 && parenDepth == 0 && (peekToken(lookahead, tk -> tk == ARROW || tk == COMMA))) {
+ return PatternResult.EXPRESSION;
}
break;
case UNDERSCORE:
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java
index de1fe22cd69e4..c3383f521902f 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyStore.java
@@ -1559,22 +1559,50 @@ private void storeCert(String alias, X509Certificate cert)
cert.getSerialNumber().toByteArray()));
attrList.add(new CK_ATTRIBUTE(CKA_VALUE, cert.getEncoded()));
- if (alias != null) {
- attrList.add(new CK_ATTRIBUTE(CKA_LABEL, alias));
- attrList.add(new CK_ATTRIBUTE(CKA_ID, alias));
- } else {
- // ibutton requires something to be set
- // - alias must be unique
- attrList.add(new CK_ATTRIBUTE(CKA_ID,
- getID(cert.getSubjectX500Principal().getName
- (X500Principal.CANONICAL), cert)));
- }
-
Session session = null;
try {
session = token.getOpSession();
+ long[] ch = findObjects(session,
+ attrList.toArray(new CK_ATTRIBUTE[attrList.size()]));
+ if (ch.length != 0) { // found a match
+ if (debug != null) {
+ String certInfo = (alias == null?
+ "CA cert " + cert.getSubjectX500Principal() :
+ "EE cert for alias " + alias);
+ debug.println("storeCert: found a match for " + certInfo);
+ }
+ if (alias != null) {
+ // Add the alias to the existing cert
+ CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
+ new CK_ATTRIBUTE(CKA_LABEL, alias),
+ new CK_ATTRIBUTE(CKA_ID, alias) };
+ token.p11.C_SetAttributeValue
+ (session.id(), ch[0], attrs);
+ if (debug != null) {
+ debug.println("storeCert: added alias: " + alias);
+ }
+ }
+ // done; no need to create the cert
+ return;
+ }
+ if (alias != null) {
+ attrList.add(new CK_ATTRIBUTE(CKA_LABEL, alias));
+ attrList.add(new CK_ATTRIBUTE(CKA_ID, alias));
+ } else {
+ // ibutton requires something to be set
+ // - alias must be unique
+ attrList.add(new CK_ATTRIBUTE(CKA_ID,
+ getID(cert.getSubjectX500Principal().getName
+ (X500Principal.CANONICAL), cert)));
+ }
token.p11.C_CreateObject(session.id(),
- attrList.toArray(new CK_ATTRIBUTE[attrList.size()]));
+ attrList.toArray(new CK_ATTRIBUTE[attrList.size()]));
+ if (debug != null) {
+ String certInfo = (alias == null?
+ "CA cert " + cert.getSubjectX500Principal() :
+ "EE cert for alias " + alias);
+ debug.println("storeCert: created " + certInfo);
+ }
} finally {
token.releaseSession(session);
}
@@ -1587,7 +1615,6 @@ private void storeChain(String alias, X509Certificate[] chain)
//
// end cert has CKA_LABEL and CKA_ID set to alias.
// other certs in chain have neither set.
-
storeCert(alias, chain[0]);
storeCaCerts(chain, 1);
}
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java
index 33621a060291b..3dfb2bc5d1013 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -83,6 +83,8 @@ static Address get_CDSFileMapRegion(Type FileMapHeader_type, Address header, int
}
private static void initialize(TypeDataBase db) {
+ vTableTypeMap = null; // force vTableTypeMap to get re-initialized later
+
Type FileMapInfo_type = db.lookupType("FileMapInfo");
Type FileMapHeader_type = db.lookupType("FileMapHeader");
Type CDSFileMapRegion_type = db.lookupType("CDSFileMapRegion");
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/StackValueCollection.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/StackValueCollection.java
index 7769bb1669b27..566b527b88aaf 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/StackValueCollection.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/StackValueCollection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,8 +47,6 @@ public class StackValueCollection {
public char charAt(int slot) { return (char) get(slot).getInteger(); }
public short shortAt(int slot) { return (short) get(slot).getInteger(); }
public int intAt(int slot) { return (int) get(slot).getInteger(); }
- public long longAt(int slot) { return VM.getVM().buildLongFromIntsPD((int) get(slot).getInteger(),
- (int) get(slot+1).getInteger()); }
public OopHandle oopHandleAt(int slot) {
StackValue sv = get(slot);
@@ -59,5 +57,4 @@ public OopHandle oopHandleAt(int slot) {
}
public float floatAt(int slot) { return Float.intBitsToFloat(intAt(slot)); }
- public double doubleAt(int slot) { return Double.longBitsToDouble(longAt(slot)); }
}
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VFrame.java
index f4d7827254c56..83b38654d9ba4 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VFrame.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VFrame.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
import java.io.*;
import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.utilities.*;
+import sun.jvm.hotspot.debugger.Address;
public class VFrame {
protected Frame fr;
@@ -145,7 +146,16 @@ public JavaVFrame javaSender() {
if (f.isJavaFrame()) {
return (JavaVFrame) f;
}
+ Address oldSP = f.getFrame().getSP();
f = f.sender(imprecise);
+ if (f != null) {
+ // Make sure the sender frame is above the current frame, not below
+ Address newSP = f.getFrame().getSP();
+ if (oldSP.greaterThanOrEqual(newSP)) {
+ String errString = "newSP(" + newSP + ") is not above oldSP(" + oldSP + ")";
+ throw new RuntimeException(errString);
+ }
+ }
}
return null;
}
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java
index b1b83ad355c4c..472b63814ad47 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -728,16 +728,6 @@ public int buildIntFromShorts(short low, short high) {
return (((int) high) << 16) | (((int) low) & 0xFFFF);
}
- /** Utility routine for building a long from two "unsigned" 32-bit
- ints in platform-dependent order */
- public long buildLongFromIntsPD(int oneHalf, int otherHalf) {
- if (isBigEndian) {
- return (((long) otherHalf) << 32) | (((long) oneHalf) & 0x00000000FFFFFFFFL);
- } else{
- return (((long) oneHalf) << 32) | (((long) otherHalf) & 0x00000000FFFFFFFFL);
- }
- }
-
public TypeDataBase getTypeDataBase() {
return db;
}
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java
index 6db450727d1da..90d070112db1e 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2019, Red Hat Inc.
- * Copyright (c) 2021, 2022, Huawei Technologies Co., Ltd. All rights reserved.
+ * Copyright (c) 2021, 2023, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -71,7 +71,7 @@ public class RISCV64Frame extends Frame {
// Native frames
private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2;
- private static VMReg fp = new VMReg(8);
+ private static VMReg fp = new VMReg(8 << 1);
static {
VM.registerVMInitializedObserver(new Observer() {
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java
index d29e3a68811b7..c586a20e866a4 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java
@@ -86,10 +86,8 @@ public void run() {
printValMB("MetaspaceSize = ", getFlagValue("MetaspaceSize", flagMap));
printValMB("CompressedClassSpaceSize = ", getFlagValue("CompressedClassSpaceSize", flagMap));
printValMB("MaxMetaspaceSize = ", getFlagValue("MaxMetaspaceSize", flagMap));
- if (heap instanceof ShenandoahHeap) {
- printValMB("ShenandoahRegionSize = ", ShenandoahHeapRegion.regionSizeBytes());
- } else {
- printValMB("G1HeapRegionSize = ", HeapRegion.grainBytes());
+ if (heap instanceof G1CollectedHeap) {
+ printValMB("G1HeapRegionSize = ", HeapRegion.grainBytes());
}
System.out.println();
@@ -138,6 +136,7 @@ public void run() {
long num_regions = sh.numOfRegions();
System.out.println("Shenandoah Heap:");
System.out.println(" regions = " + num_regions);
+ printValMB("region size = ", ShenandoahHeapRegion.regionSizeBytes());
printValMB("capacity = ", num_regions * ShenandoahHeapRegion.regionSizeBytes());
printValMB("used = ", sh.used());
printValMB("committed = ", sh.committed());
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MonitorCacheDumpPanel.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MonitorCacheDumpPanel.java
index 9f6ec170d86e5..ed3ccb2c49604 100644
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MonitorCacheDumpPanel.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/MonitorCacheDumpPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -67,8 +67,12 @@ private static void dumpMonitor(PrintStream tty, ObjectMonitor mon, boolean raw)
tty.println();
tty.println(" _header: 0x" + Long.toHexString(mon.header().value()));
OopHandle obj = mon.object();
- Oop oop = heap.newOop(obj);
- tty.println(" _object: " + obj + ", a " + oop.getKlass().getName().asString());
+ if (obj == null) {
+ tty.println(" _object: null");
+ } else {
+ Oop oop = heap.newOop(obj);
+ tty.println(" _object: " + obj + ", a " + oop.getKlass().getName().asString());
+ }
Address owner = mon.owner();
tty.println(" _owner: " + owner);
if (!raw && owner != null) {
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java
index 59f9cf1b12919..f50207ac13a05 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java
@@ -243,7 +243,7 @@ boolean methodIsIgnoredBySecurityStackWalk(HotSpotResolvedJavaMethodImpl method)
* @param accessingClass the class loader of this class is used for resolution. Must not be null.
* @param resolve force resolution to a {@link ResolvedJavaType}. If true, this method will
* either return a {@link ResolvedJavaType} or throw an exception
- * @return the type for {@code name} or 0 if resolution failed and {@code resolve == false}
+ * @return the type for {@code name} or {@code null} if resolution failed and {@code resolve == false}
* @throws NoClassDefFoundError if {@code resolve == true} and the resolution failed
*/
HotSpotResolvedJavaType lookupType(String name, HotSpotResolvedObjectTypeImpl accessingClass, boolean resolve) throws NoClassDefFoundError {
@@ -435,6 +435,19 @@ int decodeIndyIndexToCPIndex(HotSpotConstantPool constantPool, int encoded_indy_
private native int decodeIndyIndexToCPIndex(HotSpotConstantPool constantPool, long constantPoolPointer, int encoded_indy_index, boolean resolve);
+ /**
+ * Converts the {@code rawIndex} operand of a rewritten getfield/putfield/getstatic/putstatic instruction
+ * to an index directly into {@code constantPool}.
+ *
+ * @throws IllegalArgumentException if {@code rawIndex} is out of range.
+ * @return {@code JVM_CONSTANT_FieldRef} constant pool entry index for the invokedynamic
+ */
+ int decodeFieldIndexToCPIndex(HotSpotConstantPool constantPool, int rawIndex) {
+ return decodeFieldIndexToCPIndex(constantPool, constantPool.getConstantPoolPointer(), rawIndex);
+ }
+
+ private native int decodeFieldIndexToCPIndex(HotSpotConstantPool constantPool, long constantPoolPointer, int rawIndex);
+
/**
* Resolves the details for invoking the bootstrap method associated with the
* {@code CONSTANT_Dynamic_info} or @{code CONSTANT_InvokeDynamic_info} entry at {@code cpi} in
@@ -507,8 +520,8 @@ HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool
private native HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool, long constantPoolPointer, int cpi) throws LinkageError;
/**
- * Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry for at index
- * {@code cpi} in {@code constantPool}. For some opcodes, checks are performed that require the
+ * Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry denoted by
+ * {@code rawIndex}. For some opcodes, checks are performed that require the
* {@code method} that contains {@code opcode} to be specified. The values returned in
* {@code info} are:
*
@@ -520,19 +533,18 @@ HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool
* ]
*
*
- * The behavior of this method is undefined if {@code cpi} does not denote a
- * {@code JVM_CONSTANT_Field} entry.
+ * The behavior of this method is undefined if {@code rawIndex} is invalid.
*
* @param info an array in which the details of the field are returned
* @return the type defining the field if resolution is successful, null otherwise
*/
- HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int cpi, HotSpotResolvedJavaMethodImpl method, byte opcode, int[] info) {
+ HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int rawIndex, HotSpotResolvedJavaMethodImpl method, byte opcode, int[] info) {
long methodPointer = method != null ? method.getMethodPointer() : 0L;
- return resolveFieldInPool(constantPool, constantPool.getConstantPoolPointer(), cpi, method, methodPointer, opcode, info);
+ return resolveFieldInPool(constantPool, constantPool.getConstantPoolPointer(), rawIndex, method, methodPointer, opcode, info);
}
private native HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, long constantPoolPointer,
- int cpi, HotSpotResolvedJavaMethodImpl method, long methodPointer, byte opcode, int[] info);
+ int rawIndex, HotSpotResolvedJavaMethodImpl method, long methodPointer, byte opcode, int[] info);
/**
* Converts {@code cpci} from an index into the cache for {@code constantPool} to an index
@@ -548,14 +560,17 @@ int constantPoolRemapInstructionOperandFromCache(HotSpotConstantPool constantPoo
private native int constantPoolRemapInstructionOperandFromCache(HotSpotConstantPool constantPool, long constantPoolPointer, int cpci);
/**
- * Gets the appendix object (if any) associated with the entry at index {@code cpi} in
- * {@code constantPool}.
+ * Gets the appendix object (if any) associated with the entry identified by {@code which}.
+ *
+ * @param which if negative, is treated as an encoded indy index for INVOKEDYNAMIC;
+ * Otherwise, it's treated as a constant pool cache index (returned by HotSpotConstantPool::rawIndexToConstantPoolCacheIndex)
+ * for INVOKE{VIRTUAL,SPECIAL,STATIC,INTERFACE}.
*/
- HotSpotObjectConstantImpl lookupAppendixInPool(HotSpotConstantPool constantPool, int cpi) {
- return lookupAppendixInPool(constantPool, constantPool.getConstantPoolPointer(), cpi);
+ HotSpotObjectConstantImpl lookupAppendixInPool(HotSpotConstantPool constantPool, int which) {
+ return lookupAppendixInPool(constantPool, constantPool.getConstantPoolPointer(), which);
}
- private native HotSpotObjectConstantImpl lookupAppendixInPool(HotSpotConstantPool constantPool, long constantPoolPointer, int cpi);
+ private native HotSpotObjectConstantImpl lookupAppendixInPool(HotSpotConstantPool constantPool, long constantPoolPointer, int which);
/**
* Installs the result of a compilation into the code cache.
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPool.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPool.java
index 390becd4179f3..d4bb97f03c4cc 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPool.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPool.java
@@ -47,6 +47,19 @@
/**
* Implementation of {@link ConstantPool} for HotSpot.
+ *
+ * The following convention is used in the jdk.vm.ci.hotspot package when accessing the ConstantPool with an index:
+ *
+ *
rawIndex - Index in the bytecode stream after the opcode (could be rewritten for some opcodes)
+ *
cpi - The constant pool index (as specified in JVM Spec)
+ *
cpci - The constant pool cache index, used only by the four bytecodes INVOKE{VIRTUAL,SPECIAL,STATIC,INTERFACE}.
+ * It's the same as {@code rawIndex + HotSpotVMConfig::constantPoolCpCacheIndexTag}.
+ *
which - May be either a {@code rawIndex} or a {@code cpci}.
+ *
+ *
+ * Note that {@code cpci} and {@code which} are used only in the HotSpot-specific implementation. They
+ * are not used by the public interface in jdk.vm.ci.meta.*.
+ * After JDK-8301993, all uses of {@code cpci} and {@code which} will be replaced with {@code rawIndex}.
*/
public final class HotSpotConstantPool implements ConstantPool, MetaspaceHandleObject {
@@ -252,29 +265,15 @@ private HotSpotResolvedObjectType getHolder() {
* @return constant pool cache index
*/
private static int rawIndexToConstantPoolCacheIndex(int rawIndex, int opcode) {
- int index;
- if (opcode == Bytecodes.INVOKEDYNAMIC) {
- index = rawIndex;
- // See: ConstantPool::is_invokedynamic_index
- if (index >= 0) {
- throw new IllegalArgumentException("not an invokedynamic constant pool index " + index);
- }
+ if (opcode == Bytecodes.INVOKEINTERFACE ||
+ opcode == Bytecodes.INVOKEVIRTUAL ||
+ opcode == Bytecodes.INVOKESPECIAL ||
+ opcode == Bytecodes.INVOKESTATIC) {
+ return rawIndex + config().constantPoolCpCacheIndexTag;
} else {
- if (opcode == Bytecodes.GETFIELD ||
- opcode == Bytecodes.PUTFIELD ||
- opcode == Bytecodes.GETSTATIC ||
- opcode == Bytecodes.PUTSTATIC ||
- opcode == Bytecodes.INVOKEINTERFACE ||
- opcode == Bytecodes.INVOKEVIRTUAL ||
- opcode == Bytecodes.INVOKESPECIAL ||
- opcode == Bytecodes.INVOKESTATIC) {
- index = rawIndex + config().constantPoolCpCacheIndexTag;
- } else {
- throw new IllegalArgumentException("unexpected opcode " + opcode);
-
- }
+ // Only the above 4 bytecodes use ConstantPoolCacheIndex
+ throw new IllegalArgumentException("unexpected opcode " + opcode);
}
- return index;
}
/**
@@ -585,8 +584,8 @@ private static String argumentAsString(JavaConstant arg) {
}
@Override
- public BootstrapMethodInvocation lookupBootstrapMethodInvocation(int rawCpi, int opcode) {
- int cpi = opcode == -1 ? rawCpi : rawIndexToConstantPoolIndex(rawCpi, opcode);
+ public BootstrapMethodInvocation lookupBootstrapMethodInvocation(int index, int opcode) {
+ int cpi = opcode == -1 ? index : indyIndexConstantPoolIndex(index, opcode);
final JvmConstant tag = getTagAt(cpi);
switch (tag.name) {
case "InvokeDynamic":
@@ -689,13 +688,19 @@ public Signature lookupSignature(int cpi) {
}
@Override
- public JavaConstant lookupAppendix(int cpi, int opcode) {
+ public JavaConstant lookupAppendix(int rawIndex, int opcode) {
if (!Bytecodes.isInvoke(opcode)) {
- throw new IllegalArgumentException("expected an invoke bytecode at " + cpi + ", got " + opcode);
+ throw new IllegalArgumentException("expected an invoke bytecode for " + rawIndex + ", got " + opcode);
}
- final int index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
- return compilerToVM().lookupAppendixInPool(this, index);
+ if (opcode == Bytecodes.INVOKEDYNAMIC) {
+ if (!isInvokedynamicIndex(rawIndex)) {
+ throw new IllegalArgumentException("expected a raw index for INVOKEDYNAMIC but got " + rawIndex);
+ }
+ return compilerToVM().lookupAppendixInPool(this, rawIndex);
+ } else {
+ return compilerToVM().lookupAppendixInPool(this, rawIndexToConstantPoolCacheIndex(rawIndex, opcode));
+ }
}
/**
@@ -713,19 +718,19 @@ private static JavaType getJavaType(final Object type) {
}
@Override
- public JavaMethod lookupMethod(int cpi, int opcode, ResolvedJavaMethod caller) {
- final int index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
- final HotSpotResolvedJavaMethod method = compilerToVM().lookupMethodInPool(this, index, (byte) opcode, (HotSpotResolvedJavaMethodImpl) caller);
+ public JavaMethod lookupMethod(int rawIndex, int opcode, ResolvedJavaMethod caller) {
+ final int cpci = rawIndexToConstantPoolCacheIndex(rawIndex, opcode);
+ final HotSpotResolvedJavaMethod method = compilerToVM().lookupMethodInPool(this, cpci, (byte) opcode, (HotSpotResolvedJavaMethodImpl) caller);
if (method != null) {
return method;
} else {
// Get the method's name and signature.
- String name = getNameOf(index, opcode);
- HotSpotSignature signature = new HotSpotSignature(runtime(), getSignatureOf(index, opcode));
+ String name = getNameOf(cpci, opcode);
+ HotSpotSignature signature = new HotSpotSignature(runtime(), getSignatureOf(cpci, opcode));
if (opcode == Bytecodes.INVOKEDYNAMIC) {
return new UnresolvedJavaMethod(name, signature, runtime().getMethodHandleClass());
} else {
- final int klassIndex = getKlassRefIndexAt(index, opcode);
+ final int klassIndex = getKlassRefIndexAt(cpci, opcode);
final Object type = compilerToVM().lookupKlassInPool(this, klassIndex);
return new UnresolvedJavaMethod(name, signature, getJavaType(type));
}
@@ -748,8 +753,8 @@ public JavaType lookupType(int cpi, int opcode) {
}
@Override
- public JavaType lookupReferencedType(int cpi, int opcode) {
- int index;
+ public JavaType lookupReferencedType(int rawIndex, int opcode) {
+ int cpi;
switch (opcode) {
case Bytecodes.CHECKCAST:
case Bytecodes.INSTANCEOF:
@@ -759,43 +764,44 @@ public JavaType lookupReferencedType(int cpi, int opcode) {
case Bytecodes.LDC:
case Bytecodes.LDC_W:
case Bytecodes.LDC2_W:
- index = cpi;
+ cpi = rawIndex;
break;
case Bytecodes.GETSTATIC:
case Bytecodes.PUTSTATIC:
case Bytecodes.GETFIELD:
case Bytecodes.PUTFIELD:
+ cpi = getKlassRefIndexAt(rawIndex, opcode);
+ break;
case Bytecodes.INVOKEVIRTUAL:
case Bytecodes.INVOKESPECIAL:
case Bytecodes.INVOKESTATIC:
case Bytecodes.INVOKEINTERFACE: {
- index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
- index = getKlassRefIndexAt(index, opcode);
+ int cpci = rawIndexToConstantPoolCacheIndex(rawIndex, opcode);
+ cpi = getKlassRefIndexAt(cpci, opcode);
break;
}
default:
throw JVMCIError.shouldNotReachHere("Unexpected opcode " + opcode);
}
- final Object type = compilerToVM().lookupKlassInPool(this, index);
+ final Object type = compilerToVM().lookupKlassInPool(this, cpi);
return getJavaType(type);
}
@Override
- public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) {
- final int index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
- final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index, opcode);
+ public JavaField lookupField(int rawIndex, ResolvedJavaMethod method, int opcode) {
+ final int nameAndTypeIndex = getNameAndTypeRefIndexAt(rawIndex, opcode);
final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex);
String typeName = lookupUtf8(typeIndex);
JavaType type = runtime().lookupType(typeName, getHolder(), false);
- final int holderIndex = getKlassRefIndexAt(index, opcode);
+ final int holderIndex = getKlassRefIndexAt(rawIndex, opcode);
JavaType fieldHolder = lookupType(holderIndex, opcode);
if (fieldHolder instanceof HotSpotResolvedObjectTypeImpl) {
int[] info = new int[4];
HotSpotResolvedObjectTypeImpl resolvedHolder;
try {
- resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
+ resolvedHolder = compilerToVM().resolveFieldInPool(this, rawIndex, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
} catch (Throwable t) {
/*
* If there was an exception resolving the field we give up and return an unresolved
@@ -815,37 +821,34 @@ public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) {
}
/**
- * Converts a raw index from the bytecodes to a constant pool index (not a cache index).
+ * Converts a raw index for the INVOKEDYNAMIC bytecode to a constant pool index.
*
* @param rawIndex index from the bytecode
*
- * @param opcode bytecode to convert the index for
+ * @param opcode bytecode to convert the index for. Must be INVOKEDYNAMIC.
*
* @return constant pool index
*/
- public int rawIndexToConstantPoolIndex(int rawIndex, int opcode) {
+ private int indyIndexConstantPoolIndex(int rawIndex, int opcode) {
if (isInvokedynamicIndex(rawIndex)) {
if (opcode != Bytecodes.INVOKEDYNAMIC) {
throw new IllegalArgumentException("expected INVOKEDYNAMIC at " + rawIndex + ", got " + opcode);
}
return compilerToVM().decodeIndyIndexToCPIndex(this, rawIndex, false);
+ } else {
+ throw new IllegalArgumentException("expected a raw index for INVOKEDYNAMIC but got " + rawIndex);
}
- if (opcode == Bytecodes.INVOKEDYNAMIC) {
- throw new IllegalArgumentException("unexpected INVOKEDYNAMIC at " + rawIndex);
- }
- int index = rawIndexToConstantPoolCacheIndex(rawIndex, opcode);
- return compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
}
@Override
- public void loadReferencedType(int cpi, int opcode) {
- loadReferencedType(cpi, opcode, true /* initialize */);
+ public void loadReferencedType(int rawIndex, int opcode) {
+ loadReferencedType(rawIndex, opcode, true /* initialize */);
}
@Override
@SuppressWarnings("fallthrough")
- public void loadReferencedType(int cpi, int opcode, boolean initialize) {
- int index;
+ public void loadReferencedType(int rawIndex, int opcode, boolean initialize) {
+ int cpi;
switch (opcode) {
case Bytecodes.CHECKCAST:
case Bytecodes.INSTANCEOF:
@@ -855,57 +858,59 @@ public void loadReferencedType(int cpi, int opcode, boolean initialize) {
case Bytecodes.LDC:
case Bytecodes.LDC_W:
case Bytecodes.LDC2_W:
- index = cpi;
+ cpi = rawIndex;
break;
case Bytecodes.INVOKEDYNAMIC: {
// invokedynamic indices are different from constant pool cache indices
- if (!isInvokedynamicIndex(cpi)) {
- throw new IllegalArgumentException("must use invokedynamic index but got " + cpi);
+ if (!isInvokedynamicIndex(rawIndex)) {
+ throw new IllegalArgumentException("must use invokedynamic index but got " + rawIndex);
}
- index = compilerToVM().decodeIndyIndexToCPIndex(this, cpi, true);
+ cpi = compilerToVM().decodeIndyIndexToCPIndex(this, rawIndex, true);
break;
}
case Bytecodes.GETSTATIC:
case Bytecodes.PUTSTATIC:
case Bytecodes.GETFIELD:
case Bytecodes.PUTFIELD:
+ cpi = compilerToVM().decodeFieldIndexToCPIndex(this, rawIndex);
+ break;
case Bytecodes.INVOKEVIRTUAL:
case Bytecodes.INVOKESPECIAL:
case Bytecodes.INVOKESTATIC:
case Bytecodes.INVOKEINTERFACE: {
// invoke and field instructions point to a constant pool cache entry.
- index = rawIndexToConstantPoolCacheIndex(cpi, opcode);
- index = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, index);
+ int cpci = rawIndexToConstantPoolCacheIndex(rawIndex, opcode);
+ cpi = compilerToVM().constantPoolRemapInstructionOperandFromCache(this, cpci);
break;
}
default:
throw JVMCIError.shouldNotReachHere("Unexpected opcode " + opcode);
}
- final JvmConstant tag = getTagAt(index);
+ final JvmConstant tag = getTagAt(cpi);
if (tag == null) {
- assert getTagAt(index - 1) == constants.jvmDouble || getTagAt(index - 1) == constants.jvmLong;
+ assert getTagAt(cpi - 1) == constants.jvmDouble || getTagAt(cpi - 1) == constants.jvmLong;
return;
}
switch (tag.name) {
case "Methodref":
case "Fieldref":
case "InterfaceMethodref":
- index = getUncachedKlassRefIndexAt(index);
+ cpi = getUncachedKlassRefIndexAt(cpi);
// Read the tag only once because it could change between multiple reads.
- final JvmConstant klassTag = getTagAt(index);
+ final JvmConstant klassTag = getTagAt(cpi);
assert klassTag == constants.jvmClass || klassTag == constants.jvmUnresolvedClass || klassTag == constants.jvmUnresolvedClassInError : klassTag;
// fall through
case "Class":
case "UnresolvedClass":
case "UnresolvedClassInError":
- final HotSpotResolvedObjectTypeImpl type = compilerToVM().resolveTypeInPool(this, index);
+ final HotSpotResolvedObjectTypeImpl type = compilerToVM().resolveTypeInPool(this, cpi);
if (initialize && !type.isPrimitive() && !type.isArray()) {
type.ensureInitialized();
}
if (tag == constants.jvmMethodref) {
if (Bytecodes.isInvokeHandleAlias(opcode) && isSignaturePolymorphicHolder(type)) {
- final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(cpi, opcode);
+ final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(rawIndex, opcode);
checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), constants.jvmMethodref);
compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
}
@@ -943,26 +948,6 @@ static boolean isSignaturePolymorphicHolder(final ResolvedJavaType type) {
return false;
}
- /**
- * Check for a resolved dynamic adapter method at the specified index, resulting from either a
- * resolved invokedynamic or invokevirtual on a signature polymorphic MethodHandle method
- * (HotSpot invokehandle).
- *
- * @param cpi the constant pool index
- * @param opcode the opcode of the instruction for which the lookup is being performed
- * @return {@code true} if a signature polymorphic method reference was found, otherwise
- * {@code false}
- */
- public boolean isResolvedDynamicInvoke(int cpi, int opcode) {
- if (Bytecodes.isInvokeHandleAlias(opcode)) {
- final int methodRefCacheIndex = rawIndexToConstantPoolCacheIndex(cpi, opcode);
- checkTag(compilerToVM().constantPoolRemapInstructionOperandFromCache(this, methodRefCacheIndex), constants.jvmMethodref);
- int op = compilerToVM().isResolvedInvokeHandleInPool(this, methodRefCacheIndex);
- return op == opcode;
- }
- return false;
- }
-
public String getSourceFileName() {
final int sourceFileNameIndex = UNSAFE.getChar(getConstantPoolPointer() + config().constantPoolSourceFileNameIndexOffset);
if (sourceFileNameIndex == 0) {
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java
index 647779d579480..0ee69f135c942 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java
@@ -184,7 +184,8 @@ void printConfig(HotSpotJVMCIRuntime runtime) {
printConfigLine(runtime, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
}
for (VMIntrinsicMethod e : getIntrinsics()) {
- printConfigLine(runtime, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor);
+ printConfigLine(runtime, "[vmconfig:intrinsic] %d = (available:%b c1Supported:%b c2Supported:%b) %s.%s %s%n",
+ e.id, e.isAvailable, e.c1Supported, e.c2Supported, e.declaringClass, e.name, e.descriptor);
}
}
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/VMIntrinsicMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/VMIntrinsicMethod.java
index 2de959151b641..d43c9dcca72ee 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/VMIntrinsicMethod.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/VMIntrinsicMethod.java
@@ -54,12 +54,32 @@ public final class VMIntrinsicMethod {
*/
public final int id;
+ /**
+ * This value reflects the `ControlIntrinsic`, `DisableIntrinsic` and `UseXXXIntrinsic` VM flags
+ * as well as other factors such as the current CPU.
+ */
+ public final boolean isAvailable;
+
+ /**
+ * True if this intrinsic is supported by C1.
+ */
+ public final boolean c1Supported;
+
+ /**
+ * True if this intrinsic is supported by C2.
+ */
+ public final boolean c2Supported;
+
@VMEntryPoint
- VMIntrinsicMethod(String declaringClass, String name, String descriptor, int id) {
+ VMIntrinsicMethod(String declaringClass, String name, String descriptor, int id,
+ boolean isAvailable, boolean c1Supported, boolean c2Supported) {
this.declaringClass = declaringClass;
this.name = name;
this.descriptor = descriptor;
this.id = id;
+ this.isAvailable = isAvailable;
+ this.c1Supported = c1Supported;
+ this.c2Supported = c2Supported;
}
@Override
@@ -69,7 +89,10 @@ public boolean equals(Object obj) {
if (that.id == this.id) {
assert that.name.equals(this.name) &&
that.declaringClass.equals(this.declaringClass) &&
- that.descriptor.equals(this.descriptor);
+ that.descriptor.equals(this.descriptor) &&
+ that.isAvailable == this.isAvailable &&
+ that.c1Supported == this.c1Supported &&
+ that.c2Supported == this.c2Supported;
return true;
}
}
@@ -83,6 +106,7 @@ public int hashCode() {
@Override
public String toString() {
- return String.format("IntrinsicMethod[declaringClass=%s, name=%s, descriptor=%s, id=%d]", declaringClass, name, descriptor, id);
+ return String.format("IntrinsicMethod[declaringClass=%s, name=%s, descriptor=%s, id=%d, isAvailable=%b, c1Supported=%b, c2Supported=%b]",
+ declaringClass, name, descriptor, id, isAvailable, c1Supported, c2Supported);
}
}
diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ConstantPool.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ConstantPool.java
index 7c7cfb5687f1b..5a53de47f6aeb 100644
--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ConstantPool.java
+++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ConstantPool.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,14 @@
* Represents the runtime representation of the constant pool that is used by the compiler when
* parsing bytecode. Provides methods to look up a constant pool entry without performing
* resolution. They are used during compilation.
+ *
+ * The following convention is used when accessing the ConstantPool with an index:
+ *
+ *
rawIndex - index in the bytecode stream after the opcode (could be rewritten for some opcodes)
+ *
cpi - the constant pool index (as specified in JVM Spec)
+ *
+ *
+ * Some of the methods are currently not using the convention correctly. That will be addressed in JDK-8314172.
*/
public interface ConstantPool {
@@ -44,53 +52,50 @@ public interface ConstantPool {
* initialized. This can be used to compile time resolve a type. It works for field, method, or
* type constant pool entries.
*
- * @param cpi the index of the constant pool entry that references the type
+ * @param rawIndex index in the bytecode stream after the {@code opcode} (could be rewritten for some opcodes)
* @param opcode the opcode of the instruction that references the type
*/
- void loadReferencedType(int cpi, int opcode);
+ void loadReferencedType(int rawIndex, int opcode);
/**
* Ensures that the type referenced by the specified constant pool entry is loaded. This can be
* used to compile time resolve a type. It works for field, method, or type constant pool
* entries.
*
- * @param cpi the index of the constant pool entry that references the type
+ * @param rawIndex index in the bytecode stream after the {@code opcode} (could be rewritten for some opcodes)
* @param opcode the opcode of the instruction that references the type
* @param initialize if {@code true}, the referenced type is either guaranteed to be initialized
* upon return or an initialization exception is thrown
*/
- default void loadReferencedType(int cpi, int opcode, boolean initialize) {
+ default void loadReferencedType(int rawIndex, int opcode, boolean initialize) {
if (initialize) {
- loadReferencedType(cpi, opcode);
+ loadReferencedType(rawIndex, opcode);
} else {
throw new UnsupportedOperationException();
}
}
/**
- * Looks up the type referenced by the constant pool entry at {@code cpi} as referenced by the
- * {@code opcode} bytecode instruction.
+ * Looks up the type referenced by the {@code rawIndex}.
*
- * @param cpi the index of a constant pool entry that references a type
- * @param opcode the opcode of the instruction with {@code cpi} as an operand
+ * @param rawIndex index in the bytecode stream after the {@code opcode} (could be rewritten for some opcodes)
+ * @param opcode the opcode of the instruction with {@code rawIndex} as an operand
* @return a reference to the compiler interface type
*/
- JavaType lookupReferencedType(int cpi, int opcode);
+ JavaType lookupReferencedType(int rawIndex, int opcode);
/**
- * Looks up a reference to a field. If {@code opcode} is non-negative, then resolution checks
+ * Looks up a reference to a field. Resolution checks
* specific to the bytecode it denotes are performed if the field is already resolved. Checks
* for some bytecodes require the method that contains the bytecode to be specified. Should any
* of these checks fail, an unresolved field reference is returned.
*
- * @param cpi the constant pool index
- * @param opcode the opcode of the instruction for which the lookup is being performed or
- * {@code -1}
+ * @param rawIndex rewritten index in the bytecode stream after the {@code opcode}
+ * @param opcode the opcode of the instruction for which the lookup is being performed
* @param method the method for which the lookup is being performed
- * @return a reference to the field at {@code cpi} in this pool
- * @throws ClassFormatError if the entry at {@code cpi} is not a field
+ * @return a reference to the field at {@code rawIndex} in this pool
*/
- JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode);
+ JavaField lookupField(int rawIndex, ResolvedJavaMethod method, int opcode);
/**
* Looks up a reference to a method. If {@code opcode} is non-negative, then resolution checks
@@ -167,19 +172,21 @@ interface BootstrapMethodInvocation {
/**
* Gets the details for invoking a bootstrap method associated with the
- * {@code CONSTANT_Dynamic_info} or {@code CONSTANT_InvokeDynamic_info} pool entry {@code cpi}
+ * {@code CONSTANT_Dynamic_info} or {@code CONSTANT_InvokeDynamic_info} pool entry
* in the constant pool.
*
- * @param cpi a constant pool index
- * @param opcode the opcode of the instruction that has {@code cpi} as an operand or -1 if
- * {@code cpi} was not decoded from an instruction stream
- * @return the bootstrap method invocation details or {@code null} if the entry at {@code cpi}
+ * @param index if {@code opcode} is -1, {@code index} is a constant pool index. Otherwise {@code opcode}
+ * must be {@code Bytecodes.INVOKEDYNAMIC}, and {@code index} must be the operand of that
+ * opcode in the bytecode stream (i.e., a {@code rawIndex}).
+ * @param opcode must be {@code Bytecodes.INVOKEDYNAMIC}, or -1 if
+ * {@code index} was not decoded from a bytecode stream
+ * @return the bootstrap method invocation details or {@code null} if the entry specified by {@code index}
* is not a {@code CONSTANT_Dynamic_info} or @{code CONSTANT_InvokeDynamic_info}
* @throws IllegalArgumentException if the bootstrap method invocation makes use of
* {@code java.lang.invoke.BootstrapCallInfo}
* @jvms 4.7.23 The {@code BootstrapMethods} Attribute
*/
- default BootstrapMethodInvocation lookupBootstrapMethodInvocation(int cpi, int opcode) {
+ default BootstrapMethodInvocation lookupBootstrapMethodInvocation(int index, int opcode) {
throw new UnsupportedOperationException();
}
@@ -237,10 +244,9 @@ default BootstrapMethodInvocation lookupBootstrapMethodInvocation(int cpi, int o
/**
* Looks up the appendix at the specified index.
*
- * @param cpi the constant pool index
- * @param opcode the opcode of the instruction for which the lookup is being performed or
- * {@code -1}
+ * @param rawIndex index in the bytecode stream after the {@code opcode} (could be rewritten for some opcodes)
+ * @param opcode the opcode of the instruction for which the lookup is being performed
* @return the appendix if it exists and is resolved or {@code null}
*/
- JavaConstant lookupAppendix(int cpi, int opcode);
+ JavaConstant lookupAppendix(int rawIndex, int opcode);
}
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/TagletManager.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/TagletManager.java
index a4724f03e9d03..ed3727fd5bbee 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/TagletManager.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/TagletManager.java
@@ -50,8 +50,10 @@
import javax.tools.JavaFileManager;
import javax.tools.StandardJavaFileManager;
+import com.sun.source.doctree.BlockTagTree;
import com.sun.source.doctree.DocTree;
+import com.sun.source.doctree.InlineTagTree;
import jdk.javadoc.doclet.Doclet;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.doclet.Taglet.Location;
@@ -349,89 +351,88 @@ void seenTag(String name) {
* @param trees the trees containing the comments
*/
public void checkTags(Element element, Iterable extends DocTree> trees) {
- CommentHelper ch = utils.getCommentHelper(element);
for (DocTree tag : trees) {
- String name = tag.getKind().tagName;
+ String name = switch (tag.getKind()) {
+ case UNKNOWN_INLINE_TAG -> ((InlineTagTree) tag).getTagName();
+ case UNKNOWN_BLOCK_TAG -> ((BlockTagTree) tag).getTagName();
+ default -> tag.getKind().tagName;
+ };
if (name == null) {
- continue;
+ continue; // not a tag
}
- if (!name.isEmpty() && name.charAt(0) == '@') {
- name = name.substring(1);
- }
- if (! (standardTags.contains(name) || allTaglets.containsKey(name))) {
- if (standardTagsLowercase.contains(Utils.toLowerCase(name))) {
- messages.warning(ch.getDocTreePath(tag), "doclet.UnknownTagLowercase", ch.getTagName(tag));
- continue;
- } else {
- messages.warning(ch.getDocTreePath(tag), "doclet.UnknownTag", ch.getTagName(tag));
- continue;
+ if (!allTaglets.containsKey(name)) {
+ if (!config.isDocLintSyntaxGroupEnabled()) {
+ var ch = utils.getCommentHelper(element);
+ if (standardTagsLowercase.contains(Utils.toLowerCase(name))) {
+ messages.warning(ch.getDocTreePath(tag), "doclet.UnknownTagLowercase", ch.getTagName(tag));
+ } else {
+ messages.warning(ch.getDocTreePath(tag), "doclet.UnknownTag", ch.getTagName(tag));
+ }
}
+ continue; // unknown tag
}
final Taglet taglet = allTaglets.get(name);
- // Check and verify tag usage
- if (taglet != null) {
- if (taglet instanceof SimpleTaglet st && !st.isEnabled()) {
- // taglet has been disabled
- return;
- }
+ if (taglet instanceof SimpleTaglet st && !st.isEnabled()) {
+ continue; // taglet has been disabled
+ }
- new SimpleElementVisitor14() {
- @Override
- public Void visitModule(ModuleElement e, Void p) {
- if (!taglet.inModule()) {
- printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "module");
- }
- return null;
+ // Check and verify tag usage
+ new SimpleElementVisitor14() {
+ @Override
+ public Void visitModule(ModuleElement e, Void p) {
+ if (!taglet.inModule()) {
+ printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "module");
}
+ return null;
+ }
- @Override
- public Void visitPackage(PackageElement e, Void p) {
- if (!taglet.inPackage()) {
- printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "package");
- }
- return null;
+ @Override
+ public Void visitPackage(PackageElement e, Void p) {
+ if (!taglet.inPackage()) {
+ printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "package");
}
+ return null;
+ }
- @Override
- public Void visitType(TypeElement e, Void p) {
- if (!taglet.inType()) {
- printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "class");
- }
- return null;
+ @Override
+ public Void visitType(TypeElement e, Void p) {
+ if (!taglet.inType()) {
+ printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "class");
}
+ return null;
+ }
- @Override
- public Void visitExecutable(ExecutableElement e, Void p) {
- if (utils.isConstructor(e) && !taglet.inConstructor()) {
- printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "constructor");
- } else if (!taglet.inMethod()) {
- printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "method");
- }
- return null;
+ @Override
+ public Void visitExecutable(ExecutableElement e, Void p) {
+ if (utils.isConstructor(e) && !taglet.inConstructor()) {
+ printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "constructor");
+ } else if (!taglet.inMethod()) {
+ printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "method");
}
+ return null;
+ }
- @Override
- public Void visitVariable(VariableElement e, Void p) {
- if (utils.isField(e) && !taglet.inField()) {
- printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "field");
- }
- return null;
+ @Override
+ public Void visitVariable(VariableElement e, Void p) {
+ if (utils.isField(e) && !taglet.inField()) {
+ printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "field");
}
+ return null;
+ }
- @Override
- public Void visitUnknown(Element e, Void p) {
- if (utils.isOverviewElement(e) && !taglet.inOverview()) {
- printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "overview");
- }
- return null;
+ @Override
+ public Void visitUnknown(Element e, Void p) {
+ if (utils.isOverviewElement(e) && !taglet.inOverview()) {
+ printTagMisuseWarn(utils.getCommentHelper(e), taglet, tag, "overview");
}
+ return null;
+ }
- @Override
- protected Void defaultAction(Element e, Void p) {
- return null;
- }
- }.visit(element);
- }
+ @Override
+ protected Void defaultAction(Element e, Void p) {
+ return null;
+ }
+ }.visit(element);
}
}
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java
index 2a4b6332f6049..a0fad5a0e7dd4 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/Checker.java
@@ -41,6 +41,8 @@
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
@@ -1138,10 +1140,24 @@ public Void visitUnknownInlineTag(UnknownInlineTagTree tree, Void ignore) {
}
private void checkUnknownTag(DocTree tree, String tagName) {
+ // if it were a standard tag, this method wouldn't be called:
+ // a standard tag is never represented by Unknown{Block,Inline}TagTree
+ var k = tree.getKind();
+ assert k == DocTree.Kind.UNKNOWN_BLOCK_TAG
+ || k == DocTree.Kind.UNKNOWN_INLINE_TAG;
+ assert !getStandardTags().contains(tagName);
+ // report an unknown tag only if custom tags are set, see 8314213
if (env.customTags != null && !env.customTags.contains(tagName))
env.messages.error(SYNTAX, tree, "dc.tag.unknown", tagName);
}
+ private Set getStandardTags() {
+ return Stream.of(DocTree.Kind.values())
+ .filter(k -> k.tagName != null) // not all DocTree represent tags
+ .map(k -> k.tagName)
+ .collect(Collectors.toUnmodifiableSet());
+ }
+
@Override @DefinedBy(Api.COMPILER_TREE)
public Void visitUses(UsesTree tree, Void ignore) {
Element e = env.trees.getElement(env.currPath);
diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/VMConnection.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/VMConnection.java
index 7f4ae6939cbb5..555e8272e8125 100644
--- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/VMConnection.java
+++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/VMConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -544,16 +544,18 @@ private VirtualMachine launchTarget() {
} catch (IOException ioe) {
ioe.printStackTrace();
MessageOutput.fatalError("Unable to launch target VM.");
+ throw new RuntimeException(ioe);
} catch (IllegalConnectorArgumentsException icae) {
icae.printStackTrace();
MessageOutput.fatalError("Internal debugger error.");
+ throw new RuntimeException(icae);
} catch (VMStartException vmse) {
MessageOutput.println("vmstartexception", vmse.getMessage());
MessageOutput.println();
dumpFailedLaunchInfo(vmse.process());
MessageOutput.fatalError("Target VM failed to initialize.");
+ throw new RuntimeException(vmse);
}
- return null; // Shuts up the compiler
}
/* attach to running target vm */
@@ -564,11 +566,12 @@ private VirtualMachine attachTarget() {
} catch (IOException ioe) {
ioe.printStackTrace();
MessageOutput.fatalError("Unable to attach to target VM.");
+ throw new RuntimeException(ioe);
} catch (IllegalConnectorArgumentsException icae) {
icae.printStackTrace();
MessageOutput.fatalError("Internal debugger error.");
+ throw new RuntimeException(icae);
}
- return null; // Shuts up the compiler
}
/* listen for connection from target vm */
@@ -583,10 +586,11 @@ private VirtualMachine listenTarget() {
} catch (IOException ioe) {
ioe.printStackTrace();
MessageOutput.fatalError("Unable to attach to target VM.");
+ throw new RuntimeException(ioe);
} catch (IllegalConnectorArgumentsException icae) {
icae.printStackTrace();
MessageOutput.fatalError("Internal debugger error.");
+ throw new RuntimeException(icae);
}
- return null; // Shuts up the compiler
}
}
diff --git a/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c b/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c
index 4e49488da77b4..251154d9c2db9 100644
--- a/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c
+++ b/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c
@@ -736,15 +736,10 @@ socketTransport_startListening(jdwpTransportEnv* env, const char* address,
}
if (listenAddr == NULL) {
- // No address of preferred address family found, grab the fist one.
+ // No address of preferred address family found, grab the first one.
listenAddr = &(addrInfo[0]);
}
- if (listenAddr == NULL) {
- dbgsysFreeAddrInfo(addrInfo);
- RETURN_ERROR(JDWPTRANSPORT_ERROR_INTERNAL, "listen failed: wrong address");
- }
-
// Binding to IN6ADDR_ANY allows to serve both IPv4 and IPv6 connections,
// but binding to mapped INADDR_ANY (::ffff:0.0.0.0) allows to serve IPv4
// connections only. Make sure that IN6ADDR_ANY is preferred over
diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc
index ba3eb50e53fdd..6b0aa1724c439 100644
--- a/src/jdk.jfr/share/conf/jfr/default.jfc
+++ b/src/jdk.jfr/share/conf/jfr/default.jfc
@@ -700,6 +700,12 @@
0 ms
+
+ true
+ true
+ 0 ms
+
+
trueendChunk
diff --git a/src/jdk.jfr/share/conf/jfr/profile.jfc b/src/jdk.jfr/share/conf/jfr/profile.jfc
index 5563b6905698f..79ce390052a14 100644
--- a/src/jdk.jfr/share/conf/jfr/profile.jfc
+++ b/src/jdk.jfr/share/conf/jfr/profile.jfc
@@ -700,6 +700,12 @@
0 ms
+
+ true
+ true
+ 0 ms
+
+
trueendChunk
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java
index 4cf697f4f3506..cf031cb47a5ee 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppBundler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -62,13 +62,13 @@ public MacAppBundler() {
String keychain = SIGNING_KEYCHAIN.fetchFrom(params);
String result = null;
if (APP_STORE.fetchFrom(params)) {
- result = MacBaseInstallerBundler.findKey(
+ result = MacCertificate.findCertificateKey(
"3rd Party Mac Developer Application: ",
user, keychain);
}
// if either not signing for app store or couldn't find
if (result == null) {
- result = MacBaseInstallerBundler.findKey(
+ result = MacCertificate.findCertificateKey(
"Developer ID Application: ", user, keychain);
}
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java
index da174a50bfd42..d9250ae147409 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java
@@ -715,7 +715,7 @@ private static List getCodesignArgs(
return args;
}
- private static void signAppBundle(
+ static void signAppBundle(
Map params, Path appLocation,
String signingIdentity, String identifierPrefix, Path entitlements)
throws IOException {
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java
index 5bcccc061a41f..b4f63d66f5722 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -188,6 +188,12 @@ protected Path prepareAppBundle(Map params)
!AppImageFile.load(predefinedImage).isSigned()) {
new PackageFile(APP_NAME.fetchFrom(params)).save(
ApplicationLayout.macAppImage().resolveAt(appDir));
+ // We need to re-sign app image after adding ".package" to it.
+ // We only do this if app image was not signed which means it is
+ // signed with ad-hoc signature. App bundles with ad-hoc
+ // signature are sealed, but without a signing identity, so we
+ // need to re-sign it after modification.
+ MacAppImageBuilder.signAppBundle(params, appDir, "-", null, null);
}
} else {
appDir = appImageBundler.execute(params, appImageRoot);
@@ -201,47 +207,5 @@ public String getBundleType() {
return "INSTALLER";
}
- public static String findKey(String keyPrefix, String teamName, String keychainName) {
-
- boolean useAsIs = teamName.startsWith(keyPrefix)
- || teamName.startsWith("Developer ID")
- || teamName.startsWith("3rd Party Mac");
-
- String key = (useAsIs) ? teamName : (keyPrefix + teamName);
-
- try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
- PrintStream ps = new PrintStream(baos)) {
- List searchOptions = new ArrayList<>();
- searchOptions.add("/usr/bin/security");
- searchOptions.add("find-certificate");
- searchOptions.add("-c");
- searchOptions.add(key);
- searchOptions.add("-a");
- if (keychainName != null && !keychainName.isEmpty()) {
- searchOptions.add(keychainName);
- }
-
- ProcessBuilder pb = new ProcessBuilder(searchOptions);
-
- IOUtils.exec(pb, false, ps);
- Pattern p = Pattern.compile("\"alis\"=\"([^\"]+)\"");
- Matcher m = p.matcher(baos.toString());
- if (!m.find()) {
- Log.error(MessageFormat.format(I18N.getString(
- "error.cert.not.found"), key, keychainName));
- return null;
- }
- String matchedKey = m.group(1);
- if (m.find()) {
- Log.error(MessageFormat.format(I18N.getString(
- "error.multiple.certs.found"), key, keychainName));
- }
- return matchedKey;
- } catch (IOException ioe) {
- Log.verbose(ioe);
- return null;
- }
- }
-
private final Bundler appImageBundler;
}
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacCertificate.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacCertificate.java
index 4e205fd970525..90f3a8c765b44 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacCertificate.java
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacCertificate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.DateFormat;
+import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -40,6 +41,9 @@
import java.util.Date;
import java.util.List;
import java.util.Locale;
+import java.util.HexFormat;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public final class MacCertificate {
private final String certificate;
@@ -52,35 +56,219 @@ public boolean isValid() {
return verifyCertificate(this.certificate);
}
- private static Path findCertificate(String certificate) {
- Path result = null;
+ public static String findCertificateKey(String keyPrefix, String teamName,
+ String keychainName) {
+ String matchedKey = null;
+ boolean useAsIs = (keyPrefix == null)
+ || teamName.startsWith(keyPrefix)
+ || teamName.startsWith("Developer ID")
+ || teamName.startsWith("3rd Party Mac");
+
+ String name = (useAsIs) ? teamName : (keyPrefix + teamName);
+
+ String output = getFindCertificateOutput(name, keychainName);
+ if (output == null) {
+ Log.error(MessageFormat.format(I18N.getString(
+ "error.cert.not.found"), name, keychainName));
+ return null;
+ }
+
+ // Check and warn user if multiple certificates found
+ // We will use different regex to count certificates.
+ // ASCII case: "alis"="NAME"
+ // UNICODE case: "alis"=0xSOMEHEXDIGITS "NAME (\SOMEDIGITS)"
+ // In UNICODE case name will contain octal sequence representing UTF-8
+ // characters.
+ // Just look for at least two '"alis"'.
+ Pattern p = Pattern.compile("\"alis\"");
+ Matcher m = p.matcher(output);
+ if (m.find() && m.find()) {
+ Log.error(MessageFormat.format(I18N.getString(
+ "error.multiple.certs.found"), name, keychainName));
+ }
+
+ // Try to get ASCII only certificate first. This aproach only works
+ // if certificate name has ASCII only characters in name. For certificates
+ // with UNICODE characters in name we will use combination of "security"
+ // and "openssl". We keeping ASCII only aproach to avoid regressions and
+ // it works for many use cases.
+ p = Pattern.compile("\"alis\"=\"([^\"]+)\"");
+ m = p.matcher(output);
+ if (m.find()) {
+ matchedKey = m.group(1);;
+ }
+
+ // Maybe it has UNICODE characters in name. In this case use "security"
+ // and "openssl" to exctract name. We cannot use just "security", since
+ // name can be truncated.
+ if (matchedKey == null) {
+ Path file = null;
+ try {
+ file = getFindCertificateOutputPEM(name, keychainName);
+ if (file != null) {
+ matchedKey = findCertificateSubject(
+ file.toFile().getCanonicalPath());
+ }
+ } catch (IOException ioe) {
+ Log.verbose(ioe);
+ } finally {
+ try {
+ Files.deleteIfExists(file);
+ } catch (IOException ignored) {}
+ }
+ }
+
+ if (matchedKey == null) {
+ Log.error(MessageFormat.format(I18N.getString(
+ "error.cert.not.found"), name, keychainName));
+ }
+
+ return matchedKey;
+ }
+
+ private static String getFindCertificateOutput(String name,
+ String keychainName) {
+ try (ByteArrayOutputStream baos = getFindCertificateOutput(name,
+ keychainName,
+ false)) {
+ if (baos != null) {
+ return baos.toString();
+ }
+ } catch (IOException ioe) {
+ Log.verbose(ioe);
+ }
+
+ return null;
+ }
+
+ private static Path getFindCertificateOutputPEM(String name,
+ String keychainName) {
+ Path output = null;
+ try (ByteArrayOutputStream baos = getFindCertificateOutput(name,
+ keychainName,
+ true)) {
+ if (baos != null) {
+ output = Files.createTempFile("tempfile", ".tmp");
+ Files.copy(new ByteArrayInputStream(baos.toByteArray()),
+ output, StandardCopyOption.REPLACE_EXISTING);
+ return output;
+ }
+ } catch (IOException ioe) {
+ Log.verbose(ioe);
+ try {
+ Files.deleteIfExists(output);
+ } catch (IOException ignored) {}
+ }
+
+ return null;
+ }
+
+ private static ByteArrayOutputStream getFindCertificateOutput(String name,
+ String keychainName,
+ boolean isPEMFormat) {
List args = new ArrayList<>();
args.add("/usr/bin/security");
args.add("find-certificate");
args.add("-c");
- args.add(certificate);
+ args.add(name);
args.add("-a");
- args.add("-p");
+ if (isPEMFormat) {
+ args.add("-p");
+ }
+ if (keychainName != null && !keychainName.isEmpty()) {
+ args.add(keychainName);
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (PrintStream ps = new PrintStream(baos)) {
+ ProcessBuilder pb = new ProcessBuilder(args);
+ IOUtils.exec(pb, false, ps);
+ return baos;
+ } catch (IOException ioe) {
+ Log.verbose(ioe);
+ return null;
+ }
+ }
+
+ private static String findCertificateSubject(String filename) {
+ String result = null;
+
+ List args = new ArrayList<>();
+ args.add("/usr/bin/openssl");
+ args.add("x509");
+ args.add("-noout");
+ args.add("-subject");
+ args.add("-in");
+ args.add(filename);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos)) {
ProcessBuilder security = new ProcessBuilder(args);
IOUtils.exec(security, false, ps);
+ String output = baos.toString().strip();
+ // Example output:
+ // subject= /UID=ABCDABCD/CN=jpackage.openjdk.java.net (\xC3\xB6) (ABCDABCD)/C=US
+ // We need 'CN' value
+ String [] pairs = output.split("/");
+ for (String pair : pairs) {
+ if (pair.startsWith("CN=")) {
+ result = pair.substring(3);
+ // Convert escaped UTF-8 code points to characters
+ result = convertHexToChar(result);
+ break;
+ }
+ }
+ } catch (IOException ex) {
+ Log.verbose(ex);
+ }
- Path output = Files.createTempFile("tempfile", ".tmp");
+ return result;
+ }
- Files.copy(new ByteArrayInputStream(baos.toByteArray()),
- output, StandardCopyOption.REPLACE_EXISTING);
+ // Certificate name with Unicode will be:
+ // Developer ID Application: jpackage.openjdk.java.net (\xHH\xHH)
+ // Convert UTF-8 code points '\xHH\xHH' to character.
+ private static String convertHexToChar(String input) {
+ if (input == null || input.isEmpty()) {
+ return input;
+ }
- result = output;
+ if (!input.contains("\\x")) {
+ return input;
}
- catch (IOException ignored) {}
- return result;
+ StringBuilder output = new StringBuilder();
+ try {
+ int len = input.length();
+ for (int i = 0; i < len; i++) {
+ if (input.codePointAt(i) == '\\' &&
+ (i + 8) <= len &&
+ input.codePointAt(i + 1) == 'x' &&
+ input.codePointAt(i + 4) == '\\' &&
+ input.codePointAt(i + 5) == 'x') {
+ // We found '\xHH\xHH'
+ // HEX code points to byte array
+ byte [] bytes = HexFormat.of().parseHex(
+ input.substring(i + 2, i + 4) + input.substring(i + 6, i + 8));
+ // Byte array with UTF-8 code points to character
+ output.append(new String(bytes, "UTF-8"));
+ i += 7; // Skip '\xHH\xHH'
+ } else {
+ output.appendCodePoint(input.codePointAt(i));
+ }
+ }
+ } catch (Exception ex) {
+ Log.verbose(ex);
+ // We will consider any excpetions during conversion as
+ // certificate not found.
+ return null;
+ }
+
+ return output.toString();
}
- private static Date findCertificateDate(String filename) {
+ private Date findCertificateDate(String filename) {
Date result = null;
List args = new ArrayList<>();
@@ -107,7 +295,7 @@ private static Date findCertificateDate(String filename) {
return result;
}
- private static boolean verifyCertificate(String certificate) {
+ private boolean verifyCertificate(String certificate) {
boolean result = false;
try {
@@ -115,16 +303,15 @@ private static boolean verifyCertificate(String certificate) {
Date certificateDate = null;
try {
- file = findCertificate(certificate);
+ file = getFindCertificateOutputPEM(certificate, null);
if (file != null) {
certificateDate = findCertificateDate(
file.toFile().getCanonicalPath());
}
- }
- finally {
+ } finally {
if (file != null) {
- Files.delete(file);
+ Files.deleteIfExists(file);
}
}
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java
index 034c8013b70d3..60cd11b6f06f8 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgBundler.java
@@ -110,13 +110,13 @@ public class MacPkgBundler extends MacBaseInstallerBundler {
String keychain = SIGNING_KEYCHAIN.fetchFrom(params);
String result = null;
if (APP_STORE.fetchFrom(params)) {
- result = MacBaseInstallerBundler.findKey(
+ result = MacCertificate.findCertificateKey(
"3rd Party Mac Developer Installer: ",
user, keychain);
}
// if either not signing for app store or couldn't find
if (result == null) {
- result = MacBaseInstallerBundler.findKey(
+ result = MacCertificate.findCertificateKey(
"Developer ID Installer: ", user, keychain);
}
diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java
index 03b2a3c0f5719..c1a13c8627d79 100644
--- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java
+++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java
@@ -3085,10 +3085,22 @@ private void readExtra(ZipFileSystem zipfs) throws IOException {
int sz = SH(extra, pos + 2);
pos += 4;
if (pos + sz > elen) { // invalid data
- throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)");
+ throw new ZipException(String.format(
+ "Invalid CEN header (invalid extra data field size for " +
+ "tag: 0x%04x size: %d)",
+ tag, sz));
}
switch (tag) {
case EXTID_ZIP64 :
+ // if ZIP64_EXTID blocksize == 0, which may occur with some older
+ // versions of Apache Ant and Commons Compress, validate csize
+ // size, and locoff to make sure the fields != ZIP64_MAGICVAL
+ if (sz == 0) {
+ if (csize == ZIP64_MINVAL || size == ZIP64_MINVAL || locoff == ZIP64_MINVAL) {
+ throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)");
+ }
+ break;
+ }
// Check to see if we have a valid block size
if (!isZip64ExtBlockSizeValid(sz)) {
throw new ZipException("Invalid CEN header (invalid zip64 extra data field size)");
diff --git a/test/hotspot/gtest/classfile/test_symbolTable.cpp b/test/hotspot/gtest/classfile/test_symbolTable.cpp
index 77d076ec21327..4f4cbfe3e89b3 100644
--- a/test/hotspot/gtest/classfile/test_symbolTable.cpp
+++ b/test/hotspot/gtest/classfile/test_symbolTable.cpp
@@ -125,3 +125,17 @@ TEST_VM_FATAL_ERROR_MSG(SymbolTable, test_symbol_underflow, ".*refcount has gone
my_symbol->decrement_refcount();
my_symbol->increment_refcount(); // Should crash even in PRODUCT mode
}
+
+TEST_VM(SymbolTable, test_cleanup_leak) {
+ // Check that dead entry cleanup doesn't increment refcount of live entry in same bucket.
+
+ // Create symbol and release ref, marking it available for cleanup.
+ Symbol* entry1 = SymbolTable::new_symbol("hash_collision_123");
+ entry1->decrement_refcount();
+
+ // Create a new symbol in the same bucket, which will notice the dead entry and trigger cleanup.
+ // Note: relies on SymbolTable's use of String::hashCode which collides for these two values.
+ Symbol* entry2 = SymbolTable::new_symbol("hash_collision_397476851");
+
+ ASSERT_EQ(entry2->refcount(), 1) << "Symbol refcount just created is 1";
+}
diff --git a/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp b/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp
index 7a3845e336a31..875186b83d001 100644
--- a/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp
+++ b/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
#include "utilities/globalDefinitions.hpp"
#include "utilities/vmassert_uninstall.hpp"
+#include
#include
#include
#include "utilities/vmassert_reinstall.hpp"
diff --git a/test/hotspot/gtest/logging/test_logConfiguration.cpp b/test/hotspot/gtest/logging/test_logConfiguration.cpp
index c9be6965c5e84..907cfcb78c2c9 100644
--- a/test/hotspot/gtest/logging/test_logConfiguration.cpp
+++ b/test/hotspot/gtest/logging/test_logConfiguration.cpp
@@ -36,6 +36,8 @@
#include "unittest.hpp"
#include "utilities/ostream.hpp"
+using testing::HasSubstr;
+
class LogConfigurationTest : public LogTestFixture {
protected:
static char _all_decorators[256];
@@ -71,26 +73,26 @@ TEST_VM_F(LogConfigurationTest, describe) {
const char* description = ss.as_string();
// Verify that stdout and stderr are listed by default
- EXPECT_PRED2(string_contains_substring, description, LogConfiguration::StdoutLog->name());
- EXPECT_PRED2(string_contains_substring, description, LogConfiguration::StderrLog->name());
+ EXPECT_THAT(description, HasSubstr(LogConfiguration::StdoutLog->name()));
+ EXPECT_THAT(description, HasSubstr(LogConfiguration::StderrLog->name()));
// Verify that each tag, level and decorator is listed
for (size_t i = 0; i < LogTag::Count; i++) {
- EXPECT_PRED2(string_contains_substring, description, LogTag::name(static_cast(i)));
+ EXPECT_THAT(description, HasSubstr(LogTag::name(static_cast(i))));
}
for (size_t i = 0; i < LogLevel::Count; i++) {
- EXPECT_PRED2(string_contains_substring, description, LogLevel::name(static_cast(i)));
+ EXPECT_THAT(description, HasSubstr(LogLevel::name(static_cast(i))));
}
for (size_t i = 0; i < LogDecorators::Count; i++) {
- EXPECT_PRED2(string_contains_substring, description, LogDecorators::name(static_cast(i)));
+ EXPECT_THAT(description, HasSubstr(LogDecorators::name(static_cast(i))));
}
// Verify that the default configuration is printed
char expected_buf[256];
int ret = jio_snprintf(expected_buf, sizeof(expected_buf), "=%s", LogLevel::name(LogLevel::Default));
ASSERT_NE(-1, ret);
- EXPECT_PRED2(string_contains_substring, description, expected_buf);
- EXPECT_PRED2(string_contains_substring, description, "#1: stderr all=off");
+ EXPECT_THAT(description, HasSubstr(expected_buf));
+ EXPECT_THAT(description, HasSubstr("#1: stderr all=off"));
// Verify default decorators are listed
LogDecorators default_decorators;
@@ -107,7 +109,7 @@ TEST_VM_F(LogConfigurationTest, describe) {
ASSERT_NE(-1, ret);
}
}
- EXPECT_PRED2(string_contains_substring, description, expected_buf);
+ EXPECT_THAT(description, HasSubstr(expected_buf));
// Add a new output and verify that it gets described after it has been added
const char* what = "all=trace";
@@ -493,8 +495,8 @@ TEST_VM_F(LogConfigurationTest, parse_invalid_tagset) {
bool success = LogConfiguration::parse_log_arguments("stdout", invalid_tagset, NULL, NULL, &ss);
const char* msg = ss.as_string();
EXPECT_TRUE(success) << "Should only cause a warning, not an error";
- EXPECT_TRUE(string_contains_substring(msg, "No tag set matches selection:"));
- EXPECT_TRUE(string_contains_substring(msg, invalid_tagset));
+ EXPECT_THAT(msg, HasSubstr("No tag set matches selection:"));
+ EXPECT_THAT(msg, HasSubstr(invalid_tagset));
}
TEST_VM_F(LogConfigurationTest, output_name_normalization) {
@@ -559,7 +561,7 @@ TEST_VM_F(LogConfigurationTest, suggest_similar_selection) {
const char* suggestion = ss.as_string();
SCOPED_TRACE(suggestion);
- EXPECT_TRUE(string_contains_substring(ss.as_string(), "Did you mean any of the following?"));
+ EXPECT_THAT(suggestion, HasSubstr("Did you mean any of the following?"));
EXPECT_TRUE(string_contains_substring(suggestion, "logging") ||
string_contains_substring(suggestion, "start") ||
string_contains_substring(suggestion, "exit") ||
diff --git a/test/hotspot/gtest/logging/test_logFileOutput.cpp b/test/hotspot/gtest/logging/test_logFileOutput.cpp
index 770d0c04b80c3..7ea5f78b9e1f1 100644
--- a/test/hotspot/gtest/logging/test_logFileOutput.cpp
+++ b/test/hotspot/gtest/logging/test_logFileOutput.cpp
@@ -188,7 +188,7 @@ TEST_VM(LogFileOutput, invalid_file) {
EXPECT_FALSE(bad_file.initialize("", &ss))
<< "file was initialized when there was an existing directory with the same name";
char* logger_output = ss.as_string();
- EXPECT_TRUE(string_contains_substring(logger_output, expected_output_substring))
+ EXPECT_THAT(logger_output, testing::HasSubstr(expected_output_substring))
<< "missing expected error message, received msg: %s" << logger_output;
delete_empty_directory(path);
}
diff --git a/test/hotspot/gtest/logging/test_logTagSetDescriptions.cpp b/test/hotspot/gtest/logging/test_logTagSetDescriptions.cpp
index 84253e1943378..069e6877e32a5 100644
--- a/test/hotspot/gtest/logging/test_logTagSetDescriptions.cpp
+++ b/test/hotspot/gtest/logging/test_logTagSetDescriptions.cpp
@@ -42,7 +42,7 @@ TEST_VM(LogTagSetDescriptions, describe) {
ResourceMark rm;
stringStream stream;
LogConfiguration::describe(&stream);
- EXPECT_PRED2(string_contains_substring, stream.as_string(), expected)
+ EXPECT_THAT(stream.base(), testing::HasSubstr(expected))
<< "missing log tag set descriptions in LogConfiguration::describe";
}
}
diff --git a/test/hotspot/gtest/memory/test_guardedMemory.cpp b/test/hotspot/gtest/memory/test_guardedMemory.cpp
index 93047324fe59f..9e1d1754d3e86 100644
--- a/test/hotspot/gtest/memory/test_guardedMemory.cpp
+++ b/test/hotspot/gtest/memory/test_guardedMemory.cpp
@@ -139,7 +139,7 @@ TEST(GuardedMemory, wrap) {
if (HasFatalFailure()) {
return;
}
- EXPECT_EQ(0, strcmp(str, str_copy)) << "Not identical copy";
+ EXPECT_STREQ(str, str_copy) << "Not identical copy";
EXPECT_TRUE(GuardedMemory::free_copy(str_copy)) << "Free copy failed to verify";
void* no_data = NULL;
diff --git a/test/hotspot/gtest/metaspace/test_binlist.cpp b/test/hotspot/gtest/metaspace/test_binlist.cpp
index c526d4cd492b8..fd211a2eb8d54 100644
--- a/test/hotspot/gtest/metaspace/test_binlist.cpp
+++ b/test/hotspot/gtest/metaspace/test_binlist.cpp
@@ -46,7 +46,6 @@ using metaspace::MemRangeCounter;
template
struct BinListBasicTest {
- static const size_t minws;
static const size_t maxws;
static void basic_test() {
@@ -57,7 +56,7 @@ struct BinListBasicTest {
MetaWord arr[1000];
- size_t innocous_size = minws + ((maxws - minws) / 2);
+ size_t innocous_size = MAX2((size_t)1, maxws / 2);
// Try to get a block from an empty list.
size_t real_size = 4711;
@@ -88,8 +87,8 @@ struct BinListBasicTest {
MetaWord arr[1000];
- for (size_t s1 = minws; s1 <= maxws; s1++) {
- for (size_t s2 = minws; s2 <= maxws; s2++) {
+ for (size_t s1 = 1; s1 <= maxws; s1++) {
+ for (size_t s2 = 1; s2 <= maxws; s2++) {
bl.add_block(arr, s1);
CHECK_BL_CONTENT(bl, 1, s1);
@@ -108,7 +107,7 @@ struct BinListBasicTest {
CHECK_BL_CONTENT(bl, 1, s1);
DEBUG_ONLY(bl.verify();)
// drain bl
- p = bl.remove_block(minws, &real_size);
+ p = bl.remove_block(1, &real_size);
EXPECT_EQ(p, arr);
EXPECT_EQ((size_t)s1, real_size);
CHECK_BL_CONTENT(bl, 0, 0);
@@ -129,7 +128,7 @@ struct BinListBasicTest {
ASSERT_EQ(cnt[1].total_size(), bl[1].total_size());
FeederBuffer fb(1024);
- RandSizeGenerator rgen(minws, maxws + 1);
+ RandSizeGenerator rgen(1, maxws + 1);
// feed all
int which = 0;
@@ -184,10 +183,10 @@ struct BinListBasicTest {
while (bl[which].is_empty() == false) {
size_t real_size = 4711;
- MetaWord* p = bl[which].remove_block(minws, &real_size);
+ MetaWord* p = bl[which].remove_block(1, &real_size);
ASSERT_NE(p, (MetaWord*) NULL);
- ASSERT_GE(real_size, minws);
+ ASSERT_GE(real_size, (size_t)1);
ASSERT_TRUE(fb.is_valid_range(p, real_size));
// This must hold true since we always return the smallest fit.
@@ -205,24 +204,16 @@ struct BinListBasicTest {
}
};
-template const size_t BinListBasicTest::minws = BINLISTTYPE::MinWordSize;
template const size_t BinListBasicTest::maxws = BINLISTTYPE::MaxWordSize;
-TEST_VM(metaspace, BinList_basic_8) { BinListBasicTest< BinListImpl<2, 8> >::basic_test(); }
-TEST_VM(metaspace, BinList_basic_16) { BinListBasicTest< BinListImpl<2, 16> >::basic_test(); }
+TEST_VM(metaspace, BinList_basic_1) { BinListBasicTest< BinListImpl<1> >::basic_test(); }
+TEST_VM(metaspace, BinList_basic_8) { BinListBasicTest< BinListImpl<8> >::basic_test(); }
TEST_VM(metaspace, BinList_basic_32) { BinListBasicTest::basic_test(); }
-TEST_VM(metaspace, BinList_basic_1331) { BinListBasicTest< BinListImpl<13, 31> >::basic_test(); }
-TEST_VM(metaspace, BinList_basic_131) { BinListBasicTest< BinListImpl<13, 1> >::basic_test(); }
-TEST_VM(metaspace, BinList_basic2_8) { BinListBasicTest< BinListImpl<2, 8> >::basic_test_2(); }
-TEST_VM(metaspace, BinList_basic2_16) { BinListBasicTest< BinListImpl<2, 16> >::basic_test_2(); }
-TEST_VM(metaspace, BinList_basic2_32) { BinListBasicTest::basic_test_2(); }
-TEST_VM(metaspace, BinList_basic2_1331) { BinListBasicTest< BinListImpl<13, 31> >::basic_test_2(); }
-TEST_VM(metaspace, BinList_basic2_131) { BinListBasicTest< BinListImpl<13, 1> >::basic_test_2(); }
-
-TEST_VM(metaspace, BinList_random_test_8) { BinListBasicTest< BinListImpl<2, 8> >::random_test(); }
-TEST_VM(metaspace, BinList_random_test_16) { BinListBasicTest< BinListImpl<2, 16> >::random_test(); }
-TEST_VM(metaspace, BinList_random_test_32) { BinListBasicTest::random_test(); }
-TEST_VM(metaspace, BinList_random_test_1331) { BinListBasicTest< BinListImpl<13, 31> >::random_test(); }
-TEST_VM(metaspace, BinList_random_test_131) { BinListBasicTest< BinListImpl<13, 1> >::random_test(); }
+TEST_VM(metaspace, BinList_basic_2_1) { BinListBasicTest< BinListImpl<1> >::basic_test_2(); }
+TEST_VM(metaspace, BinList_basic_2_8) { BinListBasicTest< BinListImpl<8> >::basic_test_2(); }
+TEST_VM(metaspace, BinList_basic_2_32) { BinListBasicTest::basic_test_2(); }
+TEST_VM(metaspace, BinList_basic_rand_1) { BinListBasicTest< BinListImpl<1> >::random_test(); }
+TEST_VM(metaspace, BinList_basic_rand_8) { BinListBasicTest< BinListImpl<8> >::random_test(); }
+TEST_VM(metaspace, BinList_basic_rand_32) { BinListBasicTest::random_test(); }
diff --git a/test/hotspot/gtest/metaspace/test_chunkManager_stress.cpp b/test/hotspot/gtest/metaspace/test_chunkManager_stress.cpp
index ddafce062421f..2ccc4ebc09eec 100644
--- a/test/hotspot/gtest/metaspace/test_chunkManager_stress.cpp
+++ b/test/hotspot/gtest/metaspace/test_chunkManager_stress.cpp
@@ -54,7 +54,7 @@ class ChunkManagerRandomChunkAllocTest {
// Assuming we allocate only the largest type of chunk, committed to the fullest commit factor,
// how many chunks can we accomodate before hitting max_footprint_words?
const size_t largest_chunk_size = word_size_for_level(r.lowest());
- int max_chunks = (max_footprint_words * commit_factor) / largest_chunk_size;
+ int max_chunks = (int)((max_footprint_words * commit_factor) / (float) largest_chunk_size);
// .. but cap at (min) 50 and (max) 1000
max_chunks = MIN2(1000, max_chunks);
max_chunks = MAX2(50, max_chunks);
@@ -96,7 +96,7 @@ class ChunkManagerRandomChunkAllocTest {
// Given a chunk level and a factor, return a random commit size.
static size_t random_committed_words(chunklevel_t lvl, float commit_factor) {
- const size_t sz = word_size_for_level(lvl) * commit_factor;
+ const size_t sz = (size_t)((float)word_size_for_level(lvl) * commit_factor);
if (sz < 2) {
return 0;
}
@@ -194,7 +194,7 @@ class ChunkManagerRandomChunkAllocTest {
IntRange rand(100);
- for (int j = 0; j < 1000; j++) {
+ for (int j = 0; j < 750; j++) {
bool force_alloc = false;
bool force_free = true;
@@ -249,7 +249,7 @@ class ChunkManagerRandomChunkAllocTest {
// {}
void do_tests() {
- const int num_runs = 5;
+ const int num_runs = 3;
for (int n = 0; n < num_runs; n++) {
one_test();
}
diff --git a/test/hotspot/gtest/metaspace/test_freeblocks.cpp b/test/hotspot/gtest/metaspace/test_freeblocks.cpp
index 1ad14d7fc2250..6ca5fb8b05fc4 100644
--- a/test/hotspot/gtest/metaspace/test_freeblocks.cpp
+++ b/test/hotspot/gtest/metaspace/test_freeblocks.cpp
@@ -130,7 +130,7 @@ class FreeBlocksTest {
bool forcefeed = false;
bool draining = false;
bool stop = false;
- int iter = 100000; // safety stop
+ int iter = 25000; // safety stop
while (!stop && iter > 0) {
iter --;
int surprise = (int)os::random() % 10;
diff --git a/test/hotspot/gtest/metaspace/test_metaspacearena.cpp b/test/hotspot/gtest/metaspace/test_metaspacearena.cpp
index 8c1a21cf6dde8..c81a4cb6b2298 100644
--- a/test/hotspot/gtest/metaspace/test_metaspacearena.cpp
+++ b/test/hotspot/gtest/metaspace/test_metaspacearena.cpp
@@ -41,6 +41,7 @@
#include "metaspaceGtestContexts.hpp"
#include "metaspaceGtestRangeHelpers.hpp"
+using metaspace::AllocationAlignmentByteSize;
using metaspace::ArenaGrowthPolicy;
using metaspace::CommitLimiter;
using metaspace::InternalStats;
@@ -50,11 +51,6 @@ using metaspace::SizeAtomicCounter;
using metaspace::Settings;
using metaspace::ArenaStats;
-// See metaspaceArena.cpp : needed for predicting commit sizes.
-namespace metaspace {
- extern size_t get_raw_word_size_for_requested_word_size(size_t net_word_size);
-}
-
class MetaspaceArenaTestHelper {
MetaspaceGtestContext& _context;
@@ -179,7 +175,7 @@ class MetaspaceArenaTestHelper {
ASSERT_EQ(capacity, capacity2);
} else {
// Allocation succeeded. Should be correctly aligned.
- ASSERT_TRUE(is_aligned(p, sizeof(MetaWord)));
+ ASSERT_TRUE(is_aligned(p, AllocationAlignmentByteSize));
// used: may go up or may not (since our request may have been satisfied from the freeblocklist
// whose content already counts as used).
// committed: may go up, may not
diff --git a/test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp b/test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp
index 50c5d0bc0e1ba..2d0dc665f9aae 100644
--- a/test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp
+++ b/test/hotspot/gtest/metaspace/test_metaspacearena_stress.cpp
@@ -38,6 +38,7 @@
#include "metaspaceGtestContexts.hpp"
#include "metaspaceGtestSparseArray.hpp"
+using metaspace::AllocationAlignmentByteSize;
using metaspace::ArenaGrowthPolicy;
using metaspace::ChunkManager;
using metaspace::IntCounter;
@@ -52,11 +53,6 @@ static bool fifty_fifty() {
return IntRange(100).random_value() < 50;
}
-// See metaspaceArena.cpp : needed for predicting commit sizes.
-namespace metaspace {
- extern size_t get_raw_word_size_for_requested_word_size(size_t net_word_size);
-}
-
// A MetaspaceArenaTestBed contains a single MetaspaceArena and its lock.
// It keeps track of allocations done from this MetaspaceArena.
class MetaspaceArenaTestBed : public CHeapObj {
@@ -179,7 +175,8 @@ class MetaspaceArenaTestBed : public CHeapObj {
size_t word_size = 1 + _allocation_range.random_value();
MetaWord* p = _arena->allocate(word_size);
if (p != NULL) {
- EXPECT_TRUE(is_aligned(p, sizeof(MetaWord)));
+ EXPECT_TRUE(is_aligned(p, AllocationAlignmentByteSize));
+
allocation_t* a = NEW_C_HEAP_OBJ(allocation_t, mtInternal);
a->word_size = word_size;
a->p = p;
@@ -383,7 +380,7 @@ class MetaspaceArenaTest {
// - (rarely) deallocate (simulates metaspace deallocation, e.g. class redefinitions)
// - delete a test bed (simulates collection of a loader and subsequent return of metaspace to freelists)
- const int iterations = 10000;
+ const int iterations = 2500;
// Lets have a ceiling on number of words allocated (this is independent from the commit limit)
const size_t max_allocation_size = 8 * M;
diff --git a/test/hotspot/gtest/metaspace/test_virtualspacenode.cpp b/test/hotspot/gtest/metaspace/test_virtualspacenode.cpp
index daadee7333104..74e0aaa61240a 100644
--- a/test/hotspot/gtest/metaspace/test_virtualspacenode.cpp
+++ b/test/hotspot/gtest/metaspace/test_virtualspacenode.cpp
@@ -355,7 +355,7 @@ class VirtualSpaceNodeTest {
TestMap testmap(c->word_size());
assert(testmap.get_num_set() == 0, "Sanity");
- for (int run = 0; run < 1000; run++) {
+ for (int run = 0; run < 750; run++) {
const size_t committed_words_before = testmap.get_num_set();
ASSERT_EQ(_commit_limiter.committed_words(), committed_words_before);
@@ -425,7 +425,7 @@ class VirtualSpaceNodeTest {
assert(_commit_limit >= _vs_word_size, "No commit limit here pls");
- // Allocate a root chunk and commit a random part of it. Then repeatedly split
+ // Allocate a root chunk and commit a part of it. Then repeatedly split
// it and merge it back together; observe the committed regions of the split chunks.
Metachunk* c = alloc_root_chunk();
@@ -562,15 +562,10 @@ TEST_VM(metaspace, virtual_space_node_test_2) {
}
TEST_VM(metaspace, virtual_space_node_test_3) {
- double d = os::elapsedTime();
// Test committing uncommitting arbitrary ranges
- for (int run = 0; run < 100; run++) {
- VirtualSpaceNodeTest test(metaspace::chunklevel::MAX_CHUNK_WORD_SIZE,
- metaspace::chunklevel::MAX_CHUNK_WORD_SIZE);
- test.test_split_and_merge_chunks();
- }
- double d2 = os::elapsedTime();
- LOG("%f", (d2-d));
+ VirtualSpaceNodeTest test(metaspace::chunklevel::MAX_CHUNK_WORD_SIZE,
+ metaspace::chunklevel::MAX_CHUNK_WORD_SIZE);
+ test.test_split_and_merge_chunks();
}
TEST_VM(metaspace, virtual_space_node_test_4) {
diff --git a/test/hotspot/gtest/nmt/test_nmt_reserved_region.cpp b/test/hotspot/gtest/nmt/test_nmt_reserved_region.cpp
new file mode 100644
index 0000000000000..753a374fdbb26
--- /dev/null
+++ b/test/hotspot/gtest/nmt/test_nmt_reserved_region.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2023 SAP SE. All rights reserved.
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "runtime/os.hpp"
+#include "services/memTracker.hpp"
+#include "services/virtualMemoryTracker.hpp"
+#include "unittest.hpp"
+
+// Tests the assignment operator of ReservedMemoryRegion
+TEST_VM(NMT, ReservedRegionCopy) {
+ address dummy1 = (address)0x10000000;
+ NativeCallStack stack1(&dummy1, 1);
+ ReservedMemoryRegion region1(dummy1, os::vm_page_size(), stack1, mtThreadStack);
+ VirtualMemorySummary::record_reserved_memory(os::vm_page_size(), region1.flag());
+ region1.add_committed_region(dummy1, os::vm_page_size(), stack1);
+ address dummy2 = (address)0x20000000;
+ NativeCallStack stack2(&dummy2, 1);
+ ReservedMemoryRegion region2(dummy2, os::vm_page_size(), stack2, mtCode);
+ VirtualMemorySummary::record_reserved_memory(os::vm_page_size(), region2.flag());
+ region2.add_committed_region(dummy2, os::vm_page_size(), stack2);
+
+ region2 = region1;
+
+ CommittedRegionIterator itr = region2.iterate_committed_regions();
+ const CommittedMemoryRegion* rgn = itr.next();
+ ASSERT_EQ(rgn->base(), dummy1); // Now we should see dummy1
+ ASSERT_EQ(region2.flag(), mtThreadStack); // Should be correct flag
+ ASSERT_EQ(region2.call_stack()->get_frame(0), dummy1); // Check the stack
+ rgn = itr.next();
+ ASSERT_EQ(rgn, (const CommittedMemoryRegion*)nullptr); // and nothing else
+}
+
diff --git a/test/hotspot/gtest/oops/test_cpCache_output.cpp b/test/hotspot/gtest/oops/test_cpCache_output.cpp
index 8d5015e6eebbe..75d8b78091b55 100644
--- a/test/hotspot/gtest/oops/test_cpCache_output.cpp
+++ b/test/hotspot/gtest/oops/test_cpCache_output.cpp
@@ -42,31 +42,21 @@ TEST_VM(ConstantPoolCache, print_on) {
klass->constants()->cache()->print_on(&ss);
const char* output = ss.freeze();
- // method entry test
- ASSERT_TRUE(strstr(output, "this") != NULL) << "must have \"this\"";
- ASSERT_TRUE(strstr(output, "bytecode 1:") != NULL) << "must have \"bytecode 1\"";
- ASSERT_TRUE(strstr(output, "bytecode 2:") != NULL) << "must have \"bytecode 2\"";
- ASSERT_TRUE(strstr(output, "cp index:") != NULL) << "must have constant pool index";
- ASSERT_TRUE(strstr(output, "F1:") != NULL) << "must have F1 value";
- ASSERT_TRUE(strstr(output, "F2:") != NULL) << "must have F2 value";
- ASSERT_TRUE(strstr(output, "method:") != NULL) << "must have a method";
- ASSERT_TRUE(strstr(output, "flag values:") != NULL) << "must have a flag";
- ASSERT_TRUE(strstr(output, "tos:") != NULL) << "must have result type";
- ASSERT_TRUE(strstr(output, "local signature:") != NULL) << "must have local signature flag";
- ASSERT_TRUE(strstr(output, "has appendix:") != NULL) << "must have appendix flag";
- ASSERT_TRUE(strstr(output, "forced virtual:") != NULL) << "must have forced virtual flag";
- ASSERT_TRUE(strstr(output, "final:") != NULL) << "must have final flag";
- ASSERT_TRUE(strstr(output, "virtual final:") != NULL) << "must have virtual final flag";
- ASSERT_TRUE(strstr(output, "resolution failed:") != NULL) << "must have resolution failed flag";
- ASSERT_TRUE(strstr(output, "num parameters:") != NULL) << "must have number of parameters";
+ static const char* const expected_strings[] = {
+ // Method entry tests:
+ "this", "bytecode 1:", "bytecode 2:", "cp index:", "F1:", "F2:",
+ "method:", "flag values:", "tos:", "local signature:", "has appendix:",
+ "forced virtual:", "final:", "virtual final:", "resolution failed:",
+ "num parameters:",
+
+ // field entry test
+ "Offset:", "Field Index:", "CP Index:", "TOS:", "Is Final:", "Is Volatile:",
+ "Put Bytecode:", "Get Bytecode:",
+ nullptr
+ };
+
+ for (int i = 0; expected_strings[i] != nullptr; i++) {
+ ASSERT_THAT(output, testing::HasSubstr(expected_strings[i]));
+ }
- // field entry test
- ASSERT_TRUE(strstr(output, "Offset:") != NULL) << "must have field offset";
- ASSERT_TRUE(strstr(output, "Field Index:") != NULL) << "must have field index";
- ASSERT_TRUE(strstr(output, "CP Index:") != NULL) << "must have constant pool index";
- ASSERT_TRUE(strstr(output, "TOS:") != NULL) << "must have type";
- ASSERT_TRUE(strstr(output, "Is Final:") != NULL) << "must have final flag";
- ASSERT_TRUE(strstr(output, "Is Volatile:") != NULL) << "must have volatile flag";
- ASSERT_TRUE(strstr(output, "Put Bytecode:") != NULL) << "must have \"put code\"";
- ASSERT_TRUE(strstr(output, "Get Bytecode:") != NULL) << "must have \"get code\"";
}
diff --git a/test/hotspot/gtest/oops/test_instanceKlass.cpp b/test/hotspot/gtest/oops/test_instanceKlass.cpp
index dd7982e88aad9..b99cad554597c 100644
--- a/test/hotspot/gtest/oops/test_instanceKlass.cpp
+++ b/test/hotspot/gtest/oops/test_instanceKlass.cpp
@@ -33,6 +33,8 @@
#include "runtime/interfaceSupport.inline.hpp"
#include "unittest.hpp"
+using testing::HasSubstr;
+
// Tests for InstanceKlass::is_class_loader_instance_klass() function
TEST_VM(InstanceKlass, class_loader_class) {
InstanceKlass* klass = vmClasses::ClassLoader_klass();
@@ -51,20 +53,20 @@ TEST_VM(InstanceKlass, class_loader_printer) {
stringStream st;
loader->print_on(&st);
// See if injected loader_data field is printed in string
- ASSERT_TRUE(strstr(st.as_string(), "injected 'loader_data'") != NULL) << "Must contain injected fields";
+ ASSERT_THAT(st.base(), HasSubstr("injected 'loader_data'")) << "Must contain injected fields";
st.reset();
// See if mirror injected fields are printed.
oop mirror = vmClasses::ClassLoader_klass()->java_mirror();
mirror->print_on(&st);
- ASSERT_TRUE(strstr(st.as_string(), "injected 'protection_domain'") != NULL) << "Must contain injected fields";
+ ASSERT_THAT(st.base(), HasSubstr("injected 'protection_domain'")) << "Must contain injected fields";
// We should test other printing functions too.
#ifndef PRODUCT
st.reset();
// method printing is non-product
Method* method = vmClasses::ClassLoader_klass()->methods()->at(0); // we know there's a method here!
method->print_on(&st);
- ASSERT_TRUE(strstr(st.as_string(), "method holder:") != NULL) << "Must contain method_holder field";
- ASSERT_TRUE(strstr(st.as_string(), "'java/lang/ClassLoader'") != NULL) << "Must be in ClassLoader";
+ ASSERT_THAT(st.base(), HasSubstr("method holder:")) << "Must contain method_holder field";
+ ASSERT_THAT(st.base(), HasSubstr("'java/lang/ClassLoader'")) << "Must be in ClassLoader";
#endif
}
diff --git a/test/hotspot/gtest/oops/test_markWord.cpp b/test/hotspot/gtest/oops/test_markWord.cpp
index e6ab7c8ca6f82..2797bafc032f1 100644
--- a/test/hotspot/gtest/oops/test_markWord.cpp
+++ b/test/hotspot/gtest/oops/test_markWord.cpp
@@ -40,14 +40,11 @@
// The test doesn't work for PRODUCT because it needs WizardMode
#ifndef PRODUCT
-static bool test_pattern(stringStream* st, const char* pattern) {
- return (strstr(st->as_string(), pattern) != NULL);
-}
static void assert_test_pattern(Handle object, const char* pattern) {
stringStream st;
object->print_on(&st);
- ASSERT_TRUE(test_pattern(&st, pattern)) << pattern << " not in " << st.as_string();
+ ASSERT_THAT(st.base(), testing::HasSubstr(pattern));
}
class LockerThread : public JavaTestThread {
diff --git a/test/hotspot/gtest/runtime/test_classPrinter.cpp b/test/hotspot/gtest/runtime/test_classPrinter.cpp
index 8af285a6dde82..a2b6860f3d9d1 100644
--- a/test/hotspot/gtest/runtime/test_classPrinter.cpp
+++ b/test/hotspot/gtest/runtime/test_classPrinter.cpp
@@ -29,6 +29,8 @@
#include "utilities/ostream.hpp"
#include "unittest.hpp"
+using testing::HasSubstr;
+
TEST_VM(ClassPrinter, print_classes) {
JavaThread* THREAD = JavaThread::current();
ThreadInVMfromNative invm(THREAD);
@@ -38,9 +40,9 @@ TEST_VM(ClassPrinter, print_classes) {
ClassPrinter::print_classes("java/lang/Object", 0x03, &ss);
const char* output = ss.freeze();
- ASSERT_TRUE(strstr(output, "class java/lang/Object loader data:") != NULL) << "must find java/lang/Object";
- ASSERT_TRUE(strstr(output, "method wait : (J)V") != NULL) << "must find java/lang/Object::wait";
- ASSERT_TRUE(strstr(output, "method finalize : ()V\n 0 return") != NULL) << "must find java/lang/Object::finalize and disasm";
+ ASSERT_THAT(output, HasSubstr("class java/lang/Object loader data:")) << "must find java/lang/Object";
+ ASSERT_THAT(output, HasSubstr("method wait : (J)V")) << "must find java/lang/Object::wait";
+ ASSERT_THAT(output, HasSubstr("method finalize : ()V\n 0 return")) << "must find java/lang/Object::finalize and disasm";
}
TEST_VM(ClassPrinter, print_methods) {
@@ -51,16 +53,16 @@ TEST_VM(ClassPrinter, print_methods) {
stringStream s1;
ClassPrinter::print_methods("*ang/Object*", "wait", 0x1, &s1);
const char* o1 = s1.freeze();
- ASSERT_TRUE(strstr(o1, "class java/lang/Object loader data:") != NULL) << "must find java/lang/Object";
- ASSERT_TRUE(strstr(o1, "method wait : (J)V") != NULL) << "must find java/lang/Object::wait(long)";
- ASSERT_TRUE(strstr(o1, "method wait : ()V") != NULL) << "must find java/lang/Object::wait()";
- ASSERT_TRUE(strstr(o1, "method finalize : ()V") == NULL) << "must not find java/lang/Object::finalize";
+ ASSERT_THAT(o1, HasSubstr("class java/lang/Object loader data:")) << "must find java/lang/Object";
+ ASSERT_THAT(o1, HasSubstr("method wait : (J)V")) << "must find java/lang/Object::wait(long)";
+ ASSERT_THAT(o1, HasSubstr("method wait : ()V")) << "must find java/lang/Object::wait()";
+ ASSERT_THAT(o1, Not(HasSubstr("method finalize : ()V"))) << "must not find java/lang/Object::finalize";
stringStream s2;
ClassPrinter::print_methods("j*ang/Object*", "wait:(*J*)V", 0x1, &s2);
const char* o2 = s2.freeze();
- ASSERT_TRUE(strstr(o2, "class java/lang/Object loader data:") != NULL) << "must find java/lang/Object";
- ASSERT_TRUE(strstr(o2, "method wait : (J)V") != NULL) << "must find java/lang/Object::wait(long)";
- ASSERT_TRUE(strstr(o2, "method wait : (JI)V") != NULL) << "must find java/lang/Object::wait(long,int)";
- ASSERT_TRUE(strstr(o2, "method wait : ()V") == NULL) << "must not find java/lang/Object::wait()";
+ ASSERT_THAT(o2, HasSubstr("class java/lang/Object loader data:")) << "must find java/lang/Object";
+ ASSERT_THAT(o2, HasSubstr("method wait : (J)V")) << "must find java/lang/Object::wait(long)";
+ ASSERT_THAT(o2, HasSubstr("method wait : (JI)V")) << "must find java/lang/Object::wait(long,int)";
+ ASSERT_THAT(o2, Not(HasSubstr("method wait : ()V"))) << "must not find java/lang/Object::wait()";
}
diff --git a/test/hotspot/gtest/runtime/test_globals.cpp b/test/hotspot/gtest/runtime/test_globals.cpp
index 04724303e4235..1b0d58f8fb4a2 100644
--- a/test/hotspot/gtest/runtime/test_globals.cpp
+++ b/test/hotspot/gtest/runtime/test_globals.cpp
@@ -77,11 +77,11 @@ TEST_VM(FlagGuard, ccstr_flag) {
TEST_VM(FlagAccess, ccstr_flag) {
FLAG_SET_CMDLINE(SharedArchiveConfigFile, "");
ASSERT_EQ(FLAG_IS_CMDLINE(SharedArchiveConfigFile), true);
- ASSERT_EQ(strcmp(SharedArchiveConfigFile, ""), 0);
+ EXPECT_STREQ(SharedArchiveConfigFile, "");
FLAG_SET_ERGO(SharedArchiveConfigFile, "foobar");
ASSERT_EQ(FLAG_IS_ERGO(SharedArchiveConfigFile), true);
- ASSERT_EQ(strcmp(SharedArchiveConfigFile, "foobar") , 0);
+ EXPECT_STREQ(SharedArchiveConfigFile, "foobar");
FLAG_SET_ERGO(SharedArchiveConfigFile, nullptr);
ASSERT_EQ(FLAG_IS_ERGO(SharedArchiveConfigFile), true);
@@ -89,7 +89,7 @@ TEST_VM(FlagAccess, ccstr_flag) {
FLAG_SET_ERGO(SharedArchiveConfigFile, "xyz");
ASSERT_EQ(FLAG_IS_ERGO(SharedArchiveConfigFile), true);
- ASSERT_EQ(strcmp(SharedArchiveConfigFile, "xyz"), 0);
+ EXPECT_STREQ(SharedArchiveConfigFile, "xyz");
}
template
diff --git a/test/hotspot/gtest/runtime/test_os.cpp b/test/hotspot/gtest/runtime/test_os.cpp
index 81c72d8855624..bcd532d1bcf9f 100644
--- a/test/hotspot/gtest/runtime/test_os.cpp
+++ b/test/hotspot/gtest/runtime/test_os.cpp
@@ -38,6 +38,8 @@
#include "os_windows.hpp"
#endif
+using testing::HasSubstr;
+
static size_t small_page_size() {
return os::vm_page_size();
}
@@ -171,7 +173,7 @@ static void do_test_print_hex_dump(address addr, size_t len, int unitsize, const
os::print_hex_dump(&ss, addr, addr + len, unitsize);
// tty->print_cr("expected: %s", expected);
// tty->print_cr("result: %s", buf);
- EXPECT_THAT(buf, testing::HasSubstr(expected));
+ EXPECT_THAT(buf, HasSubstr(expected));
}
TEST_VM(os, test_print_hex_dump) {
@@ -768,7 +770,7 @@ TEST_VM(os, pagesizes_test_print) {
char buffer[256];
stringStream ss(buffer, sizeof(buffer));
pss.print_on(&ss);
- ASSERT_EQ(strcmp(expected, buffer), 0);
+ EXPECT_STREQ(expected, buffer);
}
TEST_VM(os, dll_address_to_function_and_library_name) {
@@ -777,9 +779,9 @@ TEST_VM(os, dll_address_to_function_and_library_name) {
stringStream st(output, sizeof(output));
#define EXPECT_CONTAINS(haystack, needle) \
- EXPECT_NE(::strstr(haystack, needle), (char*)NULL)
+ EXPECT_THAT(haystack, HasSubstr(needle));
#define EXPECT_DOES_NOT_CONTAIN(haystack, needle) \
- EXPECT_EQ(::strstr(haystack, needle), (char*)NULL)
+ EXPECT_THAT(haystack, Not(HasSubstr(needle)));
// #define LOG(...) tty->print_cr(__VA_ARGS__); // enable if needed
#define LOG(...)
@@ -924,3 +926,24 @@ TEST_VM(os, open_O_CLOEXEC) {
::close(fd);
#endif
}
+
+TEST_VM(os, reserve_at_wish_address_shall_not_replace_mappings_smallpages) {
+ char* p1 = os::reserve_memory(M, false, mtTest);
+ ASSERT_NE(p1, nullptr);
+ char* p2 = os::attempt_reserve_memory_at(p1, M);
+ ASSERT_EQ(p2, nullptr); // should have failed
+ os::release_memory(p1, M);
+}
+
+TEST_VM(os, reserve_at_wish_address_shall_not_replace_mappings_largepages) {
+ if (UseLargePages && !os::can_commit_large_page_memory()) { // aka special
+ const size_t lpsz = os::large_page_size();
+ char* p1 = os::reserve_memory_aligned(lpsz, lpsz, false);
+ ASSERT_NE(p1, nullptr);
+ char* p2 = os::reserve_memory_special(lpsz, lpsz, lpsz, p1, false);
+ ASSERT_EQ(p2, nullptr); // should have failed
+ os::release_memory(p1, M);
+ } else {
+ tty->print_cr("Skipped.");
+ }
+}
diff --git a/test/hotspot/gtest/runtime/test_os_linux.cpp b/test/hotspot/gtest/runtime/test_os_linux.cpp
index b1826276e006e..53534fc58bf97 100644
--- a/test/hotspot/gtest/runtime/test_os_linux.cpp
+++ b/test/hotspot/gtest/runtime/test_os_linux.cpp
@@ -433,7 +433,7 @@ TEST(os_linux, addr_to_function_valid) {
int offset = -1;
address valid_function_pointer = (address)JNI_CreateJavaVM;
ASSERT_TRUE(os::dll_address_to_function_name(valid_function_pointer, buf, sizeof(buf), &offset, true));
- ASSERT_TRUE(strstr(buf, "JNI_CreateJavaVM") != nullptr);
+ ASSERT_THAT(buf, testing::HasSubstr("JNI_CreateJavaVM"));
ASSERT_TRUE(offset >= 0);
}
@@ -444,7 +444,7 @@ TEST_VM(os_linux, decoder_get_source_info_valid) {
int line = -1;
address valid_function_pointer = (address)ReportJNIFatalError;
ASSERT_TRUE(Decoder::get_source_info(valid_function_pointer, buf, sizeof(buf), &line));
- ASSERT_TRUE(strcmp(buf, "jniCheck.hpp") == 0);
+ EXPECT_STREQ(buf, "jniCheck.hpp");
ASSERT_TRUE(line > 0);
}
@@ -471,7 +471,7 @@ TEST_VM(os_linux, decoder_get_source_info_valid_overflow) {
int line = -1;
address valid_function_pointer = (address)ReportJNIFatalError;
ASSERT_TRUE(Decoder::get_source_info(valid_function_pointer, buf, 11, &line));
- ASSERT_TRUE(strcmp(buf, "") == 0);
+ EXPECT_STREQ(buf, "");
ASSERT_TRUE(line > 0);
}
@@ -482,7 +482,7 @@ TEST_VM(os_linux, decoder_get_source_info_valid_overflow_minimal) {
int line = -1;
address valid_function_pointer = (address)ReportJNIFatalError;
ASSERT_TRUE(Decoder::get_source_info(valid_function_pointer, buf, 2, &line));
- ASSERT_TRUE(strcmp(buf, "L") == 0); // Overflow message does not fit, so we fall back to "L:line_number"
+ EXPECT_STREQ(buf, "L"); // Overflow message does not fit, so we fall back to "L:line_number"
ASSERT_TRUE(line > 0); // Line should correctly be found and returned
}
#endif // clang
diff --git a/test/hotspot/gtest/utilities/test_concurrentHashtable.cpp b/test/hotspot/gtest/utilities/test_concurrentHashtable.cpp
index 2094565dea307..ca41fc6b0f119 100644
--- a/test/hotspot/gtest/utilities/test_concurrentHashtable.cpp
+++ b/test/hotspot/gtest/utilities/test_concurrentHashtable.cpp
@@ -107,9 +107,12 @@ struct SimpleTestLookup {
uintx get_hash() {
return Pointer::get_hash(_val, NULL);
}
- bool equals(const uintptr_t* value, bool* is_dead) {
+ bool equals(const uintptr_t* value) {
return _val == *value;
}
+ bool is_dead(const uintptr_t* value) {
+ return false;
+ }
};
struct ValueGet {
@@ -561,9 +564,12 @@ struct TestLookup {
uintx get_hash() {
return TestInterface::get_hash(_val, NULL);
}
- bool equals(const uintptr_t* value, bool* is_dead) {
+ bool equals(const uintptr_t* value) {
return _val == *value;
}
+ bool is_dead(const uintptr_t* value) {
+ return false;
+ }
};
static uintptr_t cht_get_copy(TestTable* cht, Thread* thr, TestLookup tl) {
diff --git a/test/hotspot/gtest/utilities/test_globalDefinitions.cpp b/test/hotspot/gtest/utilities/test_globalDefinitions.cpp
index dfaa4a31a29d7..5dc43fb543f95 100644
--- a/test/hotspot/gtest/utilities/test_globalDefinitions.cpp
+++ b/test/hotspot/gtest/utilities/test_globalDefinitions.cpp
@@ -226,11 +226,9 @@ TEST(globalDefinitions, array_size) {
stringStream out; \
out.print((format), (value)); \
const char* result = out.as_string(); \
- EXPECT_EQ(strcmp(result, (expected)), 0) << "Failed with" \
+ EXPECT_STREQ((result), (expected)) << "Failed with" \
<< " format '" << (format) << "'" \
- << " value '" << (value) << "'" \
- << " result '" << result << "'" \
- << " expected '" << (expected) << "'"; \
+ << " value '" << (value); \
} while (false)
TEST(globalDefinitions, format_specifiers) {
diff --git a/test/hotspot/gtest/utilities/test_parse_memory_size.cpp b/test/hotspot/gtest/utilities/test_parse_memory_size.cpp
index 8ce02c6cea68e..c723966fa9cd1 100644
--- a/test/hotspot/gtest/utilities/test_parse_memory_size.cpp
+++ b/test/hotspot/gtest/utilities/test_parse_memory_size.cpp
@@ -66,7 +66,7 @@ static void do_test_valid(T expected_value, const char* pattern) {
ASSERT_TRUE(rc);
ASSERT_EQ(value, expected_value);
ASSERT_EQ(end, ss.base() + strlen(pattern));
- ASSERT_EQ(strcmp(end, ":-)"), 0);
+ EXPECT_STREQ(end, ":-)");
rc = parse_integer(ss.base(), &value);
ASSERT_FALSE(rc);
diff --git a/test/hotspot/gtest/utilities/test_resourceHash.cpp b/test/hotspot/gtest/utilities/test_resourceHash.cpp
index 1e6c00871f58f..9124f4b977ccf 100644
--- a/test/hotspot/gtest/utilities/test_resourceHash.cpp
+++ b/test/hotspot/gtest/utilities/test_resourceHash.cpp
@@ -468,7 +468,7 @@ TEST_VM_F(ResourceHashtablePrintTest, print_test) {
const char* strings[] = {
"Number of buckets", "Number of entries", "300", "Number of literals", "Average bucket size", "Maximum bucket size" };
for (const auto& str : strings) {
- ASSERT_TRUE(strstr(st.as_string(), str) != nullptr) << "string not present " << str;
+ ASSERT_THAT(st.base(), testing::HasSubstr(str));
}
// Cleanup: need to delete pointers in entries
TableDeleter deleter;
diff --git a/test/hotspot/jtreg/ProblemList-generational-zgc.txt b/test/hotspot/jtreg/ProblemList-generational-zgc.txt
index de22024f8d7f3..b5c35f2cec2be 100644
--- a/test/hotspot/jtreg/ProblemList-generational-zgc.txt
+++ b/test/hotspot/jtreg/ProblemList-generational-zgc.txt
@@ -32,6 +32,7 @@
resourcehogs/serviceability/sa/TestHeapDumpForLargeArray.java 8307393 generic-all
serviceability/sa/CDSJMapClstats.java 8307393 generic-all
serviceability/sa/ClhsdbAttach.java 8307393 generic-all
+serviceability/sa/ClhsdbAttachDifferentJVMs.java 8307393 generic-all
serviceability/sa/ClhsdbCDSCore.java 8307393 generic-all
serviceability/sa/ClhsdbCDSJstackPrintAll.java 8307393 generic-all
serviceability/sa/ClhsdbClasses.java 8307393 generic-all
diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt
index 4b85f92999901..8445fbc661ee9 100644
--- a/test/hotspot/jtreg/ProblemList.txt
+++ b/test/hotspot/jtreg/ProblemList.txt
@@ -103,6 +103,7 @@ runtime/CompressedOops/CompressedClassPointers.java 8305765 generic-all
runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all
runtime/ErrorHandling/TestDwarf.java 8305489 linux-all
runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le
+runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64
applications/jcstress/copy.java 8229852 linux-all
diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT
index 43a76558ea4bd..ba2e151f67ed4 100644
--- a/test/hotspot/jtreg/TEST.ROOT
+++ b/test/hotspot/jtreg/TEST.ROOT
@@ -88,7 +88,7 @@ requires.properties= \
jdk.containerized
# Minimum jtreg version
-requiredVersion=7.3+1
+requiredVersion=7.3.1+1
# Path to libraries in the topmost test directory. This is needed so @library
# does not need ../../../ notation to reach them
diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups
index c458ae7ed44fd..be6d9fdeddf6c 100644
--- a/test/hotspot/jtreg/TEST.groups
+++ b/test/hotspot/jtreg/TEST.groups
@@ -384,8 +384,6 @@ tier1_runtime = \
-runtime/memory/ReserveMemory.java \
-runtime/Metaspace/FragmentMetaspace.java \
-runtime/Metaspace/FragmentMetaspaceSimple.java \
- -runtime/Metaspace/elastic/TestMetaspaceAllocationMT1.java \
- -runtime/Metaspace/elastic/TestMetaspaceAllocationMT2.java \
-runtime/MirrorFrame/Test8003720.java \
-runtime/modules/LoadUnloadModuleStress.java \
-runtime/modules/ModuleStress/ExportModuleStressTest.java \
diff --git a/test/hotspot/jtreg/applications/scimark/Scimark.java b/test/hotspot/jtreg/applications/scimark/Scimark.java
index 96c5dccabeff7..8aab97aa2bc02 100644
--- a/test/hotspot/jtreg/applications/scimark/Scimark.java
+++ b/test/hotspot/jtreg/applications/scimark/Scimark.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,6 @@
/*
* @test
* @library /test/lib
- * @requires vm.flagless
* @run driver Scimark
*/
@@ -47,7 +46,9 @@ public static void main(String... args) throws Exception {
+ Scimark.class.getName(), e);
}
- OutputAnalyzer output = new OutputAnalyzer(ProcessTools.createJavaProcessBuilder(
+ System.setProperty("test.noclasspath", "true");
+
+ OutputAnalyzer output = new OutputAnalyzer(ProcessTools.createTestJvm(
"-cp", artifacts.get("gov.nist.math.scimark-2.0").toString(),
"jnt.scimark2.commandline", "-large")
.start());
diff --git a/test/hotspot/jtreg/compiler/arguments/TestLogJIT.java b/test/hotspot/jtreg/compiler/arguments/TestLogJIT.java
new file mode 100644
index 0000000000000..afafe17523cc0
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/arguments/TestLogJIT.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test running with log:jit*=debug enabled.
+ * @run main/othervm -Xlog:jit*=debug compiler.arguments.TestTraceTypeProfile
+ */
+
+package compiler.arguments;
+
+public class TestLogJIT {
+
+ static public void main(String[] args) {
+ System.out.println("Passed");
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/arguments/TestTraceTypeProfile.java b/test/hotspot/jtreg/compiler/arguments/TestTraceTypeProfile.java
new file mode 100644
index 0000000000000..df1c253b68975
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/arguments/TestTraceTypeProfile.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test running TraceTypeProfile enabled.
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
+ * -XX:+TraceTypeProfile compiler.arguments.TestTraceTypeProfile
+ */
+
+package compiler.arguments;
+
+public class TestTraceTypeProfile {
+
+ static public void main(String[] args) {
+ System.out.println("Passed");
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/c2/TestMinMaxSubword.java b/test/hotspot/jtreg/compiler/c2/TestMinMaxSubword.java
index 129fdc7096a61..955aa4058f046 100644
--- a/test/hotspot/jtreg/compiler/c2/TestMinMaxSubword.java
+++ b/test/hotspot/jtreg/compiler/c2/TestMinMaxSubword.java
@@ -61,7 +61,7 @@ public class TestMinMaxSubword {
// as Java APIs for Math.min/max do not support integer subword types and superword
// should not generate vectorized Min/Max nodes for them.
@Test
- @IR(failOn = {IRNode.MIN_V})
+ @IR(failOn = {IRNode.MIN_VI, IRNode.MIN_VF, IRNode.MIN_VD})
public static void testMinShort() {
for (int i = 0; i < LENGTH; i++) {
sb[i] = (short) Math.min(sa[i], val);
@@ -77,7 +77,7 @@ public static void testMinShort_runner() {
}
@Test
- @IR(failOn = {IRNode.MAX_V})
+ @IR(failOn = {IRNode.MAX_VI, IRNode.MAX_VF, IRNode.MAX_VD})
public static void testMaxShort() {
for (int i = 0; i < LENGTH; i++) {
sb[i] = (short) Math.max(sa[i], val);
@@ -92,7 +92,7 @@ public static void testMaxShort_runner() {
}
@Test
- @IR(failOn = {IRNode.MIN_V})
+ @IR(failOn = {IRNode.MIN_VI, IRNode.MIN_VF, IRNode.MIN_VD})
public static void testMinByte() {
for (int i = 0; i < LENGTH; i++) {
bb[i] = (byte) Math.min(ba[i], val);
@@ -108,7 +108,7 @@ public static void testMinByte_runner() {
}
@Test
- @IR(failOn = {IRNode.MAX_V})
+ @IR(failOn = {IRNode.MAX_VI, IRNode.MAX_VF, IRNode.MAX_VD})
public static void testMaxByte() {
for (int i = 0; i < LENGTH; i++) {
bb[i] = (byte) Math.max(ba[i], val);
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVecCountingDownLoop.java b/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVecCountingDownLoop.java
index 9769f8d43a767..994ec1e9cc0bf 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVecCountingDownLoop.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVecCountingDownLoop.java
@@ -46,7 +46,7 @@ public static void main(String[] args) {
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, " >0 "})
+ @IR(counts = {IRNode.LOAD_VECTOR_I, " >0 "})
@IR(counts = {IRNode.STORE_VECTOR, " >0 "})
private static void testCountingDown(int[] a, int[] b) {
for (int i = 2000; i > 0; i--) {
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java b/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java
index 31fc5361b6bbc..c9b2904d91c74 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java
@@ -48,9 +48,12 @@ public static void main(String[] args) {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, " >0 " })
- @IR(counts = { IRNode.ADD_VD, " >0 " })
- @IR(counts = { IRNode.STORE_VECTOR, " >0 " })
+ // Given small iteration count, the unrolling factor is not very predictable,
+ // hence it is difficult to exactly predict the vector size. But let's at least
+ // check that there is some vectorization of any size.
+ @IR(counts = { IRNode.LOAD_VECTOR_D, IRNode.VECTOR_SIZE_ANY, " >0 " })
+ @IR(counts = { IRNode.ADD_VD, IRNode.VECTOR_SIZE_ANY, " >0 " })
+ @IR(counts = { IRNode.STORE_VECTOR, " >0 " })
private static void testDouble(double[][] a , double[][] b, double[][] c) {
for(int i = 0; i < a.length; i++) {
for (int j = 0; j < a[0].length; j++) {
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestDisableAutoVectOpcodes.java b/test/hotspot/jtreg/compiler/c2/irTests/TestDisableAutoVectOpcodes.java
index f493b3fc3074c..31112a74eb11f 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/TestDisableAutoVectOpcodes.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/TestDisableAutoVectOpcodes.java
@@ -53,7 +53,7 @@ public static void main(String[] args) {
}
@Test
- @IR(failOn = {IRNode.VECTOR_CAST_D2X})
+ @IR(failOn = {IRNode.VECTOR_CAST_D2I})
private static void testConvD2I() {
for(int i = 0; i < SIZE; i++) {
inta[i] = (int) (doublea[i]);
@@ -61,7 +61,7 @@ private static void testConvD2I() {
}
@Test
- @IR(failOn = {IRNode.VECTOR_CAST_L2X})
+ @IR(failOn = {IRNode.VECTOR_CAST_L2F})
private static void testConvL2F() {
for(int i = 0; i < SIZE; i++) {
floata[i] = (float) (longa[i]);
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestIRFma.java b/test/hotspot/jtreg/compiler/c2/irTests/TestIRFma.java
new file mode 100644
index 0000000000000..0e2cd067a13d2
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/c2/irTests/TestIRFma.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.c2.irTests;
+
+import compiler.lib.ir_framework.*;
+import java.util.Random;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+
+/*
+ * @test
+ * @bug 8308340
+ * @key randomness
+ * @summary Test fma match rule after C2 optimizer.
+ * @library /test/lib /
+ * @run driver compiler.c2.irTests.TestIRFma
+ */
+
+public class TestIRFma {
+
+ private static final Random RANDOM = Utils.getRandomInstance();
+
+ public static void main(String[] args) {
+ TestFramework.run();
+ }
+
+ @Run(test = {"test1", "test2", "test3",
+ "test4", "test5", "test6",
+ "test7", "test8", "test9",
+ "test10", "test11", "test12",
+ "test13", "test14"})
+ public void runMethod() {
+ float fa = RANDOM.nextFloat();
+ float fb = RANDOM.nextFloat();
+ float fc = RANDOM.nextFloat();
+ assertResult(fa, fb, fc);
+
+ double da = RANDOM.nextDouble();
+ double db = RANDOM.nextDouble();
+ double dc = RANDOM.nextDouble();
+ assertResult(da, db, dc);
+ }
+
+ @DontCompile
+ public void assertResult(float a, float b, float c) {
+ Asserts.assertEquals(Math.fma(-a, -b, c) , test1(a, b, c));
+ Asserts.assertEquals(Math.fma(-a, b, c) , test3(a, b, c));
+ Asserts.assertEquals(Math.fma(a, -b, c) , test5(a, b, c));
+ Asserts.assertEquals(Math.fma(-a, b, -c) , test7(a, b, c));
+ Asserts.assertEquals(Math.fma(a, -b, -c) , test9(a, b, c));
+ Asserts.assertEquals(Math.fma(a, b, -c) , test11(a, b, c));
+ Asserts.assertEquals(Math.fma(-a, -b, -c) , test13(a, b, c));
+ }
+
+ @DontCompile
+ public void assertResult(double a, double b, double c) {
+ Asserts.assertEquals(Math.fma(-a, -b, c) , test2(a, b, c));
+ Asserts.assertEquals(Math.fma(-a, b, c) , test4(a, b, c));
+ Asserts.assertEquals(Math.fma(a, -b, c) , test6(a, b, c));
+ Asserts.assertEquals(Math.fma(-a, b, -c) , test8(a, b, c));
+ Asserts.assertEquals(Math.fma(a, -b, -c) , test10(a, b, c));
+ Asserts.assertEquals(Math.fma(a, b, -c) , test12(a, b, c));
+ Asserts.assertEquals(Math.fma(-a, -b, -c) , test14(a, b, c));
+ }
+
+ @Test
+ @IR(counts = {IRNode.FMSUB, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static float test1(float a, float b, float c) {
+ return Math.fma(-a, -b, c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FMSUB, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static double test2(double a, double b, double c) {
+ return Math.fma(-a, -b, c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FMSUB, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static float test3(float a, float b, float c) {
+ return Math.fma(-a, b, c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FMSUB, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static double test4(double a, double b, double c) {
+ return Math.fma(-a, b, c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FMSUB, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static float test5(float a, float b, float c) {
+ return Math.fma(a, -b, c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FMSUB, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static double test6(double a, double b, double c) {
+ return Math.fma(a, -b, c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FNMADD, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static float test7(float a, float b, float c) {
+ return Math.fma(-a, b, -c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FNMADD, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static double test8(double a, double b, double c) {
+ return Math.fma(-a, b, -c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FNMADD, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static float test9(float a, float b, float c) {
+ return Math.fma(a, -b, -c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FNMADD, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static double test10(double a, double b, double c) {
+ return Math.fma(a, -b, -c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FNMSUB, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static float test11(float a, float b, float c) {
+ return Math.fma(a, b, -c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FNMSUB, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static double test12(double a, double b, double c) {
+ return Math.fma(a, b, -c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FNMADD, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static float test13(float a, float b, float c) {
+ return Math.fma(-a, -b, -c);
+ }
+
+ @Test
+ @IR(counts = {IRNode.FNMADD, "> 0"},
+ applyIfCPUFeature = {"asimd", "true"})
+ static double test14(double a, double b, double c) {
+ return Math.fma(-a, -b, -c);
+ }
+
+ }
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorConditionalMove.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorConditionalMove.java
index 6cd87f19339dc..6f6b7f5bd306d 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorConditionalMove.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorConditionalMove.java
@@ -31,7 +31,7 @@
/*
* @test
- * @bug 8289422 8306088
+ * @bug 8289422 8306088 8313720
* @key randomness
* @summary Auto-vectorization enhancement to support vector conditional move.
* @library /test/lib /
@@ -203,7 +203,10 @@ private double cmoveDGTforD(double a, double b, double c, double d) {
// Compare 2 values, and pick one of them
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveVFGT(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
@@ -212,7 +215,10 @@ private static void testCMoveVFGT(float[] a, float[] b, float[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveVFGTSwap(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
@@ -221,7 +227,10 @@ private static void testCMoveVFGTSwap(float[] a, float[] b, float[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveVFLT(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
@@ -230,7 +239,10 @@ private static void testCMoveVFLT(float[] a, float[] b, float[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveVFLTSwap(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
@@ -239,7 +251,10 @@ private static void testCMoveVFLTSwap(float[] a, float[] b, float[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveVFEQ(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
@@ -248,7 +263,10 @@ private static void testCMoveVFEQ(float[] a, float[] b, float[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveVDLE(double[] a, double[] b, double[] c) {
for (int i = 0; i < a.length; i++) {
@@ -257,7 +275,10 @@ private static void testCMoveVDLE(double[] a, double[] b, double[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveVDLESwap(double[] a, double[] b, double[] c) {
for (int i = 0; i < a.length; i++) {
@@ -266,7 +287,10 @@ private static void testCMoveVDLESwap(double[] a, double[] b, double[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveVDGE(double[] a, double[] b, double[] c) {
for (int i = 0; i < a.length; i++) {
@@ -275,7 +299,10 @@ private static void testCMoveVDGE(double[] a, double[] b, double[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveVDGESwap(double[] a, double[] b, double[] c) {
for (int i = 0; i < a.length; i++) {
@@ -284,7 +311,10 @@ private static void testCMoveVDGESwap(double[] a, double[] b, double[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveVDNE(double[] a, double[] b, double[] c) {
for (int i = 0; i < a.length; i++) {
@@ -294,7 +324,10 @@ private static void testCMoveVDNE(double[] a, double[] b, double[] c) {
// Extensions: compare 2 values, and pick from 2 consts
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveFGTforFConst(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
@@ -303,7 +336,10 @@ private static void testCMoveFGTforFConst(float[] a, float[] b, float[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveFGEforFConst(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
@@ -312,7 +348,10 @@ private static void testCMoveFGEforFConst(float[] a, float[] b, float[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveFLTforFConst(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
@@ -321,7 +360,10 @@ private static void testCMoveFLTforFConst(float[] a, float[] b, float[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveFLEforFConst(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
@@ -330,7 +372,10 @@ private static void testCMoveFLEforFConst(float[] a, float[] b, float[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveFEQforFConst(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
@@ -339,7 +384,10 @@ private static void testCMoveFEQforFConst(float[] a, float[] b, float[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveFNEQforFConst(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
@@ -348,7 +396,62 @@ private static void testCMoveFNEQforFConst(float[] a, float[] b, float[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
+ applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
+ private static void testCMoveFLTforFConstH2(float[] a, float[] b, float[] c) {
+ for (int i = 0; i < a.length; i+=2) {
+ c[i+0] = (a[i+0] < b[i+0]) ? 0.1f : -0.1f;
+ c[i+1] = (a[i+1] < b[i+1]) ? 0.1f : -0.1f;
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
+ applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
+ private static void testCMoveFLEforFConstH2(float[] a, float[] b, float[] c) {
+ for (int i = 0; i < a.length; i+=2) {
+ c[i+0] = (a[i+0] <= b[i+0]) ? 0.1f : -0.1f;
+ c[i+1] = (a[i+1] <= b[i+1]) ? 0.1f : -0.1f;
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD_VECTOR_F, "=0",
+ IRNode.VECTOR_MASK_CMP_F, "=0",
+ IRNode.VECTOR_BLEND_F, "=0",
+ IRNode.STORE_VECTOR, "=0"},
+ applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
+ private static void testCMoveFYYforFConstH2(float[] a, float[] b, float[] c) {
+ for (int i = 0; i < a.length; i+=2) {
+ c[i+0] = (a[i+0] <= b[i+0]) ? 0.1f : -0.1f;
+ c[i+1] = (a[i+1] < b[i+1]) ? 0.1f : -0.1f;
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD_VECTOR_F, "=0",
+ IRNode.VECTOR_MASK_CMP_F, "=0",
+ IRNode.VECTOR_BLEND_F, "=0",
+ IRNode.STORE_VECTOR, "=0"},
+ applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
+ private static void testCMoveFXXforFConstH2(float[] a, float[] b, float[] c) {
+ for (int i = 0; i < a.length; i+=2) {
+ c[i+0] = (a[i+0] < b[i+0]) ? 0.1f : -0.1f;
+ c[i+1] = (a[i+1] <= b[i+1]) ? 0.1f : -0.1f;
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveDGTforDConst(double[] a, double[] b, double[] c) {
for (int i = 0; i < a.length; i++) {
@@ -357,7 +460,10 @@ private static void testCMoveDGTforDConst(double[] a, double[] b, double[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveDGEforDConst(double[] a, double[] b, double[] c) {
for (int i = 0; i < a.length; i++) {
@@ -366,7 +472,10 @@ private static void testCMoveDGEforDConst(double[] a, double[] b, double[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveDLTforDConst(double[] a, double[] b, double[] c) {
for (int i = 0; i < a.length; i++) {
@@ -375,7 +484,10 @@ private static void testCMoveDLTforDConst(double[] a, double[] b, double[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveDLEforDConst(double[] a, double[] b, double[] c) {
for (int i = 0; i < a.length; i++) {
@@ -384,7 +496,10 @@ private static void testCMoveDLEforDConst(double[] a, double[] b, double[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveDEQforDConst(double[] a, double[] b, double[] c) {
for (int i = 0; i < a.length; i++) {
@@ -393,7 +508,10 @@ private static void testCMoveDEQforDConst(double[] a, double[] b, double[] c) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveDNEQforDConst(double[] a, double[] b, double[] c) {
for (int i = 0; i < a.length; i++) {
@@ -401,6 +519,58 @@ private static void testCMoveDNEQforDConst(double[] a, double[] b, double[] c) {
}
}
+ @Test
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
+ applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
+ private static void testCMoveDLTforDConstH2(double[] a, double[] b, double[] c) {
+ for (int i = 0; i < a.length; i+=2) {
+ c[i+0] = (a[i+0] < b[i+0]) ? 0.1 : -0.1;
+ c[i+1] = (a[i+1] < b[i+1]) ? 0.1 : -0.1;
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
+ applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
+ private static void testCMoveDLEforDConstH2(double[] a, double[] b, double[] c) {
+ for (int i = 0; i < a.length; i+=2) {
+ c[i+0] = (a[i+0] <= b[i+0]) ? 0.1 : -0.1;
+ c[i+1] = (a[i+1] <= b[i+1]) ? 0.1 : -0.1;
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD_VECTOR_D, "=0",
+ IRNode.VECTOR_MASK_CMP_D, "=0",
+ IRNode.VECTOR_BLEND_D, "=0",
+ IRNode.STORE_VECTOR, "=0"},
+ applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
+ private static void testCMoveDYYforDConstH2(double[] a, double[] b, double[] c) {
+ for (int i = 0; i < a.length; i+=2) {
+ c[i+0] = (a[i+0] <= b[i+0]) ? 0.1 : -0.1;
+ c[i+1] = (a[i+1] < b[i+1]) ? 0.1 : -0.1;
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD_VECTOR_D, "=0",
+ IRNode.VECTOR_MASK_CMP_D, "=0",
+ IRNode.VECTOR_BLEND_D, "=0",
+ IRNode.STORE_VECTOR, "=0"},
+ applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
+ private static void testCMoveDXXforDConstH2(double[] a, double[] b, double[] c) {
+ for (int i = 0; i < a.length; i+=2) {
+ c[i+0] = (a[i+0] < b[i+0]) ? 0.1 : -0.1;
+ c[i+1] = (a[i+1] <= b[i+1]) ? 0.1 : -0.1;
+ }
+ }
+
// Extension: Compare 2 ILFD values, and pick from 2 ILFD values
// Note:
// To guarantee that CMove is introduced, I need to perform the loads before the branch. To ensure they
@@ -408,7 +578,7 @@ private static void testCMoveDNEQforDConst(double[] a, double[] b, double[] c) {
// compilation does not know that).
// So far, vectorization only works for CMoveF/D, with same data-width comparison (F/I for F, D/L for D).
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveIGTforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) {
for (int i = 0; i < a.length; i++) {
int cc = c[i];
@@ -419,7 +589,7 @@ private static void testCMoveIGTforI(int[] a, int[] b, int[] c, int[] d, int[] r
}
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveIGTforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) {
for (int i = 0; i < a.length; i++) {
long cc = c[i];
@@ -430,7 +600,11 @@ private static void testCMoveIGTforL(int[] a, int[] b, long[] c, long[] d, long[
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0",
+ IRNode.LOAD_VECTOR_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0",
+ IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0",
+ IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveIGTforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) {
for (int i = 0; i < a.length; i++) {
@@ -442,7 +616,7 @@ private static void testCMoveIGTforF(int[] a, int[] b, float[] c, float[] d, flo
}
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveIGTforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) {
for (int i = 0; i < a.length; i++) {
double cc = c[i];
@@ -453,7 +627,7 @@ private static void testCMoveIGTforD(int[] a, int[] b, double[] c, double[] d, d
}
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveLGTforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) {
for (int i = 0; i < a.length; i++) {
int cc = c[i];
@@ -464,7 +638,7 @@ private static void testCMoveLGTforI(long[] a, long[] b, int[] c, int[] d, int[]
}
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveLGTforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) {
for (int i = 0; i < a.length; i++) {
long cc = c[i];
@@ -475,7 +649,7 @@ private static void testCMoveLGTforL(long[] a, long[] b, long[] c, long[] d, lon
}
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveLGTforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) {
for (int i = 0; i < a.length; i++) {
float cc = c[i];
@@ -486,7 +660,11 @@ private static void testCMoveLGTforF(long[] a, long[] b, float[] c, float[] d, f
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0",
+ IRNode.LOAD_VECTOR_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0",
+ IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0",
+ IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"})
// Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4.
private static void testCMoveLGTforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) {
@@ -499,7 +677,7 @@ private static void testCMoveLGTforD(long[] a, long[] b, double[] c, double[] d,
}
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveFGTforI(float[] a, float[] b, int[] c, int[] d, int[] r, int[] r2) {
for (int i = 0; i < a.length; i++) {
int cc = c[i];
@@ -510,7 +688,7 @@ private static void testCMoveFGTforI(float[] a, float[] b, int[] c, int[] d, int
}
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveFGTforL(float[] a, float[] b, long[] c, long[] d, long[] r, long[] r2) {
for (int i = 0; i < a.length; i++) {
long cc = c[i];
@@ -521,7 +699,10 @@ private static void testCMoveFGTforL(float[] a, float[] b, long[] c, long[] d, l
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveFGTforF(float[] a, float[] b, float[] c, float[] d, float[] r, float[] r2) {
for (int i = 0; i < a.length; i++) {
@@ -533,7 +714,7 @@ private static void testCMoveFGTforF(float[] a, float[] b, float[] c, float[] d,
}
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveFGTforD(float[] a, float[] b, double[] c, double[] d, double[] r, double[] r2) {
for (int i = 0; i < a.length; i++) {
double cc = c[i];
@@ -544,7 +725,7 @@ private static void testCMoveFGTforD(float[] a, float[] b, double[] c, double[]
}
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveDGTforI(double[] a, double[] b, int[] c, int[] d, int[] r, int[] r2) {
for (int i = 0; i < a.length; i++) {
int cc = c[i];
@@ -555,7 +736,7 @@ private static void testCMoveDGTforI(double[] a, double[] b, int[] c, int[] d, i
}
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveDGTforL(double[] a, double[] b, long[] c, long[] d, long[] r, long[] r2) {
for (int i = 0; i < a.length; i++) {
long cc = c[i];
@@ -566,7 +747,7 @@ private static void testCMoveDGTforL(double[] a, double[] b, long[] c, long[] d,
}
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveDGTforF(double[] a, double[] b, float[] c, float[] d, float[] r, float[] r2) {
for (int i = 0; i < a.length; i++) {
float cc = c[i];
@@ -577,7 +758,10 @@ private static void testCMoveDGTforF(double[] a, double[] b, float[] c, float[]
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_D, ">0",
+ IRNode.VECTOR_MASK_CMP_D, ">0",
+ IRNode.VECTOR_BLEND_D, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveDGTforD(double[] a, double[] b, double[] c, double[] d, double[] r, double[] r2) {
for (int i = 0; i < a.length; i++) {
@@ -590,7 +774,10 @@ private static void testCMoveDGTforD(double[] a, double[] b, double[] c, double[
// Use some constants in the comparison
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveFGTforFCmpCon1(float a, float[] b, float[] c, float[] d, float[] r, float[] r2) {
for (int i = 0; i < b.length; i++) {
@@ -602,7 +789,10 @@ private static void testCMoveFGTforFCmpCon1(float a, float[] b, float[] c, float
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"},
+ @IR(counts = {IRNode.LOAD_VECTOR_F, ">0",
+ IRNode.VECTOR_MASK_CMP_F, ">0",
+ IRNode.VECTOR_BLEND_F, ">0",
+ IRNode.STORE_VECTOR, ">0"},
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"})
private static void testCMoveFGTforFCmpCon2(float[] a, float b, float[] c, float[] d, float[] r, float[] r2) {
for (int i = 0; i < a.length; i++) {
@@ -615,7 +805,7 @@ private static void testCMoveFGTforFCmpCon2(float[] a, float b, float[] c, float
// A case that is currently not supported and is not expected to vectorize
@Test
- @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND})
+ @IR(failOn = {IRNode.STORE_VECTOR})
private static void testCMoveVDUnsupported() {
double[] doublec = new double[SIZE];
int seed = 1001;
@@ -630,7 +820,11 @@ private static void testCMoveVDUnsupported() {
"testCMoveFGTforFConst", "testCMoveFGEforFConst", "testCMoveFLTforFConst",
"testCMoveFLEforFConst", "testCMoveFEQforFConst", "testCMoveFNEQforFConst",
"testCMoveDGTforDConst", "testCMoveDGEforDConst", "testCMoveDLTforDConst",
- "testCMoveDLEforDConst", "testCMoveDEQforDConst", "testCMoveDNEQforDConst"})
+ "testCMoveDLEforDConst", "testCMoveDEQforDConst", "testCMoveDNEQforDConst",
+ "testCMoveFLTforFConstH2", "testCMoveFLEforFConstH2",
+ "testCMoveFYYforFConstH2", "testCMoveFXXforFConstH2",
+ "testCMoveDLTforDConstH2", "testCMoveDLEforDConstH2",
+ "testCMoveDYYforDConstH2", "testCMoveDXXforDConstH2"})
private void testCMove_runner() {
float[] floata = new float[SIZE];
float[] floatb = new float[SIZE];
@@ -729,6 +923,39 @@ private void testCMove_runner() {
Asserts.assertEquals(floatc[i], cmoveFNEQforFConst(floata[i], floatb[i]));
Asserts.assertEquals(doublec[i], cmoveDNEQforDConst(doublea[i], doubleb[i]));
}
+
+ // Hand-unrolled (H2) examples:
+ testCMoveFLTforFConstH2(floata, floatb, floatc);
+ testCMoveDLTforDConstH2(doublea, doubleb, doublec);
+ for (int i = 0; i < SIZE; i++) {
+ Asserts.assertEquals(floatc[i], cmoveFLTforFConst(floata[i], floatb[i]));
+ Asserts.assertEquals(doublec[i], cmoveDLTforDConst(doublea[i], doubleb[i]));
+ }
+
+ testCMoveFLEforFConstH2(floata, floatb, floatc);
+ testCMoveDLEforDConstH2(doublea, doubleb, doublec);
+ for (int i = 0; i < SIZE; i++) {
+ Asserts.assertEquals(floatc[i], cmoveFLEforFConst(floata[i], floatb[i]));
+ Asserts.assertEquals(doublec[i], cmoveDLEforDConst(doublea[i], doubleb[i]));
+ }
+
+ testCMoveFYYforFConstH2(floata, floatb, floatc);
+ testCMoveDYYforDConstH2(doublea, doubleb, doublec);
+ for (int i = 0; i < SIZE; i+=2) {
+ Asserts.assertEquals(floatc[i+0], cmoveFLEforFConst(floata[i+0], floatb[i+0]));
+ Asserts.assertEquals(doublec[i+0], cmoveDLEforDConst(doublea[i+0], doubleb[i+0]));
+ Asserts.assertEquals(floatc[i+1], cmoveFLTforFConst(floata[i+1], floatb[i+1]));
+ Asserts.assertEquals(doublec[i+1], cmoveDLTforDConst(doublea[i+1], doubleb[i+1]));
+ }
+
+ testCMoveFXXforFConstH2(floata, floatb, floatc);
+ testCMoveDXXforDConstH2(doublea, doubleb, doublec);
+ for (int i = 0; i < SIZE; i+=2) {
+ Asserts.assertEquals(floatc[i+0], cmoveFLTforFConst(floata[i+0], floatb[i+0]));
+ Asserts.assertEquals(doublec[i+0], cmoveDLTforDConst(doublea[i+0], doubleb[i+0]));
+ Asserts.assertEquals(floatc[i+1], cmoveFLEforFConst(floata[i+1], floatb[i+1]));
+ Asserts.assertEquals(doublec[i+1], cmoveDLEforDConst(doublea[i+1], doubleb[i+1]));
+ }
}
@Warmup(0)
@@ -895,19 +1122,33 @@ private static void init(long[] a) {
private static void init(float[] a) {
for (int i = 0; i < SIZE; i++) {
- a[i] = RANDOM.nextFloat();
- if (RANDOM.nextInt() % 20 == 0) {
- a[i] = Float.NaN;
- }
+ a[i] = switch(RANDOM.nextInt() % 20) {
+ case 0 -> Float.NaN;
+ case 1 -> 0;
+ case 2 -> 1;
+ case 3 -> Float.POSITIVE_INFINITY;
+ case 4 -> Float.NEGATIVE_INFINITY;
+ case 5 -> Float.MAX_VALUE;
+ case 6 -> Float.MIN_VALUE;
+ case 7, 8, 9 -> RANDOM.nextFloat();
+ default -> Float.intBitsToFloat(RANDOM.nextInt());
+ };
}
}
private static void init(double[] a) {
for (int i = 0; i < SIZE; i++) {
- a[i] = RANDOM.nextDouble();
- if (RANDOM.nextInt() % 20 == 0) {
- a[i] = Double.NaN;
- }
+ a[i] = switch(RANDOM.nextInt() % 20) {
+ case 0 -> Double.NaN;
+ case 1 -> 0;
+ case 2 -> 1;
+ case 3 -> Double.POSITIVE_INFINITY;
+ case 4 -> Double.NEGATIVE_INFINITY;
+ case 5 -> Double.MAX_VALUE;
+ case 6 -> Double.MIN_VALUE;
+ case 7, 8, 9 -> RANDOM.nextDouble();
+ default -> Double.longBitsToDouble(RANDOM.nextLong());
+ };
}
}
}
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java
index 0e9e48160b59d..3b7bf23173051 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java
@@ -150,7 +150,7 @@ static private void runAndVerify3(Runnable test, int offset) {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testByteLong1(byte[] dest, long[] src) {
for (int i = 0; i < src.length; i++) {
UNSAFE.putLongUnaligned(dest, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * i, src[i]);
@@ -163,7 +163,7 @@ public static void testByteLong1_runner() {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testByteLong2(byte[] dest, long[] src) {
for (int i = 1; i < src.length; i++) {
UNSAFE.putLongUnaligned(dest, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * (i - 1), src[i]);
@@ -176,7 +176,7 @@ public static void testByteLong2_runner() {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testByteLong3(byte[] dest, long[] src) {
for (int i = 0; i < src.length - 1; i++) {
UNSAFE.putLongUnaligned(dest, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * (i + 1), src[i]);
@@ -189,7 +189,7 @@ public static void testByteLong3_runner() {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testByteLong4(byte[] dest, long[] src, int start, int stop) {
for (int i = start; i < stop; i++) {
UNSAFE.putLongUnaligned(dest, 8 * i + baseOffset, src[i]);
@@ -203,7 +203,7 @@ public static void testByteLong4_runner() {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testByteLong5(byte[] dest, long[] src, int start, int stop) {
for (int i = start; i < stop; i++) {
UNSAFE.putLongUnaligned(dest, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * (i + baseOffset), src[i]);
@@ -217,7 +217,7 @@ public static void testByteLong5_runner() {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testByteByte1(byte[] dest, byte[] src) {
for (int i = 0; i < src.length / 8; i++) {
UNSAFE.putLongUnaligned(dest, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * i, UNSAFE.getLongUnaligned(src, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * i));
@@ -229,9 +229,8 @@ public static void testByteByte1_runner() {
runAndVerify2(() -> testByteByte1(byteArray, byteArray), 0);
}
- // It would be legal to vectorize this one but it's not currently
@Test
- //@IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testByteByte2(byte[] dest, byte[] src) {
for (int i = 1; i < src.length / 8; i++) {
UNSAFE.putLongUnaligned(dest, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * (i - 1), UNSAFE.getLongUnaligned(src, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * i));
@@ -244,7 +243,7 @@ public static void testByteByte2_runner() {
}
@Test
- @IR(failOn = { IRNode.LOAD_VECTOR, IRNode.STORE_VECTOR })
+ @IR(failOn = { IRNode.LOAD_VECTOR_L, IRNode.STORE_VECTOR })
public static void testByteByte3(byte[] dest, byte[] src) {
for (int i = 0; i < src.length / 8 - 1; i++) {
UNSAFE.putLongUnaligned(dest, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * (i + 1), UNSAFE.getLongUnaligned(src, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * i));
@@ -257,7 +256,7 @@ public static void testByteByte3_runner() {
}
@Test
- @IR(failOn = { IRNode.LOAD_VECTOR, IRNode.STORE_VECTOR })
+ @IR(failOn = { IRNode.LOAD_VECTOR_L, IRNode.STORE_VECTOR })
public static void testByteByte4(byte[] dest, byte[] src, int start, int stop) {
for (int i = start; i < stop; i++) {
UNSAFE.putLongUnaligned(dest, 8 * i + baseOffset, UNSAFE.getLongUnaligned(src, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * i));
@@ -271,7 +270,7 @@ public static void testByteByte4_runner() {
}
@Test
- @IR(failOn = { IRNode.LOAD_VECTOR, IRNode.STORE_VECTOR })
+ @IR(failOn = { IRNode.LOAD_VECTOR_L, IRNode.STORE_VECTOR })
public static void testByteByte5(byte[] dest, byte[] src, int start, int stop) {
for (int i = start; i < stop; i++) {
UNSAFE.putLongUnaligned(dest, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * (i + baseOffset), UNSAFE.getLongUnaligned(src, UNSAFE.ARRAY_BYTE_BASE_OFFSET + 8 * i));
@@ -285,7 +284,7 @@ public static void testByteByte5_runner() {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testOffHeapLong1(long dest, long[] src) {
for (int i = 0; i < src.length; i++) {
UNSAFE.putLongUnaligned(null, dest + 8 * i, src[i]);
@@ -298,7 +297,7 @@ public static void testOffHeapLong1_runner() {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testOffHeapLong2(long dest, long[] src) {
for (int i = 1; i < src.length; i++) {
UNSAFE.putLongUnaligned(null, dest + 8 * (i - 1), src[i]);
@@ -311,7 +310,7 @@ public static void testOffHeapLong2_runner() {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testOffHeapLong3(long dest, long[] src) {
for (int i = 0; i < src.length - 1; i++) {
UNSAFE.putLongUnaligned(null, dest + 8 * (i + 1), src[i]);
@@ -324,7 +323,7 @@ public static void testOffHeapLong3_runner() {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testOffHeapLong4(long dest, long[] src, int start, int stop) {
for (int i = start; i < stop; i++) {
UNSAFE.putLongUnaligned(null, dest + 8 * i + baseOffset, src[i]);
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMultiInvar.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMultiInvar.java
index 6b5c886cf8648..72276254ab224 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMultiInvar.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMultiInvar.java
@@ -60,7 +60,7 @@ public static void main(String[] args) {
static long baseOffset = 0;
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testByteLong1(byte[] dest, long[] src) {
for (int i = 0; i < src.length; i++) {
long j = Objects.checkIndex(i * 8, (long)(src.length * 8));
@@ -75,7 +75,7 @@ public static void testByteLong1_runner() {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_B, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testLoopNest1(byte[] dest, byte[] src,
long start1, long stop1,
long start2, long stop2,
@@ -106,7 +106,7 @@ public static void testLoopNest1_runner() {
}
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_I, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void testLoopNest2(int[] dest, int[] src,
long start1, long stop1,
long start2, long stop2,
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationNotRun.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationNotRun.java
index 26a4550c5c875..5968b7221c70c 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationNotRun.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationNotRun.java
@@ -51,7 +51,7 @@ public static void main(String[] args) {
static long[] longArray = new long[size];
@Test
- @IR(counts = { IRNode.LOAD_VECTOR, ">=1", IRNode.STORE_VECTOR, ">=1" })
+ @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" })
public static void test(byte[] dest, long[] src) {
for (int i = 0; i < src.length; i++) {
if ((i < 0) || (8 > sizeBytes - i)) {
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeTypeConversion.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeTypeConversion.java
index 9255bf4aeeef6..67c26ecbddfc3 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeTypeConversion.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeTypeConversion.java
@@ -55,8 +55,9 @@ public static void main(String[] args) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0",
- IRNode.VECTOR_CAST_I2X, ">0",
+ // Mixing types of different sizes has the effect that some vectors are shorter than the type allows.
+ @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "min(max_int, max_double)", ">0",
+ IRNode.VECTOR_CAST_I2D, IRNode.VECTOR_SIZE + "min(max_int, max_double)", ">0",
IRNode.STORE_VECTOR, ">0"},
// The vectorization of some conversions may fail when `+AlignVector`.
// We can remove the condition after JDK-8303827.
@@ -68,9 +69,11 @@ private static void testConvI2D(double[] d, int[] a) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0",
- IRNode.VECTOR_CAST_I2X, ">0",
- IRNode.VECTOR_CAST_L2X, ">0",
+ // Mixing types of different sizes has the effect that some vectors are shorter than the type allows.
+ @IR(counts = {IRNode.LOAD_VECTOR_L, IRNode.VECTOR_SIZE + "min(max_int, max_long)", ">0",
+ IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "min(max_int, max_long)", ">0",
+ IRNode.VECTOR_CAST_I2L, IRNode.VECTOR_SIZE + "min(max_int, max_long)", ">0",
+ IRNode.VECTOR_CAST_L2I, IRNode.VECTOR_SIZE + "min(max_int, max_long)", ">0",
IRNode.STORE_VECTOR, ">0"})
private static void testConvI2L(int[] d1, int d2[], long[] a1, long[] a2) {
for(int i = 0; i < d1.length; i++) {
@@ -80,9 +83,11 @@ private static void testConvI2L(int[] d1, int d2[], long[] a1, long[] a2) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0",
- IRNode.VECTOR_CAST_D2X, ">0",
- IRNode.VECTOR_CAST_F2X, ">0",
+ // Mixing types of different sizes has the effect that some vectors are shorter than the type allows.
+ @IR(counts = {IRNode.LOAD_VECTOR_F, IRNode.VECTOR_SIZE + "min(max_float, max_double)", ">0",
+ IRNode.LOAD_VECTOR_D, IRNode.VECTOR_SIZE + "min(max_float, max_double)", ">0",
+ IRNode.VECTOR_CAST_D2F, IRNode.VECTOR_SIZE + "min(max_float, max_double)", ">0",
+ IRNode.VECTOR_CAST_F2D, IRNode.VECTOR_SIZE + "min(max_float, max_double)", ">0",
IRNode.STORE_VECTOR, ">0"})
private static void testConvF2D(double[] d1, double[] d2, float[] a1, float[] a2) {
for(int i = 0; i < d1.length; i++) {
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeURShiftSubword.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeURShiftSubword.java
index 187e05855ffa7..ebe3fe63ccfda 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeURShiftSubword.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeURShiftSubword.java
@@ -70,7 +70,7 @@ public static void main(String[] args) {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.RSHIFT_VB, ">0", IRNode.STORE_VECTOR, ">0"})
+ @IR(counts = {IRNode.LOAD_VECTOR_B, ">0", IRNode.RSHIFT_VB, ">0", IRNode.STORE_VECTOR, ">0"})
public void testByte0() {
for(int i = 0; i < NUM; i++) {
byteb[i] = (byte) (bytea[i] >>> 3);
@@ -78,7 +78,7 @@ public void testByte0() {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.RSHIFT_VB, ">0", IRNode.STORE_VECTOR, ">0"})
+ @IR(counts = {IRNode.LOAD_VECTOR_B, ">0", IRNode.RSHIFT_VB, ">0", IRNode.STORE_VECTOR, ">0"})
public void testByte1() {
for(int i = 0; i < NUM; i++) {
byteb[i] = (byte) (bytea[i] >>> 24);
@@ -86,7 +86,7 @@ public void testByte1() {
}
@Test
- @IR(failOn = {IRNode.LOAD_VECTOR, IRNode.RSHIFT_VB, IRNode.STORE_VECTOR})
+ @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.RSHIFT_VB, IRNode.STORE_VECTOR})
public void testByte2() {
for(int i = 0; i < NUM; i++) {
byteb[i] = (byte) (bytea[i] >>> 25);
@@ -94,7 +94,7 @@ public void testByte2() {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.RSHIFT_VS, ">0", IRNode.STORE_VECTOR, ">0"})
+ @IR(counts = {IRNode.LOAD_VECTOR_S, ">0", IRNode.RSHIFT_VS, ">0", IRNode.STORE_VECTOR, ">0"})
public void testShort0() {
for(int i = 0; i < NUM; i++) {
shortb[i] = (short) (shorta[i] >>> 10);
@@ -102,7 +102,7 @@ public void testShort0() {
}
@Test
- @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.RSHIFT_VS, ">0", IRNode.STORE_VECTOR, ">0"})
+ @IR(counts = {IRNode.LOAD_VECTOR_S, ">0", IRNode.RSHIFT_VS, ">0", IRNode.STORE_VECTOR, ">0"})
public void testShort1() {
for(int i = 0; i < NUM; i++) {
shortb[i] = (short) (shorta[i] >>> 16);
@@ -110,7 +110,7 @@ public void testShort1() {
}
@Test
- @IR(failOn = {IRNode.LOAD_VECTOR, IRNode.RSHIFT_VS, IRNode.STORE_VECTOR})
+ @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.RSHIFT_VS, IRNode.STORE_VECTOR})
public void testShort2() {
for(int i = 0; i < NUM; i++) {
shortb[i] = (short) (shorta[i] >>> 17);
diff --git a/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java b/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java
index aa2f39ef6e600..8effcd63ae7c0 100644
--- a/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java
+++ b/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java
@@ -43,6 +43,9 @@ public static void main(String[] args) {
"-XX:+ReduceAllocationMerges",
"-XX:+TraceReduceAllocationMerges",
"-XX:+DeoptimizeALot",
+ "-XX:CompileCommand=inline,*::charAt*",
+ "-XX:CompileCommand=inline,*PicturePositions::*",
+ "-XX:CompileCommand=inline,*Point::*",
"-XX:CompileCommand=exclude,*::dummy*");
}
@@ -92,9 +95,11 @@ public static void main(String[] args) {
"testString_two_C2"
})
public void runner(RunInfo info) {
+ invocations++;
+
Random random = info.getRandom();
- boolean cond1 = random.nextBoolean();
- boolean cond2 = random.nextBoolean();
+ boolean cond1 = invocations % 2 == 0;
+ boolean cond2 = !cond1;
int l = random.nextInt();
int w = random.nextInt();
@@ -551,9 +556,10 @@ int testSubclassesTrapping(boolean c1, boolean c2, int x, int y, int w, int z) {
new F();
}
+ int res = s.a;
dummy();
- return s.a;
+ return res;
}
@Test
@@ -1196,12 +1202,13 @@ int testSRAndNSR_Trap(boolean is_c2, boolean cond1, boolean cond2, int x, int y)
global_escape = p;
}
+ int res = p.x;
if (is_c2) {
// This will show up to C2 as a trap.
dummy_defaults();
}
- return p.y;
+ return res;
}
@Test
diff --git a/test/hotspot/jtreg/compiler/codecache/CodeCacheFullCountTest.java b/test/hotspot/jtreg/compiler/codecache/CodeCacheFullCountTest.java
index 8646c5834c662..9b1a5e890718e 100644
--- a/test/hotspot/jtreg/compiler/codecache/CodeCacheFullCountTest.java
+++ b/test/hotspot/jtreg/compiler/codecache/CodeCacheFullCountTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,7 +57,11 @@ public static void runTest() throws Throwable {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:ReservedCodeCacheSize=2496k", "-XX:-UseCodeCacheFlushing", "-XX:-MethodFlushing", "CodeCacheFullCountTest", "WasteCodeCache");
OutputAnalyzer oa = ProcessTools.executeProcess(pb);
- oa.shouldHaveExitValue(0);
+ // Ignore adapter creation failures
+ if (oa.getExitValue() != 0 && !oa.getStderr().contains("Out of space in CodeCache for adapters")) {
+ oa.reportDiagnosticSummary();
+ throw new RuntimeException("VM finished with exit code " + oa.getExitValue());
+ }
String stdout = oa.getStdout();
Pattern pattern = Pattern.compile("full_count=(\\d)");
diff --git a/test/hotspot/jtreg/compiler/gcbarriers/TestArrayCopyWithLargeObjectAlignment.java b/test/hotspot/jtreg/compiler/gcbarriers/TestArrayCopyWithLargeObjectAlignment.java
new file mode 100644
index 0000000000000..dd2d485fb76df
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/gcbarriers/TestArrayCopyWithLargeObjectAlignment.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package compiler.gcbarriers;
+
+import java.util.Arrays;
+
+/**
+ * @test
+ * @bug 8312749
+ * @summary Test that, when using a larger object alignment, ZGC arraycopy
+ * barriers are only applied to actual OOPs, and not to object
+ * alignment padding words.
+ * @requires vm.gc.ZGenerational
+ * @run main/othervm -Xbatch -XX:-TieredCompilation
+ * -XX:CompileOnly=compiler.gcbarriers.TestArrayCopyWithLargeObjectAlignment::*
+ * -XX:ObjectAlignmentInBytes=16
+ * -XX:+UseZGC -XX:+ZGenerational
+ * compiler.gcbarriers.TestArrayCopyWithLargeObjectAlignment
+ */
+
+public class TestArrayCopyWithLargeObjectAlignment {
+
+ static Object[] doCopyOf(Object[] array) {
+ return Arrays.copyOf(array, array.length);
+ }
+
+ static Object[] doClone(Object[] array) {
+ return array.clone();
+ }
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 10_000; i++) {
+ // This test allocates an array 'a', copies it into a new array 'b'
+ // using Arrays.copyOf, and clones 'b' into yet another array. For
+ // ObjectAlignmentInBytes=16, the intrinsic implementation of
+ // Arrays.copyOf leaves the object alignment padding word "b[1]"
+ // untouched, preserving the badHeapWordVal value '0xbaadbabe'. The
+ // test checks that this padding word is not processed as a valid
+ // OOP by the ZGC arraycopy stub underlying the intrinsic
+ // implementation of Object.clone. Allocating b using the intrinsic
+ // implementation of Arrays.copyOf is key to reproducing the issue
+ // because, unlike regular (fast or slow) array allocation,
+ // Arrays.copyOf does not zero-clear the padding word.
+ Object[] a = {new Object()};
+ Object[] b = doCopyOf(a);
+ doClone(b);
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
index 57fc369f4f32e..225b60e0ec2dc 100644
--- a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
+++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
@@ -84,7 +84,7 @@ public static boolean methodIsIgnoredBySecurityStackWalk(HotSpotResolvedJavaMeth
}
public static HotSpotResolvedObjectType lookupType(String name,
- Class> accessClass, boolean resolve) throws ClassNotFoundException {
+ Class> accessClass, boolean resolve) throws NoClassDefFoundError {
if (accessClass == null) {
throw new NullPointerException();
}
@@ -94,11 +94,7 @@ public static HotSpotResolvedObjectType lookupType(String name,
public static HotSpotResolvedObjectType lookupTypeHelper(String name,
Class> accessingClass, boolean resolve) {
- try {
- return lookupType(name, accessingClass, resolve);
- } catch (ClassNotFoundException e) {
- throw (NoClassDefFoundError) new NoClassDefFoundError().initCause(e);
- }
+ return lookupType(name, accessingClass, resolve);
}
public static Object lookupConstantInPool(ConstantPool constantPool, int cpi, boolean resolve) {
diff --git a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/LookupTypeTest.java b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/LookupTypeTest.java
index 1593bffa62c49..3f149c9c53e7d 100644
--- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/LookupTypeTest.java
+++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/LookupTypeTest.java
@@ -29,6 +29,8 @@
* @library ../common/patches
* @modules java.base/jdk.internal.access
* @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot
+ * jdk.internal.vm.ci/jdk.vm.ci.runtime
+ * jdk.internal.vm.ci/jdk.vm.ci.meta
* @build jdk.internal.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
* -XX:-UseJVMCICompiler
@@ -43,35 +45,64 @@
import jdk.test.lib.Asserts;
import jdk.test.lib.Utils;
import jdk.vm.ci.hotspot.CompilerToVMHelper;
+import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+import jdk.vm.ci.meta.MetaAccessProvider;
+import jdk.vm.ci.meta.ResolvedJavaType;
-import java.util.HashSet;
-import java.util.Set;
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayWriter;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
public class LookupTypeTest {
+
+ /**
+ * Abstracts which lookup method is being tested.
+ */
+ public interface Lookup {
+ ResolvedJavaType lookupType(String name, Class> accessingClass, boolean resolve);
+ }
+
public static void main(String args[]) {
LookupTypeTest test = new LookupTypeTest();
- for (TestCase tcase : createTestCases()) {
- test.runTest(tcase);
+
+ // Test CompilerToVM.lookupType
+ for (TestCase tcase : createTestCases(false, true)) {
+ test.runTest(tcase, CompilerToVMHelper::lookupType);
+ }
+
+ // Test HotSpotJVMCIRuntime.lookupType
+ HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
+ MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
+ for (TestCase tcase : createTestCases(true, false)) {
+ test.runTest(tcase, (name, accessingClass, resolve) -> (ResolvedJavaType) runtime.lookupType(name,
+ (HotSpotResolvedObjectType) metaAccess.lookupJavaType(accessingClass), resolve));
}
}
- private static Set createTestCases() {
- Set result = new HashSet<>();
+ private static List createTestCases(boolean allowPrimitive, boolean allowNullAccessingClass) {
+ List result = new ArrayList<>();
// a primitive class
- result.add(new TestCase(Utils.toJVMTypeSignature(int.class),
+ if (allowPrimitive) {
+ result.add(new TestCase(Utils.toJVMTypeSignature(int.class),
+ LookupTypeTest.class, true, true));
+ } else {
+ result.add(new TestCase(Utils.toJVMTypeSignature(int.class),
LookupTypeTest.class, true, false, InternalError.class));
+ }
// lookup not existing class
result.add(new TestCase("Lsome_not_existing;", LookupTypeTest.class,
- true, false, ClassNotFoundException.class));
+ true, false, NoClassDefFoundError.class));
// lookup invalid classname
result.add(new TestCase("L!@#$%^&**()[]{}?;", LookupTypeTest.class,
- true, false, ClassNotFoundException.class));
+ true, false, NoClassDefFoundError.class));
// lookup package private class
result.add(new TestCase(
"Lcompiler/jvmci/compilerToVM/testcases/PackagePrivateClass;",
LookupTypeTest.class, true, false,
- ClassNotFoundException.class));
+ NoClassDefFoundError.class));
// lookup usual class with resolve=true
result.add(new TestCase(Utils.toJVMTypeSignature(SingleSubclass.class),
LookupTypeTest.class, true, true));
@@ -80,25 +111,30 @@ private static Set createTestCases() {
Utils.toJVMTypeSignature(DoNotExtendClass.class),
LookupTypeTest.class, false, true));
// lookup usual class with null accessor
- result.add(new TestCase(
+ if (allowNullAccessingClass) {
+ result.add(new TestCase(
Utils.toJVMTypeSignature(MultiSubclassedClass.class), null,
false, false, NullPointerException.class));
+ }
return result;
}
- private void runTest(TestCase tcase) {
+ private void runTest(TestCase tcase, Lookup lookup) {
System.out.println(tcase);
- HotSpotResolvedObjectType metaspaceKlass;
+ ResolvedJavaType metaspaceKlass;
try {
- metaspaceKlass = CompilerToVMHelper.lookupType(tcase.className,
+ metaspaceKlass = lookup.lookupType(tcase.className,
tcase.accessing, tcase.resolve);
} catch (Throwable t) {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ t.printStackTrace(new PrintStream(bos));
+ String tString = bos.toString();
Asserts.assertNotNull(tcase.expectedException,
- "Assumed no exception, but got " + t);
+ "Assumed no exception, but got " + tString);
Asserts.assertFalse(tcase.isPositive,
- "Got unexpected exception " + t);
+ "Got unexpected exception " + tString);
Asserts.assertEQ(t.getClass(), tcase.expectedException,
- "Unexpected exception");
+ "Unexpected exception: " + tString);
// passed
return;
}
diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestDynamicConstant.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestDynamicConstant.java
index 05f44fcdb7709..c69c4e5a34556 100644
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestDynamicConstant.java
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestDynamicConstant.java
@@ -271,8 +271,8 @@ private static void assertNoEagerConstantResolution(Class> testClass, Constant
private static void assertLookupBMIDoesNotInvokeBM(MetaAccessProvider metaAccess, Class> testClass) throws Exception {
ResolvedJavaMethod shouldNotBeCalled = metaAccess.lookupJavaMethod(testClass.getDeclaredMethod("shouldNotBeCalled"));
ConstantPool cp = shouldNotBeCalled.getConstantPool();
- int cpi = getFirstInvokedynamicOperand(shouldNotBeCalled);
- BootstrapMethodInvocation bmi = cp.lookupBootstrapMethodInvocation(cpi, INVOKEDYNAMIC);
+ int rawIndex = getFirstInvokedynamicOperand(shouldNotBeCalled);
+ BootstrapMethodInvocation bmi = cp.lookupBootstrapMethodInvocation(rawIndex, INVOKEDYNAMIC);
Assert.assertEquals(bmi.getName(), "do_shouldNotBeCalled");
Assert.assertEquals(bmi.getMethod().getName(), "shouldNotBeCalledBSM");
}
@@ -408,8 +408,8 @@ private static int getFirstInvokedynamicOperand(ResolvedJavaMethod method) {
* Ensures that loadReferencedType for an invokedynamic call site does not throw an exception.
*/
private static void testLoadReferencedType(ResolvedJavaMethod method, ConstantPool cp) {
- int cpi = getFirstInvokedynamicOperand(method);
- cp.loadReferencedType(cpi, INVOKEDYNAMIC, false);
+ int rawIndex = getFirstInvokedynamicOperand(method);
+ cp.loadReferencedType(rawIndex, INVOKEDYNAMIC, false);
}
// @formatter:off
diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotJVMCIRuntime.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotJVMCIRuntime.java
index 29a3508d87705..21a9575b28b06 100644
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotJVMCIRuntime.java
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotJVMCIRuntime.java
@@ -183,4 +183,9 @@ public void jniEnomemTest() throws Exception {
output.shouldNotHaveExitValue(0);
}
}
+
+ @Test
+ public void lookupTypeTest() throws Exception {
+ // This is tested by compiler/jvmci/compilerToVM/LookupTypeTest.java
+ }
}
diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantPoolTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantPoolTest.java
index 2fb53b3825629..26fcedb64d41c 100644
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantPoolTest.java
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ConstantPoolTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,13 +37,21 @@
*/
package jdk.vm.ci.runtime.test;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+
import org.testng.Assert;
import org.testng.annotations.Test;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaField;
import jdk.vm.ci.meta.JavaMethod;
import jdk.vm.ci.meta.MetaAccessProvider;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
import jdk.vm.ci.runtime.JVMCI;
public class ConstantPoolTest {
@@ -80,8 +88,12 @@ static Object cloneObjectArray(Object[] arr) {
return arr.clone();
}
- public static final int ALOAD_0 = 42; // 0x2A
- public static final int INVOKEVIRTUAL = 182; // 0xB6
+ public static final int ICONST_0 = 3;
+ public static final int ALOAD_0 = 42;
+ public static final int ALOAD_1 = 43;
+ public static final int GETSTATIC = 178;
+ public static final int INVOKEVIRTUAL = 182;
+ public static final int INVOKEDYNAMIC = 186;
public static int beU2(byte[] data, int bci) {
return ((data[bci] & 0xff) << 8) | (data[bci + 1] & 0xff);
@@ -91,6 +103,10 @@ public static int beU1(byte[] data, int bci) {
return data[bci] & 0xff;
}
+ public static int beS4(byte[] data, int bci) {
+ return (data[bci] << 24) | ((data[bci + 1] & 0xff) << 16) | ((data[bci + 2] & 0xff) << 8) | (data[bci + 3] & 0xff);
+ }
+
@Test
public void lookupArrayCloneMethodTest() throws Exception {
MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
@@ -108,4 +124,113 @@ public void lookupArrayCloneMethodTest() throws Exception {
}
}
}
+
+ static int someStaticField = 1;
+ static int getStaticField() {
+ return someStaticField;
+ }
+
+ @Test
+ public void lookupFieldTest() throws Exception {
+ MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
+ ResolvedJavaType type = metaAccess.lookupJavaType(ConstantPoolTest.class);
+
+ String methodName = "getStaticField";
+ Signature methodSig = metaAccess.parseMethodDescriptor("()I");
+ ResolvedJavaMethod m = type.findMethod(methodName, methodSig);
+ Assert.assertNotNull(m);
+
+ // Expected:
+ // 0: getstatic "someStaticField":"I";
+ // 3: ireturn;
+ byte[] bytecode = m.getCode();
+ Assert.assertNotNull(bytecode);
+ Assert.assertEquals(4, bytecode.length);
+ Assert.assertEquals(GETSTATIC, beU1(bytecode, 0));
+ int rawIndex = beU2(bytecode, 1);
+ JavaField field = m.getConstantPool().lookupField(rawIndex, m, GETSTATIC);
+ Assert.assertEquals("someStaticField", field.getName(), "Wrong field name; rawIndex = " + rawIndex + ";");
+ }
+
+ static String concatString1(String a, String b) {
+ return a + b;
+ }
+
+ static String concatString2(String a, String b) {
+ return a + b;
+ }
+
+ static void invokeHandle(MethodHandle mh) throws Throwable {
+ mh.invokeExact(0);
+ }
+
+ static void intFunc(int t) {}
+
+ @Test
+ public void lookupAppendixTest() throws Throwable {
+ // We want at least two indy bytecodes -- with a single indy, the rawIndex is -1,
+ // or 0xffffffff. Even if we load it with the wrong endianness, it will still come
+ // "correctly" out as -1.
+ concatString1("aaa", "bbb"); // force the indy to be resolved
+ concatString2("aaa", "bbb"); // force the indy to be resolved
+
+ MethodHandles.Lookup lookup = MethodHandles.lookup();
+ MethodType mt = MethodType.methodType(void.class, int.class);
+ MethodHandle mh = lookup.findStatic(ConstantPoolTest.class, "intFunc", mt);
+ invokeHandle(mh);
+
+ lookupAppendixTest_dynamic("concatString1");
+ lookupAppendixTest_dynamic("concatString2");
+ lookupAppendixTest_virtual();
+ }
+
+ public void lookupAppendixTest_dynamic(String methodName) throws Exception {
+ MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
+ ResolvedJavaType type = metaAccess.lookupJavaType(ConstantPoolTest.class);
+ Signature methodSig = metaAccess.parseMethodDescriptor("(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+ ResolvedJavaMethod m = type.findMethod(methodName, methodSig);
+ Assert.assertNotNull(m);
+
+ // Expected:
+ // aload_0;
+ // aload_1;
+ // invokedynamic ...StringConcatFactory.makeConcatWithConstants...
+ byte[] bytecode = m.getCode();
+ Assert.assertNotNull(bytecode);
+ Assert.assertEquals(8, bytecode.length);
+ Assert.assertEquals(ALOAD_0, beU1(bytecode, 0));
+ Assert.assertEquals(ALOAD_1, beU1(bytecode, 1));
+ Assert.assertEquals(INVOKEDYNAMIC, beU1(bytecode, 2));
+
+ // Note: internally HotSpot stores the indy index as a native int32, but m.getCode() byte-swaps all such
+ // indices so they appear to be big-endian.
+ int rawIndex = beS4(bytecode, 3);
+ JavaConstant constant = m.getConstantPool().lookupAppendix(rawIndex, INVOKEDYNAMIC);
+ Assert.assertTrue(constant.toString().startsWith("Object["), "wrong appendix: " + constant);
+ }
+
+ public void lookupAppendixTest_virtual() throws Exception {
+ MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
+ ResolvedJavaType type = metaAccess.lookupJavaType(ConstantPoolTest.class);
+ Signature methodSig = metaAccess.parseMethodDescriptor("(Ljava/lang/invoke/MethodHandle;)V");
+ ResolvedJavaMethod m = type.findMethod("invokeHandle", methodSig);
+ Assert.assertNotNull(m);
+
+ // Expected
+ // aload_0
+ // iconst_0
+ // invokevirtual #rawIndex // Method java/lang/invoke/MethodHandle.invokeExact:(I)V
+ byte[] bytecode = m.getCode();
+ Assert.assertNotNull(bytecode);
+ Assert.assertEquals(6, bytecode.length);
+ Assert.assertEquals(ALOAD_0, beU1(bytecode, 0));
+ Assert.assertEquals(ICONST_0, beU1(bytecode, 1));
+ Assert.assertEquals(INVOKEVIRTUAL, beU1(bytecode, 2));
+
+ int rawIndex = beU2(bytecode, 3);
+ //System.out.println("rawIndex = " + rawIndex);
+ JavaConstant constant = m.getConstantPool().lookupAppendix(rawIndex, INVOKEVIRTUAL);
+ //System.out.println("constant = " + constant);
+ Assert.assertTrue(constant.toString().startsWith("Object["), "wrong appendix: " + constant);
+ }
}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
index 89900a639eeed..3e2db1541dd2f 100644
--- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
@@ -24,6 +24,7 @@
package compiler.lib.ir_framework;
import compiler.lib.ir_framework.driver.irmatching.mapping.*;
+import compiler.lib.ir_framework.driver.irmatching.parser.VMInfo;
import compiler.lib.ir_framework.shared.CheckedTestFrameworkException;
import compiler.lib.ir_framework.shared.TestFormat;
import compiler.lib.ir_framework.shared.TestFormatException;
@@ -69,6 +70,17 @@
* Using this IR node expects another user provided string in the constraint list of
* {@link IR#failOn()} and {@link IR#counts()}. They cannot be used as normal IR nodes.
* Trying to do so will result in a format violation error.
+ *