This commit is contained in:
Prasanta Sadhukhan 2020-07-25 12:48:29 +05:30
commit 091b0c95c3
175 changed files with 2282 additions and 1292 deletions
.hgtags
doc
make
src
hotspot
java.base/share/classes/java

@ -650,3 +650,5 @@ a32f58c6b8be81877411767de7ba9c4cf087c1b5 jdk-15+31
143e258f64af490010eb7e0bacc1cfaeceff0993 jdk-16+5 143e258f64af490010eb7e0bacc1cfaeceff0993 jdk-16+5
2dad000726b8d5db9f3df647fb4949d88f269dd4 jdk-15+32 2dad000726b8d5db9f3df647fb4949d88f269dd4 jdk-15+32
4a8fd81d64bafa523cddb45f82805536edace106 jdk-16+6 4a8fd81d64bafa523cddb45f82805536edace106 jdk-16+6
6b65f4e7a975628df51ef755b02642075390041d jdk-15+33
c3a4a7ea7c304cabdacdc31741eb94c51351668d jdk-16+7

@ -283,7 +283,7 @@
<p>The JDK is currently known to be able to compile with at least version 9.2 of gcc.</p> <p>The JDK is currently known to be able to compile with at least version 9.2 of gcc.</p>
<p>In general, any version between these two should be usable.</p> <p>In general, any version between these two should be usable.</p>
<h3 id="clang">clang</h3> <h3 id="clang">clang</h3>
<p>The minimum accepted version of clang is 3.2. Older versions will not be accepted by <code>configure</code>.</p> <p>The minimum accepted version of clang is 3.5. Older versions will not be accepted by <code>configure</code>.</p>
<p>To use clang instead of gcc on Linux, use <code>--with-toolchain-type=clang</code>.</p> <p>To use clang instead of gcc on Linux, use <code>--with-toolchain-type=clang</code>.</p>
<h3 id="apple-xcode">Apple Xcode</h3> <h3 id="apple-xcode">Apple Xcode</h3>
<p>The oldest supported version of Xcode is 8.</p> <p>The oldest supported version of Xcode is 8.</p>
@ -292,9 +292,8 @@
<p>It is advisable to keep an older version of Xcode for building the JDK when updating Xcode. This <a href="http://iosdevelopertips.com/xcode/install-multiple-versions-of-xcode.html">blog page</a> has good suggestions on managing multiple Xcode versions. To use a specific version of Xcode, use <code>xcode-select -s</code> before running <code>configure</code>, or use <code>--with-toolchain-path</code> to point to the version of Xcode to use, e.g. <code>configure --with-toolchain-path=/Applications/Xcode8.app/Contents/Developer/usr/bin</code></p> <p>It is advisable to keep an older version of Xcode for building the JDK when updating Xcode. This <a href="http://iosdevelopertips.com/xcode/install-multiple-versions-of-xcode.html">blog page</a> has good suggestions on managing multiple Xcode versions. To use a specific version of Xcode, use <code>xcode-select -s</code> before running <code>configure</code>, or use <code>--with-toolchain-path</code> to point to the version of Xcode to use, e.g. <code>configure --with-toolchain-path=/Applications/Xcode8.app/Contents/Developer/usr/bin</code></p>
<p>If you have recently (inadvertently) updated your OS and/or Xcode version, and the JDK can no longer be built, please see the section on <a href="#problems-with-the-build-environment">Problems with the Build Environment</a>, and <a href="#getting-help">Getting Help</a> to find out if there are any recent, non-merged patches available for this update.</p> <p>If you have recently (inadvertently) updated your OS and/or Xcode version, and the JDK can no longer be built, please see the section on <a href="#problems-with-the-build-environment">Problems with the Build Environment</a>, and <a href="#getting-help">Getting Help</a> to find out if there are any recent, non-merged patches available for this update.</p>
<h3 id="microsoft-visual-studio">Microsoft Visual Studio</h3> <h3 id="microsoft-visual-studio">Microsoft Visual Studio</h3>
<p>The minimum accepted version of Visual Studio is 2010. Older versions will not be accepted by <code>configure</code>. The maximum accepted version of Visual Studio is 2019. Versions older than 2017 are unlikely to continue working for long.</p> <p>The minimum accepted version of Visual Studio is 2017. Older versions will not be accepted by <code>configure</code> and will not work. The maximum accepted version of Visual Studio is 2019.</p>
<p>If you have multiple versions of Visual Studio installed, <code>configure</code> will by default pick the latest. You can request a specific version to be used by setting <code>--with-toolchain-version</code>, e.g. <code>--with-toolchain-version=2015</code>.</p> <p>If you have multiple versions of Visual Studio installed, <code>configure</code> will by default pick the latest. You can request a specific version to be used by setting <code>--with-toolchain-version</code>, e.g. <code>--with-toolchain-version=2017</code>.</p>
<p>If you get <code>LINK: fatal error LNK1123: failure during conversion to COFF: file invalid</code> when building using Visual Studio 2010, you have encountered <a href="http://support.microsoft.com/kb/2757355">KB2757355</a>, a bug triggered by a specific installation order. However, the solution suggested by the KB article does not always resolve the problem. See <a href="https://stackoverflow.com/questions/10888391">this stackoverflow discussion</a> for other suggestions.</p>
<h3 id="ibm-xl-cc">IBM XL C/C++</h3> <h3 id="ibm-xl-cc">IBM XL C/C++</h3>
<p>Please consult the AIX section of the <a href="https://wiki.openjdk.java.net/display/Build/Supported+Build+Platforms">Supported Build Platforms</a> OpenJDK Build Wiki page for details about which versions of XLC are supported.</p> <p>Please consult the AIX section of the <a href="https://wiki.openjdk.java.net/display/Build/Supported+Build+Platforms">Supported Build Platforms</a> OpenJDK Build Wiki page for details about which versions of XLC are supported.</p>
<h2 id="boot-jdk-requirements">Boot JDK Requirements</h2> <h2 id="boot-jdk-requirements">Boot JDK Requirements</h2>

@ -323,7 +323,7 @@ In general, any version between these two should be usable.
### clang ### clang
The minimum accepted version of clang is 3.2. Older versions will not be The minimum accepted version of clang is 3.5. Older versions will not be
accepted by `configure`. accepted by `configure`.
To use clang instead of gcc on Linux, use `--with-toolchain-type=clang`. To use clang instead of gcc on Linux, use `--with-toolchain-type=clang`.
@ -355,20 +355,13 @@ available for this update.
### Microsoft Visual Studio ### Microsoft Visual Studio
The minimum accepted version of Visual Studio is 2010. Older versions will not The minimum accepted version of Visual Studio is 2017. Older versions will not
be accepted by `configure`. The maximum accepted version of Visual Studio is be accepted by `configure` and will not work. The maximum accepted
2019. Versions older than 2017 are unlikely to continue working for long. version of Visual Studio is 2019.
If you have multiple versions of Visual Studio installed, `configure` will by If you have multiple versions of Visual Studio installed, `configure` will by
default pick the latest. You can request a specific version to be used by default pick the latest. You can request a specific version to be used by
setting `--with-toolchain-version`, e.g. `--with-toolchain-version=2015`. setting `--with-toolchain-version`, e.g. `--with-toolchain-version=2017`.
If you get `LINK: fatal error LNK1123: failure during conversion to COFF: file
invalid` when building using Visual Studio 2010, you have encountered
[KB2757355](http://support.microsoft.com/kb/2757355), a bug triggered by a
specific installation order. However, the solution suggested by the KB article
does not always resolve the problem. See [this stackoverflow discussion](
https://stackoverflow.com/questions/10888391) for other suggestions.
### IBM XL C/C++ ### IBM XL C/C++

@ -512,6 +512,18 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
fi fi
TOOLCHAIN_CFLAGS_JDK_CONLY="$LANGSTD_CFLAGS $TOOLCHAIN_CFLAGS_JDK_CONLY" TOOLCHAIN_CFLAGS_JDK_CONLY="$LANGSTD_CFLAGS $TOOLCHAIN_CFLAGS_JDK_CONLY"
# CXXFLAGS C++ language level for all of JDK, including Hotspot.
if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang || test "x$TOOLCHAIN_TYPE" = xxlc; then
LANGSTD_CXXFLAGS="-std=c++14"
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
LANGSTD_CXXFLAGS="-std:c++14"
else
AC_MSG_ERROR([Don't know how to enable C++14 for this toolchain])
fi
TOOLCHAIN_CFLAGS_JDK_CXXONLY="$TOOLCHAIN_CFLAGS_JDK_CXXONLY $LANGSTD_CXXFLAGS"
TOOLCHAIN_CFLAGS_JVM="$TOOLCHAIN_CFLAGS_JVM $LANGSTD_CXXFLAGS"
ADLC_LANGSTD_CXXFLAGS="$LANGSTD_CXXFLAGS"
# CFLAGS WARNINGS STUFF # CFLAGS WARNINGS STUFF
# Set JVM_CFLAGS warning handling # Set JVM_CFLAGS warning handling
if test "x$TOOLCHAIN_TYPE" = xgcc; then if test "x$TOOLCHAIN_TYPE" = xgcc; then
@ -694,13 +706,6 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
$1_CFLAGS_CPU_JDK="${$1_CFLAGS_CPU_JDK} -fno-omit-frame-pointer" $1_CFLAGS_CPU_JDK="${$1_CFLAGS_CPU_JDK} -fno-omit-frame-pointer"
fi fi
$1_CXXSTD_CXXFLAG="-std=gnu++98"
FLAGS_CXX_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [${$1_CXXSTD_CXXFLAG}],
PREFIX: $3, IF_FALSE: [$1_CXXSTD_CXXFLAG=""])
$1_TOOLCHAIN_CFLAGS_JDK_CXXONLY="${$1_CXXSTD_CXXFLAG}"
$1_TOOLCHAIN_CFLAGS_JVM="${$1_TOOLCHAIN_CFLAGS_JVM} ${$1_CXXSTD_CXXFLAG}"
$2ADLC_CXXFLAG="${$1_CXXSTD_CXXFLAG}"
elif test "x$TOOLCHAIN_TYPE" = xclang; then elif test "x$TOOLCHAIN_TYPE" = xclang; then
if test "x$FLAGS_OS" = xlinux; then if test "x$FLAGS_OS" = xlinux; then
# ppc test not really needed for clang # ppc test not really needed for clang
@ -795,7 +800,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
AC_SUBST($2CFLAGS_JDKEXE) AC_SUBST($2CFLAGS_JDKEXE)
AC_SUBST($2CXXFLAGS_JDKLIB) AC_SUBST($2CXXFLAGS_JDKLIB)
AC_SUBST($2CXXFLAGS_JDKEXE) AC_SUBST($2CXXFLAGS_JDKEXE)
AC_SUBST($2ADLC_CXXFLAG) AC_SUBST($2ADLC_LANGSTD_CXXFLAGS)
COMPILER_FP_CONTRACT_OFF_FLAG="-ffp-contract=off" COMPILER_FP_CONTRACT_OFF_FLAG="-ffp-contract=off"
# Check that the compiler supports -ffp-contract=off flag # Check that the compiler supports -ffp-contract=off flag

@ -53,6 +53,7 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS],
LDFLAGS_TESTEXE="${TARGET_LDFLAGS_JDK_LIBPATH}" LDFLAGS_TESTEXE="${TARGET_LDFLAGS_JDK_LIBPATH}"
AC_SUBST(LDFLAGS_TESTEXE) AC_SUBST(LDFLAGS_TESTEXE)
AC_SUBST(ADLC_LDFLAGS)
]) ])
################################################################################ ################################################################################

@ -70,6 +70,7 @@ AC_DEFUN_ONCE([LIB_SETUP_STD_LIBS],
else else
LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS" LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS"
JVM_LDFLAGS="$JVM_LDFLAGS $STATIC_STDCXX_FLAGS" JVM_LDFLAGS="$JVM_LDFLAGS $STATIC_STDCXX_FLAGS"
ADLC_LDFLAGS="$ADLC_LDFLAGS $STATIC_STDCXX_FLAGS"
# Ideally, we should test stdc++ for the BUILD toolchain separately. For now # Ideally, we should test stdc++ for the BUILD toolchain separately. For now
# just use the same setting as for the TARGET toolchain. # just use the same setting as for the TARGET toolchain.
OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $STATIC_STDCXX_FLAGS" OPENJDK_BUILD_JVM_LDFLAGS="$OPENJDK_BUILD_JVM_LDFLAGS $STATIC_STDCXX_FLAGS"

@ -476,7 +476,8 @@ DISABLED_WARNINGS_CXX := @DISABLED_WARNINGS_CXX@
WARNINGS_AS_ERRORS := @WARNINGS_AS_ERRORS@ WARNINGS_AS_ERRORS := @WARNINGS_AS_ERRORS@
CFLAGS_CCACHE:=@CFLAGS_CCACHE@ CFLAGS_CCACHE:=@CFLAGS_CCACHE@
ADLC_CXXFLAG=@ADLC_CXXFLAG@ ADLC_LANGSTD_CXXFLAGS=@ADLC_LANGSTD_CXXFLAGS@
ADLC_LDFLAGS=@ADLC_LDFLAGS@
# Tools that potentially need to be cross compilation aware. # Tools that potentially need to be cross compilation aware.
CC:=@FIXPATH@ @CCACHE@ @ICECC@ @CC@ CC:=@FIXPATH@ @CCACHE@ @ICECC@ @CC@

@ -50,9 +50,9 @@ TOOLCHAIN_DESCRIPTION_microsoft="Microsoft Visual Studio"
TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++" TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++"
# Minimum supported versions, empty means unspecified # Minimum supported versions, empty means unspecified
TOOLCHAIN_MINIMUM_VERSION_clang="3.2" TOOLCHAIN_MINIMUM_VERSION_clang="3.5"
TOOLCHAIN_MINIMUM_VERSION_gcc="5.0" TOOLCHAIN_MINIMUM_VERSION_gcc="5.0"
TOOLCHAIN_MINIMUM_VERSION_microsoft="16.00.30319.01" # VS2010 TOOLCHAIN_MINIMUM_VERSION_microsoft="19.10.0.0" # VS2017
TOOLCHAIN_MINIMUM_VERSION_xlc="" TOOLCHAIN_MINIMUM_VERSION_xlc=""
# Minimum supported linker versions, empty means unspecified # Minimum supported linker versions, empty means unspecified

@ -25,55 +25,7 @@
################################################################################ ################################################################################
# The order of these defines the priority by which we try to find them. # The order of these defines the priority by which we try to find them.
VALID_VS_VERSIONS="2019 2017 2013 2015 2012 2010" VALID_VS_VERSIONS="2019 2017"
VS_DESCRIPTION_2010="Microsoft Visual Studio 2010"
VS_VERSION_INTERNAL_2010=100
VS_MSVCR_2010=msvcr100.dll
# We don't use msvcp on Visual Studio 2010
#VS_MSVCP_2010=msvcp100.dll
VS_ENVVAR_2010="VS100COMNTOOLS"
VS_VS_INSTALLDIR_2010="Microsoft Visual Studio 10.0"
VS_SDK_INSTALLDIR_2010="Microsoft SDKs/Windows/v7.1"
VS_VS_PLATFORM_NAME_2010="v100"
VS_SDK_PLATFORM_NAME_2010="Windows7.1SDK"
VS_SUPPORTED_2010=false
VS_DESCRIPTION_2012="Microsoft Visual Studio 2012"
VS_VERSION_INTERNAL_2012=110
VS_MSVCR_2012=msvcr110.dll
VS_MSVCP_2012=msvcp110.dll
VS_ENVVAR_2012="VS110COMNTOOLS"
VS_VS_INSTALLDIR_2012="Microsoft Visual Studio 11.0"
VS_SDK_INSTALLDIR_2012=
VS_VS_PLATFORM_NAME_2012="v110"
VS_SDK_PLATFORM_NAME_2012=
VS_SUPPORTED_2012=false
VS_DESCRIPTION_2013="Microsoft Visual Studio 2013"
VS_VERSION_INTERNAL_2013=120
VS_MSVCR_2013=msvcr120.dll
VS_MSVCP_2013=msvcp120.dll
VS_ENVVAR_2013="VS120COMNTOOLS"
VS_VS_INSTALLDIR_2013="Microsoft Visual Studio 12.0"
VS_SDK_INSTALLDIR_2013=
VS_VS_PLATFORM_NAME_2013="v120"
VS_SDK_PLATFORM_NAME_2013=
VS_SUPPORTED_2013=false
VS_DESCRIPTION_2015="Microsoft Visual Studio 2015"
VS_VERSION_INTERNAL_2015=140
VS_MSVCR_2015=vcruntime140.dll
VS_MSVCP_2015=msvcp140.dll
VS_ENVVAR_2015="VS140COMNTOOLS"
VS_VS_INSTALLDIR_2015="Microsoft Visual Studio 14.0"
VS_SDK_INSTALLDIR_2015=
VS_VS_PLATFORM_NAME_2015="v140"
VS_SDK_PLATFORM_NAME_2015=
# The vcvars of 2015 breaks if 2017 is also installed. Work around this by
# explicitly specifying Windows Kit 8.1 to be used.
VS_ENV_ARGS_2015="8.1"
VS_SUPPORTED_2015=false
VS_DESCRIPTION_2017="Microsoft Visual Studio 2017" VS_DESCRIPTION_2017="Microsoft Visual Studio 2017"
VS_VERSION_INTERNAL_2017=141 VS_VERSION_INTERNAL_2017=141

@ -37,18 +37,18 @@ ifeq ($(call check-jvm-feature, compiler2), true)
ifeq ($(call isBuildOs, linux), true) ifeq ($(call isBuildOs, linux), true)
ADLC_CFLAGS := -fno-exceptions -DLINUX ADLC_CFLAGS := -fno-exceptions -DLINUX
else ifeq ($(call isBuildOs, aix), true) else ifeq ($(call isBuildOs, aix), true)
ADLC_LDFLAGS := -q64 ADLC_LDFLAGS += -q64
ADLC_CFLAGS := -qnortti -qeh -q64 -DAIX ADLC_CFLAGS := -qnortti -qeh -q64 -DAIX
else ifeq ($(call isBuildOs, windows), true) else ifeq ($(call isBuildOs, windows), true)
ADLC_LDFLAGS := -nologo ADLC_LDFLAGS += -nologo
ADLC_CFLAGS := -nologo -EHsc ADLC_CFLAGS := -nologo -EHsc
# NOTE: The old build also have -D_CRT_SECURE_NO_DEPRECATE but it doesn't # NOTE: The old build also have -D_CRT_SECURE_NO_DEPRECATE but it doesn't
# seem needed any more. # seem needed any more.
ADLC_CFLAGS_WARNINGS := -W3 -D_CRT_SECURE_NO_WARNINGS ADLC_CFLAGS_WARNINGS := -W3 -D_CRT_SECURE_NO_WARNINGS
endif endif
# Set the C++ standard if supported # Set the C++ standard
ADLC_CFLAGS += $(ADLC_CXXFLAG) ADLC_CFLAGS += $(ADLC_LANGSTD_CXXFLAG)
# NOTE: The old build didn't set -DASSERT for windows but it doesn't seem to # NOTE: The old build didn't set -DASSERT for windows but it doesn't seem to
# hurt. # hurt.

@ -95,7 +95,8 @@ DISABLED_WARNINGS_clang := tautological-compare \
DISABLED_WARNINGS_xlc := tautological-compare shift-negative-value DISABLED_WARNINGS_xlc := tautological-compare shift-negative-value
DISABLED_WARNINGS_microsoft := 4100 4127 4201 4244 4291 4351 4511 4512 4514 4996 DISABLED_WARNINGS_microsoft := 4100 4127 4201 4244 4291 4351 \
4511 4512 4514 4624 4996
################################################################################ ################################################################################
# Platform specific setup # Platform specific setup

@ -66,6 +66,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBSA, \
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(SA_CFLAGS) $(SA_CXXFLAGS), \ CXXFLAGS := $(CXXFLAGS_JDKLIB) $(SA_CFLAGS) $(SA_CXXFLAGS), \
EXTRA_SRC := $(LIBSA_EXTRA_SRC), \ EXTRA_SRC := $(LIBSA_EXTRA_SRC), \
LDFLAGS := $(LDFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB), \
LIBS := $(LIBCXX), \
LIBS_linux := $(LIBDL), \ LIBS_linux := $(LIBDL), \
LIBS_macosx := -framework Foundation -framework JavaNativeFoundation \ LIBS_macosx := -framework Foundation -framework JavaNativeFoundation \
-framework JavaRuntimeSupport -framework Security -framework CoreFoundation, \ -framework JavaRuntimeSupport -framework Security -framework CoreFoundation, \

@ -1099,7 +1099,7 @@ source %{
// r27 is not allocatable when compressed oops is on and heapbase is not // r27 is not allocatable when compressed oops is on and heapbase is not
// zero, compressed klass pointers doesn't use r27 after JDK-8234794 // zero, compressed klass pointers doesn't use r27 after JDK-8234794
if (UseCompressedOops && CompressedOops::ptrs_base() != NULL) { if (UseCompressedOops && (CompressedOops::ptrs_base() != NULL || UseAOT)) {
_NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg())); _NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg()));
_NO_SPECIAL_REG_mask.SUBTRACT(_HEAPBASE_REG_mask); _NO_SPECIAL_REG_mask.SUBTRACT(_HEAPBASE_REG_mask);
_NO_SPECIAL_PTR_REG_mask.SUBTRACT(_HEAPBASE_REG_mask); _NO_SPECIAL_PTR_REG_mask.SUBTRACT(_HEAPBASE_REG_mask);
@ -4053,6 +4053,18 @@ operand immI_bitmask()
interface(CONST_INTER); interface(CONST_INTER);
%} %}
operand immL_positive_bitmaskI()
%{
predicate((n->get_long() != 0)
&& ((julong)n->get_long() < 0x80000000ULL)
&& is_power_of_2(n->get_long() + 1));
match(ConL);
op_cost(0);
format %{ %}
interface(CONST_INTER);
%}
// Scale values for scaled offset addressing modes (up to long but not quad) // Scale values for scaled offset addressing modes (up to long but not quad)
operand immIScale() operand immIScale()
%{ %{
@ -10150,7 +10162,7 @@ instruct lshift_ext(iRegLNoSp dst, iRegIorL2I src, immI scale, rFlagsReg cr) %{
ins_encode %{ ins_encode %{
__ sbfiz(as_Register($dst$$reg), __ sbfiz(as_Register($dst$$reg),
as_Register($src$$reg), as_Register($src$$reg),
$scale$$constant & 63, MIN(32, (-$scale$$constant) & 63)); $scale$$constant & 63, MIN2(32, (int)((-$scale$$constant) & 63)));
%} %}
ins_pipe(ialu_reg_shift); ins_pipe(ialu_reg_shift);
@ -12149,6 +12161,50 @@ instruct ubfizL(iRegLNoSp dst, iRegL src, immI lshift, immL_bitmask mask)
ins_pipe(ialu_reg_shift); ins_pipe(ialu_reg_shift);
%} %}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
// We can use ubfiz when masking by a positive number and then left shifting the result.
// We know that the mask is positive because immI_bitmask guarantees it.
instruct ubfizwIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI lshift, immI_bitmask mask)
%{
match(Set dst (ConvI2L (LShiftI (AndI src mask) lshift)));
predicate((exact_log2(n->in(1)->in(1)->in(2)->get_int() + 1) + (n->in(1)->in(2)->get_int() & 31)) <= 31);
ins_cost(INSN_COST);
format %{ "ubfizw $dst, $src, $lshift, $mask" %}
ins_encode %{
int lshift = $lshift$$constant & 31;
intptr_t mask = $mask$$constant;
int width = exact_log2(mask+1);
__ ubfizw(as_Register($dst$$reg),
as_Register($src$$reg), lshift, width);
%}
ins_pipe(ialu_reg_shift);
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
// We can use ubfiz when masking by a positive number and then left shifting the result.
// We know that the mask is positive because immL_bitmask guarantees it.
instruct ubfizLConvL2I(iRegINoSp dst, iRegL src, immI lshift, immL_positive_bitmaskI mask)
%{
match(Set dst (ConvL2I (LShiftL (AndL src mask) lshift)));
predicate((exact_log2_long(n->in(1)->in(1)->in(2)->get_long() + 1) + (n->in(1)->in(2)->get_int() & 63)) <= 31);
ins_cost(INSN_COST);
format %{ "ubfiz $dst, $src, $lshift, $mask" %}
ins_encode %{
int lshift = $lshift$$constant & 63;
intptr_t mask = $mask$$constant;
int width = exact_log2_long(mask+1);
__ ubfiz(as_Register($dst$$reg),
as_Register($src$$reg), lshift, width);
%}
ins_pipe(ialu_reg_shift);
%}
// This pattern is automatically generated from aarch64_ad.m4 // This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
@ -12171,6 +12227,42 @@ instruct ubfizIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI lshift, immI_bitmask
ins_pipe(ialu_reg_shift); ins_pipe(ialu_reg_shift);
%} %}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
// If there is a convert L to I block between and AndL and a LShiftI, we can also match ubfiz
instruct ubfizLConvL2Ix(iRegINoSp dst, iRegL src, immI lshift, immL_positive_bitmaskI mask)
%{
match(Set dst (LShiftI (ConvL2I (AndL src mask)) lshift));
predicate((exact_log2_long(n->in(1)->in(1)->in(2)->get_long() + 1) + (n->in(2)->get_int() & 31)) <= 31);
ins_cost(INSN_COST);
format %{ "ubfiz $dst, $src, $lshift, $mask" %}
ins_encode %{
int lshift = $lshift$$constant & 31;
intptr_t mask = $mask$$constant;
int width = exact_log2(mask+1);
__ ubfiz(as_Register($dst$$reg),
as_Register($src$$reg), lshift, width);
%}
ins_pipe(ialu_reg_shift);
%}
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
// Can skip int2long conversions after AND with small bitmask
instruct ubfizIConvI2LAndI(iRegLNoSp dst, iRegI src, immI_bitmask msk)
%{
match(Set dst (ConvI2L (AndI src msk)));
ins_cost(INSN_COST);
format %{ "ubfiz $dst, $src, 0, exact_log2($msk + 1) " %}
ins_encode %{
__ ubfiz(as_Register($dst$$reg), as_Register($src$$reg), 0, exact_log2($msk$$constant + 1));
%}
ins_pipe(ialu_reg_shift);
%}
// Rotations // Rotations
// This pattern is automatically generated from aarch64_ad.m4 // This pattern is automatically generated from aarch64_ad.m4

@ -237,39 +237,45 @@ define(`UBFIZ_INSN', `// This pattern is automatically generated from aarch64_ad
// We can use ubfiz when masking by a positive number and then left shifting the result. // We can use ubfiz when masking by a positive number and then left shifting the result.
// We know that the mask is positive because imm$1_bitmask guarantees it. // We know that the mask is positive because imm$1_bitmask guarantees it.
instruct $2$1(iReg$1NoSp dst, iReg$1`'ORL2I($1) src, immI lshift, imm$1_bitmask mask) instruct $3$1$8(iReg$2NoSp dst, iReg$1`'ORL2I($1) src, immI lshift, $7 mask)
%{ %{
match(Set dst (LShift$1 (And$1 src mask) lshift)); ifelse($8,,
predicate((exact_log2$5(n->in(1)->in(2)->get_$4() + 1) + (n->in(2)->get_int() & $3)) <= ($3 + 1)); match(Set dst (LShift$1 (And$1 src mask) lshift));,
match(Set dst ($8 (LShift$1 (And$1 src mask) lshift)));)
ifelse($8,,
predicate(($6(n->in(1)->in(2)->get_$5() + 1) + (n->in(2)->get_int() & $4)) <= ($4 + 1));,
predicate(($6(n->in(1)->in(1)->in(2)->get_$5() + 1) + (n->in(1)->in(2)->get_int() & $4)) <= 31);)
ins_cost(INSN_COST); ins_cost(INSN_COST);
format %{ "$2 $dst, $src, $lshift, $mask" %} format %{ "$3 $dst, $src, $lshift, $mask" %}
ins_encode %{ ins_encode %{
int lshift = $lshift$$constant & $3; int lshift = $lshift$$constant & $4;
intptr_t mask = $mask$$constant; intptr_t mask = $mask$$constant;
int width = exact_log2$5(mask+1); int width = $6(mask+1);
__ $2(as_Register($dst$$reg), __ $3(as_Register($dst$$reg),
as_Register($src$$reg), lshift, width); as_Register($src$$reg), lshift, width);
%} %}
ins_pipe(ialu_reg_shift); ins_pipe(ialu_reg_shift);
%} %}
') ')
UBFIZ_INSN(I, ubfizw, 31, int) UBFIZ_INSN(I, I, ubfizw, 31, int, exact_log2, immI_bitmask)
UBFIZ_INSN(L, ubfiz, 63, long, _long) UBFIZ_INSN(L, L, ubfiz, 63, long, exact_log2_long, immL_bitmask)
UBFIZ_INSN(I, L, ubfizw, 31, int, exact_log2, immI_bitmask, ConvI2L)
UBFIZ_INSN(L, I, ubfiz, 63, long, exact_log2_long, immL_positive_bitmaskI, ConvL2I)
// This pattern is automatically generated from aarch64_ad.m4 define(`BFX1_INSN', `// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE // DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
// If there is a convert I to L block between and AndI and a LShiftL, we can also match ubfiz // If there is a convert $1 to $2 block between and And$1 and a LShift$2, we can also match ubfiz
instruct ubfizIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI lshift, immI_bitmask mask) instruct ubfiz$1Conv$3$9(iReg$2NoSp dst, iReg$1`'ORL2I($1) src, immI lshift, $8 mask)
%{ %{
match(Set dst (LShiftL (ConvI2L (AndI src mask)) lshift)); match(Set dst (LShift$2 (Conv$3 (And$1 src mask)) lshift));
predicate((exact_log2(n->in(1)->in(1)->in(2)->get_int() + 1) + (n->in(2)->get_int() & 63)) <= (63 + 1)); predicate(($4(n->in(1)->in(1)->in(2)->$5() + 1) + (n->in(2)->get_int() & $6)) <= $7);
ins_cost(INSN_COST); ins_cost(INSN_COST);
format %{ "ubfiz $dst, $src, $lshift, $mask" %} format %{ "ubfiz $dst, $src, $lshift, $mask" %}
ins_encode %{ ins_encode %{
int lshift = $lshift$$constant & 63; int lshift = $lshift$$constant & $6;
intptr_t mask = $mask$$constant; intptr_t mask = $mask$$constant;
int width = exact_log2(mask+1); int width = exact_log2(mask+1);
__ ubfiz(as_Register($dst$$reg), __ ubfiz(as_Register($dst$$reg),
@ -277,6 +283,23 @@ instruct ubfizIConvI2L(iRegLNoSp dst, iRegIorL2I src, immI lshift, immI_bitmask
%} %}
ins_pipe(ialu_reg_shift); ins_pipe(ialu_reg_shift);
%} %}
')dnl
BFX1_INSN(I, L, I2L, exact_log2, get_int, 63, (63 + 1), immI_bitmask)
BFX1_INSN(L, I, L2I, exact_log2_long, get_long, 31, 31, immL_positive_bitmaskI, x)
// This pattern is automatically generated from aarch64_ad.m4
// DO NOT EDIT ANYTHING IN THIS SECTION OF THE FILE
// Can skip int2long conversions after AND with small bitmask
instruct ubfizIConvI2LAndI(iRegLNoSp dst, iRegI src, immI_bitmask msk)
%{
match(Set dst (ConvI2L (AndI src msk)));
ins_cost(INSN_COST);
format %{ "ubfiz $dst, $src, 0, exact_log2($msk + 1) " %}
ins_encode %{
__ ubfiz(as_Register($dst$$reg), as_Register($src$$reg), 0, exact_log2($msk$$constant + 1));
%}
ins_pipe(ialu_reg_shift);
%}
// Rotations dnl // Rotations dnl

@ -1517,7 +1517,7 @@ void Address::lea(MacroAssembler *as, Register r) const {
break; break;
} }
case base_plus_offset_reg: { case base_plus_offset_reg: {
__ add(r, _base, _index, _ext.op(), MAX(_ext.shift(), 0)); __ add(r, _base, _index, _ext.op(), MAX2(_ext.shift(), 0));
break; break;
} }
case literal: { case literal: {

@ -2284,7 +2284,6 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
assert(default_type != NULL && default_type->is_array_klass() && default_type->is_loaded(), "must be true at this point"); assert(default_type != NULL && default_type->is_array_klass() && default_type->is_loaded(), "must be true at this point");
int elem_size = type2aelembytes(basic_type); int elem_size = type2aelembytes(basic_type);
int shift_amount;
int scale = exact_log2(elem_size); int scale = exact_log2(elem_size);
Address src_length_addr = Address(src, arrayOopDesc::length_offset_in_bytes()); Address src_length_addr = Address(src, arrayOopDesc::length_offset_in_bytes());

@ -658,10 +658,10 @@ intptr_t* frame::real_fp() const {
p[frame::name##_offset], #name); \ p[frame::name##_offset], #name); \
} }
static __thread uintptr_t nextfp; static THREAD_LOCAL uintptr_t nextfp;
static __thread uintptr_t nextpc; static THREAD_LOCAL uintptr_t nextpc;
static __thread uintptr_t nextsp; static THREAD_LOCAL uintptr_t nextsp;
static __thread RegisterMap *reg_map; static THREAD_LOCAL RegisterMap *reg_map;
static void printbc(Method *m, intptr_t bcx) { static void printbc(Method *m, intptr_t bcx) {
const char *name; const char *name;

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, 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
@ -67,8 +67,6 @@ void ZBarrierSetAssembler::load_at(MacroAssembler* masm,
assert_different_registers(rscratch1, rscratch2, src.base()); assert_different_registers(rscratch1, rscratch2, src.base());
assert_different_registers(rscratch1, rscratch2, dst); assert_different_registers(rscratch1, rscratch2, dst);
RegSet savedRegs = RegSet::range(r0, r28) - RegSet::of(dst, rscratch1, rscratch2);
Label done; Label done;
// Load bad mask into scratch register. // Load bad mask into scratch register.
@ -82,37 +80,21 @@ void ZBarrierSetAssembler::load_at(MacroAssembler* masm,
__ enter(); __ enter();
__ push(savedRegs, sp); __ push_call_clobbered_registers_except(RegSet::of(dst));
if (c_rarg0 != dst) { if (c_rarg0 != dst) {
__ mov(c_rarg0, dst); __ mov(c_rarg0, dst);
} }
__ mov(c_rarg1, rscratch2); __ mov(c_rarg1, rscratch2);
int step = 4 * wordSize;
__ mov(rscratch2, -step);
__ sub(sp, sp, step);
for (int i = 28; i >= 4; i -= 4) {
__ st1(as_FloatRegister(i), as_FloatRegister(i+1), as_FloatRegister(i+2),
as_FloatRegister(i+3), __ T1D, Address(__ post(sp, rscratch2)));
}
__ st1(as_FloatRegister(0), as_FloatRegister(1), as_FloatRegister(2),
as_FloatRegister(3), __ T1D, Address(sp));
__ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2); __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2);
for (int i = 0; i <= 28; i += 4) {
__ ld1(as_FloatRegister(i), as_FloatRegister(i+1), as_FloatRegister(i+2),
as_FloatRegister(i+3), __ T1D, Address(__ post(sp, step)));
}
// Make sure dst has the return value. // Make sure dst has the return value.
if (dst != r0) { if (dst != r0) {
__ mov(dst, r0); __ mov(dst, r0);
} }
__ pop(savedRegs, sp); __ pop_call_clobbered_registers_except(RegSet::of(dst));
__ leave(); __ leave();
__ bind(done); __ bind(done);
@ -170,7 +152,7 @@ void ZBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm,
assert_different_registers(src, count, rscratch1); assert_different_registers(src, count, rscratch1);
__ pusha(); __ push(saved_regs, sp);
if (count == c_rarg0) { if (count == c_rarg0) {
if (src == c_rarg1) { if (src == c_rarg1) {
@ -189,7 +171,8 @@ void ZBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm,
__ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_array_addr(), 2); __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_array_addr(), 2);
__ popa(); __ pop(saved_regs, sp);
BLOCK_COMMENT("} ZBarrierSetAssembler::arraycopy_prologue"); BLOCK_COMMENT("} ZBarrierSetAssembler::arraycopy_prologue");
} }
@ -295,13 +278,7 @@ void ZBarrierSetAssembler::generate_c1_load_barrier_runtime_stub(StubAssembler*
DecoratorSet decorators) const { DecoratorSet decorators) const {
__ prologue("zgc_load_barrier stub", false); __ prologue("zgc_load_barrier stub", false);
// We don't use push/pop_clobbered_registers() - we need to pull out the result from r0. __ push_call_clobbered_registers_except(RegSet::of(r0));
for (int i = 0; i < 32; i += 2) {
__ stpd(as_FloatRegister(i), as_FloatRegister(i + 1), Address(__ pre(sp,-16)));
}
const RegSet save_regs = RegSet::range(r1, r28);
__ push(save_regs, sp);
// Setup arguments // Setup arguments
__ load_parameter(0, c_rarg0); __ load_parameter(0, c_rarg0);
@ -309,11 +286,7 @@ void ZBarrierSetAssembler::generate_c1_load_barrier_runtime_stub(StubAssembler*
__ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2); __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2);
__ pop(save_regs, sp); __ pop_call_clobbered_registers_except(RegSet::of(r0));
for (int i = 30; i >= 0; i -= 2) {
__ ldpd(as_FloatRegister(i), as_FloatRegister(i + 1), Address(__ post(sp, 16)));
}
__ epilogue(); __ epilogue();
} }

@ -2626,9 +2626,9 @@ void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[])
fatal("DEBUG MESSAGE: %s", msg); fatal("DEBUG MESSAGE: %s", msg);
} }
void MacroAssembler::push_call_clobbered_registers() { void MacroAssembler::push_call_clobbered_registers_except(RegSet exclude) {
int step = 4 * wordSize; int step = 4 * wordSize;
push(RegSet::range(r0, r18) - RegSet::of(rscratch1, rscratch2), sp); push(RegSet::range(r0, r18) - RegSet::of(rscratch1, rscratch2) - exclude, sp);
sub(sp, sp, step); sub(sp, sp, step);
mov(rscratch1, -step); mov(rscratch1, -step);
// Push v0-v7, v16-v31. // Push v0-v7, v16-v31.
@ -2641,14 +2641,14 @@ void MacroAssembler::push_call_clobbered_registers() {
as_FloatRegister(3), T1D, Address(sp)); as_FloatRegister(3), T1D, Address(sp));
} }
void MacroAssembler::pop_call_clobbered_registers() { void MacroAssembler::pop_call_clobbered_registers_except(RegSet exclude) {
for (int i = 0; i < 32; i += 4) { for (int i = 0; i < 32; i += 4) {
if (i <= v7->encoding() || i >= v16->encoding()) if (i <= v7->encoding() || i >= v16->encoding())
ld1(as_FloatRegister(i), as_FloatRegister(i+1), as_FloatRegister(i+2), ld1(as_FloatRegister(i), as_FloatRegister(i+1), as_FloatRegister(i+2),
as_FloatRegister(i+3), T1D, Address(post(sp, 4 * wordSize))); as_FloatRegister(i+3), T1D, Address(post(sp, 4 * wordSize)));
} }
pop(RegSet::range(r0, r18) - RegSet::of(rscratch1, rscratch2), sp); pop(RegSet::range(r0, r18) - RegSet::of(rscratch1, rscratch2) - exclude, sp);
} }
void MacroAssembler::push_CPU_state(bool save_vectors) { void MacroAssembler::push_CPU_state(bool save_vectors) {

@ -477,9 +477,18 @@ public:
// Push and pop everything that might be clobbered by a native // Push and pop everything that might be clobbered by a native
// runtime call except rscratch1 and rscratch2. (They are always // runtime call except rscratch1 and rscratch2. (They are always
// scratch, so we don't have to protect them.) Only save the lower // scratch, so we don't have to protect them.) Only save the lower
// 64 bits of each vector register. // 64 bits of each vector register. Additonal registers can be excluded
void push_call_clobbered_registers(); // in a passed RegSet.
void pop_call_clobbered_registers(); void push_call_clobbered_registers_except(RegSet exclude);
void pop_call_clobbered_registers_except(RegSet exclude);
void push_call_clobbered_registers() {
push_call_clobbered_registers_except(RegSet());
}
void pop_call_clobbered_registers() {
pop_call_clobbered_registers_except(RegSet());
}
// now mov instructions for loading absolute addresses and 32 or // now mov instructions for loading absolute addresses and 32 or
// 64 bit integers // 64 bit integers

@ -697,7 +697,6 @@ class StubGenerator: public StubCodeGenerator {
int unit = wordSize * direction; int unit = wordSize * direction;
int bias = (UseSIMDForMemoryOps ? 4:2) * wordSize; int bias = (UseSIMDForMemoryOps ? 4:2) * wordSize;
int offset;
const Register t0 = r3, t1 = r4, t2 = r5, t3 = r6, const Register t0 = r3, t1 = r4, t2 = r5, t3 = r6,
t4 = r7, t5 = r10, t6 = r11, t7 = r12; t4 = r7, t5 = r10, t6 = r11, t7 = r12;
const Register stride = r13; const Register stride = r13;
@ -4061,7 +4060,7 @@ class StubGenerator: public StubCodeGenerator {
FloatRegister vtmpZ = v0, vtmp = v1, vtmp3 = v2; FloatRegister vtmpZ = v0, vtmp = v1, vtmp3 = v2;
RegSet spilled_regs = RegSet::of(tmp3, tmp4); RegSet spilled_regs = RegSet::of(tmp3, tmp4);
int prefetchLoopExitCondition = MAX(64, SoftwarePrefetchHintDistance/2); int prefetchLoopExitCondition = MAX2(64, SoftwarePrefetchHintDistance/2);
__ eor(vtmpZ, __ T16B, vtmpZ, vtmpZ); __ eor(vtmpZ, __ T16B, vtmpZ, vtmpZ);
// cnt2 == amount of characters left to compare // cnt2 == amount of characters left to compare
@ -4219,7 +4218,7 @@ class StubGenerator: public StubCodeGenerator {
DIFF_LAST_POSITION, DIFF_LAST_POSITION2; DIFF_LAST_POSITION, DIFF_LAST_POSITION2;
// exit from large loop when less than 64 bytes left to read or we're about // exit from large loop when less than 64 bytes left to read or we're about
// to prefetch memory behind array border // to prefetch memory behind array border
int largeLoopExitCondition = MAX(64, SoftwarePrefetchHintDistance)/(isLL ? 1 : 2); int largeLoopExitCondition = MAX2(64, SoftwarePrefetchHintDistance)/(isLL ? 1 : 2);
// cnt1/cnt2 contains amount of characters to compare. cnt1 can be re-used // cnt1/cnt2 contains amount of characters to compare. cnt1 can be re-used
// update cnt2 counter with already loaded 8 bytes // update cnt2 counter with already loaded 8 bytes
__ sub(cnt2, cnt2, wordSize/(isLL ? 1 : 2)); __ sub(cnt2, cnt2, wordSize/(isLL ? 1 : 2));
@ -4645,7 +4644,7 @@ class StubGenerator: public StubCodeGenerator {
address entry = __ pc(); address entry = __ pc();
Label LOOP, LOOP_START, LOOP_PRFM, LOOP_PRFM_START, DONE; Label LOOP, LOOP_START, LOOP_PRFM, LOOP_PRFM_START, DONE;
Register src = r0, dst = r1, len = r2, octetCounter = r3; Register src = r0, dst = r1, len = r2, octetCounter = r3;
const int large_loop_threshold = MAX(64, SoftwarePrefetchHintDistance)/8 + 4; const int large_loop_threshold = MAX2(64, SoftwarePrefetchHintDistance)/8 + 4;
// do one more 8-byte read to have address 16-byte aligned in most cases // do one more 8-byte read to have address 16-byte aligned in most cases
// also use single store instruction // also use single store instruction

@ -413,6 +413,7 @@ void TemplateTable::fast_aldc(bool wide)
// Stash null_sentinel address to get its value later // Stash null_sentinel address to get its value later
__ movptr(rarg, (uintptr_t)Universe::the_null_sentinel_addr()); __ movptr(rarg, (uintptr_t)Universe::the_null_sentinel_addr());
__ ldr(tmp, Address(rarg)); __ ldr(tmp, Address(rarg));
__ resolve_oop_handle(tmp);
__ cmpoop(result, tmp); __ cmpoop(result, tmp);
__ br(Assembler::NE, notNull); __ br(Assembler::NE, notNull);
__ mov(result, 0); // NULL object reference __ mov(result, 0); // NULL object reference

@ -462,6 +462,7 @@ void TemplateTable::fast_aldc(bool wide) {
// Stash null_sentinel address to get its value later // Stash null_sentinel address to get its value later
__ mov_slow(rarg, (uintptr_t)Universe::the_null_sentinel_addr()); __ mov_slow(rarg, (uintptr_t)Universe::the_null_sentinel_addr());
__ ldr(tmp, Address(rarg)); __ ldr(tmp, Address(rarg));
__ resolve_oop_handle(tmp);
__ cmp(result, tmp); __ cmp(result, tmp);
__ b(notNull, ne); __ b(notNull, ne);
__ mov(result, 0); // NULL object reference __ mov(result, 0); // NULL object reference

@ -317,9 +317,10 @@ void TemplateTable::fast_aldc(bool wide) {
__ get_cache_index_at_bcp(Rscratch, 1, index_size); // Load index. __ get_cache_index_at_bcp(Rscratch, 1, index_size); // Load index.
__ load_resolved_reference_at_index(R17_tos, Rscratch, &is_null); __ load_resolved_reference_at_index(R17_tos, Rscratch, &is_null);
// Convert null sentinel to NULL. // Convert null sentinel to NULL
int simm16_rest = __ load_const_optimized(Rscratch, Universe::the_null_sentinel_addr(), R0, true); int simm16_rest = __ load_const_optimized(Rscratch, Universe::the_null_sentinel_addr(), R0, true);
__ ld(Rscratch, simm16_rest, Rscratch); __ ld(Rscratch, simm16_rest, Rscratch);
__ resolve_oop_handle(Rscratch);
__ cmpld(CCR0, R17_tos, Rscratch); __ cmpld(CCR0, R17_tos, Rscratch);
if (VM_Version::has_isel()) { if (VM_Version::has_isel()) {
__ isel_0(R17_tos, CCR0, Assembler::equal); __ isel_0(R17_tos, CCR0, Assembler::equal);

@ -466,6 +466,7 @@ void TemplateTable::fast_aldc(bool wide) {
// Convert null sentinel to NULL. // Convert null sentinel to NULL.
__ load_const_optimized(Z_R1_scratch, (intptr_t)Universe::the_null_sentinel_addr()); __ load_const_optimized(Z_R1_scratch, (intptr_t)Universe::the_null_sentinel_addr());
__ resolve_oop_handle(Z_R1_scratch);
__ z_cg(Z_tos, Address(Z_R1_scratch)); __ z_cg(Z_tos, Address(Z_R1_scratch));
__ z_brne(L_resolved); __ z_brne(L_resolved);
__ clear_reg(Z_tos); __ clear_reg(Z_tos);

@ -448,6 +448,7 @@ void TemplateTable::fast_aldc(bool wide) {
Label notNull; Label notNull;
ExternalAddress null_sentinel((address)Universe::the_null_sentinel_addr()); ExternalAddress null_sentinel((address)Universe::the_null_sentinel_addr());
__ movptr(tmp, null_sentinel); __ movptr(tmp, null_sentinel);
__ resolve_oop_handle(tmp);
__ cmpoop(tmp, result); __ cmpoop(tmp, result);
__ jccb(Assembler::notEqual, notNull); __ jccb(Assembler::notEqual, notNull);
__ xorptr(result, result); // NULL object reference __ xorptr(result, result); // NULL object reference

@ -27,7 +27,6 @@
#include "aot/aotCompiledMethod.hpp" #include "aot/aotCompiledMethod.hpp"
#include "classfile/symbolTable.hpp" #include "classfile/symbolTable.hpp"
#include "metaprogramming/integralConstant.hpp" #include "metaprogramming/integralConstant.hpp"
#include "metaprogramming/isRegisteredEnum.hpp"
#include "oops/metadata.hpp" #include "oops/metadata.hpp"
#include "oops/method.hpp" #include "oops/method.hpp"
@ -37,8 +36,6 @@ enum CodeState {
invalid = 2 // AOT code is invalidated because dependencies failed invalid = 2 // AOT code is invalidated because dependencies failed
}; };
template<> struct IsRegisteredEnum<CodeState> : public TrueType {};
typedef struct { typedef struct {
AOTCompiledMethod* _aot; AOTCompiledMethod* _aot;
CodeState _state; // State change cases: not_set->in_use, not_set->invalid CodeState _state; // State change cases: not_set->in_use, not_set->invalid

@ -195,6 +195,9 @@ class SymbolPropertyEntry : public HashtableEntry<Symbol*, mtSymbol> {
oop method_type() const; oop method_type() const;
void set_method_type(oop p); void set_method_type(oop p);
// We need to clear the OopHandle because these hashtable entries are not constructed properly.
void clear_method_type() { _method_type = OopHandle(); }
void free_entry(); void free_entry();
SymbolPropertyEntry* next() const { SymbolPropertyEntry* next() const {
@ -247,7 +250,7 @@ private:
symbol->increment_refcount(); symbol->increment_refcount();
entry->set_symbol_mode(symbol_mode); entry->set_symbol_mode(symbol_mode);
entry->set_method(NULL); entry->set_method(NULL);
entry->set_method_type(NULL); entry->clear_method_type();
return entry; return entry;
} }

@ -436,11 +436,11 @@ char* java_lang_String::as_platform_dependent_str(Handle java_string, TRAPS) {
char *native_platform_string; char *native_platform_string;
{ JavaThread* thread = (JavaThread*)THREAD; { JavaThread* thread = (JavaThread*)THREAD;
assert(thread->is_Java_thread(), "must be java thread"); assert(thread->is_Java_thread(), "must be java thread");
JNIEnv *env = thread->jni_environment(); jstring js = (jstring) JNIHandles::make_local(thread, java_string());
jstring js = (jstring) JNIHandles::make_local(env, java_string());
bool is_copy; bool is_copy;
HandleMark hm(thread); HandleMark hm(thread);
ThreadToNativeFromVM ttn(thread); ThreadToNativeFromVM ttn(thread);
JNIEnv *env = thread->jni_environment();
native_platform_string = (_to_platform_string_fn)(env, js, &is_copy); native_platform_string = (_to_platform_string_fn)(env, js, &is_copy);
assert(is_copy == JNI_TRUE, "is_copy value changed"); assert(is_copy == JNI_TRUE, "is_copy value changed");
JNIHandles::destroy_local(js); JNIHandles::destroy_local(js);
@ -895,7 +895,7 @@ void java_lang_Class::fixup_mirror(Klass* k, TRAPS) {
assert(present, "Missing archived mirror for %s", k->external_name()); assert(present, "Missing archived mirror for %s", k->external_name());
return; return;
} else { } else {
k->set_java_mirror_handle(OopHandle()); k->clear_java_mirror_handle();
k->clear_has_raw_archived_mirror(); k->clear_has_raw_archived_mirror();
} }
} }
@ -1201,7 +1201,7 @@ oop java_lang_Class::archive_mirror(Klass* k, TRAPS) {
ik->is_shared_app_class())) { ik->is_shared_app_class())) {
// Archiving mirror for classes from non-builtin loaders is not // Archiving mirror for classes from non-builtin loaders is not
// supported. Clear the _java_mirror within the archived class. // supported. Clear the _java_mirror within the archived class.
k->set_java_mirror_handle(OopHandle()); k->clear_java_mirror_handle();
return NULL; return NULL;
} }
} }
@ -2844,10 +2844,10 @@ Method* java_lang_StackFrameInfo::get_method(Handle stackFrame, InstanceKlass* h
void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, TRAPS) { void java_lang_StackFrameInfo::set_method_and_bci(Handle stackFrame, const methodHandle& method, int bci, TRAPS) {
// set Method* or mid/cpref // set Method* or mid/cpref
HandleMark hm(THREAD); HandleMark hm(THREAD);
Handle mname(Thread::current(), stackFrame->obj_field(_memberName_offset)); Handle mname(THREAD, stackFrame->obj_field(_memberName_offset));
InstanceKlass* ik = method->method_holder(); InstanceKlass* ik = method->method_holder();
CallInfo info(method(), ik, CHECK); CallInfo info(method(), ik, CHECK);
MethodHandles::init_method_MemberName(mname, info); MethodHandles::init_method_MemberName(mname, info, THREAD);
// set bci // set bci
java_lang_StackFrameInfo::set_bci(stackFrame(), bci); java_lang_StackFrameInfo::set_bci(stackFrame(), bci);
// method may be redefined; store the version // method may be redefined; store the version

@ -1903,8 +1903,7 @@ class CopySharedClassInfoToArchive : StackObj {
bool _is_builtin; bool _is_builtin;
public: public:
CopySharedClassInfoToArchive(CompactHashtableWriter* writer, CopySharedClassInfoToArchive(CompactHashtableWriter* writer,
bool is_builtin, bool is_builtin)
bool is_static_archive)
: _writer(writer), _is_builtin(is_builtin) {} : _writer(writer), _is_builtin(is_builtin) {}
bool do_entry(InstanceKlass* k, DumpTimeSharedClassInfo& info) { bool do_entry(InstanceKlass* k, DumpTimeSharedClassInfo& info) {
@ -1953,12 +1952,11 @@ void SystemDictionaryShared::write_lambda_proxy_class_dictionary(LambdaProxyClas
} }
void SystemDictionaryShared::write_dictionary(RunTimeSharedDictionary* dictionary, void SystemDictionaryShared::write_dictionary(RunTimeSharedDictionary* dictionary,
bool is_builtin, bool is_builtin) {
bool is_static_archive) {
CompactHashtableStats stats; CompactHashtableStats stats;
dictionary->reset(); dictionary->reset();
CompactHashtableWriter writer(_dumptime_table->count_of(is_builtin), &stats); CompactHashtableWriter writer(_dumptime_table->count_of(is_builtin), &stats);
CopySharedClassInfoToArchive copy(&writer, is_builtin, is_static_archive); CopySharedClassInfoToArchive copy(&writer, is_builtin);
_dumptime_table->iterate(&copy); _dumptime_table->iterate(&copy);
writer.dump(dictionary, is_builtin ? "builtin dictionary" : "unregistered dictionary"); writer.dump(dictionary, is_builtin ? "builtin dictionary" : "unregistered dictionary");
} }

@ -211,8 +211,7 @@ private:
TRAPS); TRAPS);
static DumpTimeSharedClassInfo* find_or_allocate_info_for(InstanceKlass* k); static DumpTimeSharedClassInfo* find_or_allocate_info_for(InstanceKlass* k);
static void write_dictionary(RunTimeSharedDictionary* dictionary, static void write_dictionary(RunTimeSharedDictionary* dictionary,
bool is_builtin, bool is_builtin);
bool is_static_archive = true);
static void write_lambda_proxy_class_dictionary(LambdaProxyClassDictionary* dictionary); static void write_lambda_proxy_class_dictionary(LambdaProxyClassDictionary* dictionary);
static bool is_jfr_event_class(InstanceKlass *k); static bool is_jfr_event_class(InstanceKlass *k);
static bool is_registered_lambda_proxy_class(InstanceKlass* ik); static bool is_registered_lambda_proxy_class(InstanceKlass* ik);

@ -296,7 +296,6 @@ bool Verifier::is_eligible_for_verification(InstanceKlass* klass, bool should_ve
Symbol* Verifier::inference_verify( Symbol* Verifier::inference_verify(
InstanceKlass* klass, char* message, size_t message_len, TRAPS) { InstanceKlass* klass, char* message, size_t message_len, TRAPS) {
JavaThread* thread = (JavaThread*)THREAD; JavaThread* thread = (JavaThread*)THREAD;
JNIEnv *env = thread->jni_environment();
verify_byte_codes_fn_t verify_func = verify_byte_codes_fn(); verify_byte_codes_fn_t verify_func = verify_byte_codes_fn();
@ -305,10 +304,10 @@ Symbol* Verifier::inference_verify(
return vmSymbols::java_lang_VerifyError(); return vmSymbols::java_lang_VerifyError();
} }
ResourceMark rm(THREAD); ResourceMark rm(thread);
log_info(verification)("Verifying class %s with old format", klass->external_name()); log_info(verification)("Verifying class %s with old format", klass->external_name());
jclass cls = (jclass) JNIHandles::make_local(env, klass->java_mirror()); jclass cls = (jclass) JNIHandles::make_local(thread, klass->java_mirror());
jint result; jint result;
{ {
@ -316,7 +315,7 @@ Symbol* Verifier::inference_verify(
ThreadToNativeFromVM ttn(thread); ThreadToNativeFromVM ttn(thread);
// ThreadToNativeFromVM takes care of changing thread_state, so safepoint // ThreadToNativeFromVM takes care of changing thread_state, so safepoint
// code knows that we have left the VM // code knows that we have left the VM
JNIEnv *env = thread->jni_environment();
result = (*verify_func)(env, cls, message, (int)message_len, klass->major_version()); result = (*verify_func)(env, cls, message, (int)message_len, klass->major_version());
} }

@ -1655,7 +1655,7 @@ void CompileBroker::wait_for_completion(CompileTask* task) {
bool free_task; bool free_task;
#if INCLUDE_JVMCI #if INCLUDE_JVMCI
AbstractCompiler* comp = compiler(task->comp_level()); AbstractCompiler* comp = compiler(task->comp_level());
if (!UseJVMCINativeLibrary && comp->is_jvmci() && !task->should_wait_for_compilation()) { if (comp->is_jvmci() && !task->should_wait_for_compilation()) {
// It may return before compilation is completed. // It may return before compilation is completed.
free_task = wait_for_jvmci_completion((JVMCICompiler*) comp, task, thread); free_task = wait_for_jvmci_completion((JVMCICompiler*) comp, task, thread);
} else } else

@ -68,9 +68,11 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h,
// entries, since entry 0 keeps track of surviving bytes for non-young regions. // entries, since entry 0 keeps track of surviving bytes for non-young regions.
// We also add a few elements at the beginning and at the end in // We also add a few elements at the beginning and at the end in
// an attempt to eliminate cache contention // an attempt to eliminate cache contention
size_t array_length = PADDING_ELEM_NUM + _surviving_words_length + PADDING_ELEM_NUM; const size_t padding_elem_num = (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t));
size_t array_length = padding_elem_num + _surviving_words_length + padding_elem_num;
_surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length, mtGC); _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length, mtGC);
_surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM; _surviving_young_words = _surviving_young_words_base + padding_elem_num;
memset(_surviving_young_words, 0, _surviving_words_length * sizeof(size_t)); memset(_surviving_young_words, 0, _surviving_words_length * sizeof(size_t));
_plab_allocator = new G1PLABAllocator(_g1h->allocator()); _plab_allocator = new G1PLABAllocator(_g1h->allocator());

@ -81,8 +81,6 @@ class G1ParScanThreadState : public CHeapObj<mtGC> {
// available for allocation. // available for allocation.
bool _old_gen_is_full; bool _old_gen_is_full;
#define PADDING_ELEM_NUM (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t))
G1RedirtyCardsQueue& redirty_cards_queue() { return _rdcq; } G1RedirtyCardsQueue& redirty_cards_queue() { return _rdcq; }
G1CardTable* ct() { return _ct; } G1CardTable* ct() { return _ct; }

@ -53,6 +53,7 @@ ShenandoahParallelWeakRootsCleaningTask<IsAlive, KeepAlive>::~ShenandoahParallel
if (StringDedup::is_enabled()) { if (StringDedup::is_enabled()) {
StringDedup::gc_epilogue(); StringDedup::gc_epilogue();
} }
_weak_processing_task.report_num_dead();
} }
template<typename IsAlive, typename KeepAlive> template<typename IsAlive, typename KeepAlive>

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2020, 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
@ -135,7 +135,6 @@ T* JfrDoublyLinkedList<T>::remove(T* const node) {
prev->set_next(next); prev->set_next(next);
} }
--_count; --_count;
assert(_count >= 0, "invariant");
assert(!in_list(node), "still in list error"); assert(!in_list(node), "still in list error");
return node; return node;
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2020, 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
@ -83,7 +83,7 @@ class JfrBasicHashtable : public CHeapObj<mtTracing> {
size_t hash_to_index(uintptr_t full_hash) const { size_t hash_to_index(uintptr_t full_hash) const {
const uintptr_t h = full_hash % _table_size; const uintptr_t h = full_hash % _table_size;
assert(h >= 0 && h < _table_size, "Illegal hash value"); assert(h < _table_size, "Illegal hash value");
return (size_t)h; return (size_t)h;
} }
size_t entry_size() const { return _entry_size; } size_t entry_size() const { return _entry_size; }

@ -251,7 +251,7 @@ C2V_VMENTRY_NULL(jobject, getObjectAtAddress, (JNIEnv* env, jobject c2vm, jlong
if (obj != NULL) { if (obj != NULL) {
oopDesc::verify(obj); oopDesc::verify(obj);
} }
return JNIHandles::make_local(obj); return JNIHandles::make_local(THREAD, obj);
C2V_END C2V_END
C2V_VMENTRY_NULL(jbyteArray, getBytecode, (JNIEnv* env, jobject, jobject jvmci_method)) C2V_VMENTRY_NULL(jbyteArray, getBytecode, (JNIEnv* env, jobject, jobject jvmci_method))
@ -1038,7 +1038,7 @@ C2V_VMENTRY_NULL(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject
if (jap.return_type() == T_VOID) { if (jap.return_type() == T_VOID) {
return NULL; return NULL;
} else if (is_reference_type(jap.return_type())) { } else if (is_reference_type(jap.return_type())) {
return JNIHandles::make_local((oop) result.get_jobject()); return JNIHandles::make_local(THREAD, (oop) result.get_jobject());
} else { } else {
jvalue *value = (jvalue *) result.get_value_addr(); jvalue *value = (jvalue *) result.get_value_addr();
// Narrow the value down if required (Important on big endian machines) // Narrow the value down if required (Important on big endian machines)
@ -2314,7 +2314,7 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas
} }
typeArrayOop info_oop = oopFactory::new_longArray(4, CHECK_0); typeArrayOop info_oop = oopFactory::new_longArray(4, CHECK_0);
jlongArray info = (jlongArray) JNIHandles::make_local(info_oop); jlongArray info = (jlongArray) JNIHandles::make_local(THREAD, info_oop);
runtime->init_JavaVM_info(info, JVMCI_CHECK_0); runtime->init_JavaVM_info(info, JVMCI_CHECK_0);
return info; return info;
} }
@ -2565,7 +2565,7 @@ C2V_VMENTRY_NULL(jobject, asReflectionField, (JNIEnv* env, jobject, jobject jvmc
} }
fieldDescriptor fd(iklass, index); fieldDescriptor fd(iklass, index);
oop reflected = Reflection::new_field(&fd, CHECK_NULL); oop reflected = Reflection::new_field(&fd, CHECK_NULL);
return JNIHandles::make_local(env, reflected); return JNIHandles::make_local(THREAD, reflected);
} }
C2V_VMENTRY_NULL(jobjectArray, getFailedSpeculations, (JNIEnv* env, jobject, jlong failed_speculations_address, jobjectArray current)) C2V_VMENTRY_NULL(jobjectArray, getFailedSpeculations, (JNIEnv* env, jobject, jlong failed_speculations_address, jobjectArray current))

@ -672,6 +672,7 @@ void JVMCINMethodData::set_nmethod_mirror(nmethod* nm, oop new_mirror) {
// Since we've patched some oops in the nmethod, // Since we've patched some oops in the nmethod,
// (re)register it with the heap. // (re)register it with the heap.
MutexLocker ml(CodeCache_lock, Mutex::_no_safepoint_check_flag);
Universe::heap()->register_nmethod(nm); Universe::heap()->register_nmethod(nm);
} }
@ -800,7 +801,7 @@ JNIEnv* JVMCIRuntime::init_shared_library_javavm() {
JNI_CreateJavaVM = CAST_TO_FN_PTR(JNI_CreateJavaVM_t, os::dll_lookup(sl_handle, "JNI_CreateJavaVM")); JNI_CreateJavaVM = CAST_TO_FN_PTR(JNI_CreateJavaVM_t, os::dll_lookup(sl_handle, "JNI_CreateJavaVM"));
if (JNI_CreateJavaVM == NULL) { if (JNI_CreateJavaVM == NULL) {
vm_exit_during_initialization("Unable to find JNI_CreateJavaVM", sl_path); fatal("Unable to find JNI_CreateJavaVM in %s", sl_path);
} }
ResourceMark rm; ResourceMark rm;
@ -835,7 +836,7 @@ JNIEnv* JVMCIRuntime::init_shared_library_javavm() {
JVMCI_event_1("created JavaVM[%ld]@" PTR_FORMAT " for JVMCI runtime %d", javaVM_id, p2i(javaVM), _id); JVMCI_event_1("created JavaVM[%ld]@" PTR_FORMAT " for JVMCI runtime %d", javaVM_id, p2i(javaVM), _id);
return env; return env;
} else { } else {
vm_exit_during_initialization(err_msg("JNI_CreateJavaVM failed with return value %d", result), sl_path); fatal("JNI_CreateJavaVM failed with return value %d", result);
} }
} }
return NULL; return NULL;

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 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
@ -22,23 +22,16 @@
* *
*/ */
#include "precompiled.hpp" #ifndef SHARE_MEMORY_ALLSTATIC_HPP
#include "memory/allocation.hpp" #define SHARE_MEMORY_ALLSTATIC_HPP
#include "metaprogramming/integralConstant.hpp"
#include "metaprogramming/isRegisteredEnum.hpp"
#include "unittest.hpp" // Base class for classes used as namespaces. HotSpot style prefers
// using classes for grouping. Deriving from this class indicates the
struct IsRegisteredEnumTest : AllStatic { // derived class is intended to be a namespace, with no instances ever
enum A { A_x, A_y, A_z }; // created.
enum B { B_x, B_y, B_z }; struct AllStatic {
AllStatic() = delete;
~AllStatic() = delete;
}; };
typedef IsRegisteredEnumTest::A A; #endif // SHARE_MEMORY_ALLSTATIC_HPP
typedef IsRegisteredEnumTest::B B;
template<> struct IsRegisteredEnum<A> : public TrueType {};
STATIC_ASSERT(!IsRegisteredEnum<int>::value);
STATIC_ASSERT(IsRegisteredEnum<A>::value);
STATIC_ASSERT(!IsRegisteredEnum<B>::value);

@ -25,6 +25,7 @@
#ifndef SHARE_MEMORY_ALLOCATION_HPP #ifndef SHARE_MEMORY_ALLOCATION_HPP
#define SHARE_MEMORY_ALLOCATION_HPP #define SHARE_MEMORY_ALLOCATION_HPP
#include "memory/allStatic.hpp"
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
@ -349,13 +350,6 @@ class MetaspaceObj {
class Arena; class Arena;
class AllStatic {
public:
AllStatic() { ShouldNotCallThis(); }
~AllStatic() { ShouldNotCallThis(); }
};
extern char* resource_allocate_bytes(size_t size, extern char* resource_allocate_bytes(size_t size,
AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
extern char* resource_allocate_bytes(Thread* thread, size_t size, extern char* resource_allocate_bytes(Thread* thread, size_t size,

@ -60,6 +60,7 @@
#include "oops/instanceRefKlass.hpp" #include "oops/instanceRefKlass.hpp"
#include "oops/objArrayOop.inline.hpp" #include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "oops/oopHandle.inline.hpp"
#include "oops/typeArrayKlass.hpp" #include "oops/typeArrayKlass.hpp"
#include "prims/resolvedMethodTable.hpp" #include "prims/resolvedMethodTable.hpp"
#include "runtime/arguments.hpp" #include "runtime/arguments.hpp"
@ -106,35 +107,46 @@ PRIMITIVE_MIRRORS_DO(DEFINE_PRIMITIVE_MIRROR)
Klass* Universe::_typeArrayKlassObjs[T_LONG+1] = { NULL /*, NULL...*/ }; Klass* Universe::_typeArrayKlassObjs[T_LONG+1] = { NULL /*, NULL...*/ };
Klass* Universe::_objectArrayKlassObj = NULL; Klass* Universe::_objectArrayKlassObj = NULL;
oop Universe::_mirrors[T_VOID+1] = { NULL /*, NULL...*/ }; oop Universe::_mirrors[T_VOID+1] = { NULL /*, NULL...*/ };
oop Universe::_main_thread_group = NULL;
oop Universe::_system_thread_group = NULL; OopHandle Universe::_main_thread_group;
objArrayOop Universe::_the_empty_class_klass_array = NULL; OopHandle Universe::_system_thread_group;
OopHandle Universe::_the_empty_class_array;
OopHandle Universe::_the_null_string;
OopHandle Universe::_the_min_jint_string;
OopHandle Universe::_the_null_sentinel;
// _out_of_memory_errors is an objArray
enum OutOfMemoryInstance { _oom_java_heap,
_oom_c_heap,
_oom_metaspace,
_oom_class_metaspace,
_oom_array_size,
_oom_gc_overhead_limit,
_oom_realloc_objects,
_oom_retry,
_oom_count };
OopHandle Universe::_out_of_memory_errors;
OopHandle Universe::_delayed_stack_overflow_error_message;
OopHandle Universe::_preallocated_out_of_memory_error_array;
volatile jint Universe::_preallocated_out_of_memory_error_avail_count = 0;
OopHandle Universe::_null_ptr_exception_instance;
OopHandle Universe::_arithmetic_exception_instance;
OopHandle Universe::_virtual_machine_error_instance;
oop Universe::_reference_pending_list = NULL;
Array<Klass*>* Universe::_the_array_interfaces_array = NULL; Array<Klass*>* Universe::_the_array_interfaces_array = NULL;
oop Universe::_the_null_sentinel = NULL;
oop Universe::_the_null_string = NULL;
oop Universe::_the_min_jint_string = NULL;
LatestMethodCache* Universe::_finalizer_register_cache = NULL; LatestMethodCache* Universe::_finalizer_register_cache = NULL;
LatestMethodCache* Universe::_loader_addClass_cache = NULL; LatestMethodCache* Universe::_loader_addClass_cache = NULL;
LatestMethodCache* Universe::_throw_illegal_access_error_cache = NULL; LatestMethodCache* Universe::_throw_illegal_access_error_cache = NULL;
LatestMethodCache* Universe::_throw_no_such_method_error_cache = NULL; LatestMethodCache* Universe::_throw_no_such_method_error_cache = NULL;
LatestMethodCache* Universe::_do_stack_walk_cache = NULL; LatestMethodCache* Universe::_do_stack_walk_cache = NULL;
oop Universe::_out_of_memory_error_java_heap = NULL;
oop Universe::_out_of_memory_error_metaspace = NULL;
oop Universe::_out_of_memory_error_class_metaspace = NULL;
oop Universe::_out_of_memory_error_array_size = NULL;
oop Universe::_out_of_memory_error_gc_overhead_limit = NULL;
oop Universe::_out_of_memory_error_realloc_objects = NULL;
oop Universe::_out_of_memory_error_retry = NULL;
oop Universe::_delayed_stack_overflow_error_message = NULL;
objArrayOop Universe::_preallocated_out_of_memory_error_array = NULL;
volatile jint Universe::_preallocated_out_of_memory_error_avail_count = 0;
bool Universe::_verify_in_progress = false; bool Universe::_verify_in_progress = false;
long Universe::verify_flags = Universe::Verify_All; long Universe::verify_flags = Universe::Verify_All;
oop Universe::_null_ptr_exception_instance = NULL;
oop Universe::_arithmetic_exception_instance = NULL;
oop Universe::_virtual_machine_error_instance = NULL;
oop Universe::_vm_exception = NULL;
oop Universe::_reference_pending_list = NULL;
Array<int>* Universe::_the_empty_int_array = NULL; Array<int>* Universe::_the_empty_int_array = NULL;
Array<u2>* Universe::_the_empty_short_array = NULL; Array<u2>* Universe::_the_empty_short_array = NULL;
@ -143,7 +155,7 @@ Array<InstanceKlass*>* Universe::_the_empty_instance_klass_array = NULL;
Array<Method*>* Universe::_the_empty_method_array = NULL; Array<Method*>* Universe::_the_empty_method_array = NULL;
// These variables are guarded by FullGCALot_lock. // These variables are guarded by FullGCALot_lock.
debug_only(objArrayOop Universe::_fullgc_alot_dummy_array = NULL;) debug_only(OopHandle Universe::_fullgc_alot_dummy_array;)
debug_only(int Universe::_fullgc_alot_dummy_next = 0;) debug_only(int Universe::_fullgc_alot_dummy_next = 0;)
// Heap // Heap
@ -166,6 +178,25 @@ OopStorage* Universe::_vm_global = NULL;
CollectedHeap* Universe::_collectedHeap = NULL; CollectedHeap* Universe::_collectedHeap = NULL;
objArrayOop Universe::the_empty_class_array () {
return (objArrayOop)_the_empty_class_array.resolve();
}
oop Universe::main_thread_group() { return _main_thread_group.resolve(); }
void Universe::set_main_thread_group(oop group) { _main_thread_group = OopHandle(vm_global(), group); }
oop Universe::system_thread_group() { return _system_thread_group.resolve(); }
void Universe::set_system_thread_group(oop group) { _system_thread_group = OopHandle(vm_global(), group); }
oop Universe::the_null_string() { return _the_null_string.resolve(); }
oop Universe::the_min_jint_string() { return _the_min_jint_string.resolve(); }
oop Universe::null_ptr_exception_instance() { return _null_ptr_exception_instance.resolve(); }
oop Universe::arithmetic_exception_instance() { return _arithmetic_exception_instance.resolve(); }
oop Universe::virtual_machine_error_instance() { return _virtual_machine_error_instance.resolve(); }
oop Universe::the_null_sentinel() { return _the_null_sentinel.resolve(); }
void Universe::basic_type_classes_do(void f(Klass*)) { void Universe::basic_type_classes_do(void f(Klass*)) {
for (int i = T_BOOLEAN; i < T_LONG+1; i++) { for (int i = T_BOOLEAN; i < T_LONG+1; i++) {
f(_typeArrayKlassObjs[i]); f(_typeArrayKlassObjs[i]);
@ -185,31 +216,11 @@ void Universe::oops_do(OopClosure* f) {
PRIMITIVE_MIRRORS_DO(DO_PRIMITIVE_MIRROR); PRIMITIVE_MIRRORS_DO(DO_PRIMITIVE_MIRROR);
for (int i = T_BOOLEAN; i < T_VOID+1; i++) { for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
f->do_oop((oop*) &_mirrors[i]); f->do_oop(&_mirrors[i]);
} }
assert(_mirrors[0] == NULL && _mirrors[T_BOOLEAN - 1] == NULL, "checking"); assert(_mirrors[0] == NULL && _mirrors[T_BOOLEAN - 1] == NULL, "checking");
f->do_oop((oop*)&_the_empty_class_klass_array); f->do_oop(&_reference_pending_list);
f->do_oop((oop*)&_the_null_sentinel);
f->do_oop((oop*)&_the_null_string);
f->do_oop((oop*)&_the_min_jint_string);
f->do_oop((oop*)&_out_of_memory_error_java_heap);
f->do_oop((oop*)&_out_of_memory_error_metaspace);
f->do_oop((oop*)&_out_of_memory_error_class_metaspace);
f->do_oop((oop*)&_out_of_memory_error_array_size);
f->do_oop((oop*)&_out_of_memory_error_gc_overhead_limit);
f->do_oop((oop*)&_out_of_memory_error_realloc_objects);
f->do_oop((oop*)&_out_of_memory_error_retry);
f->do_oop((oop*)&_delayed_stack_overflow_error_message);
f->do_oop((oop*)&_preallocated_out_of_memory_error_array);
f->do_oop((oop*)&_null_ptr_exception_instance);
f->do_oop((oop*)&_arithmetic_exception_instance);
f->do_oop((oop*)&_virtual_machine_error_instance);
f->do_oop((oop*)&_main_thread_group);
f->do_oop((oop*)&_system_thread_group);
f->do_oop((oop*)&_vm_exception);
f->do_oop((oop*)&_reference_pending_list);
debug_only(f->do_oop((oop*)&_fullgc_alot_dummy_array);)
ThreadsSMRSupport::exiting_threads_oops_do(f); ThreadsSMRSupport::exiting_threads_oops_do(f);
} }
@ -331,10 +342,12 @@ void Universe::genesis(TRAPS) {
SystemDictionary::initialize(CHECK); SystemDictionary::initialize(CHECK);
Klass* ok = SystemDictionary::Object_klass(); // Create string constants
oop s = StringTable::intern("null", CHECK);
_the_null_string = OopHandle(vm_global(), s);
s = StringTable::intern("-2147483648", CHECK);
_the_min_jint_string = OopHandle(vm_global(), s);
_the_null_string = StringTable::intern("null", CHECK);
_the_min_jint_string = StringTable::intern("-2147483648", CHECK);
#if INCLUDE_CDS #if INCLUDE_CDS
if (UseSharedSpaces) { if (UseSharedSpaces) {
@ -363,7 +376,7 @@ void Universe::genesis(TRAPS) {
{ {
Handle tns = java_lang_String::create_from_str("<null_sentinel>", CHECK); Handle tns = java_lang_String::create_from_str("<null_sentinel>", CHECK);
_the_null_sentinel = tns(); _the_null_sentinel = OopHandle(vm_global(), tns());
} }
// Maybe this could be lifted up now that object array can be initialized // Maybe this could be lifted up now that object array can be initialized
@ -398,7 +411,6 @@ void Universe::genesis(TRAPS) {
// But we can't allocate directly in the old generation, // But we can't allocate directly in the old generation,
// so we allocate wherever, and hope that the first collection // so we allocate wherever, and hope that the first collection
// moves these objects to the bottom of the old generation. // moves these objects to the bottom of the old generation.
// We can allocate directly in the permanent generation, so we do.
int size = FullGCALotDummies * 2; int size = FullGCALotDummies * 2;
objArrayOop naked_array = oopFactory::new_objArray(SystemDictionary::Object_klass(), size, CHECK); objArrayOop naked_array = oopFactory::new_objArray(SystemDictionary::Object_klass(), size, CHECK);
@ -414,11 +426,11 @@ void Universe::genesis(TRAPS) {
// If we had a race to here, the other dummy_array instances // If we had a race to here, the other dummy_array instances
// and their elements just get dropped on the floor, which is fine. // and their elements just get dropped on the floor, which is fine.
MutexLocker ml(THREAD, FullGCALot_lock); MutexLocker ml(THREAD, FullGCALot_lock);
if (_fullgc_alot_dummy_array == NULL) { if (_fullgc_alot_dummy_array.is_empty()) {
_fullgc_alot_dummy_array = dummy_array(); _fullgc_alot_dummy_array = OopHandle(vm_global(), dummy_array());
} }
} }
assert(i == _fullgc_alot_dummy_array->length(), "just checking"); assert(i == ((objArrayOop)_fullgc_alot_dummy_array.resolve())->length(), "just checking");
} }
#endif #endif
} }
@ -509,9 +521,9 @@ oop Universe::reference_pending_list() {
return _reference_pending_list; return _reference_pending_list;
} }
void Universe::set_reference_pending_list(oop list) { void Universe::clear_reference_pending_list() {
assert_pll_ownership(); assert_pll_ownership();
_reference_pending_list = list; _reference_pending_list = NULL;
} }
bool Universe::has_reference_pending_list() { bool Universe::has_reference_pending_list() {
@ -563,6 +575,45 @@ bool Universe::on_page_boundary(void* addr) {
return is_aligned(addr, os::vm_page_size()); return is_aligned(addr, os::vm_page_size());
} }
// the array of preallocated errors with backtraces
objArrayOop Universe::preallocated_out_of_memory_errors() {
return (objArrayOop)_preallocated_out_of_memory_error_array.resolve();
}
objArrayOop Universe::out_of_memory_errors() { return (objArrayOop)_out_of_memory_errors.resolve(); }
oop Universe::out_of_memory_error_java_heap() {
return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_java_heap));
}
oop Universe::out_of_memory_error_c_heap() {
return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_c_heap));
}
oop Universe::out_of_memory_error_metaspace() {
return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_metaspace));
}
oop Universe::out_of_memory_error_class_metaspace() {
return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_class_metaspace));
}
oop Universe::out_of_memory_error_array_size() {
return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_array_size));
}
oop Universe::out_of_memory_error_gc_overhead_limit() {
return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_gc_overhead_limit));
}
oop Universe::out_of_memory_error_realloc_objects() {
return gen_out_of_memory_error(out_of_memory_errors()->obj_at(_oom_realloc_objects));
}
// Throw default _out_of_memory_error_retry object as it will never propagate out of the VM
oop Universe::out_of_memory_error_retry() { return out_of_memory_errors()->obj_at(_oom_retry); }
oop Universe::delayed_stack_overflow_error_message() { return _delayed_stack_overflow_error_message.resolve(); }
bool Universe::should_fill_in_stack_trace(Handle throwable) { bool Universe::should_fill_in_stack_trace(Handle throwable) {
// never attempt to fill in the stack trace of preallocated errors that do not have // never attempt to fill in the stack trace of preallocated errors that do not have
@ -570,13 +621,13 @@ bool Universe::should_fill_in_stack_trace(Handle throwable) {
// preallocated errors with backtrace have been consumed. Also need to avoid // preallocated errors with backtrace have been consumed. Also need to avoid
// a potential loop which could happen if an out of memory occurs when attempting // a potential loop which could happen if an out of memory occurs when attempting
// to allocate the backtrace. // to allocate the backtrace.
return ((throwable() != Universe::_out_of_memory_error_java_heap) && objArrayOop preallocated_oom = out_of_memory_errors();
(throwable() != Universe::_out_of_memory_error_metaspace) && for (int i = 0; i < _oom_count; i++) {
(throwable() != Universe::_out_of_memory_error_class_metaspace) && if (throwable() == preallocated_oom->obj_at(i)) {
(throwable() != Universe::_out_of_memory_error_array_size) && return false;
(throwable() != Universe::_out_of_memory_error_gc_overhead_limit) && }
(throwable() != Universe::_out_of_memory_error_realloc_objects) && }
(throwable() != Universe::_out_of_memory_error_retry)); return true;
} }
@ -619,6 +670,57 @@ oop Universe::gen_out_of_memory_error(oop default_err) {
} }
} }
// Setup preallocated OutOfMemoryError errors
void Universe::create_preallocated_out_of_memory_errors(TRAPS) {
InstanceKlass* ik = SystemDictionary::OutOfMemoryError_klass();
objArrayOop oa = oopFactory::new_objArray(ik, _oom_count, CHECK);
objArrayHandle oom_array(THREAD, oa);
for (int i = 0; i < _oom_count; i++) {
oop oom_obj = ik->allocate_instance(CHECK);
oom_array->obj_at_put(i, oom_obj);
}
_out_of_memory_errors = OopHandle(vm_global(), oom_array());
Handle msg = java_lang_String::create_from_str("Java heap space", CHECK);
java_lang_Throwable::set_message(oom_array->obj_at(_oom_java_heap), msg());
msg = java_lang_String::create_from_str("C heap space", CHECK);
java_lang_Throwable::set_message(oom_array->obj_at(_oom_c_heap), msg());
msg = java_lang_String::create_from_str("Metaspace", CHECK);
java_lang_Throwable::set_message(oom_array->obj_at(_oom_metaspace), msg());
msg = java_lang_String::create_from_str("Compressed class space", CHECK);
java_lang_Throwable::set_message(oom_array->obj_at(_oom_class_metaspace), msg());
msg = java_lang_String::create_from_str("Requested array size exceeds VM limit", CHECK);
java_lang_Throwable::set_message(oom_array->obj_at(_oom_array_size), msg());
msg = java_lang_String::create_from_str("GC overhead limit exceeded", CHECK);
java_lang_Throwable::set_message(oom_array->obj_at(_oom_gc_overhead_limit), msg());
msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK);
java_lang_Throwable::set_message(oom_array->obj_at(_oom_realloc_objects), msg());
msg = java_lang_String::create_from_str("Java heap space: failed retryable allocation", CHECK);
java_lang_Throwable::set_message(oom_array->obj_at(_oom_retry), msg());
// Setup the array of errors that have preallocated backtrace
int len = (StackTraceInThrowable) ? (int)PreallocatedOutOfMemoryErrorCount : 0;
objArrayOop instance = oopFactory::new_objArray(ik, len, CHECK);
_preallocated_out_of_memory_error_array = OopHandle(vm_global(), instance);
objArrayHandle preallocated_oom_array(THREAD, instance);
for (int i=0; i<len; i++) {
oop err = ik->allocate_instance(CHECK);
Handle err_h(THREAD, err);
java_lang_Throwable::allocate_backtrace(err_h, CHECK);
preallocated_oom_array->obj_at_put(i, err_h());
}
_preallocated_out_of_memory_error_avail_count = (jint)len;
}
intptr_t Universe::_non_oop_bits = 0; intptr_t Universe::_non_oop_bits = 0;
void* Universe::non_oop_word() { void* Universe::non_oop_word() {
@ -882,35 +984,33 @@ bool universe_post_init() {
} }
HandleMark hm(THREAD); HandleMark hm(THREAD);
// Setup preallocated empty java.lang.Class array // Setup preallocated empty java.lang.Class array for Method reflection.
Universe::_the_empty_class_klass_array = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_false);
objArrayOop the_empty_class_array = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_false);
Universe::_the_empty_class_array = OopHandle(Universe::vm_global(), the_empty_class_array);
// Setup preallocated OutOfMemoryError errors // Setup preallocated OutOfMemoryError errors
Klass* k = SystemDictionary::OutOfMemoryError_klass(); Universe::create_preallocated_out_of_memory_errors(CHECK_false);
InstanceKlass* ik = InstanceKlass::cast(k);
Universe::_out_of_memory_error_java_heap = ik->allocate_instance(CHECK_false);
Universe::_out_of_memory_error_metaspace = ik->allocate_instance(CHECK_false);
Universe::_out_of_memory_error_class_metaspace = ik->allocate_instance(CHECK_false);
Universe::_out_of_memory_error_array_size = ik->allocate_instance(CHECK_false);
Universe::_out_of_memory_error_gc_overhead_limit =
ik->allocate_instance(CHECK_false);
Universe::_out_of_memory_error_realloc_objects = ik->allocate_instance(CHECK_false);
Universe::_out_of_memory_error_retry = ik->allocate_instance(CHECK_false);
oop instance;
// Setup preallocated cause message for delayed StackOverflowError // Setup preallocated cause message for delayed StackOverflowError
if (StackReservedPages > 0) { if (StackReservedPages > 0) {
Universe::_delayed_stack_overflow_error_message = instance = java_lang_String::create_oop_from_str("Delayed StackOverflowError due to ReservedStackAccess annotated method", CHECK_false);
java_lang_String::create_oop_from_str("Delayed StackOverflowError due to ReservedStackAccess annotated method", CHECK_false); Universe::_delayed_stack_overflow_error_message = OopHandle(Universe::vm_global(), instance);
} }
// Setup preallocated NullPointerException // Setup preallocated NullPointerException
// (this is currently used for a cheap & dirty solution in compiler exception handling) // (this is currently used for a cheap & dirty solution in compiler exception handling)
k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_NullPointerException(), true, CHECK_false); Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_NullPointerException(), true, CHECK_false);
Universe::_null_ptr_exception_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false); instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
Universe::_null_ptr_exception_instance = OopHandle(Universe::vm_global(), instance);
// Setup preallocated ArithmeticException // Setup preallocated ArithmeticException
// (this is currently used for a cheap & dirty solution in compiler exception handling) // (this is currently used for a cheap & dirty solution in compiler exception handling)
k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ArithmeticException(), true, CHECK_false); k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ArithmeticException(), true, CHECK_false);
Universe::_arithmetic_exception_instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false); instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
Universe::_arithmetic_exception_instance = OopHandle(Universe::vm_global(), instance);
// Virtual Machine Error for when we get into a situation we can't resolve // Virtual Machine Error for when we get into a situation we can't resolve
k = SystemDictionary::VirtualMachineError_klass(); k = SystemDictionary::VirtualMachineError_klass();
bool linked = InstanceKlass::cast(k)->link_class_or_fail(CHECK_false); bool linked = InstanceKlass::cast(k)->link_class_or_fail(CHECK_false);
@ -918,48 +1018,11 @@ bool universe_post_init() {
tty->print_cr("Unable to link/verify VirtualMachineError class"); tty->print_cr("Unable to link/verify VirtualMachineError class");
return false; // initialization failed return false; // initialization failed
} }
Universe::_virtual_machine_error_instance = instance = InstanceKlass::cast(k)->allocate_instance(CHECK_false);
InstanceKlass::cast(k)->allocate_instance(CHECK_false); Universe::_virtual_machine_error_instance = OopHandle(Universe::vm_global(), instance);
Universe::_vm_exception = InstanceKlass::cast(k)->allocate_instance(CHECK_false); Handle msg = java_lang_String::create_from_str("/ by zero", CHECK_false);
java_lang_Throwable::set_message(Universe::arithmetic_exception_instance(), msg());
Handle msg = java_lang_String::create_from_str("Java heap space", CHECK_false);
java_lang_Throwable::set_message(Universe::_out_of_memory_error_java_heap, msg());
msg = java_lang_String::create_from_str("Metaspace", CHECK_false);
java_lang_Throwable::set_message(Universe::_out_of_memory_error_metaspace, msg());
msg = java_lang_String::create_from_str("Compressed class space", CHECK_false);
java_lang_Throwable::set_message(Universe::_out_of_memory_error_class_metaspace, msg());
msg = java_lang_String::create_from_str("Requested array size exceeds VM limit", CHECK_false);
java_lang_Throwable::set_message(Universe::_out_of_memory_error_array_size, msg());
msg = java_lang_String::create_from_str("GC overhead limit exceeded", CHECK_false);
java_lang_Throwable::set_message(Universe::_out_of_memory_error_gc_overhead_limit, msg());
msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK_false);
java_lang_Throwable::set_message(Universe::_out_of_memory_error_realloc_objects, msg());
msg = java_lang_String::create_from_str("Java heap space: failed retryable allocation", CHECK_false);
java_lang_Throwable::set_message(Universe::_out_of_memory_error_retry, msg());
msg = java_lang_String::create_from_str("/ by zero", CHECK_false);
java_lang_Throwable::set_message(Universe::_arithmetic_exception_instance, msg());
// Setup the array of errors that have preallocated backtrace
k = Universe::_out_of_memory_error_java_heap->klass();
assert(k->name() == vmSymbols::java_lang_OutOfMemoryError(), "should be out of memory error");
ik = InstanceKlass::cast(k);
int len = (StackTraceInThrowable) ? (int)PreallocatedOutOfMemoryErrorCount : 0;
Universe::_preallocated_out_of_memory_error_array = oopFactory::new_objArray(ik, len, CHECK_false);
for (int i=0; i<len; i++) {
oop err = ik->allocate_instance(CHECK_false);
Handle err_h = Handle(THREAD, err);
java_lang_Throwable::allocate_backtrace(err_h, CHECK_false);
Universe::preallocated_out_of_memory_errors()->obj_at_put(i, err_h());
}
Universe::_preallocated_out_of_memory_error_avail_count = (jint)len;
Universe::initialize_known_methods(CHECK_false); Universe::initialize_known_methods(CHECK_false);
@ -1225,18 +1288,16 @@ Method* LatestMethodCache::get_method() {
// Release dummy object(s) at bottom of heap // Release dummy object(s) at bottom of heap
bool Universe::release_fullgc_alot_dummy() { bool Universe::release_fullgc_alot_dummy() {
MutexLocker ml(FullGCALot_lock); MutexLocker ml(FullGCALot_lock);
if (_fullgc_alot_dummy_array != NULL) { objArrayOop fullgc_alot_dummy_array = (objArrayOop)_fullgc_alot_dummy_array.resolve();
if (_fullgc_alot_dummy_next >= _fullgc_alot_dummy_array->length()) { if (fullgc_alot_dummy_array != NULL) {
if (_fullgc_alot_dummy_next >= fullgc_alot_dummy_array->length()) {
// No more dummies to release, release entire array instead // No more dummies to release, release entire array instead
_fullgc_alot_dummy_array = NULL; _fullgc_alot_dummy_array.release(Universe::vm_global());
return false; return false;
} }
// Release dummy at bottom of old generation // Release dummy at bottom of old generation
_fullgc_alot_dummy_array->obj_at_put(_fullgc_alot_dummy_next++, NULL); fullgc_alot_dummy_array->obj_at_put(_fullgc_alot_dummy_next++, NULL);
// Release dummy at bottom of permanent generation
_fullgc_alot_dummy_array->obj_at_put(_fullgc_alot_dummy_next++, NULL);
} }
return true; return true;
} }

@ -27,6 +27,7 @@
#include "gc/shared/verifyOption.hpp" #include "gc/shared/verifyOption.hpp"
#include "oops/array.hpp" #include "oops/array.hpp"
#include "oops/oopHandle.hpp"
#include "runtime/handles.hpp" #include "runtime/handles.hpp"
#include "utilities/growableArray.hpp" #include "utilities/growableArray.hpp"
@ -106,31 +107,27 @@ class Universe: AllStatic {
static oop _short_mirror; static oop _short_mirror;
static oop _void_mirror; static oop _void_mirror;
static oop _main_thread_group; // Reference to the main thread group object static OopHandle _main_thread_group; // Reference to the main thread group object
static oop _system_thread_group; // Reference to the system thread group object static OopHandle _system_thread_group; // Reference to the system thread group object
static OopHandle _the_empty_class_array; // Canonicalized obj array of type java.lang.Class
static OopHandle _the_null_string; // A cache of "null" as a Java string
static OopHandle _the_min_jint_string; // A cache of "-2147483648" as a Java string
static OopHandle _the_null_sentinel; // A unique object pointer unused except as a sentinel for null.
// preallocated error objects (no backtrace)
static OopHandle _out_of_memory_errors;
// preallocated cause message for delayed StackOverflowError
static OopHandle _delayed_stack_overflow_error_message;
static objArrayOop _the_empty_class_klass_array; // Canonicalized obj array of type java.lang.Class
static oop _the_null_sentinel; // A unique object pointer unused except as a sentinel for null.
static oop _the_null_string; // A cache of "null" as a Java string
static oop _the_min_jint_string; // A cache of "-2147483648" as a Java string
static LatestMethodCache* _finalizer_register_cache; // static method for registering finalizable objects static LatestMethodCache* _finalizer_register_cache; // static method for registering finalizable objects
static LatestMethodCache* _loader_addClass_cache; // method for registering loaded classes in class loader vector static LatestMethodCache* _loader_addClass_cache; // method for registering loaded classes in class loader vector
static LatestMethodCache* _throw_illegal_access_error_cache; // Unsafe.throwIllegalAccessError() method static LatestMethodCache* _throw_illegal_access_error_cache; // Unsafe.throwIllegalAccessError() method
static LatestMethodCache* _throw_no_such_method_error_cache; // Unsafe.throwNoSuchMethodError() method static LatestMethodCache* _throw_no_such_method_error_cache; // Unsafe.throwNoSuchMethodError() method
static LatestMethodCache* _do_stack_walk_cache; // method for stack walker callback static LatestMethodCache* _do_stack_walk_cache; // method for stack walker callback
// preallocated error objects (no backtrace)
static oop _out_of_memory_error_java_heap;
static oop _out_of_memory_error_metaspace;
static oop _out_of_memory_error_class_metaspace;
static oop _out_of_memory_error_array_size;
static oop _out_of_memory_error_gc_overhead_limit;
static oop _out_of_memory_error_realloc_objects;
static oop _out_of_memory_error_retry;
// preallocated cause message for delayed StackOverflowError
static oop _delayed_stack_overflow_error_message;
static Array<int>* _the_empty_int_array; // Canonicalized int array static Array<int>* _the_empty_int_array; // Canonicalized int array
static Array<u2>* _the_empty_short_array; // Canonicalized short array static Array<u2>* _the_empty_short_array; // Canonicalized short array
static Array<Klass*>* _the_empty_klass_array; // Canonicalized klass array static Array<Klass*>* _the_empty_klass_array; // Canonicalized klass array
@ -140,17 +137,14 @@ class Universe: AllStatic {
static Array<Klass*>* _the_array_interfaces_array; static Array<Klass*>* _the_array_interfaces_array;
// array of preallocated error objects with backtrace // array of preallocated error objects with backtrace
static objArrayOop _preallocated_out_of_memory_error_array; static OopHandle _preallocated_out_of_memory_error_array;
// number of preallocated error objects available for use // number of preallocated error objects available for use
static volatile jint _preallocated_out_of_memory_error_avail_count; static volatile jint _preallocated_out_of_memory_error_avail_count;
static oop _null_ptr_exception_instance; // preallocated exception object static OopHandle _null_ptr_exception_instance; // preallocated exception object
static oop _arithmetic_exception_instance; // preallocated exception object static OopHandle _arithmetic_exception_instance; // preallocated exception object
static oop _virtual_machine_error_instance; // preallocated exception object static OopHandle _virtual_machine_error_instance; // preallocated exception object
// The object used as an exception dummy when exceptions are thrown for
// the vm thread.
static oop _vm_exception;
// References waiting to be transferred to the ReferenceHandler // References waiting to be transferred to the ReferenceHandler
static oop _reference_pending_list; static oop _reference_pending_list;
@ -161,8 +155,7 @@ class Universe: AllStatic {
static intptr_t _non_oop_bits; static intptr_t _non_oop_bits;
// array of dummy objects used with +FullGCAlot // array of dummy objects used with +FullGCAlot
debug_only(static objArrayOop _fullgc_alot_dummy_array;) debug_only(static OopHandle _fullgc_alot_dummy_array;)
// index of next entry to clear
debug_only(static int _fullgc_alot_dummy_next;) debug_only(static int _fullgc_alot_dummy_next;)
// Compiler/dispatch support // Compiler/dispatch support
@ -174,8 +167,9 @@ class Universe: AllStatic {
static bool _fully_initialized; // true after universe_init and initialize_vtables called static bool _fully_initialized; // true after universe_init and initialize_vtables called
// the array of preallocated errors with backtraces // the array of preallocated errors with backtraces
static objArrayOop preallocated_out_of_memory_errors() { return _preallocated_out_of_memory_error_array; } static objArrayOop preallocated_out_of_memory_errors();
static objArrayOop out_of_memory_errors();
// generate an out of memory error; if possible using an error with preallocated backtrace; // generate an out of memory error; if possible using an error with preallocated backtrace;
// otherwise return the given default error. // otherwise return the given default error.
static oop gen_out_of_memory_error(oop default_err); static oop gen_out_of_memory_error(oop default_err);
@ -265,17 +259,23 @@ class Universe: AllStatic {
assert((uint)t < T_VOID+1, "range check"); assert((uint)t < T_VOID+1, "range check");
return check_mirror(_mirrors[t]); return check_mirror(_mirrors[t]);
} }
static oop main_thread_group() { return _main_thread_group; } static oop main_thread_group();
static void set_main_thread_group(oop group) { _main_thread_group = group;} static void set_main_thread_group(oop group);
static oop system_thread_group() { return _system_thread_group; } static oop system_thread_group();
static void set_system_thread_group(oop group) { _system_thread_group = group;} static void set_system_thread_group(oop group);
static objArrayOop the_empty_class_array ();
static oop the_null_string();
static oop the_min_jint_string();
static oop null_ptr_exception_instance();
static oop arithmetic_exception_instance();
static oop virtual_machine_error_instance();
static oop vm_exception() { return virtual_machine_error_instance(); }
static objArrayOop the_empty_class_klass_array () { return _the_empty_class_klass_array; }
static Array<Klass*>* the_array_interfaces_array() { return _the_array_interfaces_array; } static Array<Klass*>* the_array_interfaces_array() { return _the_array_interfaces_array; }
static oop the_null_string() { return _the_null_string; }
static oop the_min_jint_string() { return _the_min_jint_string; }
static Method* finalizer_register_method() { return _finalizer_register_cache->get_method(); } static Method* finalizer_register_method() { return _finalizer_register_cache->get_method(); }
static Method* loader_addClass_method() { return _loader_addClass_cache->get_method(); } static Method* loader_addClass_method() { return _loader_addClass_cache->get_method(); }
@ -284,16 +284,13 @@ class Universe: AllStatic {
static Method* do_stack_walk_method() { return _do_stack_walk_cache->get_method(); } static Method* do_stack_walk_method() { return _do_stack_walk_cache->get_method(); }
static oop the_null_sentinel() { return _the_null_sentinel; } static oop the_null_sentinel();
static address the_null_sentinel_addr() { return (address) &_the_null_sentinel; } static address the_null_sentinel_addr() { return (address) &_the_null_sentinel; }
// Function to initialize these // Function to initialize these
static void initialize_known_methods(TRAPS); static void initialize_known_methods(TRAPS);
static oop null_ptr_exception_instance() { return _null_ptr_exception_instance; } static void create_preallocated_out_of_memory_errors(TRAPS);
static oop arithmetic_exception_instance() { return _arithmetic_exception_instance; }
static oop virtual_machine_error_instance() { return _virtual_machine_error_instance; }
static oop vm_exception() { return _vm_exception; }
// Reference pending list manipulation. Access is protected by // Reference pending list manipulation. Access is protected by
// Heap_lock. The getter, setter and predicate require the caller // Heap_lock. The getter, setter and predicate require the caller
@ -302,7 +299,7 @@ class Universe: AllStatic {
// Heap_lock, so requires the lock is locked, but not necessarily by // Heap_lock, so requires the lock is locked, but not necessarily by
// the current thread. // the current thread.
static oop reference_pending_list(); static oop reference_pending_list();
static void set_reference_pending_list(oop list); static void clear_reference_pending_list();
static bool has_reference_pending_list(); static bool has_reference_pending_list();
static oop swap_reference_pending_list(oop list); static oop swap_reference_pending_list(oop list);
@ -315,15 +312,17 @@ class Universe: AllStatic {
// OutOfMemoryError support. Returns an error with the required message. The returned error // OutOfMemoryError support. Returns an error with the required message. The returned error
// may or may not have a backtrace. If error has a backtrace then the stack trace is already // may or may not have a backtrace. If error has a backtrace then the stack trace is already
// filled in. // filled in.
static oop out_of_memory_error_java_heap() { return gen_out_of_memory_error(_out_of_memory_error_java_heap); } static oop out_of_memory_error_java_heap();
static oop out_of_memory_error_metaspace() { return gen_out_of_memory_error(_out_of_memory_error_metaspace); } static oop out_of_memory_error_c_heap();
static oop out_of_memory_error_class_metaspace() { return gen_out_of_memory_error(_out_of_memory_error_class_metaspace); } static oop out_of_memory_error_metaspace();
static oop out_of_memory_error_array_size() { return gen_out_of_memory_error(_out_of_memory_error_array_size); } static oop out_of_memory_error_class_metaspace();
static oop out_of_memory_error_gc_overhead_limit() { return gen_out_of_memory_error(_out_of_memory_error_gc_overhead_limit); } static oop out_of_memory_error_array_size();
static oop out_of_memory_error_realloc_objects() { return gen_out_of_memory_error(_out_of_memory_error_realloc_objects); } static oop out_of_memory_error_gc_overhead_limit();
static oop out_of_memory_error_realloc_objects();
// Throw default _out_of_memory_error_retry object as it will never propagate out of the VM // Throw default _out_of_memory_error_retry object as it will never propagate out of the VM
static oop out_of_memory_error_retry() { return _out_of_memory_error_retry; } static oop out_of_memory_error_retry();
static oop delayed_stack_overflow_error_message() { return _delayed_stack_overflow_error_message; } static oop delayed_stack_overflow_error_message();
// The particular choice of collected heap. // The particular choice of collected heap.
static CollectedHeap* heap() { return _collectedHeap; } static CollectedHeap* heap() { return _collectedHeap; }

@ -1,40 +0,0 @@
/*
* Copyright (c) 2017, 2019, 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_METAPROGRAMMING_ISREGISTEREDENUM_HPP
#define SHARE_METAPROGRAMMING_ISREGISTEREDENUM_HPP
#include "metaprogramming/integralConstant.hpp"
// Recognize registered enum types.
// Registration is by specializing this trait.
//
// This is a manual stand-in for the C++11 std::is_enum<T> type trait.
// It's a lot of work to implement is_enum portably in C++98, so this
// manual approach is being taken for those enum types we need to
// distinguish.
template<typename T>
struct IsRegisteredEnum : public FalseType {};
#endif // SHARE_METAPROGRAMMING_ISREGISTEREDENUM_HPP

@ -30,8 +30,8 @@
#include "metaprogramming/integralConstant.hpp" #include "metaprogramming/integralConstant.hpp"
#include "metaprogramming/isFloatingPoint.hpp" #include "metaprogramming/isFloatingPoint.hpp"
#include "metaprogramming/isIntegral.hpp" #include "metaprogramming/isIntegral.hpp"
#include "metaprogramming/isRegisteredEnum.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
#include <type_traits>
class PrimitiveConversions : public AllStatic { class PrimitiveConversions : public AllStatic {
public: public:
@ -68,8 +68,8 @@ private:
// Return an object of type T with the same value representation as x. // Return an object of type T with the same value representation as x.
// //
// T and U must be of the same size. It is expected that one of T and // T and U must be of the same size. It is expected that one of T and
// U is an integral type, and the other is an integral type, a // U is an integral type, and the other is an integral type, an enum type,
// (registered) enum type, or a floating point type // or a floating point type.
// //
// This implementation uses the "union trick", which seems to be the // This implementation uses the "union trick", which seems to be the
// best of a bad set of options. Though technically undefined // best of a bad set of options. Though technically undefined
@ -122,7 +122,7 @@ template<typename T, typename U>
struct PrimitiveConversions::Cast< struct PrimitiveConversions::Cast<
T, U, true, T, U, true,
typename EnableIf<IsIntegral<T>::value && typename EnableIf<IsIntegral<T>::value &&
(IsRegisteredEnum<U>::value || (std::is_enum<U>::value ||
IsFloatingPoint<U>::value)>::type> IsFloatingPoint<U>::value)>::type>
{ {
T operator()(U x) const { return cast_using_union<T>(x); } T operator()(U x) const { return cast_using_union<T>(x); }
@ -133,7 +133,7 @@ template<typename T, typename U>
struct PrimitiveConversions::Cast< struct PrimitiveConversions::Cast<
T, U, true, T, U, true,
typename EnableIf<IsIntegral<U>::value && typename EnableIf<IsIntegral<U>::value &&
(IsRegisteredEnum<T>::value || (std::is_enum<T>::value ||
IsFloatingPoint<T>::value)>::type> IsFloatingPoint<T>::value)>::type>
{ {
T operator()(U x) const { return cast_using_union<T>(x); } T operator()(U x) const { return cast_using_union<T>(x); }

@ -53,7 +53,7 @@
void Klass::set_java_mirror(Handle m) { void Klass::set_java_mirror(Handle m) {
assert(!m.is_null(), "New mirror should never be null."); assert(!m.is_null(), "New mirror should never be null.");
assert(_java_mirror.resolve() == NULL, "should only be used to initialize mirror"); assert(_java_mirror.is_empty(), "should only be used to initialize mirror");
_java_mirror = class_loader_data()->add_handle(m); _java_mirror = class_loader_data()->add_handle(m);
} }
@ -61,6 +61,10 @@ oop Klass::java_mirror_no_keepalive() const {
return _java_mirror.peek(); return _java_mirror.peek();
} }
void Klass::replace_java_mirror(oop mirror) {
_java_mirror.replace(mirror);
}
bool Klass::is_cloneable() const { bool Klass::is_cloneable() const {
return _access_flags.is_cloneable_fast() || return _access_flags.is_cloneable_fast() ||
is_subtype_of(SystemDictionary::Cloneable_klass()); is_subtype_of(SystemDictionary::Cloneable_klass());
@ -195,10 +199,7 @@ void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word
// which zeros out memory - calloc equivalent. // which zeros out memory - calloc equivalent.
// The constructor is also used from CppVtableCloner, // The constructor is also used from CppVtableCloner,
// which doesn't zero out the memory before calling the constructor. // which doesn't zero out the memory before calling the constructor.
// Need to set the _java_mirror field explicitly to not hit an assert that the field
// should be NULL before setting it.
Klass::Klass(KlassID id) : _id(id), Klass::Klass(KlassID id) : _id(id),
_java_mirror(NULL),
_prototype_header(markWord::prototype()), _prototype_header(markWord::prototype()),
_shared_class_path_index(-1) { _shared_class_path_index(-1) {
CDS_ONLY(_shared_class_flags = 0;) CDS_ONLY(_shared_class_flags = 0;)
@ -555,7 +556,7 @@ void Klass::remove_java_mirror() {
log_trace(cds, unshareable)("remove java_mirror: %s", external_name()); log_trace(cds, unshareable)("remove java_mirror: %s", external_name());
} }
// Just null out the mirror. The class_loader_data() no longer exists. // Just null out the mirror. The class_loader_data() no longer exists.
_java_mirror = OopHandle(); clear_java_mirror_handle();
} }
void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
@ -609,7 +610,7 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec
// No archived mirror data // No archived mirror data
log_debug(cds, mirror)("No archived mirror data for %s", external_name()); log_debug(cds, mirror)("No archived mirror data for %s", external_name());
_java_mirror = OopHandle(); clear_java_mirror_handle();
this->clear_has_raw_archived_mirror(); this->clear_has_raw_archived_mirror();
} }

@ -267,12 +267,11 @@ protected:
void set_archived_java_mirror_raw(oop m) NOT_CDS_JAVA_HEAP_RETURN; // no GC barrier void set_archived_java_mirror_raw(oop m) NOT_CDS_JAVA_HEAP_RETURN; // no GC barrier
// Temporary mirror switch used by RedefineClasses // Temporary mirror switch used by RedefineClasses
// Both mirrors are on the ClassLoaderData::_handles list already so no void replace_java_mirror(oop mirror);
// barriers are needed.
void set_java_mirror_handle(OopHandle mirror) { _java_mirror = mirror; } // Set java mirror OopHandle to NULL for CDS
OopHandle java_mirror_handle() const { // This leaves the OopHandle in the CLD, but that's ok, you can't release them.
return _java_mirror; void clear_java_mirror_handle() { _java_mirror = OopHandle(); }
}
// modifier flags // modifier flags
jint modifier_flags() const { return _modifier_flags; } jint modifier_flags() const { return _modifier_flags; }

@ -805,7 +805,7 @@ bool Method::needs_clinit_barrier() const {
objArrayHandle Method::resolved_checked_exceptions_impl(Method* method, TRAPS) { objArrayHandle Method::resolved_checked_exceptions_impl(Method* method, TRAPS) {
int length = method->checked_exceptions_length(); int length = method->checked_exceptions_length();
if (length == 0) { // common case if (length == 0) { // common case
return objArrayHandle(THREAD, Universe::the_empty_class_klass_array()); return objArrayHandle(THREAD, Universe::the_empty_class_array());
} else { } else {
methodHandle h_this(THREAD, method); methodHandle h_this(THREAD, method);
objArrayOop m_oop = oopFactory::new_objArray(SystemDictionary::Class_klass(), length, CHECK_(objArrayHandle())); objArrayOop m_oop = oopFactory::new_objArray(SystemDictionary::Class_klass(), length, CHECK_(objArrayHandle()));

@ -45,11 +45,25 @@ public:
explicit OopHandle(oop* w) : _obj(w) {} explicit OopHandle(oop* w) : _obj(w) {}
OopHandle(OopStorage* storage, oop obj); OopHandle(OopStorage* storage, oop obj);
OopHandle(const OopHandle& copy) : _obj(copy._obj) {}
OopHandle& operator=(const OopHandle& copy) {
// Allow "this" to be junk if copy is empty; needed by initialization of
// raw memory in hashtables.
assert(is_empty() || copy.is_empty(), "can only copy if empty");
_obj = copy._obj;
return *this;
}
inline oop resolve() const; inline oop resolve() const;
inline oop peek() const; inline oop peek() const;
bool is_empty() const { return _obj == NULL; }
inline void release(OopStorage* storage); inline void release(OopStorage* storage);
inline void replace(oop obj);
// Used only for removing handle. // Used only for removing handle.
oop* ptr_raw() const { return _obj; } oop* ptr_raw() const { return _obj; }
}; };

@ -54,4 +54,10 @@ inline void OopHandle::release(OopStorage* storage) {
} }
} }
inline void OopHandle::replace(oop obj) {
oop* ptr = ptr_raw();
assert(ptr != NULL, "should not use replace");
NativeAccess<>::oop_store(ptr, obj);
}
#endif // SHARE_OOPS_OOPHANDLE_INLINE_HPP #endif // SHARE_OOPS_OOPHANDLE_INLINE_HPP

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2020, 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
@ -723,8 +723,7 @@ void ConnectionGraph::add_to_congraph_unsafe_access(Node* n, uint opcode, Unique
if (adr_type->isa_oopptr() if (adr_type->isa_oopptr()
|| ((opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass) || ((opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass)
&& adr_type == TypeRawPtr::NOTNULL && adr_type == TypeRawPtr::NOTNULL
&& adr->in(AddPNode::Address)->is_Proj() && is_captured_store_address(adr))) {
&& adr->in(AddPNode::Address)->in(0)->is_Allocate())) {
delayed_worklist->push(n); // Process it later. delayed_worklist->push(n); // Process it later.
#ifdef ASSERT #ifdef ASSERT
assert (adr->is_AddP(), "expecting an AddP"); assert (adr->is_AddP(), "expecting an AddP");
@ -771,8 +770,7 @@ bool ConnectionGraph::add_final_edges_unsafe_access(Node* n, uint opcode) {
if (adr_type->isa_oopptr() if (adr_type->isa_oopptr()
|| ((opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass) || ((opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass)
&& adr_type == TypeRawPtr::NOTNULL && adr_type == TypeRawPtr::NOTNULL
&& adr->in(AddPNode::Address)->is_Proj() && is_captured_store_address(adr))) {
&& adr->in(AddPNode::Address)->in(0)->is_Allocate())) {
// Point Address to Value // Point Address to Value
PointsToNode* adr_ptn = ptnode_adr(adr->_idx); PointsToNode* adr_ptn = ptnode_adr(adr->_idx);
assert(adr_ptn != NULL && assert(adr_ptn != NULL &&
@ -1584,8 +1582,7 @@ int ConnectionGraph::find_init_values(JavaObjectNode* pta, PointsToNode* init_va
// Raw pointers are used for initializing stores so skip it // Raw pointers are used for initializing stores so skip it
// since it should be recorded already // since it should be recorded already
Node* base = get_addp_base(field->ideal_node()); Node* base = get_addp_base(field->ideal_node());
assert(adr_type->isa_rawptr() && base->is_Proj() && assert(adr_type->isa_rawptr() && is_captured_store_address(field->ideal_node()), "unexpected pointer type");
(base->in(0) == alloc),"unexpected pointer type");
#endif #endif
continue; continue;
} }
@ -1916,8 +1913,7 @@ void ConnectionGraph::optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklis
Node *n = storestore_worklist.pop(); Node *n = storestore_worklist.pop();
MemBarStoreStoreNode *storestore = n ->as_MemBarStoreStore(); MemBarStoreStoreNode *storestore = n ->as_MemBarStoreStore();
Node *alloc = storestore->in(MemBarNode::Precedent)->in(0); Node *alloc = storestore->in(MemBarNode::Precedent)->in(0);
assert (alloc->is_Allocate(), "storestore should point to AllocateNode"); if (alloc->is_Allocate() && not_global_escape(alloc)) {
if (not_global_escape(alloc)) {
MemBarNode* mb = MemBarNode::make(C, Op_MemBarCPUOrder, Compile::AliasIdxBot); MemBarNode* mb = MemBarNode::make(C, Op_MemBarCPUOrder, Compile::AliasIdxBot);
mb->init_req(TypeFunc::Memory, storestore->in(TypeFunc::Memory)); mb->init_req(TypeFunc::Memory, storestore->in(TypeFunc::Memory));
mb->init_req(TypeFunc::Control, storestore->in(TypeFunc::Control)); mb->init_req(TypeFunc::Control, storestore->in(TypeFunc::Control));
@ -2251,11 +2247,29 @@ bool FieldNode::has_base(JavaObjectNode* jobj) const {
} }
#endif #endif
bool ConnectionGraph::is_captured_store_address(Node* addp) {
// Handle simple case first.
assert(_igvn->type(addp)->isa_oopptr() == NULL, "should be raw access");
if (addp->in(AddPNode::Address)->is_Proj() && addp->in(AddPNode::Address)->in(0)->is_Allocate()) {
return true;
} else if (addp->in(AddPNode::Address)->is_Phi()) {
for (DUIterator_Fast imax, i = addp->fast_outs(imax); i < imax; i++) {
Node* addp_use = addp->fast_out(i);
if (addp_use->is_Store()) {
for (DUIterator_Fast jmax, j = addp_use->fast_outs(jmax); j < jmax; j++) {
if (addp_use->fast_out(j)->is_Initialize()) {
return true;
}
}
}
}
}
return false;
}
int ConnectionGraph::address_offset(Node* adr, PhaseTransform *phase) { int ConnectionGraph::address_offset(Node* adr, PhaseTransform *phase) {
const Type *adr_type = phase->type(adr); const Type *adr_type = phase->type(adr);
if (adr->is_AddP() && adr_type->isa_oopptr() == NULL && if (adr->is_AddP() && adr_type->isa_oopptr() == NULL && is_captured_store_address(adr)) {
adr->in(AddPNode::Address)->is_Proj() &&
adr->in(AddPNode::Address)->in(0)->is_Allocate()) {
// We are computing a raw address for a store captured by an Initialize // We are computing a raw address for a store captured by an Initialize
// compute an appropriate address type. AddP cases #3 and #5 (see below). // compute an appropriate address type. AddP cases #3 and #5 (see below).
int offs = (int)phase->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot); int offs = (int)phase->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot);
@ -2358,7 +2372,7 @@ Node* ConnectionGraph::get_addp_base(Node *addp) {
assert(opcode == Op_ConP || opcode == Op_ThreadLocal || assert(opcode == Op_ConP || opcode == Op_ThreadLocal ||
opcode == Op_CastX2P || uncast_base->is_DecodeNarrowPtr() || opcode == Op_CastX2P || uncast_base->is_DecodeNarrowPtr() ||
(uncast_base->is_Mem() && (uncast_base->bottom_type()->isa_rawptr() != NULL)) || (uncast_base->is_Mem() && (uncast_base->bottom_type()->isa_rawptr() != NULL)) ||
(uncast_base->is_Proj() && uncast_base->in(0)->is_Allocate()), "sanity"); is_captured_store_address(addp), "sanity");
} }
} }
return base; return base;
@ -2974,7 +2988,10 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist,
continue; continue;
} }
if (!n->is_CheckCastPP()) { // not unique CheckCastPP. if (!n->is_CheckCastPP()) { // not unique CheckCastPP.
assert(!alloc->is_Allocate(), "allocation should have unique type"); // we could reach here for allocate case if one init is associated with many allocs.
if (alloc->is_Allocate()) {
alloc->as_Allocate()->_is_scalar_replaceable = false;
}
continue; continue;
} }

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2020, 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
@ -512,6 +512,7 @@ private:
// offset of a field reference // offset of a field reference
int address_offset(Node* adr, PhaseTransform *phase); int address_offset(Node* adr, PhaseTransform *phase);
bool is_captured_store_address(Node* addp);
// Propagate unique types created for unescaped allocated objects // Propagate unique types created for unescaped allocated objects
// through the graph // through the graph

@ -1554,78 +1554,95 @@ jfloat Node::getf() const {
#ifndef PRODUCT #ifndef PRODUCT
//------------------------------find------------------------------------------ // Call this from debugger:
// Find a neighbor of this Node with the given _idx Node* find_node(Node* n, const int idx) {
// If idx is negative, find its absolute value, following both _in and _out.
static void find_recur(Compile* C, Node* &result, Node *n, int idx, bool only_ctrl,
VectorSet* old_space, VectorSet* new_space ) {
int node_idx = (idx >= 0) ? idx : -idx;
if (NotANode(n)) return; // Gracefully handle NULL, -1, 0xabababab, etc.
// Contained in new_space or old_space? Check old_arena first since it's mostly empty.
VectorSet *v = C->old_arena()->contains(n) ? old_space : new_space;
if( v->test(n->_idx) ) return;
if( (int)n->_idx == node_idx
debug_only(|| n->debug_idx() == node_idx) ) {
if (result != NULL)
tty->print("find: " INTPTR_FORMAT " and " INTPTR_FORMAT " both have idx==%d\n",
(uintptr_t)result, (uintptr_t)n, node_idx);
result = n;
}
v->set(n->_idx);
for( uint i=0; i<n->len(); i++ ) {
if( only_ctrl && !(n->is_Region()) && (n->Opcode() != Op_Root) && (i != TypeFunc::Control) ) continue;
find_recur(C, result, n->in(i), idx, only_ctrl, old_space, new_space );
}
// Search along forward edges also:
if (idx < 0 && !only_ctrl) {
for( uint j=0; j<n->outcnt(); j++ ) {
find_recur(C, result, n->raw_out(j), idx, only_ctrl, old_space, new_space );
}
}
#ifdef ASSERT
// Search along debug_orig edges last, checking for cycles
Node* orig = n->debug_orig();
if (orig != NULL) {
do {
if (NotANode(orig)) break;
find_recur(C, result, orig, idx, only_ctrl, old_space, new_space );
orig = orig->debug_orig();
} while (orig != NULL && orig != n->debug_orig());
}
#endif //ASSERT
}
// call this from debugger:
Node* find_node(Node* n, int idx) {
return n->find(idx); return n->find(idx);
} }
// call this from debugger with root node as default: // Call this from debugger with root node as default:
Node* find_node(int idx) { Node* find_node(const int idx) {
return Compile::current()->root()->find(idx); return Compile::current()->root()->find(idx);
} }
//------------------------------find------------------------------------------- // Call this from debugger:
Node* Node::find(int idx) const { Node* find_ctrl(Node* n, const int idx) {
VectorSet old_space, new_space; return n->find_ctrl(idx);
Node* result = NULL; }
find_recur(Compile::current(), result, (Node*) this, idx, false, &old_space, &new_space);
return result; // Call this from debugger with root node as default:
Node* find_ctrl(const int idx) {
return Compile::current()->root()->find_ctrl(idx);
} }
//------------------------------find_ctrl-------------------------------------- //------------------------------find_ctrl--------------------------------------
// Find an ancestor to this node in the control history with given _idx // Find an ancestor to this node in the control history with given _idx
Node* Node::find_ctrl(int idx) const { Node* Node::find_ctrl(int idx) {
VectorSet old_space, new_space; return find(idx, true);
}
//------------------------------find-------------------------------------------
// Tries to find the node with the index |idx| starting from this node. If idx is negative,
// the search also includes forward (out) edges. Returns NULL if not found.
// If only_ctrl is set, the search will only be done on control nodes. Returns NULL if
// not found or if the node to be found is not a control node (search will not find it).
Node* Node::find(const int idx, bool only_ctrl) {
ResourceMark rm;
VectorSet old_space;
VectorSet new_space;
Node_List worklist;
Arena* old_arena = Compile::current()->old_arena();
add_to_worklist(this, &worklist, old_arena, &old_space, &new_space);
Node* result = NULL; Node* result = NULL;
find_recur(Compile::current(), result, (Node*)this, idx, true, &old_space, &new_space); int node_idx = (idx >= 0) ? idx : -idx;
for (uint list_index = 0; list_index < worklist.size(); list_index++) {
Node* n = worklist[list_index];
if ((int)n->_idx == node_idx debug_only(|| n->debug_idx() == node_idx)) {
if (result != NULL) {
tty->print("find: " INTPTR_FORMAT " and " INTPTR_FORMAT " both have idx==%d\n",
(uintptr_t)result, (uintptr_t)n, node_idx);
}
result = n;
}
for (uint i = 0; i < n->len(); i++) {
if (!only_ctrl || n->is_Region() || (n->Opcode() == Op_Root) || (i == TypeFunc::Control)) {
// If only_ctrl is set: Add regions, the root node, or control inputs only
add_to_worklist(n->in(i), &worklist, old_arena, &old_space, &new_space);
}
}
// Also search along forward edges if idx is negative and the search is not done on control nodes only
if (idx < 0 && !only_ctrl) {
for (uint i = 0; i < n->outcnt(); i++) {
add_to_worklist(n->raw_out(i), &worklist, old_arena, &old_space, &new_space);
}
}
#ifdef ASSERT
// Search along debug_orig edges last
Node* orig = n->debug_orig();
while (orig != NULL && add_to_worklist(orig, &worklist, old_arena, &old_space, &new_space)) {
orig = orig->debug_orig();
}
#endif // ASSERT
}
return result; return result;
} }
#endif
bool Node::add_to_worklist(Node* n, Node_List* worklist, Arena* old_arena, VectorSet* old_space, VectorSet* new_space) {
if (NotANode(n)) {
return false; // Gracefully handle NULL, -1, 0xabababab, etc.
}
// Contained in new_space or old_space? Check old_arena first since it's mostly empty.
#ifndef PRODUCT VectorSet* v = old_arena->contains(n) ? old_space : new_space;
if (!v->test_set(n->_idx)) {
worklist->push(n);
return true;
}
return false;
}
// -----------------------------Name------------------------------------------- // -----------------------------Name-------------------------------------------
extern const char *NodeClassNames[]; extern const char *NodeClassNames[];
@ -2141,8 +2158,9 @@ void Node::verify_edges(Unique_Node_List &visited) {
} }
assert( cnt == 0,"Mismatched edge count."); assert( cnt == 0,"Mismatched edge count.");
} else if (n == NULL) { } else if (n == NULL) {
assert(i >= req() || i == 0 || is_Region() || is_Phi() || is_ArrayCopy() assert(i >= req() || i == 0 || is_Region() || is_Phi() || is_ArrayCopy() || (is_Unlock() && i == req()-1)
|| (is_Unlock() && i == req()-1), "only region, phi, arraycopy or unlock nodes have null data edges"); || (is_MemBar() && i == 5), // the precedence edge to a membar can be removed during macro node expansion
"only region, phi, arraycopy, unlock or membar nodes have null data edges");
} else { } else {
assert(n->is_top(), "sanity"); assert(n->is_top(), "sanity");
// Nothing to check. // Nothing to check.
@ -2226,7 +2244,7 @@ void Node::verify(Node* n, int verify_depth) {
} }
} }
} }
#endif #endif // not PRODUCT
//------------------------------walk------------------------------------------- //------------------------------walk-------------------------------------------
// Graph walk, with both pre-order and post-order functions // Graph walk, with both pre-order and post-order functions

@ -1118,10 +1118,11 @@ private:
void walk_(NFunc pre, NFunc post, void *env, VectorSet &visited); void walk_(NFunc pre, NFunc post, void *env, VectorSet &visited);
//----------------- Printing, etc //----------------- Printing, etc
public:
#ifndef PRODUCT #ifndef PRODUCT
Node* find(int idx) const; // Search the graph for the given idx. static bool add_to_worklist(Node* n, Node_List* worklist, Arena* old_arena, VectorSet* old_space, VectorSet* new_space);
Node* find_ctrl(int idx) const; // Search control ancestors for the given idx. public:
Node* find(int idx, bool only_ctrl = false); // Search the graph for the given idx.
Node* find_ctrl(int idx); // Search control ancestors for the given idx.
void dump() const { dump("\n"); } // Print this node. void dump() const { dump("\n"); } // Print this node.
void dump(const char* suffix, bool mark = false, outputStream *st = tty) const; // Print this node. void dump(const char* suffix, bool mark = false, outputStream *st = tty) const; // Print this node.
void dump(int depth) const; // Print this node, recursively to depth d void dump(int depth) const; // Print this node, recursively to depth d

@ -344,8 +344,7 @@ JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderR
trace_class_resolution(k); trace_class_resolution(k);
} }
cls = (jclass)JNIHandles::make_local( cls = (jclass)JNIHandles::make_local(THREAD, k->java_mirror());
env, k->java_mirror());
return cls; return cls;
JNI_END JNI_END
@ -501,7 +500,7 @@ JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID meth
} else { } else {
reflection_method = Reflection::new_method(m, false, CHECK_NULL); reflection_method = Reflection::new_method(m, false, CHECK_NULL);
} }
ret = JNIHandles::make_local(env, reflection_method); ret = JNIHandles::make_local(THREAD, reflection_method);
return ret; return ret;
JNI_END JNI_END
@ -535,7 +534,7 @@ JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
: k->super() ) ); : k->super() ) );
assert(super == super2, assert(super == super2,
"java_super computation depends on interface, array, other super"); "java_super computation depends on interface, array, other super");
obj = (super == NULL) ? NULL : (jclass) JNIHandles::make_local(super->java_mirror()); obj = (super == NULL) ? NULL : (jclass) JNIHandles::make_local(THREAD, super->java_mirror());
return obj; return obj;
JNI_END JNI_END
@ -623,7 +622,7 @@ JNI_ENTRY_NO_PRESERVE(jthrowable, jni_ExceptionOccurred(JNIEnv *env))
jni_check_async_exceptions(thread); jni_check_async_exceptions(thread);
oop exception = thread->pending_exception(); oop exception = thread->pending_exception();
jthrowable ret = (jthrowable) JNIHandles::make_local(env, exception); jthrowable ret = (jthrowable) JNIHandles::make_local(THREAD, exception);
HOTSPOT_JNI_EXCEPTIONOCCURRED_RETURN(ret); HOTSPOT_JNI_EXCEPTIONOCCURRED_RETURN(ret);
return ret; return ret;
@ -754,7 +753,7 @@ JNI_ENTRY(jobject, jni_NewGlobalRef(JNIEnv *env, jobject ref))
HOTSPOT_JNI_NEWGLOBALREF_ENTRY(env, ref); HOTSPOT_JNI_NEWGLOBALREF_ENTRY(env, ref);
Handle ref_handle(thread, JNIHandles::resolve(ref)); Handle ref_handle(thread, JNIHandles::resolve(ref));
jobject ret = JNIHandles::make_global(ref_handle); jobject ret = JNIHandles::make_global(ref_handle, AllocFailStrategy::RETURN_NULL);
HOTSPOT_JNI_NEWGLOBALREF_RETURN(ret); HOTSPOT_JNI_NEWGLOBALREF_RETURN(ret);
return ret; return ret;
@ -798,7 +797,8 @@ JNI_ENTRY(jobject, jni_NewLocalRef(JNIEnv *env, jobject ref))
HOTSPOT_JNI_NEWLOCALREF_ENTRY(env, ref); HOTSPOT_JNI_NEWLOCALREF_ENTRY(env, ref);
jobject ret = JNIHandles::make_local(env, JNIHandles::resolve(ref)); jobject ret = JNIHandles::make_local(THREAD, JNIHandles::resolve(ref),
AllocFailStrategy::RETURN_NULL);
HOTSPOT_JNI_NEWLOCALREF_RETURN(ret); HOTSPOT_JNI_NEWLOCALREF_RETURN(ret);
return ret; return ret;
@ -976,7 +976,7 @@ static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver,
// Convert result // Convert result
if (is_reference_type(result->get_type())) { if (is_reference_type(result->get_type())) {
result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject())); result->set_jobject(JNIHandles::make_local(THREAD, (oop) result->get_jobject()));
} }
} }
@ -1038,7 +1038,7 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive
// Convert result // Convert result
if (is_reference_type(result->get_type())) { if (is_reference_type(result->get_type())) {
result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject())); result->set_jobject(JNIHandles::make_local(THREAD, (oop) result->get_jobject()));
} }
} }
@ -1054,7 +1054,7 @@ JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))
DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret); DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL); instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
ret = JNIHandles::make_local(env, i); ret = JNIHandles::make_local(THREAD, i);
return ret; return ret;
JNI_END JNI_END
@ -1070,7 +1070,7 @@ JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID,
DT_RETURN_MARK(NewObjectA, jobject, (const jobject)obj); DT_RETURN_MARK(NewObjectA, jobject, (const jobject)obj);
instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL); instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
obj = JNIHandles::make_local(env, i); obj = JNIHandles::make_local(THREAD, i);
JavaValue jvalue(T_VOID); JavaValue jvalue(T_VOID);
JNI_ArgumentPusherArray ap(methodID, args); JNI_ArgumentPusherArray ap(methodID, args);
jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL); jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
@ -1090,7 +1090,7 @@ JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID,
DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj); DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL); instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
obj = JNIHandles::make_local(env, i); obj = JNIHandles::make_local(THREAD, i);
JavaValue jvalue(T_VOID); JavaValue jvalue(T_VOID);
JNI_ArgumentPusherVaArg ap(methodID, args); JNI_ArgumentPusherVaArg ap(methodID, args);
jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL); jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
@ -1110,7 +1110,7 @@ JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID,
DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj); DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL); instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
obj = JNIHandles::make_local(env, i); obj = JNIHandles::make_local(THREAD, i);
va_list args; va_list args;
va_start(args, methodID); va_start(args, methodID);
JavaValue jvalue(T_VOID); JavaValue jvalue(T_VOID);
@ -1128,7 +1128,7 @@ JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
Klass* k = JNIHandles::resolve_non_null(obj)->klass(); Klass* k = JNIHandles::resolve_non_null(obj)->klass();
jclass ret = jclass ret =
(jclass) JNIHandles::make_local(env, k->java_mirror()); (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret); HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
return ret; return ret;
@ -1910,7 +1910,7 @@ JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID
o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false); o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
} }
oop loaded_obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset); oop loaded_obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
jobject ret = JNIHandles::make_local(env, loaded_obj); jobject ret = JNIHandles::make_local(THREAD, loaded_obj);
HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret); HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
return ret; return ret;
JNI_END JNI_END
@ -2090,7 +2090,7 @@ JNI_ENTRY(jobject, jni_ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldI
} }
assert(found, "bad fieldID passed into jni_ToReflectedField"); assert(found, "bad fieldID passed into jni_ToReflectedField");
oop reflected = Reflection::new_field(&fd, CHECK_NULL); oop reflected = Reflection::new_field(&fd, CHECK_NULL);
ret = JNIHandles::make_local(env, reflected); ret = JNIHandles::make_local(THREAD, reflected);
return ret; return ret;
JNI_END JNI_END
@ -2150,7 +2150,7 @@ JNI_ENTRY(jobject, jni_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID
if (JvmtiExport::should_post_field_access()) { if (JvmtiExport::should_post_field_access()) {
JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true);
} }
jobject ret = JNIHandles::make_local(id->holder()->java_mirror()->obj_field(id->offset())); jobject ret = JNIHandles::make_local(THREAD, id->holder()->java_mirror()->obj_field(id->offset()));
HOTSPOT_JNI_GETSTATICOBJECTFIELD_RETURN(ret); HOTSPOT_JNI_GETSTATICOBJECTFIELD_RETURN(ret);
return ret; return ret;
JNI_END JNI_END
@ -2277,7 +2277,7 @@ JNI_ENTRY(jstring, jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize l
jstring ret = NULL; jstring ret = NULL;
DT_RETURN_MARK(NewString, jstring, (const jstring&)ret); DT_RETURN_MARK(NewString, jstring, (const jstring&)ret);
oop string=java_lang_String::create_oop_from_unicode((jchar*) unicodeChars, len, CHECK_NULL); oop string=java_lang_String::create_oop_from_unicode((jchar*) unicodeChars, len, CHECK_NULL);
ret = (jstring) JNIHandles::make_local(env, string); ret = (jstring) JNIHandles::make_local(THREAD, string);
return ret; return ret;
JNI_END JNI_END
@ -2353,7 +2353,7 @@ JNI_ENTRY(jstring, jni_NewStringUTF(JNIEnv *env, const char *bytes))
DT_RETURN_MARK(NewStringUTF, jstring, (const jstring&)ret); DT_RETURN_MARK(NewStringUTF, jstring, (const jstring&)ret);
oop result = java_lang_String::create_oop_from_str((char*) bytes, CHECK_NULL); oop result = java_lang_String::create_oop_from_str((char*) bytes, CHECK_NULL);
ret = (jstring) JNIHandles::make_local(env, result); ret = (jstring) JNIHandles::make_local(THREAD, result);
return ret; return ret;
JNI_END JNI_END
@ -2433,7 +2433,7 @@ JNI_ENTRY(jobjectArray, jni_NewObjectArray(JNIEnv *env, jsize length, jclass ele
result->obj_at_put(index, initial_value); result->obj_at_put(index, initial_value);
} }
} }
ret = (jobjectArray) JNIHandles::make_local(env, result); ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
return ret; return ret;
JNI_END JNI_END
@ -2447,7 +2447,7 @@ JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, js
DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret); DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
if (a->is_within_bounds(index)) { if (a->is_within_bounds(index)) {
ret = JNIHandles::make_local(env, a->obj_at(index)); ret = JNIHandles::make_local(THREAD, a->obj_at(index));
return ret; return ret;
} else { } else {
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
@ -2507,7 +2507,7 @@ JNI_ENTRY(Return, \
DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\ DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
\ \
oop obj= oopFactory::Allocator(len, CHECK_NULL); \ oop obj= oopFactory::Allocator(len, CHECK_NULL); \
ret = (Return) JNIHandles::make_local(env, obj); \ ret = (Return) JNIHandles::make_local(THREAD, obj); \
return ret;\ return ret;\
JNI_END JNI_END
@ -3051,7 +3051,10 @@ JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref))
JNIWrapper("jni_NewWeakGlobalRef"); JNIWrapper("jni_NewWeakGlobalRef");
HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY(env, ref); HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY(env, ref);
Handle ref_handle(thread, JNIHandles::resolve(ref)); Handle ref_handle(thread, JNIHandles::resolve(ref));
jweak ret = JNIHandles::make_weak_global(ref_handle); jweak ret = JNIHandles::make_weak_global(ref_handle, AllocFailStrategy::RETURN_NULL);
if (ret == NULL) {
THROW_OOP_(Universe::out_of_memory_error_c_heap(), NULL);
}
HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN(ret); HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN(ret);
return ret; return ret;
JNI_END JNI_END
@ -3128,6 +3131,12 @@ static bool initializeDirectBufferSupport(JNIEnv* env, JavaThread* thread) {
directBufferClass = (jclass) env->NewGlobalRef(directBufferClass); directBufferClass = (jclass) env->NewGlobalRef(directBufferClass);
directByteBufferClass = (jclass) env->NewGlobalRef(directByteBufferClass); directByteBufferClass = (jclass) env->NewGlobalRef(directByteBufferClass);
// Global refs will be NULL if out-of-memory (no exception is pending)
if (bufferClass == NULL || directBufferClass == NULL || directByteBufferClass == NULL) {
directBufferSupportInitializeFailed = 1;
return false;
}
// Get needed field and method IDs // Get needed field and method IDs
directByteBufferConstructor = env->GetMethodID(directByteBufferClass, "<init>", "(JI)V"); directByteBufferConstructor = env->GetMethodID(directByteBufferClass, "<init>", "(JI)V");
if (env->ExceptionCheck()) { if (env->ExceptionCheck()) {

@ -141,7 +141,7 @@ static void trace_class_resolution_impl(Klass* to_class, TRAPS) {
const char * source_file = NULL; const char * source_file = NULL;
const char * trace = "explicit"; const char * trace = "explicit";
InstanceKlass* caller = NULL; InstanceKlass* caller = NULL;
JavaThread* jthread = JavaThread::current(); JavaThread* jthread = (JavaThread*) THREAD;
if (jthread->has_last_Java_frame()) { if (jthread->has_last_Java_frame()) {
vframeStream vfst(jthread); vframeStream vfst(jthread);
@ -447,7 +447,7 @@ JVM_ENTRY(jobjectArray, JVM_GetProperties(JNIEnv *env))
} }
} }
return (jobjectArray) JNIHandles::make_local(env, result_h()); return (jobjectArray) JNIHandles::make_local(THREAD, result_h());
JVM_END JVM_END
@ -464,7 +464,7 @@ JVM_ENTRY(jstring, JVM_GetTemporaryDirectory(JNIEnv *env))
HandleMark hm(THREAD); HandleMark hm(THREAD);
const char* temp_dir = os::get_temp_directory(); const char* temp_dir = os::get_temp_directory();
Handle h = java_lang_String::create_from_platform_dependent_str(temp_dir, CHECK_NULL); Handle h = java_lang_String::create_from_platform_dependent_str(temp_dir, CHECK_NULL);
return (jstring) JNIHandles::make_local(env, h()); return (jstring) JNIHandles::make_local(THREAD, h());
JVM_END JVM_END
@ -568,7 +568,7 @@ JVM_ENTRY(jstring, JVM_GetExtendedNPEMessage(JNIEnv *env, jthrowable throwable))
bool ok = BytecodeUtils::get_NPE_message_at(&ss, method, bci); bool ok = BytecodeUtils::get_NPE_message_at(&ss, method, bci);
if (ok) { if (ok) {
oop result = java_lang_String::create_oop_from_str(ss.base(), CHECK_NULL); oop result = java_lang_String::create_oop_from_str(ss.base(), CHECK_NULL);
return (jstring) JNIHandles::make_local(env, result); return (jstring) JNIHandles::make_local(THREAD, result);
} else { } else {
return NULL; return NULL;
} }
@ -622,7 +622,7 @@ JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mod
oop result = StackWalk::walk(stackStream_h, mode, skip_frames, frame_count, oop result = StackWalk::walk(stackStream_h, mode, skip_frames, frame_count,
start_index, frames_array_h, CHECK_NULL); start_index, frames_array_h, CHECK_NULL);
return JNIHandles::make_local(env, result); return JNIHandles::make_local(THREAD, result);
JVM_END JVM_END
@ -630,7 +630,6 @@ JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
jint frame_count, jint start_index, jint frame_count, jint start_index,
jobjectArray frames)) jobjectArray frames))
JVMWrapper("JVM_MoreStackWalk"); JVMWrapper("JVM_MoreStackWalk");
JavaThread* jt = (JavaThread*) THREAD;
// frames array is a Class<?>[] array when only getting caller reference, // frames array is a Class<?>[] array when only getting caller reference,
// and a StackFrameInfo[] array (or derivative) otherwise. It should never // and a StackFrameInfo[] array (or derivative) otherwise. It should never
@ -738,7 +737,7 @@ JVM_ENTRY(jobject, JVM_Clone(JNIEnv* env, jobject handle))
new_obj = Handle(THREAD, new_obj_oop); new_obj = Handle(THREAD, new_obj_oop);
} }
return JNIHandles::make_local(env, new_obj()); return JNIHandles::make_local(THREAD, new_obj());
JVM_END JVM_END
// java.io.File /////////////////////////////////////////////////////////////// // java.io.File ///////////////////////////////////////////////////////////////
@ -784,7 +783,7 @@ JVM_ENTRY(jclass, JVM_GetCallerClass(JNIEnv* env))
default: default:
if (!m->is_ignored_by_security_stack_walk()) { if (!m->is_ignored_by_security_stack_walk()) {
// We have reached the desired frame; return the holder class. // We have reached the desired frame; return the holder class.
return (jclass) JNIHandles::make_local(env, m->method_holder()->java_mirror()); return (jclass) JNIHandles::make_local(THREAD, m->method_holder()->java_mirror());
} }
break; break;
} }
@ -803,7 +802,7 @@ JVM_ENTRY(jclass, JVM_FindPrimitiveClass(JNIEnv* env, const char* utf))
if (mirror == NULL) { if (mirror == NULL) {
THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), (char*) utf); THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), (char*) utf);
} else { } else {
return (jclass) JNIHandles::make_local(env, mirror); return (jclass) JNIHandles::make_local(THREAD, mirror);
} }
JVM_END JVM_END
@ -832,7 +831,7 @@ JVM_ENTRY(jclass, JVM_FindClassFromBootLoader(JNIEnv* env,
if (log_is_enabled(Debug, class, resolve)) { if (log_is_enabled(Debug, class, resolve)) {
trace_class_resolution(k); trace_class_resolution(k);
} }
return (jclass) JNIHandles::make_local(env, k->java_mirror()); return (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
JVM_END JVM_END
// Find a class with this name in this loader, using the caller's protection domain. // Find a class with this name in this loader, using the caller's protection domain.
@ -920,7 +919,7 @@ static void is_lock_held_by_thread(Handle loader, PerfCounter* counter, TRAPS) {
} }
// common code for JVM_DefineClass() and JVM_DefineClassWithSource() // common code for JVM_DefineClass() and JVM_DefineClassWithSource()
static jclass jvm_define_class_common(JNIEnv *env, const char *name, static jclass jvm_define_class_common(const char *name,
jobject loader, const jbyte *buf, jobject loader, const jbyte *buf,
jsize len, jobject pd, const char *source, jsize len, jobject pd, const char *source,
TRAPS) { TRAPS) {
@ -964,7 +963,7 @@ static jclass jvm_define_class_common(JNIEnv *env, const char *name,
trace_class_resolution(k); trace_class_resolution(k);
} }
return (jclass) JNIHandles::make_local(env, k->java_mirror()); return (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
} }
enum { enum {
@ -978,11 +977,10 @@ enum {
* Define a class with the specified flags that indicates if it's a nestmate, * Define a class with the specified flags that indicates if it's a nestmate,
* hidden, or strongly referenced from class loader. * hidden, or strongly referenced from class loader.
*/ */
static jclass jvm_lookup_define_class(JNIEnv *env, jclass lookup, const char *name, static jclass jvm_lookup_define_class(jclass lookup, const char *name,
const jbyte *buf, jsize len, jobject pd, const jbyte *buf, jsize len, jobject pd,
jboolean init, int flags, jobject classData, TRAPS) { jboolean init, int flags, jobject classData, TRAPS) {
assert(THREAD->is_Java_thread(), "must be a JavaThread"); assert(THREAD->is_Java_thread(), "must be a JavaThread");
JavaThread* jt = (JavaThread*) THREAD;
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
Klass* lookup_k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(lookup)); Klass* lookup_k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(lookup));
@ -1099,13 +1097,13 @@ static jclass jvm_lookup_define_class(JNIEnv *env, jclass lookup, const char *na
ik->link_class(CHECK_NULL); ik->link_class(CHECK_NULL);
} }
return (jclass) JNIHandles::make_local(env, defined_k->java_mirror()); return (jclass) JNIHandles::make_local(THREAD, defined_k->java_mirror());
} }
JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd)) JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd))
JVMWrapper("JVM_DefineClass"); JVMWrapper("JVM_DefineClass");
return jvm_define_class_common(env, name, loader, buf, len, pd, NULL, THREAD); return jvm_define_class_common(name, loader, buf, len, pd, NULL, THREAD);
JVM_END JVM_END
/* /*
@ -1129,13 +1127,13 @@ JVM_ENTRY(jclass, JVM_LookupDefineClass(JNIEnv *env, jclass lookup, const char *
assert(buf != NULL, "buf must not be NULL"); assert(buf != NULL, "buf must not be NULL");
return jvm_lookup_define_class(env, lookup, name, buf, len, pd, initialize, flags, classData, THREAD); return jvm_lookup_define_class(lookup, name, buf, len, pd, initialize, flags, classData, THREAD);
JVM_END JVM_END
JVM_ENTRY(jclass, JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source)) JVM_ENTRY(jclass, JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source))
JVMWrapper("JVM_DefineClassWithSource"); JVMWrapper("JVM_DefineClassWithSource");
return jvm_define_class_common(env, name, loader, buf, len, pd, source, THREAD); return jvm_define_class_common(name, loader, buf, len, pd, source, THREAD);
JVM_END JVM_END
JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name)) JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name))
@ -1187,7 +1185,7 @@ JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name)
} }
#endif #endif
return (k == NULL) ? NULL : return (k == NULL) ? NULL :
(jclass) JNIHandles::make_local(env, k->java_mirror()); (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
JVM_END JVM_END
// Module support ////////////////////////////////////////////////////////////////////////////// // Module support //////////////////////////////////////////////////////////////////////////////
@ -1233,7 +1231,7 @@ JVM_ENTRY(jstring, JVM_InitClassName(JNIEnv *env, jclass cls))
HandleMark hm(THREAD); HandleMark hm(THREAD);
Handle java_class(THREAD, JNIHandles::resolve(cls)); Handle java_class(THREAD, JNIHandles::resolve(cls));
oop result = java_lang_Class::name(java_class, CHECK_NULL); oop result = java_lang_Class::name(java_class, CHECK_NULL);
return (jstring) JNIHandles::make_local(env, result); return (jstring) JNIHandles::make_local(THREAD, result);
JVM_END JVM_END
@ -1246,7 +1244,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls))
if (java_lang_Class::is_primitive(mirror)) { if (java_lang_Class::is_primitive(mirror)) {
// Primitive objects does not have any interfaces // Primitive objects does not have any interfaces
objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL);
return (jobjectArray) JNIHandles::make_local(env, r); return (jobjectArray) JNIHandles::make_local(THREAD, r);
} }
Klass* klass = java_lang_Class::as_Klass(mirror); Klass* klass = java_lang_Class::as_Klass(mirror);
@ -1274,7 +1272,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls))
result->obj_at_put(0, SystemDictionary::Cloneable_klass()->java_mirror()); result->obj_at_put(0, SystemDictionary::Cloneable_klass()->java_mirror());
result->obj_at_put(1, SystemDictionary::Serializable_klass()->java_mirror()); result->obj_at_put(1, SystemDictionary::Serializable_klass()->java_mirror());
} }
return (jobjectArray) JNIHandles::make_local(env, result()); return (jobjectArray) JNIHandles::make_local(THREAD, result());
JVM_END JVM_END
@ -1325,7 +1323,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassSigners(JNIEnv *env, jclass cls))
} }
// return the copy // return the copy
return (jobjectArray) JNIHandles::make_local(env, signers_copy); return (jobjectArray) JNIHandles::make_local(THREAD, signers_copy);
JVM_END JVM_END
@ -1355,7 +1353,7 @@ JVM_ENTRY(jobject, JVM_GetProtectionDomain(JNIEnv *env, jclass cls))
} }
oop pd = java_lang_Class::protection_domain(JNIHandles::resolve(cls)); oop pd = java_lang_Class::protection_domain(JNIHandles::resolve(cls));
return (jobject) JNIHandles::make_local(env, pd); return (jobject) JNIHandles::make_local(THREAD, pd);
JVM_END JVM_END
@ -1363,7 +1361,7 @@ JVM_END
JVM_ENTRY(jobject, JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls)) JVM_ENTRY(jobject, JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls))
JVMWrapper("JVM_GetInheritedAccessControlContext"); JVMWrapper("JVM_GetInheritedAccessControlContext");
oop result = java_lang_Thread::inherited_access_control_context(thread->threadObj()); oop result = java_lang_Thread::inherited_access_control_context(thread->threadObj());
return JNIHandles::make_local(env, result); return JNIHandles::make_local(THREAD, result);
JVM_END JVM_END
class RegisterArrayForGC { class RegisterArrayForGC {
@ -1442,7 +1440,7 @@ JVM_ENTRY(jobject, JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls))
if (is_privileged && privileged_context.is_null()) return NULL; if (is_privileged && privileged_context.is_null()) return NULL;
oop result = java_security_AccessControlContext::create(objArrayHandle(), is_privileged, privileged_context, CHECK_NULL); oop result = java_security_AccessControlContext::create(objArrayHandle(), is_privileged, privileged_context, CHECK_NULL);
return JNIHandles::make_local(env, result); return JNIHandles::make_local(THREAD, result);
} }
// the resource area must be registered in case of a gc // the resource area must be registered in case of a gc
@ -1456,7 +1454,7 @@ JVM_ENTRY(jobject, JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls))
oop result = java_security_AccessControlContext::create(h_context, is_privileged, privileged_context, CHECK_NULL); oop result = java_security_AccessControlContext::create(h_context, is_privileged, privileged_context, CHECK_NULL);
return JNIHandles::make_local(env, result); return JNIHandles::make_local(THREAD, result);
JVM_END JVM_END
@ -1498,7 +1496,7 @@ JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass))
if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) ||
! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_instance_klass()) { ! java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_instance_klass()) {
oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL);
return (jobjectArray)JNIHandles::make_local(env, result); return (jobjectArray)JNIHandles::make_local(THREAD, result);
} }
InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)));
@ -1507,7 +1505,7 @@ JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass))
if (iter.length() == 0) { if (iter.length() == 0) {
// Neither an inner nor outer class // Neither an inner nor outer class
oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL); oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL);
return (jobjectArray)JNIHandles::make_local(env, result); return (jobjectArray)JNIHandles::make_local(THREAD, result);
} }
// find inner class info // find inner class info
@ -1549,10 +1547,10 @@ JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass))
for(int i = 0; i < members; i++) { for(int i = 0; i < members; i++) {
res->obj_at_put(i, result->obj_at(i)); res->obj_at_put(i, result->obj_at(i));
} }
return (jobjectArray)JNIHandles::make_local(env, res); return (jobjectArray)JNIHandles::make_local(THREAD, res);
} }
return (jobjectArray)JNIHandles::make_local(env, result()); return (jobjectArray)JNIHandles::make_local(THREAD, result());
JVM_END JVM_END
@ -1570,7 +1568,7 @@ JVM_ENTRY(jclass, JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass))
)->compute_enclosing_class(&inner_is_member, CHECK_NULL); )->compute_enclosing_class(&inner_is_member, CHECK_NULL);
if (outer_klass == NULL) return NULL; // already a top-level class if (outer_klass == NULL) return NULL; // already a top-level class
if (!inner_is_member) return NULL; // a hidden or unsafe anonymous class (inside a method) if (!inner_is_member) return NULL; // a hidden or unsafe anonymous class (inside a method)
return (jclass) JNIHandles::make_local(env, outer_klass->java_mirror()); return (jclass) JNIHandles::make_local(THREAD, outer_klass->java_mirror());
} }
JVM_END JVM_END
@ -1588,7 +1586,7 @@ JVM_ENTRY(jstring, JVM_GetSimpleBinaryName(JNIEnv *env, jclass cls))
constantPoolHandle i_cp(thread, k->constants()); constantPoolHandle i_cp(thread, k->constants());
Symbol* name = i_cp->symbol_at(noff); Symbol* name = i_cp->symbol_at(noff);
Handle str = java_lang_String::create_from_symbol(name, CHECK_NULL); Handle str = java_lang_String::create_from_symbol(name, CHECK_NULL);
return (jstring) JNIHandles::make_local(env, str()); return (jstring) JNIHandles::make_local(THREAD, str());
} }
} }
return NULL; return NULL;
@ -1607,7 +1605,7 @@ JVM_ENTRY(jstring, JVM_GetClassSignature(JNIEnv *env, jclass cls))
Symbol* sym = InstanceKlass::cast(k)->generic_signature(); Symbol* sym = InstanceKlass::cast(k)->generic_signature();
if (sym == NULL) return NULL; if (sym == NULL) return NULL;
Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL); Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
return (jstring) JNIHandles::make_local(env, str()); return (jstring) JNIHandles::make_local(THREAD, str());
} }
} }
return NULL; return NULL;
@ -1623,7 +1621,7 @@ JVM_ENTRY(jbyteArray, JVM_GetClassAnnotations(JNIEnv *env, jclass cls))
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls));
if (k->is_instance_klass()) { if (k->is_instance_klass()) {
typeArrayOop a = Annotations::make_java_array(InstanceKlass::cast(k)->class_annotations(), CHECK_NULL); typeArrayOop a = Annotations::make_java_array(InstanceKlass::cast(k)->class_annotations(), CHECK_NULL);
return (jbyteArray) JNIHandles::make_local(env, a); return (jbyteArray) JNIHandles::make_local(THREAD, a);
} }
} }
return NULL; return NULL;
@ -1695,7 +1693,7 @@ JVM_ENTRY(jbyteArray, JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls))
AnnotationArray* type_annotations = InstanceKlass::cast(k)->class_type_annotations(); AnnotationArray* type_annotations = InstanceKlass::cast(k)->class_type_annotations();
if (type_annotations != NULL) { if (type_annotations != NULL) {
typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL); typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL);
return (jbyteArray) JNIHandles::make_local(env, a); return (jbyteArray) JNIHandles::make_local(THREAD, a);
} }
} }
} }
@ -1715,7 +1713,7 @@ JVM_ENTRY(jbyteArray, JVM_GetMethodTypeAnnotations(JNIEnv *env, jobject method))
AnnotationArray* type_annotations = m->type_annotations(); AnnotationArray* type_annotations = m->type_annotations();
if (type_annotations != NULL) { if (type_annotations != NULL) {
typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL); typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL);
return (jbyteArray) JNIHandles::make_local(env, a); return (jbyteArray) JNIHandles::make_local(THREAD, a);
} }
return NULL; return NULL;
@ -1731,7 +1729,7 @@ JVM_ENTRY(jbyteArray, JVM_GetFieldTypeAnnotations(JNIEnv *env, jobject field))
return NULL; return NULL;
} }
return (jbyteArray) JNIHandles::make_local(env, Annotations::make_java_array(fd.type_annotations(), THREAD)); return (jbyteArray) JNIHandles::make_local(THREAD, Annotations::make_java_array(fd.type_annotations(), THREAD));
JVM_END JVM_END
static void bounds_check(const constantPoolHandle& cp, jint index, TRAPS) { static void bounds_check(const constantPoolHandle& cp, jint index, TRAPS) {
@ -1787,7 +1785,7 @@ JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method))
flags, CHECK_NULL); flags, CHECK_NULL);
result->obj_at_put(i, param); result->obj_at_put(i, param);
} }
return (jobjectArray)JNIHandles::make_local(env, result()); return (jobjectArray)JNIHandles::make_local(THREAD, result());
} }
} }
JVM_END JVM_END
@ -1804,7 +1802,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass,
java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_array_klass()) { java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_array_klass()) {
// Return empty array // Return empty array
oop res = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), 0, CHECK_NULL); oop res = oopFactory::new_objArray(SystemDictionary::reflect_Field_klass(), 0, CHECK_NULL);
return (jobjectArray) JNIHandles::make_local(env, res); return (jobjectArray) JNIHandles::make_local(THREAD, res);
} }
InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)));
@ -1839,7 +1837,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass,
} }
} }
assert(out_idx == num_fields, "just checking"); assert(out_idx == num_fields, "just checking");
return (jobjectArray) JNIHandles::make_local(env, result()); return (jobjectArray) JNIHandles::make_local(THREAD, result());
} }
JVM_END JVM_END
@ -1881,13 +1879,13 @@ JVM_ENTRY(jobjectArray, JVM_GetRecordComponents(JNIEnv* env, jclass ofClass))
oop component_oop = java_lang_reflect_RecordComponent::create(ik, component, CHECK_NULL); oop component_oop = java_lang_reflect_RecordComponent::create(ik, component, CHECK_NULL);
components_h->obj_at_put(x, component_oop); components_h->obj_at_put(x, component_oop);
} }
return (jobjectArray)JNIHandles::make_local(components_h()); return (jobjectArray)JNIHandles::make_local(THREAD, components_h());
} }
} }
// Return empty array if ofClass is not a record. // Return empty array if ofClass is not a record.
objArrayOop result = oopFactory::new_objArray(SystemDictionary::RecordComponent_klass(), 0, CHECK_NULL); objArrayOop result = oopFactory::new_objArray(SystemDictionary::RecordComponent_klass(), 0, CHECK_NULL);
return (jobjectArray)JNIHandles::make_local(env, result); return (jobjectArray)JNIHandles::make_local(THREAD, result);
} }
JVM_END JVM_END
@ -1912,7 +1910,7 @@ static jobjectArray get_class_declared_methods_helper(
|| java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_array_klass()) { || java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->is_array_klass()) {
// Return empty array // Return empty array
oop res = oopFactory::new_objArray(klass, 0, CHECK_NULL); oop res = oopFactory::new_objArray(klass, 0, CHECK_NULL);
return (jobjectArray) JNIHandles::make_local(env, res); return (jobjectArray) JNIHandles::make_local(THREAD, res);
} }
InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass)));
@ -1965,7 +1963,7 @@ static jobjectArray get_class_declared_methods_helper(
} }
} }
return (jobjectArray) JNIHandles::make_local(env, result()); return (jobjectArray) JNIHandles::make_local(THREAD, result());
} }
JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly)) JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly))
@ -2147,7 +2145,7 @@ JVM_ENTRY(jobject, JVM_GetClassConstantPool(JNIEnv *env, jclass cls))
InstanceKlass* k_h = InstanceKlass::cast(k); InstanceKlass* k_h = InstanceKlass::cast(k);
Handle jcp = reflect_ConstantPool::create(CHECK_NULL); Handle jcp = reflect_ConstantPool::create(CHECK_NULL);
reflect_ConstantPool::set_cp(jcp(), k_h->constants()); reflect_ConstantPool::set_cp(jcp(), k_h->constants());
return JNIHandles::make_local(jcp()); return JNIHandles::make_local(THREAD, jcp());
} }
} }
return NULL; return NULL;
@ -2174,7 +2172,7 @@ JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAt(JNIEnv *env, jobject obj, jobject u
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
} }
Klass* k = cp->klass_at(index, CHECK_NULL); Klass* k = cp->klass_at(index, CHECK_NULL);
return (jclass) JNIHandles::make_local(k->java_mirror()); return (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
} }
JVM_END JVM_END
@ -2189,7 +2187,7 @@ JVM_ENTRY(jclass, JVM_ConstantPoolGetClassAtIfLoaded(JNIEnv *env, jobject obj, j
} }
Klass* k = ConstantPool::klass_at_if_loaded(cp, index); Klass* k = ConstantPool::klass_at_if_loaded(cp, index);
if (k == NULL) return NULL; if (k == NULL) return NULL;
return (jclass) JNIHandles::make_local(k->java_mirror()); return (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
} }
JVM_END JVM_END
@ -2219,7 +2217,7 @@ static jobject get_method_at_helper(const constantPoolHandle& cp, jint index, bo
} else { } else {
method = Reflection::new_constructor(m, CHECK_NULL); method = Reflection::new_constructor(m, CHECK_NULL);
} }
return JNIHandles::make_local(method); return JNIHandles::make_local(THREAD, method);
} }
JVM_ENTRY(jobject, JVM_ConstantPoolGetMethodAt(JNIEnv *env, jobject obj, jobject unused, jint index)) JVM_ENTRY(jobject, JVM_ConstantPoolGetMethodAt(JNIEnv *env, jobject obj, jobject unused, jint index))
@ -2266,7 +2264,7 @@ static jobject get_field_at_helper(constantPoolHandle cp, jint index, bool force
THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to look up field in target class"); THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to look up field in target class");
} }
oop field = Reflection::new_field(&fd, CHECK_NULL); oop field = Reflection::new_field(&fd, CHECK_NULL);
return JNIHandles::make_local(field); return JNIHandles::make_local(THREAD, field);
} }
JVM_ENTRY(jobject, JVM_ConstantPoolGetFieldAt(JNIEnv *env, jobject obj, jobject unusedl, jint index)) JVM_ENTRY(jobject, JVM_ConstantPoolGetFieldAt(JNIEnv *env, jobject obj, jobject unusedl, jint index))
@ -2313,7 +2311,7 @@ JVM_ENTRY(jobjectArray, JVM_ConstantPoolGetMemberRefInfoAt(JNIEnv *env, jobject
dest->obj_at_put(1, str()); dest->obj_at_put(1, str());
str = java_lang_String::create_from_symbol(member_sig, CHECK_NULL); str = java_lang_String::create_from_symbol(member_sig, CHECK_NULL);
dest->obj_at_put(2, str()); dest->obj_at_put(2, str());
return (jobjectArray) JNIHandles::make_local(dest()); return (jobjectArray) JNIHandles::make_local(THREAD, dest());
} }
JVM_END JVM_END
@ -2363,7 +2361,7 @@ JVM_ENTRY(jobjectArray, JVM_ConstantPoolGetNameAndTypeRefInfoAt(JNIEnv *env, job
dest->obj_at_put(0, str()); dest->obj_at_put(0, str());
str = java_lang_String::create_from_symbol(member_sig, CHECK_NULL); str = java_lang_String::create_from_symbol(member_sig, CHECK_NULL);
dest->obj_at_put(1, str()); dest->obj_at_put(1, str());
return (jobjectArray) JNIHandles::make_local(dest()); return (jobjectArray) JNIHandles::make_local(THREAD, dest());
} }
JVM_END JVM_END
@ -2429,7 +2427,7 @@ JVM_ENTRY(jstring, JVM_ConstantPoolGetStringAt(JNIEnv *env, jobject obj, jobject
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index"); THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Wrong type at constant pool index");
} }
oop str = cp->string_at(index, CHECK_NULL); oop str = cp->string_at(index, CHECK_NULL);
return (jstring) JNIHandles::make_local(str); return (jstring) JNIHandles::make_local(THREAD, str);
} }
JVM_END JVM_END
@ -2445,7 +2443,7 @@ JVM_ENTRY(jstring, JVM_ConstantPoolGetUTF8At(JNIEnv *env, jobject obj, jobject u
} }
Symbol* sym = cp->symbol_at(index); Symbol* sym = cp->symbol_at(index);
Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL); Handle str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
return (jstring) JNIHandles::make_local(str()); return (jstring) JNIHandles::make_local(THREAD, str());
} }
JVM_END JVM_END
@ -2502,7 +2500,7 @@ JVM_ENTRY(jobject, JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused))
JVMWrapper("JVM_AssertionStatusDirectives"); JVMWrapper("JVM_AssertionStatusDirectives");
JvmtiVMObjectAllocEventCollector oam; JvmtiVMObjectAllocEventCollector oam;
oop asd = JavaAssertions::createAssertionStatusDirectives(CHECK_NULL); oop asd = JavaAssertions::createAssertionStatusDirectives(CHECK_NULL);
return JNIHandles::make_local(env, asd); return JNIHandles::make_local(THREAD, asd);
JVM_END JVM_END
// Verification //////////////////////////////////////////////////////////////////////////////// // Verification ////////////////////////////////////////////////////////////////////////////////
@ -3284,8 +3282,8 @@ JVM_END
JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass)) JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass))
JVMWrapper("JVM_CurrentThread"); JVMWrapper("JVM_CurrentThread");
oop jthread = thread->threadObj(); oop jthread = thread->threadObj();
assert (thread != NULL, "no current thread!"); assert(jthread != NULL, "no current thread!");
return JNIHandles::make_local(env, jthread); return JNIHandles::make_local(THREAD, jthread);
JVM_END JVM_END
JVM_ENTRY(void, JVM_Interrupt(JNIEnv* env, jobject jthread)) JVM_ENTRY(void, JVM_Interrupt(JNIEnv* env, jobject jthread))
@ -3377,7 +3375,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassContext(JNIEnv *env))
result->obj_at_put(i, klass_array->at(i)->java_mirror()); result->obj_at_put(i, klass_array->at(i)->java_mirror());
} }
return (jobjectArray) JNIHandles::make_local(env, result); return (jobjectArray) JNIHandles::make_local(THREAD, result);
JVM_END JVM_END
@ -3390,7 +3388,7 @@ JVM_ENTRY(jstring, JVM_GetSystemPackage(JNIEnv *env, jstring name))
JvmtiVMObjectAllocEventCollector oam; JvmtiVMObjectAllocEventCollector oam;
char* str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name)); char* str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(name));
oop result = ClassLoader::get_system_package(str, CHECK_NULL); oop result = ClassLoader::get_system_package(str, CHECK_NULL);
return (jstring) JNIHandles::make_local(result); return (jstring) JNIHandles::make_local(THREAD, result);
JVM_END JVM_END
@ -3398,7 +3396,7 @@ JVM_ENTRY(jobjectArray, JVM_GetSystemPackages(JNIEnv *env))
JVMWrapper("JVM_GetSystemPackages"); JVMWrapper("JVM_GetSystemPackages");
JvmtiVMObjectAllocEventCollector oam; JvmtiVMObjectAllocEventCollector oam;
objArrayOop result = ClassLoader::get_system_packages(CHECK_NULL); objArrayOop result = ClassLoader::get_system_packages(CHECK_NULL);
return (jobjectArray) JNIHandles::make_local(result); return (jobjectArray) JNIHandles::make_local(THREAD, result);
JVM_END JVM_END
@ -3411,9 +3409,9 @@ JVM_ENTRY(jobject, JVM_GetAndClearReferencePendingList(JNIEnv* env))
MonitorLocker ml(Heap_lock); MonitorLocker ml(Heap_lock);
oop ref = Universe::reference_pending_list(); oop ref = Universe::reference_pending_list();
if (ref != NULL) { if (ref != NULL) {
Universe::set_reference_pending_list(NULL); Universe::clear_reference_pending_list();
} }
return JNIHandles::make_local(env, ref); return JNIHandles::make_local(THREAD, ref);
JVM_END JVM_END
JVM_ENTRY(jboolean, JVM_HasReferencePendingList(JNIEnv* env)) JVM_ENTRY(jboolean, JVM_HasReferencePendingList(JNIEnv* env))
@ -3441,7 +3439,7 @@ JVM_ENTRY(jobject, JVM_LatestUserDefinedLoader(JNIEnv *env))
vfst.skip_reflection_related_frames(); // Only needed for 1.4 reflection vfst.skip_reflection_related_frames(); // Only needed for 1.4 reflection
oop loader = vfst.method()->method_holder()->class_loader(); oop loader = vfst.method()->method_holder()->class_loader();
if (loader != NULL && !SystemDictionary::is_platform_class_loader(loader)) { if (loader != NULL && !SystemDictionary::is_platform_class_loader(loader)) {
return JNIHandles::make_local(env, loader); return JNIHandles::make_local(THREAD, loader);
} }
} }
return NULL; return NULL;
@ -3480,7 +3478,7 @@ JVM_ENTRY(jobject, JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index))
jvalue value; jvalue value;
BasicType type = Reflection::array_get(&value, a, index, CHECK_NULL); BasicType type = Reflection::array_get(&value, a, index, CHECK_NULL);
oop box = Reflection::box(&value, type, CHECK_NULL); oop box = Reflection::box(&value, type, CHECK_NULL);
return JNIHandles::make_local(env, box); return JNIHandles::make_local(THREAD, box);
JVM_END JVM_END
@ -3530,7 +3528,7 @@ JVM_ENTRY(jobject, JVM_NewArray(JNIEnv *env, jclass eltClass, jint length))
JvmtiVMObjectAllocEventCollector oam; JvmtiVMObjectAllocEventCollector oam;
oop element_mirror = JNIHandles::resolve(eltClass); oop element_mirror = JNIHandles::resolve(eltClass);
oop result = Reflection::reflect_new_array(element_mirror, length, CHECK_NULL); oop result = Reflection::reflect_new_array(element_mirror, length, CHECK_NULL);
return JNIHandles::make_local(env, result); return JNIHandles::make_local(THREAD, result);
JVM_END JVM_END
@ -3541,7 +3539,7 @@ JVM_ENTRY(jobject, JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim
oop element_mirror = JNIHandles::resolve(eltClass); oop element_mirror = JNIHandles::resolve(eltClass);
assert(dim_array->is_typeArray(), "just checking"); assert(dim_array->is_typeArray(), "just checking");
oop result = Reflection::reflect_new_multi_array(element_mirror, typeArrayOop(dim_array), CHECK_NULL); oop result = Reflection::reflect_new_multi_array(element_mirror, typeArrayOop(dim_array), CHECK_NULL);
return JNIHandles::make_local(env, result); return JNIHandles::make_local(THREAD, result);
JVM_END JVM_END
@ -3608,7 +3606,7 @@ JVM_ENTRY(jstring, JVM_InternString(JNIEnv *env, jstring str))
if (str == NULL) return NULL; if (str == NULL) return NULL;
oop string = JNIHandles::resolve_non_null(str); oop string = JNIHandles::resolve_non_null(str);
oop result = StringTable::intern(string, CHECK_NULL); oop result = StringTable::intern(string, CHECK_NULL);
return (jstring) JNIHandles::make_local(env, result); return (jstring) JNIHandles::make_local(THREAD, result);
JVM_END JVM_END
@ -3667,7 +3665,7 @@ jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init,
if (init && klass->is_instance_klass()) { if (init && klass->is_instance_klass()) {
klass->initialize(CHECK_NULL); klass->initialize(CHECK_NULL);
} }
return (jclass) JNIHandles::make_local(env, klass->java_mirror()); return (jclass) JNIHandles::make_local(THREAD, klass->java_mirror());
} }
@ -3681,14 +3679,14 @@ JVM_ENTRY(jobject, JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jo
Handle receiver(THREAD, JNIHandles::resolve(obj)); Handle receiver(THREAD, JNIHandles::resolve(obj));
objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0))); objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0)));
oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL); oop result = Reflection::invoke_method(method_handle(), receiver, args, CHECK_NULL);
jobject res = JNIHandles::make_local(env, result); jobject res = JNIHandles::make_local(THREAD, result);
if (JvmtiExport::should_post_vm_object_alloc()) { if (JvmtiExport::should_post_vm_object_alloc()) {
oop ret_type = java_lang_reflect_Method::return_type(method_handle()); oop ret_type = java_lang_reflect_Method::return_type(method_handle());
assert(ret_type != NULL, "sanity check: ret_type oop must not be NULL!"); assert(ret_type != NULL, "sanity check: ret_type oop must not be NULL!");
if (java_lang_Class::is_primitive(ret_type)) { if (java_lang_Class::is_primitive(ret_type)) {
// Only for primitive type vm allocates memory for java object. // Only for primitive type vm allocates memory for java object.
// See box() method. // See box() method.
JvmtiExport::post_vm_object_alloc(JavaThread::current(), result); JvmtiExport::post_vm_object_alloc(thread, result);
} }
} }
return res; return res;
@ -3703,9 +3701,9 @@ JVM_ENTRY(jobject, JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjec
oop constructor_mirror = JNIHandles::resolve(c); oop constructor_mirror = JNIHandles::resolve(c);
objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0))); objArrayHandle args(THREAD, objArrayOop(JNIHandles::resolve(args0)));
oop result = Reflection::invoke_constructor(constructor_mirror, args, CHECK_NULL); oop result = Reflection::invoke_constructor(constructor_mirror, args, CHECK_NULL);
jobject res = JNIHandles::make_local(env, result); jobject res = JNIHandles::make_local(THREAD, result);
if (JvmtiExport::should_post_vm_object_alloc()) { if (JvmtiExport::should_post_vm_object_alloc()) {
JvmtiExport::post_vm_object_alloc(JavaThread::current(), result); JvmtiExport::post_vm_object_alloc(thread, result);
} }
return res; return res;
JVM_END JVM_END
@ -3818,7 +3816,7 @@ JVM_ENTRY(jclass, JVM_LookupLambdaProxyClassFromArchive(JNIEnv* env,
jclass jcls = NULL; jclass jcls = NULL;
if (lambda_ik != NULL) { if (lambda_ik != NULL) {
InstanceKlass* loaded_lambda = SystemDictionaryShared::prepare_shared_lambda_proxy_class(lambda_ik, caller_ik, initialize, THREAD); InstanceKlass* loaded_lambda = SystemDictionaryShared::prepare_shared_lambda_proxy_class(lambda_ik, caller_ik, initialize, THREAD);
jcls = loaded_lambda == NULL ? NULL : (jclass) JNIHandles::make_local(env, loaded_lambda->java_mirror()); jcls = loaded_lambda == NULL ? NULL : (jclass) JNIHandles::make_local(THREAD, loaded_lambda->java_mirror());
} }
return jcls; return jcls;
#else #else
@ -3876,7 +3874,7 @@ JVM_ENTRY(jobjectArray, JVM_GetAllThreads(JNIEnv *env, jclass dummy))
threads_ah->obj_at_put(i, h()); threads_ah->obj_at_put(i, h());
} }
return (jobjectArray) JNIHandles::make_local(env, threads_ah()); return (jobjectArray) JNIHandles::make_local(THREAD, threads_ah());
JVM_END JVM_END
@ -3918,7 +3916,7 @@ JVM_ENTRY(jobjectArray, JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobject
// The JavaThread references in thread_handle_array are validated // The JavaThread references in thread_handle_array are validated
// in VM_ThreadDump::doit(). // in VM_ThreadDump::doit().
Handle stacktraces = ThreadService::dump_stack_traces(thread_handle_array, num_threads, CHECK_NULL); Handle stacktraces = ThreadService::dump_stack_traces(thread_handle_array, num_threads, CHECK_NULL);
return (jobjectArray)JNIHandles::make_local(env, stacktraces()); return (jobjectArray)JNIHandles::make_local(THREAD, stacktraces());
JVM_END JVM_END
@ -3981,7 +3979,7 @@ JVM_ENTRY(jobjectArray, JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass))
str = java_lang_String::create_from_symbol(sym, CHECK_NULL); str = java_lang_String::create_from_symbol(sym, CHECK_NULL);
dest->obj_at_put(2, str()); dest->obj_at_put(2, str());
} }
return (jobjectArray) JNIHandles::make_local(dest()); return (jobjectArray) JNIHandles::make_local(THREAD, dest());
} }
JVM_END JVM_END
@ -4011,7 +4009,7 @@ JVM_ENTRY(jobjectArray, JVM_GetVmArguments(JNIEnv *env))
Handle h = java_lang_String::create_from_platform_dependent_str(vm_args[i], CHECK_NULL); Handle h = java_lang_String::create_from_platform_dependent_str(vm_args[i], CHECK_NULL);
result_h->obj_at_put(index, h()); result_h->obj_at_put(index, h());
} }
return (jobjectArray) JNIHandles::make_local(env, result_h()); return (jobjectArray) JNIHandles::make_local(THREAD, result_h());
JVM_END JVM_END
JVM_ENTRY_NO_ENV(jint, JVM_FindSignal(const char *name)) JVM_ENTRY_NO_ENV(jint, JVM_FindSignal(const char *name))

@ -724,13 +724,13 @@ JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread
javaVFrame *jvf, GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list, jint stack_depth) { javaVFrame *jvf, GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list, jint stack_depth) {
jvmtiError err = JVMTI_ERROR_NONE; jvmtiError err = JVMTI_ERROR_NONE;
ResourceMark rm; ResourceMark rm;
HandleMark hm;
GrowableArray<MonitorInfo*>* mons = jvf->monitors(); GrowableArray<MonitorInfo*>* mons = jvf->monitors();
if (mons->is_empty()) { if (mons->is_empty()) {
return err; // this javaVFrame holds no monitors return err; // this javaVFrame holds no monitors
} }
HandleMark hm;
oop wait_obj = NULL; oop wait_obj = NULL;
{ {
// The ObjectMonitor* can't be async deflated since we are either // The ObjectMonitor* can't be async deflated since we are either
@ -1005,7 +1005,6 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec
// as lightweight locks before inflating the monitor are not included. // as lightweight locks before inflating the monitor are not included.
// We have to count the number of recursive monitor entries the hard way. // We have to count the number of recursive monitor entries the hard way.
// We pass a handle to survive any GCs along the way. // We pass a handle to survive any GCs along the way.
ResourceMark rm(current_thread);
ret.entry_count = count_locked_objects(owning_thread, hobj); ret.entry_count = count_locked_objects(owning_thread, hobj);
} }
// implied else: entry_count == 0 // implied else: entry_count == 0

@ -1221,6 +1221,44 @@ bool VM_RedefineClasses::is_unresolved_class_mismatch(const constantPoolHandle&
} // end is_unresolved_class_mismatch() } // end is_unresolved_class_mismatch()
// The bug 6214132 caused the verification to fail.
// 1. What's done in RedefineClasses() before verification:
// a) A reference to the class being redefined (_the_class) and a
// reference to new version of the class (_scratch_class) are
// saved here for use during the bytecode verification phase of
// RedefineClasses.
// b) The _java_mirror field from _the_class is copied to the
// _java_mirror field in _scratch_class. This means that a jclass
// returned for _the_class or _scratch_class will refer to the
// same Java mirror. The verifier will see the "one true mirror"
// for the class being verified.
// 2. See comments in JvmtiThreadState for what is done during verification.
class RedefineVerifyMark : public StackObj {
private:
JvmtiThreadState* _state;
Klass* _scratch_class;
Handle _scratch_mirror;
public:
RedefineVerifyMark(Klass* the_class, Klass* scratch_class,
JvmtiThreadState* state) : _state(state), _scratch_class(scratch_class)
{
_state->set_class_versions_map(the_class, scratch_class);
_scratch_mirror = Handle(_state->get_thread(), _scratch_class->java_mirror());
_scratch_class->replace_java_mirror(the_class->java_mirror());
}
~RedefineVerifyMark() {
// Restore the scratch class's mirror, so when scratch_class is removed
// the correct mirror pointing to it can be cleared.
_scratch_class->replace_java_mirror(_scratch_mirror());
_state->clear_class_versions_map();
}
};
jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) {
// For consistency allocate memory using os::malloc wrapper. // For consistency allocate memory using os::malloc wrapper.

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2020, 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
@ -247,19 +247,8 @@ class JvmtiThreadState : public CHeapObj<mtInternal> {
// RedefineClasses support // RedefineClasses support
// The bug 6214132 caused the verification to fail. // The bug 6214132 caused the verification to fail.
// //
// Below is the detailed description of the fix approach taken: // What is done at verification:
// 1. What's done in RedefineClasses() before verification: // (This seems to only apply to the old verifier.)
// a) A reference to the class being redefined (_the_class) and a
// reference to new version of the class (_scratch_class) are
// saved here for use during the bytecode verification phase of
// RedefineClasses. See RedefineVerifyMark for how these fields
// are managed.
// b) The _java_mirror field from _the_class is copied to the
// _java_mirror field in _scratch_class. This means that a jclass
// returned for _the_class or _scratch_class will refer to the
// same Java mirror. The verifier will see the "one true mirror"
// for the class being verified.
// 2. What is done at verification:
// When the verifier makes calls into the VM to ask questions about // When the verifier makes calls into the VM to ask questions about
// the class being verified, it will pass the jclass to JVM_* functions. // the class being verified, it will pass the jclass to JVM_* functions.
// The jclass is always pointing to the mirror of _the_class. // The jclass is always pointing to the mirror of _the_class.
@ -401,27 +390,4 @@ public:
void run_nmethod_entry_barriers(); void run_nmethod_entry_barriers();
}; };
class RedefineVerifyMark : public StackObj {
private:
JvmtiThreadState* _state;
Klass* _scratch_class;
OopHandle _scratch_mirror;
public:
RedefineVerifyMark(Klass* the_class, Klass* scratch_class,
JvmtiThreadState *state) : _state(state), _scratch_class(scratch_class)
{
_state->set_class_versions_map(the_class, scratch_class);
_scratch_mirror = _scratch_class->java_mirror_handle();
_scratch_class->set_java_mirror_handle(the_class->java_mirror_handle());
}
~RedefineVerifyMark() {
// Restore the scratch class's mirror, so when scratch_class is removed
// the correct mirror pointing to it can be cleared.
_scratch_class->set_java_mirror_handle(_scratch_mirror);
_state->clear_class_versions_map();
}
};
#endif // SHARE_PRIMS_JVMTITHREADSTATE_HPP #endif // SHARE_PRIMS_JVMTITHREADSTATE_HPP

@ -179,7 +179,6 @@ Handle MethodHandles::resolve_MemberName_type(Handle mname, Klass* caller, TRAPS
oop MethodHandles::init_MemberName(Handle mname, Handle target, TRAPS) { oop MethodHandles::init_MemberName(Handle mname, Handle target, TRAPS) {
// This method is used from java.lang.invoke.MemberName constructors. // This method is used from java.lang.invoke.MemberName constructors.
// It fills in the new MemberName from a java.lang.reflect.Member. // It fills in the new MemberName from a java.lang.reflect.Member.
Thread* thread = Thread::current();
oop target_oop = target(); oop target_oop = target();
Klass* target_klass = target_oop->klass(); Klass* target_klass = target_oop->klass();
if (target_klass == SystemDictionary::reflect_Field_klass()) { if (target_klass == SystemDictionary::reflect_Field_klass()) {
@ -207,7 +206,7 @@ oop MethodHandles::init_MemberName(Handle mname, Handle target, TRAPS) {
if (m == NULL || is_signature_polymorphic(m->intrinsic_id())) if (m == NULL || is_signature_polymorphic(m->intrinsic_id()))
return NULL; // do not resolve unless there is a concrete signature return NULL; // do not resolve unless there is a concrete signature
CallInfo info(m, k, CHECK_NULL); CallInfo info(m, k, CHECK_NULL);
return init_method_MemberName(mname, info); return init_method_MemberName(mname, info, THREAD);
} }
} else if (target_klass == SystemDictionary::reflect_Constructor_klass()) { } else if (target_klass == SystemDictionary::reflect_Constructor_klass()) {
oop clazz = java_lang_reflect_Constructor::clazz(target_oop); oop clazz = java_lang_reflect_Constructor::clazz(target_oop);
@ -217,13 +216,13 @@ oop MethodHandles::init_MemberName(Handle mname, Handle target, TRAPS) {
Method* m = InstanceKlass::cast(k)->method_with_idnum(slot); Method* m = InstanceKlass::cast(k)->method_with_idnum(slot);
if (m == NULL) return NULL; if (m == NULL) return NULL;
CallInfo info(m, k, CHECK_NULL); CallInfo info(m, k, CHECK_NULL);
return init_method_MemberName(mname, info); return init_method_MemberName(mname, info, THREAD);
} }
} }
return NULL; return NULL;
} }
oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) { oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, TRAPS) {
assert(info.resolved_appendix().is_null(), "only normal methods here"); assert(info.resolved_appendix().is_null(), "only normal methods here");
methodHandle m(Thread::current(), info.resolved_method()); methodHandle m(Thread::current(), info.resolved_method());
assert(m.not_null(), "null method handle"); assert(m.not_null(), "null method handle");
@ -789,7 +788,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, Klass* caller,
THROW_MSG_(vmSymbols::java_lang_InternalError(), "appendix", empty); THROW_MSG_(vmSymbols::java_lang_InternalError(), "appendix", empty);
} }
result.set_resolved_method_name(CHECK_(empty)); result.set_resolved_method_name(CHECK_(empty));
oop mname2 = init_method_MemberName(mname, result); oop mname2 = init_method_MemberName(mname, result, THREAD);
return Handle(THREAD, mname2); return Handle(THREAD, mname2);
} }
case IS_CONSTRUCTOR: case IS_CONSTRUCTOR:
@ -812,7 +811,7 @@ Handle MethodHandles::resolve_MemberName(Handle mname, Klass* caller,
} }
assert(result.is_statically_bound(), ""); assert(result.is_statically_bound(), "");
result.set_resolved_method_name(CHECK_(empty)); result.set_resolved_method_name(CHECK_(empty));
oop mname2 = init_method_MemberName(mname, result); oop mname2 = init_method_MemberName(mname, result, THREAD);
return Handle(THREAD, mname2); return Handle(THREAD, mname2);
} }
case IS_FIELD: case IS_FIELD:
@ -922,8 +921,6 @@ int MethodHandles::find_MemberNames(Klass* k,
int skip, objArrayHandle results, TRAPS) { int skip, objArrayHandle results, TRAPS) {
// %%% take caller into account! // %%% take caller into account!
Thread* thread = Thread::current();
if (k == NULL || !k->is_instance_klass()) return -1; if (k == NULL || !k->is_instance_klass()) return -1;
int rfill = 0, rlimit = results->length(), rskip = skip; int rfill = 0, rlimit = results->length(), rskip = skip;
@ -960,7 +957,7 @@ int MethodHandles::find_MemberNames(Klass* k,
if (rskip > 0) { if (rskip > 0) {
--rskip; --rskip;
} else if (rfill < rlimit) { } else if (rfill < rlimit) {
Handle result(thread, results->obj_at(rfill++)); Handle result(THREAD, results->obj_at(rfill++));
if (!java_lang_invoke_MemberName::is_instance(result())) if (!java_lang_invoke_MemberName::is_instance(result()))
return -99; // caller bug! return -99; // caller bug!
oop saved = MethodHandles::init_field_MemberName(result, st.field_descriptor()); oop saved = MethodHandles::init_field_MemberName(result, st.field_descriptor());
@ -1011,11 +1008,11 @@ int MethodHandles::find_MemberNames(Klass* k,
if (rskip > 0) { if (rskip > 0) {
--rskip; --rskip;
} else if (rfill < rlimit) { } else if (rfill < rlimit) {
Handle result(thread, results->obj_at(rfill++)); Handle result(THREAD, results->obj_at(rfill++));
if (!java_lang_invoke_MemberName::is_instance(result())) if (!java_lang_invoke_MemberName::is_instance(result()))
return -99; // caller bug! return -99; // caller bug!
CallInfo info(m, NULL, CHECK_0); CallInfo info(m, NULL, CHECK_0);
oop saved = MethodHandles::init_method_MemberName(result, info); oop saved = MethodHandles::init_method_MemberName(result, info, THREAD);
if (saved != result()) if (saved != result())
results->obj_at_put(rfill-1, saved); // show saved instance to user results->obj_at_put(rfill-1, saved); // show saved instance to user
} else if (++overflow >= overflow_limit) { } else if (++overflow >= overflow_limit) {
@ -1302,7 +1299,7 @@ JVM_ENTRY(jobject, MHN_getMemberVMInfo(JNIEnv *env, jobject igcls, jobject mname
x = mname(); x = mname();
} }
result->obj_at_put(1, x); result->obj_at_put(1, x);
return JNIHandles::make_local(env, result()); return JNIHandles::make_local(THREAD, result());
} }
JVM_END JVM_END
@ -1550,7 +1547,7 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class))
assert(SystemDictionary::MethodHandle_klass() != NULL, "should be present"); assert(SystemDictionary::MethodHandle_klass() != NULL, "should be present");
oop mirror = SystemDictionary::MethodHandle_klass()->java_mirror(); oop mirror = SystemDictionary::MethodHandle_klass()->java_mirror();
jclass MH_class = (jclass) JNIHandles::make_local(env, mirror); jclass MH_class = (jclass) JNIHandles::make_local(THREAD, mirror);
{ {
ThreadToNativeFromVM ttnfv(thread); ThreadToNativeFromVM ttnfv(thread);

@ -65,7 +65,7 @@ class MethodHandles: AllStatic {
static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing
static oop init_MemberName(Handle mname_h, Handle target_h, TRAPS); // compute vmtarget/vmindex from target static oop init_MemberName(Handle mname_h, Handle target_h, TRAPS); // compute vmtarget/vmindex from target
static oop init_field_MemberName(Handle mname_h, fieldDescriptor& fd, bool is_setter = false); static oop init_field_MemberName(Handle mname_h, fieldDescriptor& fd, bool is_setter = false);
static oop init_method_MemberName(Handle mname_h, CallInfo& info); static oop init_method_MemberName(Handle mname_h, CallInfo& info, TRAPS);
static int find_MemberNames(Klass* k, Symbol* name, Symbol* sig, static int find_MemberNames(Klass* k, Symbol* name, Symbol* sig,
int mflags, Klass* caller, int mflags, Klass* caller,
int skip, objArrayHandle results, TRAPS); int skip, objArrayHandle results, TRAPS);

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2020, 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
@ -288,6 +288,9 @@ void LiveFrameStream::fill_live_stackframe(Handle stackFrame,
const methodHandle& method, TRAPS) { const methodHandle& method, TRAPS) {
fill_stackframe(stackFrame, method, CHECK); fill_stackframe(stackFrame, method, CHECK);
if (_jvf != NULL) { if (_jvf != NULL) {
ResourceMark rm(THREAD);
HandleMark hm(THREAD);
StackValueCollection* locals = _jvf->locals(); StackValueCollection* locals = _jvf->locals();
StackValueCollection* expressions = _jvf->expressions(); StackValueCollection* expressions = _jvf->expressions();
GrowableArray<MonitorInfo*>* monitors = _jvf->monitors(); GrowableArray<MonitorInfo*>* monitors = _jvf->monitors();

@ -265,7 +265,7 @@ UNSAFE_ENTRY(jobject, Unsafe_GetReference(JNIEnv *env, jobject unsafe, jobject o
oop p = JNIHandles::resolve(obj); oop p = JNIHandles::resolve(obj);
assert_field_offset_sane(p, offset); assert_field_offset_sane(p, offset);
oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset); oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
return JNIHandles::make_local(env, v); return JNIHandles::make_local(THREAD, v);
} UNSAFE_END } UNSAFE_END
UNSAFE_ENTRY(void, Unsafe_PutReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { UNSAFE_ENTRY(void, Unsafe_PutReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
@ -279,7 +279,7 @@ UNSAFE_ENTRY(jobject, Unsafe_GetReferenceVolatile(JNIEnv *env, jobject unsafe, j
oop p = JNIHandles::resolve(obj); oop p = JNIHandles::resolve(obj);
assert_field_offset_sane(p, offset); assert_field_offset_sane(p, offset);
oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset); oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
return JNIHandles::make_local(env, v); return JNIHandles::make_local(THREAD, v);
} UNSAFE_END } UNSAFE_END
UNSAFE_ENTRY(void, Unsafe_PutReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { UNSAFE_ENTRY(void, Unsafe_PutReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
@ -291,7 +291,7 @@ UNSAFE_ENTRY(void, Unsafe_PutReferenceVolatile(JNIEnv *env, jobject unsafe, jobj
UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) { UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
oop v = *(oop*) (address) addr; oop v = *(oop*) (address) addr;
return JNIHandles::make_local(env, v); return JNIHandles::make_local(THREAD, v);
} UNSAFE_END } UNSAFE_END
#define DEFINE_GETSETOOP(java_type, Type) \ #define DEFINE_GETSETOOP(java_type, Type) \
@ -356,7 +356,7 @@ UNSAFE_LEAF(void, Unsafe_FullFence(JNIEnv *env, jobject unsafe)) {
UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls)) { UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls)) {
instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(cls), CHECK_NULL); instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(cls), CHECK_NULL);
return JNIHandles::make_local(env, i); return JNIHandles::make_local(THREAD, i);
} UNSAFE_END } UNSAFE_END
UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory0(JNIEnv *env, jobject unsafe, jlong size)) { UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory0(JNIEnv *env, jobject unsafe, jlong size)) {
@ -565,7 +565,7 @@ UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBase0(JNIEnv *env, jobject unsafe, jobje
THROW_0(vmSymbols::java_lang_IllegalArgumentException()); THROW_0(vmSymbols::java_lang_IllegalArgumentException());
} }
return JNIHandles::make_local(env, mirror); return JNIHandles::make_local(THREAD, mirror);
} UNSAFE_END } UNSAFE_END
UNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized0(JNIEnv *env, jobject unsafe, jobject clazz)) { UNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized0(JNIEnv *env, jobject unsafe, jobject clazz)) {
@ -881,7 +881,7 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass0(JNIEnv *env, jobject unsafe, j
InstanceKlass* anon_klass = Unsafe_DefineAnonymousClass_impl(env, host_class, data, cp_patches_jh, &temp_alloc, THREAD); InstanceKlass* anon_klass = Unsafe_DefineAnonymousClass_impl(env, host_class, data, cp_patches_jh, &temp_alloc, THREAD);
if (anon_klass != NULL) { if (anon_klass != NULL) {
res_jh = JNIHandles::make_local(env, anon_klass->java_mirror()); res_jh = JNIHandles::make_local(THREAD, anon_klass->java_mirror());
} }
// try/finally clause: // try/finally clause:
@ -914,7 +914,7 @@ UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeReference(JNIEnv *env, jobject un
oop p = JNIHandles::resolve(obj); oop p = JNIHandles::resolve(obj);
assert_field_offset_sane(p, offset); assert_field_offset_sane(p, offset);
oop res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x); oop res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_atomic_cmpxchg_at(p, (ptrdiff_t)offset, e, x);
return JNIHandles::make_local(env, res); return JNIHandles::make_local(THREAD, res);
} UNSAFE_END } UNSAFE_END
UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) { UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {

@ -631,7 +631,7 @@ WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env))
G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectedHeap* g1h = G1CollectedHeap::heap();
MemoryUsage usage = g1h->get_auxiliary_data_memory_usage(); MemoryUsage usage = g1h->get_auxiliary_data_memory_usage();
Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
return JNIHandles::make_local(env, h()); return JNIHandles::make_local(THREAD, h());
} }
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1AuxiliaryMemoryUsage: G1 GC is not enabled"); THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1AuxiliaryMemoryUsage: G1 GC is not enabled");
WB_END WB_END
@ -654,7 +654,7 @@ WB_ENTRY(jintArray, WB_G1MemoryNodeIds(JNIEnv* env, jobject o))
for (int i = 0; i < num_node_ids; i++) { for (int i = 0; i < num_node_ids; i++) {
result->int_at_put(i, (jint)node_ids[i]); result->int_at_put(i, (jint)node_ids[i]);
} }
return (jintArray) JNIHandles::make_local(env, result); return (jintArray) JNIHandles::make_local(THREAD, result);
} }
THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1MemoryNodeIds: G1 GC is not enabled"); THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "WB_G1MemoryNodeIds: G1 GC is not enabled");
WB_END WB_END
@ -715,7 +715,7 @@ WB_ENTRY(jlongArray, WB_G1GetMixedGCInfo(JNIEnv* env, jobject o, jint liveness))
result->long_at_put(0, rli.total_count()); result->long_at_put(0, rli.total_count());
result->long_at_put(1, rli.total_memory()); result->long_at_put(1, rli.total_memory());
result->long_at_put(2, rli.total_memory_to_free()); result->long_at_put(2, rli.total_memory_to_free());
return (jlongArray) JNIHandles::make_local(env, result); return (jlongArray) JNIHandles::make_local(THREAD, result);
WB_END WB_END
#endif // INCLUDE_G1GC #endif // INCLUDE_G1GC
@ -1678,12 +1678,11 @@ WB_ENTRY(jlong, WB_GetMethodData(JNIEnv* env, jobject wv, jobject method))
WB_END WB_END
WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o)) WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o))
return (jlong) Thread::current()->stack_size(); return (jlong) thread->stack_size();
WB_END WB_END
WB_ENTRY(jlong, WB_GetThreadRemainingStackSize(JNIEnv* env, jobject o)) WB_ENTRY(jlong, WB_GetThreadRemainingStackSize(JNIEnv* env, jobject o))
JavaThread* t = JavaThread::current(); return (jlong) thread->stack_available(os::current_stack_pointer()) - (jlong)JavaThread::stack_shadow_zone_size();
return (jlong) t->stack_available(os::current_stack_pointer()) - (jlong)JavaThread::stack_shadow_zone_size();
WB_END WB_END
@ -1790,7 +1789,7 @@ WB_ENTRY(void, WB_AssertSpecialLock(JNIEnv* env, jobject o, jboolean allowVMBloc
MutexLocker ml(new Mutex(Mutex::special, "SpecialTest_lock", allowVMBlock, sfpt_check_required), safepoint_check); MutexLocker ml(new Mutex(Mutex::special, "SpecialTest_lock", allowVMBlock, sfpt_check_required), safepoint_check);
// If the lock above succeeds, try to safepoint to test the NSV implied with this special lock. // If the lock above succeeds, try to safepoint to test the NSV implied with this special lock.
ThreadBlockInVM tbivm(JavaThread::current()); ThreadBlockInVM tbivm(thread);
WB_END WB_END
WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj)) WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
@ -1957,7 +1956,7 @@ WB_ENTRY(jobject, WB_GetResolvedReferences(JNIEnv* env, jobject wb, jclass clazz
InstanceKlass *ik = InstanceKlass::cast(k); InstanceKlass *ik = InstanceKlass::cast(k);
ConstantPool *cp = ik->constants(); ConstantPool *cp = ik->constants();
objArrayOop refs = cp->resolved_references(); objArrayOop refs = cp->resolved_references();
return (jobject)JNIHandles::make_local(env, refs); return (jobject)JNIHandles::make_local(THREAD, refs);
} else { } else {
return NULL; return NULL;
} }

@ -38,6 +38,7 @@
#include "utilities/align.hpp" #include "utilities/align.hpp"
#include "utilities/bytes.hpp" #include "utilities/bytes.hpp"
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
#include <type_traits>
enum atomic_memory_order { enum atomic_memory_order {
// The modes that align with C++11 are intended to // The modes that align with C++11 are intended to
@ -383,7 +384,7 @@ template<typename T, typename PlatformOp>
struct Atomic::LoadImpl< struct Atomic::LoadImpl<
T, T,
PlatformOp, PlatformOp,
typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value || IsPointer<T>::value>::type> typename EnableIf<IsIntegral<T>::value || std::is_enum<T>::value || IsPointer<T>::value>::type>
{ {
T operator()(T const volatile* dest) const { T operator()(T const volatile* dest) const {
// Forward to the platform handler for the size of T. // Forward to the platform handler for the size of T.
@ -435,7 +436,7 @@ template<typename T, typename PlatformOp>
struct Atomic::StoreImpl< struct Atomic::StoreImpl<
T, T, T, T,
PlatformOp, PlatformOp,
typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type> typename EnableIf<IsIntegral<T>::value || std::is_enum<T>::value>::type>
{ {
void operator()(T volatile* dest, T new_value) const { void operator()(T volatile* dest, T new_value) const {
// Forward to the platform handler for the size of T. // Forward to the platform handler for the size of T.
@ -737,7 +738,7 @@ inline bool Atomic::replace_if_null(D* volatile* dest, T* value,
template<typename T> template<typename T>
struct Atomic::CmpxchgImpl< struct Atomic::CmpxchgImpl<
T, T, T, T, T, T,
typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type> typename EnableIf<IsIntegral<T>::value || std::is_enum<T>::value>::type>
{ {
T operator()(T volatile* dest, T compare_value, T exchange_value, T operator()(T volatile* dest, T compare_value, T exchange_value,
atomic_memory_order order) const { atomic_memory_order order) const {
@ -871,7 +872,7 @@ inline T Atomic::CmpxchgByteUsingInt::operator()(T volatile* dest,
template<typename T> template<typename T>
struct Atomic::XchgImpl< struct Atomic::XchgImpl<
T, T, T, T,
typename EnableIf<IsIntegral<T>::value || IsRegisteredEnum<T>::value>::type> typename EnableIf<IsIntegral<T>::value || std::is_enum<T>::value>::type>
{ {
T operator()(T volatile* dest, T exchange_value, atomic_memory_order order) const { T operator()(T volatile* dest, T exchange_value, atomic_memory_order order) const {
// Forward to the platform handler for the size of T. // Forward to the platform handler for the size of T.

@ -906,8 +906,10 @@ void BiasedLocking::preserve_marks() {
_preserved_mark_stack = new (ResourceObj::C_HEAP, mtGC) GrowableArray<markWord>(10, mtGC); _preserved_mark_stack = new (ResourceObj::C_HEAP, mtGC) GrowableArray<markWord>(10, mtGC);
_preserved_oop_stack = new (ResourceObj::C_HEAP, mtGC) GrowableArray<Handle>(10, mtGC); _preserved_oop_stack = new (ResourceObj::C_HEAP, mtGC) GrowableArray<Handle>(10, mtGC);
ResourceMark rm;
Thread* cur = Thread::current(); Thread* cur = Thread::current();
ResourceMark rm(cur);
HandleMark hm(cur);
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) { for (JavaThreadIteratorWithHandle jtiwh; JavaThread *thread = jtiwh.next(); ) {
if (thread->has_last_Java_frame()) { if (thread->has_last_Java_frame()) {
RegisterMap rm(thread); RegisterMap rm(thread);

@ -1,5 +1,3 @@
/* /*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, 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.
@ -218,6 +216,7 @@ static bool eliminate_allocations(JavaThread* thread, int exec_mode, CompiledMet
} }
static void eliminate_locks(JavaThread* thread, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures) { static void eliminate_locks(JavaThread* thread, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures) {
HandleMark hm;
#ifndef PRODUCT #ifndef PRODUCT
bool first = true; bool first = true;
#endif #endif
@ -1535,6 +1534,8 @@ void Deoptimization::revoke_from_deopt_handler(JavaThread* thread, frame fr, Reg
if (!UseBiasedLocking) { if (!UseBiasedLocking) {
return; return;
} }
ResourceMark rm;
HandleMark hm;
GrowableArray<Handle>* objects_to_revoke = new GrowableArray<Handle>(); GrowableArray<Handle>* objects_to_revoke = new GrowableArray<Handle>();
get_monitors_from_stack(objects_to_revoke, thread, fr, map); get_monitors_from_stack(objects_to_revoke, thread, fr, map);

@ -55,43 +55,21 @@ void jni_handles_init() {
} }
jobject JNIHandles::make_local(oop obj) { jobject JNIHandles::make_local(oop obj) {
if (obj == NULL) { return make_local(Thread::current(), obj);
return NULL; // ignore null handles
} else {
Thread* thread = Thread::current();
assert(oopDesc::is_oop(obj), "not an oop");
assert(!current_thread_in_native(), "must not be in native");
return thread->active_handles()->allocate_handle(obj);
}
} }
// Used by NewLocalRef which requires NULL on out-of-memory
// optimized versions jobject JNIHandles::make_local(Thread* thread, oop obj, AllocFailType alloc_failmode) {
jobject JNIHandles::make_local(Thread* thread, oop obj) {
if (obj == NULL) { if (obj == NULL) {
return NULL; // ignore null handles return NULL; // ignore null handles
} else { } else {
assert(oopDesc::is_oop(obj), "not an oop"); assert(oopDesc::is_oop(obj), "not an oop");
assert(thread->is_Java_thread(), "not a Java thread"); assert(thread->is_Java_thread(), "not a Java thread");
assert(!current_thread_in_native(), "must not be in native"); assert(!current_thread_in_native(), "must not be in native");
return thread->active_handles()->allocate_handle(obj); return thread->active_handles()->allocate_handle(obj, alloc_failmode);
} }
} }
jobject JNIHandles::make_local(JNIEnv* env, oop obj) {
if (obj == NULL) {
return NULL; // ignore null handles
} else {
JavaThread* thread = JavaThread::thread_from_jni_environment(env);
assert(oopDesc::is_oop(obj), "not an oop");
assert(!current_thread_in_native(), "must not be in native");
return thread->active_handles()->allocate_handle(obj);
}
}
static void report_handle_allocation_failure(AllocFailType alloc_failmode, static void report_handle_allocation_failure(AllocFailType alloc_failmode,
const char* handle_kind) { const char* handle_kind) {
if (alloc_failmode == AllocFailStrategy::EXIT_OOM) { if (alloc_failmode == AllocFailStrategy::EXIT_OOM) {
@ -124,7 +102,6 @@ jobject JNIHandles::make_global(Handle obj, AllocFailType alloc_failmode) {
return res; return res;
} }
jobject JNIHandles::make_weak_global(Handle obj, AllocFailType alloc_failmode) { jobject JNIHandles::make_weak_global(Handle obj, AllocFailType alloc_failmode) {
assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
assert(!current_thread_in_native(), "must not be in native"); assert(!current_thread_in_native(), "must not be in native");
@ -365,7 +342,7 @@ void JNIHandleBlock::zap() {
} }
#endif // ASSERT #endif // ASSERT
JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread) { JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread, AllocFailType alloc_failmode) {
assert(thread == NULL || thread == Thread::current(), "sanity check"); assert(thread == NULL || thread == Thread::current(), "sanity check");
JNIHandleBlock* block; JNIHandleBlock* block;
// Check the thread-local free list for a block so we don't // Check the thread-local free list for a block so we don't
@ -383,7 +360,14 @@ JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread) {
Mutex::_no_safepoint_check_flag); Mutex::_no_safepoint_check_flag);
if (_block_free_list == NULL) { if (_block_free_list == NULL) {
// Allocate new block // Allocate new block
if (alloc_failmode == AllocFailStrategy::RETURN_NULL) {
block = new (std::nothrow) JNIHandleBlock();
if (block == NULL) {
return NULL;
}
} else {
block = new JNIHandleBlock(); block = new JNIHandleBlock();
}
_blocks_allocated++; _blocks_allocated++;
block->zap(); block->zap();
#ifndef PRODUCT #ifndef PRODUCT
@ -483,7 +467,7 @@ void JNIHandleBlock::oops_do(OopClosure* f) {
} }
jobject JNIHandleBlock::allocate_handle(oop obj) { jobject JNIHandleBlock::allocate_handle(oop obj, AllocFailType alloc_failmode) {
assert(Universe::heap()->is_in(obj), "sanity check"); assert(Universe::heap()->is_in(obj), "sanity check");
if (_top == 0) { if (_top == 0) {
// This is the first allocation or the initial block got zapped when // This is the first allocation or the initial block got zapped when
@ -531,7 +515,7 @@ jobject JNIHandleBlock::allocate_handle(oop obj) {
if (_last->_next != NULL) { if (_last->_next != NULL) {
// update last and retry // update last and retry
_last = _last->_next; _last = _last->_next;
return allocate_handle(obj); return allocate_handle(obj, alloc_failmode);
} }
// No space available, we have to rebuild free list or expand // No space available, we have to rebuild free list or expand
@ -542,12 +526,15 @@ jobject JNIHandleBlock::allocate_handle(oop obj) {
Thread* thread = Thread::current(); Thread* thread = Thread::current();
Handle obj_handle(thread, obj); Handle obj_handle(thread, obj);
// This can block, so we need to preserve obj across call. // This can block, so we need to preserve obj across call.
_last->_next = JNIHandleBlock::allocate_block(thread); _last->_next = JNIHandleBlock::allocate_block(thread, alloc_failmode);
if (_last->_next == NULL) {
return NULL;
}
_last = _last->_next; _last = _last->_next;
_allocate_before_rebuild--; _allocate_before_rebuild--;
obj = obj_handle(); obj = obj_handle();
} }
return allocate_handle(obj); // retry return allocate_handle(obj, alloc_failmode); // retry
} }
void JNIHandleBlock::rebuild_free_list() { void JNIHandleBlock::rebuild_free_list() {

@ -84,16 +84,18 @@ class JNIHandles : AllStatic {
// Local handles // Local handles
static jobject make_local(oop obj); static jobject make_local(oop obj);
static jobject make_local(JNIEnv* env, oop obj); // Fast version when env is known static jobject make_local(Thread* thread, oop obj, // Faster version when current thread is known
static jobject make_local(Thread* thread, oop obj); // Even faster version when current thread is known AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
inline static void destroy_local(jobject handle); inline static void destroy_local(jobject handle);
// Global handles // Global handles
static jobject make_global(Handle obj, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); static jobject make_global(Handle obj,
AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
static void destroy_global(jobject handle); static void destroy_global(jobject handle);
// Weak global handles // Weak global handles
static jobject make_weak_global(Handle obj, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); static jobject make_weak_global(Handle obj,
AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
static void destroy_weak_global(jobject handle); static void destroy_weak_global(jobject handle);
static bool is_global_weak_cleared(jweak handle); // Test jweak without resolution static bool is_global_weak_cleared(jweak handle); // Test jweak without resolution
@ -177,10 +179,10 @@ class JNIHandleBlock : public CHeapObj<mtInternal> {
public: public:
// Handle allocation // Handle allocation
jobject allocate_handle(oop obj); jobject allocate_handle(oop obj, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
// Block allocation and block free list management // Block allocation and block free list management
static JNIHandleBlock* allocate_block(Thread* thread = NULL); static JNIHandleBlock* allocate_block(Thread* thread = NULL, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM);
static void release_block(JNIHandleBlock* block, Thread* thread = NULL); static void release_block(JNIHandleBlock* block, Thread* thread = NULL);
// JNI PushLocalFrame/PopLocalFrame support // JNI PushLocalFrame/PopLocalFrame support

@ -27,7 +27,6 @@
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "memory/padded.hpp" #include "memory/padded.hpp"
#include "metaprogramming/isRegisteredEnum.hpp"
#include "oops/markWord.hpp" #include "oops/markWord.hpp"
#include "runtime/os.hpp" #include "runtime/os.hpp"
#include "runtime/park.hpp" #include "runtime/park.hpp"
@ -378,7 +377,4 @@ class ObjectMonitor {
void install_displaced_markword_in_object(const oop obj); void install_displaced_markword_in_object(const oop obj);
}; };
// Register for atomic operations.
template<> struct IsRegisteredEnum<ObjectMonitor::AllocationState> : public TrueType {};
#endif // SHARE_RUNTIME_OBJECTMONITOR_HPP #endif // SHARE_RUNTIME_OBJECTMONITOR_HPP

@ -27,7 +27,6 @@
#include "jvm.h" #include "jvm.h"
#include "jvmtifiles/jvmti.h" #include "jvmtifiles/jvmti.h"
#include "metaprogramming/isRegisteredEnum.hpp"
#include "metaprogramming/integralConstant.hpp" #include "metaprogramming/integralConstant.hpp"
#include "utilities/exceptions.hpp" #include "utilities/exceptions.hpp"
#include "utilities/ostream.hpp" #include "utilities/ostream.hpp"
@ -972,10 +971,6 @@ class os: AllStatic {
}; };
#ifndef _WINDOWS
template<> struct IsRegisteredEnum<os::SuspendResume::State> : public TrueType {};
#endif // !_WINDOWS
// Note that "PAUSE" is almost always used with synchronization // Note that "PAUSE" is almost always used with synchronization
// so arguably we should provide Atomic::SpinPause() instead // so arguably we should provide Atomic::SpinPause() instead
// of the global SpinPause() with C linkage. // of the global SpinPause() with C linkage.

@ -812,8 +812,7 @@ oop Reflection::new_method(const methodHandle& method, bool for_constant_pool_ac
Handle return_type(THREAD, return_type_oop); Handle return_type(THREAD, return_type_oop);
objArrayHandle exception_types = get_exception_types(method, CHECK_NULL); objArrayHandle exception_types = get_exception_types(method, CHECK_NULL);
assert(!exception_types.is_null(), "cannot return null");
if (exception_types.is_null()) return NULL;
Symbol* method_name = method->name(); Symbol* method_name = method->name();
oop name_oop = StringTable::intern(method_name, CHECK_NULL); oop name_oop = StringTable::intern(method_name, CHECK_NULL);
@ -859,7 +858,7 @@ oop Reflection::new_constructor(const methodHandle& method, TRAPS) {
if (parameter_types.is_null()) return NULL; if (parameter_types.is_null()) return NULL;
objArrayHandle exception_types = get_exception_types(method, CHECK_NULL); objArrayHandle exception_types = get_exception_types(method, CHECK_NULL);
if (exception_types.is_null()) return NULL; assert(!exception_types.is_null(), "cannot return null");
const int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS; const int modifiers = method->access_flags().as_int() & JVM_RECOGNIZED_METHOD_MODIFIERS;

@ -165,6 +165,7 @@ void javaVFrame::print_locked_object_class_name(outputStream* st, Handle obj, co
void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
Thread* THREAD = Thread::current(); Thread* THREAD = Thread::current();
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
HandleMark hm(THREAD);
// If this is the first frame and it is java.lang.Object.wait(...) // If this is the first frame and it is java.lang.Object.wait(...)
// then print out the receiver. Locals are not always available, // then print out the receiver. Locals are not always available,
@ -447,6 +448,21 @@ void interpretedVFrame::set_locals(StackValueCollection* values) const {
entryVFrame::entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) entryVFrame::entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread)
: externalVFrame(fr, reg_map, thread) {} : externalVFrame(fr, reg_map, thread) {}
MonitorInfo::MonitorInfo(oop owner, BasicLock* lock, bool eliminated, bool owner_is_scalar_replaced) {
Thread* thread = Thread::current();
if (!owner_is_scalar_replaced) {
_owner = Handle(thread, owner);
_owner_klass = Handle();
} else {
assert(eliminated, "monitor should be eliminated for scalar replaced object");
_owner = Handle();
_owner_klass = Handle(thread, owner);
}
_lock = lock;
_eliminated = eliminated;
_owner_is_scalar_replaced = owner_is_scalar_replaced;
}
#ifdef ASSERT #ifdef ASSERT
void vframeStreamCommon::found_bad_method_frame() const { void vframeStreamCommon::found_bad_method_frame() const {
// 6379830 Cut point for an assertion that occasionally fires when // 6379830 Cut point for an assertion that occasionally fires when
@ -612,6 +628,8 @@ static void print_stack_values(const char* title, StackValueCollection* values)
void javaVFrame::print() { void javaVFrame::print() {
ResourceMark rm; ResourceMark rm;
HandleMark hm;
vframe::print(); vframe::print();
tty->print("\t"); tty->print("\t");
method()->print_value(); method()->print_value();

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, 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
@ -30,6 +30,7 @@
#include "code/location.hpp" #include "code/location.hpp"
#include "oops/oop.hpp" #include "oops/oop.hpp"
#include "runtime/frame.hpp" #include "runtime/frame.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/stackValue.hpp" #include "runtime/stackValue.hpp"
#include "runtime/stackValueCollection.hpp" #include "runtime/stackValueCollection.hpp"
#include "utilities/growableArray.hpp" #include "utilities/growableArray.hpp"
@ -241,34 +242,22 @@ class entryVFrame: public externalVFrame {
// 2) the monitor lock // 2) the monitor lock
class MonitorInfo : public ResourceObj { class MonitorInfo : public ResourceObj {
private: private:
oop _owner; // the object owning the monitor Handle _owner; // the object owning the monitor
BasicLock* _lock; BasicLock* _lock;
oop _owner_klass; // klass (mirror) if owner was scalar replaced Handle _owner_klass; // klass (mirror) if owner was scalar replaced
bool _eliminated; bool _eliminated;
bool _owner_is_scalar_replaced; bool _owner_is_scalar_replaced;
public: public:
// Constructor // Constructor
MonitorInfo(oop owner, BasicLock* lock, bool eliminated, bool owner_is_scalar_replaced) { MonitorInfo(oop owner, BasicLock* lock, bool eliminated, bool owner_is_scalar_replaced);
if (!owner_is_scalar_replaced) {
_owner = owner;
_owner_klass = NULL;
} else {
assert(eliminated, "monitor should be eliminated for scalar replaced object");
_owner = NULL;
_owner_klass = owner;
}
_lock = lock;
_eliminated = eliminated;
_owner_is_scalar_replaced = owner_is_scalar_replaced;
}
// Accessors // Accessors
oop owner() const { oop owner() const {
assert(!_owner_is_scalar_replaced, "should not be called for scalar replaced object"); assert(!_owner_is_scalar_replaced, "should not be called for scalar replaced object");
return _owner; return _owner();
} }
oop owner_klass() const { oop owner_klass() const {
assert(_owner_is_scalar_replaced, "should not be called for not scalar replaced object"); assert(_owner_is_scalar_replaced, "should not be called for not scalar replaced object");
return _owner_klass; return _owner_klass();
} }
BasicLock* lock() const { return _lock; } BasicLock* lock() const { return _lock; }
bool eliminated() const { return _eliminated; } bool eliminated() const { return _eliminated; }

@ -70,6 +70,9 @@ void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) {
int index; int index;
{
ResourceMark rm;
HandleMark hm;
// Get the monitors off-stack // Get the monitors off-stack
GrowableArray<MonitorInfo*>* list = vf->monitors(); GrowableArray<MonitorInfo*>* list = vf->monitors();
@ -95,6 +98,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) {
} }
} }
} }
}
// Convert the vframe locals and expressions to off stack // Convert the vframe locals and expressions to off stack
// values. Because we will not gc all oops can be converted to // values. Because we will not gc all oops can be converted to

@ -369,23 +369,7 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
/************/ \ /************/ \
/* Universe */ \ /* Universe */ \
/************/ \ /************/ \
\
static_field(Universe, _mirrors[0], oop) \
static_field(Universe, _main_thread_group, oop) \
static_field(Universe, _system_thread_group, oop) \
static_field(Universe, _the_empty_class_klass_array, objArrayOop) \
static_field(Universe, _null_ptr_exception_instance, oop) \
static_field(Universe, _arithmetic_exception_instance, oop) \
static_field(Universe, _vm_exception, oop) \
static_field(Universe, _collectedHeap, CollectedHeap*) \ static_field(Universe, _collectedHeap, CollectedHeap*) \
static_field(Universe, _base_vtable_size, int) \
static_field(Universe, _bootstrapping, bool) \
static_field(Universe, _fully_initialized, bool) \
static_field(Universe, _verify_count, int) \
static_field(Universe, _verify_oop_mask, uintptr_t) \
static_field(Universe, _verify_oop_bits, uintptr_t) \
static_field(Universe, _non_oop_bits, intptr_t) \
\
/******************/ \ /******************/ \
/* CompressedOops */ \ /* CompressedOops */ \
/******************/ \ /******************/ \

@ -26,7 +26,6 @@
#define SHARE_SERVICES_ATTACHLISTENER_HPP #define SHARE_SERVICES_ATTACHLISTENER_HPP
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "metaprogramming/isRegisteredEnum.hpp"
#include "runtime/atomic.hpp" #include "runtime/atomic.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
@ -57,8 +56,6 @@ enum AttachListenerState {
AL_INITIALIZED AL_INITIALIZED
}; };
template<> struct IsRegisteredEnum<AttachListenerState> : public TrueType {};
class AttachListener: AllStatic { class AttachListener: AllStatic {
public: public:
static void vm_start() NOT_SERVICES_RETURN; static void vm_start() NOT_SERVICES_RETURN;

@ -508,7 +508,7 @@ JVM_ENTRY(jobjectArray, jmm_GetMemoryPools(JNIEnv* env, jobject obj))
poolArray->obj_at_put(i, ph()); poolArray->obj_at_put(i, ph());
} }
} }
return (jobjectArray) JNIHandles::make_local(env, poolArray()); return (jobjectArray) JNIHandles::make_local(THREAD, poolArray());
JVM_END JVM_END
// Returns an array of java/lang/management/MemoryManagerMXBean object // Returns an array of java/lang/management/MemoryManagerMXBean object
@ -552,7 +552,7 @@ JVM_ENTRY(jobjectArray, jmm_GetMemoryManagers(JNIEnv* env, jobject obj))
mgrArray->obj_at_put(i, ph()); mgrArray->obj_at_put(i, ph());
} }
} }
return (jobjectArray) JNIHandles::make_local(env, mgrArray()); return (jobjectArray) JNIHandles::make_local(THREAD, mgrArray());
JVM_END JVM_END
@ -565,7 +565,7 @@ JVM_ENTRY(jobject, jmm_GetMemoryPoolUsage(JNIEnv* env, jobject obj))
if (pool != NULL) { if (pool != NULL) {
MemoryUsage usage = pool->get_memory_usage(); MemoryUsage usage = pool->get_memory_usage();
Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
return JNIHandles::make_local(env, h()); return JNIHandles::make_local(THREAD, h());
} else { } else {
return NULL; return NULL;
} }
@ -580,7 +580,7 @@ JVM_ENTRY(jobject, jmm_GetPeakMemoryPoolUsage(JNIEnv* env, jobject obj))
if (pool != NULL) { if (pool != NULL) {
MemoryUsage usage = pool->get_peak_memory_usage(); MemoryUsage usage = pool->get_peak_memory_usage();
Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
return JNIHandles::make_local(env, h()); return JNIHandles::make_local(THREAD, h());
} else { } else {
return NULL; return NULL;
} }
@ -595,7 +595,7 @@ JVM_ENTRY(jobject, jmm_GetPoolCollectionUsage(JNIEnv* env, jobject obj))
if (pool != NULL && pool->is_collected_pool()) { if (pool != NULL && pool->is_collected_pool()) {
MemoryUsage usage = pool->get_last_collection_usage(); MemoryUsage usage = pool->get_last_collection_usage();
Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
return JNIHandles::make_local(env, h()); return JNIHandles::make_local(THREAD, h());
} else { } else {
return NULL; return NULL;
} }
@ -759,7 +759,7 @@ JVM_ENTRY(jobject, jmm_GetMemoryUsage(JNIEnv* env, jboolean heap))
} }
Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL); Handle obj = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
return JNIHandles::make_local(env, obj()); return JNIHandles::make_local(THREAD, obj());
JVM_END JVM_END
// Returns the boolean value of a given attribute. // Returns the boolean value of a given attribute.
@ -1274,7 +1274,7 @@ JVM_ENTRY(jobjectArray, jmm_DumpThreads(JNIEnv *env, jlongArray thread_ids, jboo
result_h->obj_at_put(index, info_obj); result_h->obj_at_put(index, info_obj);
} }
return (jobjectArray) JNIHandles::make_local(env, result_h()); return (jobjectArray) JNIHandles::make_local(THREAD, result_h());
JVM_END JVM_END
// Reset statistic. Return true if the requested statistic is reset. // Reset statistic. Return true if the requested statistic is reset.
@ -1420,23 +1420,23 @@ JVM_ENTRY(jobjectArray, jmm_GetVMGlobalNames(JNIEnv *env))
for(int i = 0; i < num_entries; i++) { for(int i = 0; i < num_entries; i++) {
res->obj_at_put(i, flags_ah->obj_at(i)); res->obj_at_put(i, flags_ah->obj_at(i));
} }
return (jobjectArray)JNIHandles::make_local(env, res); return (jobjectArray)JNIHandles::make_local(THREAD, res);
} }
return (jobjectArray)JNIHandles::make_local(env, flags_ah()); return (jobjectArray)JNIHandles::make_local(THREAD, flags_ah());
JVM_END JVM_END
// Utility function used by jmm_GetVMGlobals. Returns false if flag type // Utility function used by jmm_GetVMGlobals. Returns false if flag type
// can't be determined, true otherwise. If false is returned, then *global // can't be determined, true otherwise. If false is returned, then *global
// will be incomplete and invalid. // will be incomplete and invalid.
bool add_global_entry(JNIEnv* env, Handle name, jmmVMGlobal *global, JVMFlag *flag, TRAPS) { bool add_global_entry(Handle name, jmmVMGlobal *global, JVMFlag *flag, TRAPS) {
Handle flag_name; Handle flag_name;
if (name() == NULL) { if (name() == NULL) {
flag_name = java_lang_String::create_from_str(flag->_name, CHECK_false); flag_name = java_lang_String::create_from_str(flag->_name, CHECK_false);
} else { } else {
flag_name = name; flag_name = name;
} }
global->name = (jstring)JNIHandles::make_local(env, flag_name()); global->name = (jstring)JNIHandles::make_local(THREAD, flag_name());
if (flag->is_bool()) { if (flag->is_bool()) {
global->value.z = flag->get_bool() ? JNI_TRUE : JNI_FALSE; global->value.z = flag->get_bool() ? JNI_TRUE : JNI_FALSE;
@ -1464,7 +1464,7 @@ bool add_global_entry(JNIEnv* env, Handle name, jmmVMGlobal *global, JVMFlag *fl
global->type = JMM_VMGLOBAL_TYPE_JLONG; global->type = JMM_VMGLOBAL_TYPE_JLONG;
} else if (flag->is_ccstr()) { } else if (flag->is_ccstr()) {
Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_false); Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_false);
global->value.l = (jobject)JNIHandles::make_local(env, str()); global->value.l = (jobject)JNIHandles::make_local(THREAD, str());
global->type = JMM_VMGLOBAL_TYPE_JSTRING; global->type = JMM_VMGLOBAL_TYPE_JSTRING;
} else { } else {
global->type = JMM_VMGLOBAL_TYPE_UNKNOWN; global->type = JMM_VMGLOBAL_TYPE_UNKNOWN;
@ -1543,7 +1543,7 @@ JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env,
char* str = java_lang_String::as_utf8_string(s); char* str = java_lang_String::as_utf8_string(s);
JVMFlag* flag = JVMFlag::find_flag(str); JVMFlag* flag = JVMFlag::find_flag(str);
if (flag != NULL && if (flag != NULL &&
add_global_entry(env, sh, &globals[i], flag, THREAD)) { add_global_entry(sh, &globals[i], flag, THREAD)) {
num_entries++; num_entries++;
} else { } else {
globals[i].name = NULL; globals[i].name = NULL;
@ -1565,7 +1565,7 @@ JVM_ENTRY(jint, jmm_GetVMGlobals(JNIEnv *env,
} }
// Exclude the locked (diagnostic, experimental) flags // Exclude the locked (diagnostic, experimental) flags
if ((flag->is_unlocked() || flag->is_unlocker()) && if ((flag->is_unlocked() || flag->is_unlocker()) &&
add_global_entry(env, null_h, &globals[num_entries], flag, THREAD)) { add_global_entry(null_h, &globals[num_entries], flag, THREAD)) {
num_entries++; num_entries++;
} }
} }
@ -1750,7 +1750,7 @@ static Handle find_deadlocks(bool object_monitors_only, TRAPS) {
// //
JVM_ENTRY(jobjectArray, jmm_FindDeadlockedThreads(JNIEnv *env, jboolean object_monitors_only)) JVM_ENTRY(jobjectArray, jmm_FindDeadlockedThreads(JNIEnv *env, jboolean object_monitors_only))
Handle result = find_deadlocks(object_monitors_only != 0, CHECK_NULL); Handle result = find_deadlocks(object_monitors_only != 0, CHECK_NULL);
return (jobjectArray) JNIHandles::make_local(env, result()); return (jobjectArray) JNIHandles::make_local(THREAD, result());
JVM_END JVM_END
// Finds cycles of threads that are deadlocked on monitor locks // Finds cycles of threads that are deadlocked on monitor locks
@ -1758,7 +1758,7 @@ JVM_END
// Otherwise, returns NULL. // Otherwise, returns NULL.
JVM_ENTRY(jobjectArray, jmm_FindMonitorDeadlockedThreads(JNIEnv *env)) JVM_ENTRY(jobjectArray, jmm_FindMonitorDeadlockedThreads(JNIEnv *env))
Handle result = find_deadlocks(true, CHECK_NULL); Handle result = find_deadlocks(true, CHECK_NULL);
return (jobjectArray) JNIHandles::make_local(env, result()); return (jobjectArray) JNIHandles::make_local(THREAD, result());
JVM_END JVM_END
// Gets the information about GC extension attributes including // Gets the information about GC extension attributes including
@ -1940,7 +1940,7 @@ JVM_ENTRY(jobjectArray, jmm_GetDiagnosticCommands(JNIEnv *env))
oop cmd_name = java_lang_String::create_oop_from_str(dcmd_list->at(i), CHECK_NULL); oop cmd_name = java_lang_String::create_oop_from_str(dcmd_list->at(i), CHECK_NULL);
cmd_array->obj_at_put(i, cmd_name); cmd_array->obj_at_put(i, cmd_name);
} }
return (jobjectArray) JNIHandles::make_local(env, cmd_array()); return (jobjectArray) JNIHandles::make_local(THREAD, cmd_array());
JVM_END JVM_END
JVM_ENTRY(void, jmm_GetDiagnosticCommandInfo(JNIEnv *env, jobjectArray cmds, JVM_ENTRY(void, jmm_GetDiagnosticCommandInfo(JNIEnv *env, jobjectArray cmds,
@ -2049,7 +2049,7 @@ JVM_ENTRY(jstring, jmm_ExecuteDiagnosticCommand(JNIEnv *env, jstring commandline
bufferedStream output; bufferedStream output;
DCmd::parse_and_execute(DCmd_Source_MBean, &output, cmdline, ' ', CHECK_NULL); DCmd::parse_and_execute(DCmd_Source_MBean, &output, cmdline, ' ', CHECK_NULL);
oop result = java_lang_String::create_oop_from_str(output.as_string(), CHECK_NULL); oop result = java_lang_String::create_oop_from_str(output.as_string(), CHECK_NULL);
return (jstring) JNIHandles::make_local(env, result); return (jstring) JNIHandles::make_local(THREAD, result);
JVM_END JVM_END
JVM_ENTRY(void, jmm_SetDiagnosticFrameworkNotificationEnabled(JNIEnv *env, jboolean enabled)) JVM_ENTRY(void, jmm_SetDiagnosticFrameworkNotificationEnabled(JNIEnv *env, jboolean enabled))

@ -567,6 +567,7 @@ StackFrameInfo::StackFrameInfo(javaVFrame* jvf, bool with_lock_info) {
_locked_monitors = NULL; _locked_monitors = NULL;
if (with_lock_info) { if (with_lock_info) {
ResourceMark rm; ResourceMark rm;
HandleMark hm;
GrowableArray<MonitorInfo*>* list = jvf->locked_monitors(); GrowableArray<MonitorInfo*>* list = jvf->locked_monitors();
int length = list->length(); int length = list->length();
if (length > 0) { if (length > 0) {

@ -1095,7 +1095,11 @@ template<class T> static void swap(T& a, T& b) {
b = tmp; b = tmp;
} }
#define ARRAY_SIZE(array) (sizeof(array)/sizeof((array)[0])) // array_size_impl is a function that takes a reference to T[N] and
// returns a reference to char[N]. It is not ODR-used, so not defined.
template<typename T, size_t N> char (&array_size_impl(T (&)[N]))[N];
#define ARRAY_SIZE(array) sizeof(array_size_impl(array))
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
// Sum and product which can never overflow: they wrap, just like the // Sum and product which can never overflow: they wrap, just like the

@ -36,6 +36,7 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -83,6 +84,9 @@ final class ProcessHandleImpl implements ProcessHandle {
*/ */
private static final Executor processReaperExecutor = private static final Executor processReaperExecutor =
doPrivileged((PrivilegedAction<Executor>) () -> { doPrivileged((PrivilegedAction<Executor>) () -> {
// Initialize ThreadLocalRandom now to avoid using the smaller stack
// of the processReaper threads.
ThreadLocalRandom.current();
ThreadGroup tg = Thread.currentThread().getThreadGroup(); ThreadGroup tg = Thread.currentThread().getThreadGroup();
while (tg.getParent() != null) tg = tg.getParent(); while (tg.getParent() != null) tg = tg.getParent();

@ -43,7 +43,6 @@ import java.util.Optional;
import java.util.Spliterator; import java.util.Spliterator;
import java.util.StringJoiner; import java.util.StringJoiner;
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException; import java.util.regex.PatternSyntaxException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -1134,16 +1133,16 @@ public final class String
/** /**
* Compares this {@code String} to another {@code String}, ignoring case * Compares this {@code String} to another {@code String}, ignoring case
* considerations. Two strings are considered equal ignoring case if they * considerations. Two strings are considered equal ignoring case if they
* are of the same length and corresponding characters in the two strings * are of the same length and corresponding Unicode code points in the two
* are equal ignoring case. * strings are equal ignoring case.
* *
* <p> Two characters {@code c1} and {@code c2} are considered the same * <p> Two Unicode code points are considered the same
* ignoring case if at least one of the following is true: * ignoring case if at least one of the following is true:
* <ul> * <ul>
* <li> The two characters are the same (as compared by the * <li> The two Unicode code points are the same (as compared by the
* {@code ==} operator) * {@code ==} operator)
* <li> Calling {@code Character.toLowerCase(Character.toUpperCase(char))} * <li> Calling {@code Character.toLowerCase(Character.toUpperCase(int))}
* on each character produces the same result * on each Unicode code point produces the same result
* </ul> * </ul>
* *
* <p>Note that this method does <em>not</em> take locale into account, and * <p>Note that this method does <em>not</em> take locale into account, and
@ -1158,6 +1157,7 @@ public final class String
* false} otherwise * false} otherwise
* *
* @see #equals(Object) * @see #equals(Object)
* @see #codePoints()
*/ */
public boolean equalsIgnoreCase(String anotherString) { public boolean equalsIgnoreCase(String anotherString) {
return (this == anotherString) ? true return (this == anotherString) ? true
@ -1224,7 +1224,8 @@ public final class String
/** /**
* A Comparator that orders {@code String} objects as by * A Comparator that orders {@code String} objects as by
* {@code compareToIgnoreCase}. This comparator is serializable. * {@link #compareToIgnoreCase(String) compareToIgnoreCase}.
* This comparator is serializable.
* <p> * <p>
* Note that this Comparator does <em>not</em> take locale into account, * Note that this Comparator does <em>not</em> take locale into account,
* and will result in an unsatisfactory ordering for certain locales. * and will result in an unsatisfactory ordering for certain locales.
@ -1261,10 +1262,10 @@ public final class String
/** /**
* Compares two strings lexicographically, ignoring case * Compares two strings lexicographically, ignoring case
* differences. This method returns an integer whose sign is that of * differences. This method returns an integer whose sign is that of
* calling {@code compareTo} with normalized versions of the strings * calling {@code compareTo} with case folded versions of the strings
* where case differences have been eliminated by calling * where case differences have been eliminated by calling
* {@code Character.toLowerCase(Character.toUpperCase(character))} on * {@code Character.toLowerCase(Character.toUpperCase(int))} on
* each character. * each Unicode code point.
* <p> * <p>
* Note that this method does <em>not</em> take locale into account, * Note that this method does <em>not</em> take locale into account,
* and will result in an unsatisfactory ordering for certain locales. * and will result in an unsatisfactory ordering for certain locales.
@ -1275,6 +1276,7 @@ public final class String
* specified String is greater than, equal to, or less * specified String is greater than, equal to, or less
* than this String, ignoring case considerations. * than this String, ignoring case considerations.
* @see java.text.Collator * @see java.text.Collator
* @see #codePoints()
* @since 1.2 * @since 1.2
*/ */
public int compareToIgnoreCase(String str) { public int compareToIgnoreCase(String str) {
@ -1362,30 +1364,26 @@ public final class String
* <p> * <p>
* A substring of this {@code String} object is compared to a substring * A substring of this {@code String} object is compared to a substring
* of the argument {@code other}. The result is {@code true} if these * of the argument {@code other}. The result is {@code true} if these
* substrings represent character sequences that are the same, ignoring * substrings represent Unicode code point sequences that are the same,
* case if and only if {@code ignoreCase} is true. The substring of * ignoring case if and only if {@code ignoreCase} is true.
* this {@code String} object to be compared begins at index * The sequences {@code tsequence} and {@code osequence} are compared,
* {@code toffset} and has length {@code len}. The substring of * where {@code tsequence} is the sequence produced as if by calling
* {@code other} to be compared begins at index {@code ooffset} and * {@code this.substring(toffset, len).codePoints()} and {@code osequence}
* has length {@code len}. The result is {@code false} if and only if * is the sequence produced as if by calling
* at least one of the following is true: * {@code other.substring(ooffset, len).codePoints()}.
* <ul><li>{@code toffset} is negative. * The result is {@code true} if and only if all of the following
* <li>{@code ooffset} is negative. * are true:
* <li>{@code toffset+len} is greater than the length of this * <ul><li>{@code toffset} is non-negative.
* <li>{@code ooffset} is non-negative.
* <li>{@code toffset+len} is less than or equal to the length of this
* {@code String} object. * {@code String} object.
* <li>{@code ooffset+len} is greater than the length of the other * <li>{@code ooffset+len} is less than or equal to the length of the other
* argument. * argument.
* <li>{@code ignoreCase} is {@code false} and there is some nonnegative * <li>if {@code ignoreCase} is {@code false}, all pairs of corresponding Unicode
* integer <i>k</i> less than {@code len} such that: * code points are equal integer values; or if {@code ignoreCase} is {@code true},
* <blockquote><pre> * {@link Character#toLowerCase(int) Character.toLowerCase(}
* this.charAt(toffset+k) != other.charAt(ooffset+k) * {@link Character#toUpperCase(int)}{@code )} on all pairs of Unicode code points
* </pre></blockquote> * results in equal integer values.
* <li>{@code ignoreCase} is {@code true} and there is some nonnegative
* integer <i>k</i> less than {@code len} such that:
* <blockquote><pre>
* Character.toLowerCase(Character.toUpperCase(this.charAt(toffset+k))) !=
* Character.toLowerCase(Character.toUpperCase(other.charAt(ooffset+k)))
* </pre></blockquote>
* </ul> * </ul>
* *
* <p>Note that this method does <em>not</em> take locale into account, * <p>Note that this method does <em>not</em> take locale into account,
@ -1400,12 +1398,14 @@ public final class String
* @param other the string argument. * @param other the string argument.
* @param ooffset the starting offset of the subregion in the string * @param ooffset the starting offset of the subregion in the string
* argument. * argument.
* @param len the number of characters to compare. * @param len the number of characters (Unicode code units -
* 16bit {@code char} value) to compare.
* @return {@code true} if the specified subregion of this string * @return {@code true} if the specified subregion of this string
* matches the specified subregion of the string argument; * matches the specified subregion of the string argument;
* {@code false} otherwise. Whether the matching is exact * {@code false} otherwise. Whether the matching is exact
* or case insensitive depends on the {@code ignoreCase} * or case insensitive depends on the {@code ignoreCase}
* argument. * argument.
* @see #codePoints()
*/ */
public boolean regionMatches(boolean ignoreCase, int toffset, public boolean regionMatches(boolean ignoreCase, int toffset,
String other, int ooffset, int len) { String other, int ooffset, int len) {

@ -319,25 +319,92 @@ final class StringUTF16 {
} }
public static int compareToCI(byte[] value, byte[] other) { public static int compareToCI(byte[] value, byte[] other) {
int len1 = length(value); return compareToCIImpl(value, 0, length(value), other, 0, length(other));
int len2 = length(other); }
int lim = Math.min(len1, len2);
for (int k = 0; k < lim; k++) { private static int compareToCIImpl(byte[] value, int toffset, int tlen,
char c1 = getChar(value, k); byte[] other, int ooffset, int olen) {
char c2 = getChar(other, k); int tlast = toffset + tlen;
if (c1 != c2) { int olast = ooffset + olen;
c1 = Character.toUpperCase(c1); assert toffset >= 0 && ooffset >= 0;
c2 = Character.toUpperCase(c2); assert tlast <= length(value);
if (c1 != c2) { assert olast <= length(other);
c1 = Character.toLowerCase(c1);
c2 = Character.toLowerCase(c2); for (int k1 = toffset, k2 = ooffset; k1 < tlast && k2 < olast; k1++, k2++) {
if (c1 != c2) { int cp1 = (int)getChar(value, k1);
return c1 - c2; int cp2 = (int)getChar(other, k2);
if (cp1 == cp2 || compareCodePointCI(cp1, cp2) == 0) {
continue;
}
// Check for supplementary characters case
cp1 = codePointIncluding(value, cp1, k1, toffset, tlast);
if (cp1 < 0) {
k1++;
cp1 -= cp1;
}
cp2 = codePointIncluding(other, cp2, k2, ooffset, olast);
if (cp2 < 0) {
k2++;
cp2 -= cp2;
}
int diff = compareCodePointCI(cp1, cp2);
if (diff != 0) {
return diff;
} }
} }
return tlen - olen;
}
// Case insensitive comparison of two code points
private static int compareCodePointCI(int cp1, int cp2) {
// try converting both characters to uppercase.
// If the results match, then the comparison scan should
// continue.
cp1 = Character.toUpperCase(cp1);
cp2 = Character.toUpperCase(cp2);
if (cp1 != cp2) {
// Unfortunately, conversion to uppercase does not work properly
// for the Georgian alphabet, which has strange rules about case
// conversion. So we need to make one last check before
// exiting.
cp1 = Character.toLowerCase(cp1);
cp2 = Character.toLowerCase(cp2);
if (cp1 != cp2) {
return cp1 - cp2;
} }
} }
return len1 - len2; return 0;
}
// Returns a code point from the code unit pointed by "index". If it is
// not a surrogate or an unpaired surrogate, then the code unit is
// returned as is. Otherwise, it is combined with the code unit before
// or after, depending on the type of the surrogate at index, to make a
// supplementary code point. The return value will be negated if the code
// unit pointed by index is a high surrogate, and index + 1 is a low surrogate.
private static int codePointIncluding(byte[] ba, int cp, int index, int start, int end) {
// fast check
if (!Character.isSurrogate((char)cp)) {
return cp;
}
if (Character.isLowSurrogate((char)cp)) {
if (index > start) {
char c = getChar(ba, index - 1);
if (Character.isHighSurrogate(c)) {
return Character.toCodePoint(c, (char)cp);
}
}
} else if (index + 1 < end) { // cp == high surrogate
char c = getChar(ba, index + 1);
if (Character.isLowSurrogate(c)) {
// negate the code point
return - Character.toCodePoint((char)cp, c);
}
}
return cp;
} }
public static int compareToCI_Latin1(byte[] value, byte[] other) { public static int compareToCI_Latin1(byte[] value, byte[] other) {
@ -716,34 +783,7 @@ final class StringUTF16 {
public static boolean regionMatchesCI(byte[] value, int toffset, public static boolean regionMatchesCI(byte[] value, int toffset,
byte[] other, int ooffset, int len) { byte[] other, int ooffset, int len) {
int last = toffset + len; return compareToCIImpl(value, toffset, len, other, ooffset, len) == 0;
assert toffset >= 0 && ooffset >= 0;
assert ooffset + len <= length(other);
assert last <= length(value);
while (toffset < last) {
char c1 = getChar(value, toffset++);
char c2 = getChar(other, ooffset++);
if (c1 == c2) {
continue;
}
// try converting both characters to uppercase.
// If the results match, then the comparison scan should
// continue.
char u1 = Character.toUpperCase(c1);
char u2 = Character.toUpperCase(c2);
if (u1 == u2) {
continue;
}
// Unfortunately, conversion to uppercase does not work properly
// for the Georgian alphabet, which has strange rules about case
// conversion. So we need to make one last check before
// exiting.
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
continue;
}
return false;
}
return true;
} }
public static boolean regionMatchesCI_Latin1(byte[] value, int toffset, public static boolean regionMatchesCI_Latin1(byte[] value, int toffset,

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, 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
@ -60,6 +60,11 @@ import java.security.spec.AlgorithmParameterSpec;
public abstract class AlgorithmParameterGeneratorSpi { public abstract class AlgorithmParameterGeneratorSpi {
/**
* Constructor for subclasses to call.
*/
public AlgorithmParameterGeneratorSpi() {}
/** /**
* Initializes this parameter generator for a certain size * Initializes this parameter generator for a certain size
* and source of randomness. * and source of randomness.

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, 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,6 +50,11 @@ import java.security.spec.InvalidParameterSpecException;
public abstract class AlgorithmParametersSpi { public abstract class AlgorithmParametersSpi {
/**
* Constructor for subclasses to call.
*/
public AlgorithmParametersSpi() {}
/** /**
* Initializes this parameters object using the parameters * Initializes this parameters object using the parameters
* specified in {@code paramSpec}. * specified in {@code paramSpec}.

@ -69,6 +69,11 @@ import java.security.spec.InvalidKeySpecException;
public abstract class KeyFactorySpi { public abstract class KeyFactorySpi {
/**
* Constructor for subclasses to call.
*/
public KeyFactorySpi() {}
/** /**
* Generates a public key object from the provided key * Generates a public key object from the provided key
* specification (key material). * specification (key material).

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, 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
@ -58,6 +58,11 @@ import java.security.spec.AlgorithmParameterSpec;
public abstract class KeyPairGeneratorSpi { public abstract class KeyPairGeneratorSpi {
/**
* Constructor for subclasses to call.
*/
public KeyPairGeneratorSpi() {}
/** /**
* Initializes the key pair generator for a certain keysize, using * Initializes the key pair generator for a certain keysize, using
* the default parameter set. * the default parameter set.

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2020, 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
@ -53,6 +53,11 @@ import javax.security.auth.callback.*;
public abstract class KeyStoreSpi { public abstract class KeyStoreSpi {
/**
* Constructor for subclasses to call.
*/
public KeyStoreSpi() {}
/** /**
* Returns the key associated with the given alias, using the given * Returns the key associated with the given alias, using the given
* password to recover it. The key must have been associated with * password to recover it. The key must have been associated with

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, 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
@ -54,6 +54,11 @@ public abstract class MessageDigestSpi {
// for re-use in engineUpdate(ByteBuffer input) // for re-use in engineUpdate(ByteBuffer input)
private byte[] tempArray; private byte[] tempArray;
/**
* Constructor for subclasses to call.
*/
public MessageDigestSpi() {}
/** /**
* Returns the digest length in bytes. * Returns the digest length in bytes.
* *

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, 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
@ -102,6 +102,11 @@ public abstract class PermissionCollection implements java.io.Serializable {
// when set, add will throw an exception. // when set, add will throw an exception.
private volatile boolean readOnly; private volatile boolean readOnly;
/**
* Constructor for subclasses to call.
*/
public PermissionCollection() {}
/** /**
* Adds a permission object to the current collection of permission objects. * Adds a permission object to the current collection of permission objects.
* *

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, 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
@ -87,6 +87,11 @@ import sun.security.util.SecurityConstants;
public abstract class Policy { public abstract class Policy {
/**
* Constructor for subclasses to call.
*/
public Policy() {}
/** /**
* A read-only empty PermissionCollection instance. * A read-only empty PermissionCollection instance.
* @since 1.6 * @since 1.6

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2020, 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
@ -44,6 +44,11 @@ package java.security;
public abstract class PolicySpi { public abstract class PolicySpi {
/**
* Constructor for subclasses to call.
*/
public PolicySpi() {}
/** /**
* Check whether the policy has granted a Permission to a ProtectionDomain. * Check whether the policy has granted a Permission to a ProtectionDomain.
* *

@ -52,6 +52,11 @@ import sun.security.jca.JCAUtil;
public abstract class SignatureSpi { public abstract class SignatureSpi {
/**
* Constructor for subclasses to call.
*/
public SignatureSpi() {}
/** /**
* Application-specified source of randomness. * Application-specified source of randomness.
*/ */

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2020, 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
@ -65,6 +65,11 @@ import java.security.NoSuchProviderException;
public abstract class CertificateFactorySpi { public abstract class CertificateFactorySpi {
/**
* Constructor for subclasses to call.
*/
public CertificateFactorySpi() {}
/** /**
* Generates a certificate object and initializes it with * Generates a certificate object and initializes it with
* the data read from the input stream {@code inStream}. * the data read from the input stream {@code inStream}.

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2020, 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
@ -67,6 +67,11 @@ import sun.security.x509.X509CRLEntryImpl;
public abstract class X509CRLEntry implements X509Extension { public abstract class X509CRLEntry implements X509Extension {
/**
* Constructor for subclasses to call.
*/
public X509CRLEntry() {}
/** /**
* Compares this CRL entry for equality with the given * Compares this CRL entry for equality with the given
* object. If the {@code other} object is an * object. If the {@code other} object is an

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2020, 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
@ -30,7 +30,6 @@ import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import sun.nio.cs.ISO_8859_1; import sun.nio.cs.ISO_8859_1;
@ -963,10 +962,13 @@ public class Base64 {
private final boolean isMIME; private final boolean isMIME;
private final int[] base64; // base64 -> byte mapping private final int[] base64; // base64 -> byte mapping
private int bits = 0; // 24-bit buffer for decoding private int bits = 0; // 24-bit buffer for decoding
private int nextin = 18; // next available "off" in "bits" for input;
// -> 18, 12, 6, 0 /* writing bit pos inside bits; one of 24 (left, msb), 18, 12, 6, 0 */
private int nextout = -8; // next available "off" in "bits" for output; private int wpos = 0;
// -> 8, 0, -8 (no byte for output)
/* reading bit pos inside bits: one of 24 (left, msb), 16, 8, 0 */
private int rpos = 0;
private boolean eof = false; private boolean eof = false;
private boolean closed = false; private boolean closed = false;
@ -983,107 +985,153 @@ public class Base64 {
return read(sbBuf, 0, 1) == -1 ? -1 : sbBuf[0] & 0xff; return read(sbBuf, 0, 1) == -1 ? -1 : sbBuf[0] & 0xff;
} }
private int eof(byte[] b, int off, int len, int oldOff) private int leftovers(byte[] b, int off, int pos, int limit) {
throws IOException
{
eof = true; eof = true;
if (nextin != 18) {
if (nextin == 12) /*
throw new IOException("Base64 stream has one un-decoded dangling byte."); * We use a loop here, as this method is executed only a few times.
// treat ending xx/xxx without padding character legal. * Unrolling the loop would probably not contribute much here.
// same logic as v == '=' below */
b[off++] = (byte)(bits >> (16)); while (rpos - 8 >= wpos && pos != limit) {
if (nextin == 0) { // only one padding byte rpos -= 8;
if (len == 1) { // no enough output space b[pos++] = (byte) (bits >> rpos);
bits >>= 8; // shift to lowest byte
nextout = 0;
} else {
b[off++] = (byte) (bits >> 8);
} }
} return pos - off != 0 || rpos - 8 >= wpos ? pos - off : -1;
}
return off == oldOff ? -1 : off - oldOff;
} }
private int padding(byte[] b, int off, int len, int oldOff) private int eof(byte[] b, int off, int pos, int limit) throws IOException {
throws IOException /*
{ * pos != limit
// = shiftto==18 unnecessary padding *
// x= shiftto==12 dangling x, invalid unit * wpos == 18: x dangling single x, invalid unit
// xx= shiftto==6 && missing last '=' * accept ending xx or xxx without padding characters
// xx=y or last is not '=' */
if (nextin == 18 || nextin == 12 || if (wpos == 18) {
nextin == 6 && is.read() != '=') { throw new IOException("Base64 stream has one un-decoded dangling byte.");
throw new IOException("Illegal base64 ending sequence:" + nextin);
} }
b[off++] = (byte)(bits >> (16)); rpos = 24;
if (nextin == 0) { // only one padding byte return leftovers(b, off, pos, limit);
if (len == 1) { // no enough output space
bits >>= 8; // shift to lowest byte
nextout = 0;
} else {
b[off++] = (byte) (bits >> 8);
} }
private int padding(byte[] b, int off, int pos, int limit) throws IOException {
/*
* pos != limit
*
* wpos == 24: = (unnecessary padding)
* wpos == 18: x= (dangling single x, invalid unit)
* wpos == 12 and missing last '=': xx= (invalid padding)
* wpos == 12 and last is not '=': xx=x (invalid padding)
*/
if (wpos >= 18 || wpos == 12 && is.read() != '=') {
throw new IOException("Illegal base64 ending sequence:" + wpos);
} }
eof = true; rpos = 24;
return off - oldOff; return leftovers(b, off, pos, limit);
} }
@Override @Override
public int read(byte[] b, int off, int len) throws IOException { public int read(byte[] b, int off, int len) throws IOException {
if (closed) if (closed) {
throw new IOException("Stream is closed"); throw new IOException("Stream is closed");
if (eof && nextout < 0) // eof and no leftover
return -1;
if (off < 0 || len < 0 || len > b.length - off)
throw new IndexOutOfBoundsException();
int oldOff = off;
while (nextout >= 0) { // leftover output byte(s) in bits buf
if (len == 0)
return off - oldOff;
b[off++] = (byte)(bits >> nextout);
len--;
nextout -= 8;
} }
Objects.checkFromIndexSize(off, len, b.length);
if (len == 0) {
return 0;
}
/*
* Rather than keeping 2 running vars (e.g., off and len),
* we only keep one (pos), while definitely fixing the boundaries
* of the range [off, limit).
* More specifically, each use of pos as an index in b meets
* pos - off >= 0 & limit - pos > 0
*
* Note that limit can overflow to Integer.MIN_VALUE. However,
* as long as comparisons with pos are as coded, there's no harm.
*/
int pos = off;
final int limit = off + len;
if (eof) {
return leftovers(b, off, pos, limit);
}
/*
* Leftovers from previous invocation; here, wpos = 0.
* There can be at most 2 leftover bytes (rpos <= 16).
* Further, b has at least one free place.
*
* The logic could be coded as a loop, (as in method leftovers())
* but the explicit "unrolling" makes it possible to generate
* better byte extraction code.
*/
if (rpos == 16) {
b[pos++] = (byte) (bits >> 8);
rpos = 8;
if (pos == limit) {
return len;
}
}
if (rpos == 8) {
b[pos++] = (byte) bits;
rpos = 0;
if (pos == limit) {
return len;
}
}
bits = 0; bits = 0;
while (len > 0) { wpos = 24;
int v = is.read(); for (;;) {
/* pos != limit & rpos == 0 */
final int i = is.read();
if (i < 0) {
return eof(b, off, pos, limit);
}
final int v = base64[i];
if (v < 0) {
/*
* i not in alphabet, thus
* v == -2: i is '=', the padding
* v == -1: i is something else, typically CR or LF
*/
if (v == -1) { if (v == -1) {
return eof(b, off, len, oldOff); if (isMIME) {
continue;
} }
if ((v = base64[v]) < 0) { throw new IOException("Illegal base64 character 0x" +
if (v == -2) { // padding byte(s) Integer.toHexString(i));
return padding(b, off, len, oldOff);
} }
if (v == -1) { return padding(b, off, pos, limit);
if (!isMIME)
throw new IOException("Illegal base64 character " +
Integer.toString(v, 16));
continue; // skip if for rfc2045
} }
// neve be here wpos -= 6;
bits |= v << wpos;
if (wpos != 0) {
continue;
} }
bits |= (v << nextin); if (limit - pos >= 3) {
if (nextin == 0) { /* frequently taken fast path, no need to track rpos */
nextin = 18; // clear for next in b[pos++] = (byte) (bits >> 16);
b[off++] = (byte)(bits >> 16); b[pos++] = (byte) (bits >> 8);
if (len == 1) { b[pos++] = (byte) bits;
nextout = 8; // 2 bytes left in bits
break;
}
b[off++] = (byte)(bits >> 8);
if (len == 2) {
nextout = 0; // 1 byte left in bits
break;
}
b[off++] = (byte)bits;
len -= 3;
bits = 0; bits = 0;
} else { wpos = 24;
nextin -= 6; if (pos == limit) {
return len;
} }
continue;
}
/* b has either 1 or 2 free places */
b[pos++] = (byte) (bits >> 16);
if (pos == limit) {
rpos = 16;
return len;
}
b[pos++] = (byte) (bits >> 8);
/* pos == limit, no need for an if */
rpos = 8;
return len;
} }
return off - oldOff;
} }
@Override @Override

@ -76,6 +76,11 @@ import java.util.List;
*/ */
public abstract class AbstractExecutorService implements ExecutorService { public abstract class AbstractExecutorService implements ExecutorService {
/**
* Constructor for subclasses to call.
*/
public AbstractExecutorService() {}
/** /**
* Returns a {@code RunnableFuture} for the given runnable and default * Returns a {@code RunnableFuture} for the given runnable and default
* value. * value.

@ -242,6 +242,11 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
private static final int SIGNAL = 1 << 16; // true if joiner waiting private static final int SIGNAL = 1 << 16; // true if joiner waiting
private static final int SMASK = 0xffff; // short bits for tags private static final int SMASK = 0xffff; // short bits for tags
/**
* Constructor for subclasses to call.
*/
public ForkJoinTask() {}
static boolean isExceptionalStatus(int s) { // needed by subclasses static boolean isExceptionalStatus(int s) { // needed by subclasses
return (s & THROWN) != 0; return (s & THROWN) != 0;
} }

@ -165,6 +165,11 @@ package java.util.concurrent;
public abstract class RecursiveAction extends ForkJoinTask<Void> { public abstract class RecursiveAction extends ForkJoinTask<Void> {
private static final long serialVersionUID = 5232453952276485070L; private static final long serialVersionUID = 5232453952276485070L;
/**
* Constructor for subclasses to call.
*/
public RecursiveAction() {}
/** /**
* The main computation performed by this task. * The main computation performed by this task.
*/ */

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