Merge branch 'master' into JDK-8348611 to fix conflict.

This commit is contained in:
Archie L. Cobbs 2025-05-01 13:40:59 -05:00
commit a356d884b2
652 changed files with 19483 additions and 5631 deletions

View File

@ -5,3 +5,7 @@ trim_trailing_whitespace = true
[Makefile]
trim_trailing_whitespace = true
[src/hotspot/**.{cpp,hpp,h}]
indent_style = space
indent_size = 2

View File

@ -594,7 +594,7 @@ to compile successfully without issues.</p>
</tr>
<tr class="odd">
<td>Windows</td>
<td>Microsoft Visual Studio 2022 version 17.6.5</td>
<td>Microsoft Visual Studio 2022 version 17.13.2</td>
</tr>
</tbody>
</table>

View File

@ -390,11 +390,11 @@ possible to compile the JDK with both older and newer versions, but the closer
you stay to this list, the more likely you are to compile successfully without
issues.
| Operating system | Toolchain version |
| ------------------ | ------------------------------------------- |
| Linux | gcc 14.2.0 |
| macOS | Apple Xcode 14.3.1 (using clang 14.0.3) |
| Windows | Microsoft Visual Studio 2022 version 17.6.5 |
| Operating system | Toolchain version |
| ------------------ | -------------------------------------------- |
| Linux | gcc 14.2.0 |
| macOS | Apple Xcode 14.3.1 (using clang 14.0.3) |
| Windows | Microsoft Visual Studio 2022 version 17.13.2 |
All compilers are expected to be able to handle the C11 language standard for
C, and C++14 for C++.

View File

@ -174,9 +174,11 @@ else
JRE_IMAGE_HOMEDIR := $(JRE_IMAGE_DIR)
JDK_BUNDLE_SUBDIR := jdk-$(VERSION_NUMBER)
JRE_BUNDLE_SUBDIR := jre-$(VERSION_NUMBER)
STATIC_JDK_BUNDLE_SUBDIR := static-jdk-$(VERSION_NUMBER)
ifneq ($(DEBUG_LEVEL), release)
JDK_BUNDLE_SUBDIR := $(JDK_BUNDLE_SUBDIR)/$(DEBUG_LEVEL)
JRE_BUNDLE_SUBDIR := $(JRE_BUNDLE_SUBDIR)/$(DEBUG_LEVEL)
STATIC_JDK_BUNDLE_SUBDIR := $(STATIC_JDK_BUNDLE_SUBDIR)/$(DEBUG_LEVEL)
endif
# In certain situations, the JDK_IMAGE_DIR points to an image without the
# the symbols and demos. If so, the symobls and demos can be found in a
@ -500,6 +502,21 @@ ifneq ($(filter static-libs-graal-bundles, $(MAKECMDGOALS)), )
STATIC_LIBS_GRAAL_TARGETS += $(BUILD_STATIC_LIBS_GRAAL_BUNDLE)
endif
#################################################################################
ifneq ($(filter static-jdk-bundles, $(MAKECMDGOALS)), )
STATIC_JDK_BUNDLE_FILES := $(call FindFiles, $(STATIC_JDK_IMAGE_DIR))
$(eval $(call SetupBundleFile, BUILD_STATIC_JDK_BUNDLE, \
BUNDLE_NAME := $(STATIC_JDK_BUNDLE_NAME), \
FILES := $(STATIC_JDK_BUNDLE_FILES), \
BASE_DIRS := $(STATIC_JDK_IMAGE_DIR), \
SUBDIR := $(STATIC_JDK_BUNDLE_SUBDIR), \
))
STATIC_JDK_TARGETS += $(BUILD_STATIC_JDK_BUNDLE)
endif
################################################################################
product-bundles: $(PRODUCT_TARGETS)
@ -510,11 +527,12 @@ docs-javase-bundles: $(DOCS_JAVASE_TARGETS)
docs-reference-bundles: $(DOCS_REFERENCE_TARGETS)
static-libs-bundles: $(STATIC_LIBS_TARGETS)
static-libs-graal-bundles: $(STATIC_LIBS_GRAAL_TARGETS)
static-jdk-bundles: $(STATIC_JDK_TARGETS)
jcov-bundles: $(JCOV_TARGETS)
.PHONY: product-bundles test-bundles \
docs-jdk-bundles docs-javase-bundles docs-reference-bundles \
static-libs-bundles static-libs-graal-bundles jcov-bundles
static-libs-bundles static-libs-graal-bundles static-jdk-bundles jcov-bundles
################################################################################

View File

@ -98,7 +98,7 @@ JAVADOC_DISABLED_DOCLINT_PACKAGES := org.w3c.* javax.smartcardio
JAVADOC_OPTIONS := -use -keywords -notimestamp \
-serialwarn -encoding ISO-8859-1 -docencoding UTF-8 -breakiterator \
-splitIndex --system none -javafx --expand-requires transitive \
--override-methods=summary
--override-methods=summary --syntax-highlight
# The reference options must stay stable to allow for comparisons across the
# development cycle.

View File

@ -66,7 +66,7 @@ endif
# default classlist is minimal, let's filter out the '@cp' lines until we can
# find a proper solution.
CLASSLIST_FILE_VM_OPTS = \
-Duser.language=en -Duser.country=US
-Duser.language=en -Duser.country=US --enable-native-access=ALL-UNNAMED
# Save the stderr output of the command and print it along with stdout in case
# something goes wrong.

View File

@ -875,6 +875,12 @@ $(eval $(call SetupTarget, static-libs-graal-bundles, \
DEPS := static-libs-graal-image, \
))
$(eval $(call SetupTarget, static-jdk-bundles, \
MAKEFILE := Bundles, \
TARGET := static-jdk-bundles, \
DEPS := static-jdk-image, \
))
ifeq ($(JCOV_ENABLED), true)
$(eval $(call SetupTarget, jcov-bundles, \
MAKEFILE := Bundles, \

View File

@ -520,8 +520,21 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER],
# Silence them for now.
UBSAN_CHECKS="-fsanitize=undefined -fsanitize=float-divide-by-zero -fno-sanitize=shift-base -fno-sanitize=alignment \
$ADDITIONAL_UBSAN_CHECKS"
UBSAN_CFLAGS="$UBSAN_CHECKS -Wno-stringop-truncation -Wno-format-overflow -Wno-array-bounds -Wno-stringop-overflow -fno-omit-frame-pointer -DUNDEFINED_BEHAVIOR_SANITIZER"
UBSAN_CFLAGS="$UBSAN_CHECKS -Wno-array-bounds -fno-omit-frame-pointer -DUNDEFINED_BEHAVIOR_SANITIZER"
if test "x$TOOLCHAIN_TYPE" = "xgcc"; then
UBSAN_CFLAGS="$UBSAN_CFLAGS -Wno-format-overflow -Wno-stringop-overflow -Wno-stringop-truncation"
fi
UBSAN_LDFLAGS="$UBSAN_CHECKS"
# On AIX, the llvm_symbolizer is not found out of the box, so we have to provide the
# full qualified llvm_symbolizer path in the __ubsan_default_options() function in
# make/data/ubsan/ubsan_default_options.c. To get it there we compile our sources
# with an additional define LLVM_SYMBOLIZER, which we set here.
# To calculate the correct llvm_symbolizer path we can use the location of the compiler, because
# their relation is fixed.
if test "x$TOOLCHAIN_TYPE" = "xclang" && test "x$OPENJDK_TARGET_OS" = "xaix"; then
UBSAN_CFLAGS="$UBSAN_CFLAGS -fno-sanitize=function,vptr -DLLVM_SYMBOLIZER=$(dirname $(dirname $CC))/tools/ibm-llvm-symbolizer"
UBSAN_LDFLAGS="$UBSAN_LDFLAGS -fno-sanitize=function,vptr -Wl,-bbigtoc"
fi
UTIL_ARG_ENABLE(NAME: ubsan, DEFAULT: false, RESULT: UBSAN_ENABLED,
DESC: [enable UndefinedBehaviorSanitizer],
CHECK_AVAILABLE: [

View File

@ -846,10 +846,12 @@ SVE_CFLAGS := @SVE_CFLAGS@
JDK_IMAGE_SUBDIR := jdk
JRE_IMAGE_SUBDIR := jre
JCOV_IMAGE_SUBDIR := jdk-jcov
STATIC_JDK_IMAGE_SUBDIR := static-jdk
# Colon left out to be able to override output dir for bootcycle-images
JDK_IMAGE_DIR = $(IMAGES_OUTPUTDIR)/$(JDK_IMAGE_SUBDIR)
JRE_IMAGE_DIR = $(IMAGES_OUTPUTDIR)/$(JRE_IMAGE_SUBDIR)
STATIC_JDK_IMAGE_DIR = $(IMAGES_OUTPUTDIR)/$(STATIC_JDK_IMAGE_SUBDIR)
JCOV_IMAGE_DIR = $(IMAGES_OUTPUTDIR)/$(JCOV_IMAGE_SUBDIR)
# Test image, as above
@ -929,6 +931,7 @@ DOCS_JAVASE_BUNDLE_NAME := javase-$(BASE_NAME)_doc-api-spec$(DEBUG_PART).tar.gz
DOCS_REFERENCE_BUNDLE_NAME := jdk-reference-$(BASE_NAME)_doc-api-spec$(DEBUG_PART).tar.gz
STATIC_LIBS_BUNDLE_NAME := jdk-$(BASE_NAME)_bin-static-libs$(DEBUG_PART).tar.gz
STATIC_LIBS_GRAAL_BUNDLE_NAME := jdk-$(BASE_NAME)_bin-static-libs-graal$(DEBUG_PART).tar.gz
STATIC_JDK_BUNDLE_NAME := static-jdk-$(BASE_NAME)_bin$(DEBUG_PART).$(JDK_BUNDLE_EXTENSION)
JCOV_BUNDLE_NAME := jdk-jcov-$(BASE_NAME)_bin$(DEBUG_PART).$(JDK_BUNDLE_EXTENSION)
JDK_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(JDK_BUNDLE_NAME)
@ -939,6 +942,7 @@ TEST_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(TEST_BUNDLE_NAME)
DOCS_JDK_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(DOCS_JDK_BUNDLE_NAME)
DOCS_JAVASE_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(DOCS_JAVASE_BUNDLE_NAME)
DOCS_REFERENCE_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(DOCS_REFERENCE_BUNDLE_NAME)
STATIC_JDK_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(STATIC_JDK_BUNDLE_NAME)
JCOV_BUNDLE := $(BUNDLES_OUTPUTDIR)/$(JCOV_BUNDLE_NAME)
# This macro is called to allow inclusion of closed source counterparts.

View File

@ -1090,7 +1090,7 @@ var getJibProfilesDependencies = function (input, common) {
var devkit_platform_revisions = {
linux_x64: "gcc14.2.0-OL6.4+1.0",
macosx: "Xcode14.3.1+1.0",
windows_x64: "VS2022-17.6.5+1.0",
windows_x64: "VS2022-17.13.2+1.0",
linux_aarch64: "gcc14.2.0-OL7.6+1.0",
linux_arm: "gcc8.2.0-Fedora27+1.0",
linux_ppc64le: "gcc14.2.0-Fedora_41+1.0",

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -43,6 +43,18 @@
#define ATTRIBUTE_USED
#endif
// On AIX, the llvm_symbolizer is not found out of the box, so we have to provide the
// full qualified llvm_symbolizer path in the __ubsan_default_options() function.
// To get it here we compile our sources with an additional define LLVM_SYMBOLIZER
// containing the path, which we set in make/autoconf/jdk-options.m4.
#ifdef LLVM_SYMBOLIZER
#define _LLVM_SYMBOLIZER(X) ",external_symbolizer_path=" X_LLVM_SYMBOLIZER(X)
#define X_LLVM_SYMBOLIZER(X) #X
#else
#define LLVM_SYMBOLIZER
#define _LLVM_SYMBOLIZER(X)
#endif
// Override weak symbol exposed by UBSan to override default options. This is called by UBSan
// extremely early during library loading, before main is called. We need to override the default
// options because by default UBSan only prints a warning for each occurrence. We want jtreg tests
@ -50,5 +62,5 @@
// thread so it is easier to track down. You can override these options by setting the environment
// variable UBSAN_OPTIONS.
ATTRIBUTE_DEFAULT_VISIBILITY ATTRIBUTE_USED const char* __ubsan_default_options() {
return "halt_on_error=1,print_stacktrace=1";
return "halt_on_error=1,print_stacktrace=1" _LLVM_SYMBOLIZER(LLVM_SYMBOLIZER);
}

View File

@ -56,16 +56,22 @@ BUILD_DIR="${SCRIPT_DIR}/../../build/devkit"
UNAME_SYSTEM=`uname -s`
UNAME_RELEASE=`uname -r`
UNAME_OS=`uname -o`
# Detect cygwin or WSL
IS_CYGWIN=`echo $UNAME_SYSTEM | grep -i CYGWIN`
IS_WSL=`echo $UNAME_RELEASE | grep Microsoft`
IS_MSYS=`echo $UNAME_OS | grep -i Msys`
MSYS2_ARG_CONV_EXCL="*" # make "cmd.exe /c" work for msys2
CMD_EXE="cmd.exe /c"
if test "x$IS_CYGWIN" != "x"; then
BUILD_ENV="cygwin"
elif test "x$IS_MSYS" != "x"; then
BUILD_ENV="cygwin"
elif test "x$IS_WSL" != "x"; then
BUILD_ENV="wsl"
else
echo "Unknown environment; only Cygwin and WSL are supported."
echo "Unknown environment; only Cygwin/MSYS2/WSL are supported."
exit 1
fi
@ -76,7 +82,7 @@ elif test "x$BUILD_ENV" = "xwsl"; then
fi
# Work around the insanely named ProgramFiles(x86) env variable
PROGRAMFILES_X86="$($WINDOWS_PATH_TO_UNIX_PATH "$(cmd.exe /c set | sed -n 's/^ProgramFiles(x86)=//p' | tr -d '\r')")"
PROGRAMFILES_X86="$($WINDOWS_PATH_TO_UNIX_PATH "$(${CMD_EXE} set | sed -n 's/^ProgramFiles(x86)=//p' | tr -d '\r')")"
PROGRAMFILES="$($WINDOWS_PATH_TO_UNIX_PATH "$PROGRAMFILES")"
case $VS_VERSION in
@ -99,13 +105,15 @@ esac
# Find Visual Studio installation dir
VSNNNCOMNTOOLS=`cmd.exe /c echo %VS${VS_VERSION_NUM_NODOT}COMNTOOLS% | tr -d '\r'`
VSNNNCOMNTOOLS=`${CMD_EXE} echo %VS${VS_VERSION_NUM_NODOT}COMNTOOLS% | tr -d '\r'`
VSNNNCOMNTOOLS="$($WINDOWS_PATH_TO_UNIX_PATH "$VSNNNCOMNTOOLS")"
if [ -d "$VSNNNCOMNTOOLS" ]; then
VS_INSTALL_DIR="$($WINDOWS_PATH_TO_UNIX_PATH "$VSNNNCOMNTOOLS/../..")"
VS_INSTALL_DIR="$VSNNNCOMNTOOLS/../.."
else
VS_INSTALL_DIR="${MSVC_PROGRAMFILES_DIR}/Microsoft Visual Studio/$VS_VERSION"
VS_INSTALL_DIR="$(ls -d "${VS_INSTALL_DIR}/"{Community,Professional,Enterprise} 2>/dev/null | head -n1)"
fi
echo "VSNNNCOMNTOOLS: $VSNNNCOMNTOOLS"
echo "VS_INSTALL_DIR: $VS_INSTALL_DIR"
# Extract semantic version
@ -180,7 +188,11 @@ cp $DEVKIT_ROOT/VC/redist/arm64/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/arm64
################################################################################
# Copy SDK files
SDK_INSTALL_DIR="$PROGRAMFILES_X86/Windows Kits/$SDK_VERSION"
SDK_INSTALL_DIR=`${CMD_EXE} echo %WindowsSdkDir% | tr -d '\r'`
SDK_INSTALL_DIR="$($WINDOWS_PATH_TO_UNIX_PATH "$SDK_INSTALL_DIR")"
if [ ! -d "$SDK_INSTALL_DIR" ]; then
SDK_INSTALL_DIR="$PROGRAMFILES_X86/Windows Kits/$SDK_VERSION"
fi
echo "SDK_INSTALL_DIR: $SDK_INSTALL_DIR"
SDK_FULL_VERSION="$(ls "$SDK_INSTALL_DIR/bin" | sort -r -n | head -n1)"

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,6 +31,8 @@
*/
package build.tools.classlist;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
@ -59,6 +61,7 @@ public class HelloClasslist {
private static final Logger LOGGER = Logger.getLogger("Hello");
@SuppressWarnings("restricted")
public static void main(String ... args) throws Throwable {
FileSystems.getDefault();
@ -141,6 +144,7 @@ public class HelloClasslist {
HelloClasslist.class.getMethod("staticMethod_V").invoke(null);
var obj = HelloClasslist.class.getMethod("staticMethod_L_L", Object.class).invoke(null, instance);
HelloClasslist.class.getField("field").get(instance);
MethodHandles.Lookup.ClassOption.class.getEnumConstants();
// A selection of trivial and relatively common MH operations
invoke(MethodHandles.identity(double.class), 1.0);
@ -160,6 +164,9 @@ public class HelloClasslist {
case B b -> b.b;
default -> 17;
};
// record run-time methods
o.equals(new B(5));
o.hashCode();
LOGGER.log(Level.FINE, "Value: " + value);
// The Striped64$Cell is loaded rarely only when there's a contention among
@ -167,6 +174,10 @@ public class HelloClasslist {
// an inconsistency in the classlist between builds (see JDK-8295951).
// To avoid the problem, load the class explicitly.
Class<?> striped64Class = Class.forName("java.util.concurrent.atomic.Striped64$Cell");
// Initialize FFM linkers
var signature = FunctionDescriptor.ofVoid();
Linker.nativeLinker().downcallHandle(signature);
}
public HelloClasslist() {}

View File

@ -158,6 +158,7 @@ endif
$(eval $(call SetupJdkLibrary, BUILD_LIBSYSLOOKUP, \
NAME := syslookup, \
EXTRA_HEADER_DIRS := java.base:libjava, \
LD_SET_ORIGIN := false, \
LDFLAGS_linux := -Wl$(COMMA)--no-as-needed, \
LDFLAGS_aix := -brtl -bexpfull, \

View File

@ -1,3 +0,0 @@
[*.{cpp,hpp,c,h}]
indent_style = space
indent_size = 2

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2014, 2024, Red Hat, Inc. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
@ -2296,6 +2296,26 @@ bool Matcher::match_rule_supported(int opcode) {
return false;
}
break;
case Op_FmaHF:
// UseFMA flag also needs to be checked along with FEAT_FP16
if (!UseFMA || !is_feat_fp16_supported()) {
return false;
}
break;
case Op_AddHF:
case Op_SubHF:
case Op_MulHF:
case Op_DivHF:
case Op_MinHF:
case Op_MaxHF:
case Op_SqrtHF:
// Half-precision floating point scalar operations require FEAT_FP16
// to be available. FEAT_FP16 is enabled if both "fphp" and "asimdhp"
// features are supported.
if (!is_feat_fp16_supported()) {
return false;
}
break;
}
return true; // Per default match rules are supported.
@ -2306,11 +2326,11 @@ const RegMask* Matcher::predicate_reg_mask(void) {
}
bool Matcher::supports_vector_calling_convention(void) {
return EnableVectorSupport && UseVectorStubs;
return EnableVectorSupport;
}
OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
assert(EnableVectorSupport && UseVectorStubs, "sanity");
assert(EnableVectorSupport, "sanity");
int lo = V0_num;
int hi = V0_H_num;
if (ideal_reg == Op_VecX || ideal_reg == Op_VecA) {
@ -4599,6 +4619,15 @@ operand immF0()
interface(CONST_INTER);
%}
// Half Float (FP16) Immediate
operand immH()
%{
match(ConH);
op_cost(0);
format %{ %}
interface(CONST_INTER);
%}
//
operand immFPacked()
%{
@ -6942,6 +6971,21 @@ instruct loadConD(vRegD dst, immD con) %{
ins_pipe(fp_load_constant_d);
%}
// Load Half Float Constant
// The "ldr" instruction loads a 32-bit word from the constant pool into a
// 32-bit register but only the bottom half will be populated and the top
// 16 bits are zero.
instruct loadConH(vRegF dst, immH con) %{
match(Set dst con);
format %{
"ldrs $dst, [$constantaddress]\t# load from constant table: half float=$con\n\t"
%}
ins_encode %{
__ ldrs(as_FloatRegister($dst$$reg), $constantaddress($con));
%}
ins_pipe(fp_load_constant_s);
%}
// Store Instructions
// Store Byte
@ -8144,6 +8188,7 @@ instruct castPP(iRegPNoSp dst)
instruct castII(iRegI dst)
%{
predicate(VerifyConstraintCasts == 0);
match(Set dst (CastII dst));
size(0);
@ -8153,8 +8198,22 @@ instruct castII(iRegI dst)
ins_pipe(pipe_class_empty);
%}
instruct castII_checked(iRegI dst, rFlagsReg cr)
%{
predicate(VerifyConstraintCasts > 0);
match(Set dst (CastII dst));
effect(KILL cr);
format %{ "# castII_checked of $dst" %}
ins_encode %{
__ verify_int_in_range(_idx, bottom_type()->is_int(), $dst$$Register, rscratch1);
%}
ins_pipe(pipe_slow);
%}
instruct castLL(iRegL dst)
%{
predicate(VerifyConstraintCasts == 0);
match(Set dst (CastLL dst));
size(0);
@ -8164,6 +8223,19 @@ instruct castLL(iRegL dst)
ins_pipe(pipe_class_empty);
%}
instruct castLL_checked(iRegL dst, rFlagsReg cr)
%{
predicate(VerifyConstraintCasts > 0);
match(Set dst (CastLL dst));
effect(KILL cr);
format %{ "# castLL_checked of $dst" %}
ins_encode %{
__ verify_long_in_range(_idx, bottom_type()->is_long(), $dst$$Register, rscratch1);
%}
ins_pipe(pipe_slow);
%}
instruct castFF(vRegF dst)
%{
match(Set dst (CastFF dst));
@ -13606,6 +13678,17 @@ instruct bits_reverse_L(iRegLNoSp dst, iRegL src)
// ============================================================================
// Floating Point Arithmetic Instructions
instruct addHF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (AddHF src1 src2));
format %{ "faddh $dst, $src1, $src2" %}
ins_encode %{
__ faddh($dst$$FloatRegister,
$src1$$FloatRegister,
$src2$$FloatRegister);
%}
ins_pipe(fp_dop_reg_reg_s);
%}
instruct addF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (AddF src1 src2));
@ -13636,6 +13719,17 @@ instruct addD_reg_reg(vRegD dst, vRegD src1, vRegD src2) %{
ins_pipe(fp_dop_reg_reg_d);
%}
instruct subHF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (SubHF src1 src2));
format %{ "fsubh $dst, $src1, $src2" %}
ins_encode %{
__ fsubh($dst$$FloatRegister,
$src1$$FloatRegister,
$src2$$FloatRegister);
%}
ins_pipe(fp_dop_reg_reg_s);
%}
instruct subF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (SubF src1 src2));
@ -13666,6 +13760,17 @@ instruct subD_reg_reg(vRegD dst, vRegD src1, vRegD src2) %{
ins_pipe(fp_dop_reg_reg_d);
%}
instruct mulHF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (MulHF src1 src2));
format %{ "fmulh $dst, $src1, $src2" %}
ins_encode %{
__ fmulh($dst$$FloatRegister,
$src1$$FloatRegister,
$src2$$FloatRegister);
%}
ins_pipe(fp_dop_reg_reg_s);
%}
instruct mulF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (MulF src1 src2));
@ -13696,6 +13801,20 @@ instruct mulD_reg_reg(vRegD dst, vRegD src1, vRegD src2) %{
ins_pipe(fp_dop_reg_reg_d);
%}
// src1 * src2 + src3 (half-precision float)
instruct maddHF_reg_reg(vRegF dst, vRegF src1, vRegF src2, vRegF src3) %{
match(Set dst (FmaHF src3 (Binary src1 src2)));
format %{ "fmaddh $dst, $src1, $src2, $src3" %}
ins_encode %{
assert(UseFMA, "Needs FMA instructions support.");
__ fmaddh($dst$$FloatRegister,
$src1$$FloatRegister,
$src2$$FloatRegister,
$src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
// src1 * src2 + src3
instruct maddF_reg_reg(vRegF dst, vRegF src1, vRegF src2, vRegF src3) %{
match(Set dst (FmaF src3 (Binary src1 src2)));
@ -13837,6 +13956,29 @@ instruct mnsubD_reg_reg(vRegD dst, vRegD src1, vRegD src2, vRegD src3, immD0 zer
ins_pipe(pipe_class_default);
%}
// Math.max(HH)H (half-precision float)
instruct maxHF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (MaxHF src1 src2));
format %{ "fmaxh $dst, $src1, $src2" %}
ins_encode %{
__ fmaxh($dst$$FloatRegister,
$src1$$FloatRegister,
$src2$$FloatRegister);
%}
ins_pipe(fp_dop_reg_reg_s);
%}
// Math.min(HH)H (half-precision float)
instruct minHF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (MinHF src1 src2));
format %{ "fminh $dst, $src1, $src2" %}
ins_encode %{
__ fminh($dst$$FloatRegister,
$src1$$FloatRegister,
$src2$$FloatRegister);
%}
ins_pipe(fp_dop_reg_reg_s);
%}
// Math.max(FF)F
instruct maxF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
@ -13894,6 +14036,16 @@ instruct minD_reg_reg(vRegD dst, vRegD src1, vRegD src2) %{
ins_pipe(fp_dop_reg_reg_d);
%}
instruct divHF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (DivHF src1 src2));
format %{ "fdivh $dst, $src1, $src2" %}
ins_encode %{
__ fdivh($dst$$FloatRegister,
$src1$$FloatRegister,
$src2$$FloatRegister);
%}
ins_pipe(fp_div_s);
%}
instruct divF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{
match(Set dst (DivF src1 src2));
@ -14067,6 +14219,16 @@ instruct sqrtF_reg(vRegF dst, vRegF src) %{
ins_pipe(fp_div_d);
%}
instruct sqrtHF_reg(vRegF dst, vRegF src) %{
match(Set dst (SqrtHF src));
format %{ "fsqrth $dst, $src" %}
ins_encode %{
__ fsqrth($dst$$FloatRegister,
$src$$FloatRegister);
%}
ins_pipe(fp_div_s);
%}
// Math.rint, floor, ceil
instruct roundD_reg(vRegD dst, vRegD src, immI rmode) %{
match(Set dst (RoundDoubleMode src rmode));
@ -17116,6 +17278,64 @@ instruct expandBitsL_memcon(iRegINoSp dst, memory8 mem, immL mask,
ins_pipe(pipe_slow);
%}
//----------------------------- Reinterpret ----------------------------------
// Reinterpret a half-precision float value in a floating point register to a general purpose register
instruct reinterpretHF2S(iRegINoSp dst, vRegF src) %{
match(Set dst (ReinterpretHF2S src));
format %{ "reinterpretHF2S $dst, $src" %}
ins_encode %{
__ smov($dst$$Register, $src$$FloatRegister, __ H, 0);
%}
ins_pipe(pipe_slow);
%}
// Reinterpret a half-precision float value in a general purpose register to a floating point register
instruct reinterpretS2HF(vRegF dst, iRegINoSp src) %{
match(Set dst (ReinterpretS2HF src));
format %{ "reinterpretS2HF $dst, $src" %}
ins_encode %{
__ mov($dst$$FloatRegister, __ H, 0, $src$$Register);
%}
ins_pipe(pipe_slow);
%}
// Without this optimization, ReinterpretS2HF (ConvF2HF src) would result in the following
// instructions (the first two are for ConvF2HF and the last instruction is for ReinterpretS2HF) -
// fcvt $tmp1_fpr, $src_fpr // Convert float to half-precision float
// mov $tmp2_gpr, $tmp1_fpr // Move half-precision float in FPR to a GPR
// mov $dst_fpr, $tmp2_gpr // Move the result from a GPR to an FPR
// The move from FPR to GPR in ConvF2HF and the move from GPR to FPR in ReinterpretS2HF
// can be omitted in this pattern, resulting in -
// fcvt $dst, $src // Convert float to half-precision float
instruct convF2HFAndS2HF(vRegF dst, vRegF src)
%{
match(Set dst (ReinterpretS2HF (ConvF2HF src)));
format %{ "convF2HFAndS2HF $dst, $src" %}
ins_encode %{
__ fcvtsh($dst$$FloatRegister, $src$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
// Without this optimization, ConvHF2F (ReinterpretHF2S src) would result in the following
// instructions (the first one is for ReinterpretHF2S and the last two are for ConvHF2F) -
// mov $tmp1_gpr, $src_fpr // Move the half-precision float from an FPR to a GPR
// mov $tmp2_fpr, $tmp1_gpr // Move the same value from GPR to an FPR
// fcvt $dst_fpr, $tmp2_fpr // Convert the half-precision float to 32-bit float
// The move from FPR to GPR in ReinterpretHF2S and the move from GPR to FPR in ConvHF2F
// can be omitted as the input (src) is already in an FPR required for the fcvths instruction
// resulting in -
// fcvt $dst, $src // Convert half-precision float to a 32-bit float
instruct convHF2SAndHF2F(vRegF dst, vRegF src)
%{
match(Set dst (ConvHF2F (ReinterpretHF2S src)));
format %{ "convHF2SAndHF2F $dst, $src" %}
ins_encode %{
__ fcvths($dst$$FloatRegister, $src$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
// ============================================================================
// This name is KNOWN by the ADLC and cannot be changed.
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type

View File

@ -2032,6 +2032,8 @@ void mvnw(Register Rd, Register Rm,
INSN(fsqrtd, 0b01, 0b000011);
INSN(fcvtd, 0b01, 0b000100); // Double-precision to single-precision
INSN(fsqrth, 0b11, 0b000011); // Half-precision sqrt
private:
void _fcvt_narrow_extend(FloatRegister Vd, SIMD_Arrangement Ta,
FloatRegister Vn, SIMD_Arrangement Tb, bool do_extend) {
@ -2059,37 +2061,68 @@ public:
#undef INSN
// Floating-point data-processing (2 source)
void data_processing(unsigned op31, unsigned type, unsigned opcode,
void data_processing(unsigned op31, unsigned type, unsigned opcode, unsigned op21,
FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) {
starti;
f(op31, 31, 29);
f(0b11110, 28, 24);
f(type, 23, 22), f(1, 21), f(opcode, 15, 10);
f(type, 23, 22), f(op21, 21), f(opcode, 15, 10);
rf(Vm, 16), rf(Vn, 5), rf(Vd, 0);
}
#define INSN(NAME, op31, type, opcode) \
#define INSN(NAME, op31, type, opcode, op21) \
void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) { \
data_processing(op31, type, opcode, Vd, Vn, Vm); \
data_processing(op31, type, opcode, op21, Vd, Vn, Vm); \
}
INSN(fabds, 0b011, 0b10, 0b110101);
INSN(fmuls, 0b000, 0b00, 0b000010);
INSN(fdivs, 0b000, 0b00, 0b000110);
INSN(fadds, 0b000, 0b00, 0b001010);
INSN(fsubs, 0b000, 0b00, 0b001110);
INSN(fmaxs, 0b000, 0b00, 0b010010);
INSN(fmins, 0b000, 0b00, 0b010110);
INSN(fnmuls, 0b000, 0b00, 0b100010);
INSN(fmuls, 0b000, 0b00, 0b000010, 0b1);
INSN(fdivs, 0b000, 0b00, 0b000110, 0b1);
INSN(fadds, 0b000, 0b00, 0b001010, 0b1);
INSN(fsubs, 0b000, 0b00, 0b001110, 0b1);
INSN(fmaxs, 0b000, 0b00, 0b010010, 0b1);
INSN(fmins, 0b000, 0b00, 0b010110, 0b1);
INSN(fnmuls, 0b000, 0b00, 0b100010, 0b1);
INSN(fabdd, 0b011, 0b11, 0b110101);
INSN(fmuld, 0b000, 0b01, 0b000010);
INSN(fdivd, 0b000, 0b01, 0b000110);
INSN(faddd, 0b000, 0b01, 0b001010);
INSN(fsubd, 0b000, 0b01, 0b001110);
INSN(fmaxd, 0b000, 0b01, 0b010010);
INSN(fmind, 0b000, 0b01, 0b010110);
INSN(fnmuld, 0b000, 0b01, 0b100010);
INSN(fmuld, 0b000, 0b01, 0b000010, 0b1);
INSN(fdivd, 0b000, 0b01, 0b000110, 0b1);
INSN(faddd, 0b000, 0b01, 0b001010, 0b1);
INSN(fsubd, 0b000, 0b01, 0b001110, 0b1);
INSN(fmaxd, 0b000, 0b01, 0b010010, 0b1);
INSN(fmind, 0b000, 0b01, 0b010110, 0b1);
INSN(fnmuld, 0b000, 0b01, 0b100010, 0b1);
// Half-precision floating-point instructions
INSN(fmulh, 0b000, 0b11, 0b000010, 0b1);
INSN(fdivh, 0b000, 0b11, 0b000110, 0b1);
INSN(faddh, 0b000, 0b11, 0b001010, 0b1);
INSN(fsubh, 0b000, 0b11, 0b001110, 0b1);
INSN(fmaxh, 0b000, 0b11, 0b010010, 0b1);
INSN(fminh, 0b000, 0b11, 0b010110, 0b1);
INSN(fnmulh, 0b000, 0b11, 0b100010, 0b1);
#undef INSN
// Advanced SIMD scalar three same
#define INSN(NAME, U, size, opcode) \
void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) { \
starti; \
f(0b01, 31, 30), f(U, 29), f(0b11110, 28, 24), f(size, 23, 22), f(1, 21); \
rf(Vm, 16), f(opcode, 15, 11), f(1, 10), rf(Vn, 5), rf(Vd, 0); \
}
INSN(fabds, 0b1, 0b10, 0b11010); // Floating-point Absolute Difference (single-precision)
INSN(fabdd, 0b1, 0b11, 0b11010); // Floating-point Absolute Difference (double-precision)
#undef INSN
// Advanced SIMD scalar three same FP16
#define INSN(NAME, U, a, opcode) \
void NAME(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm) { \
starti; \
f(0b01, 31, 30), f(U, 29), f(0b11110, 28, 24), f(a, 23), f(0b10, 22, 21); \
rf(Vm, 16), f(0b00, 15, 14), f(opcode, 13, 11), f(1, 10), rf(Vn, 5), rf(Vd, 0); \
}
INSN(fabdh, 0b1, 0b1, 0b010); // Floating-point Absolute Difference (half-precision float)
#undef INSN
@ -2120,6 +2153,7 @@ public:
INSN(fnmaddd, 0b000, 0b01, 1, 0);
INSN(fnmsub, 0b000, 0b01, 1, 1);
INSN(fmaddh, 0b000, 0b11, 0, 0); // half-precision fused multiply-add (scalar)
#undef INSN
// Floating-point conditional select

View File

@ -69,7 +69,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ far_call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
return;
}
@ -90,7 +90,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ blr(lr);
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) {
@ -103,7 +103,7 @@ void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
__ far_call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
void DivByZeroStub::emit_code(LIR_Assembler* ce) {
@ -274,7 +274,7 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
__ far_call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
@ -289,7 +289,7 @@ void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
}
__ far_call(RuntimeAddress(Runtime1::entry_for(_stub)), rscratch2);
ce->add_call_info_here(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}

View File

@ -2743,3 +2743,107 @@ bool C2_MacroAssembler::in_scratch_emit_size() {
}
return MacroAssembler::in_scratch_emit_size();
}
static void abort_verify_int_in_range(uint idx, jint val, jint lo, jint hi) {
fatal("Invalid CastII, idx: %u, val: %d, lo: %d, hi: %d", idx, val, lo, hi);
}
void C2_MacroAssembler::verify_int_in_range(uint idx, const TypeInt* t, Register rval, Register rtmp) {
assert(!t->empty() && !t->singleton(), "%s", Type::str(t));
if (t == TypeInt::INT) {
return;
}
BLOCK_COMMENT("verify_int_in_range {");
Label L_success, L_failure;
jint lo = t->_lo;
jint hi = t->_hi;
if (lo != min_jint && hi != max_jint) {
subsw(rtmp, rval, lo);
br(Assembler::LT, L_failure);
subsw(rtmp, rval, hi);
br(Assembler::LE, L_success);
} else if (lo != min_jint) {
subsw(rtmp, rval, lo);
br(Assembler::GE, L_success);
} else if (hi != max_jint) {
subsw(rtmp, rval, hi);
br(Assembler::LE, L_success);
} else {
ShouldNotReachHere();
}
bind(L_failure);
movw(c_rarg0, idx);
mov(c_rarg1, rval);
movw(c_rarg2, lo);
movw(c_rarg3, hi);
reconstruct_frame_pointer(rtmp);
rt_call(CAST_FROM_FN_PTR(address, abort_verify_int_in_range), rtmp);
hlt(0);
bind(L_success);
BLOCK_COMMENT("} verify_int_in_range");
}
static void abort_verify_long_in_range(uint idx, jlong val, jlong lo, jlong hi) {
fatal("Invalid CastLL, idx: %u, val: " JLONG_FORMAT ", lo: " JLONG_FORMAT ", hi: " JLONG_FORMAT, idx, val, lo, hi);
}
void C2_MacroAssembler::verify_long_in_range(uint idx, const TypeLong* t, Register rval, Register rtmp) {
assert(!t->empty() && !t->singleton(), "%s", Type::str(t));
if (t == TypeLong::LONG) {
return;
}
BLOCK_COMMENT("verify_long_in_range {");
Label L_success, L_failure;
jlong lo = t->_lo;
jlong hi = t->_hi;
if (lo != min_jlong && hi != max_jlong) {
subs(rtmp, rval, lo);
br(Assembler::LT, L_failure);
subs(rtmp, rval, hi);
br(Assembler::LE, L_success);
} else if (lo != min_jlong) {
subs(rtmp, rval, lo);
br(Assembler::GE, L_success);
} else if (hi != max_jlong) {
subs(rtmp, rval, hi);
br(Assembler::LE, L_success);
} else {
ShouldNotReachHere();
}
bind(L_failure);
movw(c_rarg0, idx);
mov(c_rarg1, rval);
mov(c_rarg2, lo);
mov(c_rarg3, hi);
reconstruct_frame_pointer(rtmp);
rt_call(CAST_FROM_FN_PTR(address, abort_verify_long_in_range), rtmp);
hlt(0);
bind(L_success);
BLOCK_COMMENT("} verify_long_in_range");
}
void C2_MacroAssembler::reconstruct_frame_pointer(Register rtmp) {
const int framesize = Compile::current()->output()->frame_size_in_bytes();
if (PreserveFramePointer) {
// frame pointer is valid
#ifdef ASSERT
// Verify frame pointer value in rfp.
add(rtmp, sp, framesize - 2 * wordSize);
Label L_success;
cmp(rfp, rtmp);
br(Assembler::EQ, L_success);
stop("frame pointer mismatch");
bind(L_success);
#endif // ASSERT
} else {
add(rfp, sp, framesize - 2 * wordSize);
}
}

View File

@ -188,4 +188,9 @@
void vector_signum_sve(FloatRegister dst, FloatRegister src, FloatRegister zero,
FloatRegister one, FloatRegister vtmp, PRegister pgtmp, SIMD_RegVariant T);
void verify_int_in_range(uint idx, const TypeInt* t, Register val, Register tmp);
void verify_long_in_range(uint idx, const TypeLong* t, Register val, Register tmp);
void reconstruct_frame_pointer(Register rtmp);
#endif // CPU_AARCH64_C2_MACROASSEMBLER_AARCH64_HPP

View File

@ -70,7 +70,7 @@ static char* reserve_at_eor_compatible_address(size_t size, bool aslr) {
const uint64_t immediate = ((uint64_t)immediates[index]) << 32;
assert(immediate > 0 && Assembler::operand_valid_for_logical_immediate(/*is32*/false, immediate),
"Invalid immediate %d " UINT64_FORMAT, index, immediate);
result = os::attempt_reserve_memory_at((char*)immediate, size, false);
result = os::attempt_reserve_memory_at((char*)immediate, size, mtNone);
if (result == nullptr) {
log_trace(metaspace, map)("Failed to attach at " UINT64_FORMAT_X, immediate);
}
@ -114,7 +114,7 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size
if (result == nullptr) {
constexpr size_t alignment = nth_bit(32);
log_debug(metaspace, map)("Trying to reserve at a 32-bit-aligned address");
result = os::reserve_memory_aligned(size, alignment, false);
result = os::reserve_memory_aligned(size, alignment, mtNone);
}
return result;

View File

@ -1003,9 +1003,6 @@ void MacroAssembler::c2bool(Register x) {
address MacroAssembler::ic_call(address entry, jint method_index) {
RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index);
// address const_ptr = long_constant((jlong)Universe::non_oop_word());
// uintptr_t offset;
// ldr_constant(rscratch2, const_ptr);
movptr(rscratch2, (intptr_t)Universe::non_oop_word());
return trampoline_call(Address(entry, rh));
}
@ -5520,9 +5517,8 @@ void MacroAssembler::movoop(Register dst, jobject obj) {
mov(dst, Address((address)obj, rspec));
} else {
address dummy = address(uintptr_t(pc()) & -wordSize); // A nearby aligned address
ldr_constant(dst, Address(dummy, rspec));
ldr(dst, Address(dummy, rspec));
}
}
// Move a metadata address into a register.

View File

@ -1472,16 +1472,6 @@ public:
public:
void ldr_constant(Register dest, const Address &const_addr) {
if (NearCpool) {
ldr(dest, const_addr);
} else {
uint64_t offset;
adrp(dest, InternalAddress(const_addr.target()), offset);
ldr(dest, Address(dest, offset));
}
}
address read_polling_page(Register r, relocInfo::relocType rtype);
void get_polling_page(Register dest, relocInfo::relocType rtype);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -200,4 +200,8 @@
return false;
}
// Is FEAT_FP16 supported for this CPU?
static bool is_feat_fp16_supported() {
return (VM_Version::supports_fphp() && VM_Version::supports_asimdhp());
}
#endif // CPU_AARCH64_MATCHER_AARCH64_HPP

View File

@ -65,6 +65,9 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
}
MacroAssembler* masm = new MacroAssembler(&buffer);
assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned");
@ -285,6 +288,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
}
MacroAssembler* masm = new MacroAssembler(&buffer);
// TODO check various assumptions made here

View File

@ -11166,79 +11166,6 @@ class StubGenerator: public StubCodeGenerator {
// }
};
void generate_vector_math_stubs() {
// Get native vector math stub routine addresses
void* libsleef = nullptr;
char ebuf[1024];
char dll_name[JVM_MAXPATHLEN];
if (os::dll_locate_lib(dll_name, sizeof(dll_name), Arguments::get_dll_dir(), "sleef")) {
libsleef = os::dll_load(dll_name, ebuf, sizeof ebuf);
}
if (libsleef == nullptr) {
log_info(library)("Failed to load native vector math library, %s!", ebuf);
return;
}
// Method naming convention
// All the methods are named as <OP><T><N>_<U><suffix>
// Where:
// <OP> is the operation name, e.g. sin
// <T> is optional to indicate float/double
// "f/d" for vector float/double operation
// <N> is the number of elements in the vector
// "2/4" for neon, and "x" for sve
// <U> is the precision level
// "u10/u05" represents 1.0/0.5 ULP error bounds
// We use "u10" for all operations by default
// But for those functions do not have u10 support, we use "u05" instead
// <suffix> indicates neon/sve
// "sve/advsimd" for sve/neon implementations
// e.g. sinfx_u10sve is the method for computing vector float sin using SVE instructions
// cosd2_u10advsimd is the method for computing 2 elements vector double cos using NEON instructions
//
log_info(library)("Loaded library %s, handle " INTPTR_FORMAT, JNI_LIB_PREFIX "sleef" JNI_LIB_SUFFIX, p2i(libsleef));
// Math vector stubs implemented with SVE for scalable vector size.
if (UseSVE > 0) {
for (int op = 0; op < VectorSupport::NUM_VECTOR_OP_MATH; op++) {
int vop = VectorSupport::VECTOR_OP_MATH_START + op;
// Skip "tanh" because there is performance regression
if (vop == VectorSupport::VECTOR_OP_TANH) {
continue;
}
// The native library does not support u10 level of "hypot".
const char* ulf = (vop == VectorSupport::VECTOR_OP_HYPOT) ? "u05" : "u10";
snprintf(ebuf, sizeof(ebuf), "%sfx_%ssve", VectorSupport::mathname[op], ulf);
StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_SCALABLE][op] = (address)os::dll_lookup(libsleef, ebuf);
snprintf(ebuf, sizeof(ebuf), "%sdx_%ssve", VectorSupport::mathname[op], ulf);
StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_SCALABLE][op] = (address)os::dll_lookup(libsleef, ebuf);
}
}
// Math vector stubs implemented with NEON for 64/128 bits vector size.
for (int op = 0; op < VectorSupport::NUM_VECTOR_OP_MATH; op++) {
int vop = VectorSupport::VECTOR_OP_MATH_START + op;
// Skip "tanh" because there is performance regression
if (vop == VectorSupport::VECTOR_OP_TANH) {
continue;
}
// The native library does not support u10 level of "hypot".
const char* ulf = (vop == VectorSupport::VECTOR_OP_HYPOT) ? "u05" : "u10";
snprintf(ebuf, sizeof(ebuf), "%sf4_%sadvsimd", VectorSupport::mathname[op], ulf);
StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_64][op] = (address)os::dll_lookup(libsleef, ebuf);
snprintf(ebuf, sizeof(ebuf), "%sf4_%sadvsimd", VectorSupport::mathname[op], ulf);
StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_128][op] = (address)os::dll_lookup(libsleef, ebuf);
snprintf(ebuf, sizeof(ebuf), "%sd2_%sadvsimd", VectorSupport::mathname[op], ulf);
StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_128][op] = (address)os::dll_lookup(libsleef, ebuf);
}
}
// Initialization
void generate_initial_stubs() {
// Generate initial stubs and initializes the entry points
@ -11392,8 +11319,6 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_montgomerySquare = g.generate_multiply();
}
generate_vector_math_stubs();
#endif // COMPILER2
if (UseChaCha20Intrinsics) {

View File

@ -642,6 +642,7 @@ void VM_Version::initialize() {
if (_model2) {
os::snprintf_checked(buf + buf_used_len, sizeof(buf) - buf_used_len, "(0x%03x)", _model2);
}
size_t features_offset = strnlen(buf, sizeof(buf));
#define ADD_FEATURE_IF_SUPPORTED(id, name, bit) \
do { \
if (VM_Version::supports_##name()) strcat(buf, ", " #name); \
@ -649,7 +650,11 @@ void VM_Version::initialize() {
CPU_FEATURE_FLAGS(ADD_FEATURE_IF_SUPPORTED)
#undef ADD_FEATURE_IF_SUPPORTED
_features_string = os::strdup(buf);
_cpu_info_string = os::strdup(buf);
_features_string = extract_features_string(_cpu_info_string,
strnlen(_cpu_info_string, sizeof(buf)),
features_offset);
}
#if defined(LINUX)
@ -716,7 +721,7 @@ void VM_Version::initialize_cpu_information(void) {
int desc_len = snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "AArch64 ");
get_compatible_board(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len);
desc_len = (int)strlen(_cpu_desc);
snprintf(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len, " %s", _features_string);
snprintf(_cpu_desc + desc_len, CPU_DETAILED_DESC_BUF_SIZE - desc_len, " %s", _cpu_info_string);
_initialized = true;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -125,6 +125,8 @@ enum Ampere_CPU_Model {
decl(SHA2, sha256, 6) \
decl(CRC32, crc32, 7) \
decl(LSE, lse, 8) \
decl(FPHP, fphp, 9) \
decl(ASIMDHP, asimdhp, 10) \
decl(DCPOP, dcpop, 16) \
decl(SHA3, sha3, 17) \
decl(SHA512, sha512, 21) \

View File

@ -1238,11 +1238,11 @@ encode %{
enc_class save_last_PC %{
// preserve mark
address mark = __ inst_mark();
debug_only(int off0 = __ offset());
DEBUG_ONLY(int off0 = __ offset());
int ret_addr_offset = as_MachCall()->ret_addr_offset();
__ adr(LR, mark + ret_addr_offset);
__ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset()));
debug_only(int off1 = __ offset());
DEBUG_ONLY(int off1 = __ offset());
assert(off1 - off0 == 2 * Assembler::InstructionSize, "correct size prediction");
// restore mark
__ set_inst_mark(mark);
@ -1251,11 +1251,11 @@ encode %{
enc_class preserve_SP %{
// preserve mark
address mark = __ inst_mark();
debug_only(int off0 = __ offset());
DEBUG_ONLY(int off0 = __ offset());
// FP is preserved across all calls, even compiled calls.
// Use it to preserve SP in places where the callee might change the SP.
__ mov(Rmh_SP_save, SP);
debug_only(int off1 = __ offset());
DEBUG_ONLY(int off1 = __ offset());
assert(off1 - off0 == 4, "correct size prediction");
// restore mark
__ set_inst_mark(mark);

View File

@ -59,7 +59,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ call(Runtime1::entry_for(C1StubId::predicate_failed_trap_id), relocInfo::runtime_call_type);
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
return;
}
// Pass the array index on stack because all registers must be preserved
@ -91,7 +91,7 @@ void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
__ call(Runtime1::entry_for(C1StubId::predicate_failed_trap_id), relocInfo::runtime_call_type);
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
void DivByZeroStub::emit_code(LIR_Assembler* ce) {

View File

@ -72,7 +72,7 @@ void NativeNMethodBarrier::verify() const {
static NativeNMethodBarrier* native_nmethod_barrier(nmethod* nm) {
address barrier_address = nm->code_begin() + nm->frame_complete_offset() - entry_barrier_bytes;
NativeNMethodBarrier* barrier = reinterpret_cast<NativeNMethodBarrier*>(barrier_address);
debug_only(barrier->verify());
DEBUG_ONLY(barrier->verify());
return barrier;
}

View File

@ -54,6 +54,9 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Measured 8/7/03 at 660 in 32bit debug build
CodeBuffer buffer(name, 2000, 512);
#endif
if (buffer.blob() == nullptr) {
return nullptr;
}
// bypassed when code generation useless
MacroAssembler* masm = new MacroAssembler(&buffer);
const Register Rublock = R6;
@ -209,6 +212,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
// Measured 8/7/03 at 256 in 32bit debug build
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 600, 512);
if (buffer.blob() == nullptr) {
return nullptr;
}
MacroAssembler* masm = new MacroAssembler(&buffer);
int framesize_in_words = 2; // FP + LR

View File

@ -295,7 +295,7 @@ void VM_Version::initialize() {
(has_multiprocessing_extensions() ? ", mp_ext" : ""));
// buf is started with ", " or is empty
_features_string = os::strdup(buf);
_cpu_info_string = os::strdup(buf);
if (has_simd()) {
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
@ -363,6 +363,6 @@ void VM_Version::initialize_cpu_information(void) {
_no_of_threads = _no_of_cores;
_no_of_sockets = _no_of_cores;
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "ARM%d", _arm_arch);
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _features_string);
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _cpu_info_string);
_initialized = true;
}

View File

@ -74,7 +74,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ bctrl();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ illtrap());
DEBUG_ONLY(__ illtrap());
return;
}
@ -98,7 +98,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ bctrl();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ illtrap());
DEBUG_ONLY(__ illtrap());
}
@ -115,7 +115,7 @@ void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
__ bctrl();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ illtrap());
DEBUG_ONLY(__ illtrap());
}
@ -156,7 +156,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) {
__ bctrl();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ illtrap());
DEBUG_ONLY(__ illtrap());
}
@ -179,7 +179,7 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
__ bctrl();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ illtrap());
DEBUG_ONLY(__ illtrap());
}
@ -193,7 +193,7 @@ void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
__ mtctr(R0);
__ bctrl();
ce->add_call_info_here(_info);
debug_only( __ illtrap(); )
DEBUG_ONLY( __ illtrap(); )
}
@ -441,7 +441,7 @@ void DeoptimizeStub::emit_code(LIR_Assembler* ce) {
__ load_const_optimized(R0, _trap_request); // Pass trap request in R0.
__ bctrl();
ce->add_call_info_here(_info);
debug_only(__ illtrap());
DEBUG_ONLY(__ illtrap());
}

View File

@ -189,7 +189,7 @@ LIR_Opr FrameMap::_caller_save_fpu_regs[] = {};
FloatRegister FrameMap::nr2floatreg (int rnr) {
assert(_init_done, "tables not initialized");
debug_only(fpu_range_check(rnr);)
DEBUG_ONLY(fpu_range_check(rnr);)
return _fpu_regs[rnr];
}

View File

@ -108,7 +108,7 @@ static NativeNMethodBarrier* get_nmethod_barrier(nmethod* nm) {
}
auto barrier = reinterpret_cast<NativeNMethodBarrier*>(barrier_address);
debug_only(barrier->verify());
DEBUG_ONLY(barrier->verify());
return barrier;
}

View File

@ -73,6 +73,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
// Setup code generation tools.
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
}
InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer);
address start = __ pc();

View File

@ -3106,6 +3106,9 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Setup code generation tools.
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
}
InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer);
address start = __ pc();

View File

@ -219,7 +219,7 @@ void VM_Version::initialize() {
(has_brw() ? " brw" : "")
// Make sure number of %s matches num_features!
);
_features_string = os::strdup(buf);
_cpu_info_string = os::strdup(buf);
if (Verbose) {
print_features();
}
@ -519,7 +519,7 @@ void VM_Version::print_platform_virtualization_info(outputStream* st) {
}
void VM_Version::print_features() {
tty->print_cr("Version: %s L1_data_cache_line_size=%d", features_string(), L1_data_cache_line_size());
tty->print_cr("Version: %s L1_data_cache_line_size=%d", cpu_info_string(), L1_data_cache_line_size());
if (Verbose) {
if (ContendedPaddingWidth > 0) {
@ -726,6 +726,6 @@ void VM_Version::initialize_cpu_information(void) {
_no_of_threads = _no_of_cores;
_no_of_sockets = _no_of_cores;
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE, "PowerPC POWER%lu", PowerArchitecturePPC64);
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "PPC %s", features_string());
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "PPC %s", cpu_info_string());
_initialized = true;
}

View File

@ -2323,6 +2323,7 @@ enum Nf {
}
// Vector Bit-manipulation used in Cryptography (Zvbb) Extension
INSN(vandn_vx, 0b1010111, 0b100, 0b000001);
INSN(vrol_vx, 0b1010111, 0b100, 0b010101);
INSN(vror_vx, 0b1010111, 0b100, 0b010100);

View File

@ -70,7 +70,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ far_call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
return;
}
@ -92,7 +92,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ rt_call(Runtime1::entry_for(stub_id), ra);
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) {
@ -105,7 +105,7 @@ void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
__ far_call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
void DivByZeroStub::emit_code(LIR_Assembler* ce) {
@ -258,7 +258,7 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
__ far_call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
@ -272,7 +272,7 @@ void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
}
__ far_call(RuntimeAddress(Runtime1::entry_for(_stub)));
ce->add_call_info_here(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
void ArrayCopyStub::emit_code(LIR_Assembler* ce) {

View File

@ -300,7 +300,7 @@ public:
inline NativeGeneralJump* nativeGeneralJump_at(address addr) {
assert_cond(addr != nullptr);
NativeGeneralJump* jump = (NativeGeneralJump*)(addr);
debug_only(jump->verify();)
DEBUG_ONLY(jump->verify();)
return jump;
}

View File

@ -1596,7 +1596,8 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r
__ unspill(as_VectorRegister(Matcher::_regEncode[dst_lo]), ra_->reg2offset(src_lo));
} else if (src_lo_rc == rc_vector && dst_lo_rc == rc_vector) {
// vpr to vpr
__ vmv1r_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo]));
__ vsetvli_helper(T_BYTE, MaxVectorSize);
__ vmv_v_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo]));
} else {
ShouldNotReachHere();
}
@ -1614,7 +1615,8 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r
__ unspill_vmask(as_VectorRegister(Matcher::_regEncode[dst_lo]), ra_->reg2offset(src_lo));
} else if (src_lo_rc == rc_vector && dst_lo_rc == rc_vector) {
// vmask to vmask
__ vmv1r_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo]));
__ vsetvli_helper(T_BYTE, MaxVectorSize >> 3);
__ vmv_v_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo]));
} else {
ShouldNotReachHere();
}
@ -1914,9 +1916,10 @@ bool Matcher::match_rule_supported(int opcode) {
case Op_FmaF:
case Op_FmaD:
return UseFMA;
case Op_FmaVF:
case Op_FmaVD:
return UseFMA;
return UseRVV && UseFMA;
case Op_ConvHF2F:
case Op_ConvF2HF:
@ -1950,11 +1953,11 @@ const RegMask* Matcher::predicate_reg_mask(void) {
// Vector calling convention not yet implemented.
bool Matcher::supports_vector_calling_convention(void) {
return EnableVectorSupport && UseVectorStubs;
return EnableVectorSupport;
}
OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
assert(EnableVectorSupport && UseVectorStubs, "sanity");
assert(EnableVectorSupport, "sanity");
assert(ideal_reg == Op_VecA, "sanity");
// check more info at https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc
int lo = V8_num;

File diff suppressed because it is too large Load Diff

View File

@ -63,6 +63,9 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
}
MacroAssembler* masm = new MacroAssembler(&buffer);
assert_cond(masm != nullptr);
@ -282,6 +285,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
}
MacroAssembler* masm = new MacroAssembler(&buffer);
assert_cond(masm != nullptr);

View File

@ -6458,58 +6458,6 @@ static const int64_t right_3_bits = right_n_bits(3);
return start;
}
void generate_vector_math_stubs() {
if (!UseRVV) {
log_info(library)("vector is not supported, skip loading vector math (sleef) library!");
return;
}
// Get native vector math stub routine addresses
void* libsleef = nullptr;
char ebuf[1024];
char dll_name[JVM_MAXPATHLEN];
if (os::dll_locate_lib(dll_name, sizeof(dll_name), Arguments::get_dll_dir(), "sleef")) {
libsleef = os::dll_load(dll_name, ebuf, sizeof ebuf);
}
if (libsleef == nullptr) {
log_info(library)("Failed to load native vector math (sleef) library, %s!", ebuf);
return;
}
// Method naming convention
// All the methods are named as <OP><T>_<U><suffix>
//
// Where:
// <OP> is the operation name, e.g. sin, cos
// <T> is to indicate float/double
// "fx/dx" for vector float/double operation
// <U> is the precision level
// "u10/u05" represents 1.0/0.5 ULP error bounds
// We use "u10" for all operations by default
// But for those functions do not have u10 support, we use "u05" instead
// <suffix> rvv, indicates riscv vector extension
//
// e.g. sinfx_u10rvv is the method for computing vector float sin using rvv instructions
//
log_info(library)("Loaded library %s, handle " INTPTR_FORMAT, JNI_LIB_PREFIX "sleef" JNI_LIB_SUFFIX, p2i(libsleef));
for (int op = 0; op < VectorSupport::NUM_VECTOR_OP_MATH; op++) {
int vop = VectorSupport::VECTOR_OP_MATH_START + op;
if (vop == VectorSupport::VECTOR_OP_TANH) { // skip tanh because of performance regression
continue;
}
// The native library does not support u10 level of "hypot".
const char* ulf = (vop == VectorSupport::VECTOR_OP_HYPOT) ? "u05" : "u10";
snprintf(ebuf, sizeof(ebuf), "%sfx_%srvv", VectorSupport::mathname[op], ulf);
StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_SCALABLE][op] = (address)os::dll_lookup(libsleef, ebuf);
snprintf(ebuf, sizeof(ebuf), "%sdx_%srvv", VectorSupport::mathname[op], ulf);
StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_SCALABLE][op] = (address)os::dll_lookup(libsleef, ebuf);
}
}
#endif // COMPILER2
/**
@ -6741,8 +6689,6 @@ static const int64_t right_3_bits = right_n_bits(3);
generate_string_indexof_stubs();
generate_vector_math_stubs();
#endif // COMPILER2
}

View File

@ -468,7 +468,7 @@ void VM_Version::initialize_cpu_information(void) {
_no_of_threads = _no_of_cores;
_no_of_sockets = _no_of_cores;
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "RISCV64");
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "RISCV64 %s", features_string());
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "RISCV64 %s", cpu_info_string());
_initialized = true;
}

View File

@ -52,7 +52,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
CHECK_BAILOUT();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
return;
}
@ -74,7 +74,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
CHECK_BAILOUT();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) {
@ -88,7 +88,7 @@ void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
CHECK_BAILOUT();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
void CounterOverflowStub::emit_code(LIR_Assembler* ce) {
@ -116,7 +116,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) {
ce->emit_call_c(Runtime1::entry_for (C1StubId::throw_div0_exception_id));
CHECK_BAILOUT();
ce->add_call_info_here(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
@ -134,7 +134,7 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
CHECK_BAILOUT();
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
// Note: pass object in Z_R1_scratch
@ -147,7 +147,7 @@ void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
ce->emit_call_c(a);
CHECK_BAILOUT();
ce->add_call_info_here(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
NewInstanceStub::NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, C1StubId stub_id) {

View File

@ -144,13 +144,13 @@ LIR_Opr FrameMap::_caller_save_fpu_regs[] = {};
// c1 rnr -> FloatRegister
FloatRegister FrameMap::nr2floatreg (int rnr) {
assert(_init_done, "tables not initialized");
debug_only(fpu_range_check(rnr);)
DEBUG_ONLY(fpu_range_check(rnr);)
return _fpu_rnr2reg[rnr];
}
void FrameMap::map_float_register(int rnr, FloatRegister reg) {
debug_only(fpu_range_check(rnr);)
debug_only(fpu_range_check(reg->encoding());)
DEBUG_ONLY(fpu_range_check(rnr);)
DEBUG_ONLY(fpu_range_check(reg->encoding());)
_fpu_rnr2reg[rnr] = reg; // mapping c1 regnr. -> FloatRegister
_fpu_reg2rnr[reg->encoding()] = rnr; // mapping assembler encoding -> c1 regnr.
}

View File

@ -107,7 +107,7 @@
static int fpu_reg2rnr (FloatRegister reg) {
assert(_init_done, "tables not initialized");
int c1rnr = _fpu_reg2rnr[reg->encoding()];
debug_only(fpu_range_check(c1rnr);)
DEBUG_ONLY(fpu_range_check(c1rnr);)
return c1rnr;
}

View File

@ -40,7 +40,7 @@ class NativeMethodBarrier: public NativeInstruction {
address get_patchable_data_address() const {
address inst_addr = get_barrier_start_address() + PATCHABLE_INSTRUCTION_OFFSET;
debug_only(Assembler::is_z_cfi(*((long*)inst_addr)));
DEBUG_ONLY(Assembler::is_z_cfi(*((long*)inst_addr)));
return inst_addr + 2;
}
@ -91,7 +91,7 @@ static NativeMethodBarrier* get_nmethod_barrier(nmethod* nm) {
address barrier_address = nm->code_begin() + nm->frame_complete_offset() - NativeMethodBarrier::BARRIER_TOTAL_LENGTH;
auto barrier = reinterpret_cast<NativeMethodBarrier*>(barrier_address);
debug_only(barrier->verify());
DEBUG_ONLY(barrier->verify());
return barrier;
}

View File

@ -444,7 +444,7 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
// Useful if consumed previously by access via stackTop().
void InterpreterMacroAssembler::popx(int len) {
add2reg(Z_esp, len*Interpreter::stackElementSize);
debug_only(verify_esp(Z_esp, Z_R1_scratch));
DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
}
// Get Address object of stack top. No checks. No pop.
@ -458,38 +458,38 @@ void InterpreterMacroAssembler::pop_i(Register r) {
z_l(r, Interpreter::expr_offset_in_bytes(0), Z_esp);
add2reg(Z_esp, Interpreter::stackElementSize);
assert_different_registers(r, Z_R1_scratch);
debug_only(verify_esp(Z_esp, Z_R1_scratch));
DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
}
void InterpreterMacroAssembler::pop_ptr(Register r) {
z_lg(r, Interpreter::expr_offset_in_bytes(0), Z_esp);
add2reg(Z_esp, Interpreter::stackElementSize);
assert_different_registers(r, Z_R1_scratch);
debug_only(verify_esp(Z_esp, Z_R1_scratch));
DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
}
void InterpreterMacroAssembler::pop_l(Register r) {
z_lg(r, Interpreter::expr_offset_in_bytes(0), Z_esp);
add2reg(Z_esp, 2*Interpreter::stackElementSize);
assert_different_registers(r, Z_R1_scratch);
debug_only(verify_esp(Z_esp, Z_R1_scratch));
DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
}
void InterpreterMacroAssembler::pop_f(FloatRegister f) {
mem2freg_opt(f, Address(Z_esp, Interpreter::expr_offset_in_bytes(0)), false);
add2reg(Z_esp, Interpreter::stackElementSize);
debug_only(verify_esp(Z_esp, Z_R1_scratch));
DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
}
void InterpreterMacroAssembler::pop_d(FloatRegister f) {
mem2freg_opt(f, Address(Z_esp, Interpreter::expr_offset_in_bytes(0)), true);
add2reg(Z_esp, 2*Interpreter::stackElementSize);
debug_only(verify_esp(Z_esp, Z_R1_scratch));
DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
}
void InterpreterMacroAssembler::push_i(Register r) {
assert_different_registers(r, Z_R1_scratch);
debug_only(verify_esp(Z_esp, Z_R1_scratch));
DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
z_st(r, Address(Z_esp));
add2reg(Z_esp, -Interpreter::stackElementSize);
}
@ -501,7 +501,7 @@ void InterpreterMacroAssembler::push_ptr(Register r) {
void InterpreterMacroAssembler::push_l(Register r) {
assert_different_registers(r, Z_R1_scratch);
debug_only(verify_esp(Z_esp, Z_R1_scratch));
DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
int offset = -Interpreter::stackElementSize;
z_stg(r, Address(Z_esp, offset));
clear_mem(Address(Z_esp), Interpreter::stackElementSize);
@ -509,13 +509,13 @@ void InterpreterMacroAssembler::push_l(Register r) {
}
void InterpreterMacroAssembler::push_f(FloatRegister f) {
debug_only(verify_esp(Z_esp, Z_R1_scratch));
DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
freg2mem_opt(f, Address(Z_esp), false);
add2reg(Z_esp, -Interpreter::stackElementSize);
}
void InterpreterMacroAssembler::push_d(FloatRegister d) {
debug_only(verify_esp(Z_esp, Z_R1_scratch));
DEBUG_ONLY(verify_esp(Z_esp, Z_R1_scratch));
int offset = -Interpreter::stackElementSize;
freg2mem_opt(d, Address(Z_esp, offset));
add2reg(Z_esp, 2 * offset);

View File

@ -72,6 +72,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
}
MacroAssembler* masm = new MacroAssembler(&buffer);
Register handle_exception = Z_ARG5;

View File

@ -2768,6 +2768,9 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
}
InterpreterMacroAssembler* masm = new InterpreterMacroAssembler(&buffer);
Register unroll_block_reg = Z_tmp_1;

View File

@ -90,7 +90,7 @@ static const char* z_features[] = {" ",
void VM_Version::initialize() {
determine_features(); // Get processor capabilities.
set_features_string(); // Set a descriptive feature indication.
set_cpu_info_string(); // Set a descriptive feature indication.
if (Verbose || PrintAssembly || PrintStubCode) {
print_features_internal("CPU Version as detected internally:", PrintAssembly || PrintStubCode);
@ -388,9 +388,9 @@ int VM_Version::get_model_index() {
}
void VM_Version::set_features_string() {
// A note on the _features_string format:
// There are jtreg tests checking the _features_string for various properties.
void VM_Version::set_cpu_info_string() {
// A note on the _cpu_info_string format:
// There are jtreg tests checking the _cpu_info_string for various properties.
// For some strange reason, these tests require the string to contain
// only _lowercase_ characters. Keep that in mind when being surprised
// about the unusual notation of features - and when adding new ones.
@ -412,29 +412,29 @@ void VM_Version::set_features_string() {
_model_string = "unknown model";
strcpy(buf, "z/Architecture (ambiguous detection)");
}
_features_string = os::strdup(buf);
_cpu_info_string = os::strdup(buf);
if (has_Crypto_AES()) {
assert(strlen(_features_string) + 3*8 < sizeof(buf), "increase buffer size");
assert(strlen(_cpu_info_string) + 3*8 < sizeof(buf), "increase buffer size");
jio_snprintf(buf, sizeof(buf), "%s%s%s%s",
_features_string,
_cpu_info_string,
has_Crypto_AES128() ? ", aes128" : "",
has_Crypto_AES192() ? ", aes192" : "",
has_Crypto_AES256() ? ", aes256" : "");
os::free((void *)_features_string);
_features_string = os::strdup(buf);
os::free((void *)_cpu_info_string);
_cpu_info_string = os::strdup(buf);
}
if (has_Crypto_SHA()) {
assert(strlen(_features_string) + 6 + 2*8 + 7 < sizeof(buf), "increase buffer size");
assert(strlen(_cpu_info_string) + 6 + 2*8 + 7 < sizeof(buf), "increase buffer size");
jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s",
_features_string,
_cpu_info_string,
has_Crypto_SHA1() ? ", sha1" : "",
has_Crypto_SHA256() ? ", sha256" : "",
has_Crypto_SHA512() ? ", sha512" : "",
has_Crypto_GHASH() ? ", ghash" : "");
os::free((void *)_features_string);
_features_string = os::strdup(buf);
os::free((void *)_cpu_info_string);
_cpu_info_string = os::strdup(buf);
}
}
@ -464,7 +464,7 @@ bool VM_Version::test_feature_bit(unsigned long* featureBuffer, int featureNum,
}
void VM_Version::print_features_internal(const char* text, bool print_anyway) {
tty->print_cr("%s %s", text, features_string());
tty->print_cr("%s %s", text, cpu_info_string());
tty->cr();
if (Verbose || print_anyway) {
@ -906,7 +906,7 @@ void VM_Version::set_features_from(const char* march) {
err = true;
}
if (!err) {
set_features_string();
set_cpu_info_string();
if (prt || PrintAssembly) {
print_features_internal("CPU Version as set by cmdline option:", prt);
}
@ -1542,6 +1542,6 @@ void VM_Version::initialize_cpu_information(void) {
_no_of_threads = _no_of_cores;
_no_of_sockets = _no_of_cores;
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE, "s390 %s", VM_Version::get_model_string());
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "s390 %s", features_string());
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "s390 %s", cpu_info_string());
_initialized = true;
}

View File

@ -148,7 +148,7 @@ class VM_Version: public Abstract_VM_Version {
static bool test_feature_bit(unsigned long* featureBuffer, int featureNum, unsigned int bufLen);
static int get_model_index();
static void set_features_string();
static void set_cpu_info_string();
static void print_features_internal(const char* text, bool print_anyway=false);
static void determine_features();
static long call_getFeatures(unsigned long* buffer, int buflen, int functionCode);

View File

@ -801,7 +801,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
address ip = inst;
bool is_64bit = false;
debug_only(bool has_disp32 = false);
DEBUG_ONLY(bool has_disp32 = false);
int tail_size = 0; // other random bytes (#32, #16, etc.) at end of insn
again_after_prefix:
@ -859,7 +859,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x8A: // movb r, a
case 0x8B: // movl r, a
case 0x8F: // popl a
debug_only(has_disp32 = true);
DEBUG_ONLY(has_disp32 = true);
break;
case 0x68: // pushq #32
@ -898,10 +898,10 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x8B: // movw r, a
case 0x89: // movw a, r
debug_only(has_disp32 = true);
DEBUG_ONLY(has_disp32 = true);
break;
case 0xC7: // movw a, #16
debug_only(has_disp32 = true);
DEBUG_ONLY(has_disp32 = true);
tail_size = 2; // the imm16
break;
case 0x0F: // several SSE/SSE2 variants
@ -923,7 +923,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x69: // imul r, a, #32
case 0xC7: // movl a, #32(oop?)
tail_size = 4;
debug_only(has_disp32 = true); // has both kinds of operands!
DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
case 0x0F: // movx..., etc.
@ -932,11 +932,11 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
tail_size = 1;
case 0x38: // ptest, pmovzxbw
ip++; // skip opcode
debug_only(has_disp32 = true); // has both kinds of operands!
DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
case 0x70: // pshufd r, r/a, #8
debug_only(has_disp32 = true); // has both kinds of operands!
DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
case 0x73: // psrldq r, #8
tail_size = 1;
break;
@ -961,7 +961,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0xAE: // ldmxcsr, stmxcsr, fxrstor, fxsave, clflush
case 0xD6: // movq
case 0xFE: // paddd
debug_only(has_disp32 = true);
DEBUG_ONLY(has_disp32 = true);
break;
case 0xAD: // shrd r, a, %cl
@ -976,18 +976,18 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0xC1: // xaddl
case 0xC7: // cmpxchg8
case REP16(0x90): // setcc a
debug_only(has_disp32 = true);
DEBUG_ONLY(has_disp32 = true);
// fall out of the switch to decode the address
break;
case 0xC4: // pinsrw r, a, #8
debug_only(has_disp32 = true);
DEBUG_ONLY(has_disp32 = true);
case 0xC5: // pextrw r, r, #8
tail_size = 1; // the imm8
break;
case 0xAC: // shrd r, a, #8
debug_only(has_disp32 = true);
DEBUG_ONLY(has_disp32 = true);
tail_size = 1; // the imm8
break;
@ -1004,12 +1004,12 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
// also: orl, adcl, sbbl, andl, subl, xorl, cmpl
// on 32bit in the case of cmpl, the imm might be an oop
tail_size = 4;
debug_only(has_disp32 = true); // has both kinds of operands!
DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
case 0x83: // addl a, #8; addl r, #8
// also: orl, adcl, sbbl, andl, subl, xorl, cmpl
debug_only(has_disp32 = true); // has both kinds of operands!
DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
tail_size = 1;
break;
@ -1026,7 +1026,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x9B:
switch (0xFF & *ip++) {
case 0xD9: // fnstcw a
debug_only(has_disp32 = true);
DEBUG_ONLY(has_disp32 = true);
break;
default:
ShouldNotReachHere();
@ -1045,7 +1045,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x87: // xchg r, a
case REP4(0x38): // cmp...
case 0x85: // test r, a
debug_only(has_disp32 = true); // has both kinds of operands!
DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
case 0xA8: // testb rax, #8
@ -1057,7 +1057,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0xC6: // movb a, #8
case 0x80: // cmpb a, #8
case 0x6B: // imul r, a, #8
debug_only(has_disp32 = true); // has both kinds of operands!
DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
tail_size = 1; // the imm8
break;
@ -1109,7 +1109,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
break;
}
ip++; // skip opcode
debug_only(has_disp32 = true); // has both kinds of operands!
DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
case 0x62: // EVEX_4bytes
@ -1135,7 +1135,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
break;
}
ip++; // skip opcode
debug_only(has_disp32 = true); // has both kinds of operands!
DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
case 0xD1: // sal a, 1; sar a, 1; shl a, 1; shr a, 1
@ -1147,7 +1147,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0xD8: // fadd_s a; fsubr_s a; fmul_s a; fdivr_s a; fcomp_s a
case 0xDC: // fadd_d a; fsubr_d a; fmul_d a; fdivr_d a; fcomp_d a
case 0xDE: // faddp_d a; fsubrp_d a; fmulp_d a; fdivrp_d a; fcompp_d a
debug_only(has_disp32 = true);
DEBUG_ONLY(has_disp32 = true);
break;
case 0xE8: // call rdisp32
@ -1184,7 +1184,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
default:
ip++;
}
debug_only(has_disp32 = true); // has both kinds of operands!
DEBUG_ONLY(has_disp32 = true); // has both kinds of operands!
break;
default:

View File

@ -68,7 +68,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
return;
}
@ -88,7 +88,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) {
__ call(RuntimeAddress(Runtime1::entry_for(stub_id)));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
PredicateFailedStub::PredicateFailedStub(CodeEmitInfo* info) {
@ -101,7 +101,7 @@ void PredicateFailedStub::emit_code(LIR_Assembler* ce) {
__ call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
void DivByZeroStub::emit_code(LIR_Assembler* ce) {
@ -111,7 +111,7 @@ void DivByZeroStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
__ call(RuntimeAddress(Runtime1::entry_for(C1StubId::throw_div0_exception_id)));
ce->add_call_info_here(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
@ -399,7 +399,7 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) {
__ call(RuntimeAddress(a));
ce->add_call_info_here(_info);
ce->verify_oop_map(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}
@ -413,7 +413,7 @@ void SimpleExceptionStub::emit_code(LIR_Assembler* ce) {
}
__ call(RuntimeAddress(Runtime1::entry_for(_stub)));
ce->add_call_info_here(_info);
debug_only(__ should_not_reach_here());
DEBUG_ONLY(__ should_not_reach_here());
}

View File

@ -787,6 +787,119 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax,
// C2 uses the value of ZF to determine the continuation.
}
static void abort_verify_int_in_range(uint idx, jint val, jint lo, jint hi) {
fatal("Invalid CastII, idx: %u, val: %d, lo: %d, hi: %d", idx, val, lo, hi);
}
static void reconstruct_frame_pointer_helper(MacroAssembler* masm, Register dst) {
const int framesize = Compile::current()->output()->frame_size_in_bytes();
masm->movptr(dst, rsp);
if (framesize > 2 * wordSize) {
masm->addptr(dst, framesize - 2 * wordSize);
}
}
void C2_MacroAssembler::reconstruct_frame_pointer(Register rtmp) {
if (PreserveFramePointer) {
// frame pointer is valid
#ifdef ASSERT
// Verify frame pointer value in rbp.
reconstruct_frame_pointer_helper(this, rtmp);
Label L_success;
cmpq(rbp, rtmp);
jccb(Assembler::equal, L_success);
STOP("frame pointer mismatch");
bind(L_success);
#endif // ASSERT
} else {
reconstruct_frame_pointer_helper(this, rbp);
}
}
void C2_MacroAssembler::verify_int_in_range(uint idx, const TypeInt* t, Register val) {
jint lo = t->_lo;
jint hi = t->_hi;
assert(lo < hi, "type should not be empty or constant, idx: %u, lo: %d, hi: %d", idx, lo, hi);
if (t == TypeInt::INT) {
return;
}
BLOCK_COMMENT("CastII {");
Label fail;
Label succeed;
if (hi == max_jint) {
cmpl(val, lo);
jccb(Assembler::greaterEqual, succeed);
} else {
if (lo != min_jint) {
cmpl(val, lo);
jccb(Assembler::less, fail);
}
cmpl(val, hi);
jccb(Assembler::lessEqual, succeed);
}
bind(fail);
movl(c_rarg0, idx);
movl(c_rarg1, val);
movl(c_rarg2, lo);
movl(c_rarg3, hi);
reconstruct_frame_pointer(rscratch1);
call(RuntimeAddress(CAST_FROM_FN_PTR(address, abort_verify_int_in_range)));
hlt();
bind(succeed);
BLOCK_COMMENT("} // CastII");
}
static void abort_verify_long_in_range(uint idx, jlong val, jlong lo, jlong hi) {
fatal("Invalid CastLL, idx: %u, val: " JLONG_FORMAT ", lo: " JLONG_FORMAT ", hi: " JLONG_FORMAT, idx, val, lo, hi);
}
void C2_MacroAssembler::verify_long_in_range(uint idx, const TypeLong* t, Register val, Register tmp) {
jlong lo = t->_lo;
jlong hi = t->_hi;
assert(lo < hi, "type should not be empty or constant, idx: %u, lo: " JLONG_FORMAT ", hi: " JLONG_FORMAT, idx, lo, hi);
if (t == TypeLong::LONG) {
return;
}
BLOCK_COMMENT("CastLL {");
Label fail;
Label succeed;
auto cmp_val = [&](jlong bound) {
if (is_simm32(bound)) {
cmpq(val, checked_cast<int>(bound));
} else {
mov64(tmp, bound);
cmpq(val, tmp);
}
};
if (hi == max_jlong) {
cmp_val(lo);
jccb(Assembler::greaterEqual, succeed);
} else {
if (lo != min_jlong) {
cmp_val(lo);
jccb(Assembler::less, fail);
}
cmp_val(hi);
jccb(Assembler::lessEqual, succeed);
}
bind(fail);
movl(c_rarg0, idx);
movq(c_rarg1, val);
mov64(c_rarg2, lo);
mov64(c_rarg3, hi);
reconstruct_frame_pointer(rscratch1);
call(RuntimeAddress(CAST_FROM_FN_PTR(address, abort_verify_long_in_range)));
hlt();
bind(succeed);
BLOCK_COMMENT("} // CastLL");
}
//-------------------------------------------------------------------------------------------
// Generic instructions support for use in .ad files C2 code generation

View File

@ -44,6 +44,9 @@ public:
Register t, Register thread);
void fast_unlock_lightweight(Register obj, Register reg_rax, Register t, Register thread);
void verify_int_in_range(uint idx, const TypeInt* t, Register val);
void verify_long_in_range(uint idx, const TypeLong* t, Register val, Register tmp);
// Generic instructions support for use in .ad files C2 code generation
void vabsnegd(int opcode, XMMRegister dst, XMMRegister src);
void vabsnegd(int opcode, XMMRegister dst, XMMRegister src, int vector_len);
@ -574,4 +577,7 @@ public:
void scalar_max_min_fp16(int opcode, XMMRegister dst, XMMRegister src1, XMMRegister src2,
KRegister ktmp, XMMRegister xtmp1, XMMRegister xtmp2);
void reconstruct_frame_pointer(Register rtmp);
#endif // CPU_X86_C2_MACROASSEMBLER_X86_HPP

View File

@ -34,9 +34,7 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
#define SUPPORTS_NATIVE_CX8
#ifdef _LP64
#define SUPPORT_MONITOR_COUNT
#endif
#define CPU_MULTI_COPY_ATOMIC
@ -44,15 +42,11 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
#define DEFAULT_CACHE_LINE_SIZE 64
// The default padding size for data structures to avoid false sharing.
#ifdef _LP64
// The common wisdom is that adjacent cache line prefetchers on some hardware
// may pull two cache lines on access, so we have to pessimistically assume twice
// the cache line size for padding. TODO: Check if this is still true for modern
// hardware. If not, DEFAULT_CACHE_LINE_SIZE might as well suffice.
#define DEFAULT_PADDING_SIZE (DEFAULT_CACHE_LINE_SIZE*2)
#else
#define DEFAULT_PADDING_SIZE DEFAULT_CACHE_LINE_SIZE
#endif
#if defined(LINUX) || defined(__APPLE__)
#define SUPPORT_RESERVED_STACK_AREA

View File

@ -61,29 +61,19 @@ define_pd_global(intx, InlineSmallCode, 1000);
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
#define MIN_STACK_RESERVED_PAGES (0)
#ifdef _LP64
// Java_java_net_SocketOutputStream_socketWrite0() uses a 64k buffer on the
// stack if compiled for unix and LP64. To pass stack overflow tests we need
// 20 shadow pages.
// stack if compiled for unix. To pass stack overflow tests we need 20 shadow pages.
#define DEFAULT_STACK_SHADOW_PAGES (NOT_WIN64(20) WIN64_ONLY(8) DEBUG_ONLY(+4))
// For those clients that do not use write socket, we allow
// the min range value to be below that of the default
#define MIN_STACK_SHADOW_PAGES (NOT_WIN64(10) WIN64_ONLY(8) DEBUG_ONLY(+4))
#else
#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
#endif // _LP64
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES);
#ifdef _LP64
define_pd_global(bool, VMContinuations, true);
#else
define_pd_global(bool, VMContinuations, false);
#endif
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);

View File

@ -67,9 +67,7 @@ void NativeCall::print() {
// Inserts a native call instruction at a given pc
void NativeCall::insert(address code_pos, address entry) {
intptr_t disp = (intptr_t)entry - ((intptr_t)code_pos + 1 + 4);
#ifdef AMD64
guarantee(disp == (intptr_t)(jint)disp, "must be 32-bit offset");
#endif // AMD64
*code_pos = instruction_code;
*((int32_t *)(code_pos+1)) = (int32_t) disp;
ICache::invalidate_range(code_pos, instruction_size);
@ -140,7 +138,7 @@ bool NativeCall::is_displacement_aligned() {
// Used in the runtime linkage of calls; see class CompiledIC.
// (Cf. 4506997 and 4479829, where threads witnessed garbage displacements.)
void NativeCall::set_destination_mt_safe(address dest) {
debug_only(verify());
DEBUG_ONLY(verify());
// Make sure patching code is locked. No two threads can patch at the same
// time but one may be executing this code.
assert(CodeCache_lock->is_locked() || SafepointSynchronize::is_at_safepoint() ||
@ -157,7 +155,6 @@ void NativeCall::set_destination_mt_safe(address dest) {
void NativeMovConstReg::verify() {
#ifdef AMD64
// make sure code pattern is actually a mov reg64, imm64 instruction
bool valid_rex_prefix = ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB;
bool valid_rex2_prefix = ubyte_at(0) == Assembler::REX2 &&
@ -169,12 +166,6 @@ void NativeMovConstReg::verify() {
print();
fatal("not a REX.W[B] mov reg64, imm64");
}
#else
// make sure code pattern is actually a mov reg, imm32 instruction
u_char test_byte = *(u_char*)instruction_address();
u_char test_byte_2 = test_byte & ( 0xff ^ register_mask);
if (test_byte_2 != instruction_code) fatal("not a mov reg, imm32");
#endif // AMD64
}
@ -192,12 +183,10 @@ int NativeMovRegMem::instruction_start() const {
// See comment in Assembler::locate_operand() about VEX prefixes.
if (instr_0 == instruction_VEX_prefix_2bytes) {
assert((UseAVX > 0), "shouldn't have VEX prefix");
NOT_LP64(assert((0xC0 & ubyte_at(1)) == 0xC0, "shouldn't have LDS and LES instructions"));
return 2;
}
if (instr_0 == instruction_VEX_prefix_3bytes) {
assert((UseAVX > 0), "shouldn't have VEX prefix");
NOT_LP64(assert((0xC0 & ubyte_at(1)) == 0xC0, "shouldn't have LDS and LES instructions"));
return 3;
}
if (instr_0 == instruction_EVEX_prefix_4bytes) {
@ -313,8 +302,7 @@ void NativeMovRegMem::print() {
void NativeLoadAddress::verify() {
// make sure code pattern is actually a mov [reg+offset], reg instruction
u_char test_byte = *(u_char*)instruction_address();
if ( ! ((test_byte == lea_instruction_code)
LP64_ONLY(|| (test_byte == mov64_instruction_code) ))) {
if ((test_byte != lea_instruction_code) && (test_byte != mov64_instruction_code)) {
fatal ("not a lea reg, [reg+offs] instruction");
}
}
@ -340,9 +328,7 @@ void NativeJump::verify() {
void NativeJump::insert(address code_pos, address entry) {
intptr_t disp = (intptr_t)entry - ((intptr_t)code_pos + 1 + 4);
#ifdef AMD64
guarantee(disp == (intptr_t)(int32_t)disp, "must be 32-bit offset");
#endif // AMD64
*code_pos = instruction_code;
*((int32_t*)(code_pos + 1)) = (int32_t)disp;
@ -355,11 +341,7 @@ void NativeJump::check_verified_entry_alignment(address entry, address verified_
// in use. The patching in that instance must happen only when certain
// alignment restrictions are true. These guarantees check those
// conditions.
#ifdef AMD64
const int linesize = 64;
#else
const int linesize = 32;
#endif // AMD64
// Must be wordSize aligned
guarantee(((uintptr_t) verified_entry & (wordSize -1)) == 0,
@ -386,7 +368,6 @@ void NativeJump::check_verified_entry_alignment(address entry, address verified_
//
void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
// complete jump instruction (to be inserted) is in code_buffer;
#ifdef _LP64
union {
jlong cb_long;
unsigned char code_buffer[8];
@ -402,43 +383,6 @@ void NativeJump::patch_verified_entry(address entry, address verified_entry, add
Atomic::store((jlong *) verified_entry, u.cb_long);
ICache::invalidate_range(verified_entry, 8);
#else
unsigned char code_buffer[5];
code_buffer[0] = instruction_code;
intptr_t disp = (intptr_t)dest - ((intptr_t)verified_entry + 1 + 4);
*(int32_t*)(code_buffer + 1) = (int32_t)disp;
check_verified_entry_alignment(entry, verified_entry);
// Can't call nativeJump_at() because it's asserts jump exists
NativeJump* n_jump = (NativeJump*) verified_entry;
//First patch dummy jmp in place
unsigned char patch[4];
assert(sizeof(patch)==sizeof(int32_t), "sanity check");
patch[0] = 0xEB; // jmp rel8
patch[1] = 0xFE; // jmp to self
patch[2] = 0xEB;
patch[3] = 0xFE;
// First patch dummy jmp in place
*(int32_t*)verified_entry = *(int32_t *)patch;
n_jump->wrote(0);
// Patch 5th byte (from jump instruction)
verified_entry[4] = code_buffer[4];
n_jump->wrote(4);
// Patch bytes 0-3 (from jump instruction)
*(int32_t*)verified_entry = *(int32_t *)code_buffer;
// Invalidate. Opteron requires a flush after every write.
n_jump->wrote(0);
#endif // _LP64
}
void NativeIllegalInstruction::insert(address code_pos) {
@ -455,9 +399,7 @@ void NativeGeneralJump::verify() {
void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
intptr_t disp = (intptr_t)entry - ((intptr_t)code_pos + 1 + 4);
#ifdef AMD64
guarantee(disp == (intptr_t)(int32_t)disp, "must be 32-bit offset");
#endif // AMD64
*code_pos = unconditional_long_jump;
*((int32_t *)(code_pos+1)) = (int32_t) disp;

View File

@ -126,10 +126,8 @@ class NativeCall: public NativeInstruction {
address return_address() const { return addr_at(return_address_offset); }
address destination() const;
void set_destination(address dest) {
#ifdef AMD64
intptr_t disp = dest - return_address();
guarantee(disp == (intptr_t)(jint)disp, "must be 32-bit offset");
#endif // AMD64
set_int_at(displacement_offset, (int)(dest - return_address()));
}
// Returns whether the 4-byte displacement operand is 4-byte aligned.
@ -211,15 +209,9 @@ class NativeCallReg: public NativeInstruction {
// Instruction format for implied addressing mode immediate operand move to register instruction:
// [REX/REX2] [OPCODE] [IMM32]
class NativeMovConstReg: public NativeInstruction {
#ifdef AMD64
static const bool has_rex = true;
static const int rex_size = 1;
static const int rex2_size = 2;
#else
static const bool has_rex = false;
static const int rex_size = 0;
static const int rex2_size = 0;
#endif // AMD64
public:
enum Intel_specific_constants {
instruction_code = 0xB8,
@ -390,13 +382,8 @@ inline NativeMovRegMem* nativeMovRegMem_at (address address) {
// leal reg, [reg + offset]
class NativeLoadAddress: public NativeMovRegMem {
#ifdef AMD64
static const bool has_rex = true;
static const int rex_size = 1;
#else
static const bool has_rex = false;
static const int rex_size = 0;
#endif // AMD64
public:
enum Intel_specific_constants {
instruction_prefix_wide = Assembler::REX_W,
@ -447,9 +434,7 @@ class NativeJump: public NativeInstruction {
if (dest == (address) -1) {
val = -5; // jump to self
}
#ifdef AMD64
assert((labs(val) & 0xFFFFFFFF00000000) == 0 || dest == (address)-1, "must be 32bit offset or -1");
#endif // AMD64
set_int_at(data_offset, (jint)val);
}
@ -503,7 +488,7 @@ class NativeGeneralJump: public NativeInstruction {
inline NativeGeneralJump* nativeGeneralJump_at(address address) {
NativeGeneralJump* jump = (NativeGeneralJump*)(address);
debug_only(jump->verify();)
DEBUG_ONLY(jump->verify();)
return jump;
}
@ -572,19 +557,14 @@ inline bool NativeInstruction::is_jump_reg() {
inline bool NativeInstruction::is_cond_jump() { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ ||
(ubyte_at(0) & 0xF0) == 0x70; /* short jump */ }
inline bool NativeInstruction::is_safepoint_poll() {
#ifdef AMD64
const bool has_rex_prefix = ubyte_at(0) == NativeTstRegMem::instruction_rex_b_prefix;
const int test_offset = has_rex2_prefix() ? 2 : (has_rex_prefix ? 1 : 0);
#else
const int test_offset = 0;
#endif
const bool is_test_opcode = ubyte_at(test_offset) == NativeTstRegMem::instruction_code_memXregl;
const bool is_rax_target = (ubyte_at(test_offset + 1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg;
return is_test_opcode && is_rax_target;
}
inline bool NativeInstruction::is_mov_literal64() {
#ifdef AMD64
bool valid_rex_prefix = ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB;
bool valid_rex2_prefix = ubyte_at(0) == Assembler::REX2 &&
(ubyte_at(1) == Assembler::REX2BIT_W ||
@ -593,9 +573,6 @@ inline bool NativeInstruction::is_mov_literal64() {
int opcode = has_rex2_prefix() ? ubyte_at(2) : ubyte_at(1);
return ((valid_rex_prefix || valid_rex2_prefix) && (opcode & (0xff ^ NativeMovConstReg::register_mask)) == 0xB8);
#else
return false;
#endif // AMD64
}
class NativePostCallNop: public NativeInstruction {

View File

@ -61,6 +61,9 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
}
MacroAssembler* masm = new MacroAssembler(&buffer);
assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned");
@ -267,6 +270,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
}
MacroAssembler* masm = new MacroAssembler(&buffer);

View File

@ -4333,70 +4333,6 @@ void StubGenerator::generate_compiler_stubs() {
}
}
// Get svml stub routine addresses
void *libjsvml = nullptr;
char ebuf[1024];
char dll_name[JVM_MAXPATHLEN];
if (os::dll_locate_lib(dll_name, sizeof(dll_name), Arguments::get_dll_dir(), "jsvml")) {
libjsvml = os::dll_load(dll_name, ebuf, sizeof ebuf);
}
if (libjsvml != nullptr) {
// SVML method naming convention
// All the methods are named as __jsvml_op<T><N>_ha_<VV>
// Where:
// ha stands for high accuracy
// <T> is optional to indicate float/double
// Set to f for vector float operation
// Omitted for vector double operation
// <N> is the number of elements in the vector
// 1, 2, 4, 8, 16
// e.g. 128 bit float vector has 4 float elements
// <VV> indicates the avx/sse level:
// z0 is AVX512, l9 is AVX2, e9 is AVX1 and ex is for SSE2
// e.g. __jsvml_expf16_ha_z0 is the method for computing 16 element vector float exp using AVX 512 insns
// __jsvml_exp8_ha_z0 is the method for computing 8 element vector double exp using AVX 512 insns
log_info(library)("Loaded library %s, handle " INTPTR_FORMAT, JNI_LIB_PREFIX "jsvml" JNI_LIB_SUFFIX, p2i(libjsvml));
if (UseAVX > 2) {
for (int op = 0; op < VectorSupport::NUM_VECTOR_OP_MATH; op++) {
int vop = VectorSupport::VECTOR_OP_MATH_START + op;
if ((!VM_Version::supports_avx512dq()) &&
(vop == VectorSupport::VECTOR_OP_LOG || vop == VectorSupport::VECTOR_OP_LOG10 || vop == VectorSupport::VECTOR_OP_POW)) {
continue;
}
snprintf(ebuf, sizeof(ebuf), "__jsvml_%sf16_ha_z0", VectorSupport::mathname[op]);
StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_512][op] = (address)os::dll_lookup(libjsvml, ebuf);
snprintf(ebuf, sizeof(ebuf), "__jsvml_%s8_ha_z0", VectorSupport::mathname[op]);
StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_512][op] = (address)os::dll_lookup(libjsvml, ebuf);
}
}
const char* avx_sse_str = (UseAVX >= 2) ? "l9" : ((UseAVX == 1) ? "e9" : "ex");
for (int op = 0; op < VectorSupport::NUM_VECTOR_OP_MATH; op++) {
int vop = VectorSupport::VECTOR_OP_MATH_START + op;
if (vop == VectorSupport::VECTOR_OP_POW) {
continue;
}
snprintf(ebuf, sizeof(ebuf), "__jsvml_%sf4_ha_%s", VectorSupport::mathname[op], avx_sse_str);
StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_64][op] = (address)os::dll_lookup(libjsvml, ebuf);
snprintf(ebuf, sizeof(ebuf), "__jsvml_%sf4_ha_%s", VectorSupport::mathname[op], avx_sse_str);
StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_128][op] = (address)os::dll_lookup(libjsvml, ebuf);
snprintf(ebuf, sizeof(ebuf), "__jsvml_%sf8_ha_%s", VectorSupport::mathname[op], avx_sse_str);
StubRoutines::_vector_f_math[VectorSupport::VEC_SIZE_256][op] = (address)os::dll_lookup(libjsvml, ebuf);
snprintf(ebuf, sizeof(ebuf), "__jsvml_%s1_ha_%s", VectorSupport::mathname[op], avx_sse_str);
StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_64][op] = (address)os::dll_lookup(libjsvml, ebuf);
snprintf(ebuf, sizeof(ebuf), "__jsvml_%s2_ha_%s", VectorSupport::mathname[op], avx_sse_str);
StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_128][op] = (address)os::dll_lookup(libjsvml, ebuf);
snprintf(ebuf, sizeof(ebuf), "__jsvml_%s4_ha_%s", VectorSupport::mathname[op], avx_sse_str);
StubRoutines::_vector_d_math[VectorSupport::VEC_SIZE_256][op] = (address)os::dll_lookup(libjsvml, ebuf);
}
}
#endif // COMPILER2
#endif // COMPILER2_OR_JVMCI
}

View File

@ -72,8 +72,6 @@ static get_cpu_info_stub_t get_cpu_info_stub = nullptr;
static detect_virt_stub_t detect_virt_stub = nullptr;
static clear_apx_test_state_t clear_apx_test_state_stub = nullptr;
#ifdef _LP64
bool VM_Version::supports_clflush() {
// clflush should always be available on x86_64
// if not we are in real trouble because we rely on it
@ -87,7 +85,6 @@ bool VM_Version::supports_clflush() {
assert ((!Universe::is_fully_initialized() || (_features & CPU_FLUSH) != 0), "clflush should be available");
return true;
}
#endif
#define CPUID_STANDARD_FN 0x0
#define CPUID_STANDARD_FN_1 0x1
@ -107,7 +104,6 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
#if defined(_LP64)
address clear_apx_test_state() {
# define __ _masm->
address start = __ pc();
@ -126,7 +122,6 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ ret(0);
return start;
}
#endif
address generate_get_cpu_info() {
// Flags to test CPU type.
@ -151,14 +146,10 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
//
// void get_cpu_info(VM_Version::CpuidInfo* cpuid_info);
//
// LP64: rcx and rdx are first and second argument registers on windows
// rcx and rdx are first and second argument registers on windows
__ push(rbp);
#ifdef _LP64
__ mov(rbp, c_rarg0); // cpuid_info address
#else
__ movptr(rbp, Address(rsp, 8)); // cpuid_info address
#endif
__ push(rbx);
__ push(rsi);
__ pushf(); // preserve rbx, and flags
@ -418,7 +409,6 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movl(Address(rsi, 8), rcx);
__ movl(Address(rsi,12), rdx);
#if defined(_LP64)
//
// Check if OS has enabled XGETBV instruction to access XCR0
// (OSXSAVE feature flag) and CPU supports APX
@ -453,7 +443,6 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movq(Address(rsi, 8), r31);
UseAPX = save_apx;
#endif
#endif
__ bind(vector_save_restore);
//
@ -527,10 +516,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movdl(xmm0, rcx);
__ vpbroadcastd(xmm0, xmm0, Assembler::AVX_512bit);
__ evmovdqul(xmm7, xmm0, Assembler::AVX_512bit);
#ifdef _LP64
__ evmovdqul(xmm8, xmm0, Assembler::AVX_512bit);
__ evmovdqul(xmm31, xmm0, Assembler::AVX_512bit);
#endif
VM_Version::clean_cpuFeatures();
__ jmp(save_restore_except);
}
@ -556,10 +543,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ pshufd(xmm0, xmm0, 0x00);
__ vinsertf128_high(xmm0, xmm0);
__ vmovdqu(xmm7, xmm0);
#ifdef _LP64
__ vmovdqu(xmm8, xmm0);
__ vmovdqu(xmm15, xmm0);
#endif
VM_Version::clean_cpuFeatures();
__ bind(save_restore_except);
@ -600,10 +585,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ lea(rsi, Address(rbp, in_bytes(VM_Version::zmm_save_offset())));
__ evmovdqul(Address(rsi, 0), xmm0, Assembler::AVX_512bit);
__ evmovdqul(Address(rsi, 64), xmm7, Assembler::AVX_512bit);
#ifdef _LP64
__ evmovdqul(Address(rsi, 128), xmm8, Assembler::AVX_512bit);
__ evmovdqul(Address(rsi, 192), xmm31, Assembler::AVX_512bit);
#endif
#ifdef _WINDOWS
__ evmovdqul(xmm31, Address(rsp, 0), Assembler::AVX_512bit);
@ -628,10 +611,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset())));
__ vmovdqu(Address(rsi, 0), xmm0);
__ vmovdqu(Address(rsi, 32), xmm7);
#ifdef _LP64
__ vmovdqu(Address(rsi, 64), xmm8);
__ vmovdqu(Address(rsi, 96), xmm15);
#endif
#ifdef _WINDOWS
__ vmovdqu(xmm15, Address(rsp, 0));
@ -687,13 +668,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ push(rbx);
__ push(rsi); // for Windows
#ifdef _LP64
__ mov(rax, c_rarg0); // CPUID leaf
__ mov(rsi, c_rarg1); // register array address (eax, ebx, ecx, edx)
#else
__ movptr(rax, Address(rsp, 16)); // CPUID leaf
__ movptr(rsi, Address(rsp, 20)); // register array address
#endif
__ cpuid();
@ -734,14 +710,10 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
//
// void getCPUIDBrandString(VM_Version::CpuidInfo* cpuid_info);
//
// LP64: rcx and rdx are first and second argument registers on windows
// rcx and rdx are first and second argument registers on windows
__ push(rbp);
#ifdef _LP64
__ mov(rbp, c_rarg0); // cpuid_info address
#else
__ movptr(rbp, Address(rsp, 8)); // cpuid_info address
#endif
__ push(rbx);
__ push(rsi);
__ pushf(); // preserve rbx, and flags
@ -889,19 +861,16 @@ void VM_Version::get_processor_features() {
// xchg and xadd instructions
_supports_atomic_getset4 = true;
_supports_atomic_getadd4 = true;
LP64_ONLY(_supports_atomic_getset8 = true);
LP64_ONLY(_supports_atomic_getadd8 = true);
_supports_atomic_getset8 = true;
_supports_atomic_getadd8 = true;
#ifdef _LP64
// OS should support SSE for x64 and hardware should support at least SSE2.
if (!VM_Version::supports_sse2()) {
vm_exit_during_initialization("Unknown x64 processor: SSE2 not supported");
}
// in 64 bit the use of SSE2 is the minimum
if (UseSSE < 2) UseSSE = 2;
#endif
#ifdef AMD64
// flush_icache_stub have to be generated first.
// That is why Icache line size is hard coded in ICache class,
// see icache_x86.hpp. It is also the reason why we can't use
@ -913,9 +882,7 @@ void VM_Version::get_processor_features() {
guarantee(_cpuid_info.std_cpuid1_edx.bits.clflush != 0, "clflush is not supported");
// clflush_size is size in quadwords (8 bytes).
guarantee(_cpuid_info.std_cpuid1_ebx.bits.clflush_size == 8, "such clflush size is not supported");
#endif
#ifdef _LP64
// assigning this field effectively enables Unsafe.writebackMemory()
// by initing UnsafeConstant.DATA_CACHE_LINE_FLUSH_SIZE to non-zero
// that is only implemented on x86_64 and only if the OS plays ball
@ -924,7 +891,6 @@ void VM_Version::get_processor_features() {
// let if default to zero thereby disabling writeback
_data_cache_line_flush_size = _cpuid_info.std_cpuid1_ebx.bits.clflush_size * 8;
}
#endif
// Check if processor has Intel Ecore
if (FLAG_IS_DEFAULT(EnableX86ECoreOpts) && is_intel() && cpu_family() == 6 &&
@ -1114,15 +1080,19 @@ void VM_Version::get_processor_features() {
}
char buf[1024];
int res = jio_snprintf(
int cpu_info_size = jio_snprintf(
buf, sizeof(buf),
"(%u cores per cpu, %u threads per core) family %d model %d stepping %d microcode 0x%x",
cores_per_cpu(), threads_per_core(),
cpu_family(), _model, _stepping, os::cpu_microcode_revision());
assert(res > 0, "not enough temporary space allocated");
insert_features_names(buf + res, sizeof(buf) - res, _features_names);
assert(cpu_info_size > 0, "not enough temporary space allocated");
insert_features_names(buf + cpu_info_size, sizeof(buf) - cpu_info_size, _features_names);
_features_string = os::strdup(buf);
_cpu_info_string = os::strdup(buf);
_features_string = extract_features_string(_cpu_info_string,
strnlen(_cpu_info_string, sizeof(buf)),
cpu_info_size);
// Use AES instructions if available.
if (supports_aes()) {
@ -1206,7 +1176,6 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
}
#ifdef _LP64
if (supports_avx2()) {
if (FLAG_IS_DEFAULT(UseAdler32Intrinsics)) {
UseAdler32Intrinsics = true;
@ -1217,12 +1186,6 @@ void VM_Version::get_processor_features() {
}
FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
}
#else
if (UseAdler32Intrinsics) {
warning("Adler32Intrinsics not available on this CPU.");
FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
}
#endif
if (supports_sse4_2() && supports_clmul()) {
if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
@ -1246,7 +1209,6 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
}
#ifdef _LP64
// ChaCha20 Intrinsics
// As long as the system supports AVX as a baseline we can do a
// SIMD-enabled block function. StubGenerator makes the determination
@ -1262,24 +1224,14 @@ void VM_Version::get_processor_features() {
}
FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false);
}
#else
// No support currently for ChaCha20 intrinsics on 32-bit platforms
if (UseChaCha20Intrinsics) {
warning("ChaCha20 intrinsics are not available on this CPU.");
FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false);
}
#endif // _LP64
// Dilithium Intrinsics
// Currently we only have them for AVX512
#ifdef _LP64
if (supports_evex() && supports_avx512bw()) {
if (FLAG_IS_DEFAULT(UseDilithiumIntrinsics)) {
UseDilithiumIntrinsics = true;
}
} else
#endif
if (UseDilithiumIntrinsics) {
} else if (UseDilithiumIntrinsics) {
warning("Intrinsics for ML-DSA are not available on this CPU.");
FLAG_SET_DEFAULT(UseDilithiumIntrinsics, false);
}
@ -1308,7 +1260,7 @@ void VM_Version::get_processor_features() {
UseMD5Intrinsics = true;
}
if (supports_sha() LP64_ONLY(|| (supports_avx2() && supports_bmi2()))) {
if (supports_sha() || (supports_avx2() && supports_bmi2())) {
if (FLAG_IS_DEFAULT(UseSHA)) {
UseSHA = true;
}
@ -1335,27 +1287,20 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
}
#ifdef _LP64
// These are only supported on 64-bit
if (UseSHA && supports_avx2() && (supports_bmi2() || supports_sha512())) {
if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
}
} else
#endif
if (UseSHA512Intrinsics) {
} else if (UseSHA512Intrinsics) {
warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
}
#ifdef _LP64
if (supports_evex() && supports_avx512bw()) {
if (FLAG_IS_DEFAULT(UseSHA3Intrinsics)) {
UseSHA3Intrinsics = true;
}
} else
#endif
if (UseSHA3Intrinsics) {
} else if (UseSHA3Intrinsics) {
warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA3Intrinsics, false);
}
@ -1377,11 +1322,7 @@ void VM_Version::get_processor_features() {
max_vector_size = 64;
}
#ifdef _LP64
int min_vector_size = 4; // We require MaxVectorSize to be at least 4 on 64bit
#else
int min_vector_size = 0;
#endif
if (!FLAG_IS_DEFAULT(MaxVectorSize)) {
if (MaxVectorSize < min_vector_size) {
@ -1405,7 +1346,7 @@ void VM_Version::get_processor_features() {
if (MaxVectorSize > 0) {
if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) {
tty->print_cr("State of YMM registers after signal handle:");
int nreg = 2 LP64_ONLY(+2);
int nreg = 4;
const char* ymm_name[4] = {"0", "7", "8", "15"};
for (int i = 0; i < nreg; i++) {
tty->print("YMM%s:", ymm_name[i]);
@ -1418,31 +1359,24 @@ void VM_Version::get_processor_features() {
}
#endif // COMPILER2 && ASSERT
#ifdef _LP64
if ((supports_avx512ifma() && supports_avx512vlbw()) || supports_avxifma()) {
if (FLAG_IS_DEFAULT(UsePoly1305Intrinsics)) {
FLAG_SET_DEFAULT(UsePoly1305Intrinsics, true);
}
} else
#endif
if (UsePoly1305Intrinsics) {
} else if (UsePoly1305Intrinsics) {
warning("Intrinsics for Poly1305 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UsePoly1305Intrinsics, false);
}
#ifdef _LP64
if ((supports_avx512ifma() && supports_avx512vlbw()) || supports_avxifma()) {
if (FLAG_IS_DEFAULT(UseIntPolyIntrinsics)) {
FLAG_SET_DEFAULT(UseIntPolyIntrinsics, true);
}
} else
#endif
if (UseIntPolyIntrinsics) {
} else if (UseIntPolyIntrinsics) {
warning("Intrinsics for Polynomial crypto functions not available on this CPU.");
FLAG_SET_DEFAULT(UseIntPolyIntrinsics, false);
}
#ifdef _LP64
if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
UseMultiplyToLenIntrinsic = true;
}
@ -1458,38 +1392,6 @@ void VM_Version::get_processor_features() {
if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
UseMontgomerySquareIntrinsic = true;
}
#else
if (UseMultiplyToLenIntrinsic) {
if (!FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
warning("multiplyToLen intrinsic is not available in 32-bit VM");
}
FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false);
}
if (UseMontgomeryMultiplyIntrinsic) {
if (!FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
warning("montgomeryMultiply intrinsic is not available in 32-bit VM");
}
FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, false);
}
if (UseMontgomerySquareIntrinsic) {
if (!FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
warning("montgomerySquare intrinsic is not available in 32-bit VM");
}
FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, false);
}
if (UseSquareToLenIntrinsic) {
if (!FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
warning("squareToLen intrinsic is not available in 32-bit VM");
}
FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, false);
}
if (UseMulAddIntrinsic) {
if (!FLAG_IS_DEFAULT(UseMulAddIntrinsic)) {
warning("mulAdd intrinsic is not available in 32-bit VM");
}
FLAG_SET_DEFAULT(UseMulAddIntrinsic, false);
}
#endif // _LP64
#endif // COMPILER2_OR_JVMCI
// On new cpus instructions which update whole XMM register should be used
@ -1766,7 +1668,6 @@ void VM_Version::get_processor_features() {
}
#endif
#ifdef _LP64
if (UseSSE42Intrinsics) {
if (FLAG_IS_DEFAULT(UseVectorizedMismatchIntrinsic)) {
UseVectorizedMismatchIntrinsic = true;
@ -1783,20 +1684,6 @@ void VM_Version::get_processor_features() {
warning("vectorizedHashCode intrinsics are not available on this CPU");
FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, false);
}
#else
if (UseVectorizedMismatchIntrinsic) {
if (!FLAG_IS_DEFAULT(UseVectorizedMismatchIntrinsic)) {
warning("vectorizedMismatch intrinsic is not available in 32-bit VM");
}
FLAG_SET_DEFAULT(UseVectorizedMismatchIntrinsic, false);
}
if (UseVectorizedHashCodeIntrinsic) {
if (!FLAG_IS_DEFAULT(UseVectorizedHashCodeIntrinsic)) {
warning("vectorizedHashCode intrinsic is not available in 32-bit VM");
}
FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, false);
}
#endif // _LP64
// Use count leading zeros count instruction if available.
if (supports_lzcnt()) {
@ -1945,7 +1832,6 @@ void VM_Version::get_processor_features() {
#endif
}
#ifdef _LP64
// Prefetch settings
// Prefetch interval for gc copy/scan == 9 dcache lines. Derived from
@ -1964,7 +1850,6 @@ void VM_Version::get_processor_features() {
if (FLAG_IS_DEFAULT(PrefetchScanIntervalInBytes)) {
FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, 576);
}
#endif
if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
(cache_line_size > ContendedPaddingWidth))
@ -2195,11 +2080,9 @@ int VM_Version::avx3_threshold() {
FLAG_IS_DEFAULT(AVX3Threshold)) ? 0 : AVX3Threshold;
}
#if defined(_LP64)
void VM_Version::clear_apx_test_state() {
clear_apx_test_state_stub();
}
#endif
static bool _vm_version_initialized = false;
@ -2217,14 +2100,11 @@ void VM_Version::initialize() {
g.generate_get_cpu_info());
detect_virt_stub = CAST_TO_FN_PTR(detect_virt_stub_t,
g.generate_detect_virt());
#if defined(_LP64)
clear_apx_test_state_stub = CAST_TO_FN_PTR(clear_apx_test_state_t,
g.clear_apx_test_state());
#endif
get_processor_features();
LP64_ONLY(Assembler::precompute_instructions();)
Assembler::precompute_instructions();
if (VM_Version::supports_hv()) { // Supports hypervisor
check_virtualizations();
@ -2991,12 +2871,10 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const {
result |= CPU_CMOV;
if (std_cpuid1_edx.bits.clflush != 0)
result |= CPU_FLUSH;
#ifdef _LP64
// clflush should always be available on x86_64
// if not we are in real trouble because we rely on it
// to flush the code cache.
assert ((result & CPU_FLUSH) != 0, "clflush should be available");
#endif
if (std_cpuid1_edx.bits.fxsr != 0 || (is_amd_family() &&
ext_cpuid1_edx.bits.fxsr != 0))
result |= CPU_FXSR;
@ -3168,7 +3046,7 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const {
bool VM_Version::os_supports_avx_vectors() {
bool retVal = false;
int nreg = 2 LP64_ONLY(+2);
int nreg = 4;
if (supports_evex()) {
// Verify that OS save/restore all bits of EVEX registers
// during signal processing.
@ -3324,11 +3202,7 @@ int VM_Version::allocate_prefetch_distance(bool use_watermark_prefetch) {
if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus
return 192;
} else if (use_watermark_prefetch) { // watermark prefetching on Core
#ifdef _LP64
return 384;
#else
return 320;
#endif
}
}
if (supports_sse2()) {

View File

@ -642,7 +642,7 @@ public:
static void set_cpuinfo_cont_addr_apx(address pc) { _cpuinfo_cont_addr_apx = pc; }
static address cpuinfo_cont_addr_apx() { return _cpuinfo_cont_addr_apx; }
LP64_ONLY(static void clear_apx_test_state());
static void clear_apx_test_state();
static void clean_cpuFeatures() { _features = 0; }
static void set_avx_cpuFeatures() { _features |= (CPU_SSE | CPU_SSE2 | CPU_AVX | CPU_VZEROUPPER ); }
@ -839,12 +839,12 @@ public:
// x86_64 supports fast class initialization checks
static bool supports_fast_class_init_checks() {
return LP64_ONLY(true) NOT_LP64(false); // not implemented on x86_32
return true;
}
// x86_64 supports secondary supers table
constexpr static bool supports_secondary_supers_table() {
return LP64_ONLY(true) NOT_LP64(false); // not implemented on x86_32
return true;
}
constexpr static bool supports_stack_watermark_barrier() {
@ -879,11 +879,7 @@ public:
// synchronize with other memory ops. so, it needs preceding
// and trailing StoreStore fences.
#ifdef _LP64
static bool supports_clflush(); // Can't inline due to header file conflict
#else
static bool supports_clflush() { return ((_features & CPU_FLUSH) != 0); }
#endif // _LP64
// Note: CPU_FLUSHOPT and CPU_CLWB bits should always be zero for 32-bit
static bool supports_clflushopt() { return ((_features & CPU_FLUSHOPT) != 0); }

View File

@ -422,6 +422,18 @@ source_hpp %{
#include "peephole_x86_64.hpp"
bool castLL_is_imm32(const Node* n);
%}
source %{
bool castLL_is_imm32(const Node* n) {
assert(n->is_CastLL(), "must be a CastLL");
const TypeLong* t = n->bottom_type()->is_long();
return (t->_lo == min_jlong || Assembler::is_simm32(t->_lo)) && (t->_hi == max_jlong || Assembler::is_simm32(t->_hi));
}
%}
// Register masks
@ -1584,14 +1596,11 @@ uint MachUEPNode::size(PhaseRegAlloc* ra_) const
//=============================================================================
bool Matcher::supports_vector_calling_convention(void) {
if (EnableVectorSupport && UseVectorStubs) {
return true;
}
return false;
return EnableVectorSupport;
}
OptoRegPair Matcher::vector_return_value(uint ideal_reg) {
assert(EnableVectorSupport && UseVectorStubs, "sanity");
assert(EnableVectorSupport, "sanity");
int lo = XMM0_num;
int hi = XMM0b_num;
if (ideal_reg == Op_VecX) hi = XMM0d_num;
@ -1838,14 +1847,14 @@ encode %{
%}
enc_class clear_avx %{
debug_only(int off0 = __ offset());
DEBUG_ONLY(int off0 = __ offset());
if (generate_vzeroupper(Compile::current())) {
// Clear upper bits of YMM registers to avoid AVX <-> SSE transition penalty
// Clear upper bits of YMM registers when current compiled code uses
// wide vectors to avoid AVX <-> SSE transition penalty during call.
__ vzeroupper();
}
debug_only(int off1 = __ offset());
DEBUG_ONLY(int off1 = __ offset());
assert(off1 - off0 == clear_avx_size(), "correct size prediction");
%}
@ -7605,6 +7614,7 @@ instruct castPP(rRegP dst)
instruct castII(rRegI dst)
%{
predicate(VerifyConstraintCasts == 0);
match(Set dst (CastII dst));
size(0);
@ -7614,8 +7624,22 @@ instruct castII(rRegI dst)
ins_pipe(empty);
%}
instruct castII_checked(rRegI dst, rFlagsReg cr)
%{
predicate(VerifyConstraintCasts > 0);
match(Set dst (CastII dst));
effect(KILL cr);
format %{ "# cast_checked_II $dst" %}
ins_encode %{
__ verify_int_in_range(_idx, bottom_type()->is_int(), $dst$$Register);
%}
ins_pipe(pipe_slow);
%}
instruct castLL(rRegL dst)
%{
predicate(VerifyConstraintCasts == 0);
match(Set dst (CastLL dst));
size(0);
@ -7625,6 +7649,32 @@ instruct castLL(rRegL dst)
ins_pipe(empty);
%}
instruct castLL_checked_L32(rRegL dst, rFlagsReg cr)
%{
predicate(VerifyConstraintCasts > 0 && castLL_is_imm32(n));
match(Set dst (CastLL dst));
effect(KILL cr);
format %{ "# cast_checked_LL $dst" %}
ins_encode %{
__ verify_long_in_range(_idx, bottom_type()->is_long(), $dst$$Register, noreg);
%}
ins_pipe(pipe_slow);
%}
instruct castLL_checked(rRegL dst, rRegL tmp, rFlagsReg cr)
%{
predicate(VerifyConstraintCasts > 0 && !castLL_is_imm32(n));
match(Set dst (CastLL dst));
effect(KILL cr, TEMP tmp);
format %{ "# cast_checked_LL $dst\tusing $tmp as TEMP" %}
ins_encode %{
__ verify_long_in_range(_idx, bottom_type()->is_long(), $dst$$Register, $tmp$$Register);
%}
ins_pipe(pipe_slow);
%}
instruct castFF(regF dst)
%{
match(Set dst (CastFF dst));

View File

@ -151,6 +151,6 @@ void VM_Version::initialize_cpu_information(void) {
_no_of_threads = _no_of_cores;
_no_of_sockets = _no_of_cores;
snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "Zero VM");
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _features_string);
snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "%s", _cpu_info_string);
_initialized = true;
}

View File

@ -132,8 +132,6 @@ extern "C" int getargs(procsinfo*, int, char*, int);
#define MAX_PATH (2 * K)
// for timer info max values which include all bits
#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
// for multipage initialization error analysis (in 'g_multipage_error')
#define ERROR_MP_OS_TOO_OLD 100
#define ERROR_MP_EXTSHM_ACTIVE 101
@ -906,7 +904,7 @@ jlong os::javaTimeNanos() {
}
void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
info_ptr->max_value = ALL_64_BITS;
info_ptr->max_value = all_bits_jlong;
// mread_real_time() is monotonic (see 'os::javaTimeNanos()')
info_ptr->may_skip_backward = false;
info_ptr->may_skip_forward = false;
@ -2571,14 +2569,14 @@ jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
}
void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits
info_ptr->may_skip_backward = false; // elapsed time not wall time
info_ptr->may_skip_forward = false; // elapsed time not wall time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
}
void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits
info_ptr->may_skip_backward = false; // elapsed time not wall time
info_ptr->may_skip_forward = false; // elapsed time not wall time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned

View File

@ -72,7 +72,7 @@ enum {
* Get info for requested PID from /proc/<pid>/psinfo file
*/
static bool read_psinfo(const u_longlong_t& pid, psinfo_t& psinfo) {
static size_t BUF_LENGTH = 32 + sizeof(u_longlong_t);
const size_t BUF_LENGTH = 32 + sizeof(u_longlong_t);
FILE* fp;
char buf[BUF_LENGTH];
@ -118,7 +118,6 @@ static OSReturn get_lcpu_ticks(perfstat_id_t* lcpu_name, cpu_tick_store_t* ptick
* Return CPU load caused by the currently executing process (the jvm).
*/
static OSReturn get_jvm_load(double* jvm_uload, double* jvm_sload) {
static clock_t ticks_per_sec = sysconf(_SC_CLK_TCK);
static u_longlong_t last_timebase = 0;
perfstat_process_t jvm_stats;
@ -204,8 +203,6 @@ static bool populate_lcpu_names(int ncpus, perfstat_id_t* lcpu_names) {
* (Context Switches / Tick) * (Tick / s) = Context Switches per second
*/
static OSReturn perf_context_switch_rate(double* rate) {
static clock_t ticks_per_sec = sysconf(_SC_CLK_TCK);
u_longlong_t ticks;
perfstat_cpu_total_t cpu_stats;
@ -214,7 +211,7 @@ static OSReturn perf_context_switch_rate(double* rate) {
}
ticks = cpu_stats.user + cpu_stats.sys + cpu_stats.idle + cpu_stats.wait;
*rate = (cpu_stats.pswitch / ticks) * ticks_per_sec;
*rate = (cpu_stats.pswitch / ticks) * os::Posix::clock_tics_per_second();
return OS_OK;
}

View File

@ -77,7 +77,7 @@ ZPhysicalMemoryBacking::ZPhysicalMemoryBacking(size_t max_capacity)
_initialized(false) {
// Reserve address space for backing memory
_base = (uintptr_t)os::reserve_memory(max_capacity, false, mtJavaHeap);
_base = (uintptr_t)os::reserve_memory(max_capacity, mtJavaHeap);
if (_base == 0) {
// Failed
ZInitialize::error("Failed to reserve address space for backing memory");

View File

@ -114,9 +114,6 @@
#define MAX_PATH (2 * K)
// for timer info max values which include all bits
#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
////////////////////////////////////////////////////////////////////////////////
// global variables
julong os::Bsd::_physical_memory = 0;
@ -815,7 +812,7 @@ jlong os::javaTimeNanos() {
}
void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
info_ptr->max_value = ALL_64_BITS;
info_ptr->max_value = all_bits_jlong;
info_ptr->may_skip_backward = false; // not subject to resetting or drifting
info_ptr->may_skip_forward = false; // not subject to resetting or drifting
info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time
@ -2423,14 +2420,14 @@ jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits
info_ptr->may_skip_backward = false; // elapsed time not wall time
info_ptr->may_skip_forward = false; // elapsed time not wall time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
}
void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits
info_ptr->may_skip_backward = false; // elapsed time not wall time
info_ptr->may_skip_forward = false; // elapsed time not wall time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned

View File

@ -139,9 +139,6 @@
#define MAX_PATH (2 * K)
// for timer info max values which include all bits
#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
#ifdef MUSL_LIBC
// dlvsym is not a part of POSIX
// and musl libc doesn't implement it.
@ -213,8 +210,6 @@ typedef int (*malloc_info_func_t)(int options, FILE *stream);
static malloc_info_func_t g_malloc_info = nullptr;
#endif // __GLIBC__
static int clock_tics_per_sec = 100;
// If the VM might have been created on the primordial thread, we need to resolve the
// primordial thread stack bounds and check if the current thread might be the
// primordial thread in places. If we know that the primordial thread is never used,
@ -1667,7 +1662,7 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) {
}
ThreadInVMfromNative tiv(jt);
debug_only(VMNativeEntryWrapper vew;)
DEBUG_ONLY(VMNativeEntryWrapper vew;)
VM_LinuxDllLoad op(filename, ebuf, ebuflen);
VMThread::execute(&op);
@ -4381,8 +4376,6 @@ static void check_pax(void) {
// this is called _before_ most of the global arguments have been parsed
void os::init(void) {
char dummy; // used to get a guess on initial stack address
clock_tics_per_sec = checked_cast<int>(sysconf(_SC_CLK_TCK));
int sys_pg_size = checked_cast<int>(sysconf(_SC_PAGESIZE));
if (sys_pg_size < 0) {
fatal("os_linux.cpp: os::init: sysconf failed (%s)",
@ -4575,7 +4568,7 @@ static void workaround_expand_exec_shield_cs_limit() {
*/
char* hint = (char*)(os::Linux::initial_thread_stack_bottom() -
(StackOverflow::stack_guard_zone_size() + page_size));
char* codebuf = os::attempt_reserve_memory_at(hint, page_size, false, mtThread);
char* codebuf = os::attempt_reserve_memory_at(hint, page_size, mtThread);
if (codebuf == nullptr) {
// JDK-8197429: There may be a stack gap of one megabyte between
@ -4583,7 +4576,7 @@ static void workaround_expand_exec_shield_cs_limit() {
// Linux kernel workaround for CVE-2017-1000364. If we failed to
// map our codebuf, try again at an address one megabyte lower.
hint -= 1 * M;
codebuf = os::attempt_reserve_memory_at(hint, page_size, false, mtThread);
codebuf = os::attempt_reserve_memory_at(hint, page_size, mtThread);
}
if ((codebuf == nullptr) || (!os::commit_memory(codebuf, page_size, true))) {
@ -5135,21 +5128,21 @@ static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
&user_time, &sys_time);
if (count != 13) return -1;
if (user_sys_cpu_time) {
return ((jlong)sys_time + (jlong)user_time) * (1000000000 / clock_tics_per_sec);
return ((jlong)sys_time + (jlong)user_time) * (1000000000 / os::Posix::clock_tics_per_second());
} else {
return (jlong)user_time * (1000000000 / clock_tics_per_sec);
return (jlong)user_time * (1000000000 / os::Posix::clock_tics_per_second());
}
}
void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits
info_ptr->may_skip_backward = false; // elapsed time not wall time
info_ptr->may_skip_forward = false; // elapsed time not wall time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
}
void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits
info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits
info_ptr->may_skip_backward = false; // elapsed time not wall time
info_ptr->may_skip_forward = false; // elapsed time not wall time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned

View File

@ -492,9 +492,9 @@ static char* chop_extra_memory(size_t size, size_t alignment, char* extra_base,
// Multiple threads can race in this code, and can remap over each other with MAP_FIXED,
// so on posix, unmap the section at the start and at the end of the chunk that we mapped
// rather than unmapping and remapping the whole chunk to get requested alignment.
char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) {
char* os::reserve_memory_aligned(size_t size, size_t alignment, MemTag mem_tag, bool exec) {
size_t extra_size = calculate_aligned_extra_size(size, alignment);
char* extra_base = os::reserve_memory(extra_size, exec);
char* extra_base = os::reserve_memory(extra_size, mem_tag, exec);
if (extra_base == nullptr) {
return nullptr;
}
@ -1326,6 +1326,10 @@ void os::Posix::init_2(void) {
_use_clock_monotonic_condattr ? "CLOCK_MONOTONIC" : "the default clock");
}
int os::Posix::clock_tics_per_second() {
return clock_tics_per_sec;
}
// Utility to convert the given timeout to an absolute timespec
// (based on the appropriate clock) to use with pthread_cond_timewait,
// and sem_timedwait().
@ -1473,12 +1477,9 @@ jlong os::javaTimeNanos() {
return result;
}
// for timer info max values which include all bits
#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
// CLOCK_MONOTONIC - amount of time since some arbitrary point in the past
info_ptr->max_value = ALL_64_BITS;
info_ptr->max_value = all_bits_jlong;
info_ptr->may_skip_backward = false; // not subject to resetting or drifting
info_ptr->may_skip_forward = false; // not subject to resetting or drifting
info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -91,6 +91,9 @@ public:
static void to_RTC_abstime(timespec* abstime, int64_t millis);
// clock ticks per second of the system
static int clock_tics_per_second();
static bool handle_stack_overflow(JavaThread* thread, address addr, address pc,
const void* ucVoid,
address* stub);

View File

@ -64,7 +64,7 @@ static char* backing_store_file_name = nullptr; // name of the backing store
static char* create_standard_memory(size_t size) {
// allocate an aligned chuck of memory
char* mapAddress = os::reserve_memory(size);
char* mapAddress = os::reserve_memory(size, mtInternal);
if (mapAddress == nullptr) {
return nullptr;

View File

@ -147,7 +147,7 @@ public:
};
debug_only(static bool signal_sets_initialized = false);
DEBUG_ONLY(static bool signal_sets_initialized = false);
static sigset_t unblocked_sigs, vm_sigs, preinstalled_sigs;
// Our own signal handlers should never ever get replaced by a third party one.
@ -1547,7 +1547,7 @@ static void signal_sets_init() {
if (!ReduceSignalUsage) {
sigaddset(&vm_sigs, BREAK_SIGNAL);
}
debug_only(signal_sets_initialized = true);
DEBUG_ONLY(signal_sets_initialized = true);
}
// These are signals that are unblocked while a thread is running Java.

View File

@ -112,9 +112,6 @@
#include <winsock2.h>
#include <versionhelpers.h>
// for timer info max values which include all bits
#define ALL_64_BITS CONST64(-1)
// For DLL loading/load error detection
// Values of PE COFF
#define IMAGE_FILE_PTR_TO_SIGNATURE 0x3c
@ -1225,16 +1222,16 @@ void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
if (freq < NANOSECS_PER_SEC) {
// the performance counter is 64 bits and we will
// be multiplying it -- so no wrap in 64 bits
info_ptr->max_value = ALL_64_BITS;
info_ptr->max_value = all_bits_jlong;
} else if (freq > NANOSECS_PER_SEC) {
// use the max value the counter can reach to
// determine the max value which could be returned
julong max_counter = (julong)ALL_64_BITS;
julong max_counter = (julong)all_bits_jlong;
info_ptr->max_value = (jlong)(max_counter / (freq / NANOSECS_PER_SEC));
} else {
// the performance counter is 64 bits and we will
// be using it directly -- so no wrap in 64 bits
info_ptr->max_value = ALL_64_BITS;
info_ptr->max_value = all_bits_jlong;
}
// using a counter, so no skipping
@ -3020,7 +3017,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags,
PAGE_READWRITE);
// If reservation failed, return null
if (p_buf == nullptr) return nullptr;
MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC);
MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC, mtNone);
os::release_memory(p_buf, bytes + chunk_size);
// we still need to round up to a page boundary (in case we are using large pages)
@ -3081,7 +3078,7 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags,
// need to create a dummy 'reserve' record to match
// the release.
MemTracker::record_virtual_memory_reserve((address)p_buf,
bytes_to_release, CALLER_PC);
bytes_to_release, CALLER_PC, mtNone);
os::release_memory(p_buf, bytes_to_release);
}
#ifdef ASSERT
@ -3099,9 +3096,9 @@ static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags,
// Although the memory is allocated individually, it is returned as one.
// NMT records it as one block.
if ((flags & MEM_COMMIT) != 0) {
MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC);
MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC, mtNone);
} else {
MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC);
MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC, mtNone);
}
// made it this far, success
@ -3241,7 +3238,7 @@ char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, in
// Multiple threads can race in this code but it's not possible to unmap small sections of
// virtual space to get requested alignment, like posix-like os's.
// Windows prevents multiple thread from remapping over each other so this loop is thread-safe.
static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MemTag mem_tag = mtNone) {
static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc, MemTag mem_tag) {
assert(is_aligned(alignment, os::vm_allocation_granularity()),
"Alignment must be a multiple of allocation granularity (page size)");
assert(is_aligned(size, os::vm_allocation_granularity()),
@ -3255,7 +3252,7 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi
for (int attempt = 0; attempt < max_attempts && aligned_base == nullptr; attempt ++) {
char* extra_base = file_desc != -1 ? os::map_memory_to_file(extra_size, file_desc, mem_tag) :
os::reserve_memory(extra_size, false, mem_tag);
os::reserve_memory(extra_size, mem_tag);
if (extra_base == nullptr) {
return nullptr;
}
@ -3272,7 +3269,7 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi
// Attempt to map, into the just vacated space, the slightly smaller aligned area.
// Which may fail, hence the loop.
aligned_base = file_desc != -1 ? os::attempt_map_memory_to_file_at(aligned_base, size, file_desc, mem_tag) :
os::attempt_reserve_memory_at(aligned_base, size, false, mem_tag);
os::attempt_reserve_memory_at(aligned_base, size, mem_tag);
}
assert(aligned_base != nullptr,
@ -3281,9 +3278,9 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi
return aligned_base;
}
char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) {
char* os::reserve_memory_aligned(size_t size, size_t alignment, MemTag mem_tag, bool exec) {
// exec can be ignored
return map_or_reserve_memory_aligned(size, alignment, -1 /* file_desc */);
return map_or_reserve_memory_aligned(size, alignment, -1/* file_desc */, mem_tag);
}
char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag) {
@ -4813,14 +4810,14 @@ jlong os::thread_cpu_time(Thread* thread, bool user_sys_cpu_time) {
}
void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
info_ptr->max_value = ALL_64_BITS; // the max value -- all 64 bits
info_ptr->max_value = all_bits_jlong; // the max value -- all 64 bits
info_ptr->may_skip_backward = false; // GetThreadTimes returns absolute time
info_ptr->may_skip_forward = false; // GetThreadTimes returns absolute time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
}
void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
info_ptr->max_value = ALL_64_BITS; // the max value -- all 64 bits
info_ptr->max_value = all_bits_jlong; // the max value -- all 64 bits
info_ptr->may_skip_backward = false; // GetThreadTimes returns absolute time
info_ptr->may_skip_forward = false; // GetThreadTimes returns absolute time
info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned
@ -5188,7 +5185,7 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
}
// Record virtual memory allocation
MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC);
MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC, mtNone);
DWORD bytes_read;
OVERLAPPED overlapped;

View File

@ -54,7 +54,7 @@ typedef BOOL (WINAPI *SetSecurityDescriptorControlFnPtr)(
static char* create_standard_memory(size_t size) {
// allocate an aligned chuck of memory
char* mapAddress = os::reserve_memory(size);
char* mapAddress = os::reserve_memory(size, mtInternal);
if (mapAddress == nullptr) {
return nullptr;

View File

@ -75,6 +75,14 @@
#define HWCAP_PACA (1 << 30)
#endif
#ifndef HWCAP_FPHP
#define HWCAP_FPHP (1<<9)
#endif
#ifndef HWCAP_ASIMDHP
#define HWCAP_ASIMDHP (1<<10)
#endif
#ifndef HWCAP2_SVE2
#define HWCAP2_SVE2 (1 << 1)
#endif
@ -119,6 +127,8 @@ void VM_Version::get_os_cpu_info() {
static_assert(CPU_SHA512 == HWCAP_SHA512, "Flag CPU_SHA512 must follow Linux HWCAP");
static_assert(CPU_SVE == HWCAP_SVE, "Flag CPU_SVE must follow Linux HWCAP");
static_assert(CPU_PACA == HWCAP_PACA, "Flag CPU_PACA must follow Linux HWCAP");
static_assert(CPU_FPHP == HWCAP_FPHP, "Flag CPU_FPHP must follow Linux HWCAP");
static_assert(CPU_ASIMDHP == HWCAP_ASIMDHP, "Flag CPU_ASIMDHP must follow Linux HWCAP");
_features = auxv & (
HWCAP_FP |
HWCAP_ASIMD |
@ -133,7 +143,9 @@ void VM_Version::get_os_cpu_info() {
HWCAP_SHA3 |
HWCAP_SHA512 |
HWCAP_SVE |
HWCAP_PACA);
HWCAP_PACA |
HWCAP_FPHP |
HWCAP_ASIMDHP);
if (auxv2 & HWCAP2_SVE2) _features |= CPU_SVE2;
if (auxv2 & HWCAP2_SVEBITPERM) _features |= CPU_SVEBITPERM;

View File

@ -129,6 +129,9 @@ void VM_Version::setup_cpu_available_features() {
snprintf(buf, sizeof(buf)/2, "%s ", uarch);
}
os::free((void*) uarch);
int features_offset = strnlen(buf, sizeof(buf));
strcat(buf, "rv64");
int i = 0;
while (_feature_list[i] != nullptr) {
@ -191,7 +194,9 @@ void VM_Version::setup_cpu_available_features() {
}
}
_features_string = os::strdup(buf);
_cpu_info_string = os::strdup(buf);
_features_string = _cpu_info_string + features_offset;
}
void VM_Version::os_aux_features() {

View File

@ -73,7 +73,7 @@ class Label;
*/
class Label {
private:
enum { PatchCacheSize = 4 debug_only( +4 ) };
enum { PatchCacheSize = 4 DEBUG_ONLY( +4 ) };
// _loc encodes both the binding state (via its sign)
// and the binding locator (via its value) of a label.

View File

@ -92,7 +92,7 @@ CodeBuffer::CodeBuffer(CodeBlob* blob) DEBUG_ONLY(: Scrubber(this, sizeof(*this)
// Provide code buffer with meaningful name
initialize_misc(blob->name());
initialize(blob->content_begin(), blob->content_size());
debug_only(verify_section_allocation();)
DEBUG_ONLY(verify_section_allocation();)
}
void CodeBuffer::initialize(csize_t code_size, csize_t locs_size) {
@ -120,7 +120,7 @@ void CodeBuffer::initialize(csize_t code_size, csize_t locs_size) {
_insts.initialize_locs(locs_size / sizeof(relocInfo));
}
debug_only(verify_section_allocation();)
DEBUG_ONLY(verify_section_allocation();)
}
@ -494,7 +494,7 @@ void CodeBuffer::compute_final_layout(CodeBuffer* dest) const {
prev_cs = cs;
}
debug_only(dest_cs->_start = nullptr); // defeat double-initialization assert
DEBUG_ONLY(dest_cs->_start = nullptr); // defeat double-initialization assert
dest_cs->initialize(buf+buf_offset, csize);
dest_cs->set_end(buf+buf_offset+csize);
assert(dest_cs->is_allocated(), "must always be allocated");
@ -505,7 +505,7 @@ void CodeBuffer::compute_final_layout(CodeBuffer* dest) const {
// Done calculating sections; did it come out to the right end?
assert(buf_offset == total_content_size(), "sanity");
debug_only(dest->verify_section_allocation();)
DEBUG_ONLY(dest->verify_section_allocation();)
}
// Append an oop reference that keeps the class alive.
@ -939,11 +939,11 @@ void CodeBuffer::expand(CodeSection* which_cs, csize_t amount) {
cb.set_blob(nullptr);
// Zap the old code buffer contents, to avoid mistakenly using them.
debug_only(Copy::fill_to_bytes(bxp->_total_start, bxp->_total_size,
DEBUG_ONLY(Copy::fill_to_bytes(bxp->_total_start, bxp->_total_size,
badCodeHeapFreeVal);)
// Make certain that the new sections are all snugly inside the new blob.
debug_only(verify_section_allocation();)
DEBUG_ONLY(verify_section_allocation();)
#ifndef PRODUCT
_decode_begin = nullptr; // sanity
@ -1042,6 +1042,9 @@ void CodeBuffer::shared_stub_to_interp_for(ciMethod* callee, csize_t call_offset
#ifndef PRODUCT
void CodeBuffer::block_comment(ptrdiff_t offset, const char* comment) {
if (insts()->scratch_emit()) {
return;
}
if (_collect_comments) {
const char* str = _asm_remarks.insert(offset, comment);
postcond(str != comment);
@ -1049,6 +1052,9 @@ void CodeBuffer::block_comment(ptrdiff_t offset, const char* comment) {
}
const char* CodeBuffer::code_string(const char* str) {
if (insts()->scratch_emit()) {
return str;
}
const char* tmp = _dbg_strings.insert(str);
postcond(tmp != str);
return tmp;

View File

@ -121,8 +121,8 @@ class CodeSection {
_locs_own = false;
_scratch_emit = false;
_skipped_instructions_size = 0;
debug_only(_index = -1);
debug_only(_outer = (CodeBuffer*)badAddress);
DEBUG_ONLY(_index = -1);
DEBUG_ONLY(_outer = (CodeBuffer*)badAddress);
}
void initialize_outer(CodeBuffer* outer, int8_t index) {
@ -535,7 +535,7 @@ class CodeBuffer: public StackObj DEBUG_ONLY(COMMA private Scrubber) {
assert(code_start != nullptr, "sanity");
initialize_misc("static buffer");
initialize(code_start, code_size);
debug_only(verify_section_allocation();)
DEBUG_ONLY(verify_section_allocation();)
}
// (2) CodeBuffer referring to pre-allocated CodeBlob.

View File

@ -109,19 +109,19 @@ class FrameMap : public CompilationResourceObj {
static Register cpu_rnr2reg (int rnr) {
assert(_init_done, "tables not initialized");
debug_only(cpu_range_check(rnr);)
DEBUG_ONLY(cpu_range_check(rnr);)
return _cpu_rnr2reg[rnr];
}
static int cpu_reg2rnr (Register reg) {
assert(_init_done, "tables not initialized");
debug_only(cpu_range_check(reg->encoding());)
DEBUG_ONLY(cpu_range_check(reg->encoding());)
return _cpu_reg2rnr[reg->encoding()];
}
static void map_register(int rnr, Register reg) {
debug_only(cpu_range_check(rnr);)
debug_only(cpu_range_check(reg->encoding());)
DEBUG_ONLY(cpu_range_check(rnr);)
DEBUG_ONLY(cpu_range_check(reg->encoding());)
_cpu_rnr2reg[rnr] = reg;
_cpu_reg2rnr[reg->encoding()] = rnr;
}

View File

@ -1363,7 +1363,7 @@ int Runtime1::move_klass_patching(JavaThread* current) {
//
// NOTE: we are still in Java
//
debug_only(NoHandleMark nhm;)
DEBUG_ONLY(NoHandleMark nhm;)
{
// Enter VM mode
ResetNoHandleMark rnhm;
@ -1380,7 +1380,7 @@ int Runtime1::move_mirror_patching(JavaThread* current) {
//
// NOTE: we are still in Java
//
debug_only(NoHandleMark nhm;)
DEBUG_ONLY(NoHandleMark nhm;)
{
// Enter VM mode
ResetNoHandleMark rnhm;
@ -1397,7 +1397,7 @@ int Runtime1::move_appendix_patching(JavaThread* current) {
//
// NOTE: we are still in Java
//
debug_only(NoHandleMark nhm;)
DEBUG_ONLY(NoHandleMark nhm;)
{
// Enter VM mode
ResetNoHandleMark rnhm;

View File

@ -25,6 +25,7 @@
#include "cds/aotClassLinker.hpp"
#include "cds/aotArtifactFinder.hpp"
#include "cds/aotClassInitializer.hpp"
#include "cds/aotReferenceObjSupport.hpp"
#include "cds/dumpTimeClassInfo.inline.hpp"
#include "cds/heapShared.hpp"
#include "cds/lambdaProxyClassDictionary.hpp"
@ -73,6 +74,7 @@ void AOTArtifactFinder::find_artifacts() {
// Note, if a class is not excluded, it does NOT mean it will be automatically included
// into the AOT cache -- that will be decided by the code below.
SystemDictionaryShared::finish_exclusion_checks();
AOTReferenceObjSupport::init_keep_alive_objs_table();
start_scanning_for_oops();

View File

@ -338,7 +338,8 @@ bool AOTClassInitializer::can_archive_initialized_mirror(InstanceKlass* ik) {
bool AOTClassInitializer::is_runtime_setup_required(InstanceKlass* ik) {
return ik == vmClasses::Class_klass() ||
ik == vmClasses::internal_Unsafe_klass() ||
ik == vmClasses::ConcurrentHashMap_klass();
ik == vmClasses::ConcurrentHashMap_klass() ||
ik == vmClasses::Reference_klass();
}
void AOTClassInitializer::call_runtime_setup(JavaThread* current, InstanceKlass* ik) {

View File

@ -0,0 +1,240 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "cds/aotReferenceObjSupport.hpp"
#include "cds/heapShared.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
#include "oops/oopHandle.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "utilities/resourceHash.hpp"
// Handling of java.lang.ref.Reference objects in the AOT cache
// ============================================================
//
// When AOTArtifactFinder finds an oop which is a instance of java.lang.ref.Reference:
//
// - We check if the oop is eligible to be stored in the AOT cache. If not, the AOT cache
// creation fails -- see AOTReferenceObjSupport::check_if_ref_obj()
//
// - Otherwise, we store the oop into the AOT cache, but we unconditionally reset its
// "next" and "discovered" fields to null. Otherwise, if AOTArtifactFinder follows these
// fields, it may found unrelated objects that we don't intend to cache.
//
// Eligibility
// ===========
//
// [1] A reference that does not require special clean up (i.e., Reference::queue == ReferenceQueue.NULL_QUEUE)
// is eligible.
//
// [2] A reference that REQUIRE specials clean up (i.e., Reference::queue != ReferenceQueue.NULL_QUEUE)
// is eligible ONLY if its referent is not null.
//
// As of this version, the only oops in group [2] that can be found by AOTArtifactFinder are
// the keys used by ReferencedKeyMap in the implementation of MethodType::internTable.
// stabilize_cached_reference_objects() ensures that all keys found by AOTArtifactFinder are eligible.
//
// The purpose of the error check in check_if_ref_obj() is to guard against changes in the JDK core
// libs that might introduce new types of oops in group [2] into the AOT cache.
//
// Reasons for the eligibility restrictions
// ========================================
//
// Reference handling is complex. In this version, we implement only enough functionality to support
// the use of Weak/Soft references used by java.lang.invoke.
//
// We intend to evolve the implementation in the future by
// -- implementing more assemblySetup() operations for other use cases, and/or
// -- relaxing the eligibility restrictions.
//
//
// null referents for group [1]
// ============================
//
// Any cached reference R1 of group [1] is allowed to have a null referent.
// This can happen in the following situations:
// (a) R1.clear() was called by Java code during the assembly phase.
// (b) The referent has been collected, and R1 is in the "pending" state.
// In case (b), the "next" and "discovered" fields of the cached copy of R1 will
// be set to null. During the production run:
// - It would appear to the Java program as if immediately during VM start-up, the referent
// was collected and ReferenceThread completed processing of R1.
// - It would appear to the GC as if immediately during VM start-up, the Java program called
// R1.clear().
#if INCLUDE_CDS_JAVA_HEAP
class KeepAliveObjectsTable : public ResourceHashtable<oop, bool,
36137, // prime number
AnyObj::C_HEAP,
mtClassShared,
HeapShared::oop_hash> {};
static KeepAliveObjectsTable* _keep_alive_objs_table;
static OopHandle _keep_alive_objs_array;
static OopHandle _null_queue;
bool AOTReferenceObjSupport::is_enabled() {
// For simplicity, AOTReferenceObjSupport is enabled only when dumping method handles.
// Otherwise we won't see Reference objects in the AOT cache. Let's be conservative now.
return CDSConfig::is_dumping_method_handles();
}
void AOTReferenceObjSupport::initialize(TRAPS) {
if (!AOTReferenceObjSupport::is_enabled()) {
return;
}
TempNewSymbol class_name = SymbolTable::new_symbol("java/lang/ref/ReferenceQueue");
Klass* k = SystemDictionary::resolve_or_fail(class_name, true, CHECK);
InstanceKlass* ik = InstanceKlass::cast(k);
ik->initialize(CHECK);
TempNewSymbol field_name = SymbolTable::new_symbol("NULL_QUEUE");
fieldDescriptor fd;
bool found = ik->find_local_field(field_name, vmSymbols::referencequeue_signature(), &fd);
precond(found);
precond(fd.is_static());
_null_queue = OopHandle(Universe::vm_global(), ik->java_mirror()->obj_field(fd.offset()));
}
// Ensure that all group [2] references found by AOTArtifactFinder are eligible.
void AOTReferenceObjSupport::stabilize_cached_reference_objects(TRAPS) {
if (AOTReferenceObjSupport::is_enabled()) {
// This assert means that the MethodType and MethodTypeForm tables won't be
// updated concurrently, so we can remove GC'ed entries ...
assert(CDSConfig::allow_only_single_java_thread(), "Required");
{
TempNewSymbol method_name = SymbolTable::new_symbol("assemblySetup");
JavaValue result(T_VOID);
JavaCalls::call_static(&result, vmClasses::MethodType_klass(),
method_name,
vmSymbols::void_method_signature(),
CHECK);
}
{
Symbol* cds_name = vmSymbols::jdk_internal_misc_CDS();
Klass* cds_klass = SystemDictionary::resolve_or_fail(cds_name, true /*throw error*/, CHECK);
TempNewSymbol method_name = SymbolTable::new_symbol("getKeepAliveObjects");
TempNewSymbol method_sig = SymbolTable::new_symbol("()[Ljava/lang/Object;");
JavaValue result(T_OBJECT);
JavaCalls::call_static(&result, cds_klass, method_name, method_sig, CHECK);
_keep_alive_objs_array = OopHandle(Universe::vm_global(), result.get_oop());
}
}
}
void AOTReferenceObjSupport::init_keep_alive_objs_table() {
assert_at_safepoint(); // _keep_alive_objs_table uses raw oops
oop a = _keep_alive_objs_array.resolve();
if (a != nullptr) {
precond(a->is_objArray());
precond(AOTReferenceObjSupport::is_enabled());
objArrayOop array = objArrayOop(a);
_keep_alive_objs_table = new (mtClass)KeepAliveObjectsTable();
for (int i = 0; i < array->length(); i++) {
oop obj = array->obj_at(i);
_keep_alive_objs_table->put(obj, true); // The array may have duplicated entries but that's OK.
}
}
}
// Returns true IFF obj is an instance of java.lang.ref.Reference. If so, perform extra eligibility checks.
bool AOTReferenceObjSupport::check_if_ref_obj(oop obj) {
// We have a single Java thread. This means java.lang.ref.Reference$ReferenceHandler thread
// is not running. Otherwise the checks for next/discovered may not work.
precond(CDSConfig::allow_only_single_java_thread());
assert_at_safepoint(); // _keep_alive_objs_table uses raw oops
if (obj->klass()->is_subclass_of(vmClasses::Reference_klass())) {
precond(AOTReferenceObjSupport::is_enabled());
precond(JavaClasses::is_supported_for_archiving(obj));
precond(_keep_alive_objs_table != nullptr);
// GC needs to know about this load, It will keep referent alive until the current safepoint ends.
oop referent = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(obj, java_lang_ref_Reference::referent_offset());
oop queue = obj->obj_field(java_lang_ref_Reference::queue_offset());
oop next = java_lang_ref_Reference::next(obj);
oop discovered = java_lang_ref_Reference::discovered(obj);
bool needs_special_cleanup = (queue != _null_queue.resolve());
// If you see the errors below, you probably modified the implementation of java.lang.invoke.
// Please check the comments at the top of this file.
if (needs_special_cleanup && (referent == nullptr || !_keep_alive_objs_table->contains(referent))) {
ResourceMark rm;
log_error(cds, heap)("Cannot archive reference object " PTR_FORMAT " of class %s",
p2i(obj), obj->klass()->external_name());
log_error(cds, heap)("referent = " PTR_FORMAT
", queue = " PTR_FORMAT
", next = " PTR_FORMAT
", discovered = " PTR_FORMAT,
p2i(referent), p2i(queue), p2i(next), p2i(discovered));
log_error(cds, heap)("This object requires special clean up as its queue is not ReferenceQueue::N" "ULL ("
PTR_FORMAT ")", p2i(_null_queue.resolve()));
log_error(cds, heap)("%s", (referent == nullptr) ?
"referent cannot be null" : "referent is not registered with CDS.keepAlive()");
HeapShared::debug_trace();
MetaspaceShared::unrecoverable_writing_error();
}
if (log_is_enabled(Info, cds, ref)) {
ResourceMark rm;
log_info(cds, ref)("Reference obj:"
" r=" PTR_FORMAT
" q=" PTR_FORMAT
" n=" PTR_FORMAT
" d=" PTR_FORMAT
" %s",
p2i(referent),
p2i(queue),
p2i(next),
p2i(discovered),
obj->klass()->external_name());
}
return true;
} else {
return false;
}
}
bool AOTReferenceObjSupport::skip_field(int field_offset) {
return (field_offset == java_lang_ref_Reference::next_offset() ||
field_offset == java_lang_ref_Reference::discovered_offset());
}
#endif // INCLUDE_CDS_JAVA_HEAP

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_CDS_AOTREFERENCEOBJSUPPORT_HPP
#define SHARE_CDS_AOTREFERENCEOBJSUPPORT_HPP
#include "memory/allStatic.hpp"
#include "oops/oopsHierarchy.hpp"
#include "utilities/exceptions.hpp"
// Support for ahead-of-time allocated instances of java.lang.ref.Reference
class AOTReferenceObjSupport : AllStatic {
public:
static void initialize(TRAPS);
static void stabilize_cached_reference_objects(TRAPS);
static void init_keep_alive_objs_table() NOT_CDS_JAVA_HEAP_RETURN;
static bool check_if_ref_obj(oop obj);
static bool skip_field(int field_offset);
static bool is_enabled();
};
#endif // SHARE_CDS_AOTREFERENCEOBJSUPPORT_HPP

View File

@ -309,7 +309,8 @@ address ArchiveBuilder::reserve_buffer() {
size_t buffer_size = LP64_ONLY(CompressedClassSpaceSize) NOT_LP64(256 * M);
ReservedSpace rs = MemoryReserver::reserve(buffer_size,
MetaspaceShared::core_region_alignment(),
os::vm_page_size());
os::vm_page_size(),
mtClassShared);
if (!rs.is_reserved()) {
log_error(cds)("Failed to reserve %zu bytes of output buffer.", buffer_size);
MetaspaceShared::unrecoverable_writing_error();
@ -1201,7 +1202,7 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
#undef _LOG_PREFIX
// Log information about a region, whose address at dump time is [base .. top). At
// runtime, this region will be mapped to requested_base. requested_base is 0 if this
// runtime, this region will be mapped to requested_base. requested_base is nullptr if this
// region will be mapped at os-selected addresses (such as the bitmap region), or will
// be accessed with os::read (the header).
//
@ -1210,7 +1211,11 @@ class ArchiveBuilder::CDSMapLogger : AllStatic {
static void log_region(const char* name, address base, address top, address requested_base) {
size_t size = top - base;
base = requested_base;
top = requested_base + size;
if (requested_base == nullptr) {
top = (address)size;
} else {
top = requested_base + size;
}
log_info(cds, map)("[%-18s " PTR_FORMAT " - " PTR_FORMAT " %9zu bytes]",
name, p2i(base), p2i(top), size);
}

View File

@ -22,6 +22,7 @@
*
*/
#include "cds/aotReferenceObjSupport.hpp"
#include "cds/archiveHeapWriter.hpp"
#include "cds/cdsConfig.hpp"
#include "cds/filemap.hpp"
@ -607,18 +608,27 @@ class ArchiveHeapWriter::EmbeddedOopRelocator: public BasicOopIterateClosure {
oop _src_obj;
address _buffered_obj;
CHeapBitMap* _oopmap;
bool _is_java_lang_ref;
public:
EmbeddedOopRelocator(oop src_obj, address buffered_obj, CHeapBitMap* oopmap) :
_src_obj(src_obj), _buffered_obj(buffered_obj), _oopmap(oopmap) {}
_src_obj(src_obj), _buffered_obj(buffered_obj), _oopmap(oopmap)
{
_is_java_lang_ref = AOTReferenceObjSupport::check_if_ref_obj(src_obj);
}
void do_oop(narrowOop *p) { EmbeddedOopRelocator::do_oop_work(p); }
void do_oop( oop *p) { EmbeddedOopRelocator::do_oop_work(p); }
private:
template <class T> void do_oop_work(T *p) {
size_t field_offset = pointer_delta(p, _src_obj, sizeof(char));
ArchiveHeapWriter::relocate_field_in_buffer<T>((T*)(_buffered_obj + field_offset), _oopmap);
int field_offset = pointer_delta_as_int((char*)p, cast_from_oop<char*>(_src_obj));
T* field_addr = (T*)(_buffered_obj + field_offset);
if (_is_java_lang_ref && AOTReferenceObjSupport::skip_field(field_offset)) {
// Do not copy these fields. Set them to null
*field_addr = (T)0x0;
} else {
ArchiveHeapWriter::relocate_field_in_buffer<T>(field_addr, _oopmap);
}
}
};

View File

@ -536,9 +536,6 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla
// run to another which resulting in non-determinstic CDS archives.
// Disable UseStringDeduplication while dumping CDS archive.
UseStringDeduplication = false;
// Don't use SoftReferences so that objects used by java.lang.invoke tables can be archived.
Arguments::PropertyList_add(new SystemProperty("java.lang.invoke.MethodHandleNatives.USE_SOFT_CACHE", "false", false));
}
// RecordDynamicDumpInfo is not compatible with ArchiveClassesAtExit

View File

@ -1066,10 +1066,10 @@ void FileMapInfo::close() {
*/
static char* map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec, MemTag mem_tag = mtNone) {
bool allow_exec, MemTag mem_tag) {
char* mem = os::map_memory(fd, file_name, file_offset, addr, bytes,
AlwaysPreTouch ? false : read_only,
allow_exec, mem_tag);
mem_tag, AlwaysPreTouch ? false : read_only,
allow_exec);
if (mem != nullptr && AlwaysPreTouch) {
os::pretouch_memory(mem, mem + bytes);
}
@ -1094,7 +1094,7 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() {
assert(WINDOWS_ONLY(false) NOT_WINDOWS(true), "Don't call on Windows");
// Replace old mapping with new one that is writable.
char *base = os::map_memory(_fd, _full_path, r->file_offset(),
addr, size, false /* !read_only */,
addr, size, mtNone, false /* !read_only */,
r->allow_exec());
close();
// These have to be errors because the shared region is now unmapped.
@ -1620,7 +1620,7 @@ bool FileMapInfo::map_heap_region_impl() {
} else {
base = map_memory(_fd, _full_path, r->file_offset(),
addr, _mapped_heap_memregion.byte_size(), r->read_only(),
r->allow_exec());
r->allow_exec(), mtJavaHeap);
if (base == nullptr || base != addr) {
dealloc_heap_region();
log_info(cds)("UseSharedSpaces: Unable to map at required address in java heap. "

View File

@ -25,6 +25,7 @@
#include "cds/aotArtifactFinder.hpp"
#include "cds/aotClassInitializer.hpp"
#include "cds/aotClassLocation.hpp"
#include "cds/aotReferenceObjSupport.hpp"
#include "cds/archiveBuilder.hpp"
#include "cds/archiveHeapLoader.hpp"
#include "cds/archiveHeapWriter.hpp"
@ -1363,34 +1364,37 @@ void HeapShared::clear_archived_roots_of(Klass* k) {
}
}
// Push all oops that are referenced by _referencing_obj onto the _stack.
class HeapShared::ReferentPusher: public BasicOopIterateClosure {
// Push all oop fields (or oop array elemenets in case of an objArray) in
// _referencing_obj onto the _stack.
class HeapShared::OopFieldPusher: public BasicOopIterateClosure {
PendingOopStack* _stack;
GrowableArray<oop> _found_oop_fields;
int _level;
bool _record_klasses_only;
KlassSubGraphInfo* _subgraph_info;
oop _referencing_obj;
bool _is_java_lang_ref;
public:
ReferentPusher(PendingOopStack* stack,
int level,
bool record_klasses_only,
KlassSubGraphInfo* subgraph_info,
oop orig) :
OopFieldPusher(PendingOopStack* stack,
int level,
bool record_klasses_only,
KlassSubGraphInfo* subgraph_info,
oop orig) :
_stack(stack),
_found_oop_fields(),
_level(level),
_record_klasses_only(record_klasses_only),
_subgraph_info(subgraph_info),
_referencing_obj(orig) {
_is_java_lang_ref = AOTReferenceObjSupport::check_if_ref_obj(orig);
}
void do_oop(narrowOop *p) { ReferentPusher::do_oop_work(p); }
void do_oop( oop *p) { ReferentPusher::do_oop_work(p); }
void do_oop(narrowOop *p) { OopFieldPusher::do_oop_work(p); }
void do_oop( oop *p) { OopFieldPusher::do_oop_work(p); }
~ReferentPusher() {
~OopFieldPusher() {
while (_found_oop_fields.length() > 0) {
// This produces the exact same traversal order as the previous version
// of ReferentPusher that recurses on the C stack -- a depth-first search,
// of OopFieldPusher that recurses on the C stack -- a depth-first search,
// walking the oop fields in _referencing_obj by ascending field offsets.
oop obj = _found_oop_fields.pop();
_stack->push(PendingOop(obj, _referencing_obj, _level + 1));
@ -1399,14 +1403,18 @@ class HeapShared::ReferentPusher: public BasicOopIterateClosure {
protected:
template <class T> void do_oop_work(T *p) {
oop obj = RawAccess<>::oop_load(p);
int field_offset = pointer_delta_as_int((char*)p, cast_from_oop<char*>(_referencing_obj));
oop obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(_referencing_obj, field_offset);
if (!CompressedOops::is_null(obj)) {
size_t field_delta = pointer_delta(p, _referencing_obj, sizeof(char));
if (_is_java_lang_ref && AOTReferenceObjSupport::skip_field(field_offset)) {
// Do not follow these fields. They will be cleared to null.
return;
}
if (!_record_klasses_only && log_is_enabled(Debug, cds, heap)) {
ResourceMark rm;
log_debug(cds, heap)("(%d) %s[%zu] ==> " PTR_FORMAT " size %zu %s", _level,
_referencing_obj->klass()->external_name(), field_delta,
log_debug(cds, heap)("(%d) %s[%d] ==> " PTR_FORMAT " size %zu %s", _level,
_referencing_obj->klass()->external_name(), field_offset,
p2i(obj), obj->size() * HeapWordSize, obj->klass()->external_name());
if (log_is_enabled(Trace, cds, heap)) {
LogTarget(Trace, cds, heap) log;
@ -1586,7 +1594,7 @@ bool HeapShared::walk_one_object(PendingOopStack* stack, int level, KlassSubGrap
// Find all the oops that are referenced by orig_obj, push them onto the stack
// so we can work on them next.
ResourceMark rm;
ReferentPusher pusher(stack, level, record_klasses_only, subgraph_info, orig_obj);
OopFieldPusher pusher(stack, level, record_klasses_only, subgraph_info, orig_obj);
orig_obj->oop_iterate(&pusher);
}
@ -1613,7 +1621,7 @@ bool HeapShared::walk_one_object(PendingOopStack* stack, int level, KlassSubGrap
// - No java.lang.Class instance (java mirror) can be included inside
// an archived sub-graph. Mirror can only be the sub-graph entry object.
//
// The Java heap object sub-graph archiving process (see ReferentPusher):
// The Java heap object sub-graph archiving process (see OopFieldPusher):
//
// 1) Java object sub-graph archiving starts from a given static field
// within a Class instance (java mirror). If the static field is a

View File

@ -164,8 +164,8 @@ private:
static void count_allocation(size_t size);
static void print_stats();
static void debug_trace();
public:
static void debug_trace();
static unsigned oop_hash(oop const& p);
static unsigned string_oop_hash(oop const& string) {
return java_lang_String::hash_code(string);
@ -357,7 +357,7 @@ private:
int level() const { return _level; }
};
class ReferentPusher;
class OopFieldPusher;
using PendingOopStack = GrowableArrayCHeap<PendingOop, mtClassShared>;
static PendingOop _object_being_archived;

View File

@ -28,6 +28,7 @@
#include "cds/aotClassLocation.hpp"
#include "cds/aotConstantPoolResolver.hpp"
#include "cds/aotLinkedClassBulkLoader.hpp"
#include "cds/aotReferenceObjSupport.hpp"
#include "cds/archiveBuilder.hpp"
#include "cds/archiveHeapLoader.hpp"
#include "cds/archiveHeapWriter.hpp"
@ -962,22 +963,14 @@ void MetaspaceShared::preload_and_dump_impl(StaticArchiveBuilder& builder, TRAPS
#if INCLUDE_CDS_JAVA_HEAP
if (CDSConfig::is_dumping_heap()) {
ArchiveHeapWriter::init();
if (CDSConfig::is_dumping_full_module_graph()) {
ClassLoaderDataShared::ensure_module_entry_tables_exist();
HeapShared::reset_archived_object_states(CHECK);
}
if (CDSConfig::is_dumping_method_handles()) {
// This assert means that the MethodType and MethodTypeForm tables won't be
// updated concurrently when we are saving their contents into a side table.
assert(CDSConfig::allow_only_single_java_thread(), "Required");
JavaValue result(T_VOID);
JavaCalls::call_static(&result, vmClasses::MethodType_klass(),
vmSymbols::createArchivedObjects(),
vmSymbols::void_method_signature(),
CHECK);
}
AOTReferenceObjSupport::initialize(CHECK);
AOTReferenceObjSupport::stabilize_cached_reference_objects(CHECK);
if (CDSConfig::is_initing_classes_at_dump_time()) {
// java.lang.Class::reflectionFactory cannot be archived yet. We set this field
@ -1345,7 +1338,7 @@ MapArchiveResult MetaspaceShared::map_archives(FileMapInfo* static_mapinfo, File
if (prot_zone_size > 0) {
assert(prot_zone_size >= os::vm_allocation_granularity(), "must be"); // not just page size!
char* p = os::attempt_reserve_memory_at(mapped_base_address, prot_zone_size,
false, MemTag::mtClassShared);
mtClassShared);
assert(p == mapped_base_address || p == nullptr, "must be");
if (p == nullptr) {
log_debug(cds)("Failed to re-reserve protection zone");
@ -1537,7 +1530,8 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
archive_space_rs = MemoryReserver::reserve((char*)base_address,
archive_space_size,
archive_space_alignment,
os::vm_page_size());
os::vm_page_size(),
mtNone);
if (archive_space_rs.is_reserved()) {
assert(base_address == nullptr ||
(address)archive_space_rs.base() == base_address, "Sanity");
@ -1605,11 +1599,13 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
archive_space_rs = MemoryReserver::reserve((char*)base_address,
archive_space_size,
archive_space_alignment,
os::vm_page_size());
os::vm_page_size(),
mtNone);
class_space_rs = MemoryReserver::reserve((char*)ccs_base,
class_space_size,
class_space_alignment,
os::vm_page_size());
os::vm_page_size(),
mtNone);
}
if (!archive_space_rs.is_reserved() || !class_space_rs.is_reserved()) {
release_reserved_spaces(total_space_rs, archive_space_rs, class_space_rs);
@ -1622,7 +1618,8 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
total_space_rs = MemoryReserver::reserve((char*) base_address,
total_range_size,
base_address_alignment,
os::vm_page_size());
os::vm_page_size(),
mtNone);
} else {
// We did not manage to reserve at the preferred address, or were instructed to relocate. In that
// case we reserve wherever possible, but the start address needs to be encodable as narrow Klass

View File

@ -138,3 +138,9 @@ ciKlass* ciInstance::java_lang_Class_klass() {
assert(java_lang_Class::as_Klass(get_oop()) != nullptr, "klass is null");
return CURRENT_ENV->get_metadata(java_lang_Class::as_Klass(get_oop()))->as_klass();
}
char* ciInstance::java_lang_String_str(char* buf, size_t buflen) {
VM_ENTRY_MARK;
assert(get_oop()->is_a(vmClasses::String_klass()), "not a String");
return java_lang_String::as_utf8_string(get_oop(), buf, buflen);
}

Some files were not shown because too many files have changed in this diff Show More