mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-11 00:13:09 +00:00
Merge remote-tracking branch 'upstream_jdk/master' into JDK-8372246
This commit is contained in:
commit
377b81b5ba
1
.gitignore
vendored
1
.gitignore
vendored
@ -16,6 +16,7 @@ NashornProfile.txt
|
||||
**/JTreport/**
|
||||
**/JTwork/**
|
||||
/src/utils/LogCompilation/target/
|
||||
/src/utils/LogCompilation/logc.jar
|
||||
/.project/
|
||||
/.settings/
|
||||
/compile_commands.json
|
||||
|
||||
@ -965,9 +965,8 @@ rather than <code>NULL</code>. See the paper for reasons to avoid
|
||||
<code>NULL</code>.</p>
|
||||
<p>Don't use (constant expression or literal) 0 for pointers. Note that
|
||||
C++14 removed non-literal 0 constants from <em>null pointer
|
||||
constants</em>, though some compilers continue to treat them as such.
|
||||
For historical reasons there may be lingering uses of 0 as a
|
||||
pointer.</p>
|
||||
constants</em>, though some compilers continue to treat them as
|
||||
such.</p>
|
||||
<h3 id="atomic"><atomic></h3>
|
||||
<p>Do not use facilities provided by the <code><atomic></code>
|
||||
header (<a
|
||||
|
||||
@ -884,8 +884,7 @@ rather than `NULL`. See the paper for reasons to avoid `NULL`.
|
||||
|
||||
Don't use (constant expression or literal) 0 for pointers. Note that C++14
|
||||
removed non-literal 0 constants from _null pointer constants_, though some
|
||||
compilers continue to treat them as such. For historical reasons there may be
|
||||
lingering uses of 0 as a pointer.
|
||||
compilers continue to treat them as such.
|
||||
|
||||
### <atomic>
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2012, 2026, 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
|
||||
@ -66,7 +66,8 @@ CALLED_SPEC_TARGETS := $(filter-out $(ALL_GLOBAL_TARGETS), $(CALLED_TARGETS))
|
||||
ifeq ($(CALLED_SPEC_TARGETS), )
|
||||
SKIP_SPEC := true
|
||||
endif
|
||||
ifeq ($(findstring p, $(MAKEFLAGS))$(findstring q, $(MAKEFLAGS)), pq)
|
||||
MFLAGS_SINGLE := $(filter-out --%, $(MFLAGS))
|
||||
ifeq ($(findstring p, $(MFLAGS_SINGLE))$(findstring q, $(MFLAGS_SINGLE)), pq)
|
||||
SKIP_SPEC := true
|
||||
endif
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, 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
|
||||
@ -209,8 +209,12 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS],
|
||||
BUILD_CC_DISABLE_WARNING_PREFIX="-wd"
|
||||
CFLAGS_WARNINGS_ARE_ERRORS="-WX"
|
||||
|
||||
WARNINGS_ENABLE_ALL="-W3"
|
||||
WARNINGS_ENABLE_ALL_NORMAL="-W3"
|
||||
WARNINGS_ENABLE_ADDITIONAL=""
|
||||
WARNINGS_ENABLE_ADDITIONAL_CXX=""
|
||||
WARNINGS_ENABLE_ADDITIONAL_JVM=""
|
||||
DISABLED_WARNINGS="4800 5105"
|
||||
CFLAGS_CONVERSION_WARNINGS=
|
||||
;;
|
||||
|
||||
gcc)
|
||||
@ -218,14 +222,16 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS],
|
||||
BUILD_CC_DISABLE_WARNING_PREFIX="-Wno-"
|
||||
CFLAGS_WARNINGS_ARE_ERRORS="-Werror"
|
||||
|
||||
WARNINGS_ENABLE_ALL_NORMAL="-Wall -Wextra"
|
||||
|
||||
# Additional warnings that are not activated by -Wall and -Wextra
|
||||
WARNINGS_ENABLE_ADDITIONAL="-Winvalid-pch -Wpointer-arith -Wreturn-type \
|
||||
WARNINGS_ENABLE_ADDITIONAL="-Wformat=2 \
|
||||
-Winvalid-pch -Wpointer-arith -Wreturn-type \
|
||||
-Wsign-compare -Wtrampolines -Wtype-limits -Wundef -Wuninitialized \
|
||||
-Wunused-const-variable=1 -Wunused-function -Wunused-result \
|
||||
-Wunused-value"
|
||||
WARNINGS_ENABLE_ADDITIONAL_CXX="-Woverloaded-virtual -Wreorder"
|
||||
WARNINGS_ENABLE_ALL_CFLAGS="-Wall -Wextra -Wformat=2 $WARNINGS_ENABLE_ADDITIONAL"
|
||||
WARNINGS_ENABLE_ALL_CXXFLAGS="$WARNINGS_ENABLE_ALL_CFLAGS $WARNINGS_ENABLE_ADDITIONAL_CXX"
|
||||
WARNINGS_ENABLE_ADDITIONAL_JVM="-Wzero-as-null-pointer-constant"
|
||||
|
||||
# These warnings will never be turned on, since they generate too many
|
||||
# false positives.
|
||||
@ -234,6 +240,7 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS],
|
||||
if test "x$OPENJDK_TARGET_CPU_ARCH" = "xppc"; then
|
||||
DISABLED_WARNINGS="$DISABLED_WARNINGS psabi"
|
||||
fi
|
||||
CFLAGS_CONVERSION_WARNINGS="-Wconversion -Wno-float-conversion"
|
||||
;;
|
||||
|
||||
clang)
|
||||
@ -241,22 +248,32 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS],
|
||||
BUILD_CC_DISABLE_WARNING_PREFIX="-Wno-"
|
||||
CFLAGS_WARNINGS_ARE_ERRORS="-Werror"
|
||||
|
||||
WARNINGS_ENABLE_ALL_NORMAL="-Wall -Wextra"
|
||||
|
||||
# Additional warnings that are not activated by -Wall and -Wextra
|
||||
WARNINGS_ENABLE_ADDITIONAL="-Wpointer-arith -Wsign-compare -Wreorder \
|
||||
WARNINGS_ENABLE_ADDITIONAL="-Wformat=2 \
|
||||
-Wpointer-arith -Wsign-compare -Wreorder \
|
||||
-Wunused-function -Wundef -Wunused-value -Woverloaded-virtual"
|
||||
WARNINGS_ENABLE_ALL="-Wall -Wextra -Wformat=2 $WARNINGS_ENABLE_ADDITIONAL"
|
||||
WARNINGS_ENABLE_ADDITIONAL_CXX=""
|
||||
WARNINGS_ENABLE_ADDITIONAL_JVM="-Wzero-as-null-pointer-constant"
|
||||
|
||||
# These warnings will never be turned on, since they generate too many
|
||||
# false positives.
|
||||
DISABLED_WARNINGS="unknown-warning-option unused-parameter"
|
||||
CFLAGS_CONVERSION_WARNINGS="-Wimplicit-int-conversion"
|
||||
;;
|
||||
esac
|
||||
WARNINGS_ENABLE_ALL="$WARNINGS_ENABLE_ALL_NORMAL $WARNINGS_ENABLE_ADDITIONAL"
|
||||
WARNINGS_ENABLE_ALL_CXX="$WARNINGS_ENABLE_ALL $WARNINGS_ENABLE_ADDITIONAL_CXX"
|
||||
WARNINGS_ENABLE_ALL_JVM="$WARNINGS_ENABLE_ALL_CXX $WARNINGS_ENABLE_ADDITIONAL_JVM"
|
||||
|
||||
AC_SUBST(DISABLE_WARNING_PREFIX)
|
||||
AC_SUBST(BUILD_CC_DISABLE_WARNING_PREFIX)
|
||||
AC_SUBST(CFLAGS_WARNINGS_ARE_ERRORS)
|
||||
AC_SUBST(DISABLED_WARNINGS)
|
||||
AC_SUBST(DISABLED_WARNINGS_C)
|
||||
AC_SUBST(DISABLED_WARNINGS_CXX)
|
||||
AC_SUBST(CFLAGS_CONVERSION_WARNINGS)
|
||||
])
|
||||
|
||||
AC_DEFUN([FLAGS_SETUP_QUALITY_CHECKS],
|
||||
@ -604,19 +621,9 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
|
||||
ADLC_LANGSTD_CXXFLAGS="$LANGSTD_CXXFLAGS"
|
||||
|
||||
# CFLAGS WARNINGS STUFF
|
||||
# Set JVM_CFLAGS warning handling
|
||||
if test "x$TOOLCHAIN_TYPE" = xgcc; then
|
||||
WARNING_CFLAGS_JDK_CONLY="$WARNINGS_ENABLE_ALL_CFLAGS"
|
||||
WARNING_CFLAGS_JDK_CXXONLY="$WARNINGS_ENABLE_ALL_CXXFLAGS"
|
||||
WARNING_CFLAGS_JVM="$WARNINGS_ENABLE_ALL_CXXFLAGS"
|
||||
|
||||
elif test "x$TOOLCHAIN_TYPE" = xclang; then
|
||||
WARNING_CFLAGS="$WARNINGS_ENABLE_ALL"
|
||||
|
||||
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
|
||||
WARNING_CFLAGS="$WARNINGS_ENABLE_ALL"
|
||||
|
||||
fi
|
||||
WARNING_CFLAGS_JDK_CONLY="$WARNINGS_ENABLE_ALL"
|
||||
WARNING_CFLAGS_JDK_CXXONLY="$WARNINGS_ENABLE_ALL_CXX"
|
||||
WARNING_CFLAGS_JVM="$WARNINGS_ENABLE_ALL_JVM"
|
||||
|
||||
# Set some additional per-OS defines.
|
||||
|
||||
@ -878,12 +885,12 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
|
||||
CFLAGS_JVM_COMMON="$ALWAYS_CFLAGS_JVM $ALWAYS_DEFINES_JVM \
|
||||
$TOOLCHAIN_CFLAGS_JVM ${$1_TOOLCHAIN_CFLAGS_JVM} \
|
||||
$OS_CFLAGS $OS_CFLAGS_JVM $CFLAGS_OS_DEF_JVM $DEBUG_CFLAGS_JVM \
|
||||
$WARNING_CFLAGS $WARNING_CFLAGS_JVM $JVM_PICFLAG $FILE_MACRO_CFLAGS \
|
||||
$WARNING_CFLAGS_JVM $JVM_PICFLAG $FILE_MACRO_CFLAGS \
|
||||
$REPRODUCIBLE_CFLAGS $BRANCH_PROTECTION_CFLAGS"
|
||||
|
||||
CFLAGS_JDK_COMMON="$ALWAYS_DEFINES_JDK $TOOLCHAIN_CFLAGS_JDK \
|
||||
$OS_CFLAGS $CFLAGS_OS_DEF_JDK $DEBUG_CFLAGS_JDK $DEBUG_OPTIONS_FLAGS_JDK \
|
||||
$WARNING_CFLAGS $WARNING_CFLAGS_JDK $DEBUG_SYMBOLS_CFLAGS_JDK \
|
||||
$DEBUG_SYMBOLS_CFLAGS_JDK \
|
||||
$FILE_MACRO_CFLAGS $REPRODUCIBLE_CFLAGS $BRANCH_PROTECTION_CFLAGS"
|
||||
|
||||
# Use ${$2EXTRA_CFLAGS} to block EXTRA_CFLAGS to be added to build flags.
|
||||
|
||||
@ -267,8 +267,8 @@ AC_DEFUN_ONCE([LIB_SETUP_ZLIB],
|
||||
LIBZ_LIBS=""
|
||||
if test "x$USE_EXTERNAL_LIBZ" = "xfalse"; then
|
||||
LIBZ_CFLAGS="$LIBZ_CFLAGS -I$TOPDIR/src/java.base/share/native/libzip/zlib"
|
||||
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
||||
LIBZ_CFLAGS="$LIBZ_CFLAGS -DHAVE_UNISTD_H"
|
||||
if test "x$OPENJDK_TARGET_OS" = xmacosx -o "x$OPENJDK_TARGET_OS" = xaix -o "x$OPENJDK_TARGET_OS" = xlinux; then
|
||||
LIBZ_CFLAGS="$LIBZ_CFLAGS -DHAVE_UNISTD_H=1 -DHAVE_STDARG_H=1"
|
||||
fi
|
||||
else
|
||||
LIBZ_LIBS="-lz"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,7 +28,7 @@
|
||||
################################################################################
|
||||
|
||||
# Minimum supported versions
|
||||
JTREG_MINIMUM_VERSION=8.1
|
||||
JTREG_MINIMUM_VERSION=8.2.1
|
||||
GTEST_MINIMUM_VERSION=1.14.0
|
||||
|
||||
################################################################################
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, 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
|
||||
@ -311,6 +311,12 @@ AC_DEFUN([PLATFORM_EXTRACT_TARGET_AND_BUILD],
|
||||
else
|
||||
OPENJDK_BUILD_OS_ENV="$VAR_OS"
|
||||
fi
|
||||
# Special handling for MSYS2 that reports a Cygwin triplet as the default host triplet.
|
||||
case `uname` in
|
||||
MSYS*)
|
||||
OPENJDK_BUILD_OS_ENV=windows.msys2
|
||||
;;
|
||||
esac
|
||||
OPENJDK_BUILD_CPU="$VAR_CPU"
|
||||
OPENJDK_BUILD_CPU_ARCH="$VAR_CPU_ARCH"
|
||||
OPENJDK_BUILD_CPU_BITS="$VAR_CPU_BITS"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, 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
|
||||
@ -529,6 +529,7 @@ CFLAGS_WARNINGS_ARE_ERRORS := @CFLAGS_WARNINGS_ARE_ERRORS@
|
||||
DISABLED_WARNINGS := @DISABLED_WARNINGS@
|
||||
DISABLED_WARNINGS_C := @DISABLED_WARNINGS_C@
|
||||
DISABLED_WARNINGS_CXX := @DISABLED_WARNINGS_CXX@
|
||||
CFLAGS_CONVERSION_WARNINGS := @CFLAGS_CONVERSION_WARNINGS@
|
||||
|
||||
# A global flag (true or false) determining if native warnings are considered errors.
|
||||
WARNINGS_AS_ERRORS := @WARNINGS_AS_ERRORS@
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2026, 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
|
||||
@ -141,6 +141,66 @@ endef
|
||||
# Make sure logging is setup for everyone that includes MakeBase.gmk.
|
||||
$(eval $(call SetupLogging))
|
||||
|
||||
################################################################################
|
||||
# Make does not have support for VARARGS, you can send variable amount
|
||||
# of arguments, but you can for example not append a list at the end.
|
||||
# It is therefore not easy to send the elements of a list of unknown
|
||||
# length as argument to a function. This can somewhat be worked around
|
||||
# by sending a list as an argument, and then interpreting each element
|
||||
# of the list as an argument to the function. However, Make is
|
||||
# limited, and using this method you can not easily send spaces.
|
||||
#
|
||||
# We need to quote strings for two reasons when sending them as
|
||||
# "variable append packs":
|
||||
#
|
||||
# 1) variable appends can include spaces, and those must be preserved
|
||||
# 2) variable appends can include assignment strings ":=", and those
|
||||
# must be quoted to a form so that we can recognise the "append pack".
|
||||
# We recognise an "append pack" by its lack of strict assignment ":="
|
||||
|
||||
Q := $(HASH)
|
||||
SpaceQ := $(Q)s
|
||||
AppendQ := $(Q)+
|
||||
AssignQ := $(Q)a
|
||||
QQ := $(Q)$(Q)
|
||||
|
||||
# $(call Quote,echo "#trala:=") -> echo#s"##trala#a"
|
||||
Quote = $(subst :=,$(AssignQ),$(subst $(SPACE),$(SpaceQ),$(subst $(Q),$(QQ),$1)))
|
||||
|
||||
# $(call Unquote,echo#s"##trala#a") -> echo "#trala:="
|
||||
Unquote = $(subst $(QQ),$(Q),$(subst $(SpaceQ),$(SPACE),$(subst $(AssignQ),:=,$1)))
|
||||
|
||||
# $(call QuoteAppend,name,some value) -> name#+some#svalue
|
||||
# $(call QuoteAppend,bad+=name,some value) -> error
|
||||
QuoteAppend = $(if $(findstring +=,$1),$(error you can not have += in a variable name: "$1"),$(call Quote,$1)$(AppendQ)$(call Quote,$2))
|
||||
|
||||
# $(call UnquoteAppendIndex,name#+some#svalue,1) -> name
|
||||
# $(call UnquoteAppendIndex,name#+some#svalue,2) -> some value
|
||||
UnquoteAppendIndex = $(call Unquote,$(word $2,$(subst $(AppendQ),$(SPACE),$1)))
|
||||
|
||||
# $(call FilterFiles,dir,%.cpp) -> file1.cpp file2.cpp (without path)
|
||||
FilterFiles = $(filter $2,$(notdir $(call FindFiles,$1)))
|
||||
|
||||
# $(call Unpack module_,file1.cpp_CXXFLAGS#+-Wconversion file2.cpp_CXXFLAGS#+-Wconversion) -> module_file1.cpp_CXXFLAGS += -Wconversion
|
||||
# module_file2.cpp_CXXFLAGS += -Wconversion
|
||||
Unpack = $(foreach pair,$2,$1$(call UnquoteAppendIndex,$(pair),1) += $(call UnquoteAppendIndex,$(pair),2)$(NEWLINE))
|
||||
|
||||
# This macro takes four arguments:
|
||||
# $1: directory where to find files (striped), example: $(TOPDIR)/src/hotspot/share/gc/g1
|
||||
# $2: filter to match what to keep (striped), example: g1Concurrent%.cpp
|
||||
# $3: what flags to override (striped), example: _CXXFLAGS
|
||||
# $4: what value to append to the flag (striped), example: $(CFLAGS_CONVERSION_WARNINGS)
|
||||
#
|
||||
# The result will be a quoted string that can be unpacked to a list of
|
||||
# variable appendings (see macro Unpack above). You do not need to take
|
||||
# care of unpacking, it is done in NamedParamsMacroTemplate.
|
||||
#
|
||||
# This feature should only be used for warnings that we want to
|
||||
# incrementally add to the rest of the code base.
|
||||
#
|
||||
# $(call ExtendFlags,dir,%.cpp,_CXXFLAGS,-Wconversion) -> file1.cpp_CXXFLAGS#+-Wconversion file2.cpp_CXXFLAGS#+-Wconversion
|
||||
ExtendFlags = $(foreach file,$(call FilterFiles,$(strip $1),$(strip $2)),$(call QuoteAppend,$(file)$(strip $3),$(strip $4)))
|
||||
|
||||
################################################################################
|
||||
|
||||
MAX_PARAMS := 96
|
||||
@ -166,7 +226,10 @@ define NamedParamsMacroTemplate
|
||||
Too many named arguments to macro, please update MAX_PARAMS in MakeBase.gmk))
|
||||
# Iterate over 2 3 4... and evaluate the named parameters with $1_ as prefix
|
||||
$(foreach i, $(PARAM_SEQUENCE), $(if $(strip $($i)), \
|
||||
$(strip $1)_$(strip $(call EscapeHash, $(call DoubleDollar, $($i))))$(NEWLINE)))
|
||||
$(if $(findstring :=,$($i)), \
|
||||
$(strip $1)_$(strip $(call EscapeHash, $(call DoubleDollar, $($i))))$(NEWLINE), \
|
||||
$(call Unpack,$(strip $1)_,$($i)))))
|
||||
|
||||
# Debug print all named parameter names and values
|
||||
$(if $(findstring $(LOG_LEVEL), trace), \
|
||||
$(info $0 $(strip $1) $(foreach i, $(PARAM_SEQUENCE), \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,7 +26,7 @@
|
||||
# Versions and download locations for dependencies used by GitHub Actions (GHA)
|
||||
|
||||
GTEST_VERSION=1.14.0
|
||||
JTREG_VERSION=8.1+1
|
||||
JTREG_VERSION=8.2.1+1
|
||||
|
||||
LINUX_X64_BOOT_JDK_EXT=tar.gz
|
||||
LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_linux-x64_bin.tar.gz
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2026, 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
|
||||
@ -1174,9 +1174,9 @@ var getJibProfilesDependencies = function (input, common) {
|
||||
jtreg: {
|
||||
server: "jpg",
|
||||
product: "jtreg",
|
||||
version: "8.1",
|
||||
version: "8.2.1",
|
||||
build_number: "1",
|
||||
file: "bundles/jtreg-8.1+1.zip",
|
||||
file: "bundles/jtreg-8.2.1+1.zip",
|
||||
environment_name: "JT_HOME",
|
||||
environment_path: input.get("jtreg", "home_path") + "/bin",
|
||||
configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"),
|
||||
|
||||
@ -78,7 +78,7 @@ else ifeq ($(BASE_OS), Fedora)
|
||||
endif
|
||||
BASE_URL := http://fedora.riscv.rocks/repos-dist/f$(BASE_OS_VERSION)/latest/$(ARCH)/Packages/
|
||||
else
|
||||
LATEST_ARCHIVED_OS_VERSION := 36
|
||||
LATEST_ARCHIVED_OS_VERSION := 41
|
||||
ifeq ($(filter aarch64 armhfp x86_64, $(ARCH)), )
|
||||
FEDORA_TYPE := fedora-secondary
|
||||
else
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2013, 2026, 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
|
||||
@ -105,7 +105,7 @@ DISABLED_WARNINGS_gcc := array-bounds comment delete-non-virtual-dtor \
|
||||
DISABLED_WARNINGS_clang := delete-non-abstract-non-virtual-dtor \
|
||||
invalid-offsetof missing-braces \
|
||||
sometimes-uninitialized unknown-pragmas unused-but-set-variable \
|
||||
unused-function unused-local-typedef unused-private-field unused-variable
|
||||
unused-local-typedef unused-private-field unused-variable
|
||||
|
||||
ifneq ($(DEBUG_LEVEL), release)
|
||||
# Assert macro gives warning
|
||||
@ -190,6 +190,8 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \
|
||||
abstract_vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
|
||||
arguments.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
|
||||
whitebox.cpp_CXXFLAGS := $(CFLAGS_SHIP_DEBUGINFO), \
|
||||
$(call ExtendFlags, $(TOPDIR)/src/hotspot/share/gc/g1, \
|
||||
g1Numa.cpp, _CXXFLAGS, $(CFLAGS_CONVERSION_WARNINGS)), \
|
||||
DISABLED_WARNINGS_gcc := $(DISABLED_WARNINGS_gcc), \
|
||||
DISABLED_WARNINGS_gcc_ad_$(HOTSPOT_TARGET_CPU_ARCH).cpp := nonnull, \
|
||||
DISABLED_WARNINGS_gcc_bytecodeInterpreter.cpp := unused-label, \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026, 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
|
||||
@ -293,8 +293,10 @@ public class CLDRConverter {
|
||||
bundleGenerator = new ResourceBundleGenerator();
|
||||
|
||||
// Parse data independent of locales
|
||||
parseSupplemental();
|
||||
// parseBCP47() must precede parseSupplemental(). The latter depends
|
||||
// on IANA alias map, which is produced by the former.
|
||||
parseBCP47();
|
||||
parseSupplemental();
|
||||
|
||||
// rules maps
|
||||
pluralRules = generateRules(handlerPlurals);
|
||||
@ -536,6 +538,12 @@ public class CLDRConverter {
|
||||
|
||||
// canonical tz name map
|
||||
// alias -> primary
|
||||
//
|
||||
// Note that CLDR meta zones do not necessarily align with IANA's
|
||||
// current time zone identifiers. For example, the CLDR "India"
|
||||
// meta zone maps to "Asia/Calcutta", whereas IANA now uses
|
||||
// "Asia/Kolkata" for the zone. Accordingly, "canonical" here is
|
||||
// defined in terms of CLDR's zone mappings.
|
||||
handlerTimeZone.getData().forEach((k, v) -> {
|
||||
String[] ids = ((String)v).split("\\s");
|
||||
for (int i = 1; i < ids.length; i++) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,6 +27,9 @@ package build.tools.cldrconverter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
@ -40,6 +43,10 @@ import org.xml.sax.SAXException;
|
||||
class TimeZoneParseHandler extends AbstractLDMLHandler<Object> {
|
||||
private static final String PREF_PREFIX = "preferred:";
|
||||
|
||||
// CLDR aliases to IANA ids map. The initial capacity is estimated
|
||||
// from the number of aliases in timezone.xml as of CLDR v48
|
||||
private final Map<String, String> ianaAliasMap = HashMap.newHashMap(32);
|
||||
|
||||
@Override
|
||||
public InputSource resolveEntity(String publicID, String systemID) throws IOException, SAXException {
|
||||
// avoid HTTP traffic to unicode.org
|
||||
@ -61,7 +68,16 @@ class TimeZoneParseHandler extends AbstractLDMLHandler<Object> {
|
||||
put(attributes.getValue("name"), PREF_PREFIX + preferred);
|
||||
}
|
||||
} else {
|
||||
put(attributes.getValue("name"), attributes.getValue("alias"));
|
||||
var alias = attributes.getValue("alias");
|
||||
var iana = attributes.getValue("iana");
|
||||
if (iana != null) {
|
||||
for (var a : alias.split("\\s+")) {
|
||||
if (!a.equals(iana)) {
|
||||
ianaAliasMap.put(a, iana);
|
||||
}
|
||||
}
|
||||
}
|
||||
put(attributes.getValue("name"), alias);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -80,4 +96,8 @@ class TimeZoneParseHandler extends AbstractLDMLHandler<Object> {
|
||||
.forEach(e -> map.put(e.getKey(),
|
||||
map.get(e.getValue().toString().substring(PREF_PREFIX.length()))));
|
||||
}
|
||||
|
||||
Map<String, String> getIanaAliasMap() {
|
||||
return ianaAliasMap;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -56,6 +56,7 @@ class WinZonesParseHandler extends AbstractLDMLHandler<Object> {
|
||||
String zoneName = attributes.getValue("other");
|
||||
String territory = attributes.getValue("territory");
|
||||
String javatz = attributes.getValue("type").replaceFirst("\\s.*", "");
|
||||
javatz = CLDRConverter.handlerTimeZone.getIanaAliasMap().getOrDefault(javatz, javatz);
|
||||
put(zoneName + ":" + territory, javatz);
|
||||
pushIgnoredContainer(qName);
|
||||
break;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2014, 2026, 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
|
||||
@ -172,6 +172,10 @@ ifeq ($(USE_EXTERNAL_LIBZ), true)
|
||||
LEGAL_EXCLUDES += zlib.md
|
||||
endif
|
||||
|
||||
ifneq ($(TOOLCHAIN_TYPE), gcc)
|
||||
LEGAL_EXCLUDES += gcc.md
|
||||
endif
|
||||
|
||||
$(eval $(call SetupCopyLegalFiles, COPY_LEGAL, \
|
||||
EXCLUDES := $(LEGAL_EXCLUDES), \
|
||||
))
|
||||
|
||||
@ -3403,11 +3403,13 @@ encode %{
|
||||
} else if (rtype == relocInfo::metadata_type) {
|
||||
__ mov_metadata(dst_reg, (Metadata*)con);
|
||||
} else {
|
||||
assert(rtype == relocInfo::none, "unexpected reloc type");
|
||||
assert(rtype == relocInfo::none || rtype == relocInfo::external_word_type, "unexpected reloc type");
|
||||
// load fake address constants using a normal move
|
||||
if (! __ is_valid_AArch64_address(con) ||
|
||||
con < (address)(uintptr_t)os::vm_page_size()) {
|
||||
__ mov(dst_reg, con);
|
||||
} else {
|
||||
// no reloc so just use adrp and add
|
||||
uint64_t offset;
|
||||
__ adrp(dst_reg, con, offset);
|
||||
__ add(dst_reg, dst_reg, offset);
|
||||
@ -4535,6 +4537,18 @@ operand immP_1()
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// AOT Runtime Constants Address
|
||||
operand immAOTRuntimeConstantsAddress()
|
||||
%{
|
||||
// Check if the address is in the range of AOT Runtime Constants
|
||||
predicate(AOTRuntimeConstants::contains((address)(n->get_ptr())));
|
||||
match(ConP);
|
||||
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Float and Double operands
|
||||
// Double Immediate
|
||||
operand immD()
|
||||
@ -6898,6 +6912,20 @@ instruct loadConP1(iRegPNoSp dst, immP_1 con)
|
||||
ins_pipe(ialu_imm);
|
||||
%}
|
||||
|
||||
instruct loadAOTRCAddress(iRegPNoSp dst, immAOTRuntimeConstantsAddress con)
|
||||
%{
|
||||
match(Set dst con);
|
||||
|
||||
ins_cost(INSN_COST);
|
||||
format %{ "adr $dst, $con\t# AOT Runtime Constants Address" %}
|
||||
|
||||
ins_encode %{
|
||||
__ load_aotrc_address($dst$$Register, (address)$con$$constant);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_imm);
|
||||
%}
|
||||
|
||||
// Load Narrow Pointer Constant
|
||||
|
||||
instruct loadConN(iRegNNoSp dst, immN con)
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include "c1/c1_ValueStack.hpp"
|
||||
#include "ci/ciArrayKlass.hpp"
|
||||
#include "ci/ciInstance.hpp"
|
||||
#include "code/aotCodeCache.hpp"
|
||||
#include "code/compiledIC.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "gc/shared/gc_globals.hpp"
|
||||
@ -532,6 +533,15 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod
|
||||
|
||||
case T_LONG: {
|
||||
assert(patch_code == lir_patch_none, "no patching handled here");
|
||||
#if INCLUDE_CDS
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
address b = c->as_pointer();
|
||||
if (AOTRuntimeConstants::contains(b)) {
|
||||
__ load_aotrc_address(dest->as_register_lo(), b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
__ mov(dest->as_register_lo(), (intptr_t)c->as_jlong());
|
||||
break;
|
||||
}
|
||||
|
||||
@ -30,7 +30,9 @@
|
||||
#include "opto/matcher.hpp"
|
||||
#include "opto/output.hpp"
|
||||
#include "opto/subnode.hpp"
|
||||
#include "runtime/objectMonitorTable.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/synchronizer.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
|
||||
@ -221,37 +223,52 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register t1,
|
||||
if (!UseObjectMonitorTable) {
|
||||
assert(t1_monitor == t1_mark, "should be the same here");
|
||||
} else {
|
||||
const Register t1_hash = t1;
|
||||
Label monitor_found;
|
||||
|
||||
// Load cache address
|
||||
lea(t3_t, Address(rthread, JavaThread::om_cache_oops_offset()));
|
||||
// Save the mark, we might need it to extract the hash.
|
||||
mov(t3, t1_mark);
|
||||
|
||||
const int num_unrolled = 2;
|
||||
// Look for the monitor in the om_cache.
|
||||
|
||||
ByteSize cache_offset = JavaThread::om_cache_oops_offset();
|
||||
ByteSize monitor_offset = OMCache::oop_to_monitor_difference();
|
||||
const int num_unrolled = OMCache::CAPACITY;
|
||||
for (int i = 0; i < num_unrolled; i++) {
|
||||
ldr(t1, Address(t3_t));
|
||||
cmp(obj, t1);
|
||||
ldr(t1_monitor, Address(rthread, cache_offset + monitor_offset));
|
||||
ldr(t2, Address(rthread, cache_offset));
|
||||
cmp(obj, t2);
|
||||
br(Assembler::EQ, monitor_found);
|
||||
increment(t3_t, in_bytes(OMCache::oop_to_oop_difference()));
|
||||
cache_offset = cache_offset + OMCache::oop_to_oop_difference();
|
||||
}
|
||||
|
||||
Label loop;
|
||||
// Look for the monitor in the table.
|
||||
|
||||
// Search for obj in cache.
|
||||
bind(loop);
|
||||
// Get the hash code.
|
||||
ubfx(t1_hash, t3, markWord::hash_shift, markWord::hash_bits);
|
||||
|
||||
// Check for match.
|
||||
ldr(t1, Address(t3_t));
|
||||
cmp(obj, t1);
|
||||
br(Assembler::EQ, monitor_found);
|
||||
// Get the table and calculate the bucket's address
|
||||
lea(t3, ExternalAddress(ObjectMonitorTable::current_table_address()));
|
||||
ldr(t3, Address(t3));
|
||||
ldr(t2, Address(t3, ObjectMonitorTable::table_capacity_mask_offset()));
|
||||
ands(t1_hash, t1_hash, t2);
|
||||
ldr(t3, Address(t3, ObjectMonitorTable::table_buckets_offset()));
|
||||
|
||||
// Search until null encountered, guaranteed _null_sentinel at end.
|
||||
increment(t3_t, in_bytes(OMCache::oop_to_oop_difference()));
|
||||
cbnz(t1, loop);
|
||||
// Cache Miss, NE set from cmp above, cbnz does not set flags
|
||||
b(slow_path);
|
||||
// Read the monitor from the bucket.
|
||||
ldr(t1_monitor, Address(t3, t1_hash, Address::lsl(LogBytesPerWord)));
|
||||
|
||||
// Check if the monitor in the bucket is special (empty, tombstone or removed).
|
||||
cmp(t1_monitor, (unsigned char)ObjectMonitorTable::SpecialPointerValues::below_is_special);
|
||||
br(Assembler::LO, slow_path);
|
||||
|
||||
// Check if object matches.
|
||||
ldr(t3, Address(t1_monitor, ObjectMonitor::object_offset()));
|
||||
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||
bs_asm->try_resolve_weak_handle_in_c2(this, t3, t2, slow_path);
|
||||
cmp(t3, obj);
|
||||
br(Assembler::NE, slow_path);
|
||||
|
||||
bind(monitor_found);
|
||||
ldr(t1_monitor, Address(t3_t, OMCache::oop_to_monitor_difference()));
|
||||
}
|
||||
|
||||
const Register t2_owner_addr = t2;
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "asm/macroAssembler.inline.hpp"
|
||||
#include "code/aotCodeCache.hpp"
|
||||
#include "gc/g1/g1BarrierSet.hpp"
|
||||
#include "gc/g1/g1BarrierSetAssembler.hpp"
|
||||
#include "gc/g1/g1BarrierSetRuntime.hpp"
|
||||
@ -243,9 +244,25 @@ static void generate_post_barrier(MacroAssembler* masm,
|
||||
assert_different_registers(store_addr, new_val, thread, tmp1, tmp2, noreg, rscratch1);
|
||||
|
||||
// Does store cross heap regions?
|
||||
__ eor(tmp1, store_addr, new_val); // tmp1 := store address ^ new value
|
||||
__ lsr(tmp1, tmp1, G1HeapRegion::LogOfHRGrainBytes); // tmp1 := ((store address ^ new value) >> LogOfHRGrainBytes)
|
||||
__ cbz(tmp1, done);
|
||||
#if INCLUDE_CDS
|
||||
// AOT code needs to load the barrier grain shift from the aot
|
||||
// runtime constants area in the code cache otherwise we can compile
|
||||
// it as an immediate operand
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
address grain_shift_address = (address)AOTRuntimeConstants::grain_shift_address();
|
||||
__ eor(tmp1, store_addr, new_val);
|
||||
__ lea(tmp2, ExternalAddress(grain_shift_address));
|
||||
__ ldrb(tmp2, tmp2);
|
||||
__ lsrv(tmp1, tmp1, tmp2);
|
||||
__ cbz(tmp1, done);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
__ eor(tmp1, store_addr, new_val); // tmp1 := store address ^ new value
|
||||
__ lsr(tmp1, tmp1, G1HeapRegion::LogOfHRGrainBytes); // tmp1 := ((store address ^ new value) >> LogOfHRGrainBytes)
|
||||
__ cbz(tmp1, done);
|
||||
}
|
||||
|
||||
// Crosses regions, storing null?
|
||||
if (new_val_may_be_null) {
|
||||
__ cbz(new_val, done);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, 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
|
||||
@ -441,6 +441,11 @@ OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Na
|
||||
return opto_reg;
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) {
|
||||
// Load the oop from the weak handle.
|
||||
__ ldr(obj, Address(obj));
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ _masm->
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, 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
|
||||
@ -135,6 +135,7 @@ public:
|
||||
OptoReg::Name opto_reg);
|
||||
OptoReg::Name refine_register(const Node* node,
|
||||
OptoReg::Name opto_reg);
|
||||
virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path);
|
||||
#endif // COMPILER2
|
||||
};
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2022, Red Hat, Inc. All rights reserved.
|
||||
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -442,6 +443,30 @@ void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj,
|
||||
Register tmp, Label& slow_path) {
|
||||
assert_different_registers(obj, tmp);
|
||||
|
||||
Label done;
|
||||
|
||||
// Resolve weak handle using the standard implementation.
|
||||
BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path);
|
||||
|
||||
// Check if the reference is null, and if it is, take the fast path.
|
||||
__ cbz(obj, done);
|
||||
|
||||
Address gc_state(rthread, ShenandoahThreadLocalData::gc_state_offset());
|
||||
__ lea(tmp, gc_state);
|
||||
__ ldrb(tmp, __ legitimize_address(gc_state, 1, tmp));
|
||||
|
||||
// Check if the heap is under weak-reference/roots processing, in
|
||||
// which case we need to take the slow path.
|
||||
__ tbnz(tmp, ShenandoahHeap::WEAK_ROOTS_BITPOS, slow_path);
|
||||
__ bind(done);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Special Shenandoah CAS implementation that handles false negatives due
|
||||
// to concurrent evacuation. The service is more complex than a
|
||||
// traditional CAS operation because the CAS operation is intended to
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved.
|
||||
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -79,6 +80,9 @@ public:
|
||||
Address dst, Register val, Register tmp1, Register tmp2, Register tmp3);
|
||||
virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
|
||||
Register obj, Register tmp, Label& slowpath);
|
||||
#ifdef COMPILER2
|
||||
virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path);
|
||||
#endif
|
||||
void cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val,
|
||||
bool acquire, bool release, bool is_cae, Register result);
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2026, 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
|
||||
@ -1326,6 +1326,23 @@ void ZStoreBarrierStubC2Aarch64::emit_code(MacroAssembler& masm) {
|
||||
register_stub(this);
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ masm->
|
||||
|
||||
void ZBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) {
|
||||
// Resolve weak handle using the standard implementation.
|
||||
BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path);
|
||||
|
||||
// Check if the oop is bad, in which case we need to take the slow path.
|
||||
__ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatMarkBadBeforeMov);
|
||||
__ movzw(tmp, barrier_Relocation::unpatched);
|
||||
__ tst(obj, tmp);
|
||||
__ br(Assembler::NE, slow_path);
|
||||
|
||||
// Oop is okay, so we uncolor it.
|
||||
__ lsr(obj, obj, ZPointerLoadShift);
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
#endif // COMPILER2
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2026, 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
|
||||
@ -191,6 +191,7 @@ public:
|
||||
ZLoadBarrierStubC2* stub) const;
|
||||
void generate_c2_store_barrier_stub(MacroAssembler* masm,
|
||||
ZStoreBarrierStubC2* stub) const;
|
||||
void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path);
|
||||
#endif // COMPILER2
|
||||
|
||||
void check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& error);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -39,7 +39,7 @@ define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap nulls
|
||||
define_pd_global(bool, DelayCompilerStubsGeneration, COMPILER2_OR_JVMCI);
|
||||
|
||||
define_pd_global(size_t, CodeCacheSegmentSize, 64);
|
||||
define_pd_global(intx, CodeEntryAlignment, 64);
|
||||
define_pd_global(uint, CodeEntryAlignment, 64);
|
||||
define_pd_global(intx, OptoLoopAlignment, 16);
|
||||
|
||||
#define DEFAULT_STACK_YELLOW_PAGES (2)
|
||||
|
||||
@ -406,7 +406,6 @@ public:
|
||||
offset <<= shift;
|
||||
uint64_t target_page = ((uint64_t)insn_addr) + offset;
|
||||
target_page &= ((uint64_t)-1) << shift;
|
||||
uint32_t insn2 = insn_at(insn_addr, 1);
|
||||
target = address(target_page);
|
||||
precond(inner != nullptr);
|
||||
inner(insn_addr, target);
|
||||
@ -520,13 +519,6 @@ int MacroAssembler::patch_narrow_klass(address insn_addr, narrowKlass n) {
|
||||
return 2 * NativeInstruction::instruction_size;
|
||||
}
|
||||
|
||||
address MacroAssembler::target_addr_for_insn_or_null(address insn_addr) {
|
||||
if (NativeInstruction::is_ldrw_to_zr(insn_addr)) {
|
||||
return nullptr;
|
||||
}
|
||||
return MacroAssembler::target_addr_for_insn(insn_addr);
|
||||
}
|
||||
|
||||
void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool in_nmethod, Register tmp) {
|
||||
ldr(tmp, Address(rthread, JavaThread::polling_word_offset()));
|
||||
if (at_return) {
|
||||
@ -1960,9 +1952,7 @@ void MacroAssembler::verify_secondary_supers_table(Register r_sub_klass,
|
||||
|
||||
const Register
|
||||
r_array_base = temp1,
|
||||
r_array_length = temp2,
|
||||
r_array_index = noreg, // unused
|
||||
r_bitmap = noreg; // unused
|
||||
r_array_length = temp2;
|
||||
|
||||
BLOCK_COMMENT("verify_secondary_supers_table {");
|
||||
|
||||
@ -3611,9 +3601,8 @@ extern "C" void findpc(intptr_t x);
|
||||
void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[])
|
||||
{
|
||||
// In order to get locks to work, we need to fake a in_VM state
|
||||
if (ShowMessageBoxOnError ) {
|
||||
if (ShowMessageBoxOnError) {
|
||||
JavaThread* thread = JavaThread::current();
|
||||
JavaThreadState saved_state = thread->thread_state();
|
||||
thread->set_thread_state(_thread_in_vm);
|
||||
#ifndef PRODUCT
|
||||
if (CountBytecodes || TraceBytecodes || StopInterpreterAt) {
|
||||
@ -5738,7 +5727,6 @@ address MacroAssembler::read_polling_page(Register r, relocInfo::relocType rtype
|
||||
}
|
||||
|
||||
void MacroAssembler::adrp(Register reg1, const Address &dest, uint64_t &byte_offset) {
|
||||
relocInfo::relocType rtype = dest.rspec().reloc()->type();
|
||||
uint64_t low_page = (uint64_t)CodeCache::low_bound() >> 12;
|
||||
uint64_t high_page = (uint64_t)(CodeCache::high_bound()-1) >> 12;
|
||||
uint64_t dest_page = (uint64_t)dest.target() >> 12;
|
||||
@ -5766,6 +5754,14 @@ void MacroAssembler::adrp(Register reg1, const Address &dest, uint64_t &byte_off
|
||||
}
|
||||
|
||||
void MacroAssembler::load_byte_map_base(Register reg) {
|
||||
#if INCLUDE_CDS
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
address byte_map_base_adr = AOTRuntimeConstants::card_table_base_address();
|
||||
lea(reg, ExternalAddress(byte_map_base_adr));
|
||||
ldr(reg, Address(reg));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
CardTableBarrierSet* ctbs = CardTableBarrierSet::barrier_set();
|
||||
|
||||
// Strictly speaking the card table base isn't an address at all, and it might
|
||||
@ -5773,6 +5769,20 @@ void MacroAssembler::load_byte_map_base(Register reg) {
|
||||
mov(reg, (uint64_t)ctbs->card_table_base_const());
|
||||
}
|
||||
|
||||
void MacroAssembler::load_aotrc_address(Register reg, address a) {
|
||||
#if INCLUDE_CDS
|
||||
assert(AOTRuntimeConstants::contains(a), "address out of range for data area");
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
// all aotrc field addresses should be registered in the AOTCodeCache address table
|
||||
lea(reg, ExternalAddress(a));
|
||||
} else {
|
||||
mov(reg, (uint64_t)a);
|
||||
}
|
||||
#else
|
||||
ShouldNotReachHere();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MacroAssembler::build_frame(int framesize) {
|
||||
assert(framesize >= 2 * wordSize, "framesize must include space for FP/LR");
|
||||
assert(framesize % (2*wordSize) == 0, "must preserve 2*wordSize alignment");
|
||||
@ -6114,7 +6124,6 @@ void MacroAssembler::string_equals(Register a1, Register a2,
|
||||
Label SAME, DONE, SHORT, NEXT_WORD;
|
||||
Register tmp1 = rscratch1;
|
||||
Register tmp2 = rscratch2;
|
||||
Register cnt2 = tmp2; // cnt2 only used in array length compare
|
||||
|
||||
assert_different_registers(a1, a2, result, cnt1, rscratch1, rscratch2);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, 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.
|
||||
*
|
||||
@ -678,7 +678,6 @@ public:
|
||||
static bool uses_implicit_null_check(void* address);
|
||||
|
||||
static address target_addr_for_insn(address insn_addr);
|
||||
static address target_addr_for_insn_or_null(address insn_addr);
|
||||
|
||||
// Required platform-specific helpers for Label::patch_instructions.
|
||||
// They _shadow_ the declarations in AbstractAssembler, which are undefined.
|
||||
@ -1477,6 +1476,9 @@ public:
|
||||
// Load the base of the cardtable byte map into reg.
|
||||
void load_byte_map_base(Register reg);
|
||||
|
||||
// Load a constant address in the AOT Runtime Constants area
|
||||
void load_aotrc_address(Register reg, address a);
|
||||
|
||||
// Prolog generator routines to support switch between x86 code and
|
||||
// generated ARM code
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, 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.
|
||||
*
|
||||
@ -192,7 +192,6 @@ int NativeMovRegMem::offset() const {
|
||||
|
||||
void NativeMovRegMem::set_offset(int x) {
|
||||
address pc = instruction_address();
|
||||
unsigned insn = *(unsigned*)pc;
|
||||
if (maybe_cpool_ref(pc)) {
|
||||
address addr = MacroAssembler::target_addr_for_insn(pc);
|
||||
*(int64_t*)addr = x;
|
||||
@ -204,7 +203,7 @@ void NativeMovRegMem::set_offset(int x) {
|
||||
|
||||
void NativeMovRegMem::verify() {
|
||||
#ifdef ASSERT
|
||||
address dest = MacroAssembler::target_addr_for_insn_or_null(instruction_address());
|
||||
MacroAssembler::target_addr_for_insn(instruction_address());
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -213,7 +212,7 @@ void NativeMovRegMem::verify() {
|
||||
void NativeJump::verify() { ; }
|
||||
|
||||
address NativeJump::jump_destination() const {
|
||||
address dest = MacroAssembler::target_addr_for_insn_or_null(instruction_address());
|
||||
address dest = MacroAssembler::target_addr_for_insn(instruction_address());
|
||||
|
||||
// We use jump to self as the unresolved address which the inline
|
||||
// cache code (and relocs) know about
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2025, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -78,7 +78,6 @@ public:
|
||||
inline bool is_nop() const;
|
||||
bool is_jump();
|
||||
bool is_general_jump();
|
||||
inline bool is_jump_or_nop();
|
||||
inline bool is_cond_jump();
|
||||
bool is_safepoint_poll();
|
||||
bool is_movz();
|
||||
@ -420,10 +419,6 @@ inline bool NativeInstruction::is_jump() {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool NativeInstruction::is_jump_or_nop() {
|
||||
return is_nop() || is_jump();
|
||||
}
|
||||
|
||||
// Call trampoline stubs.
|
||||
class NativeCallTrampolineStub : public NativeInstruction {
|
||||
public:
|
||||
|
||||
@ -96,10 +96,6 @@ static inline Address aaddress(Register r) {
|
||||
return iaddress(r);
|
||||
}
|
||||
|
||||
static inline Address at_rsp() {
|
||||
return Address(esp, 0);
|
||||
}
|
||||
|
||||
// At top of Java expression stack which may be different than esp(). It
|
||||
// isn't for category 1 objects.
|
||||
static inline Address at_tos () {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2020, Red Hat Inc. All rights reserved.
|
||||
* Copyright 2025 Arm Limited and/or its affiliates.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -446,7 +446,9 @@ void VM_Version::initialize() {
|
||||
FLAG_SET_DEFAULT(BlockZeroingLowLimit, 4 * VM_Version::zva_length());
|
||||
}
|
||||
} else if (UseBlockZeroing) {
|
||||
warning("DC ZVA is not available on this CPU");
|
||||
if (!FLAG_IS_DEFAULT(UseBlockZeroing)) {
|
||||
warning("DC ZVA is not available on this CPU");
|
||||
}
|
||||
FLAG_SET_DEFAULT(UseBlockZeroing, false);
|
||||
}
|
||||
|
||||
@ -664,16 +666,52 @@ void VM_Version::initialize() {
|
||||
void VM_Version::insert_features_names(uint64_t features, stringStream& ss) {
|
||||
int i = 0;
|
||||
ss.join([&]() {
|
||||
while (i < MAX_CPU_FEATURES) {
|
||||
if (supports_feature((VM_Version::Feature_Flag)i)) {
|
||||
return _features_names[i++];
|
||||
const char* str = nullptr;
|
||||
while ((i < MAX_CPU_FEATURES) && (str == nullptr)) {
|
||||
if (supports_feature(features, (VM_Version::Feature_Flag)i)) {
|
||||
str = _features_names[i];
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return (const char*)nullptr;
|
||||
return str;
|
||||
}, ", ");
|
||||
}
|
||||
|
||||
void VM_Version::get_cpu_features_name(void* features_buffer, stringStream& ss) {
|
||||
uint64_t features = *(uint64_t*)features_buffer;
|
||||
insert_features_names(features, ss);
|
||||
}
|
||||
|
||||
void VM_Version::get_missing_features_name(void* features_set1, void* features_set2, stringStream& ss) {
|
||||
uint64_t vm_features_set1 = *(uint64_t*)features_set1;
|
||||
uint64_t vm_features_set2 = *(uint64_t*)features_set2;
|
||||
int i = 0;
|
||||
ss.join([&]() {
|
||||
const char* str = nullptr;
|
||||
while ((i < MAX_CPU_FEATURES) && (str == nullptr)) {
|
||||
Feature_Flag flag = (Feature_Flag)i;
|
||||
if (supports_feature(vm_features_set1, flag) && !supports_feature(vm_features_set2, flag)) {
|
||||
str = _features_names[i];
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return str;
|
||||
}, ", ");
|
||||
}
|
||||
|
||||
int VM_Version::cpu_features_size() {
|
||||
return sizeof(_features);
|
||||
}
|
||||
|
||||
void VM_Version::store_cpu_features(void* buf) {
|
||||
*(uint64_t*)buf = _features;
|
||||
}
|
||||
|
||||
bool VM_Version::supports_features(void* features_buffer) {
|
||||
uint64_t features_to_test = *(uint64_t*)features_buffer;
|
||||
return (_features & features_to_test) == features_to_test;
|
||||
}
|
||||
|
||||
#if defined(LINUX)
|
||||
static bool check_info_file(const char* fpath,
|
||||
const char* virt1, VirtualizationType vt1,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, 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.
|
||||
*
|
||||
@ -184,6 +184,9 @@ public:
|
||||
static bool supports_feature(Feature_Flag flag) {
|
||||
return (_features & BIT_MASK(flag)) != 0;
|
||||
}
|
||||
static bool supports_feature(uint64_t features, Feature_Flag flag) {
|
||||
return (features & BIT_MASK(flag)) != 0;
|
||||
}
|
||||
|
||||
static int cpu_family() { return _cpu; }
|
||||
static int cpu_model() { return _model; }
|
||||
@ -204,7 +207,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_zva_enabled() { return 0 <= _zva_length; }
|
||||
static bool is_zva_enabled() { return 0 < _zva_length; }
|
||||
static int zva_length() {
|
||||
assert(is_zva_enabled(), "ZVA not available");
|
||||
return _zva_length;
|
||||
@ -244,6 +247,20 @@ public:
|
||||
static bool use_neon_for_vector(int vector_length_in_bytes) {
|
||||
return vector_length_in_bytes <= 16;
|
||||
}
|
||||
|
||||
static void get_cpu_features_name(void* features_buffer, stringStream& ss);
|
||||
|
||||
// Returns names of features present in features_set1 but not in features_set2
|
||||
static void get_missing_features_name(void* features_set1, void* features_set2, stringStream& ss);
|
||||
|
||||
// Returns number of bytes required to store cpu features representation
|
||||
static int cpu_features_size();
|
||||
|
||||
// Stores cpu features representation in the provided buffer. This representation is arch dependent.
|
||||
// Size of the buffer must be same as returned by cpu_features_size()
|
||||
static void store_cpu_features(void* buf);
|
||||
|
||||
static bool supports_features(void* features_to_test);
|
||||
};
|
||||
|
||||
#endif // CPU_AARCH64_VM_VERSION_AARCH64_HPP
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -37,7 +37,7 @@ define_pd_global(bool, TrapBasedNullChecks, false); // Not needed
|
||||
define_pd_global(bool, DelayCompilerStubsGeneration, false); // No need - only few compiler's stubs
|
||||
|
||||
define_pd_global(size_t, CodeCacheSegmentSize, 64);
|
||||
define_pd_global(intx, CodeEntryAlignment, 16);
|
||||
define_pd_global(uint, CodeEntryAlignment, 16);
|
||||
define_pd_global(intx, OptoLoopAlignment, 16);
|
||||
|
||||
#define DEFAULT_STACK_YELLOW_PAGES (2)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
|
||||
* Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026 SAP SE. 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
|
||||
@ -599,6 +599,9 @@ class Assembler : public AbstractAssembler {
|
||||
XVMAXSP_OPCODE = (60u << OPCODE_SHIFT | 192u << 3),
|
||||
XVMAXDP_OPCODE = (60u << OPCODE_SHIFT | 224u << 3),
|
||||
|
||||
XSMINJDP_OPCODE = (60u << OPCODE_SHIFT | 152u << 3),
|
||||
XSMAXJDP_OPCODE = (60u << OPCODE_SHIFT | 144u << 3),
|
||||
|
||||
// Deliver A Random Number (introduced with POWER9)
|
||||
DARN_OPCODE = (31u << OPCODE_SHIFT | 755u << 1),
|
||||
|
||||
@ -2455,6 +2458,9 @@ class Assembler : public AbstractAssembler {
|
||||
inline void xvrdpim( VectorSRegister d, VectorSRegister b);
|
||||
inline void xvrdpip( VectorSRegister d, VectorSRegister b);
|
||||
|
||||
inline void xsminjdp( VectorSRegister d, VectorSRegister a, VectorSRegister b); // Requires Power 9
|
||||
inline void xsmaxjdp( VectorSRegister d, VectorSRegister a, VectorSRegister b); // Requires Power 9
|
||||
|
||||
// The following functions do not match exactly the Java.math semantics.
|
||||
inline void xvminsp( VectorSRegister d, VectorSRegister a, VectorSRegister b);
|
||||
inline void xvmindp( VectorSRegister d, VectorSRegister a, VectorSRegister b);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
|
||||
* Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026 SAP SE. 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
|
||||
@ -908,6 +908,9 @@ inline void Assembler::xvrdpic( VectorSRegister d, VectorSRegister b)
|
||||
inline void Assembler::xvrdpim( VectorSRegister d, VectorSRegister b) { emit_int32( XVRDPIM_OPCODE | vsrt(d) | vsrb(b)); }
|
||||
inline void Assembler::xvrdpip( VectorSRegister d, VectorSRegister b) { emit_int32( XVRDPIP_OPCODE | vsrt(d) | vsrb(b)); }
|
||||
|
||||
inline void Assembler::xsminjdp(VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XSMINJDP_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); }
|
||||
inline void Assembler::xsmaxjdp(VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XSMAXJDP_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); }
|
||||
|
||||
inline void Assembler::xvminsp(VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XVMINSP_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); }
|
||||
inline void Assembler::xvmindp(VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XVMINDP_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); }
|
||||
inline void Assembler::xvmaxsp(VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XVMAXSP_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); }
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2026 SAP SE. 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
|
||||
@ -600,19 +601,21 @@ void C2_MacroAssembler::count_positives(Register src, Register cnt, Register res
|
||||
orr(tmp0, tmp2, tmp0);
|
||||
|
||||
and_(tmp0, tmp0, tmp1);
|
||||
bne(CR0, Lslow); // Found negative byte.
|
||||
bne(CR0, Lslow); // Found negative byte.
|
||||
addi(result, result, 16);
|
||||
bdnz(Lfastloop);
|
||||
|
||||
bind(Lslow); // Fallback to slow version.
|
||||
subf(tmp0, src, result); // Bytes known positive.
|
||||
subf_(tmp0, tmp0, cnt); // Remaining Bytes.
|
||||
clrldi(tmp1, cnt, 32); // Clear garbage from upper 32 bits.
|
||||
subf_(tmp0, tmp0, tmp1); // Remaining Bytes.
|
||||
beq(CR0, Ldone);
|
||||
mtctr(tmp0);
|
||||
|
||||
bind(Lloop);
|
||||
lbz(tmp0, 0, result);
|
||||
andi_(tmp0, tmp0, 0x80);
|
||||
bne(CR0, Ldone); // Found negative byte.
|
||||
bne(CR0, Ldone); // Found negative byte.
|
||||
addi(result, result, 1);
|
||||
bdnz(Lloop);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2019 SAP SE. All rights reserved.
|
||||
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -44,7 +44,7 @@ define_pd_global(intx, CompileThreshold, 10000);
|
||||
|
||||
define_pd_global(intx, OnStackReplacePercentage, 140);
|
||||
define_pd_global(intx, ConditionalMoveLimit, 3);
|
||||
define_pd_global(intx, FreqInlineSize, 175);
|
||||
define_pd_global(intx, FreqInlineSize, 325);
|
||||
define_pd_global(intx, MinJumpTableSize, 10);
|
||||
define_pd_global(intx, InteriorEntryAlignment, 16);
|
||||
define_pd_global(size_t, NewSizeThreadIncrease, ScaleForWordSize(4*K));
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2025 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -275,6 +275,11 @@ OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Na
|
||||
return opto_reg;
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) {
|
||||
// Load the oop from the weak handle.
|
||||
__ ld(obj, 0, obj);
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ _masm->
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2022 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -81,6 +81,8 @@ public:
|
||||
|
||||
#ifdef COMPILER2
|
||||
OptoReg::Name refine_register(const Node* node, OptoReg::Name opto_reg) const;
|
||||
virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj,
|
||||
Register tmp, Label& slow_path);
|
||||
#endif // COMPILER2
|
||||
};
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2025, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -662,6 +663,33 @@ void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler
|
||||
__ block_comment("} try_resolve_jobject_in_native (shenandoahgc)");
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler *masm, Register obj,
|
||||
Register tmp, Label &slow_path) {
|
||||
__ block_comment("try_resolve_weak_handle_in_c2 (shenandoahgc) {");
|
||||
|
||||
assert_different_registers(obj, tmp);
|
||||
|
||||
Label done;
|
||||
|
||||
// Resolve weak handle using the standard implementation.
|
||||
BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path);
|
||||
|
||||
// Check if the reference is null, and if it is, take the fast path.
|
||||
__ cmpdi(CR0, obj, 0);
|
||||
__ beq(CR0, done);
|
||||
|
||||
// Check if the heap is under weak-reference/roots processing, in
|
||||
// which case we need to take the slow path.
|
||||
__ lbz(tmp, in_bytes(ShenandoahThreadLocalData::gc_state_offset()), R16_thread);
|
||||
__ andi_(tmp, tmp, ShenandoahHeap::WEAK_ROOTS);
|
||||
__ bne(CR0, slow_path);
|
||||
__ bind(done);
|
||||
|
||||
__ block_comment("} try_resolve_weak_handle_in_c2 (shenandoahgc)");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Special shenandoah CAS implementation that handles false negatives due
|
||||
// to concurrent evacuation. That is, the CAS operation is intended to succeed in
|
||||
// the following scenarios (success criteria):
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2022, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (c) 2012, 2022 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -121,6 +122,9 @@ public:
|
||||
|
||||
virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register dst, Register jni_env,
|
||||
Register obj, Register tmp, Label& slowpath);
|
||||
#ifdef COMPILER2
|
||||
virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // CPU_PPC_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_PPC_HPP
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2025 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -950,6 +950,19 @@ void ZBarrierSetAssembler::generate_c2_store_barrier_stub(MacroAssembler* masm,
|
||||
__ b(*stub->continuation());
|
||||
}
|
||||
|
||||
void ZBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) {
|
||||
// Resolve weak handle using the standard implementation.
|
||||
BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path);
|
||||
|
||||
// Check if the oop is bad, in which case we need to take the slow path.
|
||||
__ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatMarkBadMask);
|
||||
__ andi_(R0, obj, barrier_Relocation::unpatched);
|
||||
__ bne(CR0, slow_path);
|
||||
|
||||
// Oop is okay, so we uncolor it.
|
||||
__ srdi(obj, obj, ZPointerLoadShift);
|
||||
}
|
||||
|
||||
#undef __
|
||||
#endif // COMPILER2
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2022 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -108,6 +108,8 @@ public:
|
||||
void generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const;
|
||||
|
||||
void generate_c2_store_barrier_stub(MacroAssembler* masm, ZStoreBarrierStubC2* stub) const;
|
||||
|
||||
void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path);
|
||||
#endif // COMPILER2
|
||||
|
||||
void store_barrier_fast(MacroAssembler* masm,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2024 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -60,7 +60,7 @@ define_pd_global(bool, VMContinuations, true);
|
||||
|
||||
// Use large code-entry alignment.
|
||||
define_pd_global(size_t, CodeCacheSegmentSize, 128);
|
||||
define_pd_global(intx, CodeEntryAlignment, 64);
|
||||
define_pd_global(uint, CodeEntryAlignment, 64);
|
||||
define_pd_global(intx, OptoLoopAlignment, 16);
|
||||
define_pd_global(intx, InlineSmallCode, 1500);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -42,6 +42,7 @@
|
||||
#include "runtime/icache.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/objectMonitor.hpp"
|
||||
#include "runtime/objectMonitorTable.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/safepointMechanism.hpp"
|
||||
@ -2756,39 +2757,54 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register
|
||||
addi(owner_addr, mark, in_bytes(ObjectMonitor::owner_offset()) - monitor_tag);
|
||||
mark = noreg;
|
||||
} else {
|
||||
const Register tmp3_bucket = tmp3;
|
||||
const Register tmp2_hash = tmp2;
|
||||
Label monitor_found;
|
||||
Register cache_addr = tmp2;
|
||||
|
||||
// Load cache address
|
||||
addi(cache_addr, R16_thread, in_bytes(JavaThread::om_cache_oops_offset()));
|
||||
// Save the mark, we might need it to extract the hash.
|
||||
mr(tmp2_hash, mark);
|
||||
|
||||
const int num_unrolled = 2;
|
||||
// Look for the monitor in the om_cache.
|
||||
|
||||
ByteSize cache_offset = JavaThread::om_cache_oops_offset();
|
||||
ByteSize monitor_offset = OMCache::oop_to_monitor_difference();
|
||||
const int num_unrolled = OMCache::CAPACITY;
|
||||
for (int i = 0; i < num_unrolled; i++) {
|
||||
ld(R0, 0, cache_addr);
|
||||
ld(R0, in_bytes(cache_offset), R16_thread);
|
||||
ld(monitor, in_bytes(cache_offset + monitor_offset), R16_thread);
|
||||
cmpd(CR0, R0, obj);
|
||||
beq(CR0, monitor_found);
|
||||
addi(cache_addr, cache_addr, in_bytes(OMCache::oop_to_oop_difference()));
|
||||
cache_offset = cache_offset + OMCache::oop_to_oop_difference();
|
||||
}
|
||||
|
||||
Label loop;
|
||||
// Look for the monitor in the table.
|
||||
|
||||
// Search for obj in cache.
|
||||
bind(loop);
|
||||
// Get the hash code.
|
||||
srdi(tmp2_hash, tmp2_hash, markWord::hash_shift);
|
||||
|
||||
// Check for match.
|
||||
ld(R0, 0, cache_addr);
|
||||
cmpd(CR0, R0, obj);
|
||||
beq(CR0, monitor_found);
|
||||
// Get the table and calculate the bucket's address
|
||||
int simm16_rest = load_const_optimized(tmp3, ObjectMonitorTable::current_table_address(), R0, true);
|
||||
ld_ptr(tmp3, simm16_rest, tmp3);
|
||||
ld(tmp1, in_bytes(ObjectMonitorTable::table_capacity_mask_offset()), tmp3);
|
||||
andr(tmp2_hash, tmp2_hash, tmp1);
|
||||
ld(tmp3_bucket, in_bytes(ObjectMonitorTable::table_buckets_offset()), tmp3);
|
||||
|
||||
// Search until null encountered, guaranteed _null_sentinel at end.
|
||||
addi(cache_addr, cache_addr, in_bytes(OMCache::oop_to_oop_difference()));
|
||||
cmpdi(CR1, R0, 0);
|
||||
bne(CR1, loop);
|
||||
// Cache Miss, CR0.NE set from cmp above
|
||||
b(slow_path);
|
||||
// Read the monitor from the bucket.
|
||||
sldi(tmp2_hash, tmp2_hash, LogBytesPerWord);
|
||||
ldx(monitor, tmp3_bucket, tmp2_hash);
|
||||
|
||||
// Check if the monitor in the bucket is special (empty, tombstone or removed).
|
||||
cmpldi(CR0, monitor, ObjectMonitorTable::SpecialPointerValues::below_is_special);
|
||||
blt(CR0, slow_path);
|
||||
|
||||
// Check if object matches.
|
||||
ld(tmp3, in_bytes(ObjectMonitor::object_offset()), monitor);
|
||||
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||
bs_asm->try_resolve_weak_handle_in_c2(this, tmp3, tmp2, slow_path);
|
||||
cmpd(CR0, tmp3, obj);
|
||||
bne(CR0, slow_path);
|
||||
|
||||
bind(monitor_found);
|
||||
ld(monitor, in_bytes(OMCache::oop_to_monitor_difference()), cache_addr);
|
||||
|
||||
// Compute owner address.
|
||||
addi(owner_addr, monitor, in_bytes(ObjectMonitor::owner_offset()));
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
|
||||
* Copyright (c) 2002, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026 SAP SE. 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
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2026 SAP SE. 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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -49,11 +49,6 @@
|
||||
|
||||
#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
|
||||
|
||||
// Workaround for C++ overloading nastiness on '0' for RegisterOrConstant.
|
||||
inline static RegisterOrConstant constant(int value) {
|
||||
return RegisterOrConstant(value);
|
||||
}
|
||||
|
||||
void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_reg,
|
||||
Register temp_reg, Register temp2_reg) {
|
||||
if (VerifyMethodHandles) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//
|
||||
// Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2012, 2025 SAP SE. All rights reserved.
|
||||
// Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2012, 2026 SAP SE. 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
|
||||
@ -2234,6 +2234,12 @@ bool Matcher::match_rule_supported(int opcode) {
|
||||
case Op_FmaVD:
|
||||
return (SuperwordUseVSX && UseFMA);
|
||||
|
||||
case Op_MinF:
|
||||
case Op_MaxF:
|
||||
case Op_MinD:
|
||||
case Op_MaxD:
|
||||
return (PowerArchitecturePPC64 >= 9);
|
||||
|
||||
case Op_Digit:
|
||||
return vmIntrinsics::is_intrinsic_available(vmIntrinsics::_isDigit);
|
||||
case Op_LowerCase:
|
||||
@ -12313,6 +12319,58 @@ instruct maxI_reg_reg_isel(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsRegC
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
instruct minF(regF dst, regF src1, regF src2) %{
|
||||
match(Set dst (MinF src1 src2));
|
||||
predicate(PowerArchitecturePPC64 >= 9);
|
||||
ins_cost(DEFAULT_COST);
|
||||
|
||||
format %{ "MinF $dst, $src1, $src2" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ xsminjdp($dst$$FloatRegister->to_vsr(), $src1$$FloatRegister->to_vsr(), $src2$$FloatRegister->to_vsr());
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
instruct minD(regD dst, regD src1, regD src2) %{
|
||||
match(Set dst (MinD src1 src2));
|
||||
predicate(PowerArchitecturePPC64 >= 9);
|
||||
ins_cost(DEFAULT_COST);
|
||||
|
||||
format %{ "MinD $dst, $src1, $src2" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ xsminjdp($dst$$FloatRegister->to_vsr(), $src1$$FloatRegister->to_vsr(), $src2$$FloatRegister->to_vsr());
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
instruct maxF(regF dst, regF src1, regF src2) %{
|
||||
match(Set dst (MaxF src1 src2));
|
||||
predicate(PowerArchitecturePPC64 >= 9);
|
||||
ins_cost(DEFAULT_COST);
|
||||
|
||||
format %{ "MaxF $dst, $src1, $src2" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ xsmaxjdp($dst$$FloatRegister->to_vsr(), $src1$$FloatRegister->to_vsr(), $src2$$FloatRegister->to_vsr());
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
instruct maxD(regD dst, regD src1, regD src2) %{
|
||||
match(Set dst (MaxD src1 src2));
|
||||
predicate(PowerArchitecturePPC64 >= 9);
|
||||
ins_cost(DEFAULT_COST);
|
||||
|
||||
format %{ "MaxD $dst, $src1, $src2" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ xsmaxjdp($dst$$FloatRegister->to_vsr(), $src1$$FloatRegister->to_vsr(), $src2$$FloatRegister->to_vsr());
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
//---------- Population Count Instructions ------------------------------------
|
||||
|
||||
instruct popCountI(iRegIdst dst, iRegIsrc src) %{
|
||||
|
||||
@ -1041,31 +1041,10 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
|
||||
__ bind(*op->stub()->continuation());
|
||||
}
|
||||
|
||||
void LIR_Assembler::type_profile_helper(Register mdo, ciMethodData *md, ciProfileData *data,
|
||||
Register recv, Label* update_done) {
|
||||
for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) {
|
||||
Label next_test;
|
||||
// See if the receiver is receiver[n].
|
||||
__ ld(t1, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i))));
|
||||
__ bne(recv, t1, next_test);
|
||||
Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i)));
|
||||
__ increment(data_addr, DataLayout::counter_increment);
|
||||
__ j(*update_done);
|
||||
__ bind(next_test);
|
||||
}
|
||||
|
||||
// Didn't find receiver; find next empty slot and fill it in
|
||||
for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) {
|
||||
Label next_test;
|
||||
Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)));
|
||||
__ ld(t1, recv_addr);
|
||||
__ bnez(t1, next_test);
|
||||
__ sd(recv, recv_addr);
|
||||
__ mv(t1, DataLayout::counter_increment);
|
||||
__ sd(t1, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))));
|
||||
__ j(*update_done);
|
||||
__ bind(next_test);
|
||||
}
|
||||
void LIR_Assembler::type_profile_helper(Register mdo, ciMethodData *md,
|
||||
ciProfileData *data, Register recv) {
|
||||
int mdp_offset = md->byte_offset_of_slot(data, in_ByteSize(0));
|
||||
__ profile_receiver_type(recv, mdo, mdp_offset);
|
||||
}
|
||||
|
||||
void LIR_Assembler::data_check(LIR_OpTypeCheck *op, ciMethodData **md, ciProfileData **data) {
|
||||
@ -1139,14 +1118,9 @@ void LIR_Assembler::profile_object(ciMethodData* md, ciProfileData* data, Regist
|
||||
__ j(*obj_is_null);
|
||||
__ bind(not_null);
|
||||
|
||||
Label update_done;
|
||||
Register recv = k_RInfo;
|
||||
__ load_klass(recv, obj);
|
||||
type_profile_helper(mdo, md, data, recv, &update_done);
|
||||
Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()));
|
||||
__ increment(counter_addr, DataLayout::counter_increment);
|
||||
|
||||
__ bind(update_done);
|
||||
type_profile_helper(mdo, md, data, recv);
|
||||
}
|
||||
|
||||
void LIR_Assembler::typecheck_loaded(LIR_OpTypeCheck *op, ciKlass* k, Register k_RInfo) {
|
||||
@ -1554,11 +1528,8 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
// We know the type that will be seen at this call site; we can
|
||||
// statically update the MethodData* rather than needing to do
|
||||
// dynamic tests on the receiver type
|
||||
// NOTE: we should probably put a lock around this search to
|
||||
// avoid collisions by concurrent compilations
|
||||
ciVirtualCallData* vc_data = (ciVirtualCallData*) data;
|
||||
uint i;
|
||||
for (i = 0; i < VirtualCallData::row_limit(); i++) {
|
||||
for (uint i = 0; i < VirtualCallData::row_limit(); i++) {
|
||||
ciKlass* receiver = vc_data->receiver(i);
|
||||
if (known_klass->equals(receiver)) {
|
||||
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)));
|
||||
@ -1566,32 +1537,13 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Receiver type not found in profile data; select an empty slot
|
||||
// Note that this is less efficient than it should be because it
|
||||
// always does a write to the receiver part of the
|
||||
// VirtualCallData rather than just the first time
|
||||
for (i = 0; i < VirtualCallData::row_limit(); i++) {
|
||||
ciKlass* receiver = vc_data->receiver(i);
|
||||
if (receiver == nullptr) {
|
||||
Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)));
|
||||
__ mov_metadata(t1, known_klass->constant_encoding());
|
||||
__ sd(t1, recv_addr);
|
||||
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)));
|
||||
__ increment(data_addr, DataLayout::counter_increment);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Receiver type is not found in profile data.
|
||||
// Fall back to runtime helper to handle the rest at runtime.
|
||||
__ mov_metadata(recv, known_klass->constant_encoding());
|
||||
} else {
|
||||
__ load_klass(recv, recv);
|
||||
Label update_done;
|
||||
type_profile_helper(mdo, md, data, recv, &update_done);
|
||||
// Receiver did not match any saved receiver and there is no empty row for it.
|
||||
// Increment total counter to indicate polymorphic case.
|
||||
__ increment(counter_addr, DataLayout::counter_increment);
|
||||
|
||||
__ bind(update_done);
|
||||
}
|
||||
type_profile_helper(mdo, md, data, recv);
|
||||
} else {
|
||||
// Static call
|
||||
__ increment(counter_addr, DataLayout::counter_increment);
|
||||
|
||||
@ -54,9 +54,8 @@ private:
|
||||
Address stack_slot_address(int index, uint shift, int adjust = 0);
|
||||
|
||||
// Record the type of the receiver in ReceiverTypeData
|
||||
void type_profile_helper(Register mdo,
|
||||
ciMethodData *md, ciProfileData *data,
|
||||
Register recv, Label* update_done);
|
||||
void type_profile_helper(Register mdo, ciMethodData *md,
|
||||
ciProfileData *data, Register recv);
|
||||
|
||||
void casw(Register addr, Register newval, Register cmpval);
|
||||
void caswu(Register addr, Register newval, Register cmpval);
|
||||
|
||||
@ -30,7 +30,9 @@
|
||||
#include "opto/intrinsicnode.hpp"
|
||||
#include "opto/output.hpp"
|
||||
#include "opto/subnode.hpp"
|
||||
#include "runtime/objectMonitorTable.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/synchronizer.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
#ifdef PRODUCT
|
||||
@ -123,35 +125,52 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box,
|
||||
if (!UseObjectMonitorTable) {
|
||||
assert(tmp1_monitor == tmp1_mark, "should be the same here");
|
||||
} else {
|
||||
const Register tmp2_hash = tmp2;
|
||||
const Register tmp3_bucket = tmp3;
|
||||
Label monitor_found;
|
||||
|
||||
// Load cache address
|
||||
la(tmp3_t, Address(xthread, JavaThread::om_cache_oops_offset()));
|
||||
// Save the mark, we might need it to extract the hash.
|
||||
mv(tmp2_hash, tmp1_mark);
|
||||
|
||||
const int num_unrolled = 2;
|
||||
// Look for the monitor in the om_cache.
|
||||
|
||||
ByteSize cache_offset = JavaThread::om_cache_oops_offset();
|
||||
ByteSize monitor_offset = OMCache::oop_to_monitor_difference();
|
||||
const int num_unrolled = OMCache::CAPACITY;
|
||||
for (int i = 0; i < num_unrolled; i++) {
|
||||
ld(tmp1, Address(tmp3_t));
|
||||
beq(obj, tmp1, monitor_found);
|
||||
add(tmp3_t, tmp3_t, in_bytes(OMCache::oop_to_oop_difference()));
|
||||
ld(tmp1_monitor, Address(xthread, cache_offset + monitor_offset));
|
||||
ld(tmp4, Address(xthread, cache_offset));
|
||||
beq(obj, tmp4, monitor_found);
|
||||
cache_offset = cache_offset + OMCache::oop_to_oop_difference();
|
||||
}
|
||||
|
||||
Label loop;
|
||||
// Look for the monitor in the table.
|
||||
|
||||
// Search for obj in cache.
|
||||
bind(loop);
|
||||
// Get the hash code.
|
||||
srli(tmp2_hash, tmp2_hash, markWord::hash_shift);
|
||||
|
||||
// Check for match.
|
||||
ld(tmp1, Address(tmp3_t));
|
||||
beq(obj, tmp1, monitor_found);
|
||||
// Get the table and calculate the bucket's address.
|
||||
la(tmp3_t, ExternalAddress(ObjectMonitorTable::current_table_address()));
|
||||
ld(tmp3_t, Address(tmp3_t));
|
||||
ld(tmp1, Address(tmp3_t, ObjectMonitorTable::table_capacity_mask_offset()));
|
||||
andr(tmp2_hash, tmp2_hash, tmp1);
|
||||
ld(tmp3_t, Address(tmp3_t, ObjectMonitorTable::table_buckets_offset()));
|
||||
|
||||
// Search until null encountered, guaranteed _null_sentinel at end.
|
||||
add(tmp3_t, tmp3_t, in_bytes(OMCache::oop_to_oop_difference()));
|
||||
bnez(tmp1, loop);
|
||||
// Cache Miss. Take the slowpath.
|
||||
j(slow_path);
|
||||
// Read the monitor from the bucket.
|
||||
shadd(tmp3_bucket, tmp2_hash, tmp3_t, tmp4, LogBytesPerWord);
|
||||
ld(tmp1_monitor, Address(tmp3_bucket));
|
||||
|
||||
// Check if the monitor in the bucket is special (empty, tombstone or removed).
|
||||
mv(tmp2, ObjectMonitorTable::SpecialPointerValues::below_is_special);
|
||||
bltu(tmp1_monitor, tmp2, slow_path);
|
||||
|
||||
// Check if object matches.
|
||||
ld(tmp3, Address(tmp1_monitor, ObjectMonitor::object_offset()));
|
||||
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||
bs_asm->try_resolve_weak_handle_in_c2(this, tmp3, tmp2, slow_path);
|
||||
bne(tmp3, obj, slow_path);
|
||||
|
||||
bind(monitor_found);
|
||||
ld(tmp1_monitor, Address(tmp3_t, OMCache::oop_to_monitor_difference()));
|
||||
}
|
||||
|
||||
const Register tmp2_owner_addr = tmp2;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -369,6 +369,11 @@ OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Na
|
||||
return opto_reg;
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) {
|
||||
// Load the oop from the weak handle.
|
||||
__ ld(obj, Address(obj));
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ _masm->
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -110,6 +110,8 @@ public:
|
||||
#ifdef COMPILER2
|
||||
OptoReg::Name refine_register(const Node* node,
|
||||
OptoReg::Name opto_reg);
|
||||
virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj,
|
||||
Register tmp, Label& slow_path);
|
||||
#endif // COMPILER2
|
||||
};
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2020, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -461,6 +462,30 @@ void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler *masm, Register obj,
|
||||
Register tmp, Label& slow_path) {
|
||||
assert_different_registers(obj, tmp);
|
||||
|
||||
Label done;
|
||||
|
||||
// Resolve weak handle using the standard implementation.
|
||||
BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path);
|
||||
|
||||
// Check if the reference is null, and if it is, take the fast path.
|
||||
__ beqz(obj, done);
|
||||
|
||||
Address gc_state(xthread, ShenandoahThreadLocalData::gc_state_offset());
|
||||
__ lbu(tmp, gc_state);
|
||||
|
||||
// Check if the heap is under weak-reference/roots processing, in
|
||||
// which case we need to take the slow path.
|
||||
__ test_bit(tmp, tmp, ShenandoahHeap::WEAK_ROOTS_BITPOS);
|
||||
__ bnez(tmp, slow_path);
|
||||
__ bind(done);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Special Shenandoah CAS implementation that handles false negatives due
|
||||
// to concurrent evacuation. The service is more complex than a
|
||||
// traditional CAS operation because the CAS operation is intended to
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -84,7 +85,9 @@ public:
|
||||
|
||||
virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
|
||||
Register obj, Register tmp, Label& slowpath);
|
||||
|
||||
#ifdef COMPILER2
|
||||
virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path);
|
||||
#endif
|
||||
void cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val,
|
||||
Assembler::Aqrl acquire, Assembler::Aqrl release, bool is_cae, Register result);
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -602,6 +602,27 @@ void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm,
|
||||
BLOCK_COMMENT("} ZBarrierSetAssembler::try_resolve_jobject_in_native");
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
void ZBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) {
|
||||
BLOCK_COMMENT("ZBarrierSetAssembler::try_resolve_weak_handle_in_c2 {");
|
||||
|
||||
// Resolve weak handle using the standard implementation.
|
||||
BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, tmp, slow_path);
|
||||
|
||||
// Check if the oop is bad, in which case we need to take the slow path.
|
||||
__ relocate(barrier_Relocation::spec(), [&] {
|
||||
__ li16u(tmp, barrier_Relocation::unpatched);
|
||||
}, ZBarrierRelocationFormatMarkBadMask);
|
||||
__ andr(tmp, obj, tmp);
|
||||
__ bnez(tmp, slow_path);
|
||||
|
||||
// Oop is okay, so we uncolor it.
|
||||
__ srli(obj, obj, ZPointerLoadShift);
|
||||
|
||||
BLOCK_COMMENT("} ZBarrierSetAssembler::try_resolve_weak_handle_in_c2");
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint16_t patch_barrier_relocation_value(int format) {
|
||||
switch (format) {
|
||||
case ZBarrierRelocationFormatLoadBadMask:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -170,6 +170,10 @@ public:
|
||||
ZLoadBarrierStubC2* stub) const;
|
||||
void generate_c2_store_barrier_stub(MacroAssembler* masm,
|
||||
ZStoreBarrierStubC2* stub) const;
|
||||
void try_resolve_weak_handle_in_c2(MacroAssembler* masm,
|
||||
Register obj,
|
||||
Register tmp,
|
||||
Label& slow_path);
|
||||
#endif // COMPILER2
|
||||
|
||||
void check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& error);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -39,7 +39,7 @@ define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap nulls
|
||||
define_pd_global(bool, DelayCompilerStubsGeneration, COMPILER2_OR_JVMCI);
|
||||
|
||||
define_pd_global(size_t, CodeCacheSegmentSize, 64 COMPILER1_AND_COMPILER2_PRESENT(+64)); // Tiered compilation has large code-entry alignment.
|
||||
define_pd_global(intx, CodeEntryAlignment, 64);
|
||||
define_pd_global(uint, CodeEntryAlignment, 64);
|
||||
define_pd_global(intx, OptoLoopAlignment, 16);
|
||||
|
||||
#define DEFAULT_STACK_YELLOW_PAGES (2)
|
||||
|
||||
@ -237,15 +237,14 @@ void InterpreterMacroAssembler::load_resolved_klass_at_offset(
|
||||
// Rsub_klass: subklass
|
||||
//
|
||||
// Kills:
|
||||
// x12, x15
|
||||
// x12
|
||||
void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
|
||||
Label& ok_is_subtype) {
|
||||
assert(Rsub_klass != x10, "x10 holds superklass");
|
||||
assert(Rsub_klass != x12, "x12 holds 2ndary super array length");
|
||||
assert(Rsub_klass != x15, "x15 holds 2ndary super array scan ptr");
|
||||
|
||||
// Profile the not-null value's klass.
|
||||
profile_typecheck(x12, Rsub_klass, x15); // blows x12, reloads x15
|
||||
profile_typecheck(x12, Rsub_klass); // blows x12
|
||||
|
||||
// Do the check.
|
||||
check_klass_subtype(Rsub_klass, x10, x12, ok_is_subtype); // blows x12
|
||||
@ -1042,7 +1041,6 @@ void InterpreterMacroAssembler::profile_final_call(Register mdp) {
|
||||
|
||||
void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
|
||||
Register mdp,
|
||||
Register reg2,
|
||||
bool receiver_can_be_null) {
|
||||
if (ProfileInterpreter) {
|
||||
Label profile_continue;
|
||||
@ -1060,7 +1058,7 @@ void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
|
||||
}
|
||||
|
||||
// Record the receiver type.
|
||||
record_klass_in_profile(receiver, mdp, reg2);
|
||||
profile_receiver_type(receiver, mdp, 0);
|
||||
bind(skip_receiver_profile);
|
||||
|
||||
// The method data pointer needs to be updated to reflect the new target.
|
||||
@ -1072,153 +1070,6 @@ void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
|
||||
}
|
||||
}
|
||||
|
||||
// This routine creates a state machine for updating the multi-row
|
||||
// type profile at a virtual call site (or other type-sensitive bytecode).
|
||||
// The machine visits each row (of receiver/count) until the receiver type
|
||||
// is found, or until it runs out of rows. At the same time, it remembers
|
||||
// the location of the first empty row. (An empty row records null for its
|
||||
// receiver, and can be allocated for a newly-observed receiver type.)
|
||||
// Because there are two degrees of freedom in the state, a simple linear
|
||||
// search will not work; it must be a decision tree. Hence this helper
|
||||
// function is recursive, to generate the required tree structured code.
|
||||
// It's the interpreter, so we are trading off code space for speed.
|
||||
// See below for example code.
|
||||
void InterpreterMacroAssembler::record_klass_in_profile_helper(
|
||||
Register receiver, Register mdp,
|
||||
Register reg2, Label& done) {
|
||||
if (TypeProfileWidth == 0) {
|
||||
increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
|
||||
} else {
|
||||
record_item_in_profile_helper(receiver, mdp, reg2, 0, done, TypeProfileWidth,
|
||||
&VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset);
|
||||
}
|
||||
}
|
||||
|
||||
void InterpreterMacroAssembler::record_item_in_profile_helper(Register item, Register mdp,
|
||||
Register reg2, int start_row, Label& done, int total_rows,
|
||||
OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn) {
|
||||
int last_row = total_rows - 1;
|
||||
assert(start_row <= last_row, "must be work left to do");
|
||||
// Test this row for both the item and for null.
|
||||
// Take any of three different outcomes:
|
||||
// 1. found item => increment count and goto done
|
||||
// 2. found null => keep looking for case 1, maybe allocate this cell
|
||||
// 3. found something else => keep looking for cases 1 and 2
|
||||
// Case 3 is handled by a recursive call.
|
||||
for (int row = start_row; row <= last_row; row++) {
|
||||
Label next_test;
|
||||
bool test_for_null_also = (row == start_row);
|
||||
|
||||
// See if the item is item[n].
|
||||
int item_offset = in_bytes(item_offset_fn(row));
|
||||
test_mdp_data_at(mdp, item_offset, item,
|
||||
(test_for_null_also ? reg2 : noreg),
|
||||
next_test);
|
||||
// (Reg2 now contains the item from the CallData.)
|
||||
|
||||
// The item is item[n]. Increment count[n].
|
||||
int count_offset = in_bytes(item_count_offset_fn(row));
|
||||
increment_mdp_data_at(mdp, count_offset);
|
||||
j(done);
|
||||
bind(next_test);
|
||||
|
||||
if (test_for_null_also) {
|
||||
Label found_null;
|
||||
// Failed the equality check on item[n]... Test for null.
|
||||
if (start_row == last_row) {
|
||||
// The only thing left to do is handle the null case.
|
||||
beqz(reg2, found_null);
|
||||
// Item did not match any saved item and there is no empty row for it.
|
||||
// Increment total counter to indicate polymorphic case.
|
||||
increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
|
||||
j(done);
|
||||
bind(found_null);
|
||||
break;
|
||||
}
|
||||
// Since null is rare, make it be the branch-taken case.
|
||||
beqz(reg2, found_null);
|
||||
|
||||
// Put all the "Case 3" tests here.
|
||||
record_item_in_profile_helper(item, mdp, reg2, start_row + 1, done, total_rows,
|
||||
item_offset_fn, item_count_offset_fn);
|
||||
|
||||
// Found a null. Keep searching for a matching item,
|
||||
// but remember that this is an empty (unused) slot.
|
||||
bind(found_null);
|
||||
}
|
||||
}
|
||||
|
||||
// In the fall-through case, we found no matching item, but we
|
||||
// observed the item[start_row] is null.
|
||||
// Fill in the item field and increment the count.
|
||||
int item_offset = in_bytes(item_offset_fn(start_row));
|
||||
set_mdp_data_at(mdp, item_offset, item);
|
||||
int count_offset = in_bytes(item_count_offset_fn(start_row));
|
||||
mv(reg2, DataLayout::counter_increment);
|
||||
set_mdp_data_at(mdp, count_offset, reg2);
|
||||
if (start_row > 0) {
|
||||
j(done);
|
||||
}
|
||||
}
|
||||
|
||||
// Example state machine code for three profile rows:
|
||||
// # main copy of decision tree, rooted at row[1]
|
||||
// if (row[0].rec == rec) then [
|
||||
// row[0].incr()
|
||||
// goto done
|
||||
// ]
|
||||
// if (row[0].rec != nullptr) then [
|
||||
// # inner copy of decision tree, rooted at row[1]
|
||||
// if (row[1].rec == rec) then [
|
||||
// row[1].incr()
|
||||
// goto done
|
||||
// ]
|
||||
// if (row[1].rec != nullptr) then [
|
||||
// # degenerate decision tree, rooted at row[2]
|
||||
// if (row[2].rec == rec) then [
|
||||
// row[2].incr()
|
||||
// goto done
|
||||
// ]
|
||||
// if (row[2].rec != nullptr) then [
|
||||
// count.incr()
|
||||
// goto done
|
||||
// ] # overflow
|
||||
// row[2].init(rec)
|
||||
// goto done
|
||||
// ] else [
|
||||
// # remember row[1] is empty
|
||||
// if (row[2].rec == rec) then [
|
||||
// row[2].incr()
|
||||
// goto done
|
||||
// ]
|
||||
// row[1].init(rec)
|
||||
// goto done
|
||||
// ]
|
||||
// else [
|
||||
// # remember row[0] is empty
|
||||
// if (row[1].rec == rec) then [
|
||||
// row[1].incr()
|
||||
// goto done
|
||||
// ]
|
||||
// if (row[2].rec == rec) then [
|
||||
// row[2].incr()
|
||||
// goto done
|
||||
// ]
|
||||
// row[0].init(rec)
|
||||
// goto done
|
||||
// ]
|
||||
// done:
|
||||
|
||||
void InterpreterMacroAssembler::record_klass_in_profile(Register receiver,
|
||||
Register mdp, Register reg2) {
|
||||
assert(ProfileInterpreter, "must be profiling");
|
||||
Label done;
|
||||
|
||||
record_klass_in_profile_helper(receiver, mdp, reg2, done);
|
||||
|
||||
bind(done);
|
||||
}
|
||||
|
||||
void InterpreterMacroAssembler::profile_ret(Register return_bci, Register mdp) {
|
||||
if (ProfileInterpreter) {
|
||||
Label profile_continue;
|
||||
@ -1274,7 +1125,7 @@ void InterpreterMacroAssembler::profile_null_seen(Register mdp) {
|
||||
}
|
||||
}
|
||||
|
||||
void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) {
|
||||
void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass) {
|
||||
if (ProfileInterpreter) {
|
||||
Label profile_continue;
|
||||
|
||||
@ -1287,7 +1138,7 @@ void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass,
|
||||
mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size());
|
||||
|
||||
// Record the object type.
|
||||
record_klass_in_profile(klass, mdp, reg2);
|
||||
profile_receiver_type(klass, mdp, 0);
|
||||
}
|
||||
update_mdp_by_constant(mdp, mdp_delta);
|
||||
|
||||
|
||||
@ -262,14 +262,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||
Register test_value_out,
|
||||
Label& not_equal_continue);
|
||||
|
||||
void record_klass_in_profile(Register receiver, Register mdp,
|
||||
Register reg2);
|
||||
void record_klass_in_profile_helper(Register receiver, Register mdp,
|
||||
Register reg2, Label& done);
|
||||
void record_item_in_profile_helper(Register item, Register mdp,
|
||||
Register reg2, int start_row, Label& done, int total_rows,
|
||||
OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn);
|
||||
|
||||
void update_mdp_by_offset(Register mdp_in, int offset_of_offset);
|
||||
void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp);
|
||||
void update_mdp_by_constant(Register mdp_in, int constant);
|
||||
@ -283,11 +275,10 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||
void profile_call(Register mdp);
|
||||
void profile_final_call(Register mdp);
|
||||
void profile_virtual_call(Register receiver, Register mdp,
|
||||
Register t1,
|
||||
bool receiver_can_be_null = false);
|
||||
void profile_ret(Register return_bci, Register mdp);
|
||||
void profile_null_seen(Register mdp);
|
||||
void profile_typecheck(Register mdp, Register klass, Register temp);
|
||||
void profile_typecheck(Register mdp, Register klass);
|
||||
void profile_typecheck_failed(Register mdp);
|
||||
void profile_switch_default(Register mdp);
|
||||
void profile_switch_case(Register index_in_scratch, Register mdp,
|
||||
|
||||
@ -543,6 +543,160 @@ void MacroAssembler::_verify_oop(Register reg, const char* s, const char* file,
|
||||
BLOCK_COMMENT("} verify_oop");
|
||||
}
|
||||
|
||||
// Handle the receiver type profile update given the "recv" klass.
|
||||
//
|
||||
// Normally updates the ReceiverData (RD) that starts at "mdp" + "mdp_offset".
|
||||
// If there are no matching or claimable receiver entries in RD, updates
|
||||
// the polymorphic counter.
|
||||
//
|
||||
// This code expected to run by either the interpreter or JIT-ed code, without
|
||||
// extra synchronization. For safety, receiver cells are claimed atomically, which
|
||||
// avoids grossly misrepresenting the profiles under concurrent updates. For speed,
|
||||
// counter updates are not atomic.
|
||||
//
|
||||
void MacroAssembler::profile_receiver_type(Register recv, Register mdp, int mdp_offset) {
|
||||
assert_different_registers(recv, mdp, t0, t1);
|
||||
|
||||
int base_receiver_offset = in_bytes(ReceiverTypeData::receiver_offset(0));
|
||||
int end_receiver_offset = in_bytes(ReceiverTypeData::receiver_offset(ReceiverTypeData::row_limit()));
|
||||
int poly_count_offset = in_bytes(CounterData::count_offset());
|
||||
int receiver_step = in_bytes(ReceiverTypeData::receiver_offset(1)) - base_receiver_offset;
|
||||
int receiver_to_count_step = in_bytes(ReceiverTypeData::receiver_count_offset(0)) - base_receiver_offset;
|
||||
|
||||
// Adjust for MDP offsets. Slots are pointer-sized, so is the global offset.
|
||||
base_receiver_offset += mdp_offset;
|
||||
end_receiver_offset += mdp_offset;
|
||||
poly_count_offset += mdp_offset;
|
||||
|
||||
#ifdef ASSERT
|
||||
// We are about to walk the MDO slots without asking for offsets.
|
||||
// Check that our math hits all the right spots.
|
||||
for (uint c = 0; c < ReceiverTypeData::row_limit(); c++) {
|
||||
int real_recv_offset = mdp_offset + in_bytes(ReceiverTypeData::receiver_offset(c));
|
||||
int real_count_offset = mdp_offset + in_bytes(ReceiverTypeData::receiver_count_offset(c));
|
||||
int offset = base_receiver_offset + receiver_step*c;
|
||||
int count_offset = offset + receiver_to_count_step;
|
||||
assert(offset == real_recv_offset, "receiver slot math");
|
||||
assert(count_offset == real_count_offset, "receiver count math");
|
||||
}
|
||||
int real_poly_count_offset = mdp_offset + in_bytes(CounterData::count_offset());
|
||||
assert(poly_count_offset == real_poly_count_offset, "poly counter math");
|
||||
#endif
|
||||
|
||||
// Corner case: no profile table. Increment poly counter and exit.
|
||||
if (ReceiverTypeData::row_limit() == 0) {
|
||||
increment(Address(mdp, poly_count_offset), DataLayout::counter_increment);
|
||||
return;
|
||||
}
|
||||
|
||||
Register offset = t1;
|
||||
|
||||
Label L_loop_search_receiver, L_loop_search_empty;
|
||||
Label L_restart, L_found_recv, L_found_empty, L_polymorphic, L_count_update;
|
||||
|
||||
// The code here recognizes three major cases:
|
||||
// A. Fastest: receiver found in the table
|
||||
// B. Fast: no receiver in the table, and the table is full
|
||||
// C. Slow: no receiver in the table, free slots in the table
|
||||
//
|
||||
// The case A performance is most important, as perfectly-behaved code would end up
|
||||
// there, especially with larger TypeProfileWidth. The case B performance is
|
||||
// important as well, this is where bulk of code would land for normally megamorphic
|
||||
// cases. The case C performance is not essential, its job is to deal with installation
|
||||
// races, we optimize for code density instead. Case C needs to make sure that receiver
|
||||
// rows are only claimed once. This makes sure we never overwrite a row for another
|
||||
// receiver and never duplicate the receivers in the list, making profile type-accurate.
|
||||
//
|
||||
// It is very tempting to handle these cases in a single loop, and claim the first slot
|
||||
// without checking the rest of the table. But, profiling code should tolerate free slots
|
||||
// in the table, as class unloading can clear them. After such cleanup, the receiver
|
||||
// we need might be _after_ the free slot. Therefore, we need to let at least full scan
|
||||
// to complete, before trying to install new slots. Splitting the code in several tight
|
||||
// loops also helpfully optimizes for cases A and B.
|
||||
//
|
||||
// This code is effectively:
|
||||
//
|
||||
// restart:
|
||||
// // Fastest: receiver is already installed
|
||||
// for (i = 0; i < receiver_count(); i++) {
|
||||
// if (receiver(i) == recv) goto found_recv(i);
|
||||
// }
|
||||
//
|
||||
// // Fast: no receiver, but profile is full
|
||||
// for (i = 0; i < receiver_count(); i++) {
|
||||
// if (receiver(i) == null) goto found_null(i);
|
||||
// }
|
||||
// goto polymorphic
|
||||
//
|
||||
// // Slow: try to install receiver
|
||||
// found_null(i):
|
||||
// CAS(&receiver(i), null, recv);
|
||||
// goto restart
|
||||
//
|
||||
// polymorphic:
|
||||
// count++;
|
||||
// return
|
||||
//
|
||||
// found_recv(i):
|
||||
// *receiver_count(i)++
|
||||
//
|
||||
|
||||
bind(L_restart);
|
||||
|
||||
// Fastest: receiver is already installed
|
||||
mv(offset, base_receiver_offset);
|
||||
bind(L_loop_search_receiver);
|
||||
add(t0, mdp, offset);
|
||||
ld(t0, Address(t0));
|
||||
beq(recv, t0, L_found_recv);
|
||||
add(offset, offset, receiver_step);
|
||||
sub(t0, offset, end_receiver_offset);
|
||||
bnez(t0, L_loop_search_receiver);
|
||||
|
||||
// Fast: no receiver, but profile is full
|
||||
mv(offset, base_receiver_offset);
|
||||
bind(L_loop_search_empty);
|
||||
add(t0, mdp, offset);
|
||||
ld(t0, Address(t0));
|
||||
beqz(t0, L_found_empty);
|
||||
add(offset, offset, receiver_step);
|
||||
sub(t0, offset, end_receiver_offset);
|
||||
bnez(t0, L_loop_search_empty);
|
||||
j(L_polymorphic);
|
||||
|
||||
// Slow: try to install receiver
|
||||
bind(L_found_empty);
|
||||
|
||||
// Atomically swing receiver slot: null -> recv.
|
||||
//
|
||||
// The update uses CAS, which clobbers t0. Therefore, t1
|
||||
// is used to hold the destination address. This is safe because the
|
||||
// offset is no longer needed after the address is computed.
|
||||
add(t1, mdp, offset);
|
||||
weak_cmpxchg(/*addr*/ t1, /*expected*/ zr, /*new*/ recv, Assembler::int64,
|
||||
/*acquire*/ Assembler::relaxed, /*release*/ Assembler::relaxed, /*result*/ t0);
|
||||
|
||||
// CAS success means the slot now has the receiver we want. CAS failure means
|
||||
// something had claimed the slot concurrently: it can be the same receiver we want,
|
||||
// or something else. Since this is a slow path, we can optimize for code density,
|
||||
// and just restart the search from the beginning.
|
||||
j(L_restart);
|
||||
|
||||
// Counter updates:
|
||||
// Increment polymorphic counter instead of receiver slot.
|
||||
bind(L_polymorphic);
|
||||
mv(offset, poly_count_offset);
|
||||
j(L_count_update);
|
||||
|
||||
// Found a receiver, convert its slot offset to corresponding count offset.
|
||||
bind(L_found_recv);
|
||||
add(offset, offset, receiver_to_count_step);
|
||||
|
||||
bind(L_count_update);
|
||||
add(t1, mdp, offset);
|
||||
increment(Address(t1), DataLayout::counter_increment);
|
||||
}
|
||||
|
||||
void MacroAssembler::_verify_oop_addr(Address addr, const char* s, const char* file, int line) {
|
||||
if (!VerifyOops) {
|
||||
return;
|
||||
|
||||
@ -390,6 +390,8 @@ class MacroAssembler: public Assembler {
|
||||
|
||||
Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0);
|
||||
|
||||
void profile_receiver_type(Register recv, Register mdp, int mdp_offset);
|
||||
|
||||
// only if +VerifyOops
|
||||
void _verify_oop(Register reg, const char* s, const char* file, int line);
|
||||
void _verify_oop_addr(Address addr, const char* s, const char* file, int line);
|
||||
|
||||
@ -3279,7 +3279,7 @@ void TemplateTable::invokevirtual_helper(Register index,
|
||||
__ load_klass(x10, recv);
|
||||
|
||||
// profile this call
|
||||
__ profile_virtual_call(x10, xlocals, x13);
|
||||
__ profile_virtual_call(x10, xlocals);
|
||||
|
||||
// get target Method & entry point
|
||||
__ lookup_virtual_method(x10, index, method);
|
||||
@ -3406,7 +3406,7 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
/*return_method=*/false);
|
||||
|
||||
// profile this call
|
||||
__ profile_virtual_call(x13, x30, x9);
|
||||
__ profile_virtual_call(x13, x30);
|
||||
|
||||
// Get declaring interface class from method, and itable index
|
||||
__ load_method_holder(x10, xmethod);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2018 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -44,7 +44,7 @@ define_pd_global(intx, CompileThreshold, 10000);
|
||||
|
||||
define_pd_global(intx, OnStackReplacePercentage, 140);
|
||||
define_pd_global(intx, ConditionalMoveLimit, 4);
|
||||
define_pd_global(intx, FreqInlineSize, 175);
|
||||
define_pd_global(intx, FreqInlineSize, 325);
|
||||
define_pd_global(intx, InteriorEntryAlignment, 4);
|
||||
define_pd_global(size_t, NewSizeThreadIncrease, ScaleForWordSize(4*K));
|
||||
define_pd_global(intx, RegisterCostAreaRatio, 12000);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2019 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -29,9 +29,6 @@
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#ifdef COMPILER2
|
||||
#include "opto/matcher.hpp"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@ -39,7 +36,6 @@
|
||||
#define __ masm->
|
||||
|
||||
address CompiledDirectCall::emit_to_interp_stub(MacroAssembler *masm, address mark/* = nullptr*/) {
|
||||
#ifdef COMPILER2
|
||||
// Stub is fixed up when the corresponding call is converted from calling
|
||||
// compiled code to calling interpreted code.
|
||||
if (mark == nullptr) {
|
||||
@ -55,7 +51,7 @@ address CompiledDirectCall::emit_to_interp_stub(MacroAssembler *masm, address ma
|
||||
__ relocate(static_stub_Relocation::spec(mark));
|
||||
|
||||
AddressLiteral meta = __ allocate_metadata_address(nullptr);
|
||||
bool success = __ load_const_from_toc(as_Register(Matcher::inline_cache_reg_encode()), meta);
|
||||
bool success = __ load_const_from_toc(Z_inline_cache, meta);
|
||||
|
||||
__ set_inst_mark();
|
||||
AddressLiteral a((address)-1);
|
||||
@ -67,10 +63,6 @@ address CompiledDirectCall::emit_to_interp_stub(MacroAssembler *masm, address ma
|
||||
__ z_br(Z_R1);
|
||||
__ end_a_stub(); // Update current stubs pointer and restore insts_end.
|
||||
return stub;
|
||||
#else
|
||||
ShouldNotReachHere();
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2024 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -129,6 +129,57 @@ void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* mas
|
||||
}
|
||||
}
|
||||
|
||||
static void generate_post_barrier(MacroAssembler* masm,
|
||||
const Register store_addr,
|
||||
const Register new_val,
|
||||
const Register thread,
|
||||
const Register tmp1,
|
||||
const Register tmp2,
|
||||
Label& done,
|
||||
bool new_val_may_be_null) {
|
||||
|
||||
__ block_comment("generate_post_barrier {");
|
||||
|
||||
assert(thread == Z_thread, "must be");
|
||||
assert_different_registers(store_addr, new_val, thread, tmp1, tmp2, noreg);
|
||||
|
||||
// Does store cross heap regions?
|
||||
if (VM_Version::has_DistinctOpnds()) {
|
||||
__ z_xgrk(tmp1, store_addr, new_val); // tmp1 := store address ^ new value
|
||||
} else {
|
||||
__ z_lgr(tmp1, store_addr);
|
||||
__ z_xgr(tmp1, new_val);
|
||||
}
|
||||
__ z_srag(tmp1, tmp1, G1HeapRegion::LogOfHRGrainBytes); // tmp1 := ((store address ^ new value) >> LogOfHRGrainBytes)
|
||||
__ branch_optimized(Assembler::bcondEqual, done);
|
||||
|
||||
// Crosses regions, storing null?
|
||||
if (new_val_may_be_null) {
|
||||
__ z_ltgr(new_val, new_val);
|
||||
__ z_bre(done);
|
||||
} else {
|
||||
#ifdef ASSERT
|
||||
__ z_ltgr(new_val, new_val);
|
||||
__ asm_assert(Assembler::bcondNotZero, "null oop not allowed (G1 post)", 0x322); // Checked by caller.
|
||||
#endif
|
||||
}
|
||||
|
||||
__ z_srag(tmp1, store_addr, CardTable::card_shift());
|
||||
|
||||
Address card_table_addr(thread, in_bytes(G1ThreadLocalData::card_table_base_offset()));
|
||||
__ z_alg(tmp1, card_table_addr); // tmp1 := card address
|
||||
|
||||
if(UseCondCardMark) {
|
||||
__ z_cli(0, tmp1, G1CardTable::clean_card_val());
|
||||
__ branch_optimized(Assembler::bcondNotEqual, done);
|
||||
}
|
||||
|
||||
static_assert(G1CardTable::dirty_card_val() == 0, "must be to use z_mvi");
|
||||
__ z_mvi(0, tmp1, G1CardTable::dirty_card_val()); // *(card address) := dirty_card_val
|
||||
|
||||
__ block_comment("} generate_post_barrier");
|
||||
}
|
||||
|
||||
#if defined(COMPILER2)
|
||||
|
||||
#undef __
|
||||
@ -204,57 +255,6 @@ void G1BarrierSetAssembler::generate_c2_pre_barrier_stub(MacroAssembler* masm,
|
||||
BLOCK_COMMENT("} generate_c2_pre_barrier_stub");
|
||||
}
|
||||
|
||||
static void generate_post_barrier(MacroAssembler* masm,
|
||||
const Register store_addr,
|
||||
const Register new_val,
|
||||
const Register thread,
|
||||
const Register tmp1,
|
||||
const Register tmp2,
|
||||
Label& done,
|
||||
bool new_val_may_be_null) {
|
||||
|
||||
__ block_comment("generate_post_barrier {");
|
||||
|
||||
assert(thread == Z_thread, "must be");
|
||||
assert_different_registers(store_addr, new_val, thread, tmp1, tmp2, noreg);
|
||||
|
||||
// Does store cross heap regions?
|
||||
if (VM_Version::has_DistinctOpnds()) {
|
||||
__ z_xgrk(tmp1, store_addr, new_val); // tmp1 := store address ^ new value
|
||||
} else {
|
||||
__ z_lgr(tmp1, store_addr);
|
||||
__ z_xgr(tmp1, new_val);
|
||||
}
|
||||
__ z_srag(tmp1, tmp1, G1HeapRegion::LogOfHRGrainBytes); // tmp1 := ((store address ^ new value) >> LogOfHRGrainBytes)
|
||||
__ branch_optimized(Assembler::bcondEqual, done);
|
||||
|
||||
// Crosses regions, storing null?
|
||||
if (new_val_may_be_null) {
|
||||
__ z_ltgr(new_val, new_val);
|
||||
__ z_bre(done);
|
||||
} else {
|
||||
#ifdef ASSERT
|
||||
__ z_ltgr(new_val, new_val);
|
||||
__ asm_assert(Assembler::bcondNotZero, "null oop not allowed (G1 post)", 0x322); // Checked by caller.
|
||||
#endif
|
||||
}
|
||||
|
||||
__ z_srag(tmp1, store_addr, CardTable::card_shift());
|
||||
|
||||
Address card_table_addr(thread, in_bytes(G1ThreadLocalData::card_table_base_offset()));
|
||||
__ z_alg(tmp1, card_table_addr); // tmp1 := card address
|
||||
|
||||
if(UseCondCardMark) {
|
||||
__ z_cli(0, tmp1, G1CardTable::clean_card_val());
|
||||
__ branch_optimized(Assembler::bcondNotEqual, done);
|
||||
}
|
||||
|
||||
static_assert(G1CardTable::dirty_card_val() == 0, "must be to use z_mvi");
|
||||
__ z_mvi(0, tmp1, G1CardTable::dirty_card_val()); // *(card address) := dirty_card_val
|
||||
|
||||
__ block_comment("} generate_post_barrier");
|
||||
}
|
||||
|
||||
void G1BarrierSetAssembler::g1_write_barrier_post_c2(MacroAssembler* masm,
|
||||
Register store_addr,
|
||||
Register new_val,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -206,6 +206,11 @@ OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Na
|
||||
return opto_reg;
|
||||
}
|
||||
|
||||
void BarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Register tmp, Label& slow_path) {
|
||||
// Load the oop from the weak handle.
|
||||
__ z_lg(obj, Address(obj));
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ _masm->
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -65,6 +65,8 @@ public:
|
||||
#ifdef COMPILER2
|
||||
OptoReg::Name refine_register(const Node* node,
|
||||
OptoReg::Name opto_reg) const;
|
||||
virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj,
|
||||
Register tmp, Label& slow_path);
|
||||
#endif // COMPILER2
|
||||
|
||||
static const int OFFSET_TO_PATCHABLE_DATA_INSTRUCTION = 6 + 6 + 6; // iihf(6) + iilf(6) + lg(6)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2018 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -43,7 +43,7 @@ define_pd_global(size_t, CodeCacheSegmentSize, 256);
|
||||
// Ideally, this is 256 (cache line size). This keeps code end data
|
||||
// on separate lines. But we reduced it to 64 since 256 increased
|
||||
// code size significantly by padding nops between IVC and second UEP.
|
||||
define_pd_global(intx, CodeEntryAlignment, 64);
|
||||
define_pd_global(uint, CodeEntryAlignment, 64);
|
||||
define_pd_global(intx, OptoLoopAlignment, 2);
|
||||
define_pd_global(intx, InlineSmallCode, 2000);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2024 SAP SE. All rights reserved.
|
||||
* Copyright 2024 IBM Corporation. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -44,6 +44,7 @@
|
||||
#include "runtime/icache.hpp"
|
||||
#include "runtime/interfaceSupport.inline.hpp"
|
||||
#include "runtime/objectMonitor.hpp"
|
||||
#include "runtime/objectMonitorTable.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/safepoint.hpp"
|
||||
#include "runtime/safepointMechanism.hpp"
|
||||
@ -6372,45 +6373,55 @@ void MacroAssembler::compiler_fast_lock_object(Register obj, Register box, Regis
|
||||
if (!UseObjectMonitorTable) {
|
||||
assert(tmp1_monitor == mark, "should be the same here");
|
||||
} else {
|
||||
const Register tmp1_bucket = tmp1;
|
||||
const Register hash = Z_R0_scratch;
|
||||
NearLabel monitor_found;
|
||||
|
||||
// load cache address
|
||||
z_la(tmp1, Address(Z_thread, JavaThread::om_cache_oops_offset()));
|
||||
// Save the mark, we might need it to extract the hash.
|
||||
z_lgr(hash, mark);
|
||||
|
||||
const int num_unrolled = 2;
|
||||
// Look for the monitor in the om_cache.
|
||||
|
||||
ByteSize cache_offset = JavaThread::om_cache_oops_offset();
|
||||
ByteSize monitor_offset = OMCache::oop_to_monitor_difference();
|
||||
const int num_unrolled = OMCache::CAPACITY;
|
||||
for (int i = 0; i < num_unrolled; i++) {
|
||||
z_cg(obj, Address(tmp1));
|
||||
z_lg(tmp1_monitor, Address(Z_thread, cache_offset + monitor_offset));
|
||||
z_cg(obj, Address(Z_thread, cache_offset));
|
||||
z_bre(monitor_found);
|
||||
add2reg(tmp1, in_bytes(OMCache::oop_to_oop_difference()));
|
||||
cache_offset = cache_offset + OMCache::oop_to_oop_difference();
|
||||
}
|
||||
|
||||
NearLabel loop;
|
||||
// Search for obj in cache
|
||||
// Get the hash code.
|
||||
z_srlg(hash, hash, markWord::hash_shift);
|
||||
|
||||
bind(loop);
|
||||
// Get the table and calculate the bucket's address.
|
||||
load_const_optimized(tmp2, ObjectMonitorTable::current_table_address());
|
||||
z_lg(tmp2, Address(tmp2));
|
||||
z_ng(hash, Address(tmp2, ObjectMonitorTable::table_capacity_mask_offset()));
|
||||
z_lg(tmp1_bucket, Address(tmp2, ObjectMonitorTable::table_buckets_offset()));
|
||||
z_sllg(hash, hash, LogBytesPerWord);
|
||||
z_agr(tmp1_bucket, hash);
|
||||
|
||||
// check for match.
|
||||
z_cg(obj, Address(tmp1));
|
||||
z_bre(monitor_found);
|
||||
// Read the monitor from the bucket.
|
||||
z_lg(tmp1_monitor, Address(tmp1_bucket));
|
||||
|
||||
// search until null encountered, guaranteed _null_sentinel at end.
|
||||
add2reg(tmp1, in_bytes(OMCache::oop_to_oop_difference()));
|
||||
z_cghsi(0, tmp1, 0);
|
||||
z_brne(loop); // if not EQ to 0, go for another loop
|
||||
// Check if the monitor in the bucket is special (empty, tombstone or removed).
|
||||
z_clgfi(tmp1_monitor, ObjectMonitorTable::SpecialPointerValues::below_is_special);
|
||||
z_brl(slow_path);
|
||||
|
||||
// we reached to the end, cache miss
|
||||
z_ltgr(obj, obj); // set CC to NE
|
||||
z_bru(slow_path);
|
||||
// Check if object matches.
|
||||
z_lg(tmp2, Address(tmp1_monitor, ObjectMonitor::object_offset()));
|
||||
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||
bs_asm->try_resolve_weak_handle_in_c2(this, tmp2, Z_R0_scratch, slow_path);
|
||||
z_cgr(obj, tmp2);
|
||||
z_brne(slow_path);
|
||||
|
||||
// cache hit
|
||||
bind(monitor_found);
|
||||
z_lg(tmp1_monitor, Address(tmp1, OMCache::oop_to_monitor_difference()));
|
||||
}
|
||||
NearLabel monitor_locked;
|
||||
// lock the monitor
|
||||
|
||||
// mark contains the tagged ObjectMonitor*.
|
||||
const Register tagged_monitor = mark;
|
||||
const Register zero = tmp2;
|
||||
|
||||
const ByteSize monitor_tag = in_ByteSize(UseObjectMonitorTable ? 0 : checked_cast<int>(markWord::monitor_value));
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, 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
|
||||
@ -7320,6 +7320,25 @@ void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
|
||||
emit_int16(0x2E, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::vucomxsd(XMMRegister dst, Address src) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit);
|
||||
attributes.set_is_evex_instruction();
|
||||
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
|
||||
emit_int8(0x2E);
|
||||
emit_operand(dst, src, 0);
|
||||
}
|
||||
|
||||
void Assembler::vucomxsd(XMMRegister dst, XMMRegister src) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionAttr attributes(AVX_128bit, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
|
||||
emit_int16(0x2E, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::ucomiss(XMMRegister dst, Address src) {
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
@ -7335,6 +7354,25 @@ void Assembler::ucomiss(XMMRegister dst, XMMRegister src) {
|
||||
emit_int16(0x2E, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::vucomxss(XMMRegister dst, Address src) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit);
|
||||
attributes.set_is_evex_instruction();
|
||||
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
|
||||
emit_int8(0x2E);
|
||||
emit_operand(dst, src, 0);
|
||||
}
|
||||
|
||||
void Assembler::vucomxss(XMMRegister dst, XMMRegister src) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F, &attributes);
|
||||
emit_int16(0x2E, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::xabort(int8_t imm8) {
|
||||
emit_int24((unsigned char)0xC6, (unsigned char)0xF8, (imm8 & 0xFF));
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, 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
|
||||
@ -2331,10 +2331,14 @@ private:
|
||||
// Unordered Compare Scalar Double-Precision Floating-Point Values and set EFLAGS
|
||||
void ucomisd(XMMRegister dst, Address src);
|
||||
void ucomisd(XMMRegister dst, XMMRegister src);
|
||||
void vucomxsd(XMMRegister dst, Address src);
|
||||
void vucomxsd(XMMRegister dst, XMMRegister src);
|
||||
|
||||
// Unordered Compare Scalar Single-Precision Floating-Point Values and set EFLAGS
|
||||
void ucomiss(XMMRegister dst, Address src);
|
||||
void ucomiss(XMMRegister dst, XMMRegister src);
|
||||
void vucomxss(XMMRegister dst, Address src);
|
||||
void vucomxss(XMMRegister dst, XMMRegister src);
|
||||
|
||||
void xabort(int8_t imm8);
|
||||
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
#include "c1/c1_ValueStack.hpp"
|
||||
#include "ci/ciArrayKlass.hpp"
|
||||
#include "ci/ciInstance.hpp"
|
||||
#include "code/aotCodeCache.hpp"
|
||||
#include "compiler/oopMap.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "gc/shared/gc_globals.hpp"
|
||||
@ -535,6 +536,15 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod
|
||||
|
||||
case T_LONG: {
|
||||
assert(patch_code == lir_patch_none, "no patching handled here");
|
||||
#if INCLUDE_CDS
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
address b = c->as_pointer();
|
||||
if (AOTRuntimeConstants::contains(b)) {
|
||||
__ load_aotrc_address(dest->as_register_lo(), b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
__ movptr(dest->as_register_lo(), (intptr_t)c->as_jlong());
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -34,7 +34,9 @@
|
||||
#include "opto/subnode.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/objectMonitor.hpp"
|
||||
#include "runtime/objectMonitorTable.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "runtime/synchronizer.hpp"
|
||||
#include "utilities/checkedCast.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
@ -217,7 +219,6 @@ inline Assembler::AvxVectorLen C2_MacroAssembler::vector_length_encoding(int vle
|
||||
// In the case of failure, the node will branch directly to the
|
||||
// FailureLabel
|
||||
|
||||
|
||||
// obj: object to lock
|
||||
// box: on-stack box address -- KILLED
|
||||
// rax: tmp -- KILLED
|
||||
@ -286,7 +287,7 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register rax_reg,
|
||||
// After successful lock, push object on lock-stack.
|
||||
movptr(Address(thread, top), obj);
|
||||
addl(Address(thread, JavaThread::lock_stack_top_offset()), oopSize);
|
||||
jmpb(locked);
|
||||
jmp(locked);
|
||||
}
|
||||
|
||||
{ // Handle inflated monitor.
|
||||
@ -297,38 +298,49 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register rax_reg,
|
||||
if (!UseObjectMonitorTable) {
|
||||
assert(mark == monitor, "should be the same here");
|
||||
} else {
|
||||
// Uses ObjectMonitorTable. Look for the monitor in the om_cache.
|
||||
// Fetch ObjectMonitor* from the cache or take the slow-path.
|
||||
const Register hash = t;
|
||||
Label monitor_found;
|
||||
|
||||
// Load cache address
|
||||
lea(t, Address(thread, JavaThread::om_cache_oops_offset()));
|
||||
// Look for the monitor in the om_cache.
|
||||
|
||||
const int num_unrolled = 2;
|
||||
ByteSize cache_offset = JavaThread::om_cache_oops_offset();
|
||||
ByteSize monitor_offset = OMCache::oop_to_monitor_difference();
|
||||
const int num_unrolled = OMCache::CAPACITY;
|
||||
for (int i = 0; i < num_unrolled; i++) {
|
||||
cmpptr(obj, Address(t));
|
||||
movptr(monitor, Address(thread, cache_offset + monitor_offset));
|
||||
cmpptr(obj, Address(thread, cache_offset));
|
||||
jccb(Assembler::equal, monitor_found);
|
||||
increment(t, in_bytes(OMCache::oop_to_oop_difference()));
|
||||
cache_offset = cache_offset + OMCache::oop_to_oop_difference();
|
||||
}
|
||||
|
||||
Label loop;
|
||||
// Look for the monitor in the table.
|
||||
|
||||
// Search for obj in cache.
|
||||
bind(loop);
|
||||
// Get the hash code.
|
||||
movptr(hash, Address(obj, oopDesc::mark_offset_in_bytes()));
|
||||
shrq(hash, markWord::hash_shift);
|
||||
andq(hash, markWord::hash_mask);
|
||||
|
||||
// Check for match.
|
||||
cmpptr(obj, Address(t));
|
||||
jccb(Assembler::equal, monitor_found);
|
||||
// Get the table and calculate the bucket's address.
|
||||
lea(rax_reg, ExternalAddress(ObjectMonitorTable::current_table_address()));
|
||||
movptr(rax_reg, Address(rax_reg));
|
||||
andq(hash, Address(rax_reg, ObjectMonitorTable::table_capacity_mask_offset()));
|
||||
movptr(rax_reg, Address(rax_reg, ObjectMonitorTable::table_buckets_offset()));
|
||||
|
||||
// Search until null encountered, guaranteed _null_sentinel at end.
|
||||
cmpptr(Address(t), 1);
|
||||
jcc(Assembler::below, slow_path); // 0 check, but with ZF=0 when *t == 0
|
||||
increment(t, in_bytes(OMCache::oop_to_oop_difference()));
|
||||
jmpb(loop);
|
||||
// Read the monitor from the bucket.
|
||||
movptr(monitor, Address(rax_reg, hash, Address::times_ptr));
|
||||
|
||||
// Check if the monitor in the bucket is special (empty, tombstone or removed)
|
||||
cmpptr(monitor, ObjectMonitorTable::SpecialPointerValues::below_is_special);
|
||||
jcc(Assembler::below, slow_path);
|
||||
|
||||
// Check if object matches.
|
||||
movptr(rax_reg, Address(monitor, ObjectMonitor::object_offset()));
|
||||
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||
bs_asm->try_resolve_weak_handle_in_c2(this, rax_reg, slow_path);
|
||||
cmpptr(rax_reg, obj);
|
||||
jcc(Assembler::notEqual, slow_path);
|
||||
|
||||
// Cache hit.
|
||||
bind(monitor_found);
|
||||
movptr(monitor, Address(t, OMCache::oop_to_monitor_difference()));
|
||||
}
|
||||
const ByteSize monitor_tag = in_ByteSize(UseObjectMonitorTable ? 0 : checked_cast<int>(markWord::monitor_value));
|
||||
const Address recursions_address(monitor, ObjectMonitor::recursions_offset() - monitor_tag);
|
||||
@ -487,14 +499,14 @@ void C2_MacroAssembler::fast_unlock(Register obj, Register reg_rax, Register t,
|
||||
cmpl(top, in_bytes(JavaThread::lock_stack_base_offset()));
|
||||
jcc(Assembler::below, check_done);
|
||||
cmpptr(obj, Address(thread, top));
|
||||
jccb(Assembler::notEqual, inflated_check_lock_stack);
|
||||
jcc(Assembler::notEqual, inflated_check_lock_stack);
|
||||
stop("Fast Unlock lock on stack");
|
||||
bind(check_done);
|
||||
if (UseObjectMonitorTable) {
|
||||
movptr(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
|
||||
}
|
||||
testptr(mark, markWord::monitor_value);
|
||||
jccb(Assembler::notZero, inflated);
|
||||
jcc(Assembler::notZero, inflated);
|
||||
stop("Fast Unlock not monitor");
|
||||
#endif
|
||||
|
||||
@ -519,7 +531,7 @@ void C2_MacroAssembler::fast_unlock(Register obj, Register reg_rax, Register t,
|
||||
|
||||
// Check if recursive.
|
||||
cmpptr(recursions_address, 0);
|
||||
jccb(Assembler::notZero, recursive);
|
||||
jcc(Assembler::notZero, recursive);
|
||||
|
||||
// Set owner to null.
|
||||
// Release to satisfy the JMM
|
||||
@ -530,11 +542,11 @@ void C2_MacroAssembler::fast_unlock(Register obj, Register reg_rax, Register t,
|
||||
|
||||
// Check if the entry_list is empty.
|
||||
cmpptr(entry_list_address, NULL_WORD);
|
||||
jccb(Assembler::zero, unlocked); // If so we are done.
|
||||
jcc(Assembler::zero, unlocked); // If so we are done.
|
||||
|
||||
// Check if there is a successor.
|
||||
cmpptr(succ_address, NULL_WORD);
|
||||
jccb(Assembler::notZero, unlocked); // If so we are done.
|
||||
jcc(Assembler::notZero, unlocked); // If so we are done.
|
||||
|
||||
// Save the monitor pointer in the current thread, so we can try to
|
||||
// reacquire the lock in SharedRuntime::monitor_exit_helper().
|
||||
@ -1046,17 +1058,28 @@ void C2_MacroAssembler::signum_fp(int opcode, XMMRegister dst, XMMRegister zero,
|
||||
|
||||
Label DONE_LABEL;
|
||||
|
||||
// Handle special cases +0.0/-0.0 and NaN, if argument is +0.0/-0.0 or NaN, return argument
|
||||
// If AVX10.2 (or newer) floating point comparison instructions used, SF=1 for equal and unordered cases
|
||||
// If other floating point comparison instructions used, ZF=1 for equal and unordered cases
|
||||
if (opcode == Op_SignumF) {
|
||||
ucomiss(dst, zero);
|
||||
jcc(Assembler::equal, DONE_LABEL); // handle special case +0.0/-0.0, if argument is +0.0/-0.0, return argument
|
||||
jcc(Assembler::parity, DONE_LABEL); // handle special case NaN, if argument NaN, return NaN
|
||||
if (VM_Version::supports_avx10_2()) {
|
||||
vucomxss(dst, zero);
|
||||
jcc(Assembler::negative, DONE_LABEL);
|
||||
} else {
|
||||
ucomiss(dst, zero);
|
||||
jcc(Assembler::equal, DONE_LABEL);
|
||||
}
|
||||
movflt(dst, one);
|
||||
jcc(Assembler::above, DONE_LABEL);
|
||||
xorps(dst, ExternalAddress(StubRoutines::x86::vector_float_sign_flip()), noreg);
|
||||
} else if (opcode == Op_SignumD) {
|
||||
ucomisd(dst, zero);
|
||||
jcc(Assembler::equal, DONE_LABEL); // handle special case +0.0/-0.0, if argument is +0.0/-0.0, return argument
|
||||
jcc(Assembler::parity, DONE_LABEL); // handle special case NaN, if argument NaN, return NaN
|
||||
if (VM_Version::supports_avx10_2()) {
|
||||
vucomxsd(dst, zero);
|
||||
jcc(Assembler::negative, DONE_LABEL);
|
||||
} else {
|
||||
ucomisd(dst, zero);
|
||||
jcc(Assembler::equal, DONE_LABEL);
|
||||
}
|
||||
movdbl(dst, one);
|
||||
jcc(Assembler::above, DONE_LABEL);
|
||||
xorpd(dst, ExternalAddress(StubRoutines::x86::vector_double_sign_flip()), noreg);
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "asm/macroAssembler.inline.hpp"
|
||||
#include "code/aotCodeCache.hpp"
|
||||
#include "gc/g1/g1BarrierSet.hpp"
|
||||
#include "gc/g1/g1BarrierSetAssembler.hpp"
|
||||
#include "gc/g1/g1BarrierSetRuntime.hpp"
|
||||
@ -268,6 +269,16 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS
|
||||
// return a register that differs from reg1, reg2, reg3 and reg4
|
||||
|
||||
static Register pick_different_reg(Register reg1, Register reg2 = noreg, Register reg3= noreg, Register reg4 = noreg) {
|
||||
RegSet available = (RegSet::of(rscratch1, rscratch2, rax, rbx) + rdx -
|
||||
RegSet::of(reg1, reg2, reg3, reg4));
|
||||
return *(available.begin());
|
||||
}
|
||||
#endif // INCLUDE_CDS
|
||||
|
||||
static void generate_post_barrier(MacroAssembler* masm,
|
||||
const Register store_addr,
|
||||
const Register new_val,
|
||||
@ -280,10 +291,32 @@ static void generate_post_barrier(MacroAssembler* masm,
|
||||
|
||||
Label L_done;
|
||||
// Does store cross heap regions?
|
||||
__ movptr(tmp1, store_addr); // tmp1 := store address
|
||||
__ xorptr(tmp1, new_val); // tmp1 := store address ^ new value
|
||||
__ shrptr(tmp1, G1HeapRegion::LogOfHRGrainBytes); // ((store address ^ new value) >> LogOfHRGrainBytes) == 0?
|
||||
__ jccb(Assembler::equal, L_done);
|
||||
#if INCLUDE_CDS
|
||||
// AOT code needs to load the barrier grain shift from the aot
|
||||
// runtime constants area in the code cache otherwise we can compile
|
||||
// it as an immediate operand
|
||||
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
address grain_shift_addr = AOTRuntimeConstants::grain_shift_address();
|
||||
Register save = pick_different_reg(rcx, tmp1, new_val, store_addr);
|
||||
__ push(save);
|
||||
__ movptr(save, store_addr);
|
||||
__ xorptr(save, new_val);
|
||||
__ push(rcx);
|
||||
__ lea(rcx, ExternalAddress(grain_shift_addr));
|
||||
__ movl(rcx, Address(rcx, 0));
|
||||
__ shrptr(save);
|
||||
__ pop(rcx);
|
||||
__ pop(save);
|
||||
__ jcc(Assembler::equal, L_done);
|
||||
} else
|
||||
#endif // INCLUDE_CDS
|
||||
{
|
||||
__ movptr(tmp1, store_addr); // tmp1 := store address
|
||||
__ xorptr(tmp1, new_val); // tmp1 := store address ^ new value
|
||||
__ shrptr(tmp1, G1HeapRegion::LogOfHRGrainBytes); // ((store address ^ new value) >> LogOfHRGrainBytes) == 0?
|
||||
__ jccb(Assembler::equal, L_done);
|
||||
}
|
||||
|
||||
// Crosses regions, storing null?
|
||||
if (new_val_may_be_null) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, 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
|
||||
@ -395,6 +395,11 @@ OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Na
|
||||
extern void vec_spill_helper(C2_MacroAssembler *masm, bool is_load,
|
||||
int stack_offset, int reg, uint ireg, outputStream* st);
|
||||
|
||||
void BarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Label& slowpath) {
|
||||
// Load the oop from the weak handle.
|
||||
__ movptr(obj, Address(obj));
|
||||
}
|
||||
|
||||
#undef __
|
||||
#define __ _masm->
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, 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
|
||||
@ -109,6 +109,8 @@ public:
|
||||
#ifdef COMPILER2
|
||||
OptoReg::Name refine_register(const Node* node,
|
||||
OptoReg::Name opto_reg);
|
||||
|
||||
virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Label& slowpath);
|
||||
#endif // COMPILER2
|
||||
};
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "asm/macroAssembler.inline.hpp"
|
||||
#include "code/aotCodeCache.hpp"
|
||||
#include "gc/shared/barrierSet.hpp"
|
||||
#include "gc/shared/cardTable.hpp"
|
||||
#include "gc/shared/cardTableBarrierSet.hpp"
|
||||
@ -111,7 +112,15 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl
|
||||
__ shrptr(end, CardTable::card_shift());
|
||||
__ subptr(end, addr); // end --> cards count
|
||||
|
||||
__ mov64(tmp, (intptr_t)ctbs->card_table_base_const());
|
||||
#if INCLUDE_CDS
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
__ lea(tmp, ExternalAddress(AOTRuntimeConstants::card_table_base_address()));
|
||||
__ movq(tmp, Address(tmp, 0));
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
__ mov64(tmp, (intptr_t)ctbs->card_table_base_const());
|
||||
}
|
||||
__ addptr(addr, tmp);
|
||||
__ BIND(L_loop);
|
||||
__ movb(Address(addr, count, Address::times_1), 0);
|
||||
@ -121,7 +130,7 @@ __ BIND(L_loop);
|
||||
__ BIND(L_done);
|
||||
}
|
||||
|
||||
void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Address dst) {
|
||||
void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Address dst, Register rscratch) {
|
||||
// Does a store check for the oop in register obj. The content of
|
||||
// register obj is destroyed afterwards.
|
||||
CardTableBarrierSet* ctbs = CardTableBarrierSet::barrier_set();
|
||||
@ -136,6 +145,13 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob
|
||||
// never need to be relocated. On 64bit however the value may be too
|
||||
// large for a 32bit displacement.
|
||||
intptr_t byte_map_base = (intptr_t)ctbs->card_table_base_const();
|
||||
#if INCLUDE_CDS
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
__ lea(rscratch, ExternalAddress(AOTRuntimeConstants::card_table_base_address()));
|
||||
__ movq(rscratch, Address(rscratch, 0));
|
||||
card_addr = Address(rscratch, obj, Address::times_1, 0);
|
||||
} else
|
||||
#endif
|
||||
if (__ is_simm32(byte_map_base)) {
|
||||
card_addr = Address(noreg, obj, Address::times_1, byte_map_base);
|
||||
} else {
|
||||
@ -174,10 +190,10 @@ void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorS
|
||||
if (needs_post_barrier) {
|
||||
// flatten object address if needed
|
||||
if (!precise || (dst.index() == noreg && dst.disp() == 0)) {
|
||||
store_check(masm, dst.base(), dst);
|
||||
store_check(masm, dst.base(), dst, tmp2);
|
||||
} else {
|
||||
__ lea(tmp1, dst);
|
||||
store_check(masm, tmp1, dst);
|
||||
store_check(masm, tmp1, dst, tmp2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ protected:
|
||||
virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
|
||||
Register addr, Register count) {}
|
||||
|
||||
void store_check(MacroAssembler* masm, Register obj, Address dst);
|
||||
void store_check(MacroAssembler* masm, Register obj, Address dst, Register rscratch);
|
||||
|
||||
virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp);
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved.
|
||||
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -618,6 +619,27 @@ void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler
|
||||
__ bind(done);
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
void ShenandoahBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Label& slowpath) {
|
||||
Label done;
|
||||
|
||||
// Resolve weak handle using the standard implementation.
|
||||
BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, slowpath);
|
||||
|
||||
// Check if the reference is null, and if it is, take the fast path.
|
||||
__ testptr(obj, obj);
|
||||
__ jcc(Assembler::zero, done);
|
||||
|
||||
Address gc_state(r15_thread, ShenandoahThreadLocalData::gc_state_offset());
|
||||
|
||||
// Check if the heap is under weak-reference/roots processing, in
|
||||
// which case we need to take the slow path.
|
||||
__ testb(gc_state, ShenandoahHeap::WEAK_ROOTS);
|
||||
__ jcc(Assembler::notZero, slowpath);
|
||||
__ bind(done);
|
||||
}
|
||||
#endif // COMPILER2
|
||||
|
||||
// Special Shenandoah CAS implementation that handles false negatives
|
||||
// due to concurrent evacuation.
|
||||
void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved.
|
||||
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -77,6 +78,9 @@ public:
|
||||
Address dst, Register val, Register tmp1, Register tmp2, Register tmp3);
|
||||
virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
|
||||
Register obj, Register tmp, Label& slowpath);
|
||||
#ifdef COMPILER2
|
||||
virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Label& slowpath);
|
||||
#endif // COMPILER2
|
||||
};
|
||||
|
||||
#endif // CPU_X86_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_X86_HPP
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, 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
|
||||
@ -1328,6 +1328,19 @@ void ZBarrierSetAssembler::generate_c2_store_barrier_stub(MacroAssembler* masm,
|
||||
__ jmp(slow_continuation);
|
||||
}
|
||||
|
||||
void ZBarrierSetAssembler::try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Label& slow_path) {
|
||||
// Resolve weak handle using the standard implementation.
|
||||
BarrierSetAssembler::try_resolve_weak_handle_in_c2(masm, obj, slow_path);
|
||||
|
||||
// Check if the oop is bad, in which case we need to take the slow path.
|
||||
__ testptr(obj, Address(r15_thread, ZThreadLocalData::mark_bad_mask_offset()));
|
||||
__ jcc(Assembler::notZero, slow_path);
|
||||
|
||||
// Oop is okay, so we uncolor it.
|
||||
__ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatLoadGoodBeforeShl);
|
||||
__ shrq(obj, barrier_Relocation::unpatched);
|
||||
}
|
||||
|
||||
#undef __
|
||||
#endif // COMPILER2
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2026, 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
|
||||
@ -167,6 +167,8 @@ public:
|
||||
ZLoadBarrierStubC2* stub) const;
|
||||
void generate_c2_store_barrier_stub(MacroAssembler* masm,
|
||||
ZStoreBarrierStubC2* stub) const;
|
||||
|
||||
virtual void try_resolve_weak_handle_in_c2(MacroAssembler* masm, Register obj, Label& slow_path);
|
||||
#endif // COMPILER2
|
||||
|
||||
void store_barrier_fast(MacroAssembler* masm,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -46,9 +46,9 @@ define_pd_global(size_t, CodeCacheSegmentSize, 64 COMPILER1_AND_COMPILER2_PRES
|
||||
// the uep and the vep doesn't get real alignment but just slops on by
|
||||
// only assured that the entry instruction meets the 5 byte size requirement.
|
||||
#if COMPILER2_OR_JVMCI
|
||||
define_pd_global(intx, CodeEntryAlignment, 32);
|
||||
define_pd_global(uint, CodeEntryAlignment, 32);
|
||||
#else
|
||||
define_pd_global(intx, CodeEntryAlignment, 16);
|
||||
define_pd_global(uint, CodeEntryAlignment, 16);
|
||||
#endif // COMPILER2_OR_JVMCI
|
||||
define_pd_global(intx, OptoLoopAlignment, 16);
|
||||
define_pd_global(intx, InlineSmallCode, 1000);
|
||||
|
||||
@ -765,7 +765,7 @@ void MacroAssembler::align32() {
|
||||
|
||||
void MacroAssembler::align(uint modulus) {
|
||||
// 8273459: Ensure alignment is possible with current segment alignment
|
||||
assert(modulus <= (uintx)CodeEntryAlignment, "Alignment must be <= CodeEntryAlignment");
|
||||
assert(modulus <= CodeEntryAlignment, "Alignment must be <= CodeEntryAlignment");
|
||||
align(modulus, offset());
|
||||
}
|
||||
|
||||
@ -2656,6 +2656,17 @@ void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src, Register rscra
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::vucomxsd(XMMRegister dst, AddressLiteral src, Register rscratch) {
|
||||
assert(rscratch != noreg || always_reachable(src), "missing");
|
||||
|
||||
if (reachable(src)) {
|
||||
Assembler::vucomxsd(dst, as_Address(src));
|
||||
} else {
|
||||
lea(rscratch, src);
|
||||
Assembler::vucomxsd(dst, Address(rscratch, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::ucomiss(XMMRegister dst, AddressLiteral src, Register rscratch) {
|
||||
assert(rscratch != noreg || always_reachable(src), "missing");
|
||||
|
||||
@ -2667,6 +2678,17 @@ void MacroAssembler::ucomiss(XMMRegister dst, AddressLiteral src, Register rscra
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::vucomxss(XMMRegister dst, AddressLiteral src, Register rscratch) {
|
||||
assert(rscratch != noreg || always_reachable(src), "missing");
|
||||
|
||||
if (reachable(src)) {
|
||||
Assembler::vucomxss(dst, as_Address(src));
|
||||
} else {
|
||||
lea(rscratch, src);
|
||||
Assembler::vucomxss(dst, Address(rscratch, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::xorpd(XMMRegister dst, AddressLiteral src, Register rscratch) {
|
||||
assert(rscratch != noreg || always_reachable(src), "missing");
|
||||
|
||||
@ -10012,6 +10034,20 @@ void MacroAssembler::restore_legacy_gprs() {
|
||||
addq(rsp, 16 * wordSize);
|
||||
}
|
||||
|
||||
void MacroAssembler::load_aotrc_address(Register reg, address a) {
|
||||
#if INCLUDE_CDS
|
||||
assert(AOTRuntimeConstants::contains(a), "address out of range for data area");
|
||||
if (AOTCodeCache::is_on_for_dump()) {
|
||||
// all aotrc field addresses should be registered in the AOTCodeCache address table
|
||||
lea(reg, ExternalAddress(a));
|
||||
} else {
|
||||
mov64(reg, (uint64_t)a);
|
||||
}
|
||||
#else
|
||||
ShouldNotReachHere();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MacroAssembler::setcc(Assembler::Condition comparison, Register dst) {
|
||||
if (VM_Version::supports_apx_f()) {
|
||||
esetzucc(comparison, dst);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, 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
|
||||
@ -1313,10 +1313,18 @@ public:
|
||||
void ucomiss(XMMRegister dst, Address src) { Assembler::ucomiss(dst, src); }
|
||||
void ucomiss(XMMRegister dst, AddressLiteral src, Register rscratch = noreg);
|
||||
|
||||
void vucomxss(XMMRegister dst, XMMRegister src) { Assembler::vucomxss(dst, src); }
|
||||
void vucomxss(XMMRegister dst, Address src) { Assembler::vucomxss(dst, src); }
|
||||
void vucomxss(XMMRegister dst, AddressLiteral src, Register rscratch = noreg);
|
||||
|
||||
void ucomisd(XMMRegister dst, XMMRegister src) { Assembler::ucomisd(dst, src); }
|
||||
void ucomisd(XMMRegister dst, Address src) { Assembler::ucomisd(dst, src); }
|
||||
void ucomisd(XMMRegister dst, AddressLiteral src, Register rscratch = noreg);
|
||||
|
||||
void vucomxsd(XMMRegister dst, XMMRegister src) { Assembler::vucomxsd(dst, src); }
|
||||
void vucomxsd(XMMRegister dst, Address src) { Assembler::vucomxsd(dst, src); }
|
||||
void vucomxsd(XMMRegister dst, AddressLiteral src, Register rscratch = noreg);
|
||||
|
||||
// Bitwise Logical XOR of Packed Double-Precision Floating-Point Values
|
||||
void xorpd(XMMRegister dst, XMMRegister src);
|
||||
void xorpd(XMMRegister dst, Address src) { Assembler::xorpd(dst, src); }
|
||||
@ -2062,6 +2070,7 @@ public:
|
||||
|
||||
void save_legacy_gprs();
|
||||
void restore_legacy_gprs();
|
||||
void load_aotrc_address(Register reg, address a);
|
||||
void setcc(Assembler::Condition comparison, Register dst);
|
||||
};
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ int VM_Version::_stepping;
|
||||
bool VM_Version::_has_intel_jcc_erratum;
|
||||
VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, };
|
||||
|
||||
#define DECLARE_CPU_FEATURE_NAME(id, name, bit) name,
|
||||
#define DECLARE_CPU_FEATURE_NAME(id, name, bit) XSTR(name),
|
||||
const char* VM_Version::_features_names[] = { CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_NAME)};
|
||||
#undef DECLARE_CPU_FEATURE_NAME
|
||||
|
||||
@ -1659,41 +1659,40 @@ void VM_Version::get_processor_features() {
|
||||
if (FLAG_IS_DEFAULT(AllocatePrefetchInstr) && supports_3dnow_prefetch()) {
|
||||
FLAG_SET_DEFAULT(AllocatePrefetchInstr, 3);
|
||||
}
|
||||
#ifdef COMPILER2
|
||||
if (UseAVX > 2) {
|
||||
if (FLAG_IS_DEFAULT(ArrayOperationPartialInlineSize) ||
|
||||
(!FLAG_IS_DEFAULT(ArrayOperationPartialInlineSize) &&
|
||||
ArrayOperationPartialInlineSize != 0 &&
|
||||
ArrayOperationPartialInlineSize != 16 &&
|
||||
ArrayOperationPartialInlineSize != 32 &&
|
||||
ArrayOperationPartialInlineSize != 64)) {
|
||||
int inline_size = 0;
|
||||
if (MaxVectorSize >= 64 && AVX3Threshold == 0) {
|
||||
inline_size = 64;
|
||||
} else if (MaxVectorSize >= 32) {
|
||||
inline_size = 32;
|
||||
} else if (MaxVectorSize >= 16) {
|
||||
inline_size = 16;
|
||||
}
|
||||
if(!FLAG_IS_DEFAULT(ArrayOperationPartialInlineSize)) {
|
||||
warning("Setting ArrayOperationPartialInlineSize as %d", inline_size);
|
||||
}
|
||||
ArrayOperationPartialInlineSize = inline_size;
|
||||
}
|
||||
|
||||
if (ArrayOperationPartialInlineSize > MaxVectorSize) {
|
||||
ArrayOperationPartialInlineSize = MaxVectorSize >= 16 ? MaxVectorSize : 0;
|
||||
if (ArrayOperationPartialInlineSize) {
|
||||
warning("Setting ArrayOperationPartialInlineSize as MaxVectorSize=%zd", MaxVectorSize);
|
||||
} else {
|
||||
warning("Setting ArrayOperationPartialInlineSize as %zd", ArrayOperationPartialInlineSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
if (UseAVX > 2) {
|
||||
if (FLAG_IS_DEFAULT(ArrayOperationPartialInlineSize) ||
|
||||
(!FLAG_IS_DEFAULT(ArrayOperationPartialInlineSize) &&
|
||||
ArrayOperationPartialInlineSize != 0 &&
|
||||
ArrayOperationPartialInlineSize != 16 &&
|
||||
ArrayOperationPartialInlineSize != 32 &&
|
||||
ArrayOperationPartialInlineSize != 64)) {
|
||||
int inline_size = 0;
|
||||
if (MaxVectorSize >= 64 && AVX3Threshold == 0) {
|
||||
inline_size = 64;
|
||||
} else if (MaxVectorSize >= 32) {
|
||||
inline_size = 32;
|
||||
} else if (MaxVectorSize >= 16) {
|
||||
inline_size = 16;
|
||||
}
|
||||
if(!FLAG_IS_DEFAULT(ArrayOperationPartialInlineSize)) {
|
||||
warning("Setting ArrayOperationPartialInlineSize as %d", inline_size);
|
||||
}
|
||||
ArrayOperationPartialInlineSize = inline_size;
|
||||
}
|
||||
|
||||
if (ArrayOperationPartialInlineSize > MaxVectorSize) {
|
||||
ArrayOperationPartialInlineSize = MaxVectorSize >= 16 ? MaxVectorSize : 0;
|
||||
if (ArrayOperationPartialInlineSize) {
|
||||
warning("Setting ArrayOperationPartialInlineSize as MaxVectorSize=%zd", MaxVectorSize);
|
||||
} else {
|
||||
warning("Setting ArrayOperationPartialInlineSize as %zd", ArrayOperationPartialInlineSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FLAG_IS_DEFAULT(OptimizeFill)) {
|
||||
if (MaxVectorSize < 32 || (!EnableX86ECoreOpts && !VM_Version::supports_avx512vlbw())) {
|
||||
OptimizeFill = false;
|
||||
@ -3298,12 +3297,50 @@ bool VM_Version::is_intrinsic_supported(vmIntrinsicID id) {
|
||||
void VM_Version::insert_features_names(VM_Version::VM_Features features, stringStream& ss) {
|
||||
int i = 0;
|
||||
ss.join([&]() {
|
||||
while (i < MAX_CPU_FEATURES) {
|
||||
if (_features.supports_feature((VM_Version::Feature_Flag)i)) {
|
||||
return _features_names[i++];
|
||||
const char* str = nullptr;
|
||||
while ((i < MAX_CPU_FEATURES) && (str == nullptr)) {
|
||||
if (features.supports_feature((VM_Version::Feature_Flag)i)) {
|
||||
str = _features_names[i];
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return (const char*)nullptr;
|
||||
return str;
|
||||
}, ", ");
|
||||
}
|
||||
|
||||
void VM_Version::get_cpu_features_name(void* features_buffer, stringStream& ss) {
|
||||
VM_Features* features = (VM_Features*)features_buffer;
|
||||
insert_features_names(*features, ss);
|
||||
}
|
||||
|
||||
void VM_Version::get_missing_features_name(void* features_set1, void* features_set2, stringStream& ss) {
|
||||
VM_Features* vm_features_set1 = (VM_Features*)features_set1;
|
||||
VM_Features* vm_features_set2 = (VM_Features*)features_set2;
|
||||
int i = 0;
|
||||
ss.join([&]() {
|
||||
const char* str = nullptr;
|
||||
while ((i < MAX_CPU_FEATURES) && (str == nullptr)) {
|
||||
Feature_Flag flag = (Feature_Flag)i;
|
||||
if (vm_features_set1->supports_feature(flag) && !vm_features_set2->supports_feature(flag)) {
|
||||
str = _features_names[i];
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return str;
|
||||
}, ", ");
|
||||
}
|
||||
|
||||
int VM_Version::cpu_features_size() {
|
||||
return sizeof(VM_Features);
|
||||
}
|
||||
|
||||
void VM_Version::store_cpu_features(void* buf) {
|
||||
VM_Features copy = _features;
|
||||
copy.clear_feature(CPU_HT); // HT does not result in incompatibility of aot code cache
|
||||
memcpy(buf, ©, sizeof(VM_Features));
|
||||
}
|
||||
|
||||
bool VM_Version::supports_features(void* features_buffer) {
|
||||
VM_Features* features_to_test = (VM_Features*)features_buffer;
|
||||
return _features.supports_features(features_to_test);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2026, 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
|
||||
@ -377,84 +377,84 @@ protected:
|
||||
*/
|
||||
enum Feature_Flag {
|
||||
#define CPU_FEATURE_FLAGS(decl) \
|
||||
decl(CX8, "cx8", 0) /* next bits are from cpuid 1 (EDX) */ \
|
||||
decl(CMOV, "cmov", 1) \
|
||||
decl(FXSR, "fxsr", 2) \
|
||||
decl(HT, "ht", 3) \
|
||||
decl(CX8, cx8, 0) /* next bits are from cpuid 1 (EDX) */ \
|
||||
decl(CMOV, cmov, 1) \
|
||||
decl(FXSR, fxsr, 2) \
|
||||
decl(HT, ht, 3) \
|
||||
\
|
||||
decl(MMX, "mmx", 4) \
|
||||
decl(3DNOW_PREFETCH, "3dnowpref", 5) /* Processor supports 3dnow prefetch and prefetchw instructions */ \
|
||||
decl(MMX, mmx, 4) \
|
||||
decl(3DNOW_PREFETCH, 3dnowpref, 5) /* Processor supports 3dnow prefetch and prefetchw instructions */ \
|
||||
/* may not necessarily support other 3dnow instructions */ \
|
||||
decl(SSE, "sse", 6) \
|
||||
decl(SSE2, "sse2", 7) \
|
||||
decl(SSE, sse, 6) \
|
||||
decl(SSE2, sse2, 7) \
|
||||
\
|
||||
decl(SSE3, "sse3", 8 ) /* SSE3 comes from cpuid 1 (ECX) */ \
|
||||
decl(SSSE3, "ssse3", 9 ) \
|
||||
decl(SSE4A, "sse4a", 10) \
|
||||
decl(SSE4_1, "sse4.1", 11) \
|
||||
decl(SSE3, sse3, 8 ) /* SSE3 comes from cpuid 1 (ECX) */ \
|
||||
decl(SSSE3, ssse3, 9 ) \
|
||||
decl(SSE4A, sse4a, 10) \
|
||||
decl(SSE4_1, sse4.1, 11) \
|
||||
\
|
||||
decl(SSE4_2, "sse4.2", 12) \
|
||||
decl(POPCNT, "popcnt", 13) \
|
||||
decl(LZCNT, "lzcnt", 14) \
|
||||
decl(TSC, "tsc", 15) \
|
||||
decl(SSE4_2, sse4.2, 12) \
|
||||
decl(POPCNT, popcnt, 13) \
|
||||
decl(LZCNT, lzcnt, 14) \
|
||||
decl(TSC, tsc, 15) \
|
||||
\
|
||||
decl(TSCINV_BIT, "tscinvbit", 16) \
|
||||
decl(TSCINV, "tscinv", 17) \
|
||||
decl(AVX, "avx", 18) \
|
||||
decl(AVX2, "avx2", 19) \
|
||||
decl(TSCINV_BIT, tscinvbit, 16) \
|
||||
decl(TSCINV, tscinv, 17) \
|
||||
decl(AVX, avx, 18) \
|
||||
decl(AVX2, avx2, 19) \
|
||||
\
|
||||
decl(AES, "aes", 20) \
|
||||
decl(ERMS, "erms", 21) /* enhanced 'rep movsb/stosb' instructions */ \
|
||||
decl(CLMUL, "clmul", 22) /* carryless multiply for CRC */ \
|
||||
decl(BMI1, "bmi1", 23) \
|
||||
decl(AES, aes, 20) \
|
||||
decl(ERMS, erms, 21) /* enhanced 'rep movsb/stosb' instructions */ \
|
||||
decl(CLMUL, clmul, 22) /* carryless multiply for CRC */ \
|
||||
decl(BMI1, bmi1, 23) \
|
||||
\
|
||||
decl(BMI2, "bmi2", 24) \
|
||||
decl(RTM, "rtm", 25) /* Restricted Transactional Memory instructions */ \
|
||||
decl(ADX, "adx", 26) \
|
||||
decl(AVX512F, "avx512f", 27) /* AVX 512bit foundation instructions */ \
|
||||
decl(BMI2, bmi2, 24) \
|
||||
decl(RTM, rtm, 25) /* Restricted Transactional Memory instructions */ \
|
||||
decl(ADX, adx, 26) \
|
||||
decl(AVX512F, avx512f, 27) /* AVX 512bit foundation instructions */ \
|
||||
\
|
||||
decl(AVX512DQ, "avx512dq", 28) \
|
||||
decl(AVX512PF, "avx512pf", 29) \
|
||||
decl(AVX512ER, "avx512er", 30) \
|
||||
decl(AVX512CD, "avx512cd", 31) \
|
||||
decl(AVX512DQ, avx512dq, 28) \
|
||||
decl(AVX512PF, avx512pf, 29) \
|
||||
decl(AVX512ER, avx512er, 30) \
|
||||
decl(AVX512CD, avx512cd, 31) \
|
||||
\
|
||||
decl(AVX512BW, "avx512bw", 32) /* Byte and word vector instructions */ \
|
||||
decl(AVX512VL, "avx512vl", 33) /* EVEX instructions with smaller vector length */ \
|
||||
decl(SHA, "sha", 34) /* SHA instructions */ \
|
||||
decl(FMA, "fma", 35) /* FMA instructions */ \
|
||||
decl(AVX512BW, avx512bw, 32) /* Byte and word vector instructions */ \
|
||||
decl(AVX512VL, avx512vl, 33) /* EVEX instructions with smaller vector length */ \
|
||||
decl(SHA, sha, 34) /* SHA instructions */ \
|
||||
decl(FMA, fma, 35) /* FMA instructions */ \
|
||||
\
|
||||
decl(VZEROUPPER, "vzeroupper", 36) /* Vzeroupper instruction */ \
|
||||
decl(AVX512_VPOPCNTDQ, "avx512_vpopcntdq", 37) /* Vector popcount */ \
|
||||
decl(AVX512_VPCLMULQDQ, "avx512_vpclmulqdq", 38) /* Vector carryless multiplication */ \
|
||||
decl(AVX512_VAES, "avx512_vaes", 39) /* Vector AES instruction */ \
|
||||
decl(VZEROUPPER, vzeroupper, 36) /* Vzeroupper instruction */ \
|
||||
decl(AVX512_VPOPCNTDQ, avx512_vpopcntdq, 37) /* Vector popcount */ \
|
||||
decl(AVX512_VPCLMULQDQ, avx512_vpclmulqdq, 38) /* Vector carryless multiplication */ \
|
||||
decl(AVX512_VAES, avx512_vaes, 39) /* Vector AES instruction */ \
|
||||
\
|
||||
decl(AVX512_VNNI, "avx512_vnni", 40) /* Vector Neural Network Instructions */ \
|
||||
decl(FLUSH, "clflush", 41) /* flush instruction */ \
|
||||
decl(FLUSHOPT, "clflushopt", 42) /* flusopth instruction */ \
|
||||
decl(CLWB, "clwb", 43) /* clwb instruction */ \
|
||||
decl(AVX512_VNNI, avx512_vnni, 40) /* Vector Neural Network Instructions */ \
|
||||
decl(FLUSH, clflush, 41) /* flush instruction */ \
|
||||
decl(FLUSHOPT, clflushopt, 42) /* flusopth instruction */ \
|
||||
decl(CLWB, clwb, 43) /* clwb instruction */ \
|
||||
\
|
||||
decl(AVX512_VBMI2, "avx512_vbmi2", 44) /* VBMI2 shift left double instructions */ \
|
||||
decl(AVX512_VBMI, "avx512_vbmi", 45) /* Vector BMI instructions */ \
|
||||
decl(HV, "hv", 46) /* Hypervisor instructions */ \
|
||||
decl(SERIALIZE, "serialize", 47) /* CPU SERIALIZE */ \
|
||||
decl(RDTSCP, "rdtscp", 48) /* RDTSCP instruction */ \
|
||||
decl(RDPID, "rdpid", 49) /* RDPID instruction */ \
|
||||
decl(FSRM, "fsrm", 50) /* Fast Short REP MOV */ \
|
||||
decl(GFNI, "gfni", 51) /* Vector GFNI instructions */ \
|
||||
decl(AVX512_BITALG, "avx512_bitalg", 52) /* Vector sub-word popcount and bit gather instructions */\
|
||||
decl(F16C, "f16c", 53) /* Half-precision and single precision FP conversion instructions*/ \
|
||||
decl(PKU, "pku", 54) /* Protection keys for user-mode pages */ \
|
||||
decl(OSPKE, "ospke", 55) /* OS enables protection keys */ \
|
||||
decl(CET_IBT, "cet_ibt", 56) /* Control Flow Enforcement - Indirect Branch Tracking */ \
|
||||
decl(CET_SS, "cet_ss", 57) /* Control Flow Enforcement - Shadow Stack */ \
|
||||
decl(AVX512_IFMA, "avx512_ifma", 58) /* Integer Vector FMA instructions*/ \
|
||||
decl(AVX_IFMA, "avx_ifma", 59) /* 256-bit VEX-coded variant of AVX512-IFMA*/ \
|
||||
decl(APX_F, "apx_f", 60) /* Intel Advanced Performance Extensions*/ \
|
||||
decl(SHA512, "sha512", 61) /* SHA512 instructions*/ \
|
||||
decl(AVX512_FP16, "avx512_fp16", 62) /* AVX512 FP16 ISA support*/ \
|
||||
decl(AVX10_1, "avx10_1", 63) /* AVX10 512 bit vector ISA Version 1 support*/ \
|
||||
decl(AVX10_2, "avx10_2", 64) /* AVX10 512 bit vector ISA Version 2 support*/ \
|
||||
decl(HYBRID, "hybrid", 65) /* Hybrid architecture */
|
||||
decl(AVX512_VBMI2, avx512_vbmi2, 44) /* VBMI2 shift left double instructions */ \
|
||||
decl(AVX512_VBMI, avx512_vbmi, 45) /* Vector BMI instructions */ \
|
||||
decl(HV, hv, 46) /* Hypervisor instructions */ \
|
||||
decl(SERIALIZE, serialize, 47) /* CPU SERIALIZE */ \
|
||||
decl(RDTSCP, rdtscp, 48) /* RDTSCP instruction */ \
|
||||
decl(RDPID, rdpid, 49) /* RDPID instruction */ \
|
||||
decl(FSRM, fsrm, 50) /* Fast Short REP MOV */ \
|
||||
decl(GFNI, gfni, 51) /* Vector GFNI instructions */ \
|
||||
decl(AVX512_BITALG, avx512_bitalg, 52) /* Vector sub-word popcount and bit gather instructions */\
|
||||
decl(F16C, f16c, 53) /* Half-precision and single precision FP conversion instructions*/ \
|
||||
decl(PKU, pku, 54) /* Protection keys for user-mode pages */ \
|
||||
decl(OSPKE, ospke, 55) /* OS enables protection keys */ \
|
||||
decl(CET_IBT, cet_ibt, 56) /* Control Flow Enforcement - Indirect Branch Tracking */ \
|
||||
decl(CET_SS, cet_ss, 57) /* Control Flow Enforcement - Shadow Stack */ \
|
||||
decl(AVX512_IFMA, avx512_ifma, 58) /* Integer Vector FMA instructions*/ \
|
||||
decl(AVX_IFMA, avx_ifma, 59) /* 256-bit VEX-coded variant of AVX512-IFMA*/ \
|
||||
decl(APX_F, apx_f, 60) /* Intel Advanced Performance Extensions*/ \
|
||||
decl(SHA512, sha512, 61) /* SHA512 instructions*/ \
|
||||
decl(AVX512_FP16, avx512_fp16, 62) /* AVX512 FP16 ISA support*/ \
|
||||
decl(AVX10_1, avx10_1, 63) /* AVX10 512 bit vector ISA Version 1 support*/ \
|
||||
decl(AVX10_2, avx10_2, 64) /* AVX10 512 bit vector ISA Version 2 support*/ \
|
||||
decl(HYBRID, hybrid, 65) /* Hybrid architecture */
|
||||
|
||||
#define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (bit),
|
||||
CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG)
|
||||
@ -516,6 +516,15 @@ protected:
|
||||
int idx = index(feature);
|
||||
return (_features_bitmap[idx] & bit_mask(feature)) != 0;
|
||||
}
|
||||
|
||||
bool supports_features(VM_Features* features_to_test) {
|
||||
for (int i = 0; i < features_bitmap_element_count(); i++) {
|
||||
if ((_features_bitmap[i] & features_to_test->_features_bitmap[i]) != features_to_test->_features_bitmap[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// CPU feature flags vector, can be affected by VM settings.
|
||||
@ -1103,6 +1112,20 @@ public:
|
||||
static bool supports_tscinv_ext(void);
|
||||
|
||||
static void initialize_cpu_information(void);
|
||||
|
||||
static void get_cpu_features_name(void* features_buffer, stringStream& ss);
|
||||
|
||||
// Returns names of features present in features_set1 but not in features_set2
|
||||
static void get_missing_features_name(void* features_set1, void* features_set2, stringStream& ss);
|
||||
|
||||
// Returns number of bytes required to store cpu features representation
|
||||
static int cpu_features_size();
|
||||
|
||||
// Stores cpu features representation in the provided buffer. This representation is arch dependent.
|
||||
// Size of the buffer must be same as returned by cpu_features_size()
|
||||
static void store_cpu_features(void* buf);
|
||||
|
||||
static bool supports_features(void* features_to_test);
|
||||
};
|
||||
|
||||
#endif // CPU_X86_VM_VERSION_X86_HPP
|
||||
|
||||
@ -1699,9 +1699,10 @@ static void emit_cmpfp_fixup(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
static void emit_cmpfp3(MacroAssembler* masm, Register dst) {
|
||||
// If any floating point comparison instruction is used, unordered case always triggers jump
|
||||
// for below condition, CF=1 is true when at least one input is NaN
|
||||
Label done;
|
||||
__ movl(dst, -1);
|
||||
__ jcc(Assembler::parity, done);
|
||||
__ jcc(Assembler::below, done);
|
||||
__ setcc(Assembler::notEqual, dst);
|
||||
__ bind(done);
|
||||
@ -5186,6 +5187,18 @@ operand immL_65535()
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// AOT Runtime Constants Address
|
||||
operand immAOTRuntimeConstantsAddress()
|
||||
%{
|
||||
// Check if the address is in the range of AOT Runtime Constants
|
||||
predicate(AOTRuntimeConstants::contains((address)(n->get_ptr())));
|
||||
match(ConP);
|
||||
|
||||
op_cost(0);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
operand kReg()
|
||||
%{
|
||||
constraint(ALLOC_IN_RC(vectmask_reg));
|
||||
@ -5529,12 +5542,21 @@ operand rFlagsRegU()
|
||||
operand rFlagsRegUCF() %{
|
||||
constraint(ALLOC_IN_RC(int_flags));
|
||||
match(RegFlags);
|
||||
predicate(false);
|
||||
predicate(!UseAPX || !VM_Version::supports_avx10_2());
|
||||
|
||||
format %{ "RFLAGS_U_CF" %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
operand rFlagsRegUCFE() %{
|
||||
constraint(ALLOC_IN_RC(int_flags));
|
||||
match(RegFlags);
|
||||
predicate(UseAPX && VM_Version::supports_avx10_2());
|
||||
|
||||
format %{ "RFLAGS_U_CFE" %}
|
||||
interface(REG_INTER);
|
||||
%}
|
||||
|
||||
// Float register operands
|
||||
operand regF() %{
|
||||
constraint(ALLOC_IN_RC(float_reg));
|
||||
@ -6027,10 +6049,10 @@ operand cmpOp()
|
||||
interface(COND_INTER) %{
|
||||
equal(0x4, "e");
|
||||
not_equal(0x5, "ne");
|
||||
less(0xC, "l");
|
||||
greater_equal(0xD, "ge");
|
||||
less_equal(0xE, "le");
|
||||
greater(0xF, "g");
|
||||
less(0xc, "l");
|
||||
greater_equal(0xd, "ge");
|
||||
less_equal(0xe, "le");
|
||||
greater(0xf, "g");
|
||||
overflow(0x0, "o");
|
||||
no_overflow(0x1, "no");
|
||||
%}
|
||||
@ -6062,11 +6084,12 @@ operand cmpOpU()
|
||||
// don't need to use cmpOpUCF2 for eq/ne
|
||||
operand cmpOpUCF() %{
|
||||
match(Bool);
|
||||
predicate(n->as_Bool()->_test._test == BoolTest::lt ||
|
||||
n->as_Bool()->_test._test == BoolTest::ge ||
|
||||
n->as_Bool()->_test._test == BoolTest::le ||
|
||||
n->as_Bool()->_test._test == BoolTest::gt ||
|
||||
n->in(1)->in(1) == n->in(1)->in(2));
|
||||
predicate((!UseAPX || !VM_Version::supports_avx10_2()) &&
|
||||
(n->as_Bool()->_test._test == BoolTest::lt ||
|
||||
n->as_Bool()->_test._test == BoolTest::ge ||
|
||||
n->as_Bool()->_test._test == BoolTest::le ||
|
||||
n->as_Bool()->_test._test == BoolTest::gt ||
|
||||
n->in(1)->in(1) == n->in(1)->in(2)));
|
||||
format %{ "" %}
|
||||
interface(COND_INTER) %{
|
||||
equal(0xb, "np");
|
||||
@ -6084,7 +6107,8 @@ operand cmpOpUCF() %{
|
||||
// Floating comparisons that can be fixed up with extra conditional jumps
|
||||
operand cmpOpUCF2() %{
|
||||
match(Bool);
|
||||
predicate((n->as_Bool()->_test._test == BoolTest::ne ||
|
||||
predicate((!UseAPX || !VM_Version::supports_avx10_2()) &&
|
||||
(n->as_Bool()->_test._test == BoolTest::ne ||
|
||||
n->as_Bool()->_test._test == BoolTest::eq) &&
|
||||
n->in(1)->in(1) != n->in(1)->in(2));
|
||||
format %{ "" %}
|
||||
@ -6100,6 +6124,37 @@ operand cmpOpUCF2() %{
|
||||
%}
|
||||
%}
|
||||
|
||||
|
||||
// Floating point comparisons that set condition flags to test more directly,
|
||||
// Unsigned tests are used for G (>) and GE (>=) conditions while signed tests
|
||||
// are used for L (<) and LE (<=) conditions. It's important to convert these
|
||||
// latter conditions to ones that use unsigned tests before passing into an
|
||||
// instruction because the preceding comparison might be based on a three way
|
||||
// comparison (CmpF3 or CmpD3) that also assigns unordered outcomes to -1.
|
||||
operand cmpOpUCFE()
|
||||
%{
|
||||
match(Bool);
|
||||
predicate((UseAPX && VM_Version::supports_avx10_2()) &&
|
||||
(n->as_Bool()->_test._test == BoolTest::ne ||
|
||||
n->as_Bool()->_test._test == BoolTest::eq ||
|
||||
n->as_Bool()->_test._test == BoolTest::lt ||
|
||||
n->as_Bool()->_test._test == BoolTest::ge ||
|
||||
n->as_Bool()->_test._test == BoolTest::le ||
|
||||
n->as_Bool()->_test._test == BoolTest::gt));
|
||||
|
||||
format %{ "" %}
|
||||
interface(COND_INTER) %{
|
||||
equal(0x4, "e");
|
||||
not_equal(0x5, "ne");
|
||||
less(0x2, "b");
|
||||
greater_equal(0x3, "ae");
|
||||
less_equal(0x6, "be");
|
||||
greater(0x7, "a");
|
||||
overflow(0x0, "o");
|
||||
no_overflow(0x1, "no");
|
||||
%}
|
||||
%}
|
||||
|
||||
// Operands for bound floating pointer register arguments
|
||||
operand rxmm0() %{
|
||||
constraint(ALLOC_IN_RC(xmm0_reg));
|
||||
@ -7289,6 +7344,19 @@ instruct loadD(regD dst, memory mem)
|
||||
ins_pipe(pipe_slow); // XXX
|
||||
%}
|
||||
|
||||
instruct loadAOTRCAddress(rRegP dst, immAOTRuntimeConstantsAddress con)
|
||||
%{
|
||||
match(Set dst con);
|
||||
|
||||
format %{ "leaq $dst, $con\t# AOT Runtime Constants Address" %}
|
||||
|
||||
ins_encode %{
|
||||
__ load_aotrc_address($dst$$Register, (address)$con$$constant);
|
||||
%}
|
||||
|
||||
ins_pipe(ialu_reg_fat);
|
||||
%}
|
||||
|
||||
// max = java.lang.Math.max(float a, float b)
|
||||
instruct maxF_reg_avx10_2(regF dst, regF a, regF b) %{
|
||||
predicate(VM_Version::supports_avx10_2());
|
||||
@ -9116,20 +9184,34 @@ instruct cmovI_imm_01UCF(rRegI dst, immI_1 src, rFlagsRegUCF cr, cmpOpUCF cop)
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct cmovI_imm_01UCFE(rRegI dst, immI_1 src, rFlagsRegUCFE cr, cmpOpUCFE cop)
|
||||
%{
|
||||
predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_int() == 0);
|
||||
match(Set dst (CMoveI (Binary cop cr) (Binary src dst)));
|
||||
|
||||
ins_cost(100); // XXX
|
||||
format %{ "setbn$cop $dst\t# signed, unsigned, int" %}
|
||||
ins_encode %{
|
||||
Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
|
||||
__ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct cmovI_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
|
||||
predicate(!UseAPX);
|
||||
match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
|
||||
|
||||
ins_cost(200);
|
||||
expand %{
|
||||
cmovI_regU(cop, cr, dst, src);
|
||||
%}
|
||||
%}
|
||||
|
||||
instruct cmovI_regUCF_ndd(rRegI dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegI src1, rRegI src2) %{
|
||||
predicate(UseAPX);
|
||||
instruct cmovI_regUCFE_ndd(rRegI dst, cmpOpUCFE cop, rFlagsRegUCFE cr, rRegI src1, rRegI src2) %{
|
||||
match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
|
||||
|
||||
ins_cost(200);
|
||||
format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
|
||||
format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, unsigned, int ndd" %}
|
||||
ins_encode %{
|
||||
__ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
|
||||
%}
|
||||
@ -9137,7 +9219,7 @@ instruct cmovI_regUCF_ndd(rRegI dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegI src1,
|
||||
%}
|
||||
|
||||
instruct cmovI_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
|
||||
predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
|
||||
predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
|
||||
match(Set dst (CMoveI (Binary cop cr) (Binary dst src)));
|
||||
|
||||
ins_cost(200); // XXX
|
||||
@ -9150,25 +9232,10 @@ instruct cmovI_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src)
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
instruct cmovI_regUCF2_ne_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src1, rRegI src2) %{
|
||||
predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
|
||||
match(Set dst (CMoveI (Binary cop cr) (Binary src1 src2)));
|
||||
effect(TEMP dst);
|
||||
|
||||
ins_cost(200);
|
||||
format %{ "ecmovpl $dst, $src1, $src2\n\t"
|
||||
"cmovnel $dst, $src2" %}
|
||||
ins_encode %{
|
||||
__ ecmovl(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
|
||||
__ cmovl(Assembler::notEqual, $dst$$Register, $src2$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
// Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
|
||||
// inputs of the CMove
|
||||
instruct cmovI_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src) %{
|
||||
predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
|
||||
predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
|
||||
match(Set dst (CMoveI (Binary cop cr) (Binary src dst)));
|
||||
effect(TEMP dst);
|
||||
|
||||
@ -9182,23 +9249,6 @@ instruct cmovI_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src)
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
// We need this special handling for only eq / neq comparison since NaN == NaN is false,
|
||||
// and parity flag bit is set if any of the operand is a NaN.
|
||||
instruct cmovI_regUCF2_eq_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegI dst, rRegI src1, rRegI src2) %{
|
||||
predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
|
||||
match(Set dst (CMoveI (Binary cop cr) (Binary src2 src1)));
|
||||
effect(TEMP dst);
|
||||
|
||||
ins_cost(200);
|
||||
format %{ "ecmovpl $dst, $src1, $src2\n\t"
|
||||
"cmovnel $dst, $src2" %}
|
||||
ins_encode %{
|
||||
__ ecmovl(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
|
||||
__ cmovl(Assembler::notEqual, $dst$$Register, $src2$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
// Conditional move
|
||||
instruct cmovI_mem(cmpOp cop, rFlagsReg cr, rRegI dst, memory src) %{
|
||||
predicate(!UseAPX);
|
||||
@ -9241,8 +9291,8 @@ instruct cmovI_memU(cmpOpU cop, rFlagsRegU cr, rRegI dst, memory src)
|
||||
%}
|
||||
|
||||
instruct cmovI_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegI dst, memory src) %{
|
||||
predicate(!UseAPX);
|
||||
match(Set dst (CMoveI (Binary cop cr) (Binary dst (LoadI src))));
|
||||
|
||||
ins_cost(250);
|
||||
expand %{
|
||||
cmovI_memU(cop, cr, dst, src);
|
||||
@ -9262,12 +9312,12 @@ instruct cmovI_rReg_rReg_memU_ndd(rRegI dst, cmpOpU cop, rFlagsRegU cr, rRegI sr
|
||||
ins_pipe(pipe_cmov_mem);
|
||||
%}
|
||||
|
||||
instruct cmovI_rReg_rReg_memUCF_ndd(rRegI dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegI src1, memory src2)
|
||||
instruct cmovI_rReg_rReg_memUCFE_ndd(rRegI dst, cmpOpUCFE cop, rFlagsRegUCFE cr, rRegI src1, memory src2)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
match(Set dst (CMoveI (Binary cop cr) (Binary src1 (LoadI src2))));
|
||||
|
||||
ins_cost(250);
|
||||
format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, int ndd" %}
|
||||
format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, unsigned, int ndd" %}
|
||||
ins_encode %{
|
||||
__ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
|
||||
%}
|
||||
@ -9317,8 +9367,8 @@ instruct cmovN_regU(cmpOpU cop, rFlagsRegU cr, rRegN dst, rRegN src)
|
||||
%}
|
||||
|
||||
instruct cmovN_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegN dst, rRegN src) %{
|
||||
predicate(!UseAPX);
|
||||
match(Set dst (CMoveN (Binary cop cr) (Binary dst src)));
|
||||
|
||||
ins_cost(200);
|
||||
expand %{
|
||||
cmovN_regU(cop, cr, dst, src);
|
||||
@ -9339,11 +9389,11 @@ instruct cmovN_regU_ndd(rRegN dst, cmpOpU cop, rFlagsRegU cr, rRegN src1, rRegN
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
instruct cmovN_regUCF_ndd(rRegN dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegN src1, rRegN src2) %{
|
||||
predicate(UseAPX);
|
||||
instruct cmovN_regUCFE_ndd(rRegN dst, cmpOpUCFE cop, rFlagsRegUCFE cr, rRegN src1, rRegN src2) %{
|
||||
match(Set dst (CMoveN (Binary cop cr) (Binary src1 src2)));
|
||||
|
||||
ins_cost(200);
|
||||
format %{ "ecmovl$cop $dst, $src1, $src2\t# unsigned, compressed ptr ndd" %}
|
||||
format %{ "ecmovl$cop $dst, $src1, $src2\t# signed, unsigned, compressed ptr ndd" %}
|
||||
ins_encode %{
|
||||
__ ecmovl((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
|
||||
%}
|
||||
@ -9437,19 +9487,19 @@ instruct cmovP_regU_ndd(rRegP dst, cmpOpU cop, rFlagsRegU cr, rRegP src1, rRegP
|
||||
%}
|
||||
|
||||
instruct cmovP_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
|
||||
predicate(!UseAPX);
|
||||
match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
|
||||
|
||||
ins_cost(200);
|
||||
expand %{
|
||||
cmovP_regU(cop, cr, dst, src);
|
||||
%}
|
||||
%}
|
||||
|
||||
instruct cmovP_regUCF_ndd(rRegP dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegP src1, rRegP src2) %{
|
||||
predicate(UseAPX);
|
||||
instruct cmovP_regUCFE_ndd(rRegP dst, cmpOpUCFE cop, rFlagsRegUCFE cr, rRegP src1, rRegP src2) %{
|
||||
match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
|
||||
|
||||
ins_cost(200);
|
||||
format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, ptr ndd" %}
|
||||
format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, unsigned, ptr ndd" %}
|
||||
ins_encode %{
|
||||
__ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
|
||||
%}
|
||||
@ -9457,7 +9507,7 @@ instruct cmovP_regUCF_ndd(rRegP dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegP src1,
|
||||
%}
|
||||
|
||||
instruct cmovP_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
|
||||
predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
|
||||
predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
|
||||
match(Set dst (CMoveP (Binary cop cr) (Binary dst src)));
|
||||
|
||||
ins_cost(200); // XXX
|
||||
@ -9470,25 +9520,10 @@ instruct cmovP_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src)
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
instruct cmovP_regUCF2_ne_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src1, rRegP src2) %{
|
||||
predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
|
||||
match(Set dst (CMoveP (Binary cop cr) (Binary src1 src2)));
|
||||
effect(TEMP dst);
|
||||
|
||||
ins_cost(200);
|
||||
format %{ "ecmovpq $dst, $src1, $src2\n\t"
|
||||
"cmovneq $dst, $src2" %}
|
||||
ins_encode %{
|
||||
__ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
|
||||
__ cmovq(Assembler::notEqual, $dst$$Register, $src2$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
// Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
|
||||
// inputs of the CMove
|
||||
instruct cmovP_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src) %{
|
||||
predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
|
||||
predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
|
||||
match(Set dst (CMoveP (Binary cop cr) (Binary src dst)));
|
||||
|
||||
ins_cost(200); // XXX
|
||||
@ -9501,21 +9536,6 @@ instruct cmovP_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src)
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
instruct cmovP_regUCF2_eq_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegP dst, rRegP src1, rRegP src2) %{
|
||||
predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
|
||||
match(Set dst (CMoveP (Binary cop cr) (Binary src2 src1)));
|
||||
effect(TEMP dst);
|
||||
|
||||
ins_cost(200);
|
||||
format %{ "ecmovpq $dst, $src1, $src2\n\t"
|
||||
"cmovneq $dst, $src2" %}
|
||||
ins_encode %{
|
||||
__ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
|
||||
__ cmovq(Assembler::notEqual, $dst$$Register, $src2$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
instruct cmovL_imm_01(rRegL dst, immL1 src, rFlagsReg cr, cmpOp cop)
|
||||
%{
|
||||
predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_long() == 0);
|
||||
@ -9636,21 +9656,35 @@ instruct cmovL_imm_01UCF(rRegL dst, immL1 src, rFlagsRegUCF cr, cmpOpUCF cop)
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct cmovL_imm_01UCFE(rRegL dst, immL1 src, rFlagsRegUCFE cr, cmpOpUCFE cop)
|
||||
%{
|
||||
predicate(n->in(2)->in(2)->is_Con() && n->in(2)->in(2)->get_long() == 0);
|
||||
match(Set dst (CMoveL (Binary cop cr) (Binary src dst)));
|
||||
|
||||
ins_cost(100); // XXX
|
||||
format %{ "setbn$cop $dst\t# signed, unsigned, long" %}
|
||||
ins_encode %{
|
||||
Assembler::Condition cond = (Assembler::Condition)($cop$$cmpcode);
|
||||
__ setb(MacroAssembler::negate_condition(cond), $dst$$Register);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct cmovL_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
|
||||
predicate(!UseAPX);
|
||||
match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
|
||||
|
||||
ins_cost(200);
|
||||
expand %{
|
||||
cmovL_regU(cop, cr, dst, src);
|
||||
%}
|
||||
%}
|
||||
|
||||
instruct cmovL_regUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1, rRegL src2)
|
||||
instruct cmovL_regUCFE_ndd(rRegL dst, cmpOpUCFE cop, rFlagsRegUCFE cr, rRegL src1, rRegL src2)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
|
||||
|
||||
ins_cost(200);
|
||||
format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
|
||||
format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, unsigned, long ndd" %}
|
||||
ins_encode %{
|
||||
__ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Register);
|
||||
%}
|
||||
@ -9658,7 +9692,7 @@ instruct cmovL_regUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1,
|
||||
%}
|
||||
|
||||
instruct cmovL_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
|
||||
predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
|
||||
predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
|
||||
match(Set dst (CMoveL (Binary cop cr) (Binary dst src)));
|
||||
|
||||
ins_cost(200); // XXX
|
||||
@ -9671,25 +9705,10 @@ instruct cmovL_regUCF2_ne(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src)
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
instruct cmovL_regUCF2_ne_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src1, rRegL src2) %{
|
||||
predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::ne);
|
||||
match(Set dst (CMoveL (Binary cop cr) (Binary src1 src2)));
|
||||
effect(TEMP dst);
|
||||
|
||||
ins_cost(200);
|
||||
format %{ "ecmovpq $dst, $src1, $src2\n\t"
|
||||
"cmovneq $dst, $src2" %}
|
||||
ins_encode %{
|
||||
__ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
|
||||
__ cmovq(Assembler::notEqual, $dst$$Register, $src2$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
// Since (x == y) == !(x != y), we can flip the sense of the test by flipping the
|
||||
// inputs of the CMove
|
||||
instruct cmovL_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src) %{
|
||||
predicate(!UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
|
||||
predicate(n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
|
||||
match(Set dst (CMoveL (Binary cop cr) (Binary src dst)));
|
||||
|
||||
ins_cost(200); // XXX
|
||||
@ -9702,21 +9721,6 @@ instruct cmovL_regUCF2_eq(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src)
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
instruct cmovL_regUCF2_eq_ndd(cmpOpUCF2 cop, rFlagsRegUCF cr, rRegL dst, rRegL src1, rRegL src2) %{
|
||||
predicate(UseAPX && n->in(1)->in(1)->as_Bool()->_test._test == BoolTest::eq);
|
||||
match(Set dst (CMoveL (Binary cop cr) (Binary src2 src1)));
|
||||
effect(TEMP dst);
|
||||
|
||||
ins_cost(200);
|
||||
format %{ "ecmovpq $dst, $src1, $src2\n\t"
|
||||
"cmovneq $dst, $src2" %}
|
||||
ins_encode %{
|
||||
__ ecmovq(Assembler::parity, $dst$$Register, $src1$$Register, $src2$$Register);
|
||||
__ cmovq(Assembler::notEqual, $dst$$Register, $src2$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_cmov_reg);
|
||||
%}
|
||||
|
||||
instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src)
|
||||
%{
|
||||
predicate(!UseAPX);
|
||||
@ -9731,8 +9735,8 @@ instruct cmovL_memU(cmpOpU cop, rFlagsRegU cr, rRegL dst, memory src)
|
||||
%}
|
||||
|
||||
instruct cmovL_memUCF(cmpOpUCF cop, rFlagsRegUCF cr, rRegL dst, memory src) %{
|
||||
predicate(!UseAPX);
|
||||
match(Set dst (CMoveL (Binary cop cr) (Binary dst (LoadL src))));
|
||||
|
||||
ins_cost(200);
|
||||
expand %{
|
||||
cmovL_memU(cop, cr, dst, src);
|
||||
@ -9752,12 +9756,12 @@ instruct cmovL_rReg_rReg_memU_ndd(rRegL dst, cmpOpU cop, rFlagsRegU cr, rRegL sr
|
||||
ins_pipe(pipe_cmov_mem);
|
||||
%}
|
||||
|
||||
instruct cmovL_rReg_rReg_memUCF_ndd(rRegL dst, cmpOpUCF cop, rFlagsRegUCF cr, rRegL src1, memory src2)
|
||||
instruct cmovL_rReg_rReg_memUCFE_ndd(rRegL dst, cmpOpUCFE cop, rFlagsRegUCFE cr, rRegL src1, memory src2)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
match(Set dst (CMoveL (Binary cop cr) (Binary src1 (LoadL src2))));
|
||||
|
||||
ins_cost(200);
|
||||
format %{ "ecmovq$cop $dst, $src1, $src2\t# unsigned, long ndd" %}
|
||||
format %{ "ecmovq$cop $dst, $src1, $src2\t# signed, unsigned, long ndd" %}
|
||||
ins_encode %{
|
||||
__ ecmovq((Assembler::Condition)($cop$$cmpcode), $dst$$Register, $src1$$Register, $src2$$Address);
|
||||
%}
|
||||
@ -9802,12 +9806,31 @@ instruct cmovF_regU(cmpOpU cop, rFlagsRegU cr, regF dst, regF src)
|
||||
|
||||
instruct cmovF_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regF dst, regF src) %{
|
||||
match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
|
||||
|
||||
ins_cost(200);
|
||||
expand %{
|
||||
cmovF_regU(cop, cr, dst, src);
|
||||
%}
|
||||
%}
|
||||
|
||||
instruct cmovF_regUCFE(cmpOpUCFE cop, rFlagsRegUCFE cr, regF dst, regF src)
|
||||
%{
|
||||
match(Set dst (CMoveF (Binary cop cr) (Binary dst src)));
|
||||
|
||||
ins_cost(200); // XXX
|
||||
format %{ "jn$cop skip\t# signed, unsigned cmove float\n\t"
|
||||
"movss $dst, $src\n"
|
||||
"skip:" %}
|
||||
ins_encode %{
|
||||
Label Lskip;
|
||||
// Invert sense of branch from sense of CMOV
|
||||
__ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip);
|
||||
__ movflt($dst$$XMMRegister, $src$$XMMRegister);
|
||||
__ bind(Lskip);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmovD_reg(cmpOp cop, rFlagsReg cr, regD dst, regD src)
|
||||
%{
|
||||
match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
|
||||
@ -9846,12 +9869,31 @@ instruct cmovD_regU(cmpOpU cop, rFlagsRegU cr, regD dst, regD src)
|
||||
|
||||
instruct cmovD_regUCF(cmpOpUCF cop, rFlagsRegUCF cr, regD dst, regD src) %{
|
||||
match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
|
||||
|
||||
ins_cost(200);
|
||||
expand %{
|
||||
cmovD_regU(cop, cr, dst, src);
|
||||
%}
|
||||
%}
|
||||
|
||||
instruct cmovD_regUCFE(cmpOpUCFE cop, rFlagsRegUCFE cr, regD dst, regD src)
|
||||
%{
|
||||
match(Set dst (CMoveD (Binary cop cr) (Binary dst src)));
|
||||
|
||||
ins_cost(200); // XXX
|
||||
format %{ "jn$cop skip\t# signed, unsigned cmove double\n\t"
|
||||
"movsd $dst, $src\n"
|
||||
"skip:" %}
|
||||
ins_encode %{
|
||||
Label Lskip;
|
||||
// Invert sense of branch from sense of CMOV
|
||||
__ jccb((Assembler::Condition)($cop$$cmpcode^1), Lskip);
|
||||
__ movdbl($dst$$XMMRegister, $src$$XMMRegister);
|
||||
__ bind(Lskip);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
//----------Arithmetic Instructions--------------------------------------------
|
||||
//----------Addition Instructions----------------------------------------------
|
||||
|
||||
@ -14319,7 +14361,7 @@ instruct cmpF_cc_reg(rFlagsRegU cr, regF src1, regF src2)
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmpF_cc_reg_CF(rFlagsRegUCF cr, regF src1, regF src2) %{
|
||||
instruct cmpF_cc_regCF(rFlagsRegUCF cr, regF src1, regF src2) %{
|
||||
match(Set cr (CmpF src1 src2));
|
||||
|
||||
ins_cost(100);
|
||||
@ -14330,6 +14372,17 @@ instruct cmpF_cc_reg_CF(rFlagsRegUCF cr, regF src1, regF src2) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmpF_cc_regCFE(rFlagsRegUCFE cr, regF src1, regF src2) %{
|
||||
match(Set cr (CmpF src1 src2));
|
||||
|
||||
ins_cost(100);
|
||||
format %{ "vucomxss $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ vucomxss($src1$$XMMRegister, $src2$$XMMRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmpF_cc_memCF(rFlagsRegUCF cr, regF src1, memory src2) %{
|
||||
match(Set cr (CmpF src1 (LoadF src2)));
|
||||
|
||||
@ -14341,8 +14394,20 @@ instruct cmpF_cc_memCF(rFlagsRegUCF cr, regF src1, memory src2) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmpF_cc_memCFE(rFlagsRegUCFE cr, regF src1, memory src2) %{
|
||||
match(Set cr (CmpF src1 (LoadF src2)));
|
||||
|
||||
ins_cost(100);
|
||||
format %{ "vucomxss $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ vucomxss($src1$$XMMRegister, $src2$$Address);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src, immF con) %{
|
||||
match(Set cr (CmpF src con));
|
||||
|
||||
ins_cost(100);
|
||||
format %{ "ucomiss $src, [$constantaddress]\t# load from constant table: float=$con" %}
|
||||
ins_encode %{
|
||||
@ -14351,6 +14416,17 @@ instruct cmpF_cc_immCF(rFlagsRegUCF cr, regF src, immF con) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmpF_cc_immCFE(rFlagsRegUCFE cr, regF src, immF con) %{
|
||||
match(Set cr (CmpF src con));
|
||||
|
||||
ins_cost(100);
|
||||
format %{ "vucomxss $src, [$constantaddress]\t# load from constant table: float=$con" %}
|
||||
ins_encode %{
|
||||
__ vucomxss($src$$XMMRegister, $constantaddress($con));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// Really expensive, avoid
|
||||
instruct cmpD_cc_reg(rFlagsRegU cr, regD src1, regD src2)
|
||||
%{
|
||||
@ -14370,7 +14446,7 @@ instruct cmpD_cc_reg(rFlagsRegU cr, regD src1, regD src2)
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmpD_cc_reg_CF(rFlagsRegUCF cr, regD src1, regD src2) %{
|
||||
instruct cmpD_cc_regCF(rFlagsRegUCF cr, regD src1, regD src2) %{
|
||||
match(Set cr (CmpD src1 src2));
|
||||
|
||||
ins_cost(100);
|
||||
@ -14381,6 +14457,17 @@ instruct cmpD_cc_reg_CF(rFlagsRegUCF cr, regD src1, regD src2) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmpD_cc_regCFE(rFlagsRegUCFE cr, regD src1, regD src2) %{
|
||||
match(Set cr (CmpD src1 src2));
|
||||
|
||||
ins_cost(100);
|
||||
format %{ "vucomxsd $src1, $src2 test" %}
|
||||
ins_encode %{
|
||||
__ vucomxsd($src1$$XMMRegister, $src2$$XMMRegister);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmpD_cc_memCF(rFlagsRegUCF cr, regD src1, memory src2) %{
|
||||
match(Set cr (CmpD src1 (LoadD src2)));
|
||||
|
||||
@ -14392,6 +14479,17 @@ instruct cmpD_cc_memCF(rFlagsRegUCF cr, regD src1, memory src2) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmpD_cc_memCFE(rFlagsRegUCFE cr, regD src1, memory src2) %{
|
||||
match(Set cr (CmpD src1 (LoadD src2)));
|
||||
|
||||
ins_cost(100);
|
||||
format %{ "vucomxsd $src1, $src2" %}
|
||||
ins_encode %{
|
||||
__ vucomxsd($src1$$XMMRegister, $src2$$Address);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src, immD con) %{
|
||||
match(Set cr (CmpD src con));
|
||||
ins_cost(100);
|
||||
@ -14402,6 +14500,17 @@ instruct cmpD_cc_immCF(rFlagsRegUCF cr, regD src, immD con) %{
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
instruct cmpD_cc_immCFE(rFlagsRegUCFE cr, regD src, immD con) %{
|
||||
match(Set cr (CmpD src con));
|
||||
|
||||
ins_cost(100);
|
||||
format %{ "vucomxsd $src, [$constantaddress]\t# load from constant table: double=$con" %}
|
||||
ins_encode %{
|
||||
__ vucomxsd($src$$XMMRegister, $constantaddress($con));
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// Compare into -1,0,1
|
||||
instruct cmpF_reg(rRegI dst, regF src1, regF src2, rFlagsReg cr)
|
||||
%{
|
||||
@ -16808,6 +16917,21 @@ instruct jmpConUCF2(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{
|
||||
ins_pipe(pipe_jcc);
|
||||
%}
|
||||
|
||||
// Jump Direct Conditional - using signed and unsigned comparison
|
||||
instruct jmpConUCFE(cmpOpUCFE cop, rFlagsRegUCFE cmp, label labl) %{
|
||||
match(If cop cmp);
|
||||
effect(USE labl);
|
||||
|
||||
ins_cost(200);
|
||||
format %{ "j$cop,su $labl" %}
|
||||
size(6);
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
__ jcc((Assembler::Condition)($cop$$cmpcode), *L, false); // Always long jump
|
||||
%}
|
||||
ins_pipe(pipe_jcc);
|
||||
%}
|
||||
|
||||
// ============================================================================
|
||||
// The 2nd slow-half of a subtype check. Scan the subklass's 2ndary
|
||||
// superklass array for an instance of the superklass. Set a hidden
|
||||
@ -17026,6 +17150,22 @@ instruct jmpConUCF2_short(cmpOpUCF2 cop, rFlagsRegUCF cmp, label labl) %{
|
||||
ins_short_branch(1);
|
||||
%}
|
||||
|
||||
// Jump Direct Conditional - using signed and unsigned comparison
|
||||
instruct jmpConUCFE_short(cmpOpUCFE cop, rFlagsRegUCFE cmp, label labl) %{
|
||||
match(If cop cmp);
|
||||
effect(USE labl);
|
||||
|
||||
ins_cost(300);
|
||||
format %{ "j$cop,sus $labl" %}
|
||||
size(2);
|
||||
ins_encode %{
|
||||
Label* L = $labl$$label;
|
||||
__ jccb((Assembler::Condition)($cop$$cmpcode), *L);
|
||||
%}
|
||||
ins_pipe(pipe_jcc);
|
||||
ins_short_branch(1);
|
||||
%}
|
||||
|
||||
// ============================================================================
|
||||
// inlined locking and unlocking
|
||||
|
||||
|
||||
@ -26,6 +26,8 @@
|
||||
#ifndef CPU_ZERO_BYTECODEINTERPRETER_ZERO_INLINE_HPP
|
||||
#define CPU_ZERO_BYTECODEINTERPRETER_ZERO_INLINE_HPP
|
||||
|
||||
#include "sanitizers/ub.hpp"
|
||||
|
||||
// Inline interpreter functions for zero
|
||||
|
||||
inline jfloat BytecodeInterpreter::VMfloatAdd(jfloat op1, jfloat op2) {
|
||||
@ -40,6 +42,7 @@ inline jfloat BytecodeInterpreter::VMfloatMul(jfloat op1, jfloat op2) {
|
||||
return op1 * op2;
|
||||
}
|
||||
|
||||
ATTRIBUTE_NO_UBSAN // IEEE-754 division by zero is well-defined
|
||||
inline jfloat BytecodeInterpreter::VMfloatDiv(jfloat op1, jfloat op2) {
|
||||
return op1 / op2;
|
||||
}
|
||||
@ -68,7 +71,7 @@ inline void BytecodeInterpreter::VMmemCopy64(uint32_t to[2],
|
||||
}
|
||||
|
||||
inline jlong BytecodeInterpreter::VMlongAdd(jlong op1, jlong op2) {
|
||||
return op1 + op2;
|
||||
return java_add(op1, op2);
|
||||
}
|
||||
|
||||
inline jlong BytecodeInterpreter::VMlongAnd(jlong op1, jlong op2) {
|
||||
@ -82,7 +85,7 @@ inline jlong BytecodeInterpreter::VMlongDiv(jlong op1, jlong op2) {
|
||||
}
|
||||
|
||||
inline jlong BytecodeInterpreter::VMlongMul(jlong op1, jlong op2) {
|
||||
return op1 * op2;
|
||||
return java_multiply(op1, op2);
|
||||
}
|
||||
|
||||
inline jlong BytecodeInterpreter::VMlongOr(jlong op1, jlong op2) {
|
||||
@ -90,7 +93,7 @@ inline jlong BytecodeInterpreter::VMlongOr(jlong op1, jlong op2) {
|
||||
}
|
||||
|
||||
inline jlong BytecodeInterpreter::VMlongSub(jlong op1, jlong op2) {
|
||||
return op1 - op2;
|
||||
return java_subtract(op1, op2);
|
||||
}
|
||||
|
||||
inline jlong BytecodeInterpreter::VMlongXor(jlong op1, jlong op2) {
|
||||
@ -104,19 +107,19 @@ inline jlong BytecodeInterpreter::VMlongRem(jlong op1, jlong op2) {
|
||||
}
|
||||
|
||||
inline jlong BytecodeInterpreter::VMlongUshr(jlong op1, jint op2) {
|
||||
return ((unsigned long long) op1) >> (op2 & 0x3F);
|
||||
return java_shift_right_unsigned(op1, op2);
|
||||
}
|
||||
|
||||
inline jlong BytecodeInterpreter::VMlongShr(jlong op1, jint op2) {
|
||||
return op1 >> (op2 & 0x3F);
|
||||
return java_shift_right(op1, op2);
|
||||
}
|
||||
|
||||
inline jlong BytecodeInterpreter::VMlongShl(jlong op1, jint op2) {
|
||||
return op1 << (op2 & 0x3F);
|
||||
return java_shift_left(op1, op2);
|
||||
}
|
||||
|
||||
inline jlong BytecodeInterpreter::VMlongNeg(jlong op) {
|
||||
return -op;
|
||||
return java_negate(op);
|
||||
}
|
||||
|
||||
inline jlong BytecodeInterpreter::VMlongNot(jlong op) {
|
||||
@ -183,8 +186,8 @@ inline jdouble BytecodeInterpreter::VMdoubleAdd(jdouble op1, jdouble op2) {
|
||||
return op1 + op2;
|
||||
}
|
||||
|
||||
ATTRIBUTE_NO_UBSAN // IEEE-754 division by zero is well-defined
|
||||
inline jdouble BytecodeInterpreter::VMdoubleDiv(jdouble op1, jdouble op2) {
|
||||
// Divide by zero... QQQ
|
||||
return op1 / op2;
|
||||
}
|
||||
|
||||
@ -228,7 +231,7 @@ inline jdouble BytecodeInterpreter::VMfloat2Double(jfloat op) {
|
||||
// Integer Arithmetic
|
||||
|
||||
inline jint BytecodeInterpreter::VMintAdd(jint op1, jint op2) {
|
||||
return op1 + op2;
|
||||
return java_add(op1, op2);
|
||||
}
|
||||
|
||||
inline jint BytecodeInterpreter::VMintAnd(jint op1, jint op2) {
|
||||
@ -242,11 +245,11 @@ inline jint BytecodeInterpreter::VMintDiv(jint op1, jint op2) {
|
||||
}
|
||||
|
||||
inline jint BytecodeInterpreter::VMintMul(jint op1, jint op2) {
|
||||
return op1 * op2;
|
||||
return java_multiply(op1, op2);
|
||||
}
|
||||
|
||||
inline jint BytecodeInterpreter::VMintNeg(jint op) {
|
||||
return -op;
|
||||
return java_negate(op);
|
||||
}
|
||||
|
||||
inline jint BytecodeInterpreter::VMintOr(jint op1, jint op2) {
|
||||
@ -260,19 +263,19 @@ inline jint BytecodeInterpreter::VMintRem(jint op1, jint op2) {
|
||||
}
|
||||
|
||||
inline jint BytecodeInterpreter::VMintShl(jint op1, jint op2) {
|
||||
return op1 << (op2 & 0x1F);
|
||||
return java_shift_left(op1, op2);
|
||||
}
|
||||
|
||||
inline jint BytecodeInterpreter::VMintShr(jint op1, jint op2) {
|
||||
return op1 >> (op2 & 0x1F);
|
||||
return java_shift_right(op1, op2);
|
||||
}
|
||||
|
||||
inline jint BytecodeInterpreter::VMintSub(jint op1, jint op2) {
|
||||
return op1 - op2;
|
||||
return java_subtract(op1, op2);
|
||||
}
|
||||
|
||||
inline juint BytecodeInterpreter::VMintUshr(jint op1, jint op2) {
|
||||
return ((juint) op1) >> (op2 & 0x1F);
|
||||
return java_shift_right_unsigned(op1, op2);
|
||||
}
|
||||
|
||||
inline jint BytecodeInterpreter::VMintXor(jint op1, jint op2) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -39,7 +39,7 @@ define_pd_global(bool, UncommonNullCast, true);
|
||||
define_pd_global(bool, DelayCompilerStubsGeneration, false); // Don't have compiler's stubs
|
||||
|
||||
define_pd_global(size_t, CodeCacheSegmentSize, 64 COMPILER1_AND_COMPILER2_PRESENT(+64)); // Tiered compilation has large code-entry alignment.
|
||||
define_pd_global(intx, CodeEntryAlignment, 32);
|
||||
define_pd_global(uint, CodeEntryAlignment, 32);
|
||||
define_pd_global(intx, OptoLoopAlignment, 16);
|
||||
define_pd_global(intx, InlineSmallCode, 1000);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2007 Red Hat, Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -48,7 +48,6 @@ class RegisterImpl : public AbstractRegisterImpl {
|
||||
};
|
||||
|
||||
// construction
|
||||
inline friend Register as_Register(int encoding);
|
||||
VMReg as_VMReg();
|
||||
|
||||
// derived registers, offsets, and addresses
|
||||
@ -113,7 +112,6 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl {
|
||||
static const int max_fpr;
|
||||
};
|
||||
|
||||
CONSTANT_REGISTER_DECLARATION(Register, noreg, (-1));
|
||||
#define noreg ((Register)(noreg_RegisterEnumValue))
|
||||
const Register noreg = as_Register(-1);
|
||||
|
||||
#endif // CPU_ZERO_REGISTER_ZERO_HPP
|
||||
|
||||
@ -368,12 +368,15 @@ int ZeroInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
||||
goto unlock_unwind_and_return;
|
||||
|
||||
void **arguments;
|
||||
void *mirror; {
|
||||
// These locals must remain on stack until call completes
|
||||
void *mirror;
|
||||
void *env;
|
||||
{
|
||||
arguments =
|
||||
(void **) stack->alloc(handler->argument_count() * sizeof(void **));
|
||||
void **dst = arguments;
|
||||
|
||||
void *env = thread->jni_environment();
|
||||
env = thread->jni_environment();
|
||||
*(dst++) = &env;
|
||||
|
||||
if (method->is_static()) {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2024 SAP SE. All rights reserved.
|
||||
* Copyright (c) 2005, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2026 SAP SE. 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
|
||||
@ -61,10 +61,6 @@
|
||||
product(bool, OptimizePollingPageLocation, true, DIAGNOSTIC, \
|
||||
"Optimize the location of the polling page used for Safepoints") \
|
||||
\
|
||||
/* Use 64K pages for virtual memory (shmat). */ \
|
||||
product(bool, Use64KPages, true, DIAGNOSTIC, \
|
||||
"Use 64K pages if available.") \
|
||||
\
|
||||
/* Normally AIX commits memory on touch, but sometimes it is helpful to have */ \
|
||||
/* explicit commit behaviour. This flag, if true, causes the VM to touch */ \
|
||||
/* memory on os::commit_memory() (which normally is a noop). */ \
|
||||
@ -79,7 +75,6 @@
|
||||
//
|
||||
|
||||
// UseLargePages means nothing, for now, on AIX.
|
||||
// Use Use64KPages or Use16MPages instead.
|
||||
define_pd_global(size_t, PreTouchParallelChunkSize, 1 * G);
|
||||
define_pd_global(bool, UseLargePages, false);
|
||||
define_pd_global(bool, UseLargePagesIndividualAllocation, false);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019 SAP SE. All rights reserved.
|
||||
* Copyright (c) 2015, 2026 SAP SE. 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
|
||||
@ -63,13 +63,12 @@ dynamicOdm::~dynamicOdm() {
|
||||
void odmWrapper::clean_data() { if (_data) { permit_forbidden_function::free(_data); _data = nullptr; } }
|
||||
|
||||
|
||||
int odmWrapper::class_offset(const char *field, bool is_aix_5)
|
||||
int odmWrapper::class_offset(const char *field)
|
||||
{
|
||||
assert(has_class(), "initialization");
|
||||
for (int i = 0; i < odm_class()->nelem; i++) {
|
||||
if (strcmp(odm_class()->elem[i].elemname, field) == 0) {
|
||||
int offset = odm_class()->elem[i].offset;
|
||||
if (is_aix_5) { offset += LINK_VAL_OFFSET; }
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
@ -88,11 +87,10 @@ void odmWrapper::determine_os_kernel_version(uint32_t* p_ver) {
|
||||
return;
|
||||
}
|
||||
int voff, roff, moff, foff;
|
||||
bool is_aix_5 = (major_aix_version == 5);
|
||||
voff = odm.class_offset("ver", is_aix_5);
|
||||
roff = odm.class_offset("rel", is_aix_5);
|
||||
moff = odm.class_offset("mod", is_aix_5);
|
||||
foff = odm.class_offset("fix", is_aix_5);
|
||||
voff = odm.class_offset("ver");
|
||||
roff = odm.class_offset("rel");
|
||||
moff = odm.class_offset("mod");
|
||||
foff = odm.class_offset("fix");
|
||||
if (voff == -1 || roff == -1 || moff == -1 || foff == -1) {
|
||||
trcVerbose("try_determine_os_kernel_version: could not get offsets");
|
||||
return;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user