mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-24 04:54:40 +02:00
Merge
This commit is contained in:
commit
31d227f25d
47 changed files with 2083 additions and 407 deletions
|
@ -24,37 +24,30 @@
|
||||||
|
|
||||||
# Sets make macros for making debug version of VM
|
# Sets make macros for making debug version of VM
|
||||||
|
|
||||||
|
# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make
|
||||||
|
# They may also specify FASTDEBUG_CFLAGS, but it defaults to DEBUG_CFLAGS.
|
||||||
|
|
||||||
|
FASTDEBUG_CFLAGS$(FASTDEBUG_CFLAGS) = $(DEBUG_CFLAGS)
|
||||||
|
|
||||||
# Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make
|
# Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make
|
||||||
OPT_CFLAGS/DEFAULT= $(OPT_CFLAGS)
|
OPT_CFLAGS/DEFAULT= $(OPT_CFLAGS)
|
||||||
OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@))
|
OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@))
|
||||||
|
|
||||||
# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files)
|
# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files)
|
||||||
|
|
||||||
ifeq ($(BUILDARCH), ia64)
|
|
||||||
# Bug in GCC, causes hang. -O1 will override the -O3 specified earlier
|
|
||||||
OPT_CFLAGS/callGenerator.o += -O1
|
|
||||||
OPT_CFLAGS/ciTypeFlow.o += -O1
|
|
||||||
OPT_CFLAGS/compile.o += -O1
|
|
||||||
OPT_CFLAGS/concurrentMarkSweepGeneration.o += -O1
|
|
||||||
OPT_CFLAGS/doCall.o += -O1
|
|
||||||
OPT_CFLAGS/generateOopMap.o += -O1
|
|
||||||
OPT_CFLAGS/generateOptoStub.o += -O1
|
|
||||||
OPT_CFLAGS/graphKit.o += -O1
|
|
||||||
OPT_CFLAGS/instanceKlass.o += -O1
|
|
||||||
OPT_CFLAGS/interpreterRT_ia64.o += -O1
|
|
||||||
OPT_CFLAGS/output.o += -O1
|
|
||||||
OPT_CFLAGS/parse1.o += -O1
|
|
||||||
OPT_CFLAGS/runtime.o += -O1
|
|
||||||
OPT_CFLAGS/synchronizer.o += -O1
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
# If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings
|
# If you set HOTSPARC_GENERIC=yes, you disable all OPT_CFLAGS settings
|
||||||
CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE)
|
CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE)
|
||||||
|
|
||||||
# Set the environment variable HOTSPARC_GENERIC to "true"
|
# Set the environment variable HOTSPARC_GENERIC to "true"
|
||||||
# to inhibit the effect of the previous line on CFLAGS.
|
# to inhibit the effect of the previous line on CFLAGS.
|
||||||
|
|
||||||
|
# The following lines are copied from debug.make, except that we
|
||||||
|
# consult FASTDEBUG_CFLAGS instead of DEBUG_CFLAGS.
|
||||||
|
# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make
|
||||||
|
DEBUG_CFLAGS/DEFAULT= $(FASTDEBUG_CFLAGS)
|
||||||
|
DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@))
|
||||||
|
CFLAGS += $(DEBUG_CFLAGS/BYFILE)
|
||||||
|
|
||||||
# Linker mapfile
|
# Linker mapfile
|
||||||
MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug
|
MAPFILE = $(GAMMADIR)/make/bsd/makefiles/mapfile-vers-debug
|
||||||
ifeq ($(OS_VENDOR), Darwin)
|
ifeq ($(OS_VENDOR), Darwin)
|
||||||
|
|
|
@ -100,7 +100,7 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_CLANG), true)
|
ifeq ($(USE_CLANG), true)
|
||||||
# clang has precompiled headers support by default, but the user can switch
|
# Clang has precompiled headers support by default, but the user can switch
|
||||||
# it off by using 'USE_PRECOMPILED_HEADER=0'.
|
# it off by using 'USE_PRECOMPILED_HEADER=0'.
|
||||||
ifdef LP64
|
ifdef LP64
|
||||||
ifeq ($(USE_PRECOMPILED_HEADER),)
|
ifeq ($(USE_PRECOMPILED_HEADER),)
|
||||||
|
@ -278,15 +278,18 @@ ifeq ($(OS_VENDOR), Darwin)
|
||||||
CFLAGS_WARN/os_bsd.o = $(CFLAGS_WARN/DEFAULT) -Wno-deprecated-declarations
|
CFLAGS_WARN/os_bsd.o = $(CFLAGS_WARN/DEFAULT) -Wno-deprecated-declarations
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# optimization control flags (Used by fastdebug and release variants)
|
||||||
|
OPT_CFLAGS/NOOPT=-O0
|
||||||
|
ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 8 \) \))" "1"
|
||||||
|
# Allow basic optimizations which don't distrupt debugging. (Principally dead code elimination)
|
||||||
|
OPT_CFLAGS/DEBUG=-Og
|
||||||
|
else
|
||||||
|
# Allow no optimizations.
|
||||||
|
OPT_CFLAGS/DEBUG=-O0
|
||||||
|
endif
|
||||||
OPT_CFLAGS/SIZE=-Os
|
OPT_CFLAGS/SIZE=-Os
|
||||||
OPT_CFLAGS/SPEED=-O3
|
OPT_CFLAGS/SPEED=-O3
|
||||||
|
|
||||||
# Hotspot uses very unstrict aliasing turn this optimization off
|
|
||||||
# This option is added to CFLAGS rather than OPT_CFLAGS
|
|
||||||
# so that OPT_CFLAGS overrides get this option too.
|
|
||||||
CFLAGS += -fno-strict-aliasing
|
|
||||||
|
|
||||||
# The flags to use for an Optimized g++ build
|
|
||||||
ifeq ($(OS_VENDOR), Darwin)
|
ifeq ($(OS_VENDOR), Darwin)
|
||||||
# use -Os by default, unless -O3 can be proved to be worth the cost, as per policy
|
# use -Os by default, unless -O3 can be proved to be worth the cost, as per policy
|
||||||
# <https://wiki.openjdk.java.net/display/MacOSXPort/Compiler+Errata>
|
# <https://wiki.openjdk.java.net/display/MacOSXPort/Compiler+Errata>
|
||||||
|
@ -295,6 +298,11 @@ else
|
||||||
OPT_CFLAGS_DEFAULT ?= SPEED
|
OPT_CFLAGS_DEFAULT ?= SPEED
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Hotspot uses very unstrict aliasing turn this optimization off
|
||||||
|
# This option is added to CFLAGS rather than OPT_CFLAGS
|
||||||
|
# so that OPT_CFLAGS overrides get this option too.
|
||||||
|
CFLAGS += -fno-strict-aliasing
|
||||||
|
|
||||||
ifdef OPT_CFLAGS
|
ifdef OPT_CFLAGS
|
||||||
ifneq ("$(origin OPT_CFLAGS)", "command line")
|
ifneq ("$(origin OPT_CFLAGS)", "command line")
|
||||||
$(error " Use OPT_EXTRAS instead of OPT_CFLAGS to add extra flags to OPT_CFLAGS.")
|
$(error " Use OPT_EXTRAS instead of OPT_CFLAGS to add extra flags to OPT_CFLAGS.")
|
||||||
|
@ -309,8 +317,6 @@ ifeq ($(BUILDARCH), ia64)
|
||||||
OPT_CFLAGS += -fno-expensive-optimizations
|
OPT_CFLAGS += -fno-expensive-optimizations
|
||||||
endif
|
endif
|
||||||
|
|
||||||
OPT_CFLAGS/NOOPT=-O0
|
|
||||||
|
|
||||||
# Work around some compiler bugs.
|
# Work around some compiler bugs.
|
||||||
ifeq ($(USE_CLANG), true)
|
ifeq ($(USE_CLANG), true)
|
||||||
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 2), 1)
|
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 2), 1)
|
||||||
|
@ -371,10 +377,22 @@ endif
|
||||||
|
|
||||||
ifeq ($(USE_CLANG),)
|
ifeq ($(USE_CLANG),)
|
||||||
# statically link libgcc and/or libgcc_s, libgcc does not exist before gcc-3.x.
|
# statically link libgcc and/or libgcc_s, libgcc does not exist before gcc-3.x.
|
||||||
ifneq ("${CC_VER_MAJOR}", "2")
|
ifneq ($(CC_VER_MAJOR), 2)
|
||||||
STATIC_LIBGCC += -static-libgcc
|
STATIC_LIBGCC += -static-libgcc
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(OS_VENDOR), Darwin)
|
||||||
|
ifneq (, findstring(debug,$(BUILD_FLAVOR)))
|
||||||
|
# for relocations read-only
|
||||||
|
LFLAGS += -Xlinker -z -Xlinker relro
|
||||||
|
|
||||||
|
ifeq ($(BUILD_FLAVOR), debug)
|
||||||
|
# disable incremental relocations linking
|
||||||
|
LFLAGS += -Xlinker -z -Xlinker now
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(BUILDARCH), ia64)
|
ifeq ($(BUILDARCH), ia64)
|
||||||
LFLAGS += -Wl,-relax
|
LFLAGS += -Wl,-relax
|
||||||
endif
|
endif
|
||||||
|
@ -425,6 +443,14 @@ ifeq ($(USE_CLANG), true)
|
||||||
CFLAGS += -flimit-debug-info
|
CFLAGS += -flimit-debug-info
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 8 \) \))" "1"
|
||||||
|
# Allow basic optimizations which don't distrupt debugging. (Principally dead code elimination)
|
||||||
|
DEBUG_CFLAGS=-Og
|
||||||
|
else
|
||||||
|
# Allow no optimizations.
|
||||||
|
DEBUG_CFLAGS=-O0
|
||||||
|
endif
|
||||||
|
|
||||||
# DEBUG_BINARIES uses full -g debug information for all configs
|
# DEBUG_BINARIES uses full -g debug information for all configs
|
||||||
ifeq ($(DEBUG_BINARIES), true)
|
ifeq ($(DEBUG_BINARIES), true)
|
||||||
CFLAGS += -g
|
CFLAGS += -g
|
||||||
|
@ -441,8 +467,13 @@ else
|
||||||
DEBUG_CFLAGS/ppc = -g
|
DEBUG_CFLAGS/ppc = -g
|
||||||
DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH))
|
DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH))
|
||||||
ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),)
|
ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),)
|
||||||
|
ifeq ($(USE_CLANG), true)
|
||||||
|
# Clang doesn't understand -gstabs
|
||||||
|
DEBUG_CFLAGS += -g
|
||||||
|
else
|
||||||
DEBUG_CFLAGS += -gstabs
|
DEBUG_CFLAGS += -gstabs
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||||
FASTDEBUG_CFLAGS/ia64 = -g
|
FASTDEBUG_CFLAGS/ia64 = -g
|
||||||
|
@ -475,6 +506,18 @@ else
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(USE_CLANG),)
|
||||||
|
# Enable bounds checking.
|
||||||
|
# _FORTIFY_SOURCE appears in GCC 4.0+
|
||||||
|
ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) )" "1"
|
||||||
|
# compile time size bounds checks
|
||||||
|
FASTDEBUG_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
|
||||||
|
|
||||||
|
# and runtime size bounds checks and paranoid stack smashing checks.
|
||||||
|
DEBUG_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
# If we are building HEADLESS, pass on to VM
|
# If we are building HEADLESS, pass on to VM
|
||||||
# so it can set the java.awt.headless property
|
# so it can set the java.awt.headless property
|
||||||
ifdef HEADLESS
|
ifdef HEADLESS
|
||||||
|
|
|
@ -24,6 +24,11 @@
|
||||||
|
|
||||||
# Sets make macros for making debug version of VM
|
# Sets make macros for making debug version of VM
|
||||||
|
|
||||||
|
# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make
|
||||||
|
# They may also specify FASTDEBUG_CFLAGS, but it defaults to DEBUG_CFLAGS.
|
||||||
|
|
||||||
|
FASTDEBUG_CFLAGS$(FASTDEBUG_CFLAGS) = $(DEBUG_CFLAGS)
|
||||||
|
|
||||||
# Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make
|
# Compiler specific OPT_CFLAGS are passed in from gcc.make, sparcWorks.make
|
||||||
OPT_CFLAGS/DEFAULT= $(OPT_CFLAGS)
|
OPT_CFLAGS/DEFAULT= $(OPT_CFLAGS)
|
||||||
OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@))
|
OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@))
|
||||||
|
@ -54,6 +59,12 @@ CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE)
|
||||||
|
|
||||||
# Set the environment variable HOTSPARC_GENERIC to "true"
|
# Set the environment variable HOTSPARC_GENERIC to "true"
|
||||||
# to inhibit the effect of the previous line on CFLAGS.
|
# to inhibit the effect of the previous line on CFLAGS.
|
||||||
|
# The following lines are copied from debug.make, except that we
|
||||||
|
# consult FASTDEBUG_CFLAGS instead of DEBUG_CFLAGS.
|
||||||
|
# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make
|
||||||
|
DEBUG_CFLAGS/DEFAULT= $(FASTDEBUG_CFLAGS)
|
||||||
|
DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@))
|
||||||
|
CFLAGS += $(DEBUG_CFLAGS/BYFILE)
|
||||||
|
|
||||||
# Linker mapfile
|
# Linker mapfile
|
||||||
MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug
|
MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug
|
||||||
|
|
|
@ -62,7 +62,6 @@ else
|
||||||
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
|
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(USE_CLANG), true)
|
ifeq ($(USE_CLANG), true)
|
||||||
# Clang has precompiled headers support by default, but the user can switch
|
# Clang has precompiled headers support by default, but the user can switch
|
||||||
# it off by using 'USE_PRECOMPILED_HEADER=0'.
|
# it off by using 'USE_PRECOMPILED_HEADER=0'.
|
||||||
|
@ -104,7 +103,7 @@ ifeq ($(USE_CLANG), true)
|
||||||
# But Clang doesn't support a precompiled header which was compiled with -O3
|
# But Clang doesn't support a precompiled header which was compiled with -O3
|
||||||
# to be used in a compilation unit which uses '-O0'. We could also prepare an
|
# to be used in a compilation unit which uses '-O0'. We could also prepare an
|
||||||
# extra '-O0' PCH file for the opt build and use it here, but it's probably
|
# extra '-O0' PCH file for the opt build and use it here, but it's probably
|
||||||
# not worth the effoert as long as only two files need this special handling.
|
# not worth the effort as long as only two files need this special handling.
|
||||||
PCH_FLAG/loopTransform.o = $(PCH_FLAG/NO_PCH)
|
PCH_FLAG/loopTransform.o = $(PCH_FLAG/NO_PCH)
|
||||||
PCH_FLAG/sharedRuntimeTrig.o = $(PCH_FLAG/NO_PCH)
|
PCH_FLAG/sharedRuntimeTrig.o = $(PCH_FLAG/NO_PCH)
|
||||||
PCH_FLAG/sharedRuntimeTrans.o = $(PCH_FLAG/NO_PCH)
|
PCH_FLAG/sharedRuntimeTrans.o = $(PCH_FLAG/NO_PCH)
|
||||||
|
@ -226,20 +225,29 @@ ifeq ($(USE_CLANG),)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(WARNING_FLAGS)
|
CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(WARNING_FLAGS)
|
||||||
|
|
||||||
# Special cases
|
# Special cases
|
||||||
CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@))
|
CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@))
|
||||||
|
|
||||||
# The flags to use for an Optimized g++ build
|
# optimization control flags (Used by fastdebug and release variants)
|
||||||
|
OPT_CFLAGS/NOOPT=-O0
|
||||||
|
ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 8 \) \))" "1"
|
||||||
|
# Allow basic optimizations which don't distrupt debugging. (Principally dead code elimination)
|
||||||
|
OPT_CFLAGS/DEBUG=-Og
|
||||||
|
else
|
||||||
|
# Allow no optimizations.
|
||||||
|
OPT_CFLAGS/DEBUG=-O0
|
||||||
|
endif
|
||||||
OPT_CFLAGS/SIZE=-Os
|
OPT_CFLAGS/SIZE=-Os
|
||||||
OPT_CFLAGS/SPEED=-O3
|
OPT_CFLAGS/SPEED=-O3
|
||||||
|
|
||||||
|
OPT_CFLAGS_DEFAULT ?= SPEED
|
||||||
|
|
||||||
# Hotspot uses very unstrict aliasing turn this optimization off
|
# Hotspot uses very unstrict aliasing turn this optimization off
|
||||||
# This option is added to CFLAGS rather than OPT_CFLAGS
|
# This option is added to CFLAGS rather than OPT_CFLAGS
|
||||||
# so that OPT_CFLAGS overrides get this option too.
|
# so that OPT_CFLAGS overrides get this option too.
|
||||||
CFLAGS += -fno-strict-aliasing
|
CFLAGS += -fno-strict-aliasing
|
||||||
|
|
||||||
OPT_CFLAGS_DEFAULT ?= SPEED
|
|
||||||
|
|
||||||
ifdef OPT_CFLAGS
|
ifdef OPT_CFLAGS
|
||||||
ifneq ("$(origin OPT_CFLAGS)", "command line")
|
ifneq ("$(origin OPT_CFLAGS)", "command line")
|
||||||
$(error " Use OPT_EXTRAS instead of OPT_CFLAGS to add extra flags to OPT_CFLAGS.")
|
$(error " Use OPT_EXTRAS instead of OPT_CFLAGS to add extra flags to OPT_CFLAGS.")
|
||||||
|
@ -254,8 +262,6 @@ ifeq ($(BUILDARCH), ia64)
|
||||||
OPT_CFLAGS += -fno-expensive-optimizations
|
OPT_CFLAGS += -fno-expensive-optimizations
|
||||||
endif
|
endif
|
||||||
|
|
||||||
OPT_CFLAGS/NOOPT=-O0
|
|
||||||
|
|
||||||
# Work around some compiler bugs.
|
# Work around some compiler bugs.
|
||||||
ifeq ($(USE_CLANG), true)
|
ifeq ($(USE_CLANG), true)
|
||||||
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 2), 1)
|
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 2), 1)
|
||||||
|
@ -271,7 +277,7 @@ endif
|
||||||
# Flags for generating make dependency flags.
|
# Flags for generating make dependency flags.
|
||||||
DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
|
DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
|
||||||
ifeq ($(USE_CLANG),)
|
ifeq ($(USE_CLANG),)
|
||||||
ifneq ("${CC_VER_MAJOR}", "2")
|
ifneq ($(CC_VER_MAJOR), 2)
|
||||||
DEPFLAGS += -fpch-deps
|
DEPFLAGS += -fpch-deps
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -282,21 +288,26 @@ endif
|
||||||
# statically link libstdc++.so, work with gcc but ignored by g++
|
# statically link libstdc++.so, work with gcc but ignored by g++
|
||||||
STATIC_STDCXX = -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
|
STATIC_STDCXX = -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
|
||||||
|
|
||||||
|
# Enable linker optimization
|
||||||
|
LFLAGS += -Xlinker -O1
|
||||||
|
|
||||||
ifeq ($(USE_CLANG),)
|
ifeq ($(USE_CLANG),)
|
||||||
# statically link libgcc and/or libgcc_s, libgcc does not exist before gcc-3.x.
|
|
||||||
ifneq ("${CC_VER_MAJOR}", "2")
|
|
||||||
STATIC_LIBGCC += -static-libgcc
|
STATIC_LIBGCC += -static-libgcc
|
||||||
|
|
||||||
|
ifneq (, findstring(debug,$(BUILD_FLAVOR)))
|
||||||
|
# for relocations read-only
|
||||||
|
LFLAGS += -Xlinker -z -Xlinker relro
|
||||||
|
|
||||||
|
ifeq ($(BUILD_FLAVOR), debug)
|
||||||
|
# disable incremental relocations linking
|
||||||
|
LFLAGS += -Xlinker -z -Xlinker now
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(BUILDARCH), ia64)
|
ifeq ($(BUILDARCH), ia64)
|
||||||
LFLAGS += -Wl,-relax
|
LFLAGS += -Wl,-relax
|
||||||
endif
|
endif
|
||||||
endif
|
|
||||||
|
|
||||||
# Enable linker optimization
|
|
||||||
LFLAGS += -Xlinker -O1
|
|
||||||
|
|
||||||
ifeq ($(USE_CLANG),)
|
|
||||||
# If this is a --hash-style=gnu system, use --hash-style=both
|
# If this is a --hash-style=gnu system, use --hash-style=both
|
||||||
# The gnu .hash section won't work on some Linux systems like SuSE 10.
|
# The gnu .hash section won't work on some Linux systems like SuSE 10.
|
||||||
_HAS_HASH_STYLE_GNU:=$(shell $(CC) -dumpspecs | grep -- '--hash-style=gnu')
|
_HAS_HASH_STYLE_GNU:=$(shell $(CC) -dumpspecs | grep -- '--hash-style=gnu')
|
||||||
|
@ -333,6 +344,14 @@ ifeq ($(USE_CLANG), true)
|
||||||
CFLAGS += -flimit-debug-info
|
CFLAGS += -flimit-debug-info
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 8 \) \))" "1"
|
||||||
|
# Allow basic optimizations which don't distrupt debugging. (Principally dead code elimination)
|
||||||
|
DEBUG_CFLAGS=-Og
|
||||||
|
else
|
||||||
|
# Allow no optimizations.
|
||||||
|
DEBUG_CFLAGS=-O0
|
||||||
|
endif
|
||||||
|
|
||||||
# DEBUG_BINARIES uses full -g debug information for all configs
|
# DEBUG_BINARIES uses full -g debug information for all configs
|
||||||
ifeq ($(DEBUG_BINARIES), true)
|
ifeq ($(DEBUG_BINARIES), true)
|
||||||
CFLAGS += -g
|
CFLAGS += -g
|
||||||
|
@ -355,6 +374,18 @@ else
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(USE_CLANG),)
|
||||||
|
# Enable bounds checking.
|
||||||
|
# _FORTIFY_SOURCE appears in GCC 4.0+
|
||||||
|
ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) )" "1"
|
||||||
|
# compile time size bounds checks
|
||||||
|
FASTDEBUG_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
|
||||||
|
|
||||||
|
# and runtime size bounds checks and paranoid stack smashing checks.
|
||||||
|
DEBUG_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
# If we are building HEADLESS, pass on to VM
|
# If we are building HEADLESS, pass on to VM
|
||||||
# so it can set the java.awt.headless property
|
# so it can set the java.awt.headless property
|
||||||
ifdef HEADLESS
|
ifdef HEADLESS
|
||||||
|
|
|
@ -117,17 +117,40 @@ endif
|
||||||
|
|
||||||
# Compiler warnings are treated as errors
|
# Compiler warnings are treated as errors
|
||||||
WARNINGS_ARE_ERRORS = -Werror
|
WARNINGS_ARE_ERRORS = -Werror
|
||||||
|
|
||||||
# Enable these warnings. See 'info gcc' about details on these options
|
# Enable these warnings. See 'info gcc' about details on these options
|
||||||
WARNING_FLAGS = -Wpointer-arith -Wconversion -Wsign-compare -Wundef -Wformat=2
|
WARNING_FLAGS = -Wpointer-arith -Wconversion -Wsign-compare -Wundef -Wformat=2
|
||||||
CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(WARNING_FLAGS)
|
CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS) $(WARNING_FLAGS)
|
||||||
|
|
||||||
# Special cases
|
# Special cases
|
||||||
CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@))
|
CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@))
|
||||||
|
|
||||||
# The flags to use for an Optimized g++ build
|
# optimization control flags (Used by fastdebug and release variants)
|
||||||
OPT_CFLAGS += -O3
|
OPT_CFLAGS/NOOPT=-O0
|
||||||
|
ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 8 \) \))" "1"
|
||||||
|
# Allow basic optimizations which don't distrupt debugging. (Principally dead code elimination)
|
||||||
|
OPT_CFLAGS/DEBUG=-Og
|
||||||
|
+else
|
||||||
|
# Allow no optimizations.
|
||||||
|
OPT_CFLAGS/DEBUG=-O0
|
||||||
|
endif
|
||||||
|
OPT_CFLAGS/SIZE=-Os
|
||||||
|
OPT_CFLAGS/SPEED=-O3
|
||||||
|
|
||||||
|
OPT_CFLAGS_DEFAULT ?= SPEED
|
||||||
|
|
||||||
# Hotspot uses very unstrict aliasing turn this optimization off
|
# Hotspot uses very unstrict aliasing turn this optimization off
|
||||||
OPT_CFLAGS += -fno-strict-aliasing
|
# This option is added to CFLAGS rather than OPT_CFLAGS
|
||||||
|
# so that OPT_CFLAGS overrides get this option too.
|
||||||
|
CFLAGS += -fno-strict-aliasing
|
||||||
|
|
||||||
|
ifdef OPT_CFLAGS
|
||||||
|
ifneq ("$(origin OPT_CFLAGS)", "command line")
|
||||||
|
$(error " Use OPT_EXTRAS instead of OPT_CFLAGS to add extra flags to OPT_CFLAGS.")
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
OPT_CFLAGS = $(OPT_CFLAGS/$(OPT_CFLAGS_DEFAULT)) $(OPT_EXTRAS)
|
||||||
|
|
||||||
# The gcc compiler segv's on ia64 when compiling bytecodeInterpreter.cpp
|
# The gcc compiler segv's on ia64 when compiling bytecodeInterpreter.cpp
|
||||||
# if we use expensive-optimizations
|
# if we use expensive-optimizations
|
||||||
|
@ -137,10 +160,20 @@ ifeq ($(BUILDARCH), ia64)
|
||||||
OPT_CFLAGS/bytecodeInterpreter.o += -fno-expensive-optimizations
|
OPT_CFLAGS/bytecodeInterpreter.o += -fno-expensive-optimizations
|
||||||
endif
|
endif
|
||||||
|
|
||||||
OPT_CFLAGS/NOOPT=-O0
|
# Work around some compiler bugs.
|
||||||
|
ifeq ($(USE_CLANG), true)
|
||||||
|
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 2), 1)
|
||||||
|
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
|
||||||
|
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
|
||||||
|
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
# Flags for generating make dependency flags.
|
# Flags for generating make dependency flags.
|
||||||
ifneq ("${CC_VER_MAJOR}", "2")
|
ifneq ($(CC_VER_MAJOR), 2)
|
||||||
DEPFLAGS = -fpch-deps -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
|
DEPFLAGS = -fpch-deps -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -155,25 +188,36 @@ endif
|
||||||
# statically link libstdc++.so, work with gcc but ignored by g++
|
# statically link libstdc++.so, work with gcc but ignored by g++
|
||||||
STATIC_STDCXX = -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
|
STATIC_STDCXX = -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
|
||||||
|
|
||||||
# statically link libgcc and/or libgcc_s, libgcc does not exist before gcc-3.x.
|
|
||||||
ifneq ("${CC_VER_MAJOR}", "2")
|
|
||||||
STATIC_LIBGCC += -static-libgcc
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(BUILDARCH), ia64)
|
|
||||||
# Note: all ia64 setting reflect the ones for linux
|
|
||||||
# No actial testing was performed: there is no Solaris on ia64 presently
|
|
||||||
LFLAGS += -Wl,-relax
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef USE_GNULD
|
ifdef USE_GNULD
|
||||||
# Enable linker optimization
|
# statically link libgcc and/or libgcc_s, libgcc does not exist before gcc-3.x.
|
||||||
LFLAGS += -Xlinker -O1
|
ifneq ($(CC_VER_MAJOR), 2)
|
||||||
|
STATIC_LIBGCC += -static-libgcc
|
||||||
|
endif
|
||||||
|
|
||||||
# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file.
|
# Enable linker optimization
|
||||||
MAPFLAG = -Xlinker --version-script=FILENAME
|
LFLAGS += -Xlinker -O1
|
||||||
|
|
||||||
|
ifneq (, findstring(debug,$(BUILD_FLAVOR)))
|
||||||
|
# for relocations read-only
|
||||||
|
LFLAGS += -Xlinker -z -Xlinker relro
|
||||||
|
|
||||||
|
ifeq ($(BUILD_FLAVOR), debug)
|
||||||
|
# disable incremental relocations linking
|
||||||
|
LFLAGS += -Xlinker -z -Xlinker now
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(BUILDARCH), ia64)
|
||||||
|
# Note: all ia64 setting reflect the ones for linux
|
||||||
|
# No actual testing was performed: there is no Solaris on ia64 presently
|
||||||
|
LFLAGS += -Wl,-relax
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file.
|
||||||
|
MAPFLAG = -Xlinker --version-script=FILENAME
|
||||||
else
|
else
|
||||||
MAPFLAG = -Xlinker -M -Xlinker FILENAME
|
MAPFLAG = -Xlinker -M -Xlinker FILENAME
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj
|
# Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj
|
||||||
|
@ -185,6 +229,15 @@ SHARED_FLAG = -shared
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
# Debug flags
|
# Debug flags
|
||||||
|
|
||||||
|
ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 8 \) \))" "1"
|
||||||
|
# Allow basic optimizations which don't distrupt debugging. (Principally dead code elimination)
|
||||||
|
DEBUG_CFLAGS=-Og
|
||||||
|
else
|
||||||
|
# Allow no optimizations.
|
||||||
|
DEBUG_CFLAGS=-O0
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
# Use the stabs format for debugging information (this is the default
|
# Use the stabs format for debugging information (this is the default
|
||||||
# on gcc-2.91). It's good enough, has all the information about line
|
# on gcc-2.91). It's good enough, has all the information about line
|
||||||
# numbers and local variables, and libjvm.so is only about 16M.
|
# numbers and local variables, and libjvm.so is only about 16M.
|
||||||
|
@ -195,5 +248,15 @@ DEBUG_CFLAGS/ia64 = -g
|
||||||
DEBUG_CFLAGS/amd64 = -g
|
DEBUG_CFLAGS/amd64 = -g
|
||||||
DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH))
|
DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH))
|
||||||
ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),)
|
ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),)
|
||||||
DEBUG_CFLAGS += -gstabs
|
DEBUG_CFLAGS += -gstabs
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Enable bounds checking.
|
||||||
|
# _FORTIFY_SOURCE appears in GCC 4.0+
|
||||||
|
ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) )" "1"
|
||||||
|
# compile time size bounds checks
|
||||||
|
FASTDEBUG_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
|
||||||
|
|
||||||
|
# and runtime size bounds checks and paranoid stack smashing checks.
|
||||||
|
DEBUG_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -123,6 +123,7 @@ class Assembler : public AbstractAssembler {
|
||||||
fpop2_op3 = 0x35,
|
fpop2_op3 = 0x35,
|
||||||
impdep1_op3 = 0x36,
|
impdep1_op3 = 0x36,
|
||||||
aes3_op3 = 0x36,
|
aes3_op3 = 0x36,
|
||||||
|
sha_op3 = 0x36,
|
||||||
alignaddr_op3 = 0x36,
|
alignaddr_op3 = 0x36,
|
||||||
faligndata_op3 = 0x36,
|
faligndata_op3 = 0x36,
|
||||||
flog3_op3 = 0x36,
|
flog3_op3 = 0x36,
|
||||||
|
@ -223,7 +224,11 @@ class Assembler : public AbstractAssembler {
|
||||||
mwtos_opf = 0x119,
|
mwtos_opf = 0x119,
|
||||||
|
|
||||||
aes_kexpand0_opf = 0x130,
|
aes_kexpand0_opf = 0x130,
|
||||||
aes_kexpand2_opf = 0x131
|
aes_kexpand2_opf = 0x131,
|
||||||
|
|
||||||
|
sha1_opf = 0x141,
|
||||||
|
sha256_opf = 0x142,
|
||||||
|
sha512_opf = 0x143
|
||||||
};
|
};
|
||||||
|
|
||||||
enum op5s {
|
enum op5s {
|
||||||
|
@ -595,6 +600,11 @@ class Assembler : public AbstractAssembler {
|
||||||
// AES crypto instructions supported only on certain processors
|
// AES crypto instructions supported only on certain processors
|
||||||
static void aes_only() { assert( VM_Version::has_aes(), "This instruction only works on SPARC with AES instructions support"); }
|
static void aes_only() { assert( VM_Version::has_aes(), "This instruction only works on SPARC with AES instructions support"); }
|
||||||
|
|
||||||
|
// SHA crypto instructions supported only on certain processors
|
||||||
|
static void sha1_only() { assert( VM_Version::has_sha1(), "This instruction only works on SPARC with SHA1"); }
|
||||||
|
static void sha256_only() { assert( VM_Version::has_sha256(), "This instruction only works on SPARC with SHA256"); }
|
||||||
|
static void sha512_only() { assert( VM_Version::has_sha512(), "This instruction only works on SPARC with SHA512"); }
|
||||||
|
|
||||||
// instruction only in VIS1
|
// instruction only in VIS1
|
||||||
static void vis1_only() { assert( VM_Version::has_vis1(), "This instruction only works on SPARC with VIS1"); }
|
static void vis1_only() { assert( VM_Version::has_vis1(), "This instruction only works on SPARC with VIS1"); }
|
||||||
|
|
||||||
|
@ -1179,7 +1189,6 @@ public:
|
||||||
u_field(3, 29, 25) | immed(true) | simm(simm13a, 13)); }
|
u_field(3, 29, 25) | immed(true) | simm(simm13a, 13)); }
|
||||||
inline void wrfprs( Register d) { v9_only(); emit_int32( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); }
|
inline void wrfprs( Register d) { v9_only(); emit_int32( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); }
|
||||||
|
|
||||||
|
|
||||||
// VIS1 instructions
|
// VIS1 instructions
|
||||||
|
|
||||||
void alignaddr( Register s1, Register s2, Register d ) { vis1_only(); emit_int32( op(arith_op) | rd(d) | op3(alignaddr_op3) | rs1(s1) | opf(alignaddr_opf) | rs2(s2)); }
|
void alignaddr( Register s1, Register s2, Register d ) { vis1_only(); emit_int32( op(arith_op) | rd(d) | op3(alignaddr_op3) | rs1(s1) | opf(alignaddr_opf) | rs2(s2)); }
|
||||||
|
@ -1203,6 +1212,12 @@ public:
|
||||||
void movwtos( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); }
|
void movwtos( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); }
|
||||||
void movxtod( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); }
|
void movxtod( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); }
|
||||||
|
|
||||||
|
// Crypto SHA instructions
|
||||||
|
|
||||||
|
void sha1() { sha1_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha1_opf)); }
|
||||||
|
void sha256() { sha256_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha256_opf)); }
|
||||||
|
void sha512() { sha512_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha512_opf)); }
|
||||||
|
|
||||||
// Creation
|
// Creation
|
||||||
Assembler(CodeBuffer* code) : AbstractAssembler(code) {
|
Assembler(CodeBuffer* code) : AbstractAssembler(code) {
|
||||||
#ifdef CHECK_DELAY
|
#ifdef CHECK_DELAY
|
||||||
|
|
|
@ -4575,6 +4575,219 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
address generate_sha1_implCompress(bool multi_block, const char *name) {
|
||||||
|
__ align(CodeEntryAlignment);
|
||||||
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
|
address start = __ pc();
|
||||||
|
|
||||||
|
Label L_sha1_loop, L_sha1_unaligned_input, L_sha1_unaligned_input_loop;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
Register buf = O0; // byte[] source+offset
|
||||||
|
Register state = O1; // int[] SHA.state
|
||||||
|
Register ofs = O2; // int offset
|
||||||
|
Register limit = O3; // int limit
|
||||||
|
|
||||||
|
// load state into F0-F4
|
||||||
|
for (i = 0; i < 5; i++) {
|
||||||
|
__ ldf(FloatRegisterImpl::S, state, i*4, as_FloatRegister(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
__ andcc(buf, 7, G0);
|
||||||
|
__ br(Assembler::notZero, false, Assembler::pn, L_sha1_unaligned_input);
|
||||||
|
__ delayed()->nop();
|
||||||
|
|
||||||
|
__ BIND(L_sha1_loop);
|
||||||
|
// load buf into F8-F22
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
__ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 8));
|
||||||
|
}
|
||||||
|
__ sha1();
|
||||||
|
if (multi_block) {
|
||||||
|
__ add(ofs, 64, ofs);
|
||||||
|
__ add(buf, 64, buf);
|
||||||
|
__ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha1_loop);
|
||||||
|
__ mov(ofs, O0); // to be returned
|
||||||
|
}
|
||||||
|
|
||||||
|
// store F0-F4 into state and return
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
__ stf(FloatRegisterImpl::S, as_FloatRegister(i), state, i*4);
|
||||||
|
}
|
||||||
|
__ retl();
|
||||||
|
__ delayed()->stf(FloatRegisterImpl::S, F4, state, 0x10);
|
||||||
|
|
||||||
|
__ BIND(L_sha1_unaligned_input);
|
||||||
|
__ alignaddr(buf, G0, buf);
|
||||||
|
|
||||||
|
__ BIND(L_sha1_unaligned_input_loop);
|
||||||
|
// load buf into F8-F22
|
||||||
|
for (i = 0; i < 9; i++) {
|
||||||
|
__ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 8));
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
__ faligndata(as_FloatRegister(i*2 + 8), as_FloatRegister(i*2 + 10), as_FloatRegister(i*2 + 8));
|
||||||
|
}
|
||||||
|
__ sha1();
|
||||||
|
if (multi_block) {
|
||||||
|
__ add(ofs, 64, ofs);
|
||||||
|
__ add(buf, 64, buf);
|
||||||
|
__ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha1_unaligned_input_loop);
|
||||||
|
__ mov(ofs, O0); // to be returned
|
||||||
|
}
|
||||||
|
|
||||||
|
// store F0-F4 into state and return
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
__ stf(FloatRegisterImpl::S, as_FloatRegister(i), state, i*4);
|
||||||
|
}
|
||||||
|
__ retl();
|
||||||
|
__ delayed()->stf(FloatRegisterImpl::S, F4, state, 0x10);
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
address generate_sha256_implCompress(bool multi_block, const char *name) {
|
||||||
|
__ align(CodeEntryAlignment);
|
||||||
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
|
address start = __ pc();
|
||||||
|
|
||||||
|
Label L_sha256_loop, L_sha256_unaligned_input, L_sha256_unaligned_input_loop;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
Register buf = O0; // byte[] source+offset
|
||||||
|
Register state = O1; // int[] SHA2.state
|
||||||
|
Register ofs = O2; // int offset
|
||||||
|
Register limit = O3; // int limit
|
||||||
|
|
||||||
|
// load state into F0-F7
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
__ ldf(FloatRegisterImpl::S, state, i*4, as_FloatRegister(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
__ andcc(buf, 7, G0);
|
||||||
|
__ br(Assembler::notZero, false, Assembler::pn, L_sha256_unaligned_input);
|
||||||
|
__ delayed()->nop();
|
||||||
|
|
||||||
|
__ BIND(L_sha256_loop);
|
||||||
|
// load buf into F8-F22
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
__ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 8));
|
||||||
|
}
|
||||||
|
__ sha256();
|
||||||
|
if (multi_block) {
|
||||||
|
__ add(ofs, 64, ofs);
|
||||||
|
__ add(buf, 64, buf);
|
||||||
|
__ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha256_loop);
|
||||||
|
__ mov(ofs, O0); // to be returned
|
||||||
|
}
|
||||||
|
|
||||||
|
// store F0-F7 into state and return
|
||||||
|
for (i = 0; i < 7; i++) {
|
||||||
|
__ stf(FloatRegisterImpl::S, as_FloatRegister(i), state, i*4);
|
||||||
|
}
|
||||||
|
__ retl();
|
||||||
|
__ delayed()->stf(FloatRegisterImpl::S, F7, state, 0x1c);
|
||||||
|
|
||||||
|
__ BIND(L_sha256_unaligned_input);
|
||||||
|
__ alignaddr(buf, G0, buf);
|
||||||
|
|
||||||
|
__ BIND(L_sha256_unaligned_input_loop);
|
||||||
|
// load buf into F8-F22
|
||||||
|
for (i = 0; i < 9; i++) {
|
||||||
|
__ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 8));
|
||||||
|
}
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
__ faligndata(as_FloatRegister(i*2 + 8), as_FloatRegister(i*2 + 10), as_FloatRegister(i*2 + 8));
|
||||||
|
}
|
||||||
|
__ sha256();
|
||||||
|
if (multi_block) {
|
||||||
|
__ add(ofs, 64, ofs);
|
||||||
|
__ add(buf, 64, buf);
|
||||||
|
__ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha256_unaligned_input_loop);
|
||||||
|
__ mov(ofs, O0); // to be returned
|
||||||
|
}
|
||||||
|
|
||||||
|
// store F0-F7 into state and return
|
||||||
|
for (i = 0; i < 7; i++) {
|
||||||
|
__ stf(FloatRegisterImpl::S, as_FloatRegister(i), state, i*4);
|
||||||
|
}
|
||||||
|
__ retl();
|
||||||
|
__ delayed()->stf(FloatRegisterImpl::S, F7, state, 0x1c);
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
address generate_sha512_implCompress(bool multi_block, const char *name) {
|
||||||
|
__ align(CodeEntryAlignment);
|
||||||
|
StubCodeMark mark(this, "StubRoutines", name);
|
||||||
|
address start = __ pc();
|
||||||
|
|
||||||
|
Label L_sha512_loop, L_sha512_unaligned_input, L_sha512_unaligned_input_loop;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
Register buf = O0; // byte[] source+offset
|
||||||
|
Register state = O1; // long[] SHA5.state
|
||||||
|
Register ofs = O2; // int offset
|
||||||
|
Register limit = O3; // int limit
|
||||||
|
|
||||||
|
// load state into F0-F14
|
||||||
|
for (i = 0; i < 8; i++) {
|
||||||
|
__ ldf(FloatRegisterImpl::D, state, i*8, as_FloatRegister(i*2));
|
||||||
|
}
|
||||||
|
|
||||||
|
__ andcc(buf, 7, G0);
|
||||||
|
__ br(Assembler::notZero, false, Assembler::pn, L_sha512_unaligned_input);
|
||||||
|
__ delayed()->nop();
|
||||||
|
|
||||||
|
__ BIND(L_sha512_loop);
|
||||||
|
// load buf into F16-F46
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
__ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 16));
|
||||||
|
}
|
||||||
|
__ sha512();
|
||||||
|
if (multi_block) {
|
||||||
|
__ add(ofs, 128, ofs);
|
||||||
|
__ add(buf, 128, buf);
|
||||||
|
__ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha512_loop);
|
||||||
|
__ mov(ofs, O0); // to be returned
|
||||||
|
}
|
||||||
|
|
||||||
|
// store F0-F14 into state and return
|
||||||
|
for (i = 0; i < 7; i++) {
|
||||||
|
__ stf(FloatRegisterImpl::D, as_FloatRegister(i*2), state, i*8);
|
||||||
|
}
|
||||||
|
__ retl();
|
||||||
|
__ delayed()->stf(FloatRegisterImpl::D, F14, state, 0x38);
|
||||||
|
|
||||||
|
__ BIND(L_sha512_unaligned_input);
|
||||||
|
__ alignaddr(buf, G0, buf);
|
||||||
|
|
||||||
|
__ BIND(L_sha512_unaligned_input_loop);
|
||||||
|
// load buf into F16-F46
|
||||||
|
for (i = 0; i < 17; i++) {
|
||||||
|
__ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 16));
|
||||||
|
}
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
__ faligndata(as_FloatRegister(i*2 + 16), as_FloatRegister(i*2 + 18), as_FloatRegister(i*2 + 16));
|
||||||
|
}
|
||||||
|
__ sha512();
|
||||||
|
if (multi_block) {
|
||||||
|
__ add(ofs, 128, ofs);
|
||||||
|
__ add(buf, 128, buf);
|
||||||
|
__ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha512_unaligned_input_loop);
|
||||||
|
__ mov(ofs, O0); // to be returned
|
||||||
|
}
|
||||||
|
|
||||||
|
// store F0-F14 into state and return
|
||||||
|
for (i = 0; i < 7; i++) {
|
||||||
|
__ stf(FloatRegisterImpl::D, as_FloatRegister(i*2), state, i*8);
|
||||||
|
}
|
||||||
|
__ retl();
|
||||||
|
__ delayed()->stf(FloatRegisterImpl::D, F14, state, 0x38);
|
||||||
|
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
void generate_initial() {
|
void generate_initial() {
|
||||||
// Generates all stubs and initializes the entry points
|
// Generates all stubs and initializes the entry points
|
||||||
|
|
||||||
|
@ -4647,6 +4860,20 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt();
|
StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt();
|
||||||
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel();
|
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generate SHA1/SHA256/SHA512 intrinsics code
|
||||||
|
if (UseSHA1Intrinsics) {
|
||||||
|
StubRoutines::_sha1_implCompress = generate_sha1_implCompress(false, "sha1_implCompress");
|
||||||
|
StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB");
|
||||||
|
}
|
||||||
|
if (UseSHA256Intrinsics) {
|
||||||
|
StubRoutines::_sha256_implCompress = generate_sha256_implCompress(false, "sha256_implCompress");
|
||||||
|
StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB");
|
||||||
|
}
|
||||||
|
if (UseSHA512Intrinsics) {
|
||||||
|
StubRoutines::_sha512_implCompress = generate_sha512_implCompress(false, "sha512_implCompress");
|
||||||
|
StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(true, "sha512_implCompressMB");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ static bool returns_to_call_stub(address return_pc) {
|
||||||
enum /* platform_dependent_constants */ {
|
enum /* platform_dependent_constants */ {
|
||||||
// %%%%%%%% May be able to shrink this a lot
|
// %%%%%%%% May be able to shrink this a lot
|
||||||
code_size1 = 20000, // simply increase if too small (assembler will crash if too small)
|
code_size1 = 20000, // simply increase if too small (assembler will crash if too small)
|
||||||
code_size2 = 22000 // simply increase if too small (assembler will crash if too small)
|
code_size2 = 23000 // simply increase if too small (assembler will crash if too small)
|
||||||
};
|
};
|
||||||
|
|
||||||
class Sparc {
|
class Sparc {
|
||||||
|
|
|
@ -234,7 +234,7 @@ void VM_Version::initialize() {
|
||||||
assert((OptoLoopAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
|
assert((OptoLoopAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
|
||||||
|
|
||||||
char buf[512];
|
char buf[512];
|
||||||
jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||||
(has_v9() ? ", v9" : (has_v8() ? ", v8" : "")),
|
(has_v9() ? ", v9" : (has_v8() ? ", v8" : "")),
|
||||||
(has_hardware_popc() ? ", popc" : ""),
|
(has_hardware_popc() ? ", popc" : ""),
|
||||||
(has_vis1() ? ", vis1" : ""),
|
(has_vis1() ? ", vis1" : ""),
|
||||||
|
@ -243,6 +243,9 @@ void VM_Version::initialize() {
|
||||||
(has_blk_init() ? ", blk_init" : ""),
|
(has_blk_init() ? ", blk_init" : ""),
|
||||||
(has_cbcond() ? ", cbcond" : ""),
|
(has_cbcond() ? ", cbcond" : ""),
|
||||||
(has_aes() ? ", aes" : ""),
|
(has_aes() ? ", aes" : ""),
|
||||||
|
(has_sha1() ? ", sha1" : ""),
|
||||||
|
(has_sha256() ? ", sha256" : ""),
|
||||||
|
(has_sha512() ? ", sha512" : ""),
|
||||||
(is_ultra3() ? ", ultra3" : ""),
|
(is_ultra3() ? ", ultra3" : ""),
|
||||||
(is_sun4v() ? ", sun4v" : ""),
|
(is_sun4v() ? ", sun4v" : ""),
|
||||||
(is_niagara_plus() ? ", niagara_plus" : (is_niagara() ? ", niagara" : "")),
|
(is_niagara_plus() ? ", niagara_plus" : (is_niagara() ? ", niagara" : "")),
|
||||||
|
@ -301,6 +304,58 @@ void VM_Version::initialize() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SHA1, SHA256, and SHA512 instructions were added to SPARC T-series at different times
|
||||||
|
if (has_sha1() || has_sha256() || has_sha512()) {
|
||||||
|
if (UseVIS > 0) { // SHA intrinsics use VIS1 instructions
|
||||||
|
if (FLAG_IS_DEFAULT(UseSHA)) {
|
||||||
|
FLAG_SET_DEFAULT(UseSHA, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (UseSHA) {
|
||||||
|
warning("SPARC SHA intrinsics require VIS1 instruction support. Intrinsics will be disabled.");
|
||||||
|
FLAG_SET_DEFAULT(UseSHA, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (UseSHA) {
|
||||||
|
warning("SHA instructions are not available on this CPU");
|
||||||
|
FLAG_SET_DEFAULT(UseSHA, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UseSHA) {
|
||||||
|
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
|
||||||
|
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
|
||||||
|
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
|
||||||
|
} else {
|
||||||
|
if (has_sha1()) {
|
||||||
|
if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) {
|
||||||
|
FLAG_SET_DEFAULT(UseSHA1Intrinsics, true);
|
||||||
|
}
|
||||||
|
} else if (UseSHA1Intrinsics) {
|
||||||
|
warning("SHA1 instruction is not available on this CPU.");
|
||||||
|
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
|
||||||
|
}
|
||||||
|
if (has_sha256()) {
|
||||||
|
if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
|
||||||
|
FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
|
||||||
|
}
|
||||||
|
} else if (UseSHA256Intrinsics) {
|
||||||
|
warning("SHA256 instruction (for SHA-224 and SHA-256) is not available on this CPU.");
|
||||||
|
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_sha512()) {
|
||||||
|
if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
|
||||||
|
FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
|
||||||
|
}
|
||||||
|
} else if (UseSHA512Intrinsics) {
|
||||||
|
warning("SHA512 instruction (for SHA-384 and SHA-512) is not available on this CPU.");
|
||||||
|
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
|
||||||
|
}
|
||||||
|
if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) {
|
||||||
|
FLAG_SET_DEFAULT(UseSHA, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
|
if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
|
||||||
(cache_line_size > ContendedPaddingWidth))
|
(cache_line_size > ContendedPaddingWidth))
|
||||||
ContendedPaddingWidth = cache_line_size;
|
ContendedPaddingWidth = cache_line_size;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -50,7 +50,10 @@ protected:
|
||||||
T_family = 16,
|
T_family = 16,
|
||||||
T1_model = 17,
|
T1_model = 17,
|
||||||
sparc5_instructions = 18,
|
sparc5_instructions = 18,
|
||||||
aes_instructions = 19
|
aes_instructions = 19,
|
||||||
|
sha1_instruction = 20,
|
||||||
|
sha256_instruction = 21,
|
||||||
|
sha512_instruction = 22
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Feature_Flag_Set {
|
enum Feature_Flag_Set {
|
||||||
|
@ -77,6 +80,9 @@ protected:
|
||||||
T1_model_m = 1 << T1_model,
|
T1_model_m = 1 << T1_model,
|
||||||
sparc5_instructions_m = 1 << sparc5_instructions,
|
sparc5_instructions_m = 1 << sparc5_instructions,
|
||||||
aes_instructions_m = 1 << aes_instructions,
|
aes_instructions_m = 1 << aes_instructions,
|
||||||
|
sha1_instruction_m = 1 << sha1_instruction,
|
||||||
|
sha256_instruction_m = 1 << sha256_instruction,
|
||||||
|
sha512_instruction_m = 1 << sha512_instruction,
|
||||||
|
|
||||||
generic_v8_m = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m,
|
generic_v8_m = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m,
|
||||||
generic_v9_m = generic_v8_m | v9_instructions_m,
|
generic_v9_m = generic_v8_m | v9_instructions_m,
|
||||||
|
@ -129,6 +135,9 @@ public:
|
||||||
static bool has_cbcond() { return (_features & cbcond_instructions_m) != 0; }
|
static bool has_cbcond() { return (_features & cbcond_instructions_m) != 0; }
|
||||||
static bool has_sparc5_instr() { return (_features & sparc5_instructions_m) != 0; }
|
static bool has_sparc5_instr() { return (_features & sparc5_instructions_m) != 0; }
|
||||||
static bool has_aes() { return (_features & aes_instructions_m) != 0; }
|
static bool has_aes() { return (_features & aes_instructions_m) != 0; }
|
||||||
|
static bool has_sha1() { return (_features & sha1_instruction_m) != 0; }
|
||||||
|
static bool has_sha256() { return (_features & sha256_instruction_m) != 0; }
|
||||||
|
static bool has_sha512() { return (_features & sha512_instruction_m) != 0; }
|
||||||
|
|
||||||
static bool supports_compare_and_exchange()
|
static bool supports_compare_and_exchange()
|
||||||
{ return has_v9(); }
|
{ return has_v9(); }
|
||||||
|
|
|
@ -590,6 +590,17 @@ void VM_Version::get_processor_features() {
|
||||||
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
|
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UseSHA) {
|
||||||
|
warning("SHA instructions are not available on this CPU");
|
||||||
|
FLAG_SET_DEFAULT(UseSHA, false);
|
||||||
|
}
|
||||||
|
if (UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics) {
|
||||||
|
warning("SHA intrinsics are not available on this CPU");
|
||||||
|
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
|
||||||
|
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
|
||||||
|
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Adjust RTM (Restricted Transactional Memory) flags
|
// Adjust RTM (Restricted Transactional Memory) flags
|
||||||
if (!supports_rtm() && UseRTMLocking) {
|
if (!supports_rtm() && UseRTMLocking) {
|
||||||
// Can't continue because UseRTMLocking affects UseBiasedLocking flag
|
// Can't continue because UseRTMLocking affects UseBiasedLocking flag
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -137,6 +137,21 @@ int VM_Version::platform_features(int features) {
|
||||||
#endif
|
#endif
|
||||||
if (av & AV_SPARC_AES) features |= aes_instructions_m;
|
if (av & AV_SPARC_AES) features |= aes_instructions_m;
|
||||||
|
|
||||||
|
#ifndef AV_SPARC_SHA1
|
||||||
|
#define AV_SPARC_SHA1 0x00400000 /* sha1 instruction supported */
|
||||||
|
#endif
|
||||||
|
if (av & AV_SPARC_SHA1) features |= sha1_instruction_m;
|
||||||
|
|
||||||
|
#ifndef AV_SPARC_SHA256
|
||||||
|
#define AV_SPARC_SHA256 0x00800000 /* sha256 instruction supported */
|
||||||
|
#endif
|
||||||
|
if (av & AV_SPARC_SHA256) features |= sha256_instruction_m;
|
||||||
|
|
||||||
|
#ifndef AV_SPARC_SHA512
|
||||||
|
#define AV_SPARC_SHA512 0x01000000 /* sha512 instruction supported */
|
||||||
|
#endif
|
||||||
|
if (av & AV_SPARC_SHA512) features |= sha512_instruction_m;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// getisax(2) failed, use the old legacy code.
|
// getisax(2) failed, use the old legacy code.
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
|
|
@ -123,24 +123,24 @@ int Runtime1::_throw_incompatible_class_change_error_count = 0;
|
||||||
int Runtime1::_throw_array_store_exception_count = 0;
|
int Runtime1::_throw_array_store_exception_count = 0;
|
||||||
int Runtime1::_throw_count = 0;
|
int Runtime1::_throw_count = 0;
|
||||||
|
|
||||||
static int _byte_arraycopy_cnt = 0;
|
static int _byte_arraycopy_stub_cnt = 0;
|
||||||
static int _short_arraycopy_cnt = 0;
|
static int _short_arraycopy_stub_cnt = 0;
|
||||||
static int _int_arraycopy_cnt = 0;
|
static int _int_arraycopy_stub_cnt = 0;
|
||||||
static int _long_arraycopy_cnt = 0;
|
static int _long_arraycopy_stub_cnt = 0;
|
||||||
static int _oop_arraycopy_cnt = 0;
|
static int _oop_arraycopy_stub_cnt = 0;
|
||||||
|
|
||||||
address Runtime1::arraycopy_count_address(BasicType type) {
|
address Runtime1::arraycopy_count_address(BasicType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case T_BOOLEAN:
|
case T_BOOLEAN:
|
||||||
case T_BYTE: return (address)&_byte_arraycopy_cnt;
|
case T_BYTE: return (address)&_byte_arraycopy_stub_cnt;
|
||||||
case T_CHAR:
|
case T_CHAR:
|
||||||
case T_SHORT: return (address)&_short_arraycopy_cnt;
|
case T_SHORT: return (address)&_short_arraycopy_stub_cnt;
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
case T_INT: return (address)&_int_arraycopy_cnt;
|
case T_INT: return (address)&_int_arraycopy_stub_cnt;
|
||||||
case T_DOUBLE:
|
case T_DOUBLE:
|
||||||
case T_LONG: return (address)&_long_arraycopy_cnt;
|
case T_LONG: return (address)&_long_arraycopy_stub_cnt;
|
||||||
case T_ARRAY:
|
case T_ARRAY:
|
||||||
case T_OBJECT: return (address)&_oop_arraycopy_cnt;
|
case T_OBJECT: return (address)&_oop_arraycopy_stub_cnt;
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1479,13 +1479,13 @@ void Runtime1::print_statistics() {
|
||||||
tty->print_cr(" _ic_miss_cnt: %d", SharedRuntime::_ic_miss_ctr);
|
tty->print_cr(" _ic_miss_cnt: %d", SharedRuntime::_ic_miss_ctr);
|
||||||
tty->print_cr(" _generic_arraycopy_cnt: %d", _generic_arraycopy_cnt);
|
tty->print_cr(" _generic_arraycopy_cnt: %d", _generic_arraycopy_cnt);
|
||||||
tty->print_cr(" _generic_arraycopystub_cnt: %d", _generic_arraycopystub_cnt);
|
tty->print_cr(" _generic_arraycopystub_cnt: %d", _generic_arraycopystub_cnt);
|
||||||
tty->print_cr(" _byte_arraycopy_cnt: %d", _byte_arraycopy_cnt);
|
tty->print_cr(" _byte_arraycopy_cnt: %d", _byte_arraycopy_stub_cnt);
|
||||||
tty->print_cr(" _short_arraycopy_cnt: %d", _short_arraycopy_cnt);
|
tty->print_cr(" _short_arraycopy_cnt: %d", _short_arraycopy_stub_cnt);
|
||||||
tty->print_cr(" _int_arraycopy_cnt: %d", _int_arraycopy_cnt);
|
tty->print_cr(" _int_arraycopy_cnt: %d", _int_arraycopy_stub_cnt);
|
||||||
tty->print_cr(" _long_arraycopy_cnt: %d", _long_arraycopy_cnt);
|
tty->print_cr(" _long_arraycopy_cnt: %d", _long_arraycopy_stub_cnt);
|
||||||
tty->print_cr(" _primitive_arraycopy_cnt: %d", _primitive_arraycopy_cnt);
|
tty->print_cr(" _primitive_arraycopy_cnt: %d", _primitive_arraycopy_cnt);
|
||||||
tty->print_cr(" _oop_arraycopy_cnt (C): %d", Runtime1::_oop_arraycopy_cnt);
|
tty->print_cr(" _oop_arraycopy_cnt (C): %d", Runtime1::_oop_arraycopy_cnt);
|
||||||
tty->print_cr(" _oop_arraycopy_cnt (stub): %d", _oop_arraycopy_cnt);
|
tty->print_cr(" _oop_arraycopy_cnt (stub): %d", _oop_arraycopy_stub_cnt);
|
||||||
tty->print_cr(" _arraycopy_slowcase_cnt: %d", _arraycopy_slowcase_cnt);
|
tty->print_cr(" _arraycopy_slowcase_cnt: %d", _arraycopy_slowcase_cnt);
|
||||||
tty->print_cr(" _arraycopy_checkcast_cnt: %d", _arraycopy_checkcast_cnt);
|
tty->print_cr(" _arraycopy_checkcast_cnt: %d", _arraycopy_checkcast_cnt);
|
||||||
tty->print_cr(" _arraycopy_checkcast_attempt_cnt:%d", _arraycopy_checkcast_attempt_cnt);
|
tty->print_cr(" _arraycopy_checkcast_attempt_cnt:%d", _arraycopy_checkcast_attempt_cnt);
|
||||||
|
|
|
@ -790,6 +790,26 @@
|
||||||
do_name( decrypt_name, "decrypt") \
|
do_name( decrypt_name, "decrypt") \
|
||||||
do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \
|
do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \
|
||||||
\
|
\
|
||||||
|
/* support for sun.security.provider.SHA */ \
|
||||||
|
do_class(sun_security_provider_sha, "sun/security/provider/SHA") \
|
||||||
|
do_intrinsic(_sha_implCompress, sun_security_provider_sha, implCompress_name, implCompress_signature, F_R) \
|
||||||
|
do_name( implCompress_name, "implCompress") \
|
||||||
|
do_signature(implCompress_signature, "([BI)V") \
|
||||||
|
\
|
||||||
|
/* support for sun.security.provider.SHA2 */ \
|
||||||
|
do_class(sun_security_provider_sha2, "sun/security/provider/SHA2") \
|
||||||
|
do_intrinsic(_sha2_implCompress, sun_security_provider_sha2, implCompress_name, implCompress_signature, F_R) \
|
||||||
|
\
|
||||||
|
/* support for sun.security.provider.SHA5 */ \
|
||||||
|
do_class(sun_security_provider_sha5, "sun/security/provider/SHA5") \
|
||||||
|
do_intrinsic(_sha5_implCompress, sun_security_provider_sha5, implCompress_name, implCompress_signature, F_R) \
|
||||||
|
\
|
||||||
|
/* support for sun.security.provider.DigestBase */ \
|
||||||
|
do_class(sun_security_provider_digestbase, "sun/security/provider/DigestBase") \
|
||||||
|
do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, implCompressMB_signature, F_R) \
|
||||||
|
do_name( implCompressMB_name, "implCompressMultiBlock") \
|
||||||
|
do_signature(implCompressMB_signature, "([BII)I") \
|
||||||
|
\
|
||||||
/* support for java.util.zip */ \
|
/* support for java.util.zip */ \
|
||||||
do_class(java_util_zip_CRC32, "java/util/zip/CRC32") \
|
do_class(java_util_zip_CRC32, "java/util/zip/CRC32") \
|
||||||
do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \
|
do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \
|
||||||
|
|
|
@ -877,11 +877,7 @@ address external_word_Relocation::target() {
|
||||||
void internal_word_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
|
void internal_word_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
|
||||||
address target = _target;
|
address target = _target;
|
||||||
if (target == NULL) {
|
if (target == NULL) {
|
||||||
if (addr_in_const()) {
|
target = new_addr_for(this->target(), src, dest);
|
||||||
target = new_addr_for(*(address*)addr(), src, dest);
|
|
||||||
} else {
|
|
||||||
target = new_addr_for(pd_get_address_from_code(), src, dest);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
set_value(target);
|
set_value(target);
|
||||||
}
|
}
|
||||||
|
@ -890,8 +886,12 @@ void internal_word_Relocation::fix_relocation_after_move(const CodeBuffer* src,
|
||||||
address internal_word_Relocation::target() {
|
address internal_word_Relocation::target() {
|
||||||
address target = _target;
|
address target = _target;
|
||||||
if (target == NULL) {
|
if (target == NULL) {
|
||||||
|
if (addr_in_const()) {
|
||||||
|
target = *(address*)addr();
|
||||||
|
} else {
|
||||||
target = pd_get_address_from_code();
|
target = pd_get_address_from_code();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -650,9 +650,6 @@
|
||||||
product(bool, UseMathExactIntrinsics, true, \
|
product(bool, UseMathExactIntrinsics, true, \
|
||||||
"Enables intrinsification of various java.lang.Math functions") \
|
"Enables intrinsification of various java.lang.Math functions") \
|
||||||
\
|
\
|
||||||
experimental(bool, ReplaceInParentMaps, false, \
|
|
||||||
"Propagate type improvements in callers of inlinee if possible") \
|
|
||||||
\
|
|
||||||
product(bool, UseTypeSpeculation, true, \
|
product(bool, UseTypeSpeculation, true, \
|
||||||
"Speculatively propagate types from profiles") \
|
"Speculatively propagate types from profiles") \
|
||||||
\
|
\
|
||||||
|
|
|
@ -63,12 +63,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool is_parse() const { return true; }
|
virtual bool is_parse() const { return true; }
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
|
virtual JVMState* generate(JVMState* jvms);
|
||||||
int is_osr() { return _is_osr; }
|
int is_osr() { return _is_osr; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JVMState* ParseGenerator::generate(JVMState* jvms, Parse* parent_parser) {
|
JVMState* ParseGenerator::generate(JVMState* jvms) {
|
||||||
Compile* C = Compile::current();
|
Compile* C = Compile::current();
|
||||||
C->print_inlining_update(this);
|
C->print_inlining_update(this);
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ JVMState* ParseGenerator::generate(JVMState* jvms, Parse* parent_parser) {
|
||||||
return NULL; // bailing out of the compile; do not try to parse
|
return NULL; // bailing out of the compile; do not try to parse
|
||||||
}
|
}
|
||||||
|
|
||||||
Parse parser(jvms, method(), _expected_uses, parent_parser);
|
Parse parser(jvms, method(), _expected_uses);
|
||||||
// Grab signature for matching/allocation
|
// Grab signature for matching/allocation
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
if (parser.tf() != (parser.depth() == 1 ? C->tf() : tf())) {
|
if (parser.tf() != (parser.depth() == 1 ? C->tf() : tf())) {
|
||||||
|
@ -120,12 +120,12 @@ class DirectCallGenerator : public CallGenerator {
|
||||||
_separate_io_proj(separate_io_proj)
|
_separate_io_proj(separate_io_proj)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
|
virtual JVMState* generate(JVMState* jvms);
|
||||||
|
|
||||||
CallStaticJavaNode* call_node() const { return _call_node; }
|
CallStaticJavaNode* call_node() const { return _call_node; }
|
||||||
};
|
};
|
||||||
|
|
||||||
JVMState* DirectCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
|
JVMState* DirectCallGenerator::generate(JVMState* jvms) {
|
||||||
GraphKit kit(jvms);
|
GraphKit kit(jvms);
|
||||||
kit.C->print_inlining_update(this);
|
kit.C->print_inlining_update(this);
|
||||||
bool is_static = method()->is_static();
|
bool is_static = method()->is_static();
|
||||||
|
@ -173,10 +173,10 @@ public:
|
||||||
vtable_index >= 0, "either invalid or usable");
|
vtable_index >= 0, "either invalid or usable");
|
||||||
}
|
}
|
||||||
virtual bool is_virtual() const { return true; }
|
virtual bool is_virtual() const { return true; }
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
|
virtual JVMState* generate(JVMState* jvms);
|
||||||
};
|
};
|
||||||
|
|
||||||
JVMState* VirtualCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
|
JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
|
||||||
GraphKit kit(jvms);
|
GraphKit kit(jvms);
|
||||||
Node* receiver = kit.argument(0);
|
Node* receiver = kit.argument(0);
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ class LateInlineCallGenerator : public DirectCallGenerator {
|
||||||
// Convert the CallStaticJava into an inline
|
// Convert the CallStaticJava into an inline
|
||||||
virtual void do_late_inline();
|
virtual void do_late_inline();
|
||||||
|
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
|
virtual JVMState* generate(JVMState* jvms) {
|
||||||
Compile *C = Compile::current();
|
Compile *C = Compile::current();
|
||||||
|
|
||||||
C->log_inline_id(this);
|
C->log_inline_id(this);
|
||||||
|
@ -298,7 +298,7 @@ class LateInlineCallGenerator : public DirectCallGenerator {
|
||||||
// that the late inlining logic can distinguish between fall
|
// that the late inlining logic can distinguish between fall
|
||||||
// through and exceptional uses of the memory and io projections
|
// through and exceptional uses of the memory and io projections
|
||||||
// as is done for allocations and macro expansion.
|
// as is done for allocations and macro expansion.
|
||||||
return DirectCallGenerator::generate(jvms, parent_parser);
|
return DirectCallGenerator::generate(jvms);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void print_inlining_late(const char* msg) {
|
virtual void print_inlining_late(const char* msg) {
|
||||||
|
@ -399,7 +399,7 @@ void LateInlineCallGenerator::do_late_inline() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now perform the inlining using the synthesized JVMState
|
// Now perform the inlining using the synthesized JVMState
|
||||||
JVMState* new_jvms = _inline_cg->generate(jvms, NULL);
|
JVMState* new_jvms = _inline_cg->generate(jvms);
|
||||||
if (new_jvms == NULL) return; // no change
|
if (new_jvms == NULL) return; // no change
|
||||||
if (C->failing()) return;
|
if (C->failing()) return;
|
||||||
|
|
||||||
|
@ -417,7 +417,7 @@ void LateInlineCallGenerator::do_late_inline() {
|
||||||
C->env()->notice_inlined_method(_inline_cg->method());
|
C->env()->notice_inlined_method(_inline_cg->method());
|
||||||
C->set_inlining_progress(true);
|
C->set_inlining_progress(true);
|
||||||
|
|
||||||
kit.replace_call(call, result);
|
kit.replace_call(call, result, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -439,8 +439,8 @@ class LateInlineMHCallGenerator : public LateInlineCallGenerator {
|
||||||
|
|
||||||
virtual bool is_mh_late_inline() const { return true; }
|
virtual bool is_mh_late_inline() const { return true; }
|
||||||
|
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
|
virtual JVMState* generate(JVMState* jvms) {
|
||||||
JVMState* new_jvms = LateInlineCallGenerator::generate(jvms, parent_parser);
|
JVMState* new_jvms = LateInlineCallGenerator::generate(jvms);
|
||||||
|
|
||||||
Compile* C = Compile::current();
|
Compile* C = Compile::current();
|
||||||
if (_input_not_const) {
|
if (_input_not_const) {
|
||||||
|
@ -486,14 +486,14 @@ class LateInlineStringCallGenerator : public LateInlineCallGenerator {
|
||||||
LateInlineStringCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
|
LateInlineStringCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
|
||||||
LateInlineCallGenerator(method, inline_cg) {}
|
LateInlineCallGenerator(method, inline_cg) {}
|
||||||
|
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
|
virtual JVMState* generate(JVMState* jvms) {
|
||||||
Compile *C = Compile::current();
|
Compile *C = Compile::current();
|
||||||
|
|
||||||
C->log_inline_id(this);
|
C->log_inline_id(this);
|
||||||
|
|
||||||
C->add_string_late_inline(this);
|
C->add_string_late_inline(this);
|
||||||
|
|
||||||
JVMState* new_jvms = DirectCallGenerator::generate(jvms, parent_parser);
|
JVMState* new_jvms = DirectCallGenerator::generate(jvms);
|
||||||
return new_jvms;
|
return new_jvms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,14 +510,14 @@ class LateInlineBoxingCallGenerator : public LateInlineCallGenerator {
|
||||||
LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
|
LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
|
||||||
LateInlineCallGenerator(method, inline_cg) {}
|
LateInlineCallGenerator(method, inline_cg) {}
|
||||||
|
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
|
virtual JVMState* generate(JVMState* jvms) {
|
||||||
Compile *C = Compile::current();
|
Compile *C = Compile::current();
|
||||||
|
|
||||||
C->log_inline_id(this);
|
C->log_inline_id(this);
|
||||||
|
|
||||||
C->add_boxing_late_inline(this);
|
C->add_boxing_late_inline(this);
|
||||||
|
|
||||||
JVMState* new_jvms = DirectCallGenerator::generate(jvms, parent_parser);
|
JVMState* new_jvms = DirectCallGenerator::generate(jvms);
|
||||||
return new_jvms;
|
return new_jvms;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -553,7 +553,7 @@ public:
|
||||||
virtual bool is_virtual() const { return _is_virtual; }
|
virtual bool is_virtual() const { return _is_virtual; }
|
||||||
virtual bool is_deferred() const { return true; }
|
virtual bool is_deferred() const { return true; }
|
||||||
|
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
|
virtual JVMState* generate(JVMState* jvms);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -563,14 +563,14 @@ CallGenerator* CallGenerator::for_warm_call(WarmCallInfo* ci,
|
||||||
return new WarmCallGenerator(ci, if_cold, if_hot);
|
return new WarmCallGenerator(ci, if_cold, if_hot);
|
||||||
}
|
}
|
||||||
|
|
||||||
JVMState* WarmCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
|
JVMState* WarmCallGenerator::generate(JVMState* jvms) {
|
||||||
Compile* C = Compile::current();
|
Compile* C = Compile::current();
|
||||||
C->print_inlining_update(this);
|
C->print_inlining_update(this);
|
||||||
|
|
||||||
if (C->log() != NULL) {
|
if (C->log() != NULL) {
|
||||||
C->log()->elem("warm_call bci='%d'", jvms->bci());
|
C->log()->elem("warm_call bci='%d'", jvms->bci());
|
||||||
}
|
}
|
||||||
jvms = _if_cold->generate(jvms, parent_parser);
|
jvms = _if_cold->generate(jvms);
|
||||||
if (jvms != NULL) {
|
if (jvms != NULL) {
|
||||||
Node* m = jvms->map()->control();
|
Node* m = jvms->map()->control();
|
||||||
if (m->is_CatchProj()) m = m->in(0); else m = C->top();
|
if (m->is_CatchProj()) m = m->in(0); else m = C->top();
|
||||||
|
@ -631,7 +631,7 @@ public:
|
||||||
virtual bool is_inline() const { return _if_hit->is_inline(); }
|
virtual bool is_inline() const { return _if_hit->is_inline(); }
|
||||||
virtual bool is_deferred() const { return _if_hit->is_deferred(); }
|
virtual bool is_deferred() const { return _if_hit->is_deferred(); }
|
||||||
|
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
|
virtual JVMState* generate(JVMState* jvms);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -643,14 +643,13 @@ CallGenerator* CallGenerator::for_predicted_call(ciKlass* predicted_receiver,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
|
JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
|
||||||
GraphKit kit(jvms);
|
GraphKit kit(jvms);
|
||||||
kit.C->print_inlining_update(this);
|
kit.C->print_inlining_update(this);
|
||||||
PhaseGVN& gvn = kit.gvn();
|
PhaseGVN& gvn = kit.gvn();
|
||||||
// We need an explicit receiver null_check before checking its type.
|
// We need an explicit receiver null_check before checking its type.
|
||||||
// We share a map with the caller, so his JVMS gets adjusted.
|
// We share a map with the caller, so his JVMS gets adjusted.
|
||||||
Node* receiver = kit.argument(0);
|
Node* receiver = kit.argument(0);
|
||||||
|
|
||||||
CompileLog* log = kit.C->log();
|
CompileLog* log = kit.C->log();
|
||||||
if (log != NULL) {
|
if (log != NULL) {
|
||||||
log->elem("predicted_call bci='%d' klass='%d'",
|
log->elem("predicted_call bci='%d' klass='%d'",
|
||||||
|
@ -662,6 +661,10 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser)
|
||||||
return kit.transfer_exceptions_into_jvms();
|
return kit.transfer_exceptions_into_jvms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make a copy of the replaced nodes in case we need to restore them
|
||||||
|
ReplacedNodes replaced_nodes = kit.map()->replaced_nodes();
|
||||||
|
replaced_nodes.clone();
|
||||||
|
|
||||||
Node* exact_receiver = receiver; // will get updated in place...
|
Node* exact_receiver = receiver; // will get updated in place...
|
||||||
Node* slow_ctl = kit.type_check_receiver(receiver,
|
Node* slow_ctl = kit.type_check_receiver(receiver,
|
||||||
_predicted_receiver, _hit_prob,
|
_predicted_receiver, _hit_prob,
|
||||||
|
@ -672,7 +675,7 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser)
|
||||||
{ PreserveJVMState pjvms(&kit);
|
{ PreserveJVMState pjvms(&kit);
|
||||||
kit.set_control(slow_ctl);
|
kit.set_control(slow_ctl);
|
||||||
if (!kit.stopped()) {
|
if (!kit.stopped()) {
|
||||||
slow_jvms = _if_missed->generate(kit.sync_jvms(), parent_parser);
|
slow_jvms = _if_missed->generate(kit.sync_jvms());
|
||||||
if (kit.failing())
|
if (kit.failing())
|
||||||
return NULL; // might happen because of NodeCountInliningCutoff
|
return NULL; // might happen because of NodeCountInliningCutoff
|
||||||
assert(slow_jvms != NULL, "must be");
|
assert(slow_jvms != NULL, "must be");
|
||||||
|
@ -693,12 +696,12 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser)
|
||||||
kit.replace_in_map(receiver, exact_receiver);
|
kit.replace_in_map(receiver, exact_receiver);
|
||||||
|
|
||||||
// Make the hot call:
|
// Make the hot call:
|
||||||
JVMState* new_jvms = _if_hit->generate(kit.sync_jvms(), parent_parser);
|
JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
|
||||||
if (new_jvms == NULL) {
|
if (new_jvms == NULL) {
|
||||||
// Inline failed, so make a direct call.
|
// Inline failed, so make a direct call.
|
||||||
assert(_if_hit->is_inline(), "must have been a failed inline");
|
assert(_if_hit->is_inline(), "must have been a failed inline");
|
||||||
CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
|
CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
|
||||||
new_jvms = cg->generate(kit.sync_jvms(), parent_parser);
|
new_jvms = cg->generate(kit.sync_jvms());
|
||||||
}
|
}
|
||||||
kit.add_exception_states_from(new_jvms);
|
kit.add_exception_states_from(new_jvms);
|
||||||
kit.set_jvms(new_jvms);
|
kit.set_jvms(new_jvms);
|
||||||
|
@ -715,6 +718,11 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser)
|
||||||
return kit.transfer_exceptions_into_jvms();
|
return kit.transfer_exceptions_into_jvms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There are 2 branches and the replaced nodes are only valid on
|
||||||
|
// one: restore the replaced nodes to what they were before the
|
||||||
|
// branch.
|
||||||
|
kit.map()->set_replaced_nodes(replaced_nodes);
|
||||||
|
|
||||||
// Finish the diamond.
|
// Finish the diamond.
|
||||||
kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
|
kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
|
||||||
RegionNode* region = new RegionNode(3);
|
RegionNode* region = new RegionNode(3);
|
||||||
|
@ -724,7 +732,15 @@ JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser)
|
||||||
Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
|
Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
|
||||||
iophi->set_req(2, slow_map->i_o());
|
iophi->set_req(2, slow_map->i_o());
|
||||||
kit.set_i_o(gvn.transform(iophi));
|
kit.set_i_o(gvn.transform(iophi));
|
||||||
|
// Merge memory
|
||||||
kit.merge_memory(slow_map->merged_memory(), region, 2);
|
kit.merge_memory(slow_map->merged_memory(), region, 2);
|
||||||
|
// Transform new memory Phis.
|
||||||
|
for (MergeMemStream mms(kit.merged_memory()); mms.next_non_empty();) {
|
||||||
|
Node* phi = mms.memory();
|
||||||
|
if (phi->is_Phi() && phi->in(0) == region) {
|
||||||
|
mms.set_memory(gvn.transform(phi));
|
||||||
|
}
|
||||||
|
}
|
||||||
uint tos = kit.jvms()->stkoff() + kit.sp();
|
uint tos = kit.jvms()->stkoff() + kit.sp();
|
||||||
uint limit = slow_map->req();
|
uint limit = slow_map->req();
|
||||||
for (uint i = TypeFunc::Parms; i < limit; i++) {
|
for (uint i = TypeFunc::Parms; i < limit; i++) {
|
||||||
|
@ -882,14 +898,14 @@ CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------PredictedIntrinsicGenerator------------------------------
|
//------------------------PredicatedIntrinsicGenerator------------------------------
|
||||||
// Internal class which handles all predicted Intrinsic calls.
|
// Internal class which handles all predicated Intrinsic calls.
|
||||||
class PredictedIntrinsicGenerator : public CallGenerator {
|
class PredicatedIntrinsicGenerator : public CallGenerator {
|
||||||
CallGenerator* _intrinsic;
|
CallGenerator* _intrinsic;
|
||||||
CallGenerator* _cg;
|
CallGenerator* _cg;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PredictedIntrinsicGenerator(CallGenerator* intrinsic,
|
PredicatedIntrinsicGenerator(CallGenerator* intrinsic,
|
||||||
CallGenerator* cg)
|
CallGenerator* cg)
|
||||||
: CallGenerator(cg->method())
|
: CallGenerator(cg->method())
|
||||||
{
|
{
|
||||||
|
@ -901,108 +917,186 @@ public:
|
||||||
virtual bool is_inlined() const { return true; }
|
virtual bool is_inlined() const { return true; }
|
||||||
virtual bool is_intrinsic() const { return true; }
|
virtual bool is_intrinsic() const { return true; }
|
||||||
|
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
|
virtual JVMState* generate(JVMState* jvms);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
CallGenerator* CallGenerator::for_predicted_intrinsic(CallGenerator* intrinsic,
|
CallGenerator* CallGenerator::for_predicated_intrinsic(CallGenerator* intrinsic,
|
||||||
CallGenerator* cg) {
|
CallGenerator* cg) {
|
||||||
return new PredictedIntrinsicGenerator(intrinsic, cg);
|
return new PredicatedIntrinsicGenerator(intrinsic, cg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms, Parse* parent_parser) {
|
JVMState* PredicatedIntrinsicGenerator::generate(JVMState* jvms) {
|
||||||
|
// The code we want to generate here is:
|
||||||
|
// if (receiver == NULL)
|
||||||
|
// uncommon_Trap
|
||||||
|
// if (predicate(0))
|
||||||
|
// do_intrinsic(0)
|
||||||
|
// else
|
||||||
|
// if (predicate(1))
|
||||||
|
// do_intrinsic(1)
|
||||||
|
// ...
|
||||||
|
// else
|
||||||
|
// do_java_comp
|
||||||
|
|
||||||
GraphKit kit(jvms);
|
GraphKit kit(jvms);
|
||||||
PhaseGVN& gvn = kit.gvn();
|
PhaseGVN& gvn = kit.gvn();
|
||||||
|
|
||||||
CompileLog* log = kit.C->log();
|
CompileLog* log = kit.C->log();
|
||||||
if (log != NULL) {
|
if (log != NULL) {
|
||||||
log->elem("predicted_intrinsic bci='%d' method='%d'",
|
log->elem("predicated_intrinsic bci='%d' method='%d'",
|
||||||
jvms->bci(), log->identify(method()));
|
jvms->bci(), log->identify(method()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* slow_ctl = _intrinsic->generate_predicate(kit.sync_jvms());
|
if (!method()->is_static()) {
|
||||||
if (kit.failing())
|
// We need an explicit receiver null_check before checking its type in predicate.
|
||||||
return NULL; // might happen because of NodeCountInliningCutoff
|
// We share a map with the caller, so his JVMS gets adjusted.
|
||||||
|
Node* receiver = kit.null_check_receiver_before_call(method());
|
||||||
kit.C->print_inlining_update(this);
|
|
||||||
SafePointNode* slow_map = NULL;
|
|
||||||
JVMState* slow_jvms;
|
|
||||||
if (slow_ctl != NULL) {
|
|
||||||
PreserveJVMState pjvms(&kit);
|
|
||||||
kit.set_control(slow_ctl);
|
|
||||||
if (!kit.stopped()) {
|
|
||||||
slow_jvms = _cg->generate(kit.sync_jvms(), parent_parser);
|
|
||||||
if (kit.failing())
|
|
||||||
return NULL; // might happen because of NodeCountInliningCutoff
|
|
||||||
assert(slow_jvms != NULL, "must be");
|
|
||||||
kit.add_exception_states_from(slow_jvms);
|
|
||||||
kit.set_map(slow_jvms->map());
|
|
||||||
if (!kit.stopped())
|
|
||||||
slow_map = kit.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kit.stopped()) {
|
if (kit.stopped()) {
|
||||||
// Predicate is always false.
|
|
||||||
kit.set_jvms(slow_jvms);
|
|
||||||
return kit.transfer_exceptions_into_jvms();
|
return kit.transfer_exceptions_into_jvms();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int n_predicates = _intrinsic->predicates_count();
|
||||||
|
assert(n_predicates > 0, "sanity");
|
||||||
|
|
||||||
|
JVMState** result_jvms = NEW_RESOURCE_ARRAY(JVMState*, (n_predicates+1));
|
||||||
|
|
||||||
|
// Region for normal compilation code if intrinsic failed.
|
||||||
|
Node* slow_region = new RegionNode(1);
|
||||||
|
|
||||||
|
int results = 0;
|
||||||
|
for (int predicate = 0; (predicate < n_predicates) && !kit.stopped(); predicate++) {
|
||||||
|
#ifdef ASSERT
|
||||||
|
JVMState* old_jvms = kit.jvms();
|
||||||
|
SafePointNode* old_map = kit.map();
|
||||||
|
Node* old_io = old_map->i_o();
|
||||||
|
Node* old_mem = old_map->memory();
|
||||||
|
Node* old_exc = old_map->next_exception();
|
||||||
|
#endif
|
||||||
|
Node* else_ctrl = _intrinsic->generate_predicate(kit.sync_jvms(), predicate);
|
||||||
|
#ifdef ASSERT
|
||||||
|
// Assert(no_new_memory && no_new_io && no_new_exceptions) after generate_predicate.
|
||||||
|
assert(old_jvms == kit.jvms(), "generate_predicate should not change jvm state");
|
||||||
|
SafePointNode* new_map = kit.map();
|
||||||
|
assert(old_io == new_map->i_o(), "generate_predicate should not change i_o");
|
||||||
|
assert(old_mem == new_map->memory(), "generate_predicate should not change memory");
|
||||||
|
assert(old_exc == new_map->next_exception(), "generate_predicate should not add exceptions");
|
||||||
|
#endif
|
||||||
|
if (!kit.stopped()) {
|
||||||
|
PreserveJVMState pjvms(&kit);
|
||||||
// Generate intrinsic code:
|
// Generate intrinsic code:
|
||||||
JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms(), parent_parser);
|
JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms());
|
||||||
if (new_jvms == NULL) {
|
if (new_jvms == NULL) {
|
||||||
// Intrinsic failed, so use slow code or make a direct call.
|
// Intrinsic failed, use normal compilation path for this predicate.
|
||||||
if (slow_map == NULL) {
|
slow_region->add_req(kit.control());
|
||||||
CallGenerator* cg = CallGenerator::for_direct_call(method());
|
|
||||||
new_jvms = cg->generate(kit.sync_jvms(), parent_parser);
|
|
||||||
} else {
|
} else {
|
||||||
kit.set_jvms(slow_jvms);
|
|
||||||
return kit.transfer_exceptions_into_jvms();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kit.add_exception_states_from(new_jvms);
|
kit.add_exception_states_from(new_jvms);
|
||||||
kit.set_jvms(new_jvms);
|
kit.set_jvms(new_jvms);
|
||||||
|
if (!kit.stopped()) {
|
||||||
|
result_jvms[results++] = kit.jvms();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (else_ctrl == NULL) {
|
||||||
|
else_ctrl = kit.C->top();
|
||||||
|
}
|
||||||
|
kit.set_control(else_ctrl);
|
||||||
|
}
|
||||||
|
if (!kit.stopped()) {
|
||||||
|
// Final 'else' after predicates.
|
||||||
|
slow_region->add_req(kit.control());
|
||||||
|
}
|
||||||
|
if (slow_region->req() > 1) {
|
||||||
|
PreserveJVMState pjvms(&kit);
|
||||||
|
// Generate normal compilation code:
|
||||||
|
kit.set_control(gvn.transform(slow_region));
|
||||||
|
JVMState* new_jvms = _cg->generate(kit.sync_jvms());
|
||||||
|
if (kit.failing())
|
||||||
|
return NULL; // might happen because of NodeCountInliningCutoff
|
||||||
|
assert(new_jvms != NULL, "must be");
|
||||||
|
kit.add_exception_states_from(new_jvms);
|
||||||
|
kit.set_jvms(new_jvms);
|
||||||
|
if (!kit.stopped()) {
|
||||||
|
result_jvms[results++] = kit.jvms();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Need to merge slow and fast?
|
if (results == 0) {
|
||||||
if (slow_map == NULL) {
|
// All paths ended in uncommon traps.
|
||||||
// The fast path is the only path remaining.
|
(void) kit.stop();
|
||||||
return kit.transfer_exceptions_into_jvms();
|
return kit.transfer_exceptions_into_jvms();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kit.stopped()) {
|
if (results == 1) { // Only one path
|
||||||
// Intrinsic method threw an exception, so it's just the slow path after all.
|
kit.set_jvms(result_jvms[0]);
|
||||||
kit.set_jvms(slow_jvms);
|
|
||||||
return kit.transfer_exceptions_into_jvms();
|
return kit.transfer_exceptions_into_jvms();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish the diamond.
|
// Merge all paths.
|
||||||
kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
|
kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
|
||||||
RegionNode* region = new RegionNode(3);
|
RegionNode* region = new RegionNode(results + 1);
|
||||||
region->init_req(1, kit.control());
|
|
||||||
region->init_req(2, slow_map->control());
|
|
||||||
kit.set_control(gvn.transform(region));
|
|
||||||
Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
|
Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
|
||||||
iophi->set_req(2, slow_map->i_o());
|
for (int i = 0; i < results; i++) {
|
||||||
|
JVMState* jvms = result_jvms[i];
|
||||||
|
int path = i + 1;
|
||||||
|
SafePointNode* map = jvms->map();
|
||||||
|
region->init_req(path, map->control());
|
||||||
|
iophi->set_req(path, map->i_o());
|
||||||
|
if (i == 0) {
|
||||||
|
kit.set_jvms(jvms);
|
||||||
|
} else {
|
||||||
|
kit.merge_memory(map->merged_memory(), region, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kit.set_control(gvn.transform(region));
|
||||||
kit.set_i_o(gvn.transform(iophi));
|
kit.set_i_o(gvn.transform(iophi));
|
||||||
kit.merge_memory(slow_map->merged_memory(), region, 2);
|
// Transform new memory Phis.
|
||||||
|
for (MergeMemStream mms(kit.merged_memory()); mms.next_non_empty();) {
|
||||||
|
Node* phi = mms.memory();
|
||||||
|
if (phi->is_Phi() && phi->in(0) == region) {
|
||||||
|
mms.set_memory(gvn.transform(phi));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge debug info.
|
||||||
|
Node** ins = NEW_RESOURCE_ARRAY(Node*, results);
|
||||||
uint tos = kit.jvms()->stkoff() + kit.sp();
|
uint tos = kit.jvms()->stkoff() + kit.sp();
|
||||||
uint limit = slow_map->req();
|
Node* map = kit.map();
|
||||||
|
uint limit = map->req();
|
||||||
for (uint i = TypeFunc::Parms; i < limit; i++) {
|
for (uint i = TypeFunc::Parms; i < limit; i++) {
|
||||||
// Skip unused stack slots; fast forward to monoff();
|
// Skip unused stack slots; fast forward to monoff();
|
||||||
if (i == tos) {
|
if (i == tos) {
|
||||||
i = kit.jvms()->monoff();
|
i = kit.jvms()->monoff();
|
||||||
if( i >= limit ) break;
|
if( i >= limit ) break;
|
||||||
}
|
}
|
||||||
Node* m = kit.map()->in(i);
|
Node* n = map->in(i);
|
||||||
Node* n = slow_map->in(i);
|
ins[0] = n;
|
||||||
|
const Type* t = gvn.type(n);
|
||||||
|
bool needs_phi = false;
|
||||||
|
for (int j = 1; j < results; j++) {
|
||||||
|
JVMState* jvms = result_jvms[j];
|
||||||
|
Node* jmap = jvms->map();
|
||||||
|
Node* m = NULL;
|
||||||
|
if (jmap->req() > i) {
|
||||||
|
m = jmap->in(i);
|
||||||
if (m != n) {
|
if (m != n) {
|
||||||
const Type* t = gvn.type(m)->meet_speculative(gvn.type(n));
|
needs_phi = true;
|
||||||
Node* phi = PhiNode::make(region, m, t);
|
t = t->meet_speculative(gvn.type(m));
|
||||||
phi->set_req(2, n);
|
|
||||||
kit.map()->set_req(i, gvn.transform(phi));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ins[j] = m;
|
||||||
|
}
|
||||||
|
if (needs_phi) {
|
||||||
|
Node* phi = PhiNode::make(region, n, t);
|
||||||
|
for (int j = 1; j < results; j++) {
|
||||||
|
phi->set_req(j + 1, ins[j]);
|
||||||
|
}
|
||||||
|
map->set_req(i, gvn.transform(phi));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return kit.transfer_exceptions_into_jvms();
|
return kit.transfer_exceptions_into_jvms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1025,7 +1119,7 @@ public:
|
||||||
virtual bool is_virtual() const { ShouldNotReachHere(); return false; }
|
virtual bool is_virtual() const { ShouldNotReachHere(); return false; }
|
||||||
virtual bool is_trap() const { return true; }
|
virtual bool is_trap() const { return true; }
|
||||||
|
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
|
virtual JVMState* generate(JVMState* jvms);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1037,7 +1131,7 @@ CallGenerator::for_uncommon_trap(ciMethod* m,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
|
JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms) {
|
||||||
GraphKit kit(jvms);
|
GraphKit kit(jvms);
|
||||||
kit.C->print_inlining_update(this);
|
kit.C->print_inlining_update(this);
|
||||||
// Take the trap with arguments pushed on the stack. (Cf. null_check_receiver).
|
// Take the trap with arguments pushed on the stack. (Cf. null_check_receiver).
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
#include "opto/type.hpp"
|
#include "opto/type.hpp"
|
||||||
#include "runtime/deoptimization.hpp"
|
#include "runtime/deoptimization.hpp"
|
||||||
|
|
||||||
class Parse;
|
|
||||||
|
|
||||||
//---------------------------CallGenerator-------------------------------------
|
//---------------------------CallGenerator-------------------------------------
|
||||||
// The subclasses of this class handle generation of ideal nodes for
|
// The subclasses of this class handle generation of ideal nodes for
|
||||||
// call sites and method entry points.
|
// call sites and method entry points.
|
||||||
|
@ -63,8 +61,9 @@ class CallGenerator : public ResourceObj {
|
||||||
virtual bool is_virtual() const { return false; }
|
virtual bool is_virtual() const { return false; }
|
||||||
// is_deferred: The decision whether to inline or not is deferred.
|
// is_deferred: The decision whether to inline or not is deferred.
|
||||||
virtual bool is_deferred() const { return false; }
|
virtual bool is_deferred() const { return false; }
|
||||||
// is_predicted: Uses an explicit check against a predicted type.
|
// is_predicated: Uses an explicit check (predicate).
|
||||||
virtual bool is_predicted() const { return false; }
|
virtual bool is_predicated() const { return false; }
|
||||||
|
virtual int predicates_count() const { return 0; }
|
||||||
// is_trap: Does not return to the caller. (E.g., uncommon trap.)
|
// is_trap: Does not return to the caller. (E.g., uncommon trap.)
|
||||||
virtual bool is_trap() const { return false; }
|
virtual bool is_trap() const { return false; }
|
||||||
// does_virtual_dispatch: Should try inlining as normal method first.
|
// does_virtual_dispatch: Should try inlining as normal method first.
|
||||||
|
@ -114,7 +113,7 @@ class CallGenerator : public ResourceObj {
|
||||||
//
|
//
|
||||||
// If the result is NULL, it means that this CallGenerator was unable
|
// If the result is NULL, it means that this CallGenerator was unable
|
||||||
// to handle the given call, and another CallGenerator should be consulted.
|
// to handle the given call, and another CallGenerator should be consulted.
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) = 0;
|
virtual JVMState* generate(JVMState* jvms) = 0;
|
||||||
|
|
||||||
// How to generate a call site that is inlined:
|
// How to generate a call site that is inlined:
|
||||||
static CallGenerator* for_inline(ciMethod* m, float expected_uses = -1);
|
static CallGenerator* for_inline(ciMethod* m, float expected_uses = -1);
|
||||||
|
@ -160,9 +159,9 @@ class CallGenerator : public ResourceObj {
|
||||||
// Registry for intrinsics:
|
// Registry for intrinsics:
|
||||||
static CallGenerator* for_intrinsic(ciMethod* m);
|
static CallGenerator* for_intrinsic(ciMethod* m);
|
||||||
static void register_intrinsic(ciMethod* m, CallGenerator* cg);
|
static void register_intrinsic(ciMethod* m, CallGenerator* cg);
|
||||||
static CallGenerator* for_predicted_intrinsic(CallGenerator* intrinsic,
|
static CallGenerator* for_predicated_intrinsic(CallGenerator* intrinsic,
|
||||||
CallGenerator* cg);
|
CallGenerator* cg);
|
||||||
virtual Node* generate_predicate(JVMState* jvms) { return NULL; };
|
virtual Node* generate_predicate(JVMState* jvms, int predicate) { return NULL; };
|
||||||
|
|
||||||
virtual void print_inlining_late(const char* msg) { ShouldNotReachHere(); }
|
virtual void print_inlining_late(const char* msg) { ShouldNotReachHere(); }
|
||||||
|
|
||||||
|
|
|
@ -1090,6 +1090,7 @@ const Type *SafePointNode::Value( PhaseTransform *phase ) const {
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void SafePointNode::dump_spec(outputStream *st) const {
|
void SafePointNode::dump_spec(outputStream *st) const {
|
||||||
st->print(" SafePoint ");
|
st->print(" SafePoint ");
|
||||||
|
_replaced_nodes.dump(st);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "opto/multnode.hpp"
|
#include "opto/multnode.hpp"
|
||||||
#include "opto/opcodes.hpp"
|
#include "opto/opcodes.hpp"
|
||||||
#include "opto/phaseX.hpp"
|
#include "opto/phaseX.hpp"
|
||||||
|
#include "opto/replacednodes.hpp"
|
||||||
#include "opto/type.hpp"
|
#include "opto/type.hpp"
|
||||||
|
|
||||||
// Portions of code courtesy of Clifford Click
|
// Portions of code courtesy of Clifford Click
|
||||||
|
@ -335,6 +336,7 @@ public:
|
||||||
OopMap* _oop_map; // Array of OopMap info (8-bit char) for GC
|
OopMap* _oop_map; // Array of OopMap info (8-bit char) for GC
|
||||||
JVMState* const _jvms; // Pointer to list of JVM State objects
|
JVMState* const _jvms; // Pointer to list of JVM State objects
|
||||||
const TypePtr* _adr_type; // What type of memory does this node produce?
|
const TypePtr* _adr_type; // What type of memory does this node produce?
|
||||||
|
ReplacedNodes _replaced_nodes; // During parsing: list of pair of nodes from calls to GraphKit::replace_in_map()
|
||||||
|
|
||||||
// Many calls take *all* of memory as input,
|
// Many calls take *all* of memory as input,
|
||||||
// but some produce a limited subset of that memory as output.
|
// but some produce a limited subset of that memory as output.
|
||||||
|
@ -426,6 +428,37 @@ public:
|
||||||
void set_next_exception(SafePointNode* n);
|
void set_next_exception(SafePointNode* n);
|
||||||
bool has_exceptions() const { return next_exception() != NULL; }
|
bool has_exceptions() const { return next_exception() != NULL; }
|
||||||
|
|
||||||
|
// Helper methods to operate on replaced nodes
|
||||||
|
ReplacedNodes replaced_nodes() const {
|
||||||
|
return _replaced_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_replaced_nodes(ReplacedNodes replaced_nodes) {
|
||||||
|
_replaced_nodes = replaced_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clone_replaced_nodes() {
|
||||||
|
_replaced_nodes.clone();
|
||||||
|
}
|
||||||
|
void record_replaced_node(Node* initial, Node* improved) {
|
||||||
|
_replaced_nodes.record(initial, improved);
|
||||||
|
}
|
||||||
|
void transfer_replaced_nodes_from(SafePointNode* sfpt, uint idx = 0) {
|
||||||
|
_replaced_nodes.transfer_from(sfpt->_replaced_nodes, idx);
|
||||||
|
}
|
||||||
|
void delete_replaced_nodes() {
|
||||||
|
_replaced_nodes.reset();
|
||||||
|
}
|
||||||
|
void apply_replaced_nodes() {
|
||||||
|
_replaced_nodes.apply(this);
|
||||||
|
}
|
||||||
|
void merge_replaced_nodes_with(SafePointNode* sfpt) {
|
||||||
|
_replaced_nodes.merge_with(sfpt->_replaced_nodes);
|
||||||
|
}
|
||||||
|
bool has_replaced_nodes() const {
|
||||||
|
return !_replaced_nodes.is_empty();
|
||||||
|
}
|
||||||
|
|
||||||
// Standard Node stuff
|
// Standard Node stuff
|
||||||
virtual int Opcode() const;
|
virtual int Opcode() const;
|
||||||
virtual bool pinned() const { return true; }
|
virtual bool pinned() const { return true; }
|
||||||
|
|
|
@ -392,6 +392,11 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) {
|
||||||
uint next = 0;
|
uint next = 0;
|
||||||
while (next < useful.size()) {
|
while (next < useful.size()) {
|
||||||
Node *n = useful.at(next++);
|
Node *n = useful.at(next++);
|
||||||
|
if (n->is_SafePoint()) {
|
||||||
|
// We're done with a parsing phase. Replaced nodes are not valid
|
||||||
|
// beyond that point.
|
||||||
|
n->as_SafePoint()->delete_replaced_nodes();
|
||||||
|
}
|
||||||
// Use raw traversal of out edges since this code removes out edges
|
// Use raw traversal of out edges since this code removes out edges
|
||||||
int max = n->outcnt();
|
int max = n->outcnt();
|
||||||
for (int j = 0; j < max; ++j) {
|
for (int j = 0; j < max; ++j) {
|
||||||
|
@ -673,7 +678,6 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||||
_print_inlining_stream(NULL),
|
_print_inlining_stream(NULL),
|
||||||
_print_inlining_idx(0),
|
_print_inlining_idx(0),
|
||||||
_print_inlining_output(NULL),
|
_print_inlining_output(NULL),
|
||||||
_preserve_jvm_state(0),
|
|
||||||
_interpreter_frame_size(0) {
|
_interpreter_frame_size(0) {
|
||||||
C = this;
|
C = this;
|
||||||
|
|
||||||
|
@ -783,7 +787,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JVMState* jvms = build_start_state(start(), tf());
|
JVMState* jvms = build_start_state(start(), tf());
|
||||||
if ((jvms = cg->generate(jvms, NULL)) == NULL) {
|
if ((jvms = cg->generate(jvms)) == NULL) {
|
||||||
record_method_not_compilable("method parse failed");
|
record_method_not_compilable("method parse failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -980,7 +984,6 @@ Compile::Compile( ciEnv* ci_env,
|
||||||
_print_inlining_stream(NULL),
|
_print_inlining_stream(NULL),
|
||||||
_print_inlining_idx(0),
|
_print_inlining_idx(0),
|
||||||
_print_inlining_output(NULL),
|
_print_inlining_output(NULL),
|
||||||
_preserve_jvm_state(0),
|
|
||||||
_allowed_reasons(0),
|
_allowed_reasons(0),
|
||||||
_interpreter_frame_size(0) {
|
_interpreter_frame_size(0) {
|
||||||
C = this;
|
C = this;
|
||||||
|
@ -1914,6 +1917,8 @@ void Compile::inline_boxing_calls(PhaseIterGVN& igvn) {
|
||||||
for_igvn()->clear();
|
for_igvn()->clear();
|
||||||
gvn->replace_with(&igvn);
|
gvn->replace_with(&igvn);
|
||||||
|
|
||||||
|
_late_inlines_pos = _late_inlines.length();
|
||||||
|
|
||||||
while (_boxing_late_inlines.length() > 0) {
|
while (_boxing_late_inlines.length() > 0) {
|
||||||
CallGenerator* cg = _boxing_late_inlines.pop();
|
CallGenerator* cg = _boxing_late_inlines.pop();
|
||||||
cg->do_late_inline();
|
cg->do_late_inline();
|
||||||
|
@ -1977,8 +1982,8 @@ void Compile::inline_incrementally(PhaseIterGVN& igvn) {
|
||||||
if (live_nodes() > (uint)LiveNodeCountInliningCutoff) {
|
if (live_nodes() > (uint)LiveNodeCountInliningCutoff) {
|
||||||
if (low_live_nodes < (uint)LiveNodeCountInliningCutoff * 8 / 10) {
|
if (low_live_nodes < (uint)LiveNodeCountInliningCutoff * 8 / 10) {
|
||||||
// PhaseIdealLoop is expensive so we only try it once we are
|
// PhaseIdealLoop is expensive so we only try it once we are
|
||||||
// out of loop and we only try it again if the previous helped
|
// out of live nodes and we only try it again if the previous
|
||||||
// got the number of nodes down significantly
|
// helped got the number of nodes down significantly
|
||||||
PhaseIdealLoop ideal_loop( igvn, false, true );
|
PhaseIdealLoop ideal_loop( igvn, false, true );
|
||||||
if (failing()) return;
|
if (failing()) return;
|
||||||
low_live_nodes = live_nodes();
|
low_live_nodes = live_nodes();
|
||||||
|
@ -2072,6 +2077,10 @@ void Compile::Optimize() {
|
||||||
// Inline valueOf() methods now.
|
// Inline valueOf() methods now.
|
||||||
inline_boxing_calls(igvn);
|
inline_boxing_calls(igvn);
|
||||||
|
|
||||||
|
if (AlwaysIncrementalInline) {
|
||||||
|
inline_incrementally(igvn);
|
||||||
|
}
|
||||||
|
|
||||||
print_method(PHASE_INCREMENTAL_BOXING_INLINE, 2);
|
print_method(PHASE_INCREMENTAL_BOXING_INLINE, 2);
|
||||||
|
|
||||||
if (failing()) return;
|
if (failing()) return;
|
||||||
|
|
|
@ -431,9 +431,6 @@ class Compile : public Phase {
|
||||||
// Remove the speculative part of types and clean up the graph
|
// Remove the speculative part of types and clean up the graph
|
||||||
void remove_speculative_types(PhaseIterGVN &igvn);
|
void remove_speculative_types(PhaseIterGVN &igvn);
|
||||||
|
|
||||||
// Are we within a PreserveJVMState block?
|
|
||||||
int _preserve_jvm_state;
|
|
||||||
|
|
||||||
void* _replay_inline_data; // Pointer to data loaded from file
|
void* _replay_inline_data; // Pointer to data loaded from file
|
||||||
|
|
||||||
void print_inlining_init();
|
void print_inlining_init();
|
||||||
|
@ -1198,21 +1195,6 @@ class Compile : public Phase {
|
||||||
|
|
||||||
// Auxiliary method for randomized fuzzing/stressing
|
// Auxiliary method for randomized fuzzing/stressing
|
||||||
static bool randomized_select(int count);
|
static bool randomized_select(int count);
|
||||||
|
|
||||||
// enter a PreserveJVMState block
|
|
||||||
void inc_preserve_jvm_state() {
|
|
||||||
_preserve_jvm_state++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// exit a PreserveJVMState block
|
|
||||||
void dec_preserve_jvm_state() {
|
|
||||||
_preserve_jvm_state--;
|
|
||||||
assert(_preserve_jvm_state >= 0, "_preserve_jvm_state shouldn't be negative");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_preserve_jvm_state() const {
|
|
||||||
return _preserve_jvm_state > 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_VM_OPTO_COMPILE_HPP
|
#endif // SHARE_VM_OPTO_COMPILE_HPP
|
||||||
|
|
|
@ -119,12 +119,12 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
|
||||||
if (allow_inline && allow_intrinsics) {
|
if (allow_inline && allow_intrinsics) {
|
||||||
CallGenerator* cg = find_intrinsic(callee, call_does_dispatch);
|
CallGenerator* cg = find_intrinsic(callee, call_does_dispatch);
|
||||||
if (cg != NULL) {
|
if (cg != NULL) {
|
||||||
if (cg->is_predicted()) {
|
if (cg->is_predicated()) {
|
||||||
// Code without intrinsic but, hopefully, inlined.
|
// Code without intrinsic but, hopefully, inlined.
|
||||||
CallGenerator* inline_cg = this->call_generator(callee,
|
CallGenerator* inline_cg = this->call_generator(callee,
|
||||||
vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor, speculative_receiver_type, false);
|
vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor, speculative_receiver_type, false);
|
||||||
if (inline_cg != NULL) {
|
if (inline_cg != NULL) {
|
||||||
cg = CallGenerator::for_predicted_intrinsic(cg, inline_cg);
|
cg = CallGenerator::for_predicated_intrinsic(cg, inline_cg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,7 +525,7 @@ void Parse::do_call() {
|
||||||
// because exceptions don't return to the call site.)
|
// because exceptions don't return to the call site.)
|
||||||
profile_call(receiver);
|
profile_call(receiver);
|
||||||
|
|
||||||
JVMState* new_jvms = cg->generate(jvms, this);
|
JVMState* new_jvms = cg->generate(jvms);
|
||||||
if (new_jvms == NULL) {
|
if (new_jvms == NULL) {
|
||||||
// When inlining attempt fails (e.g., too many arguments),
|
// When inlining attempt fails (e.g., too many arguments),
|
||||||
// it may contaminate the current compile state, making it
|
// it may contaminate the current compile state, making it
|
||||||
|
@ -539,7 +539,7 @@ void Parse::do_call() {
|
||||||
// intrinsic was expecting to optimize. Should always be possible to
|
// intrinsic was expecting to optimize. Should always be possible to
|
||||||
// get a normal java call that may inline in that case
|
// get a normal java call that may inline in that case
|
||||||
cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type, /* allow_intrinsics= */ false);
|
cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type, /* allow_intrinsics= */ false);
|
||||||
new_jvms = cg->generate(jvms, this);
|
new_jvms = cg->generate(jvms);
|
||||||
if (new_jvms == NULL) {
|
if (new_jvms == NULL) {
|
||||||
guarantee(failing(), "call failed to generate: calls should work");
|
guarantee(failing(), "call failed to generate: calls should work");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -939,7 +939,13 @@ void ConnectionGraph::process_call_arguments(CallNode *call) {
|
||||||
strcmp(call->as_CallLeaf()->_name, "aescrypt_encryptBlock") == 0 ||
|
strcmp(call->as_CallLeaf()->_name, "aescrypt_encryptBlock") == 0 ||
|
||||||
strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 ||
|
strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 ||
|
||||||
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 ||
|
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 ||
|
||||||
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_decryptAESCrypt") == 0)
|
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_decryptAESCrypt") == 0 ||
|
||||||
|
strcmp(call->as_CallLeaf()->_name, "sha1_implCompress") == 0 ||
|
||||||
|
strcmp(call->as_CallLeaf()->_name, "sha1_implCompressMB") == 0 ||
|
||||||
|
strcmp(call->as_CallLeaf()->_name, "sha256_implCompress") == 0 ||
|
||||||
|
strcmp(call->as_CallLeaf()->_name, "sha256_implCompressMB") == 0 ||
|
||||||
|
strcmp(call->as_CallLeaf()->_name, "sha512_implCompress") == 0 ||
|
||||||
|
strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0)
|
||||||
))) {
|
))) {
|
||||||
call->dump();
|
call->dump();
|
||||||
fatal(err_msg_res("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name));
|
fatal(err_msg_res("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name));
|
||||||
|
|
|
@ -432,6 +432,7 @@ void GraphKit::combine_exception_states(SafePointNode* ex_map, SafePointNode* ph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
phi_map->merge_replaced_nodes_with(ex_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------use_exception_state--------------------------------
|
//--------------------------use_exception_state--------------------------------
|
||||||
|
@ -645,7 +646,6 @@ PreserveJVMState::PreserveJVMState(GraphKit* kit, bool clone_map) {
|
||||||
_map = kit->map(); // preserve the map
|
_map = kit->map(); // preserve the map
|
||||||
_sp = kit->sp();
|
_sp = kit->sp();
|
||||||
kit->set_map(clone_map ? kit->clone_map() : NULL);
|
kit->set_map(clone_map ? kit->clone_map() : NULL);
|
||||||
Compile::current()->inc_preserve_jvm_state();
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
_bci = kit->bci();
|
_bci = kit->bci();
|
||||||
Parse* parser = kit->is_Parse();
|
Parse* parser = kit->is_Parse();
|
||||||
|
@ -663,7 +663,6 @@ PreserveJVMState::~PreserveJVMState() {
|
||||||
#endif
|
#endif
|
||||||
kit->set_map(_map);
|
kit->set_map(_map);
|
||||||
kit->set_sp(_sp);
|
kit->set_sp(_sp);
|
||||||
Compile::current()->dec_preserve_jvm_state();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1403,60 +1402,17 @@ void GraphKit::replace_in_map(Node* old, Node* neww) {
|
||||||
// on the map. This includes locals, stack, and monitors
|
// on the map. This includes locals, stack, and monitors
|
||||||
// of the current (innermost) JVM state.
|
// of the current (innermost) JVM state.
|
||||||
|
|
||||||
if (!ReplaceInParentMaps) {
|
// don't let inconsistent types from profiling escape this
|
||||||
|
// method
|
||||||
|
|
||||||
|
const Type* told = _gvn.type(old);
|
||||||
|
const Type* tnew = _gvn.type(neww);
|
||||||
|
|
||||||
|
if (!tnew->higher_equal(told)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PreserveJVMState doesn't do a deep copy so we can't modify
|
map()->record_replaced_node(old, neww);
|
||||||
// parents
|
|
||||||
if (Compile::current()->has_preserve_jvm_state()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Parse* parser = is_Parse();
|
|
||||||
bool progress = true;
|
|
||||||
Node* ctrl = map()->in(0);
|
|
||||||
// Follow the chain of parsers and see whether the update can be
|
|
||||||
// done in the map of callers. We can do the replace for a caller if
|
|
||||||
// the current control post dominates the control of a caller.
|
|
||||||
while (parser != NULL && parser->caller() != NULL && progress) {
|
|
||||||
progress = false;
|
|
||||||
Node* parent_map = parser->caller()->map();
|
|
||||||
assert(parser->exits().map()->jvms()->depth() == parser->caller()->depth(), "map mismatch");
|
|
||||||
|
|
||||||
Node* parent_ctrl = parent_map->in(0);
|
|
||||||
|
|
||||||
while (parent_ctrl->is_Region()) {
|
|
||||||
Node* n = parent_ctrl->as_Region()->is_copy();
|
|
||||||
if (n == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
parent_ctrl = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (ctrl == parent_ctrl) {
|
|
||||||
// update the map of the exits which is the one that will be
|
|
||||||
// used when compilation resume after inlining
|
|
||||||
parser->exits().map()->replace_edge(old, neww);
|
|
||||||
progress = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ctrl->is_Proj() && ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) {
|
|
||||||
ctrl = ctrl->in(0)->in(0);
|
|
||||||
} else if (ctrl->is_Region()) {
|
|
||||||
Node* n = ctrl->as_Region()->is_copy();
|
|
||||||
if (n == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ctrl = n;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parser = parser->parent_parser();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1864,12 +1820,16 @@ void GraphKit::set_predefined_output_for_runtime_call(Node* call,
|
||||||
|
|
||||||
|
|
||||||
// Replace the call with the current state of the kit.
|
// Replace the call with the current state of the kit.
|
||||||
void GraphKit::replace_call(CallNode* call, Node* result) {
|
void GraphKit::replace_call(CallNode* call, Node* result, bool do_replaced_nodes) {
|
||||||
JVMState* ejvms = NULL;
|
JVMState* ejvms = NULL;
|
||||||
if (has_exceptions()) {
|
if (has_exceptions()) {
|
||||||
ejvms = transfer_exceptions_into_jvms();
|
ejvms = transfer_exceptions_into_jvms();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReplacedNodes replaced_nodes = map()->replaced_nodes();
|
||||||
|
ReplacedNodes replaced_nodes_exception;
|
||||||
|
Node* ex_ctl = top();
|
||||||
|
|
||||||
SafePointNode* final_state = stop();
|
SafePointNode* final_state = stop();
|
||||||
|
|
||||||
// Find all the needed outputs of this call
|
// Find all the needed outputs of this call
|
||||||
|
@ -1886,6 +1846,10 @@ void GraphKit::replace_call(CallNode* call, Node* result) {
|
||||||
C->gvn_replace_by(callprojs.fallthrough_catchproj, final_ctl);
|
C->gvn_replace_by(callprojs.fallthrough_catchproj, final_ctl);
|
||||||
}
|
}
|
||||||
if (callprojs.fallthrough_memproj != NULL) {
|
if (callprojs.fallthrough_memproj != NULL) {
|
||||||
|
if (final_mem->is_MergeMem()) {
|
||||||
|
// Parser's exits MergeMem was not transformed but may be optimized
|
||||||
|
final_mem = _gvn.transform(final_mem);
|
||||||
|
}
|
||||||
C->gvn_replace_by(callprojs.fallthrough_memproj, final_mem);
|
C->gvn_replace_by(callprojs.fallthrough_memproj, final_mem);
|
||||||
}
|
}
|
||||||
if (callprojs.fallthrough_ioproj != NULL) {
|
if (callprojs.fallthrough_ioproj != NULL) {
|
||||||
|
@ -1917,10 +1881,13 @@ void GraphKit::replace_call(CallNode* call, Node* result) {
|
||||||
|
|
||||||
// Load my combined exception state into the kit, with all phis transformed:
|
// Load my combined exception state into the kit, with all phis transformed:
|
||||||
SafePointNode* ex_map = ekit.combine_and_pop_all_exception_states();
|
SafePointNode* ex_map = ekit.combine_and_pop_all_exception_states();
|
||||||
|
replaced_nodes_exception = ex_map->replaced_nodes();
|
||||||
|
|
||||||
Node* ex_oop = ekit.use_exception_state(ex_map);
|
Node* ex_oop = ekit.use_exception_state(ex_map);
|
||||||
|
|
||||||
if (callprojs.catchall_catchproj != NULL) {
|
if (callprojs.catchall_catchproj != NULL) {
|
||||||
C->gvn_replace_by(callprojs.catchall_catchproj, ekit.control());
|
C->gvn_replace_by(callprojs.catchall_catchproj, ekit.control());
|
||||||
|
ex_ctl = ekit.control();
|
||||||
}
|
}
|
||||||
if (callprojs.catchall_memproj != NULL) {
|
if (callprojs.catchall_memproj != NULL) {
|
||||||
C->gvn_replace_by(callprojs.catchall_memproj, ekit.reset_memory());
|
C->gvn_replace_by(callprojs.catchall_memproj, ekit.reset_memory());
|
||||||
|
@ -1953,6 +1920,13 @@ void GraphKit::replace_call(CallNode* call, Node* result) {
|
||||||
_gvn.transform(wl.pop());
|
_gvn.transform(wl.pop());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (callprojs.fallthrough_catchproj != NULL && !final_ctl->is_top() && do_replaced_nodes) {
|
||||||
|
replaced_nodes.apply(C, final_ctl);
|
||||||
|
}
|
||||||
|
if (!ex_ctl->is_top() && do_replaced_nodes) {
|
||||||
|
replaced_nodes_exception.apply(C, ex_ctl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2490,30 +2464,31 @@ void GraphKit::merge_memory(Node* new_mem, Node* region, int new_path) {
|
||||||
Node* new_slice = mms.memory2();
|
Node* new_slice = mms.memory2();
|
||||||
if (old_slice != new_slice) {
|
if (old_slice != new_slice) {
|
||||||
PhiNode* phi;
|
PhiNode* phi;
|
||||||
if (new_slice->is_Phi() && new_slice->as_Phi()->region() == region) {
|
if (old_slice->is_Phi() && old_slice->as_Phi()->region() == region) {
|
||||||
phi = new_slice->as_Phi();
|
if (mms.is_empty()) {
|
||||||
#ifdef ASSERT
|
// clone base memory Phi's inputs for this memory slice
|
||||||
if (old_slice->is_Phi() && old_slice->as_Phi()->region() == region)
|
assert(old_slice == mms.base_memory(), "sanity");
|
||||||
old_slice = old_slice->in(new_path);
|
phi = PhiNode::make(region, NULL, Type::MEMORY, mms.adr_type(C));
|
||||||
// Caller is responsible for ensuring that any pre-existing
|
_gvn.set_type(phi, Type::MEMORY);
|
||||||
// phis are already aware of old memory.
|
for (uint i = 1; i < phi->req(); i++) {
|
||||||
int old_path = (new_path > 1) ? 1 : 2; // choose old_path != new_path
|
phi->init_req(i, old_slice->in(i));
|
||||||
assert(phi->in(old_path) == old_slice, "pre-existing phis OK");
|
}
|
||||||
#endif
|
} else {
|
||||||
mms.set_memory(phi);
|
phi = old_slice->as_Phi(); // Phi was generated already
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
phi = PhiNode::make(region, old_slice, Type::MEMORY, mms.adr_type(C));
|
phi = PhiNode::make(region, old_slice, Type::MEMORY, mms.adr_type(C));
|
||||||
_gvn.set_type(phi, Type::MEMORY);
|
_gvn.set_type(phi, Type::MEMORY);
|
||||||
phi->set_req(new_path, new_slice);
|
|
||||||
mms.set_memory(_gvn.transform(phi)); // assume it is complete
|
|
||||||
}
|
}
|
||||||
|
phi->set_req(new_path, new_slice);
|
||||||
|
mms.set_memory(phi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------make_slow_call_ex------------------------------
|
//------------------------------make_slow_call_ex------------------------------
|
||||||
// Make the exception handler hookups for the slow call
|
// Make the exception handler hookups for the slow call
|
||||||
void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj) {
|
void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj, bool deoptimize) {
|
||||||
if (stopped()) return;
|
if (stopped()) return;
|
||||||
|
|
||||||
// Make a catch node with just two handlers: fall-through and catch-all
|
// Make a catch node with just two handlers: fall-through and catch-all
|
||||||
|
@ -2527,6 +2502,11 @@ void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool sep
|
||||||
set_i_o(i_o);
|
set_i_o(i_o);
|
||||||
|
|
||||||
if (excp != top()) {
|
if (excp != top()) {
|
||||||
|
if (deoptimize) {
|
||||||
|
// Deoptimize if an exception is caught. Don't construct exception state in this case.
|
||||||
|
uncommon_trap(Deoptimization::Reason_unhandled,
|
||||||
|
Deoptimization::Action_none);
|
||||||
|
} else {
|
||||||
// Create an exception state also.
|
// Create an exception state also.
|
||||||
// Use an exact type if the caller has specified a specific exception.
|
// Use an exact type if the caller has specified a specific exception.
|
||||||
const Type* ex_type = TypeOopPtr::make_from_klass_unique(ex_klass)->cast_to_ptr_type(TypePtr::NotNull);
|
const Type* ex_type = TypeOopPtr::make_from_klass_unique(ex_klass)->cast_to_ptr_type(TypePtr::NotNull);
|
||||||
|
@ -2534,6 +2514,7 @@ void GraphKit::make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool sep
|
||||||
add_exception_state(make_exception_state(_gvn.transform(ex_oop)));
|
add_exception_state(make_exception_state(_gvn.transform(ex_oop)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get the no-exception control from the CatchNode.
|
// Get the no-exception control from the CatchNode.
|
||||||
set_control(norm);
|
set_control(norm);
|
||||||
|
@ -3352,7 +3333,8 @@ static void hook_memory_on_init(GraphKit& kit, int alias_idx,
|
||||||
|
|
||||||
//---------------------------set_output_for_allocation-------------------------
|
//---------------------------set_output_for_allocation-------------------------
|
||||||
Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
|
Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
|
||||||
const TypeOopPtr* oop_type) {
|
const TypeOopPtr* oop_type,
|
||||||
|
bool deoptimize_on_exception) {
|
||||||
int rawidx = Compile::AliasIdxRaw;
|
int rawidx = Compile::AliasIdxRaw;
|
||||||
alloc->set_req( TypeFunc::FramePtr, frameptr() );
|
alloc->set_req( TypeFunc::FramePtr, frameptr() );
|
||||||
add_safepoint_edges(alloc);
|
add_safepoint_edges(alloc);
|
||||||
|
@ -3360,7 +3342,7 @@ Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
|
||||||
set_control( _gvn.transform(new ProjNode(allocx, TypeFunc::Control) ) );
|
set_control( _gvn.transform(new ProjNode(allocx, TypeFunc::Control) ) );
|
||||||
// create memory projection for i_o
|
// create memory projection for i_o
|
||||||
set_memory ( _gvn.transform( new ProjNode(allocx, TypeFunc::Memory, true) ), rawidx );
|
set_memory ( _gvn.transform( new ProjNode(allocx, TypeFunc::Memory, true) ), rawidx );
|
||||||
make_slow_call_ex(allocx, env()->Throwable_klass(), true);
|
make_slow_call_ex(allocx, env()->Throwable_klass(), true, deoptimize_on_exception);
|
||||||
|
|
||||||
// create a memory projection as for the normal control path
|
// create a memory projection as for the normal control path
|
||||||
Node* malloc = _gvn.transform(new ProjNode(allocx, TypeFunc::Memory));
|
Node* malloc = _gvn.transform(new ProjNode(allocx, TypeFunc::Memory));
|
||||||
|
@ -3438,9 +3420,11 @@ Node* GraphKit::set_output_for_allocation(AllocateNode* alloc,
|
||||||
// The optional arguments are for specialized use by intrinsics:
|
// The optional arguments are for specialized use by intrinsics:
|
||||||
// - If 'extra_slow_test' if not null is an extra condition for the slow-path.
|
// - If 'extra_slow_test' if not null is an extra condition for the slow-path.
|
||||||
// - If 'return_size_val', report the the total object size to the caller.
|
// - If 'return_size_val', report the the total object size to the caller.
|
||||||
|
// - deoptimize_on_exception controls how Java exceptions are handled (rethrow vs deoptimize)
|
||||||
Node* GraphKit::new_instance(Node* klass_node,
|
Node* GraphKit::new_instance(Node* klass_node,
|
||||||
Node* extra_slow_test,
|
Node* extra_slow_test,
|
||||||
Node* *return_size_val) {
|
Node* *return_size_val,
|
||||||
|
bool deoptimize_on_exception) {
|
||||||
// Compute size in doublewords
|
// Compute size in doublewords
|
||||||
// The size is always an integral number of doublewords, represented
|
// The size is always an integral number of doublewords, represented
|
||||||
// as a positive bytewise size stored in the klass's layout_helper.
|
// as a positive bytewise size stored in the klass's layout_helper.
|
||||||
|
@ -3508,7 +3492,7 @@ Node* GraphKit::new_instance(Node* klass_node,
|
||||||
size, klass_node,
|
size, klass_node,
|
||||||
initial_slow_test);
|
initial_slow_test);
|
||||||
|
|
||||||
return set_output_for_allocation(alloc, oop_type);
|
return set_output_for_allocation(alloc, oop_type, deoptimize_on_exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------new_array-------------------------------------
|
//-------------------------------new_array-------------------------------------
|
||||||
|
@ -3518,7 +3502,8 @@ Node* GraphKit::new_instance(Node* klass_node,
|
||||||
Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
|
Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
|
||||||
Node* length, // number of array elements
|
Node* length, // number of array elements
|
||||||
int nargs, // number of arguments to push back for uncommon trap
|
int nargs, // number of arguments to push back for uncommon trap
|
||||||
Node* *return_size_val) {
|
Node* *return_size_val,
|
||||||
|
bool deoptimize_on_exception) {
|
||||||
jint layout_con = Klass::_lh_neutral_value;
|
jint layout_con = Klass::_lh_neutral_value;
|
||||||
Node* layout_val = get_layout_helper(klass_node, layout_con);
|
Node* layout_val = get_layout_helper(klass_node, layout_con);
|
||||||
int layout_is_con = (layout_val == NULL);
|
int layout_is_con = (layout_val == NULL);
|
||||||
|
@ -3661,7 +3646,7 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
|
||||||
ary_type = ary_type->is_aryptr()->cast_to_size(length_type);
|
ary_type = ary_type->is_aryptr()->cast_to_size(length_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* javaoop = set_output_for_allocation(alloc, ary_type);
|
Node* javaoop = set_output_for_allocation(alloc, ary_type, deoptimize_on_exception);
|
||||||
|
|
||||||
// Cast length on remaining path to be as narrow as possible
|
// Cast length on remaining path to be as narrow as possible
|
||||||
if (map()->find_edge(length) >= 0) {
|
if (map()->find_edge(length) >= 0) {
|
||||||
|
|
|
@ -690,7 +690,7 @@ class GraphKit : public Phase {
|
||||||
// Replace the call with the current state of the kit. Requires
|
// Replace the call with the current state of the kit. Requires
|
||||||
// that the call was generated with separate io_projs so that
|
// that the call was generated with separate io_projs so that
|
||||||
// exceptional control flow can be handled properly.
|
// exceptional control flow can be handled properly.
|
||||||
void replace_call(CallNode* call, Node* result);
|
void replace_call(CallNode* call, Node* result, bool do_replaced_nodes = false);
|
||||||
|
|
||||||
// helper functions for statistics
|
// helper functions for statistics
|
||||||
void increment_counter(address counter_addr); // increment a debug counter
|
void increment_counter(address counter_addr); // increment a debug counter
|
||||||
|
@ -807,7 +807,7 @@ class GraphKit : public Phase {
|
||||||
|
|
||||||
// merge in all memory slices from new_mem, along the given path
|
// merge in all memory slices from new_mem, along the given path
|
||||||
void merge_memory(Node* new_mem, Node* region, int new_path);
|
void merge_memory(Node* new_mem, Node* region, int new_path);
|
||||||
void make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj);
|
void make_slow_call_ex(Node* call, ciInstanceKlass* ex_klass, bool separate_io_proj, bool deoptimize = false);
|
||||||
|
|
||||||
// Helper functions to build synchronizations
|
// Helper functions to build synchronizations
|
||||||
int next_monitor();
|
int next_monitor();
|
||||||
|
@ -849,13 +849,16 @@ class GraphKit : public Phase {
|
||||||
|
|
||||||
// implementation of object creation
|
// implementation of object creation
|
||||||
Node* set_output_for_allocation(AllocateNode* alloc,
|
Node* set_output_for_allocation(AllocateNode* alloc,
|
||||||
const TypeOopPtr* oop_type);
|
const TypeOopPtr* oop_type,
|
||||||
|
bool deoptimize_on_exception=false);
|
||||||
Node* get_layout_helper(Node* klass_node, jint& constant_value);
|
Node* get_layout_helper(Node* klass_node, jint& constant_value);
|
||||||
Node* new_instance(Node* klass_node,
|
Node* new_instance(Node* klass_node,
|
||||||
Node* slow_test = NULL,
|
Node* slow_test = NULL,
|
||||||
Node* *return_size_val = NULL);
|
Node* *return_size_val = NULL,
|
||||||
|
bool deoptimize_on_exception = false);
|
||||||
Node* new_array(Node* klass_node, Node* count_val, int nargs,
|
Node* new_array(Node* klass_node, Node* count_val, int nargs,
|
||||||
Node* *return_size_val = NULL);
|
Node* *return_size_val = NULL,
|
||||||
|
bool deoptimize_on_exception = false);
|
||||||
|
|
||||||
// java.lang.String helpers
|
// java.lang.String helpers
|
||||||
Node* load_String_offset(Node* ctrl, Node* str);
|
Node* load_String_offset(Node* ctrl, Node* str);
|
||||||
|
|
|
@ -52,25 +52,28 @@ class LibraryIntrinsic : public InlineCallGenerator {
|
||||||
public:
|
public:
|
||||||
private:
|
private:
|
||||||
bool _is_virtual;
|
bool _is_virtual;
|
||||||
bool _is_predicted;
|
|
||||||
bool _does_virtual_dispatch;
|
bool _does_virtual_dispatch;
|
||||||
|
int8_t _predicates_count; // Intrinsic is predicated by several conditions
|
||||||
|
int8_t _last_predicate; // Last generated predicate
|
||||||
vmIntrinsics::ID _intrinsic_id;
|
vmIntrinsics::ID _intrinsic_id;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, bool does_virtual_dispatch, vmIntrinsics::ID id)
|
LibraryIntrinsic(ciMethod* m, bool is_virtual, int predicates_count, bool does_virtual_dispatch, vmIntrinsics::ID id)
|
||||||
: InlineCallGenerator(m),
|
: InlineCallGenerator(m),
|
||||||
_is_virtual(is_virtual),
|
_is_virtual(is_virtual),
|
||||||
_is_predicted(is_predicted),
|
|
||||||
_does_virtual_dispatch(does_virtual_dispatch),
|
_does_virtual_dispatch(does_virtual_dispatch),
|
||||||
|
_predicates_count((int8_t)predicates_count),
|
||||||
|
_last_predicate((int8_t)-1),
|
||||||
_intrinsic_id(id)
|
_intrinsic_id(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual bool is_intrinsic() const { return true; }
|
virtual bool is_intrinsic() const { return true; }
|
||||||
virtual bool is_virtual() const { return _is_virtual; }
|
virtual bool is_virtual() const { return _is_virtual; }
|
||||||
virtual bool is_predicted() const { return _is_predicted; }
|
virtual bool is_predicated() const { return _predicates_count > 0; }
|
||||||
|
virtual int predicates_count() const { return _predicates_count; }
|
||||||
virtual bool does_virtual_dispatch() const { return _does_virtual_dispatch; }
|
virtual bool does_virtual_dispatch() const { return _does_virtual_dispatch; }
|
||||||
virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
|
virtual JVMState* generate(JVMState* jvms);
|
||||||
virtual Node* generate_predicate(JVMState* jvms);
|
virtual Node* generate_predicate(JVMState* jvms, int predicate);
|
||||||
vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; }
|
vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,8 +116,8 @@ class LibraryCallKit : public GraphKit {
|
||||||
vmIntrinsics::ID intrinsic_id() const { return _intrinsic->intrinsic_id(); }
|
vmIntrinsics::ID intrinsic_id() const { return _intrinsic->intrinsic_id(); }
|
||||||
ciMethod* callee() const { return _intrinsic->method(); }
|
ciMethod* callee() const { return _intrinsic->method(); }
|
||||||
|
|
||||||
bool try_to_inline();
|
bool try_to_inline(int predicate);
|
||||||
Node* try_to_predicate();
|
Node* try_to_predicate(int predicate);
|
||||||
|
|
||||||
void push_result() {
|
void push_result() {
|
||||||
// Push the result onto the stack.
|
// Push the result onto the stack.
|
||||||
|
@ -313,6 +316,14 @@ class LibraryCallKit : public GraphKit {
|
||||||
Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting);
|
Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting);
|
||||||
Node* get_key_start_from_aescrypt_object(Node* aescrypt_object);
|
Node* get_key_start_from_aescrypt_object(Node* aescrypt_object);
|
||||||
Node* get_original_key_start_from_aescrypt_object(Node* aescrypt_object);
|
Node* get_original_key_start_from_aescrypt_object(Node* aescrypt_object);
|
||||||
|
bool inline_sha_implCompress(vmIntrinsics::ID id);
|
||||||
|
bool inline_digestBase_implCompressMB(int predicate);
|
||||||
|
bool inline_sha_implCompressMB(Node* digestBaseObj, ciInstanceKlass* instklass_SHA,
|
||||||
|
bool long_state, address stubAddr, const char *stubName,
|
||||||
|
Node* src_start, Node* ofs, Node* limit);
|
||||||
|
Node* get_state_from_sha_object(Node *sha_object);
|
||||||
|
Node* get_state_from_sha5_object(Node *sha_object);
|
||||||
|
Node* inline_digestBase_implCompressMB_predicate(int predicate);
|
||||||
bool inline_encodeISOArray();
|
bool inline_encodeISOArray();
|
||||||
bool inline_updateCRC32();
|
bool inline_updateCRC32();
|
||||||
bool inline_updateBytesCRC32();
|
bool inline_updateBytesCRC32();
|
||||||
|
@ -373,7 +384,7 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_predicted = false;
|
int predicates = 0;
|
||||||
bool does_virtual_dispatch = false;
|
bool does_virtual_dispatch = false;
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
@ -513,7 +524,24 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
|
||||||
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
||||||
if (!UseAESIntrinsics) return NULL;
|
if (!UseAESIntrinsics) return NULL;
|
||||||
// these two require the predicated logic
|
// these two require the predicated logic
|
||||||
is_predicted = true;
|
predicates = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case vmIntrinsics::_sha_implCompress:
|
||||||
|
if (!UseSHA1Intrinsics) return NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case vmIntrinsics::_sha2_implCompress:
|
||||||
|
if (!UseSHA256Intrinsics) return NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case vmIntrinsics::_sha5_implCompress:
|
||||||
|
if (!UseSHA512Intrinsics) return NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case vmIntrinsics::_digestBase_implCompressMB:
|
||||||
|
if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return NULL;
|
||||||
|
predicates = 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vmIntrinsics::_updateCRC32:
|
case vmIntrinsics::_updateCRC32:
|
||||||
|
@ -582,7 +610,7 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
|
||||||
if (!InlineUnsafeOps) return NULL;
|
if (!InlineUnsafeOps) return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new LibraryIntrinsic(m, is_virtual, is_predicted, does_virtual_dispatch, (vmIntrinsics::ID) id);
|
return new LibraryIntrinsic(m, is_virtual, predicates, does_virtual_dispatch, (vmIntrinsics::ID) id);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------register_library_intrinsics-----------------------
|
//----------------------register_library_intrinsics-----------------------
|
||||||
|
@ -591,7 +619,7 @@ void Compile::register_library_intrinsics() {
|
||||||
// Nothing to do here.
|
// Nothing to do here.
|
||||||
}
|
}
|
||||||
|
|
||||||
JVMState* LibraryIntrinsic::generate(JVMState* jvms, Parse* parent_parser) {
|
JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
|
||||||
LibraryCallKit kit(jvms, this);
|
LibraryCallKit kit(jvms, this);
|
||||||
Compile* C = kit.C;
|
Compile* C = kit.C;
|
||||||
int nodes = C->unique();
|
int nodes = C->unique();
|
||||||
|
@ -606,7 +634,7 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms, Parse* parent_parser) {
|
||||||
const int bci = kit.bci();
|
const int bci = kit.bci();
|
||||||
|
|
||||||
// Try to inline the intrinsic.
|
// Try to inline the intrinsic.
|
||||||
if (kit.try_to_inline()) {
|
if (kit.try_to_inline(_last_predicate)) {
|
||||||
if (C->print_intrinsics() || C->print_inlining()) {
|
if (C->print_intrinsics() || C->print_inlining()) {
|
||||||
C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
|
C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
|
||||||
}
|
}
|
||||||
|
@ -641,12 +669,13 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms, Parse* parent_parser) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) {
|
Node* LibraryIntrinsic::generate_predicate(JVMState* jvms, int predicate) {
|
||||||
LibraryCallKit kit(jvms, this);
|
LibraryCallKit kit(jvms, this);
|
||||||
Compile* C = kit.C;
|
Compile* C = kit.C;
|
||||||
int nodes = C->unique();
|
int nodes = C->unique();
|
||||||
|
_last_predicate = predicate;
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
assert(is_predicted(), "sanity");
|
assert(is_predicated() && predicate < predicates_count(), "sanity");
|
||||||
if ((C->print_intrinsics() || C->print_inlining()) && Verbose) {
|
if ((C->print_intrinsics() || C->print_inlining()) && Verbose) {
|
||||||
char buf[1000];
|
char buf[1000];
|
||||||
const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf));
|
const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf));
|
||||||
|
@ -656,10 +685,10 @@ Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) {
|
||||||
ciMethod* callee = kit.callee();
|
ciMethod* callee = kit.callee();
|
||||||
const int bci = kit.bci();
|
const int bci = kit.bci();
|
||||||
|
|
||||||
Node* slow_ctl = kit.try_to_predicate();
|
Node* slow_ctl = kit.try_to_predicate(predicate);
|
||||||
if (!kit.failing()) {
|
if (!kit.failing()) {
|
||||||
if (C->print_intrinsics() || C->print_inlining()) {
|
if (C->print_intrinsics() || C->print_inlining()) {
|
||||||
C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
|
C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual, predicate)" : "(intrinsic, predicate)");
|
||||||
}
|
}
|
||||||
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked);
|
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked);
|
||||||
if (C->log()) {
|
if (C->log()) {
|
||||||
|
@ -688,7 +717,7 @@ Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LibraryCallKit::try_to_inline() {
|
bool LibraryCallKit::try_to_inline(int predicate) {
|
||||||
// Handle symbolic names for otherwise undistinguished boolean switches:
|
// Handle symbolic names for otherwise undistinguished boolean switches:
|
||||||
const bool is_store = true;
|
const bool is_store = true;
|
||||||
const bool is_native_ptr = true;
|
const bool is_native_ptr = true;
|
||||||
|
@ -882,6 +911,14 @@ bool LibraryCallKit::try_to_inline() {
|
||||||
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
||||||
return inline_cipherBlockChaining_AESCrypt(intrinsic_id());
|
return inline_cipherBlockChaining_AESCrypt(intrinsic_id());
|
||||||
|
|
||||||
|
case vmIntrinsics::_sha_implCompress:
|
||||||
|
case vmIntrinsics::_sha2_implCompress:
|
||||||
|
case vmIntrinsics::_sha5_implCompress:
|
||||||
|
return inline_sha_implCompress(intrinsic_id());
|
||||||
|
|
||||||
|
case vmIntrinsics::_digestBase_implCompressMB:
|
||||||
|
return inline_digestBase_implCompressMB(predicate);
|
||||||
|
|
||||||
case vmIntrinsics::_encodeISOArray:
|
case vmIntrinsics::_encodeISOArray:
|
||||||
return inline_encodeISOArray();
|
return inline_encodeISOArray();
|
||||||
|
|
||||||
|
@ -905,7 +942,7 @@ bool LibraryCallKit::try_to_inline() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* LibraryCallKit::try_to_predicate() {
|
Node* LibraryCallKit::try_to_predicate(int predicate) {
|
||||||
if (!jvms()->has_method()) {
|
if (!jvms()->has_method()) {
|
||||||
// Root JVMState has a null method.
|
// Root JVMState has a null method.
|
||||||
assert(map()->memory()->Opcode() == Op_Parm, "");
|
assert(map()->memory()->Opcode() == Op_Parm, "");
|
||||||
|
@ -919,6 +956,8 @@ Node* LibraryCallKit::try_to_predicate() {
|
||||||
return inline_cipherBlockChaining_AESCrypt_predicate(false);
|
return inline_cipherBlockChaining_AESCrypt_predicate(false);
|
||||||
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
||||||
return inline_cipherBlockChaining_AESCrypt_predicate(true);
|
return inline_cipherBlockChaining_AESCrypt_predicate(true);
|
||||||
|
case vmIntrinsics::_digestBase_implCompressMB:
|
||||||
|
return inline_digestBase_implCompressMB_predicate(predicate);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// If you get here, it may be that someone has added a new intrinsic
|
// If you get here, it may be that someone has added a new intrinsic
|
||||||
|
@ -4579,7 +4618,10 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
|
||||||
// It's an instance, and it passed the slow-path tests.
|
// It's an instance, and it passed the slow-path tests.
|
||||||
PreserveJVMState pjvms(this);
|
PreserveJVMState pjvms(this);
|
||||||
Node* obj_size = NULL;
|
Node* obj_size = NULL;
|
||||||
Node* alloc_obj = new_instance(obj_klass, NULL, &obj_size);
|
// Need to deoptimize on exception from allocation since Object.clone intrinsic
|
||||||
|
// is reexecuted if deoptimization occurs and there could be problems when merging
|
||||||
|
// exception state between multiple Object.clone versions (reexecute=true vs reexecute=false).
|
||||||
|
Node* alloc_obj = new_instance(obj_klass, NULL, &obj_size, /*deoptimize_on_exception=*/true);
|
||||||
|
|
||||||
copy_to_clone(obj, alloc_obj, obj_size, false, !use_ReduceInitialCardMarks());
|
copy_to_clone(obj, alloc_obj, obj_size, false, !use_ReduceInitialCardMarks());
|
||||||
|
|
||||||
|
@ -5865,7 +5907,12 @@ Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * field
|
||||||
BasicType bt = field->layout_type();
|
BasicType bt = field->layout_type();
|
||||||
|
|
||||||
// Build the resultant type of the load
|
// Build the resultant type of the load
|
||||||
const Type *type = TypeOopPtr::make_from_klass(field_klass->as_klass());
|
const Type *type;
|
||||||
|
if (bt == T_OBJECT) {
|
||||||
|
type = TypeOopPtr::make_from_klass(field_klass->as_klass());
|
||||||
|
} else {
|
||||||
|
type = Type::get_const_basic_type(bt);
|
||||||
|
}
|
||||||
|
|
||||||
// Build the load.
|
// Build the load.
|
||||||
Node* loadedField = make_load(NULL, adr, type, bt, adr_type, MemNode::unordered, is_vol);
|
Node* loadedField = make_load(NULL, adr, type, bt, adr_type, MemNode::unordered, is_vol);
|
||||||
|
@ -5995,7 +6042,7 @@ bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) {
|
||||||
assert(tinst != NULL, "CBC obj is null");
|
assert(tinst != NULL, "CBC obj is null");
|
||||||
assert(tinst->klass()->is_loaded(), "CBC obj is not loaded");
|
assert(tinst->klass()->is_loaded(), "CBC obj is not loaded");
|
||||||
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
|
||||||
if (!klass_AESCrypt->is_loaded()) return false;
|
assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded");
|
||||||
|
|
||||||
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
|
ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
|
||||||
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt);
|
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt);
|
||||||
|
@ -6070,11 +6117,8 @@ Node * LibraryCallKit::get_original_key_start_from_aescrypt_object(Node *aescryp
|
||||||
// note cipher==plain is more conservative than the original java code but that's OK
|
// note cipher==plain is more conservative than the original java code but that's OK
|
||||||
//
|
//
|
||||||
Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting) {
|
Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting) {
|
||||||
// First, check receiver for NULL since it is virtual method.
|
// The receiver was checked for NULL already.
|
||||||
Node* objCBC = argument(0);
|
Node* objCBC = argument(0);
|
||||||
objCBC = null_check(objCBC);
|
|
||||||
|
|
||||||
if (stopped()) return NULL; // Always NULL
|
|
||||||
|
|
||||||
// Load embeddedCipher field of CipherBlockChaining object.
|
// Load embeddedCipher field of CipherBlockChaining object.
|
||||||
Node* embeddedCipherObj = load_field_from_object(objCBC, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false);
|
Node* embeddedCipherObj = load_field_from_object(objCBC, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false);
|
||||||
|
@ -6121,3 +6165,258 @@ Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypt
|
||||||
record_for_igvn(region);
|
record_for_igvn(region);
|
||||||
return _gvn.transform(region);
|
return _gvn.transform(region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------inline_sha_implCompress-----------------------
|
||||||
|
//
|
||||||
|
// Calculate SHA (i.e., SHA-1) for single-block byte[] array.
|
||||||
|
// void com.sun.security.provider.SHA.implCompress(byte[] buf, int ofs)
|
||||||
|
//
|
||||||
|
// Calculate SHA2 (i.e., SHA-244 or SHA-256) for single-block byte[] array.
|
||||||
|
// void com.sun.security.provider.SHA2.implCompress(byte[] buf, int ofs)
|
||||||
|
//
|
||||||
|
// Calculate SHA5 (i.e., SHA-384 or SHA-512) for single-block byte[] array.
|
||||||
|
// void com.sun.security.provider.SHA5.implCompress(byte[] buf, int ofs)
|
||||||
|
//
|
||||||
|
bool LibraryCallKit::inline_sha_implCompress(vmIntrinsics::ID id) {
|
||||||
|
assert(callee()->signature()->size() == 2, "sha_implCompress has 2 parameters");
|
||||||
|
|
||||||
|
Node* sha_obj = argument(0);
|
||||||
|
Node* src = argument(1); // type oop
|
||||||
|
Node* ofs = argument(2); // type int
|
||||||
|
|
||||||
|
const Type* src_type = src->Value(&_gvn);
|
||||||
|
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||||
|
if (top_src == NULL || top_src->klass() == NULL) {
|
||||||
|
// failed array check
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Figure out the size and type of the elements we will be copying.
|
||||||
|
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||||
|
if (src_elem != T_BYTE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 'src_start' points to src array + offset
|
||||||
|
Node* src_start = array_element_address(src, ofs, src_elem);
|
||||||
|
Node* state = NULL;
|
||||||
|
address stubAddr;
|
||||||
|
const char *stubName;
|
||||||
|
|
||||||
|
switch(id) {
|
||||||
|
case vmIntrinsics::_sha_implCompress:
|
||||||
|
assert(UseSHA1Intrinsics, "need SHA1 instruction support");
|
||||||
|
state = get_state_from_sha_object(sha_obj);
|
||||||
|
stubAddr = StubRoutines::sha1_implCompress();
|
||||||
|
stubName = "sha1_implCompress";
|
||||||
|
break;
|
||||||
|
case vmIntrinsics::_sha2_implCompress:
|
||||||
|
assert(UseSHA256Intrinsics, "need SHA256 instruction support");
|
||||||
|
state = get_state_from_sha_object(sha_obj);
|
||||||
|
stubAddr = StubRoutines::sha256_implCompress();
|
||||||
|
stubName = "sha256_implCompress";
|
||||||
|
break;
|
||||||
|
case vmIntrinsics::_sha5_implCompress:
|
||||||
|
assert(UseSHA512Intrinsics, "need SHA512 instruction support");
|
||||||
|
state = get_state_from_sha5_object(sha_obj);
|
||||||
|
stubAddr = StubRoutines::sha512_implCompress();
|
||||||
|
stubName = "sha512_implCompress";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal_unexpected_iid(id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (state == NULL) return false;
|
||||||
|
|
||||||
|
// Call the stub.
|
||||||
|
Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::sha_implCompress_Type(),
|
||||||
|
stubAddr, stubName, TypePtr::BOTTOM,
|
||||||
|
src_start, state);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------inline_digestBase_implCompressMB-----------------------
|
||||||
|
//
|
||||||
|
// Calculate SHA/SHA2/SHA5 for multi-block byte[] array.
|
||||||
|
// int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit)
|
||||||
|
//
|
||||||
|
bool LibraryCallKit::inline_digestBase_implCompressMB(int predicate) {
|
||||||
|
assert(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics,
|
||||||
|
"need SHA1/SHA256/SHA512 instruction support");
|
||||||
|
assert((uint)predicate < 3, "sanity");
|
||||||
|
assert(callee()->signature()->size() == 3, "digestBase_implCompressMB has 3 parameters");
|
||||||
|
|
||||||
|
Node* digestBase_obj = argument(0); // The receiver was checked for NULL already.
|
||||||
|
Node* src = argument(1); // byte[] array
|
||||||
|
Node* ofs = argument(2); // type int
|
||||||
|
Node* limit = argument(3); // type int
|
||||||
|
|
||||||
|
const Type* src_type = src->Value(&_gvn);
|
||||||
|
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||||
|
if (top_src == NULL || top_src->klass() == NULL) {
|
||||||
|
// failed array check
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Figure out the size and type of the elements we will be copying.
|
||||||
|
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||||
|
if (src_elem != T_BYTE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 'src_start' points to src array + offset
|
||||||
|
Node* src_start = array_element_address(src, ofs, src_elem);
|
||||||
|
|
||||||
|
const char* klass_SHA_name = NULL;
|
||||||
|
const char* stub_name = NULL;
|
||||||
|
address stub_addr = NULL;
|
||||||
|
bool long_state = false;
|
||||||
|
|
||||||
|
switch (predicate) {
|
||||||
|
case 0:
|
||||||
|
if (UseSHA1Intrinsics) {
|
||||||
|
klass_SHA_name = "sun/security/provider/SHA";
|
||||||
|
stub_name = "sha1_implCompressMB";
|
||||||
|
stub_addr = StubRoutines::sha1_implCompressMB();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (UseSHA256Intrinsics) {
|
||||||
|
klass_SHA_name = "sun/security/provider/SHA2";
|
||||||
|
stub_name = "sha256_implCompressMB";
|
||||||
|
stub_addr = StubRoutines::sha256_implCompressMB();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (UseSHA512Intrinsics) {
|
||||||
|
klass_SHA_name = "sun/security/provider/SHA5";
|
||||||
|
stub_name = "sha512_implCompressMB";
|
||||||
|
stub_addr = StubRoutines::sha512_implCompressMB();
|
||||||
|
long_state = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal(err_msg_res("unknown SHA intrinsic predicate: %d", predicate));
|
||||||
|
}
|
||||||
|
if (klass_SHA_name != NULL) {
|
||||||
|
// get DigestBase klass to lookup for SHA klass
|
||||||
|
const TypeInstPtr* tinst = _gvn.type(digestBase_obj)->isa_instptr();
|
||||||
|
assert(tinst != NULL, "digestBase_obj is not instance???");
|
||||||
|
assert(tinst->klass()->is_loaded(), "DigestBase is not loaded");
|
||||||
|
|
||||||
|
ciKlass* klass_SHA = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_SHA_name));
|
||||||
|
assert(klass_SHA->is_loaded(), "predicate checks that this class is loaded");
|
||||||
|
ciInstanceKlass* instklass_SHA = klass_SHA->as_instance_klass();
|
||||||
|
return inline_sha_implCompressMB(digestBase_obj, instklass_SHA, long_state, stub_addr, stub_name, src_start, ofs, limit);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//------------------------------inline_sha_implCompressMB-----------------------
|
||||||
|
bool LibraryCallKit::inline_sha_implCompressMB(Node* digestBase_obj, ciInstanceKlass* instklass_SHA,
|
||||||
|
bool long_state, address stubAddr, const char *stubName,
|
||||||
|
Node* src_start, Node* ofs, Node* limit) {
|
||||||
|
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_SHA);
|
||||||
|
const TypeOopPtr* xtype = aklass->as_instance_type();
|
||||||
|
Node* sha_obj = new CheckCastPPNode(control(), digestBase_obj, xtype);
|
||||||
|
sha_obj = _gvn.transform(sha_obj);
|
||||||
|
|
||||||
|
Node* state;
|
||||||
|
if (long_state) {
|
||||||
|
state = get_state_from_sha5_object(sha_obj);
|
||||||
|
} else {
|
||||||
|
state = get_state_from_sha_object(sha_obj);
|
||||||
|
}
|
||||||
|
if (state == NULL) return false;
|
||||||
|
|
||||||
|
// Call the stub.
|
||||||
|
Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
|
||||||
|
OptoRuntime::digestBase_implCompressMB_Type(),
|
||||||
|
stubAddr, stubName, TypePtr::BOTTOM,
|
||||||
|
src_start, state, ofs, limit);
|
||||||
|
// return ofs (int)
|
||||||
|
Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
|
||||||
|
set_result(result);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------get_state_from_sha_object-----------------------
|
||||||
|
Node * LibraryCallKit::get_state_from_sha_object(Node *sha_object) {
|
||||||
|
Node* sha_state = load_field_from_object(sha_object, "state", "[I", /*is_exact*/ false);
|
||||||
|
assert (sha_state != NULL, "wrong version of sun.security.provider.SHA/SHA2");
|
||||||
|
if (sha_state == NULL) return (Node *) NULL;
|
||||||
|
|
||||||
|
// now have the array, need to get the start address of the state array
|
||||||
|
Node* state = array_element_address(sha_state, intcon(0), T_INT);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------get_state_from_sha5_object-----------------------
|
||||||
|
Node * LibraryCallKit::get_state_from_sha5_object(Node *sha_object) {
|
||||||
|
Node* sha_state = load_field_from_object(sha_object, "state", "[J", /*is_exact*/ false);
|
||||||
|
assert (sha_state != NULL, "wrong version of sun.security.provider.SHA5");
|
||||||
|
if (sha_state == NULL) return (Node *) NULL;
|
||||||
|
|
||||||
|
// now have the array, need to get the start address of the state array
|
||||||
|
Node* state = array_element_address(sha_state, intcon(0), T_LONG);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------inline_digestBase_implCompressMB_predicate----------------------------
|
||||||
|
// Return node representing slow path of predicate check.
|
||||||
|
// the pseudo code we want to emulate with this predicate is:
|
||||||
|
// if (digestBaseObj instanceof SHA/SHA2/SHA5) do_intrinsic, else do_javapath
|
||||||
|
//
|
||||||
|
Node* LibraryCallKit::inline_digestBase_implCompressMB_predicate(int predicate) {
|
||||||
|
assert(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics,
|
||||||
|
"need SHA1/SHA256/SHA512 instruction support");
|
||||||
|
assert((uint)predicate < 3, "sanity");
|
||||||
|
|
||||||
|
// The receiver was checked for NULL already.
|
||||||
|
Node* digestBaseObj = argument(0);
|
||||||
|
|
||||||
|
// get DigestBase klass for instanceOf check
|
||||||
|
const TypeInstPtr* tinst = _gvn.type(digestBaseObj)->isa_instptr();
|
||||||
|
assert(tinst != NULL, "digestBaseObj is null");
|
||||||
|
assert(tinst->klass()->is_loaded(), "DigestBase is not loaded");
|
||||||
|
|
||||||
|
const char* klass_SHA_name = NULL;
|
||||||
|
switch (predicate) {
|
||||||
|
case 0:
|
||||||
|
if (UseSHA1Intrinsics) {
|
||||||
|
// we want to do an instanceof comparison against the SHA class
|
||||||
|
klass_SHA_name = "sun/security/provider/SHA";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (UseSHA256Intrinsics) {
|
||||||
|
// we want to do an instanceof comparison against the SHA2 class
|
||||||
|
klass_SHA_name = "sun/security/provider/SHA2";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (UseSHA512Intrinsics) {
|
||||||
|
// we want to do an instanceof comparison against the SHA5 class
|
||||||
|
klass_SHA_name = "sun/security/provider/SHA5";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal(err_msg_res("unknown SHA intrinsic predicate: %d", predicate));
|
||||||
|
}
|
||||||
|
|
||||||
|
ciKlass* klass_SHA = NULL;
|
||||||
|
if (klass_SHA_name != NULL) {
|
||||||
|
klass_SHA = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_SHA_name));
|
||||||
|
}
|
||||||
|
if ((klass_SHA == NULL) || !klass_SHA->is_loaded()) {
|
||||||
|
// if none of SHA/SHA2/SHA5 is loaded, we never take the intrinsic fast path
|
||||||
|
Node* ctrl = control();
|
||||||
|
set_control(top()); // no intrinsic path
|
||||||
|
return ctrl;
|
||||||
|
}
|
||||||
|
ciInstanceKlass* instklass_SHA = klass_SHA->as_instance_klass();
|
||||||
|
|
||||||
|
Node* instofSHA = gen_instanceof(digestBaseObj, makecon(TypeKlassPtr::make(instklass_SHA)));
|
||||||
|
Node* cmp_instof = _gvn.transform(new CmpINode(instofSHA, intcon(1)));
|
||||||
|
Node* bool_instof = _gvn.transform(new BoolNode(cmp_instof, BoolTest::ne));
|
||||||
|
Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN);
|
||||||
|
|
||||||
|
return instof_false; // even if it is NULL
|
||||||
|
}
|
||||||
|
|
|
@ -2771,11 +2771,11 @@ void PhaseIdealLoop::reorg_offsets(IdealLoopTree *loop) {
|
||||||
// Hit! Refactor use to use the post-incremented tripcounter.
|
// Hit! Refactor use to use the post-incremented tripcounter.
|
||||||
// Compute a post-increment tripcounter.
|
// Compute a post-increment tripcounter.
|
||||||
Node *opaq = new Opaque2Node( C, cle->incr() );
|
Node *opaq = new Opaque2Node( C, cle->incr() );
|
||||||
register_new_node( opaq, u_ctrl );
|
register_new_node(opaq, exit);
|
||||||
Node *neg_stride = _igvn.intcon(-cle->stride_con());
|
Node *neg_stride = _igvn.intcon(-cle->stride_con());
|
||||||
set_ctrl(neg_stride, C->root());
|
set_ctrl(neg_stride, C->root());
|
||||||
Node *post = new AddINode( opaq, neg_stride);
|
Node *post = new AddINode( opaq, neg_stride);
|
||||||
register_new_node( post, u_ctrl );
|
register_new_node(post, exit);
|
||||||
_igvn.rehash_node_delayed(use);
|
_igvn.rehash_node_delayed(use);
|
||||||
for (uint j = 1; j < use->req(); j++) {
|
for (uint j = 1; j < use->req(); j++) {
|
||||||
if (use->in(j) == phi)
|
if (use->in(j) == phi)
|
||||||
|
|
|
@ -514,6 +514,9 @@ Node *Node::clone() const {
|
||||||
if (n->is_Call()) {
|
if (n->is_Call()) {
|
||||||
n->as_Call()->clone_jvms(C);
|
n->as_Call()->clone_jvms(C);
|
||||||
}
|
}
|
||||||
|
if (n->is_SafePoint()) {
|
||||||
|
n->as_SafePoint()->clone_replaced_nodes();
|
||||||
|
}
|
||||||
return n; // Return the clone
|
return n; // Return the clone
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -609,6 +612,9 @@ void Node::destruct() {
|
||||||
if (is_expensive()) {
|
if (is_expensive()) {
|
||||||
compile->remove_expensive_node(this);
|
compile->remove_expensive_node(this);
|
||||||
}
|
}
|
||||||
|
if (is_SafePoint()) {
|
||||||
|
as_SafePoint()->delete_replaced_nodes();
|
||||||
|
}
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
// We will not actually delete the storage, but we'll make the node unusable.
|
// We will not actually delete the storage, but we'll make the node unusable.
|
||||||
*(address*)this = badAddress; // smash the C++ vtbl, probably
|
*(address*)this = badAddress; // smash the C++ vtbl, probably
|
||||||
|
|
|
@ -359,12 +359,13 @@ class Parse : public GraphKit {
|
||||||
int _est_switch_depth; // Debugging SwitchRanges.
|
int _est_switch_depth; // Debugging SwitchRanges.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// parser for the caller of the method of this object
|
bool _first_return; // true if return is the first to be parsed
|
||||||
Parse* const _parent;
|
bool _replaced_nodes_for_exceptions; // needs processing of replaced nodes in exception paths?
|
||||||
|
uint _new_idx; // any node with _idx above were new during this parsing. Used to trim the replaced nodes list.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Parse* parent);
|
Parse(JVMState* caller, ciMethod* parse_method, float expected_uses);
|
||||||
|
|
||||||
virtual Parse* is_Parse() const { return (Parse*)this; }
|
virtual Parse* is_Parse() const { return (Parse*)this; }
|
||||||
|
|
||||||
|
@ -425,8 +426,6 @@ class Parse : public GraphKit {
|
||||||
return block()->successor_for_bci(bci);
|
return block()->successor_for_bci(bci);
|
||||||
}
|
}
|
||||||
|
|
||||||
Parse* parent_parser() const { return _parent; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Create a JVMS & map for the initial state of this method.
|
// Create a JVMS & map for the initial state of this method.
|
||||||
SafePointNode* create_entry_map();
|
SafePointNode* create_entry_map();
|
||||||
|
|
|
@ -383,8 +383,8 @@ void Parse::load_interpreter_state(Node* osr_buf) {
|
||||||
|
|
||||||
//------------------------------Parse------------------------------------------
|
//------------------------------Parse------------------------------------------
|
||||||
// Main parser constructor.
|
// Main parser constructor.
|
||||||
Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Parse* parent)
|
Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
|
||||||
: _exits(caller), _parent(parent)
|
: _exits(caller)
|
||||||
{
|
{
|
||||||
// Init some variables
|
// Init some variables
|
||||||
_caller = caller;
|
_caller = caller;
|
||||||
|
@ -399,6 +399,9 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Pars
|
||||||
_entry_bci = InvocationEntryBci;
|
_entry_bci = InvocationEntryBci;
|
||||||
_tf = NULL;
|
_tf = NULL;
|
||||||
_block = NULL;
|
_block = NULL;
|
||||||
|
_first_return = true;
|
||||||
|
_replaced_nodes_for_exceptions = false;
|
||||||
|
_new_idx = C->unique();
|
||||||
debug_only(_block_count = -1);
|
debug_only(_block_count = -1);
|
||||||
debug_only(_blocks = (Block*)-1);
|
debug_only(_blocks = (Block*)-1);
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -901,6 +904,10 @@ void Parse::throw_to_exit(SafePointNode* ex_map) {
|
||||||
for (uint i = 0; i < TypeFunc::Parms; i++) {
|
for (uint i = 0; i < TypeFunc::Parms; i++) {
|
||||||
caller.map()->set_req(i, ex_map->in(i));
|
caller.map()->set_req(i, ex_map->in(i));
|
||||||
}
|
}
|
||||||
|
if (ex_map->has_replaced_nodes()) {
|
||||||
|
_replaced_nodes_for_exceptions = true;
|
||||||
|
}
|
||||||
|
caller.map()->transfer_replaced_nodes_from(ex_map, _new_idx);
|
||||||
// ...and the exception:
|
// ...and the exception:
|
||||||
Node* ex_oop = saved_ex_oop(ex_map);
|
Node* ex_oop = saved_ex_oop(ex_map);
|
||||||
SafePointNode* caller_ex_map = caller.make_exception_state(ex_oop);
|
SafePointNode* caller_ex_map = caller.make_exception_state(ex_oop);
|
||||||
|
@ -991,7 +998,7 @@ void Parse::do_exits() {
|
||||||
bool do_synch = method()->is_synchronized() && GenerateSynchronizationCode;
|
bool do_synch = method()->is_synchronized() && GenerateSynchronizationCode;
|
||||||
|
|
||||||
// record exit from a method if compiled while Dtrace is turned on.
|
// record exit from a method if compiled while Dtrace is turned on.
|
||||||
if (do_synch || C->env()->dtrace_method_probes()) {
|
if (do_synch || C->env()->dtrace_method_probes() || _replaced_nodes_for_exceptions) {
|
||||||
// First move the exception list out of _exits:
|
// First move the exception list out of _exits:
|
||||||
GraphKit kit(_exits.transfer_exceptions_into_jvms());
|
GraphKit kit(_exits.transfer_exceptions_into_jvms());
|
||||||
SafePointNode* normal_map = kit.map(); // keep this guy safe
|
SafePointNode* normal_map = kit.map(); // keep this guy safe
|
||||||
|
@ -1016,6 +1023,9 @@ void Parse::do_exits() {
|
||||||
if (C->env()->dtrace_method_probes()) {
|
if (C->env()->dtrace_method_probes()) {
|
||||||
kit.make_dtrace_method_exit(method());
|
kit.make_dtrace_method_exit(method());
|
||||||
}
|
}
|
||||||
|
if (_replaced_nodes_for_exceptions) {
|
||||||
|
kit.map()->apply_replaced_nodes();
|
||||||
|
}
|
||||||
// Done with exception-path processing.
|
// Done with exception-path processing.
|
||||||
ex_map = kit.make_exception_state(ex_oop);
|
ex_map = kit.make_exception_state(ex_oop);
|
||||||
assert(ex_jvms->same_calls_as(ex_map->jvms()), "sanity");
|
assert(ex_jvms->same_calls_as(ex_map->jvms()), "sanity");
|
||||||
|
@ -1035,6 +1045,7 @@ void Parse::do_exits() {
|
||||||
_exits.add_exception_state(ex_map);
|
_exits.add_exception_state(ex_map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_exits.map()->apply_replaced_nodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------create_entry_map-------------------------------
|
//-----------------------------create_entry_map-------------------------------
|
||||||
|
@ -1049,6 +1060,9 @@ SafePointNode* Parse::create_entry_map() {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear current replaced nodes that are of no use from here on (map was cloned in build_exits).
|
||||||
|
_caller->map()->delete_replaced_nodes();
|
||||||
|
|
||||||
// If this is an inlined method, we may have to do a receiver null check.
|
// If this is an inlined method, we may have to do a receiver null check.
|
||||||
if (_caller->has_method() && is_normal_parse() && !method()->is_static()) {
|
if (_caller->has_method() && is_normal_parse() && !method()->is_static()) {
|
||||||
GraphKit kit(_caller);
|
GraphKit kit(_caller);
|
||||||
|
@ -1072,6 +1086,8 @@ SafePointNode* Parse::create_entry_map() {
|
||||||
|
|
||||||
SafePointNode* inmap = _caller->map();
|
SafePointNode* inmap = _caller->map();
|
||||||
assert(inmap != NULL, "must have inmap");
|
assert(inmap != NULL, "must have inmap");
|
||||||
|
// In case of null check on receiver above
|
||||||
|
map()->transfer_replaced_nodes_from(inmap, _new_idx);
|
||||||
|
|
||||||
uint i;
|
uint i;
|
||||||
|
|
||||||
|
@ -1701,6 +1717,8 @@ void Parse::merge_common(Parse::Block* target, int pnum) {
|
||||||
set_control(r->nonnull_req());
|
set_control(r->nonnull_req());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map()->merge_replaced_nodes_with(newin);
|
||||||
|
|
||||||
// newin has been subsumed into the lazy merge, and is now dead.
|
// newin has been subsumed into the lazy merge, and is now dead.
|
||||||
set_block(save_block);
|
set_block(save_block);
|
||||||
|
|
||||||
|
@ -2130,6 +2148,13 @@ void Parse::return_current(Node* value) {
|
||||||
phi->add_req(value);
|
phi->add_req(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_first_return) {
|
||||||
|
_exits.map()->transfer_replaced_nodes_from(map(), _new_idx);
|
||||||
|
_first_return = false;
|
||||||
|
} else {
|
||||||
|
_exits.map()->merge_replaced_nodes_with(map());
|
||||||
|
}
|
||||||
|
|
||||||
stop_and_kill_map(); // This CFG path dies here
|
stop_and_kill_map(); // This CFG path dies here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
219
hotspot/src/share/vm/opto/replacednodes.cpp
Normal file
219
hotspot/src/share/vm/opto/replacednodes.cpp
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "opto/cfgnode.hpp"
|
||||||
|
#include "opto/phaseX.hpp"
|
||||||
|
#include "opto/replacednodes.hpp"
|
||||||
|
|
||||||
|
void ReplacedNodes::allocate_if_necessary() {
|
||||||
|
if (_replaced_nodes == NULL) {
|
||||||
|
_replaced_nodes = new GrowableArray<ReplacedNode>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReplacedNodes::is_empty() const {
|
||||||
|
return _replaced_nodes == NULL || _replaced_nodes->length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReplacedNodes::has_node(const ReplacedNode& r) const {
|
||||||
|
return _replaced_nodes->find(r) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReplacedNodes::has_target_node(Node* n) const {
|
||||||
|
for (int i = 0; i < _replaced_nodes->length(); i++) {
|
||||||
|
if (_replaced_nodes->at(i).improved() == n) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record replaced node if not seen before
|
||||||
|
void ReplacedNodes::record(Node* initial, Node* improved) {
|
||||||
|
allocate_if_necessary();
|
||||||
|
ReplacedNode r(initial, improved);
|
||||||
|
if (!has_node(r)) {
|
||||||
|
_replaced_nodes->push(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy replaced nodes from one map to another. idx is used to
|
||||||
|
// identify nodes that are too new to be of interest in the target
|
||||||
|
// node list.
|
||||||
|
void ReplacedNodes::transfer_from(const ReplacedNodes& other, uint idx) {
|
||||||
|
if (other.is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
allocate_if_necessary();
|
||||||
|
for (int i = 0; i < other._replaced_nodes->length(); i++) {
|
||||||
|
ReplacedNode replaced = other._replaced_nodes->at(i);
|
||||||
|
// Only transfer the nodes that can actually be useful
|
||||||
|
if (!has_node(replaced) && (replaced.initial()->_idx < idx || has_target_node(replaced.initial()))) {
|
||||||
|
_replaced_nodes->push(replaced);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplacedNodes::clone() {
|
||||||
|
if (_replaced_nodes != NULL) {
|
||||||
|
GrowableArray<ReplacedNode>* replaced_nodes_clone = new GrowableArray<ReplacedNode>();
|
||||||
|
replaced_nodes_clone->appendAll(_replaced_nodes);
|
||||||
|
_replaced_nodes = replaced_nodes_clone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplacedNodes::reset() {
|
||||||
|
if (_replaced_nodes != NULL) {
|
||||||
|
_replaced_nodes->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perfom node replacement (used when returning to caller)
|
||||||
|
void ReplacedNodes::apply(Node* n) {
|
||||||
|
if (is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < _replaced_nodes->length(); i++) {
|
||||||
|
ReplacedNode replaced = _replaced_nodes->at(i);
|
||||||
|
n->replace_edge(replaced.initial(), replaced.improved());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void enqueue_use(Node* n, Node* use, Unique_Node_List& work) {
|
||||||
|
if (use->is_Phi()) {
|
||||||
|
Node* r = use->in(0);
|
||||||
|
assert(r->is_Region(), "Phi should have Region");
|
||||||
|
for (uint i = 1; i < use->req(); i++) {
|
||||||
|
if (use->in(i) == n) {
|
||||||
|
work.push(r->in(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
work.push(use);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perfom node replacement following late inlining
|
||||||
|
void ReplacedNodes::apply(Compile* C, Node* ctl) {
|
||||||
|
// ctl is the control on exit of the method that was late inlined
|
||||||
|
if (is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < _replaced_nodes->length(); i++) {
|
||||||
|
ReplacedNode replaced = _replaced_nodes->at(i);
|
||||||
|
Node* initial = replaced.initial();
|
||||||
|
Node* improved = replaced.improved();
|
||||||
|
assert (ctl != NULL && !ctl->is_top(), "replaced node should have actual control");
|
||||||
|
|
||||||
|
ResourceMark rm;
|
||||||
|
Unique_Node_List work;
|
||||||
|
// Go over all the uses of the node that is considered for replacement...
|
||||||
|
for (DUIterator j = initial->outs(); initial->has_out(j); j++) {
|
||||||
|
Node* use = initial->out(j);
|
||||||
|
|
||||||
|
if (use == improved || use->outcnt() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
work.clear();
|
||||||
|
enqueue_use(initial, use, work);
|
||||||
|
bool replace = true;
|
||||||
|
// Check that this use is dominated by ctl. Go ahead with the
|
||||||
|
// replacement if it is.
|
||||||
|
while (work.size() != 0 && replace) {
|
||||||
|
Node* n = work.pop();
|
||||||
|
if (use->outcnt() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (n->is_CFG() || (n->in(0) != NULL && !n->in(0)->is_top())) {
|
||||||
|
int depth = 0;
|
||||||
|
Node *m = n;
|
||||||
|
if (!n->is_CFG()) {
|
||||||
|
n = n->in(0);
|
||||||
|
}
|
||||||
|
assert(n->is_CFG(), "should be CFG now");
|
||||||
|
while(n != ctl) {
|
||||||
|
n = IfNode::up_one_dom(n);
|
||||||
|
depth++;
|
||||||
|
// limit search depth
|
||||||
|
if (depth >= 100 || n == NULL) {
|
||||||
|
replace = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (DUIterator k = n->outs(); n->has_out(k); k++) {
|
||||||
|
enqueue_use(n, n->out(k), work);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (replace) {
|
||||||
|
bool is_in_table = C->initial_gvn()->hash_delete(use);
|
||||||
|
int replaced = use->replace_edge(initial, improved);
|
||||||
|
if (is_in_table) {
|
||||||
|
C->initial_gvn()->hash_find_insert(use);
|
||||||
|
}
|
||||||
|
C->record_for_igvn(use);
|
||||||
|
|
||||||
|
assert(replaced > 0, "inconsistent");
|
||||||
|
--j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReplacedNodes::dump(outputStream *st) const {
|
||||||
|
if (!is_empty()) {
|
||||||
|
tty->print("replaced nodes: ");
|
||||||
|
for (int i = 0; i < _replaced_nodes->length(); i++) {
|
||||||
|
tty->print("%d->%d", _replaced_nodes->at(i).initial()->_idx, _replaced_nodes->at(i).improved()->_idx);
|
||||||
|
if (i < _replaced_nodes->length()-1) {
|
||||||
|
tty->print(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge 2 list of replaced node at a point where control flow paths merge
|
||||||
|
void ReplacedNodes::merge_with(const ReplacedNodes& other) {
|
||||||
|
if (is_empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (other.is_empty()) {
|
||||||
|
reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int shift = 0;
|
||||||
|
int len = _replaced_nodes->length();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
if (!other.has_node(_replaced_nodes->at(i))) {
|
||||||
|
shift++;
|
||||||
|
} else if (shift > 0) {
|
||||||
|
_replaced_nodes->at_put(i-shift, _replaced_nodes->at(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shift > 0) {
|
||||||
|
_replaced_nodes->trunc_to(len - shift);
|
||||||
|
}
|
||||||
|
}
|
81
hotspot/src/share/vm/opto/replacednodes.hpp
Normal file
81
hotspot/src/share/vm/opto/replacednodes.hpp
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARE_VM_OPTO_REPLACEDNODES_HPP
|
||||||
|
#define SHARE_VM_OPTO_REPLACEDNODES_HPP
|
||||||
|
|
||||||
|
#include "opto/connode.hpp"
|
||||||
|
|
||||||
|
// During parsing, when a node is "improved",
|
||||||
|
// GraphKit::replace_in_map() is called to update the current map so
|
||||||
|
// that the improved node is used from that point
|
||||||
|
// on. GraphKit::replace_in_map() doesn't operate on the callers maps
|
||||||
|
// and so some optimization opportunities may be lost. The
|
||||||
|
// ReplacedNodes class addresses that problem.
|
||||||
|
//
|
||||||
|
// A ReplacedNodes object is a list of pair of nodes. Every
|
||||||
|
// SafePointNode carries a ReplacedNodes object. Every time
|
||||||
|
// GraphKit::replace_in_map() is called, a new pair of nodes is pushed
|
||||||
|
// on the list of replaced nodes. When control flow paths merge, their
|
||||||
|
// replaced nodes are also merged. When parsing exits a method to
|
||||||
|
// return to a caller, the replaced nodes on the exit path are used to
|
||||||
|
// update the caller's map.
|
||||||
|
class ReplacedNodes VALUE_OBJ_CLASS_SPEC {
|
||||||
|
private:
|
||||||
|
class ReplacedNode VALUE_OBJ_CLASS_SPEC {
|
||||||
|
private:
|
||||||
|
Node* _initial;
|
||||||
|
Node* _improved;
|
||||||
|
public:
|
||||||
|
ReplacedNode() : _initial(NULL), _improved(NULL) {}
|
||||||
|
ReplacedNode(Node* initial, Node* improved) : _initial(initial), _improved(improved) {}
|
||||||
|
Node* initial() const { return _initial; }
|
||||||
|
Node* improved() const { return _improved; }
|
||||||
|
|
||||||
|
bool operator==(const ReplacedNode& other) {
|
||||||
|
return _initial == other._initial && _improved == other._improved;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
GrowableArray<ReplacedNode>* _replaced_nodes;
|
||||||
|
|
||||||
|
void allocate_if_necessary();
|
||||||
|
bool has_node(const ReplacedNode& r) const;
|
||||||
|
bool has_target_node(Node* n) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ReplacedNodes()
|
||||||
|
: _replaced_nodes(NULL) {}
|
||||||
|
|
||||||
|
void clone();
|
||||||
|
void record(Node* initial, Node* improved);
|
||||||
|
void transfer_from(const ReplacedNodes& other, uint idx);
|
||||||
|
void reset();
|
||||||
|
void apply(Node* n);
|
||||||
|
void merge_with(const ReplacedNodes& other);
|
||||||
|
bool is_empty() const;
|
||||||
|
void dump(outputStream *st) const;
|
||||||
|
void apply(Compile* C, Node* ctl);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHARE_VM_OPTO_REPLACEDNODES_HPP
|
|
@ -896,6 +896,50 @@ const TypeFunc* OptoRuntime::cipherBlockChaining_aescrypt_Type() {
|
||||||
return TypeFunc::make(domain, range);
|
return TypeFunc::make(domain, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void implCompress(byte[] buf, int ofs)
|
||||||
|
*/
|
||||||
|
const TypeFunc* OptoRuntime::sha_implCompress_Type() {
|
||||||
|
// create input type (domain)
|
||||||
|
int num_args = 2;
|
||||||
|
int argcnt = num_args;
|
||||||
|
const Type** fields = TypeTuple::fields(argcnt);
|
||||||
|
int argp = TypeFunc::Parms;
|
||||||
|
fields[argp++] = TypePtr::NOTNULL; // buf
|
||||||
|
fields[argp++] = TypePtr::NOTNULL; // state
|
||||||
|
assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
|
||||||
|
const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
|
||||||
|
|
||||||
|
// no result type needed
|
||||||
|
fields = TypeTuple::fields(1);
|
||||||
|
fields[TypeFunc::Parms+0] = NULL; // void
|
||||||
|
const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields);
|
||||||
|
return TypeFunc::make(domain, range);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* int implCompressMultiBlock(byte[] b, int ofs, int limit)
|
||||||
|
*/
|
||||||
|
const TypeFunc* OptoRuntime::digestBase_implCompressMB_Type() {
|
||||||
|
// create input type (domain)
|
||||||
|
int num_args = 4;
|
||||||
|
int argcnt = num_args;
|
||||||
|
const Type** fields = TypeTuple::fields(argcnt);
|
||||||
|
int argp = TypeFunc::Parms;
|
||||||
|
fields[argp++] = TypePtr::NOTNULL; // buf
|
||||||
|
fields[argp++] = TypePtr::NOTNULL; // state
|
||||||
|
fields[argp++] = TypeInt::INT; // ofs
|
||||||
|
fields[argp++] = TypeInt::INT; // limit
|
||||||
|
assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
|
||||||
|
const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
|
||||||
|
|
||||||
|
// returning ofs (int)
|
||||||
|
fields = TypeTuple::fields(1);
|
||||||
|
fields[TypeFunc::Parms+0] = TypeInt::INT; // ofs
|
||||||
|
const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields);
|
||||||
|
return TypeFunc::make(domain, range);
|
||||||
|
}
|
||||||
|
|
||||||
//------------- Interpreter state access for on stack replacement
|
//------------- Interpreter state access for on stack replacement
|
||||||
const TypeFunc* OptoRuntime::osr_end_Type() {
|
const TypeFunc* OptoRuntime::osr_end_Type() {
|
||||||
// create input type (domain)
|
// create input type (domain)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -300,6 +300,9 @@ private:
|
||||||
static const TypeFunc* aescrypt_block_Type();
|
static const TypeFunc* aescrypt_block_Type();
|
||||||
static const TypeFunc* cipherBlockChaining_aescrypt_Type();
|
static const TypeFunc* cipherBlockChaining_aescrypt_Type();
|
||||||
|
|
||||||
|
static const TypeFunc* sha_implCompress_Type();
|
||||||
|
static const TypeFunc* digestBase_implCompressMB_Type();
|
||||||
|
|
||||||
static const TypeFunc* updateBytesCRC32_Type();
|
static const TypeFunc* updateBytesCRC32_Type();
|
||||||
|
|
||||||
// leaf on stack replacement interpreter accessor types
|
// leaf on stack replacement interpreter accessor types
|
||||||
|
|
|
@ -3838,10 +3838,6 @@ jint Arguments::apply_ergo() {
|
||||||
// nothing to use the profiling, turn if off
|
// nothing to use the profiling, turn if off
|
||||||
FLAG_SET_DEFAULT(TypeProfileLevel, 0);
|
FLAG_SET_DEFAULT(TypeProfileLevel, 0);
|
||||||
}
|
}
|
||||||
if (UseTypeSpeculation && FLAG_IS_DEFAULT(ReplaceInParentMaps)) {
|
|
||||||
// Doing the replace in parent maps helps speculation
|
|
||||||
FLAG_SET_DEFAULT(ReplaceInParentMaps, true);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (PrintAssembly && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
|
if (PrintAssembly && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
|
||||||
|
|
|
@ -599,6 +599,9 @@ class CommandLineFlags {
|
||||||
product(bool, UseAES, false, \
|
product(bool, UseAES, false, \
|
||||||
"Control whether AES instructions can be used on x86/x64") \
|
"Control whether AES instructions can be used on x86/x64") \
|
||||||
\
|
\
|
||||||
|
product(bool, UseSHA, false, \
|
||||||
|
"Control whether SHA instructions can be used on SPARC") \
|
||||||
|
\
|
||||||
product(uintx, LargePageSizeInBytes, 0, \
|
product(uintx, LargePageSizeInBytes, 0, \
|
||||||
"Large page size (0 to let VM choose the page size)") \
|
"Large page size (0 to let VM choose the page size)") \
|
||||||
\
|
\
|
||||||
|
@ -705,6 +708,15 @@ class CommandLineFlags {
|
||||||
product(bool, UseAESIntrinsics, false, \
|
product(bool, UseAESIntrinsics, false, \
|
||||||
"Use intrinsics for AES versions of crypto") \
|
"Use intrinsics for AES versions of crypto") \
|
||||||
\
|
\
|
||||||
|
product(bool, UseSHA1Intrinsics, false, \
|
||||||
|
"Use intrinsics for SHA-1 crypto hash function") \
|
||||||
|
\
|
||||||
|
product(bool, UseSHA256Intrinsics, false, \
|
||||||
|
"Use intrinsics for SHA-224 and SHA-256 crypto hash functions") \
|
||||||
|
\
|
||||||
|
product(bool, UseSHA512Intrinsics, false, \
|
||||||
|
"Use intrinsics for SHA-384 and SHA-512 crypto hash functions") \
|
||||||
|
\
|
||||||
product(bool, UseCRC32Intrinsics, false, \
|
product(bool, UseCRC32Intrinsics, false, \
|
||||||
"use intrinsics for java.util.zip.CRC32") \
|
"use intrinsics for java.util.zip.CRC32") \
|
||||||
\
|
\
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -125,6 +125,13 @@ address StubRoutines::_aescrypt_decryptBlock = NULL;
|
||||||
address StubRoutines::_cipherBlockChaining_encryptAESCrypt = NULL;
|
address StubRoutines::_cipherBlockChaining_encryptAESCrypt = NULL;
|
||||||
address StubRoutines::_cipherBlockChaining_decryptAESCrypt = NULL;
|
address StubRoutines::_cipherBlockChaining_decryptAESCrypt = NULL;
|
||||||
|
|
||||||
|
address StubRoutines::_sha1_implCompress = NULL;
|
||||||
|
address StubRoutines::_sha1_implCompressMB = NULL;
|
||||||
|
address StubRoutines::_sha256_implCompress = NULL;
|
||||||
|
address StubRoutines::_sha256_implCompressMB = NULL;
|
||||||
|
address StubRoutines::_sha512_implCompress = NULL;
|
||||||
|
address StubRoutines::_sha512_implCompressMB = NULL;
|
||||||
|
|
||||||
address StubRoutines::_updateBytesCRC32 = NULL;
|
address StubRoutines::_updateBytesCRC32 = NULL;
|
||||||
address StubRoutines::_crc_table_adr = NULL;
|
address StubRoutines::_crc_table_adr = NULL;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -207,6 +207,13 @@ class StubRoutines: AllStatic {
|
||||||
static address _cipherBlockChaining_encryptAESCrypt;
|
static address _cipherBlockChaining_encryptAESCrypt;
|
||||||
static address _cipherBlockChaining_decryptAESCrypt;
|
static address _cipherBlockChaining_decryptAESCrypt;
|
||||||
|
|
||||||
|
static address _sha1_implCompress;
|
||||||
|
static address _sha1_implCompressMB;
|
||||||
|
static address _sha256_implCompress;
|
||||||
|
static address _sha256_implCompressMB;
|
||||||
|
static address _sha512_implCompress;
|
||||||
|
static address _sha512_implCompressMB;
|
||||||
|
|
||||||
static address _updateBytesCRC32;
|
static address _updateBytesCRC32;
|
||||||
static address _crc_table_adr;
|
static address _crc_table_adr;
|
||||||
|
|
||||||
|
@ -356,6 +363,13 @@ class StubRoutines: AllStatic {
|
||||||
static address cipherBlockChaining_encryptAESCrypt() { return _cipherBlockChaining_encryptAESCrypt; }
|
static address cipherBlockChaining_encryptAESCrypt() { return _cipherBlockChaining_encryptAESCrypt; }
|
||||||
static address cipherBlockChaining_decryptAESCrypt() { return _cipherBlockChaining_decryptAESCrypt; }
|
static address cipherBlockChaining_decryptAESCrypt() { return _cipherBlockChaining_decryptAESCrypt; }
|
||||||
|
|
||||||
|
static address sha1_implCompress() { return _sha1_implCompress; }
|
||||||
|
static address sha1_implCompressMB() { return _sha1_implCompressMB; }
|
||||||
|
static address sha256_implCompress() { return _sha256_implCompress; }
|
||||||
|
static address sha256_implCompressMB() { return _sha256_implCompressMB; }
|
||||||
|
static address sha512_implCompress() { return _sha512_implCompress; }
|
||||||
|
static address sha512_implCompressMB() { return _sha512_implCompressMB; }
|
||||||
|
|
||||||
static address updateBytesCRC32() { return _updateBytesCRC32; }
|
static address updateBytesCRC32() { return _updateBytesCRC32; }
|
||||||
static address crc_table_addr() { return _crc_table_adr; }
|
static address crc_table_addr() { return _crc_table_adr; }
|
||||||
|
|
||||||
|
|
|
@ -349,6 +349,7 @@ template<class E> class GrowableArray : public GenericGrowableArray {
|
||||||
|
|
||||||
// inserts the given element before the element at index i
|
// inserts the given element before the element at index i
|
||||||
void insert_before(const int idx, const E& elem) {
|
void insert_before(const int idx, const E& elem) {
|
||||||
|
assert(0 <= idx && idx <= _len, "illegal index");
|
||||||
check_nesting();
|
check_nesting();
|
||||||
if (_len == _max) grow(_len);
|
if (_len == _max) grow(_len);
|
||||||
for (int j = _len - 1; j >= idx; j--) {
|
for (int j = _len - 1; j >= idx; j--) {
|
||||||
|
@ -360,7 +361,7 @@ template<class E> class GrowableArray : public GenericGrowableArray {
|
||||||
|
|
||||||
void appendAll(const GrowableArray<E>* l) {
|
void appendAll(const GrowableArray<E>* l) {
|
||||||
for (int i = 0; i < l->_len; i++) {
|
for (int i = 0; i < l->_len; i++) {
|
||||||
raw_at_put_grow(_len, l->_data[i], 0);
|
raw_at_put_grow(_len, l->_data[i], E());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
80
hotspot/test/compiler/intrinsics/clone/TestObjectClone.java
Normal file
80
hotspot/test/compiler/intrinsics/clone/TestObjectClone.java
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8033626
|
||||||
|
* @summary assert(ex_map->jvms()->same_calls_as(_exceptions->jvms())) failed: all collected exceptions must come from the same place
|
||||||
|
* @library /testlibrary
|
||||||
|
* @run main/othervm -XX:-TieredCompilation -Xbatch -XX:CompileOnly=TestObjectClone::f TestObjectClone
|
||||||
|
*/
|
||||||
|
import com.oracle.java.testlibrary.Asserts;
|
||||||
|
|
||||||
|
public class TestObjectClone implements Cloneable {
|
||||||
|
static class A extends TestObjectClone {}
|
||||||
|
static class B extends TestObjectClone {
|
||||||
|
public B clone() {
|
||||||
|
return (B)TestObjectClone.b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static class C extends TestObjectClone {
|
||||||
|
public C clone() {
|
||||||
|
return (C)TestObjectClone.c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static class D extends TestObjectClone {
|
||||||
|
public D clone() {
|
||||||
|
return (D)TestObjectClone.d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static TestObjectClone a = new A(), b = new B(), c = new C(), d = new D();
|
||||||
|
|
||||||
|
public static Object f(TestObjectClone o) throws CloneNotSupportedException {
|
||||||
|
// Polymorphic call site: >90% Object::clone / <10% other methods
|
||||||
|
return o.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
TestObjectClone[] params1 = {a, a, a, a, a, a, a, a, a, a, a,
|
||||||
|
a, a, a, a, a, a, a, a, a, a, a,
|
||||||
|
a, a, a, a, a, a, a, a, a, a, a,
|
||||||
|
b, c, d};
|
||||||
|
|
||||||
|
for (int i = 0; i < 15000; i++) {
|
||||||
|
f(params1[i % params1.length]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Asserts.assertTrue(f(a) != a);
|
||||||
|
Asserts.assertTrue(f(b) == b);
|
||||||
|
Asserts.assertTrue(f(c) == c);
|
||||||
|
Asserts.assertTrue(f(d) == d);
|
||||||
|
|
||||||
|
try {
|
||||||
|
f(null);
|
||||||
|
throw new AssertionError("");
|
||||||
|
} catch (NullPointerException e) { /* expected */ }
|
||||||
|
|
||||||
|
System.out.println("TEST PASSED");
|
||||||
|
}
|
||||||
|
}
|
141
hotspot/test/compiler/intrinsics/sha/TestSHA.java
Normal file
141
hotspot/test/compiler/intrinsics/sha/TestSHA.java
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8035968
|
||||||
|
* @summary C2 support for SHA on SPARC
|
||||||
|
*
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1 TestSHA
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-224 TestSHA
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-256 TestSHA
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-384 TestSHA
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-512 TestSHA
|
||||||
|
*
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1 -Doffset=1 TestSHA
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-224 -Doffset=1 TestSHA
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-256 -Doffset=1 TestSHA
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-384 -Doffset=1 TestSHA
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-512 -Doffset=1 TestSHA
|
||||||
|
*
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1 -Dalgorithm2=SHA-256 TestSHA
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1 -Dalgorithm2=SHA-512 TestSHA
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-256 -Dalgorithm2=SHA-512 TestSHA
|
||||||
|
*
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1 -Dalgorithm2=MD5 TestSHA
|
||||||
|
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=MD5 -Dalgorithm2=SHA-1 TestSHA
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class TestSHA {
|
||||||
|
private static final int HASH_LEN = 64; /* up to 512-bit */
|
||||||
|
private static final int ALIGN = 8; /* for different data alignments */
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
String provider = System.getProperty("provider", "SUN");
|
||||||
|
String algorithm = System.getProperty("algorithm", "SHA-1");
|
||||||
|
String algorithm2 = System.getProperty("algorithm2", "");
|
||||||
|
int msgSize = Integer.getInteger("msgSize", 1024);
|
||||||
|
int offset = Integer.getInteger("offset", 0) % ALIGN;
|
||||||
|
int iters = (args.length > 0 ? Integer.valueOf(args[0]) : 100000);
|
||||||
|
int warmupIters = (args.length > 1 ? Integer.valueOf(args[1]) : 20000);
|
||||||
|
|
||||||
|
testSHA(provider, algorithm, msgSize, offset, iters, warmupIters);
|
||||||
|
|
||||||
|
if (algorithm2.equals("") == false) {
|
||||||
|
testSHA(provider, algorithm2, msgSize, offset, iters, warmupIters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void testSHA(String provider, String algorithm, int msgSize,
|
||||||
|
int offset, int iters, int warmupIters) throws Exception {
|
||||||
|
System.out.println("provider = " + provider);
|
||||||
|
System.out.println("algorithm = " + algorithm);
|
||||||
|
System.out.println("msgSize = " + msgSize + " bytes");
|
||||||
|
System.out.println("offset = " + offset);
|
||||||
|
System.out.println("iters = " + iters);
|
||||||
|
|
||||||
|
byte[] expectedHash = new byte[HASH_LEN];
|
||||||
|
byte[] hash = new byte[HASH_LEN];
|
||||||
|
byte[] data = new byte[msgSize + offset];
|
||||||
|
for (int i = 0; i < (msgSize + offset); i++) {
|
||||||
|
data[i] = (byte)(i & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
MessageDigest sha = MessageDigest.getInstance(algorithm, provider);
|
||||||
|
|
||||||
|
/* do once, which doesn't use intrinsics */
|
||||||
|
sha.reset();
|
||||||
|
sha.update(data, offset, msgSize);
|
||||||
|
expectedHash = sha.digest();
|
||||||
|
|
||||||
|
/* warm up */
|
||||||
|
for (int i = 0; i < warmupIters; i++) {
|
||||||
|
sha.reset();
|
||||||
|
sha.update(data, offset, msgSize);
|
||||||
|
hash = sha.digest();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check result */
|
||||||
|
if (Arrays.equals(hash, expectedHash) == false) {
|
||||||
|
System.out.println("TestSHA Error: ");
|
||||||
|
showArray(expectedHash, "expectedHash");
|
||||||
|
showArray(hash, "computedHash");
|
||||||
|
//System.exit(1);
|
||||||
|
throw new Exception("TestSHA Error");
|
||||||
|
} else {
|
||||||
|
showArray(hash, "hash");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* measure performance */
|
||||||
|
long start = System.nanoTime();
|
||||||
|
for (int i = 0; i < iters; i++) {
|
||||||
|
sha.reset();
|
||||||
|
sha.update(data, offset, msgSize);
|
||||||
|
hash = sha.digest();
|
||||||
|
}
|
||||||
|
long end = System.nanoTime();
|
||||||
|
double total = (double)(end - start)/1e9; /* in seconds */
|
||||||
|
double thruput = (double)msgSize*iters/1e6/total; /* in MB/s */
|
||||||
|
System.out.println("TestSHA runtime = " + total + " seconds");
|
||||||
|
System.out.println("TestSHA throughput = " + thruput + " MB/s");
|
||||||
|
System.out.println();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("Exception: " + e);
|
||||||
|
//System.exit(1);
|
||||||
|
throw new Exception(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void showArray(byte b[], String name) {
|
||||||
|
System.out.format("%s [%d]: ", name, b.length);
|
||||||
|
for (int i = 0; i < Math.min(b.length, HASH_LEN); i++) {
|
||||||
|
System.out.format("%02x ", b[i] & 0xff);
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
}
|
111
hotspot/test/compiler/loopopts/TestLogSum.java
Normal file
111
hotspot/test/compiler/loopopts/TestLogSum.java
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8046516
|
||||||
|
* @summary Segmentation fault in JVM (easily reproducible)
|
||||||
|
* @run main/othervm -XX:-TieredCompilation -Xbatch TestLogSum
|
||||||
|
* @author jackkamm@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
public class TestLogSum {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
double sum;
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
for (int n = 2; n < 30; n++) {
|
||||||
|
for (int j = 1; j <= n; j++) {
|
||||||
|
for (int k = 1; k <= j; k++) {
|
||||||
|
// System.out.println(computeSum(k, j));
|
||||||
|
sum = computeSum(k, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<List<Integer>, Double> cache = new HashMap<List<Integer>, Double>();
|
||||||
|
public static double computeSum(int x, int y) {
|
||||||
|
List<Integer> key = Arrays.asList(new Integer[] {x, y});
|
||||||
|
|
||||||
|
if (!cache.containsKey(key)) {
|
||||||
|
|
||||||
|
// explicitly creating/updating a double[] array, instead of using the LogSumArray wrapper object, will prevent the error
|
||||||
|
LogSumArray toReturn = new LogSumArray(x);
|
||||||
|
|
||||||
|
// changing loop indices will prevent the error
|
||||||
|
// in particular, for(z=0; z<x-1; z++), and then using z+1 in place of z, will not produce error
|
||||||
|
for (int z = 1; z < x+1; z++) {
|
||||||
|
double logSummand = Math.log(z + x + y);
|
||||||
|
toReturn.addLogSummand(logSummand);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returning the value here without cacheing it will prevent the segfault
|
||||||
|
cache.put(key, toReturn.retrieveLogSum());
|
||||||
|
}
|
||||||
|
return cache.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a bunch of logarithms log(X),log(Y),log(Z),...
|
||||||
|
* This class is used to compute the log of the sum, log(X+Y+Z+...)
|
||||||
|
*/
|
||||||
|
private static class LogSumArray {
|
||||||
|
private double[] logSummandArray;
|
||||||
|
private int currSize;
|
||||||
|
|
||||||
|
private double maxLogSummand;
|
||||||
|
|
||||||
|
public LogSumArray(int maxEntries) {
|
||||||
|
this.logSummandArray = new double[maxEntries];
|
||||||
|
|
||||||
|
this.currSize = 0;
|
||||||
|
this.maxLogSummand = Double.NEGATIVE_INFINITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLogSummand(double logSummand) {
|
||||||
|
logSummandArray[currSize] = logSummand;
|
||||||
|
currSize++;
|
||||||
|
// removing this line will prevent the error
|
||||||
|
maxLogSummand = Math.max(maxLogSummand, logSummand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double retrieveLogSum() {
|
||||||
|
if (maxLogSummand == Double.NEGATIVE_INFINITY) return Double.NEGATIVE_INFINITY;
|
||||||
|
|
||||||
|
assert currSize <= logSummandArray.length;
|
||||||
|
|
||||||
|
double factorSum = 0;
|
||||||
|
for (int i = 0; i < currSize; i++) {
|
||||||
|
factorSum += Math.exp(logSummandArray[i] - maxLogSummand);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.log(factorSum) + maxLogSummand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
hotspot/test/compiler/relocations/TestPrintRelocations.java
Normal file
38
hotspot/test/compiler/relocations/TestPrintRelocations.java
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8044538
|
||||||
|
* @summary assert hit while printing relocations for jump table entries
|
||||||
|
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:+PrintRelocations TestPrintRelocations
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The test compiles all methods (-Xcomp) and prints their relocation
|
||||||
|
* entries (-XX:+PrintRelocations) to make sure the printing works.
|
||||||
|
*/
|
||||||
|
public class TestPrintRelocations {
|
||||||
|
|
||||||
|
static public void main(String[] args) { }
|
||||||
|
}
|
|
@ -28,7 +28,7 @@
|
||||||
* @build IsMethodCompilableTest
|
* @build IsMethodCompilableTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
* @run main ClassFileInstaller com.oracle.java.testlibrary.Platform
|
* @run main ClassFileInstaller com.oracle.java.testlibrary.Platform
|
||||||
* @run main/othervm/timeout=2400 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:PerMethodRecompilationCutoff=3 -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* IsMethodCompilableTest
|
* @run main/othervm/timeout=2400 -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:PerMethodRecompilationCutoff=3 -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* IsMethodCompilableTest
|
||||||
* @summary testing of WB::isMethodCompilable()
|
* @summary testing of WB::isMethodCompilable()
|
||||||
* @author igor.ignatyev@oracle.com
|
* @author igor.ignatyev@oracle.com
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
import com.oracle.java.testlibrary.Platform;
|
import com.oracle.java.testlibrary.Platform;
|
||||||
|
|
||||||
public class UintxTest {
|
public class UintxTest {
|
||||||
private static final String FLAG_NAME = "TypeProfileLevel";
|
private static final String FLAG_NAME = "VerifyGCStartAt";
|
||||||
private static final Long[] TESTS = {0L, 100L, (long) Integer.MAX_VALUE,
|
private static final Long[] TESTS = {0L, 100L, (long) Integer.MAX_VALUE,
|
||||||
(1L << 32L) - 1L, 1L << 32L};
|
(1L << 32L) - 1L, 1L << 32L};
|
||||||
private static final Long[] EXPECTED_64 = TESTS;
|
private static final Long[] EXPECTED_64 = TESTS;
|
||||||
|
|
|
@ -55,9 +55,7 @@ public final class VmFlagTest<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private T getValue() {
|
private T getValue() {
|
||||||
T t = get.apply(flagName);
|
return get.apply(flagName);
|
||||||
System.out.println("T = " + t);
|
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static <T> void runTest(String existentFlag, T[] tests,
|
protected static <T> void runTest(String existentFlag, T[] tests,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue