This commit is contained in:
J. Duke 2021-02-05 12:07:57 -08:00
commit eab53bafad
78 changed files with 2435 additions and 978 deletions

View File

@ -417,9 +417,43 @@ b25838a28195f4b6dab34668411eedd2d366a16c jdk-9+169
2c25fc24103251f9711a1c280c31e1e41016d90f jdk-9+172
88d7fd969e7df0e07a53b201cfd29393ca33ede9 jdk-9+173
5466f409346e0446ee9a6daeb7f5d75c8fc76823 jdk-9+174
023f93e511bae768203c33bb8681f82ee75014da jdk-9.0.1+00
023f93e511bae768203c33bb8681f82ee75014da jdk-9.0.3+00
8f7227c6012b0051ea4e0bcee040c627bf699b88 jdk-9+175
84777531d994ef70163d35078ec9c4127f2eadb5 jdk-9+176
a4371edb589c60db01142e45c317adb9ccbcb083 jdk-9+177
ec4159ebe7050fcc5dcee8a2d150cf948ecc97db jdk-9+178
252475ccfd84cc249f8d6faf4b7806b5e2c384ce jdk-9+179
d2982a786f53814367698e63efe6349c9128e1db jdk-9+180
b656dea9398ef601f7fc08d1a5157a560e0ccbe0 jdk-9+181
d73368c690d4f1ab188cf306f4b27218e28596b6 jdk-9.0.3+1
ede48839f34b0b74210e2e081872a3c12d5339ab jdk-9.0.3+2
086e9950ebfa8a0239018ade61f59b7c539bacc9 jdk-9.0.3+3
2c95bee2722f2396b709b384473c07291a7d1e4b jdk-9.0.3+4
d24281b60e0bb6d441ec3a9440e7daa322bbc822 jdk-9.0.3+5
489c57f8e1c0f6fa34de86f8ed8f98a809cba4a9 jdk-9.0.3+6
9d5aca497123931d52625b3539a8549d98728622 jdk-9.0.3+7
eaa4ea516c7f1e31c8e0faaec3ef981eb2919ae3 jdk-9.0.3+8
a31dfd85bee9c16aac1e65dfbe81d1c5fe443c2c jdk-9.0.3+9
9acb1002f33e257e932a188632969e45cc32e66c jdk-9.0.1+10
9acb1002f33e257e932a188632969e45cc32e66c jdk-9.0.1+10
0000000000000000000000000000000000000000 jdk-9.0.1+10
0000000000000000000000000000000000000000 jdk-9.0.1+10
5a9191c980ca3ada63b234e2b9ec6dc23bd37595 jdk-9.0.1+10
e6edc89f5b2dc6dacd6041305e942a3f04a25ce5 jdk-9.0.1+11
3a64fdb24a8c26e2d7d32864dad4425a9496b90d jdk-9.0.4+00
726bf8524f7d3780518ada8648488ad4a7bfe6a2 jdk-9.0.4+1
8055b6778ac8fc6bb165082230951cc8f146f8fd jdk-9.0.4+2
572ea0db1d87a1d2fcc01f73ffbcfb78bd5688f4 jdk-9.0.4+3
0053ace2e9e484fb52d00ec961e24805d0aae04a jdk-9.0.4+4
73d63ccf56f46f258f367ed72633f0f5cc229680 jdk-9.0.4+5
86219e4c9f8cd730bacd2f6080b6ac1dea7a0226 jdk-9.0.4+6
9aba57f3071362ed7f2326d737506863b9d2646f jdk-9.0.4+7
a4f0515fe6da55cfe74dec3e6e30b69c9693d133 jdk-9.0.4+8
a4f0515fe6da55cfe74dec3e6e30b69c9693d133 jdk-9.0.4+8
0000000000000000000000000000000000000000 jdk-9.0.4+8
0000000000000000000000000000000000000000 jdk-9.0.4+8
953d306b203e7d0808cb842a51e006fddc41b6c2 jdk-9.0.4+8
c6f4c28a56ef14fb9a41303390b9584976765502 jdk-9.0.4+9
409c6b8aa5cae19a701ddd2fb09f85fb9af7da78 jdk-9.0.4+10
620cbf135de96df32c78c2693cfbf275dec1cb4d jdk-9.0.4+11

View File

@ -1 +1,2 @@
project=jdk9
bugids=dup

37
ADDITIONAL_LICENSE_INFO Normal file
View File

@ -0,0 +1,37 @@
ADDITIONAL INFORMATION ABOUT LICENSING
Certain files distributed by Oracle America, Inc. and/or its affiliates are
subject to the following clarification and special exception to the GPLv2,
based on the GNU Project exception for its Classpath libraries, known as the
GNU Classpath Exception.
Note that Oracle includes multiple, independent programs in this software
package. Some of those programs are provided under licenses deemed
incompatible with the GPLv2 by the Free Software Foundation and others.
For example, the package includes programs licensed under the Apache
License, Version 2.0 and may include FreeType. Such programs are licensed
to you under their original licenses.
Oracle facilitates your further distribution of this package by adding the
Classpath Exception to the necessary parts of its GPLv2 code, which permits
you to use that code in combination with other independent modules not
licensed under the GPLv2. However, note that this would not permit you to
commingle code under an incompatible license with Oracle's GPLv2 licensed
code by, for example, cutting and pasting such code into a file also
containing Oracle's GPLv2 licensed code and then distributing the result.
Additionally, if you were to remove the Classpath Exception from any of the
files to which it applies and distribute the result, you would likely be
required to license some or all of the other code in that distribution under
the GPLv2 as well, and since the GPLv2 is incompatible with the license terms
of some items included in the distribution by Oracle, removing the Classpath
Exception could therefore effectively compromise your ability to further
distribute the package.
Failing to distribute notices associated with some files may also create
unexpected legal consequences.
Proceed with caution and we recommend that you obtain the advice of a lawyer
skilled in open source matters before removing the Classpath Exception or
making modifications to this package which may subsequently be redistributed
and/or involve the use of third party software.

View File

@ -1090,10 +1090,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS],
# We can build without it.
LDD="true"
fi
BASIC_PATH_PROGS(OTOOL, otool)
if test "x$OTOOL" = "x"; then
OTOOL="true"
fi
BASIC_PATH_PROGS(READELF, [greadelf readelf])
BASIC_PATH_PROGS(DOT, dot)
BASIC_PATH_PROGS(HG, hg)

File diff suppressed because it is too large Load Diff

View File

@ -443,20 +443,31 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE],
fi
AC_MSG_RESULT([$BUNDLE_FREETYPE])
fi # end freetype needed
FREETYPE_LICENSE=""
if test "x$with_freetype_license" = "xyes"; then
AC_MSG_ERROR([--with-freetype-license must have a value])
elif test "x$with_freetype_license" != "x"; then
AC_MSG_CHECKING([for freetype license])
AC_MSG_RESULT([$with_freetype_license])
FREETYPE_LICENSE="$with_freetype_license"
BASIC_FIXUP_PATH(FREETYPE_LICENSE)
if test ! -f "$FREETYPE_LICENSE"; then
AC_MSG_ERROR([$FREETYPE_LICENSE cannot be found])
if test "x$BUNDLE_FREETYPE" = xyes; then
FREETYPE_LICENSE=""
AC_MSG_CHECKING([for freetype license])
if test "x$with_freetype_license" = "xyes"; then
AC_MSG_RESULT([no])
AC_MSG_ERROR([--with-freetype-license must have a value])
elif test "x$with_freetype_license" != "x"; then
AC_MSG_RESULT([$with_freetype_license])
FREETYPE_LICENSE="$with_freetype_license"
BASIC_FIXUP_PATH(FREETYPE_LICENSE)
if test ! -f "$FREETYPE_LICENSE"; then
AC_MSG_ERROR([$FREETYPE_LICENSE cannot be found])
fi
else
if test "x$with_freetype" != "x" && test -f $with_freetype/freetype.md; then
FREETYPE_LICENSE="$with_freetype/freetype.md"
AC_MSG_RESULT([$FREETYPE_LICENSE])
BASIC_FIXUP_PATH(FREETYPE_LICENSE)
else
AC_MSG_RESULT([no])
fi
fi
fi
fi
fi # end freetype needed
AC_SUBST(FREETYPE_BUNDLE_LIB_PATH)
AC_SUBST(FREETYPE_CFLAGS)

View File

@ -483,6 +483,7 @@ GNM:=@GNM@
STRIP:=@STRIP@
LIPO:=@LIPO@
INSTALL_NAME_TOOL:=@INSTALL_NAME_TOOL@
# Options to linker to specify a mapfile.
# (Note absence of := assignment, because we do not want to evaluate the macro body here)

View File

@ -628,6 +628,10 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_EXTRA],
if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then
BASIC_PATH_PROGS(LIPO, lipo)
BASIC_FIXUP_EXECUTABLE(LIPO)
BASIC_REQUIRE_PROGS(OTOOL, otool)
BASIC_FIXUP_EXECUTABLE(OTOOL)
BASIC_REQUIRE_PROGS(INSTALL_NAME_TOOL, install_name_tool)
BASIC_FIXUP_EXECUTABLE(INSTALL_NAME_TOOL)
fi
if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,7 @@
DEFAULT_VERSION_MAJOR=9
DEFAULT_VERSION_MINOR=0
DEFAULT_VERSION_SECURITY=0
DEFAULT_VERSION_SECURITY=4
DEFAULT_VERSION_PATCH=0
LAUNCHER_NAME=openjdk

View File

@ -387,7 +387,7 @@ var getJibProfilesCommon = function (input, data) {
// on such hardware.
if (input.build_cpu == "sparcv9") {
var cpu_brand = $EXEC("bash -c \"kstat -m cpu_info | grep brand | head -n1 | awk '{ print \$2 }'\"");
if (cpu_brand.trim().match('SPARC-.7')) {
if (cpu_brand.trim().match('SPARC-.[78]')) {
boot_jdk_revision = "8u20";
boot_jdk_subdirpart = "1.8.0_20";
}
@ -435,7 +435,7 @@ var getJibProfilesProfiles = function (input, common, data) {
"macosx-x64": {
target_os: "macosx",
target_cpu: "x64",
dependencies: ["devkit"],
dependencies: ["devkit", "freetype"],
configure_args: concat(common.configure_args_64bit, "--with-zlib=system"),
},
@ -728,9 +728,9 @@ var getJibProfilesProfiles = function (input, common, data) {
jdk: {
local: "bundles/\\(jdk.*bin.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/linux-x64/jdk-" + data.version
"bundles/openjdk/GPL/linux-x64/openjdk-" + data.version
+ "_linux-x64_bin.tar.gz",
"bundles/openjdk/GPL/linux-x64/\\1"
"bundles/openjdk/GPL/linux-x64/open\\1"
],
subdir: "jdk-" + data.version
},
@ -741,17 +741,17 @@ var getJibProfilesProfiles = function (input, common, data) {
test: {
local: "bundles/\\(jdk.*bin-tests.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/linux-x64/jdk-" + data.version
"bundles/openjdk/GPL/linux-x64/openjdk-" + data.version
+ "_linux-x64_bin-tests.tar.gz",
"bundles/openjdk/GPL/linux-x64/\\1"
"bundles/openjdk/GPL/linux-x64/open\\1"
]
},
jdk_symbols: {
local: "bundles/\\(jdk.*bin-symbols.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/linux-x64/jdk-" + data.version
"bundles/openjdk/GPL/linux-x64/openjdk-" + data.version
+ "_linux-x64_bin-symbols.tar.gz",
"bundles/openjdk/GPL/linux-x64/\\1"
"bundles/openjdk/GPL/linux-x64/open\\1"
],
subdir: "jdk-" + data.version
},
@ -771,27 +771,27 @@ var getJibProfilesProfiles = function (input, common, data) {
jdk: {
local: "bundles/\\(jdk.*bin.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/linux-x86/jdk-" + data.version
"bundles/openjdk/GPL/linux-x86/openjdk-" + data.version
+ "_linux-x86_bin.tar.gz",
"bundles/openjdk/GPL/linux-x86/\\1"
"bundles/openjdk/GPL/linux-x86/open\\1"
],
subdir: "jdk-" + data.version
},
jdk_symbols: {
local: "bundles/\\(jdk.*bin-symbols.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/linux-x86/jdk-" + data.version
"bundles/openjdk/GPL/linux-x86/openjdk-" + data.version
+ "_linux-x86_bin-symbols.tar.gz",
"bundles/openjdk/GPL/linux-x86/\\1"
"bundles/openjdk/GPL/linux-x86/open\\1"
],
subdir: "jdk-" + data.version
},
test: {
local: "bundles/\\(jdk.*bin-tests.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/linux-x86/jdk-" + data.version
"bundles/openjdk/GPL/linux-x86/openjdk-" + data.version
+ "_linux-x86_bin-tests.tar.gz",
"bundles/openjdk/GPL/linux-x86/\\1"
"bundles/openjdk/GPL/linux-x86/open\\1"
]
},
jre: {
@ -814,41 +814,84 @@ var getJibProfilesProfiles = function (input, common, data) {
}
},
"windows-x86-open": {
"macosx-x64-open": {
artifacts: {
jdk: {
local: "bundles/\\(jdk.*bin.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/windows-x86/jdk-" + data.version
+ "_windows-x86_bin.tar.gz",
"bundles/openjdk/GPL/windows-x86/\\1"
"bundles/openjdk/GPL/osx-x64/openjdk-" + data.version
+ "_osx-x64_bin.tar.gz",
"bundles/openjdk/GPL/osx-x64/open\\1"
],
subdir: "jdk-" + data.version
},
jre: {
local: "bundles/\\(jre.*bin.tar.gz\\)",
remote: "bundles/openjdk/GPL/windows-x86/\\1"
remote: "bundles/openjdk/GPL/osx-x64/\\1",
},
test: {
local: "bundles/\\(jdk.*bin-tests.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/windows-x86/jdk-" + data.version
+ "_windows-x86_bin-tests.tar.gz",
"bundles/openjdk/GPL/windows-x86/\\1"
"bundles/openjdk/GPL/osx-x64/openjdk-" + data.version
+ "_osx-x64_bin-tests.tar.gz",
"bundles/openjdk/GPL/osx-x64/open\\1"
]
},
jdk_symbols: {
local: "bundles/\\(jdk.*bin-symbols.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/windows-x86/jdk-" + data.version
+ "_windows-x86_bin-symbols.tar.gz",
"bundles/openjdk/GPL/windows-x86/\\1"
"bundles/openjdk/GPL/osx-x64/openjdk-" + data.version
+ "_osx-x64_bin-symbols.tar.gz",
"bundles/openjdk/GPL/osx-x64/open\\1"
],
subdir: "jdk-" + data.version
},
jre_symbols: {
local: "bundles/\\(jre.*bin-symbols.tar.gz\\)",
remote: "bundles/openjdk/GPL/windows-x86/\\1",
remote: "bundles/openjdk/GPL/osx-x64/\\1",
},
doc_api_spec: {
local: "bundles/\\(jdk.*doc-api-spec.tar.gz\\)",
remote: "bundles/openjdk/GPL/osx-x64/\\1",
},
}
},
"windows-x64-open": {
artifacts: {
jdk: {
local: "bundles/\\(jdk.*bin.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/windows-x64/openjdk-" + data.version
+ "_windows-x64_bin.tar.gz",
"bundles/openjdk/GPL/windows-x64/open\\1"
],
subdir: "jdk-" + data.version
},
jre: {
local: "bundles/\\(jre.*bin.tar.gz\\)",
remote: "bundles/openjdk/GPL/windows-x64/\\1"
},
test: {
local: "bundles/\\(jdk.*bin-tests.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/windows-x64/openjdk-" + data.version
+ "_windows-x64_bin-tests.tar.gz",
"bundles/openjdk/GPL/windows-x64/open\\1"
]
},
jdk_symbols: {
local: "bundles/\\(jdk.*bin-symbols.tar.gz\\)",
remote: [
"bundles/openjdk/GPL/windows-x64/openjdk-" + data.version
+ "_windows-x64_bin-symbols.tar.gz",
"bundles/openjdk/GPL/windows-x64/open\\1"
],
subdir: "jdk-" + data.version
},
jre_symbols: {
local: "bundles/\\(jre.*bin-symbols.tar.gz\\)",
remote: "bundles/openjdk/GPL/windows-x64/\\1",
}
}
},
@ -880,10 +923,11 @@ var getJibProfilesProfiles = function (input, common, data) {
profiles["linux-x64-ri"] = clone(profiles["linux-x64-open"]);
profiles["linux-x86-ri"] = clone(profiles["linux-x86-open"]);
profiles["linux-x86-ri-debug"] = clone(profiles["linux-x86-open-debug"]);
profiles["windows-x86-ri"] = clone(profiles["windows-x86-open"]);
profiles["macosx-x64-ri"] = clone(profiles["macosx-x64-open"]);
profiles["windows-x64-ri"] = clone(profiles["windows-x64-open"]);
// Generate artifacts for ri profiles
[ "linux-x64-ri", "linux-x86-ri", "linux-x86-ri-debug", "windows-x86-ri" ]
[ "linux-x64-ri", "linux-x86-ri", "linux-x86-ri-debug", "macosx-x64-ri", "windows-x64-ri" ]
.forEach(function (name) {
// Rewrite all remote dirs to "bundles/openjdk/BCL/..."
for (artifactName in profiles[name].artifacts) {
@ -893,16 +937,6 @@ var getJibProfilesProfiles = function (input, common, data) {
}
});
// The windows ri profile needs to add the freetype license file
profilesRiFreetype = {
"windows-x86-ri": {
configure_args: "--with-freetype-license="
+ input.get("freetype", "install_path")
+ "/freetype-2.7.1-v120-x86/freetype.md"
}
};
profiles = concatObjects(profiles, profilesRiFreetype);
// Generate the missing platform attributes
profiles = generatePlatformAttributes(profiles);
profiles = generateDefaultMakeTargetsConfigureArg(common, profiles);
@ -934,6 +968,12 @@ var getJibProfilesDependencies = function (input, common) {
? input.target_os + "_x64"
: input.target_platform);
var freetype_version = {
windows_x64: "2.7.1-v120+1.1",
windows_x86: "2.7.1-v120+1.1",
macosx_x64: "2.7.1-Xcode6.3-MacOSX10.9+1.0"
}[input.target_platform];
var dependencies = {
boot_jdk: {
@ -998,7 +1038,7 @@ var getJibProfilesDependencies = function (input, common) {
freetype: {
organization: common.organization,
ext: "tar.gz",
revision: "2.7.1-v120+1.0",
revision: freetype_version,
module: "freetype-" + input.target_platform
},
@ -1200,7 +1240,8 @@ var versionArgs = function(input, common) {
if (input.build_type == "promoted") {
args = concat(args,
// This needs to be changed when we start building release candidates
"--with-version-pre=ea",
// 'ea' for EA builds and empty value for 'fcs'
"--with-version-pre=",
"--without-version-opt");
} else {
args = concat(args, "--with-version-opt=" + common.build_id);

View File

@ -577,9 +577,35 @@ d53171650a2cc6c6f699c966c533b914ca9c0602 jdk-9+171
1ae9e84f68b359420d2d153ecfe5ee2903e33a2e jdk-9+172
e64b1cb48d6e7703928a9d1da106fc27f8cb65fd jdk-9+173
944791f8160185bffa13fbb821fc09b6198f1f25 jdk-9+174
ca47dcfdd35129fe3ab2dab71b2601d7a0ff07c0 jdk-9.0.1+00
ca47dcfdd35129fe3ab2dab71b2601d7a0ff07c0 jdk-9.0.3+00
8f04d457168b9f1f4a1b2c37f49e0513ca9d33a7 jdk-9+175
2ab74e5dbdc2b6a962c865500cafd23cf387dc60 jdk-9+176
1ca8f038fceb88c640badf9bd18905205bc63b43 jdk-9+177
9d032191f82fca5ba0aac98682f69c4ff0f1283d jdk-9+178
d2661aa42bff322badbe6c1337fc638d2e0f5730 jdk-9+179
d7baadc223e790c08bc69bf7e553bce65b4e7e40 jdk-9+180
4a443796f6f57842d6a0434ac27ca3d1033ccc20 jdk-9+181
8297b62a7b62bafe42c7d567a5752f7a82bafab8 jdk-9.0.3+1
d2efdbb193a02613867c8949f783d2905f7a28fc jdk-9.0.3+2
68f9ff7c5eedfd41f9c10959e41024efbd3aa79c jdk-9.0.3+3
82584ea6464de2e0a59e9fc00173e18a85dc45d8 jdk-9.0.3+4
c45e75533bae7b5db5c626bf9233b4226934d582 jdk-9.0.3+5
4c0248d117fabf46c5931cdd09e543c3d89b68a5 jdk-9.0.3+6
fca264c9fa3ce57b3f4d662242d38b44fb442c87 jdk-9.0.3+7
1f5a9c0ddb4b8da443f70fc5d135b320f6e0b78a jdk-9.0.3+8
a10c11fed5bdc5202523baee3cf391cc0e0cfcaa jdk-9.0.3+9
172baf6c99c5e9fdd72a6f3729f6ec8cd6b48183 jdk-9.0.1+10
3546eb2ee2693043eb107d980ce5b72fe7f8f47a jdk-9.0.1+11
5be37d3ef648d06850aa164d8b22ac7539559e80 jdk-9.0.4+00
46290b7298be50f9a70d27465d50d1675732f0af jdk-9.0.4+1
dab4c60adabfb8ea35cfcd96a7218994a84d652f jdk-9.0.4+2
deed95e4b4cba997b3cc13b62e33615fd11bc902 jdk-9.0.4+3
ce49d719fd4d5f0ff12a1906d9d8b651a7a7d60c jdk-9.0.4+4
11116cc619ac1b0d00cdcd47e8a7eb2339207bbf jdk-9.0.4+5
f3ba0e190ffcc82f1ed0dd8275a51096123514b6 jdk-9.0.4+6
e020892c9b441ff0855479ad4de63a9eb4b59bf7 jdk-9.0.4+7
d74a282dcd6d05cc3752c8e29a526eb9216fa08c jdk-9.0.4+8
a825ddfdd78e3277e6275a469f3cd2be23759c13 jdk-9.0.4+9
a8e5681c2532b4d21567bbee5d3dd42027118e72 jdk-9.0.4+10
f6418daf023ea194db63519e3d13ca6c252028ed jdk-9.0.4+11

View File

@ -1 +1,2 @@
project=jdk9
bugids=dup

View File

@ -0,0 +1,37 @@
ADDITIONAL INFORMATION ABOUT LICENSING
Certain files distributed by Oracle America, Inc. and/or its affiliates are
subject to the following clarification and special exception to the GPLv2,
based on the GNU Project exception for its Classpath libraries, known as the
GNU Classpath Exception.
Note that Oracle includes multiple, independent programs in this software
package. Some of those programs are provided under licenses deemed
incompatible with the GPLv2 by the Free Software Foundation and others.
For example, the package includes programs licensed under the Apache
License, Version 2.0 and may include FreeType. Such programs are licensed
to you under their original licenses.
Oracle facilitates your further distribution of this package by adding the
Classpath Exception to the necessary parts of its GPLv2 code, which permits
you to use that code in combination with other independent modules not
licensed under the GPLv2. However, note that this would not permit you to
commingle code under an incompatible license with Oracle's GPLv2 licensed
code by, for example, cutting and pasting such code into a file also
containing Oracle's GPLv2 licensed code and then distributing the result.
Additionally, if you were to remove the Classpath Exception from any of the
files to which it applies and distribute the result, you would likely be
required to license some or all of the other code in that distribution under
the GPLv2 as well, and since the GPLv2 is incompatible with the license terms
of some items included in the distribution by Oracle, removing the Classpath
Exception could therefore effectively compromise your ability to further
distribute the package.
Failing to distribute notices associated with some files may also create
unexpected legal consequences.
Proceed with caution and we recommend that you obtain the advice of a lawyer
skilled in open source matters before removing the Classpath Exception or
making modifications to this package which may subsequently be redistributed
and/or involve the use of third party software.

View File

@ -927,8 +927,12 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
RegisterOrConstant itable_index,
Register method_result,
Register scan_temp,
Label& L_no_such_interface) {
assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
Label& L_no_such_interface,
bool return_method) {
assert_different_registers(recv_klass, intf_klass, scan_temp);
assert_different_registers(method_result, intf_klass, scan_temp);
assert(recv_klass != method_result || !return_method,
"recv_klass can be destroyed when method isn't needed");
assert(itable_index.is_constant() || itable_index.as_register() == method_result,
"caller must use same register for non-constant itable index as for method");
@ -946,12 +950,14 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
lea(scan_temp, Address(recv_klass, scan_temp, Address::lsl(3)));
add(scan_temp, scan_temp, vtable_base);
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
// lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off));
lea(recv_klass, Address(recv_klass, itable_index, Address::lsl(3)));
if (itentry_off)
add(recv_klass, recv_klass, itentry_off);
if (return_method) {
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
// lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off));
lea(recv_klass, Address(recv_klass, itable_index, Address::lsl(3)));
if (itentry_off)
add(recv_klass, recv_klass, itentry_off);
}
// for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
// if (scan->interface() == intf) {
@ -985,8 +991,10 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
bind(found_method);
// Got a hit.
ldr(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes()));
ldr(method_result, Address(recv_klass, scan_temp));
if (return_method) {
ldrw(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes()));
ldr(method_result, Address(recv_klass, scan_temp, Address::uxtw(0)));
}
}
// virtual method calling
@ -1005,7 +1013,8 @@ void MacroAssembler::lookup_virtual_method(Register recv_klass,
ldr(method_result, Address(method_result, vtable_offset_in_bytes));
} else {
vtable_offset_in_bytes += vtable_index.as_constant() * wordSize;
ldr(method_result, Address(recv_klass, vtable_offset_in_bytes));
ldr(method_result,
form_address(rscratch1, recv_klass, vtable_offset_in_bytes, 0));
}
}

View File

@ -870,7 +870,8 @@ public:
RegisterOrConstant itable_index,
Register method_result,
Register scan_temp,
Label& no_such_interface);
Label& no_such_interface,
bool return_method = true);
// virtual method calling
// n.b. x86 allows RegisterOrConstant for vtable_index

View File

@ -773,7 +773,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
__ load_klass(rscratch1, receiver);
__ ldr(tmp, Address(holder, CompiledICHolder::holder_klass_offset()));
__ cmp(rscratch1, tmp);
__ ldr(rmethod, Address(holder, CompiledICHolder::holder_method_offset()));
__ ldr(rmethod, Address(holder, CompiledICHolder::holder_metadata_offset()));
__ br(Assembler::EQ, ok);
__ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));

View File

@ -3279,11 +3279,11 @@ void TemplateTable::invokeinterface(int byte_no) {
transition(vtos, vtos);
assert(byte_no == f1_byte, "use this argument");
prepare_invoke(byte_no, r0, rmethod, // get f1 Klass*, f2 itable index
prepare_invoke(byte_no, r0, rmethod, // get f1 Klass*, f2 Method*
r2, r3); // recv, flags
// r0: interface klass (from f1)
// rmethod: itable index (from f2)
// rmethod: method (from f2)
// r2: receiver
// r3: flags
@ -3302,10 +3302,27 @@ void TemplateTable::invokeinterface(int byte_no) {
__ null_check(r2, oopDesc::klass_offset_in_bytes());
__ load_klass(r3, r2);
Label no_such_interface, no_such_method;
// Receiver subtype check against REFC.
// Superklass in r0. Subklass in r3. Blows rscratch2, r13
__ lookup_interface_method(// inputs: rec. class, interface, itable index
r3, r0, noreg,
// outputs: scan temp. reg, scan temp. reg
rscratch2, r13,
no_such_interface,
/*return_method=*/false);
// profile this call
__ profile_virtual_call(r3, r13, r19);
Label no_such_interface, no_such_method;
// Get declaring interface class from method, and itable index
__ ldr(r0, Address(rmethod, Method::const_offset()));
__ ldr(r0, Address(r0, ConstMethod::constants_offset()));
__ ldr(r0, Address(r0, ConstantPool::pool_holder_offset_in_bytes()));
__ ldrw(rmethod, Address(rmethod, Method::itable_index_offset()));
__ subw(rmethod, rmethod, Method::itable_index_max);
__ negw(rmethod, rmethod);
__ lookup_interface_method(// inputs: rec. class, interface, itable index
r3, r0, rmethod,

View File

@ -29,6 +29,7 @@
#include "code/vtableStubs.hpp"
#include "interp_masm_aarch64.hpp"
#include "memory/resourceArea.hpp"
#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@ -62,8 +63,8 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
#ifndef PRODUCT
if (CountCompiledCalls) {
__ lea(r19, ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
__ incrementw(Address(r19));
__ lea(r16, ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
__ incrementw(Address(r16));
}
#endif
@ -72,13 +73,13 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
// get receiver klass
address npe_addr = __ pc();
__ load_klass(r19, j_rarg0);
__ load_klass(r16, j_rarg0);
#ifndef PRODUCT
if (DebugVtables) {
Label L;
// check offset vs vtable length
__ ldrw(rscratch1, Address(r19, Klass::vtable_length_offset()));
__ ldrw(rscratch1, Address(r16, Klass::vtable_length_offset()));
__ cmpw(rscratch1, vtable_index * vtableEntry::size());
__ br(Assembler::GT, L);
__ enter();
@ -90,7 +91,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
}
#endif // PRODUCT
__ lookup_virtual_method(r19, vtable_index, rmethod);
__ lookup_virtual_method(r16, vtable_index, rmethod);
if (DebugVtables) {
Label L;
@ -140,28 +141,44 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
#endif
// Entry arguments:
// rscratch2: Interface
// rscratch2: CompiledICHolder
// j_rarg0: Receiver
// Free registers (non-args) are r0 (interface), rmethod
// Most registers are in use; we'll use r16, rmethod, r10, r11
const Register recv_klass_reg = r10;
const Register holder_klass_reg = r16; // declaring interface klass (DECC)
const Register resolved_klass_reg = rmethod; // resolved interface klass (REFC)
const Register temp_reg = r11;
const Register icholder_reg = rscratch2;
Label L_no_such_interface;
__ ldr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
__ ldr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
// get receiver (need to skip return address on top of stack)
assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0");
// get receiver klass (also an implicit null-check)
address npe_addr = __ pc();
__ load_klass(recv_klass_reg, j_rarg0);
// Most registers are in use; we'll use r0, rmethod, r10, r11
__ load_klass(r10, j_rarg0);
// Receiver subtype check against REFC.
// Destroys recv_klass_reg value.
__ lookup_interface_method(// inputs: rec. class, interface
recv_klass_reg, resolved_klass_reg, noreg,
// outputs: scan temp. reg1, scan temp. reg2
recv_klass_reg, temp_reg,
L_no_such_interface,
/*return_method=*/false);
Label throw_icce;
// Get Method* and entrypoint for compiler
// Get selected method from declaring class and itable index
__ load_klass(recv_klass_reg, j_rarg0); // restore recv_klass_reg
__ lookup_interface_method(// inputs: rec. class, interface, itable index
r10, rscratch2, itable_index,
// outputs: method, scan temp. reg
rmethod, r11,
throw_icce);
recv_klass_reg, holder_klass_reg, itable_index,
// outputs: method, scan temp. reg
rmethod, temp_reg,
L_no_such_interface);
// method (rmethod): Method*
// j_rarg0: receiver
@ -183,7 +200,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ ldr(rscratch1, Address(rmethod, Method::from_compiled_offset()));
__ br(rscratch1);
__ bind(throw_icce);
__ bind(L_no_such_interface);
__ far_jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
__ flush();
@ -205,11 +222,11 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
int size = DebugVtables ? 216 : 0;
if (CountCompiledCalls)
size += 6 * 4;
// FIXME
// FIXME: vtable stubs only need 36 bytes
if (is_vtable_stub)
size += 52;
else
size += 104;
size += 176;
return size;
// In order to tune these parameters, run the JVM with VM options
@ -217,33 +234,58 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
// actual itable stubs. Run it with -Xmx31G -XX:+UseCompressedOops.
//
// If Universe::narrow_klass_base is nonzero, decoding a compressed
// class can take zeveral instructions. Run it with -Xmx31G
// -XX:+UseCompressedOops.
// class can take zeveral instructions.
//
// The JVM98 app. _202_jess has a megamorphic interface call.
// The itable code looks like this:
// Decoding VtableStub itbl[1]@12
// ldr w10, [x1,#8]
// lsl x10, x10, #3
// ldr w11, [x10,#280]
// add x11, x10, x11, uxtx #3
// add x11, x11, #0x1b8
// ldr x12, [x11]
// cmp x9, x12
// b.eq success
// loop:
// cbz x12, throw_icce
// add x11, x11, #0x10
// ldr x12, [x11]
// cmp x9, x12
// b.ne loop
// success:
// ldr x11, [x11,#8]
// ldr x12, [x10,x11]
// ldr x8, [x12,#72]
// br x8
// throw_icce:
// b throw_ICCE_entry
// ldr xmethod, [xscratch2,#CompiledICHolder::holder_klass_offset]
// ldr x0, [xscratch2]
// ldr w10, [x1,#oopDesc::klass_offset_in_bytes]
// mov xheapbase, #0x3c000000 // #narrow_klass_base
// movk xheapbase, #0x3f7, lsl #32
// add x10, xheapbase, x10
// mov xheapbase, #0xe7ff0000 // #heapbase
// movk xheapbase, #0x3f7, lsl #32
// ldr w11, [x10,#vtable_length_offset]
// add x11, x10, x11, uxtx #3
// add x11, x11, #itableMethodEntry::method_offset_in_bytes
// ldr x10, [x11]
// cmp xmethod, x10
// b.eq found_method
// search:
// cbz x10, no_such_interface
// add x11, x11, #0x10
// ldr x10, [x11]
// cmp xmethod, x10
// b.ne search
// found_method:
// ldr w10, [x1,#oopDesc::klass_offset_in_bytes]
// mov xheapbase, #0x3c000000 // #narrow_klass_base
// movk xheapbase, #0x3f7, lsl #32
// add x10, xheapbase, x10
// mov xheapbase, #0xe7ff0000 // #heapbase
// movk xheapbase, #0x3f7, lsl #32
// ldr w11, [x10,#vtable_length_offset]
// add x11, x10, x11, uxtx #3
// add x11, x11, #itableMethodEntry::method_offset_in_bytes
// add x10, x10, #itentry_off
// ldr xmethod, [x11]
// cmp x0, xmethod
// b.eq found_method2
// search2:
// cbz xmethod, 0x000003ffa872e6cc
// add x11, x11, #0x10
// ldr xmethod, [x11]
// cmp x0, xmethod
// b.ne search2
// found_method2:
// ldr w11, [x11,#itableOffsetEntry::offset_offset_in_bytes]
// ldr xmethod, [x10,w11,uxtw]
// ldr xscratch1, [xmethod,#Method::from_compiled_offset]
// br xscratch1
// no_such_interface:
// b throw_ICCE_entry
}

View File

@ -2475,49 +2475,65 @@ void MacroAssembler::store_sized_value(Register src, Address dst, size_t size_in
// On success, the result will be in method_result, and execution falls through.
// On failure, execution transfers to the given label.
void MacroAssembler::lookup_interface_method(Register Rklass,
Register Rinterf,
Register Rindex,
Register Rintf,
RegisterOrConstant itable_index,
Register method_result,
Register temp_reg1,
Register temp_reg2,
Register Rscan,
Register Rtmp,
Label& L_no_such_interface) {
assert_different_registers(Rklass, Rinterf, temp_reg1, temp_reg2, Rindex);
assert_different_registers(Rklass, Rintf, Rscan, Rtmp);
Register Ritable = temp_reg1;
const int entry_size = itableOffsetEntry::size() * HeapWordSize;
assert(itableOffsetEntry::interface_offset_in_bytes() == 0, "not added for convenience");
// Compute start of first itableOffsetEntry (which is at the end of the vtable)
const int base = in_bytes(Klass::vtable_start_offset());
const int scale = exact_log2(vtableEntry::size_in_bytes());
ldr_s32(temp_reg2, Address(Rklass, Klass::vtable_length_offset())); // Get length of vtable
add(Ritable, Rklass, base);
add(Ritable, Ritable, AsmOperand(temp_reg2, lsl, scale));
ldr_s32(Rtmp, Address(Rklass, Klass::vtable_length_offset())); // Get length of vtable
add(Rscan, Rklass, base);
add(Rscan, Rscan, AsmOperand(Rtmp, lsl, scale));
Label entry, search;
// Search through the itable for an interface equal to incoming Rintf
// itable looks like [intface][offset][intface][offset][intface][offset]
b(entry);
Label loop;
bind(loop);
ldr(Rtmp, Address(Rscan, entry_size, post_indexed));
#ifdef AARCH64
Label found;
cmp(Rtmp, Rintf);
b(found, eq);
cbnz(Rtmp, loop);
#else
cmp(Rtmp, Rintf); // set ZF and CF if interface is found
cmn(Rtmp, 0, ne); // check if tmp == 0 and clear CF if it is
b(loop, ne);
#endif // AARCH64
bind(search);
add(Ritable, Ritable, itableOffsetEntry::size() * HeapWordSize);
#ifdef AARCH64
b(L_no_such_interface);
bind(found);
#else
// CF == 0 means we reached the end of itable without finding icklass
b(L_no_such_interface, cc);
#endif // !AARCH64
bind(entry);
// Check that the entry is non-null. A null entry means that the receiver
// class doesn't implement the interface, and wasn't the same as the
// receiver class checked when the interface was resolved.
ldr(temp_reg2, Address(Ritable, itableOffsetEntry::interface_offset_in_bytes()));
cbz(temp_reg2, L_no_such_interface);
cmp(Rinterf, temp_reg2);
b(search, ne);
ldr_s32(temp_reg2, Address(Ritable, itableOffsetEntry::offset_offset_in_bytes()));
add(temp_reg2, temp_reg2, Rklass); // Add offset to Klass*
assert(itableMethodEntry::size() * HeapWordSize == wordSize, "adjust the scaling in the code below");
assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust the offset in the code below");
ldr(method_result, Address::indexed_ptr(temp_reg2, Rindex));
if (method_result != noreg) {
// Interface found at previous position of Rscan, now load the method
ldr_s32(Rtmp, Address(Rscan, itableOffsetEntry::offset_offset_in_bytes() - entry_size));
if (itable_index.is_register()) {
add(Rtmp, Rtmp, Rklass); // Add offset to Klass*
assert(itableMethodEntry::size() * HeapWordSize == wordSize, "adjust the scaling in the code below");
assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust the offset in the code below");
ldr(method_result, Address::indexed_ptr(Rtmp, itable_index.as_register()));
} else {
int method_offset = itableMethodEntry::size() * HeapWordSize * itable_index.as_constant() +
itableMethodEntry::method_offset_in_bytes();
add_slow(method_result, Rklass, method_offset);
ldr(method_result, Address(method_result, Rtmp));
}
}
}
#ifdef COMPILER2

View File

@ -1316,7 +1316,7 @@ public:
void lookup_interface_method(Register recv_klass,
Register intf_klass,
Register itable_index,
RegisterOrConstant itable_index,
Register method_result,
Register temp_reg1,
Register temp_reg2,

View File

@ -987,7 +987,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
__ load_klass(receiver_klass, receiver);
__ ldr(holder_klass, Address(Ricklass, CompiledICHolder::holder_klass_offset()));
__ ldr(Rmethod, Address(Ricklass, CompiledICHolder::holder_method_offset()));
__ ldr(Rmethod, Address(Ricklass, CompiledICHolder::holder_metadata_offset()));
__ cmp(receiver_klass, holder_klass);
#ifdef AARCH64

View File

@ -4192,7 +4192,7 @@ void TemplateTable::invokeinterface(int byte_no) {
const Register Rflags = R3_tmp;
const Register Rklass = R3_tmp;
prepare_invoke(byte_no, Rinterf, Rindex, Rrecv, Rflags);
prepare_invoke(byte_no, Rinterf, Rmethod, Rrecv, Rflags);
// Special case of invokeinterface called for virtual method of
// java.lang.Object. See cpCacheOop.cpp for details.
@ -4201,56 +4201,39 @@ void TemplateTable::invokeinterface(int byte_no) {
Label notMethod;
__ tbz(Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift, notMethod);
__ mov(Rmethod, Rindex);
invokevirtual_helper(Rmethod, Rrecv, Rflags);
__ bind(notMethod);
// Get receiver klass into Rklass - also a null check
__ load_klass(Rklass, Rrecv);
Label no_such_interface;
// Receiver subtype check against REFC.
__ lookup_interface_method(// inputs: rec. class, interface
Rklass, Rinterf, noreg,
// outputs: scan temp. reg1, scan temp. reg2
noreg, Ritable, Rtemp,
no_such_interface);
// profile this call
__ profile_virtual_call(R0_tmp, Rklass);
// Compute start of first itableOffsetEntry (which is at the end of the vtable)
const int base = in_bytes(Klass::vtable_start_offset());
assert(vtableEntry::size() == 1, "adjust the scaling in the code below");
__ ldr_s32(Rtemp, Address(Rklass, Klass::vtable_length_offset())); // Get length of vtable
__ add(Ritable, Rklass, base);
__ add(Ritable, Ritable, AsmOperand(Rtemp, lsl, LogBytesPerWord));
// Get declaring interface class from method
__ ldr(Rtemp, Address(Rmethod, Method::const_offset()));
__ ldr(Rtemp, Address(Rtemp, ConstMethod::constants_offset()));
__ ldr(Rinterf, Address(Rtemp, ConstantPool::pool_holder_offset_in_bytes()));
Label entry, search, interface_ok;
// Get itable index from method
__ ldr_s32(Rtemp, Address(Rmethod, Method::itable_index_offset()));
__ add(Rtemp, Rtemp, (-Method::itable_index_max)); // small negative constant is too large for an immediate on arm32
__ neg(Rindex, Rtemp);
__ b(entry);
__ bind(search);
__ add(Ritable, Ritable, itableOffsetEntry::size() * HeapWordSize);
__ bind(entry);
// Check that the entry is non-null. A null entry means that the receiver
// class doesn't implement the interface, and wasn't the same as the
// receiver class checked when the interface was resolved.
__ ldr(Rtemp, Address(Ritable, itableOffsetEntry::interface_offset_in_bytes()));
__ cbnz(Rtemp, interface_ok);
// throw exception
__ call_VM(noreg, CAST_FROM_FN_PTR(address,
InterpreterRuntime::throw_IncompatibleClassChangeError));
// the call_VM checks for exception, so we should never return here.
__ should_not_reach_here();
__ bind(interface_ok);
__ cmp(Rinterf, Rtemp);
__ b(search, ne);
__ ldr_s32(Rtemp, Address(Ritable, itableOffsetEntry::offset_offset_in_bytes()));
__ add(Rtemp, Rtemp, Rklass); // Add offset to Klass*
assert(itableMethodEntry::size() == 1, "adjust the scaling in the code below");
__ ldr(Rmethod, Address::indexed_ptr(Rtemp, Rindex));
__ lookup_interface_method(// inputs: rec. class, interface
Rklass, Rinterf, Rindex,
// outputs: scan temp. reg1, scan temp. reg2
Rmethod, Ritable, Rtemp,
no_such_interface);
// Rmethod: Method* to call
@ -4272,6 +4255,13 @@ void TemplateTable::invokeinterface(int byte_no) {
// do the call
__ jump_from_interpreted(Rmethod);
// throw exception
__ bind(no_such_interface);
__ restore_method();
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
// the call_VM checks for exception, so we should never return here.
__ should_not_reach_here();
}
void TemplateTable::invokehandle(int byte_no) {

View File

@ -28,6 +28,7 @@
#include "code/vtableStubs.hpp"
#include "interp_masm_arm.hpp"
#include "memory/resourceArea.hpp"
#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@ -118,67 +119,48 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
// R0-R3 / R0-R7 registers hold the arguments and cannot be spoiled
const Register Rclass = AARCH64_ONLY(R9) NOT_AARCH64(R4);
const Register Rlength = AARCH64_ONLY(R10) NOT_AARCH64(R5);
const Register Rintf = AARCH64_ONLY(R10) NOT_AARCH64(R5);
const Register Rscan = AARCH64_ONLY(R11) NOT_AARCH64(R6);
const Register tmp = Rtemp;
assert_different_registers(Ricklass, Rclass, Rlength, Rscan, tmp);
assert_different_registers(Ricklass, Rclass, Rintf, Rscan, Rtemp);
// Calculate the start of itable (itable goes after vtable)
const int scale = exact_log2(vtableEntry::size_in_bytes());
address npe_addr = __ pc();
__ load_klass(Rclass, R0);
__ ldr_s32(Rlength, Address(Rclass, Klass::vtable_length_offset()));
__ add(Rscan, Rclass, in_bytes(Klass::vtable_start_offset()));
__ add(Rscan, Rscan, AsmOperand(Rlength, lsl, scale));
Label L_no_such_interface;
// Search through the itable for an interface equal to incoming Ricklass
// itable looks like [intface][offset][intface][offset][intface][offset]
const int entry_size = itableOffsetEntry::size() * HeapWordSize;
assert(itableOffsetEntry::interface_offset_in_bytes() == 0, "not added for convenience");
// Receiver subtype check against REFC.
__ ldr(Rintf, Address(Ricklass, CompiledICHolder::holder_klass_offset()));
__ lookup_interface_method(// inputs: rec. class, interface, itable index
Rclass, Rintf, noreg,
// outputs: temp reg1, temp reg2
noreg, Rscan, Rtemp,
L_no_such_interface);
Label loop;
__ bind(loop);
__ ldr(tmp, Address(Rscan, entry_size, post_indexed));
#ifdef AARCH64
Label found;
__ cmp(tmp, Ricklass);
__ b(found, eq);
__ cbnz(tmp, loop);
#else
__ cmp(tmp, Ricklass); // set ZF and CF if interface is found
__ cmn(tmp, 0, ne); // check if tmp == 0 and clear CF if it is
__ b(loop, ne);
#endif // AARCH64
assert(StubRoutines::throw_IncompatibleClassChangeError_entry() != NULL, "Check initialization order");
#ifdef AARCH64
__ jump(StubRoutines::throw_IncompatibleClassChangeError_entry(), relocInfo::runtime_call_type, tmp);
__ bind(found);
#else
// CF == 0 means we reached the end of itable without finding icklass
__ jump(StubRoutines::throw_IncompatibleClassChangeError_entry(), relocInfo::runtime_call_type, noreg, cc);
#endif // !AARCH64
// Interface found at previous position of Rscan, now load the method oop
__ ldr_s32(tmp, Address(Rscan, itableOffsetEntry::offset_offset_in_bytes() - entry_size));
{
const int method_offset = itableMethodEntry::size() * HeapWordSize * itable_index +
itableMethodEntry::method_offset_in_bytes();
__ add_slow(Rmethod, Rclass, method_offset);
}
__ ldr(Rmethod, Address(Rmethod, tmp));
// Get Method* and entry point for compiler
__ ldr(Rintf, Address(Ricklass, CompiledICHolder::holder_metadata_offset()));
__ lookup_interface_method(// inputs: rec. class, interface, itable index
Rclass, Rintf, itable_index,
// outputs: temp reg1, temp reg2, temp reg3
Rmethod, Rscan, Rtemp,
L_no_such_interface);
address ame_addr = __ pc();
#ifdef AARCH64
__ ldr(tmp, Address(Rmethod, Method::from_compiled_offset()));
__ br(tmp);
__ ldr(Rtemp, Address(Rmethod, Method::from_compiled_offset()));
__ br(Rtemp);
#else
__ ldr(PC, Address(Rmethod, Method::from_compiled_offset()));
#endif // AARCH64
__ bind(L_no_such_interface);
assert(StubRoutines::throw_IncompatibleClassChangeError_entry() != NULL, "check initialization order");
__ jump(StubRoutines::throw_IncompatibleClassChangeError_entry(), relocInfo::runtime_call_type, Rtemp);
masm->flush();
if (PrintMiscellaneous && (WizardMode || Verbose)) {
@ -205,7 +187,7 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
instr_count = NOT_AARCH64(4) AARCH64_ONLY(5);
} else {
// itable stub size
instr_count = NOT_AARCH64(20) AARCH64_ONLY(20);
instr_count = NOT_AARCH64(31) AARCH64_ONLY(31);
}
#ifdef AARCH64

View File

@ -1786,11 +1786,10 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
RegisterOrConstant itable_index,
Register method_result,
Register scan_temp,
Register sethi_temp,
Label& L_no_such_interface) {
Register temp2,
Label& L_no_such_interface,
bool return_method) {
assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
assert(itable_index.is_constant() || itable_index.as_register() == method_result,
"caller must use same register for non-constant itable index as for method");
// Compute start of first itableOffsetEntry (which is at the end of the vtable).
int vtable_base = in_bytes(Klass::vtable_start_offset());
@ -1808,15 +1807,17 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
add(scan_temp, recv_klass, scan_temp);
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
if (itable_index.is_register()) {
Register itable_offset = itable_index.as_register();
sldi(itable_offset, itable_offset, logMEsize);
if (itentry_off) addi(itable_offset, itable_offset, itentry_off);
add(recv_klass, itable_offset, recv_klass);
} else {
long itable_offset = (long)itable_index.as_constant();
load_const_optimized(sethi_temp, (itable_offset<<logMEsize)+itentry_off); // static address, no relocation
add(recv_klass, sethi_temp, recv_klass);
if (return_method) {
if (itable_index.is_register()) {
Register itable_offset = itable_index.as_register();
sldi(method_result, itable_offset, logMEsize);
if (itentry_off) { addi(method_result, method_result, itentry_off); }
add(method_result, method_result, recv_klass);
} else {
long itable_offset = (long)itable_index.as_constant();
// static address, no relocation
add_const_optimized(method_result, recv_klass, (itable_offset << logMEsize) + itentry_off, temp2);
}
}
// for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
@ -1829,12 +1830,12 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
for (int peel = 1; peel >= 0; peel--) {
// %%%% Could load both offset and interface in one ldx, if they were
// in the opposite order. This would save a load.
ld(method_result, itableOffsetEntry::interface_offset_in_bytes(), scan_temp);
ld(temp2, itableOffsetEntry::interface_offset_in_bytes(), scan_temp);
// Check that this entry is non-null. A null entry means that
// the receiver class doesn't implement the interface, and wasn't the
// same as when the caller was compiled.
cmpd(CCR0, method_result, intf_klass);
cmpd(CCR0, temp2, intf_klass);
if (peel) {
beq(CCR0, found_method);
@ -1847,7 +1848,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
bind(search);
cmpdi(CCR0, method_result, 0);
cmpdi(CCR0, temp2, 0);
beq(CCR0, L_no_such_interface);
addi(scan_temp, scan_temp, scan_step);
}
@ -1855,9 +1856,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
bind(found_method);
// Got a hit.
int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
lwz(scan_temp, ito_offset, scan_temp);
ldx(method_result, scan_temp, recv_klass);
if (return_method) {
int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
lwz(scan_temp, ito_offset, scan_temp);
ldx(method_result, scan_temp, method_result);
}
}
// virtual method calling

View File

@ -517,7 +517,8 @@ class MacroAssembler: public Assembler {
RegisterOrConstant itable_index,
Register method_result,
Register temp_reg, Register temp2_reg,
Label& no_such_interface);
Label& no_such_interface,
bool return_method = true);
// virtual method calling
void lookup_virtual_method(Register recv_klass,

View File

@ -1185,7 +1185,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
// Argument is valid and klass is as expected, continue.
// Extract method from inline cache, verified entry point needs it.
__ ld(R19_method, CompiledICHolder::holder_method_offset(), ic);
__ ld(R19_method, CompiledICHolder::holder_metadata_offset(), ic);
assert(R19_method == ic, "the inline cache register is dead here");
__ ld(code, method_(code));

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2016 SAP SE. All rights reserved.
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2017 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -3478,11 +3478,11 @@ void TemplateTable::invokestatic(int byte_no) {
void TemplateTable::invokeinterface_object_method(Register Rrecv_klass,
Register Rret,
Register Rflags,
Register Rindex,
Register Rmethod,
Register Rtemp1,
Register Rtemp2) {
assert_different_registers(Rindex, Rret, Rrecv_klass, Rflags, Rtemp1, Rtemp2);
assert_different_registers(Rmethod, Rret, Rrecv_klass, Rflags, Rtemp1, Rtemp2);
Label LnotFinal;
// Check for vfinal.
@ -3494,14 +3494,14 @@ void TemplateTable::invokeinterface_object_method(Register Rrecv_klass,
// Final call case.
__ profile_final_call(Rtemp1, Rscratch);
// Argument and return type profiling.
__ profile_arguments_type(Rindex, Rscratch, Rrecv_klass /* scratch */, true);
__ profile_arguments_type(Rmethod, Rscratch, Rrecv_klass /* scratch */, true);
// Do the final call - the index (f2) contains the method.
__ call_from_interpreter(Rindex, Rret, Rscratch, Rrecv_klass /* scratch */);
__ call_from_interpreter(Rmethod, Rret, Rscratch, Rrecv_klass /* scratch */);
// Non-final callc case.
__ bind(LnotFinal);
__ profile_virtual_call(Rrecv_klass, Rtemp1, Rscratch, false);
generate_vtable_call(Rrecv_klass, Rindex, Rret, Rscratch);
generate_vtable_call(Rrecv_klass, Rmethod, Rret, Rscratch);
}
void TemplateTable::invokeinterface(int byte_no) {
@ -3510,58 +3510,61 @@ void TemplateTable::invokeinterface(int byte_no) {
const Register Rscratch1 = R11_scratch1,
Rscratch2 = R12_scratch2,
Rscratch3 = R9_ARG7,
Rscratch4 = R10_ARG8,
Rtable_addr = Rscratch2,
Rmethod = R6_ARG4,
Rmethod2 = R9_ARG7,
Rinterface_klass = R5_ARG3,
Rret_type = R8_ARG6,
Rret_addr = Rret_type,
Rindex = R6_ARG4,
Rreceiver = R4_ARG2,
Rrecv_klass = Rreceiver,
Rret_addr = R8_ARG6,
Rindex = R10_ARG8,
Rreceiver = R3_ARG1,
Rrecv_klass = R4_ARG2,
Rflags = R7_ARG5;
prepare_invoke(byte_no, Rinterface_klass, Rret_addr, Rindex, Rreceiver, Rflags, Rscratch1);
prepare_invoke(byte_no, Rinterface_klass, Rret_addr, Rmethod, Rreceiver, Rflags, Rscratch1);
// Get receiver klass.
__ null_check_throw(Rreceiver, oopDesc::klass_offset_in_bytes(), Rscratch3);
__ null_check_throw(Rreceiver, oopDesc::klass_offset_in_bytes(), Rscratch2);
__ load_klass(Rrecv_klass, Rreceiver);
// Check corner case object method.
Label LobjectMethod;
Label LobjectMethod, L_no_such_interface, Lthrow_ame;
__ testbitdi(CCR0, R0, Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift);
__ btrue(CCR0, LobjectMethod);
// Fallthrough: The normal invokeinterface case.
__ lookup_interface_method(Rrecv_klass, Rinterface_klass, noreg, noreg, Rscratch1, Rscratch2,
L_no_such_interface, /*return_method=*/false);
__ profile_virtual_call(Rrecv_klass, Rscratch1, Rscratch2, false);
// Find entry point to call.
Label Lthrow_icc, Lthrow_ame;
// Result will be returned in Rindex.
__ mr(Rscratch4, Rrecv_klass);
__ mr(Rscratch3, Rindex);
__ lookup_interface_method(Rrecv_klass, Rinterface_klass, Rindex, Rindex, Rscratch1, Rscratch2, Lthrow_icc);
__ cmpdi(CCR0, Rindex, 0);
// Get declaring interface class from method
__ ld(Rinterface_klass, in_bytes(Method::const_offset()), Rmethod);
__ ld(Rinterface_klass, in_bytes(ConstMethod::constants_offset()), Rinterface_klass);
__ ld(Rinterface_klass, ConstantPool::pool_holder_offset_in_bytes(), Rinterface_klass);
// Get itable index from method
__ lwa(Rindex, in_bytes(Method::itable_index_offset()), Rmethod);
__ subfic(Rindex, Rindex, Method::itable_index_max);
__ lookup_interface_method(Rrecv_klass, Rinterface_klass, Rindex, Rmethod2, Rscratch1, Rscratch2,
L_no_such_interface);
__ cmpdi(CCR0, Rmethod2, 0);
__ beq(CCR0, Lthrow_ame);
// Found entry. Jump off!
// Argument and return type profiling.
__ profile_arguments_type(Rindex, Rscratch1, Rscratch2, true);
__ call_from_interpreter(Rindex, Rret_addr, Rscratch1, Rscratch2);
__ profile_arguments_type(Rmethod2, Rscratch1, Rscratch2, true);
//__ profile_called_method(Rindex, Rscratch1);
__ call_from_interpreter(Rmethod2, Rret_addr, Rscratch1, Rscratch2);
// Vtable entry was NULL => Throw abstract method error.
__ bind(Lthrow_ame);
__ mr(Rrecv_klass, Rscratch4);
__ mr(Rindex, Rscratch3);
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
// Interface was not found => Throw incompatible class change error.
__ bind(Lthrow_icc);
__ mr(Rrecv_klass, Rscratch4);
__ bind(L_no_such_interface);
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
__ should_not_reach_here();
DEBUG_ONLY( __ should_not_reach_here(); )
// Special case of invokeinterface called for virtual method of
// java.lang.Object. See ConstantPoolCacheEntry::set_method() for details:
@ -3569,7 +3572,7 @@ void TemplateTable::invokeinterface(int byte_no) {
// to handle this corner case. This code isn't produced by javac, but could
// be produced by another compliant java compiler.
__ bind(LobjectMethod);
invokeinterface_object_method(Rrecv_klass, Rret_addr, Rflags, Rindex, Rscratch1, Rscratch2);
invokeinterface_object_method(Rrecv_klass, Rret_addr, Rflags, Rmethod, Rscratch1, Rscratch2);
}
void TemplateTable::invokedynamic(int byte_no) {

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 SAP SE. All rights reserved.
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,7 @@
#include "code/vtableStubs.hpp"
#include "interp_masm_ppc.hpp"
#include "memory/resourceArea.hpp"
#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@ -55,17 +56,22 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
// PPC port: use fixed size.
const int code_length = VtableStub::pd_code_size_limit(true);
VtableStub* s = new (code_length) VtableStub(true, vtable_index);
// Can be NULL if there is no free space in the code cache.
if (s == NULL) {
return NULL;
}
ResourceMark rm;
CodeBuffer cb(s->entry_point(), code_length);
MacroAssembler* masm = new MacroAssembler(&cb);
address start_pc;
#ifndef PRODUCT
if (CountCompiledCalls) {
__ load_const(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr());
__ lwz(R12_scratch2, 0, R11_scratch1);
int offs = __ load_const_optimized(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr(), R12_scratch2, true);
__ lwz(R12_scratch2, offs, R11_scratch1);
__ addi(R12_scratch2, R12_scratch2, 1);
__ stw(R12_scratch2, 0, R11_scratch1);
__ stw(R12_scratch2, offs, R11_scratch1);
}
#endif
@ -116,6 +122,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
__ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method);
__ mtctr(R12_scratch2);
__ bctr();
masm->flush();
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
@ -125,10 +132,16 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
return s;
}
VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
VtableStub* VtableStubs::create_itable_stub(int itable_index) {
// PPC port: use fixed size.
const int code_length = VtableStub::pd_code_size_limit(false);
VtableStub* s = new (code_length) VtableStub(false, vtable_index);
VtableStub* s = new (code_length) VtableStub(false, itable_index);
// Can be NULL if there is no free space in the code cache.
if (s == NULL) {
return NULL;
}
ResourceMark rm;
CodeBuffer cb(s->entry_point(), code_length);
MacroAssembler* masm = new MacroAssembler(&cb);
@ -136,10 +149,10 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
#ifndef PRODUCT
if (CountCompiledCalls) {
__ load_const(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr());
__ lwz(R12_scratch2, 0, R11_scratch1);
int offs = __ load_const_optimized(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr(), R12_scratch2, true);
__ lwz(R12_scratch2, offs, R11_scratch1);
__ addi(R12_scratch2, R12_scratch2, 1);
__ stw(R12_scratch2, 0, R11_scratch1);
__ stw(R12_scratch2, offs, R11_scratch1);
}
#endif
@ -148,62 +161,28 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
// Entry arguments:
// R19_method: Interface
// R3_ARG1: Receiver
//
const Register rcvr_klass = R11_scratch1;
const Register vtable_len = R12_scratch2;
const Register itable_entry_addr = R21_tmp1;
const Register itable_interface = R22_tmp2;
Label L_no_such_interface;
const Register rcvr_klass = R11_scratch1,
interface = R12_scratch2,
tmp1 = R21_tmp1,
tmp2 = R22_tmp2;
// Get receiver klass.
// We might implicit NULL fault here.
address npe_addr = __ pc(); // npe = null pointer exception
__ null_check(R3_ARG1, oopDesc::klass_offset_in_bytes(), /*implicit only*/NULL);
__ load_klass(rcvr_klass, R3_ARG1);
BLOCK_COMMENT("Load start of itable entries into itable_entry.");
__ lwz(vtable_len, in_bytes(Klass::vtable_length_offset()), rcvr_klass);
__ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes()));
__ add(itable_entry_addr, vtable_len, rcvr_klass);
// Receiver subtype check against REFC.
__ ld(interface, CompiledICHolder::holder_klass_offset(), R19_method);
__ lookup_interface_method(rcvr_klass, interface, noreg,
R0, tmp1, tmp2,
L_no_such_interface, /*return_method=*/ false);
// Loop over all itable entries until desired interfaceOop(Rinterface) found.
BLOCK_COMMENT("Increment itable_entry_addr in loop.");
const int vtable_base_offset = in_bytes(Klass::vtable_start_offset());
__ addi(itable_entry_addr, itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes());
const int itable_offset_search_inc = itableOffsetEntry::size() * wordSize;
Label search;
__ bind(search);
__ ld(itable_interface, 0, itable_entry_addr);
// Handle IncompatibleClassChangeError in itable stubs.
// If the entry is NULL then we've reached the end of the table
// without finding the expected interface, so throw an exception.
BLOCK_COMMENT("Handle IncompatibleClassChangeError in itable stubs.");
Label throw_icce;
__ cmpdi(CCR1, itable_interface, 0);
__ cmpd(CCR0, itable_interface, R19_method);
__ addi(itable_entry_addr, itable_entry_addr, itable_offset_search_inc);
__ beq(CCR1, throw_icce);
__ bne(CCR0, search);
// Entry found and itable_entry_addr points to it, get offset of vtable for interface.
const Register vtable_offset = R12_scratch2;
const Register itable_method = R11_scratch1;
const int vtable_offset_offset = (itableOffsetEntry::offset_offset_in_bytes() -
itableOffsetEntry::interface_offset_in_bytes()) -
itable_offset_search_inc;
__ lwz(vtable_offset, vtable_offset_offset, itable_entry_addr);
// Compute itableMethodEntry and get method and entry point for compiler.
const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) +
itableMethodEntry::method_offset_in_bytes();
__ add(itable_method, rcvr_klass, vtable_offset);
__ ld(R19_method, method_offset, itable_method);
// Get Method* and entrypoint for compiler
__ ld(interface, CompiledICHolder::holder_metadata_offset(), R19_method);
__ lookup_interface_method(rcvr_klass, interface, itable_index,
R19_method, tmp1, tmp2,
L_no_such_interface, /*return_method=*/ true);
#ifndef PRODUCT
if (DebugVtables) {
@ -219,7 +198,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
address ame_addr = __ pc(); // ame = abstract method error
// Must do an explicit check if implicit checks are disabled.
__ null_check(R19_method, in_bytes(Method::from_compiled_offset()), &throw_icce);
__ null_check(R19_method, in_bytes(Method::from_compiled_offset()), &L_no_such_interface);
__ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method);
__ mtctr(R12_scratch2);
__ bctr();
@ -229,8 +208,8 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
// We force resolving of the call site by jumping to the "handle
// wrong method" stub, and so let the interpreter runtime do all the
// dirty work.
__ bind(throw_icce);
__ load_const(R11_scratch1, SharedRuntime::get_handle_wrong_method_stub());
__ bind(L_no_such_interface);
__ load_const_optimized(R11_scratch1, SharedRuntime::get_handle_wrong_method_stub(), R12_scratch2);
__ mtctr(R11_scratch1);
__ bctr();
@ -245,14 +224,15 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
if (DebugVtables || CountCompiledCalls || VerifyOops) {
return 1000;
} else {
int decode_klass_size = MacroAssembler::instr_size_for_decode_klass_not_null();
if (is_vtable_stub) {
return 20 + decode_klass_size + 8 + 8; // Plain + cOops + Traps + safety
} else {
return 96 + decode_klass_size + 12 + 8; // Plain + cOops + Traps + safety
}
}
int size = is_vtable_stub ? 20 + 8 : 164 + 20; // Plain + safety
if (UseCompressedClassPointers) {
size += MacroAssembler::instr_size_for_decode_klass_not_null();
}
if (!ImplicitNullChecks || !os::zero_page_read_protected()) {
size += is_vtable_stub ? 8 : 12;
}
return size;
}
int VtableStub::pd_code_alignment() {

View File

@ -291,7 +291,7 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
length.set_instruction(x->length());
length.load_item();
}
if (needs_store_check) {
if (needs_store_check || x->check_boolean()) {
value.load_item();
} else {
value.load_for_store(x->elt_type());
@ -341,11 +341,14 @@ void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
// Needs GC write barriers.
pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */,
true /* do_load */, false /* patch */, NULL);
__ move(value.result(), array_addr, null_check_info);
// Seems to be a precise.
}
LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info);
__ move(result, array_addr, null_check_info);
if (obj_store) {
// Precise card mark
post_barrier(LIR_OprFact::address(array_addr), value.result());
} else {
__ move(value.result(), array_addr, null_check_info);
}
}

View File

@ -842,6 +842,38 @@ void InterpreterMacroAssembler::unlock_if_synchronized_method(TosState state,
verify_oop(Z_tos, state);
}
void InterpreterMacroAssembler::narrow(Register result, Register ret_type) {
get_method(ret_type);
z_lg(ret_type, Address(ret_type, in_bytes(Method::const_offset())));
z_lb(ret_type, Address(ret_type, in_bytes(ConstMethod::result_type_offset())));
Label notBool, notByte, notChar, done;
// common case first
compareU32_and_branch(ret_type, T_INT, bcondEqual, done);
compareU32_and_branch(ret_type, T_BOOLEAN, bcondNotEqual, notBool);
z_nilf(result, 0x1);
z_bru(done);
bind(notBool);
compareU32_and_branch(ret_type, T_BYTE, bcondNotEqual, notByte);
z_lbr(result, result);
z_bru(done);
bind(notByte);
compareU32_and_branch(ret_type, T_CHAR, bcondNotEqual, notChar);
z_nilf(result, 0xffff);
z_bru(done);
bind(notChar);
// compareU32_and_branch(ret_type, T_SHORT, bcondNotEqual, notShort);
z_lhr(result, result);
// Nothing to do for T_INT
bind(done);
}
// remove activation
//
// Unlock the receiver if this is a synchronized method.

View File

@ -86,6 +86,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
void dispatch_next_noverify_oop(TosState state, int step = 0);
void dispatch_via(TosState state, address* table);
void narrow(Register result, Register ret_type);
// Jump to an invoked target.
void prepare_to_jump_from_interpreted(Register method);
void jump_from_interpreted(Register method, Register temp);

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -2731,8 +2731,8 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
RegisterOrConstant itable_index,
Register method_result,
Register temp1_reg,
Register temp2_reg,
Label& no_such_interface) {
Label& no_such_interface,
bool return_method) {
const Register vtable_len = temp1_reg; // Used to compute itable_entry_addr.
const Register itable_entry_addr = Z_R1_scratch;
@ -2741,11 +2741,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
BLOCK_COMMENT("lookup_interface_method {");
// Load start of itable entries into itable_entry_addr.
z_llgf(vtable_len, Address(recv_klass, InstanceKlass::vtable_length_offset()));
z_llgf(vtable_len, Address(recv_klass, Klass::vtable_length_offset()));
z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes()));
// Loop over all itable entries until desired interfaceOop(Rinterface) found.
const int vtable_base_offset = in_bytes(InstanceKlass::vtable_start_offset());
const int vtable_base_offset = in_bytes(Klass::vtable_start_offset());
add2reg_with_index(itable_entry_addr,
vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(),
@ -2767,38 +2767,36 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
z_brne(search);
// Entry found and itable_entry_addr points to it, get offset of vtable for interface.
if (return_method) {
const int vtable_offset_offset = (itableOffsetEntry::offset_offset_in_bytes() -
itableOffsetEntry::interface_offset_in_bytes()) -
itable_offset_search_inc;
const int vtable_offset_offset = (itableOffsetEntry::offset_offset_in_bytes() -
itableOffsetEntry::interface_offset_in_bytes()) -
itable_offset_search_inc;
// Compute itableMethodEntry and get method and entry point
// we use addressing with index and displacement, since the formula
// for computing the entry's offset has a fixed and a dynamic part,
// the latter depending on the matched interface entry and on the case,
// that the itable index has been passed as a register, not a constant value.
int method_offset = itableMethodEntry::method_offset_in_bytes();
// Fixed part (displacement), common operand.
Register itable_offset = method_result; // Dynamic part (index register).
// Compute itableMethodEntry and get method and entry point
// we use addressing with index and displacement, since the formula
// for computing the entry's offset has a fixed and a dynamic part,
// the latter depending on the matched interface entry and on the case,
// that the itable index has been passed as a register, not a constant value.
int method_offset = itableMethodEntry::method_offset_in_bytes();
// Fixed part (displacement), common operand.
Register itable_offset; // Dynamic part (index register).
if (itable_index.is_register()) {
// Compute the method's offset in that register, for the formula, see the
// else-clause below.
z_sllg(itable_offset, itable_index.as_register(), exact_log2(itableMethodEntry::size() * wordSize));
z_agf(itable_offset, vtable_offset_offset, itable_entry_addr);
} else {
// Displacement increases.
method_offset += itableMethodEntry::size() * wordSize * itable_index.as_constant();
if (itable_index.is_register()) {
// Compute the method's offset in that register, for the formula, see the
// else-clause below.
itable_offset = itable_index.as_register();
// Load index from itable.
z_llgf(itable_offset, vtable_offset_offset, itable_entry_addr);
}
z_sllg(itable_offset, itable_offset, exact_log2(itableMethodEntry::size() * wordSize));
z_agf(itable_offset, vtable_offset_offset, itable_entry_addr);
} else {
itable_offset = Z_R1_scratch;
// Displacement increases.
method_offset += itableMethodEntry::size() * wordSize * itable_index.as_constant();
// Load index from itable.
z_llgf(itable_offset, vtable_offset_offset, itable_entry_addr);
// Finally load the method's oop.
z_lg(method_result, method_offset, itable_offset, recv_klass);
}
// Finally load the method's oop.
z_lg(method_result, method_offset, itable_offset, recv_klass);
BLOCK_COMMENT("} lookup_interface_method");
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -650,8 +650,8 @@ class MacroAssembler: public Assembler {
RegisterOrConstant itable_index,
Register method_result,
Register temp1_reg,
Register temp2_reg,
Label& no_such_interface);
Label& no_such_interface,
bool return_method = true);
// virtual method calling
void lookup_virtual_method(Register recv_klass,

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -491,7 +491,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
Label L_no_such_interface;
__ lookup_interface_method(temp1_recv_klass, temp3_intf,
// Note: next two args must be the same:
Z_index, Z_method, temp2, noreg,
Z_index, Z_method, temp2,
L_no_such_interface);
jump_from_method_handle(_masm, Z_method, temp2, Z_R0, for_compiler_entry);

View File

@ -2628,9 +2628,9 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
Label skip_fixup;
{
Label ic_miss;
const int klass_offset = oopDesc::klass_offset_in_bytes();
const int holder_klass_offset = CompiledICHolder::holder_klass_offset();
const int holder_method_offset = CompiledICHolder::holder_method_offset();
const int klass_offset = oopDesc::klass_offset_in_bytes();
const int holder_klass_offset = CompiledICHolder::holder_klass_offset();
const int holder_metadata_offset = CompiledICHolder::holder_metadata_offset();
// Out-of-line call to ic_miss handler.
__ call_ic_miss_handler(ic_miss, 0x11, 0, Z_R1_scratch);
@ -2659,7 +2659,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
// This def MUST MATCH code in gen_c2i_adapter!
const Register code = Z_R11;
__ z_lg(Z_method, holder_method_offset, Z_method);
__ z_lg(Z_method, holder_metadata_offset, Z_method);
__ load_and_test_long(Z_R0, method_(code));
__ z_brne(ic_miss); // Cache miss: call runtime to handle this.

View File

@ -2314,6 +2314,12 @@ address TemplateInterpreterGenerator::generate_earlyret_entry_for (TosState stat
__ store_const(Address(RjvmtiState, JvmtiThreadState::earlyret_state_offset()),
JvmtiThreadState::earlyret_inactive, 4, 4, Z_R0_scratch);
if (state == itos) {
// Narrow result if state is itos but result type is smaller.
// Need to narrow in the return bytecode rather than in generate_return_entry
// since compiled code callers expect the result to already be narrowed.
__ narrow(Z_tos, Z_tmp_1); /* fall through */
}
__ remove_activation(state,
Z_tmp_1, // retaddr
false, // throw_monitor_exception

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1174,8 +1174,20 @@ void TemplateTable::bastore() {
__ pop_i(Z_ARG3);
__ pop_ptr(Z_tmp_2);
// Z_tos : value
// Z_ARG3 : index
// Z_ARG3 : index
// Z_tmp_2 : array
// Need to check whether array is boolean or byte
// since both types share the bastore bytecode.
__ load_klass(Z_tmp_1, Z_tmp_2);
__ z_llgf(Z_tmp_1, Address(Z_tmp_1, Klass::layout_helper_offset()));
__ z_tmll(Z_tmp_1, Klass::layout_helper_boolean_diffbit());
Label L_skip;
__ z_bfalse(L_skip);
// if it is a T_BOOLEAN array, mask the stored value to 0/1
__ z_nilf(Z_tos, 0x1);
__ bind(L_skip);
// No index shift necessary - pass 0.
index_check(Z_tmp_2, Z_ARG3, 0); // Prefer index in Z_ARG3.
__ z_stc(Z_tos,
@ -2321,6 +2333,13 @@ void TemplateTable::_return(TosState state) {
__ bind(skip_register_finalizer);
}
if (state == itos) {
// Narrow result if state is itos but result type is smaller.
// Need to narrow in the return bytecode rather than in generate_return_entry
// since compiled code callers expect the result to already be narrowed.
__ narrow(Z_tos, Z_tmp_1); /* fall through */
}
__ remove_activation(state, Z_R14);
__ z_br(Z_R14);
}
@ -3526,66 +3545,67 @@ void TemplateTable::invokeinterface(int byte_no) {
transition(vtos, vtos);
assert(byte_no == f1_byte, "use this argument");
Register interface = Z_tos;
Register index = Z_ARG3;
Register receiver = Z_tmp_1;
Register flags = Z_ARG5;
Register klass = Z_ARG2,
method = Z_ARG3,
interface = Z_ARG4,
flags = Z_ARG5,
receiver = Z_tmp_1;
BLOCK_COMMENT("invokeinterface {");
// Destroys Z_ARG1 and Z_ARG2, thus use Z_ARG4 and copy afterwards.
prepare_invoke(byte_no, Z_ARG4, index, // Get f1 klassOop, f2 itable index.
prepare_invoke(byte_no, interface, method, // Get f1 klassOop, f2 itable index.
receiver, flags);
// Z_R14 (== Z_bytecode) : return entry
__ z_lgr(interface, Z_ARG4);
// Special case of invokeinterface called for virtual method of
// java.lang.Object. See cpCacheOop.cpp for details.
// This code isn't produced by javac, but could be produced by
// another compliant java compiler.
Label notMethod;
NearLabel notMethod, no_such_interface, no_such_method;
__ testbit(flags, ConstantPoolCacheEntry::is_forced_virtual_shift);
__ z_brz(notMethod);
invokevirtual_helper(index, receiver, flags);
invokevirtual_helper(method, receiver, flags);
__ bind(notMethod);
// Get receiver klass into klass - also a null check.
Register klass = flags;
__ restore_locals();
__ load_klass(klass, receiver);
__ lookup_interface_method(klass, interface, noreg, noreg, /*temp*/Z_ARG1,
no_such_interface, /*return_method=*/false);
// Profile this call.
__ profile_virtual_call(klass, Z_ARG2/*mdp*/, Z_ARG4/*scratch*/);
__ profile_virtual_call(klass, Z_ARG1/*mdp*/, flags/*scratch*/);
NearLabel no_such_interface, no_such_method;
Register method = Z_tmp_2;
// Find entry point to call.
// TK 2010-08-24: save the index to Z_ARG4. needed in case of an error
// in throw_AbstractMethodErrorByTemplateTable
__ z_lgr(Z_ARG4, index);
// TK 2011-03-24: copy also klass because it could be changed in
// lookup_interface_method
__ z_lgr(Z_ARG2, klass);
__ lookup_interface_method(// inputs: rec. class, interface, itable index
klass, interface, index,
// outputs: method, scan temp. reg
method, Z_tmp_2, Z_R1_scratch,
no_such_interface);
// Get declaring interface class from method
__ z_lg(interface, Address(method, Method::const_offset()));
__ z_lg(interface, Address(interface, ConstMethod::constants_offset()));
__ z_lg(interface, Address(interface, ConstantPool::pool_holder_offset_in_bytes()));
// Get itable index from method
Register index = receiver,
method2 = flags;
__ z_lgf(index, Address(method, Method::itable_index_offset()));
__ z_aghi(index, -Method::itable_index_max);
__ z_lcgr(index, index);
__ lookup_interface_method(klass, interface, index, method2, Z_tmp_2,
no_such_interface);
// Check for abstract method error.
// Note: This should be done more efficiently via a throw_abstract_method_error
// interpreter entry point and a conditional jump to it in case of a null
// method.
__ compareU64_and_branch(method, (intptr_t) 0,
__ compareU64_and_branch(method2, (intptr_t) 0,
Assembler::bcondZero, no_such_method);
__ profile_arguments_type(Z_ARG3, method, Z_ARG5, true);
__ profile_arguments_type(Z_tmp_1, method2, Z_tmp_2, true);
// Do the call.
__ jump_from_interpreted(method, Z_ARG5);
__ jump_from_interpreted(method2, Z_tmp_2);
__ should_not_reach_here();
// exception handling code follows...
@ -3597,12 +3617,8 @@ void TemplateTable::invokeinterface(int byte_no) {
// Throw exception.
__ restore_bcp(); // Bcp must be correct for exception handler (was destroyed).
__ restore_locals(); // Make sure locals pointer is correct as well (was destroyed).
// TK 2010-08-24: Call throw_AbstractMethodErrorByTemplateTable now with the
// relevant information for generating a better error message
__ call_VM(noreg,
CAST_FROM_FN_PTR(address,
InterpreterRuntime::throw_AbstractMethodError),
Z_ARG2, interface, Z_ARG4);
CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
// The call_VM checks for exception, so we should never return here.
__ should_not_reach_here();
@ -3611,12 +3627,8 @@ void TemplateTable::invokeinterface(int byte_no) {
// Throw exception.
__ restore_bcp(); // Bcp must be correct for exception handler (was destroyed).
__ restore_locals(); // Make sure locals pointer is correct as well (was destroyed).
// TK 2010-08-24: Call throw_IncompatibleClassChangeErrorByTemplateTable now with the
// relevant information for generating a better error message
__ call_VM(noreg,
CAST_FROM_FN_PTR(address,
InterpreterRuntime::throw_IncompatibleClassChangeError),
Z_ARG2, interface);
CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
// The call_VM checks for exception, so we should never return here.
__ should_not_reach_here();

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016 SAP SE. All rights reserved.
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,7 @@
#include "code/vtableStubs.hpp"
#include "interp_masm_s390.hpp"
#include "memory/resourceArea.hpp"
#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@ -57,7 +58,6 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
ResourceMark rm;
CodeBuffer cb(s->entry_point(), code_length);
MacroAssembler *masm = new MacroAssembler(&cb);
address start_pc;
int padding_bytes = 0;
#if (!defined(PRODUCT) && defined(COMPILER2))
@ -144,9 +144,9 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
return s;
}
VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
VtableStub* VtableStubs::create_itable_stub(int itable_index) {
const int code_length = VtableStub::pd_code_size_limit(false);
VtableStub *s = new(code_length) VtableStub(false, vtable_index);
VtableStub *s = new(code_length) VtableStub(false, itable_index);
if (s == NULL) { // Indicates OOM in the code cache.
return NULL;
}
@ -154,7 +154,6 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
ResourceMark rm;
CodeBuffer cb(s->entry_point(), code_length);
MacroAssembler *masm = new MacroAssembler(&cb);
address start_pc;
int padding_bytes = 0;
#if (!defined(PRODUCT) && defined(COMPILER2))
@ -174,11 +173,9 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
// Entry arguments:
// Z_method: Interface
// Z_ARG1: Receiver
const Register rcvr_klass = Z_tmp_1; // Used to compute itable_entry_addr.
// Use extra reg to avoid re-load.
const Register vtable_len = Z_tmp_2; // Used to compute itable_entry_addr.
const Register itable_entry_addr = Z_R1_scratch;
const Register itable_interface = Z_R0_scratch;
NearLabel no_such_interface;
const Register rcvr_klass = Z_tmp_1,
interface = Z_tmp_2;
// Get receiver klass.
// Must do an explicit check if implicit checks are disabled.
@ -186,50 +183,15 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
__ null_check(Z_ARG1, Z_R1_scratch, oopDesc::klass_offset_in_bytes());
__ load_klass(rcvr_klass, Z_ARG1);
// Load start of itable entries into itable_entry.
__ z_llgf(vtable_len, Address(rcvr_klass, InstanceKlass::vtable_length_offset()));
__ z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes()));
// Receiver subtype check against REFC.
__ z_lg(interface, Address(Z_method, CompiledICHolder::holder_klass_offset()));
__ lookup_interface_method(rcvr_klass, interface, noreg,
noreg, Z_R1, no_such_interface, /*return_method=*/ false);
// Loop over all itable entries until desired interfaceOop(Rinterface) found.
const int vtable_base_offset = in_bytes(InstanceKlass::vtable_start_offset());
// Count unused bytes.
start_pc = __ pc();
__ add2reg_with_index(itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(), rcvr_klass, vtable_len);
padding_bytes += 20 - (__ pc() - start_pc);
const int itable_offset_search_inc = itableOffsetEntry::size() * wordSize;
Label search;
__ bind(search);
// Handle IncompatibleClassChangeError in itable stubs.
// If the entry is NULL then we've reached the end of the table
// without finding the expected interface, so throw an exception.
NearLabel throw_icce;
__ load_and_test_long(itable_interface, Address(itable_entry_addr));
__ z_bre(throw_icce); // Throw the exception out-of-line.
// Count unused bytes.
start_pc = __ pc();
__ add2reg(itable_entry_addr, itable_offset_search_inc);
padding_bytes += 20 - (__ pc() - start_pc);
__ z_cgr(itable_interface, Z_method);
__ z_brne(search);
// Entry found. Itable_entry_addr points to the subsequent entry (itable_offset_search_inc too far).
// Get offset of vtable for interface.
const Register vtable_offset = Z_R1_scratch;
const Register itable_method = rcvr_klass; // Calculated before.
const int vtable_offset_offset = (itableOffsetEntry::offset_offset_in_bytes() -
itableOffsetEntry::interface_offset_in_bytes()) -
itable_offset_search_inc;
__ z_llgf(vtable_offset, vtable_offset_offset, itable_entry_addr);
// Compute itableMethodEntry and get method and entry point for compiler.
const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) +
itableMethodEntry::method_offset_in_bytes();
__ z_lg(Z_method, method_offset, vtable_offset, itable_method);
// Get Method* and entrypoint for compiler
__ z_lg(interface, Address(Z_method, CompiledICHolder::holder_metadata_offset()));
__ lookup_interface_method(rcvr_klass, interface, itable_index,
Z_method, Z_R1, no_such_interface, /*return_method=*/ true);
#ifndef PRODUCT
if (DebugVtables) {
@ -244,13 +206,13 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
address ame_addr = __ pc();
// Must do an explicit check if implicit checks are disabled.
if (!ImplicitNullChecks) {
__ compare64_and_branch(Z_method, (intptr_t) 0, Assembler::bcondEqual, throw_icce);
__ compare64_and_branch(Z_method, (intptr_t) 0, Assembler::bcondEqual, no_such_interface);
}
__ z_lg(Z_R1_scratch, in_bytes(Method::from_compiled_offset()), Z_method);
__ z_br(Z_R1_scratch);
// Handle IncompatibleClassChangeError in itable stubs.
__ bind(throw_icce);
__ bind(no_such_interface);
// Count unused bytes
// worst case actual size
// We force resolving of the call site by jumping to
@ -273,13 +235,12 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
if (CountCompiledCalls) {
size += 6 * 4;
}
if (is_vtable_stub) {
size += 52;
} else {
size += 104;
size += is_vtable_stub ? 36 : 140;
if (UseCompressedClassPointers) {
size += MacroAssembler::instr_size_for_decode_klass_not_null();
}
if (Universe::narrow_klass_base() != NULL) {
size += 16; // A guess.
if (!ImplicitNullChecks) {
size += 36;
}
return size;
}

View File

@ -2069,9 +2069,10 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
Register method_result,
Register scan_temp,
Register sethi_temp,
Label& L_no_such_interface) {
Label& L_no_such_interface,
bool return_method) {
assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
assert(itable_index.is_constant() || itable_index.as_register() == method_result,
assert(!return_method || itable_index.is_constant() || itable_index.as_register() == method_result,
"caller must use same register for non-constant itable index as for method");
Label L_no_such_interface_restore;
@ -2103,11 +2104,13 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
add(scan_temp, itb_offset, scan_temp);
add(recv_klass, scan_temp, scan_temp);
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
RegisterOrConstant itable_offset = itable_index;
itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset);
itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset);
add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass);
if (return_method) {
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
RegisterOrConstant itable_offset = itable_index;
itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset);
itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset);
add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass);
}
// for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
// if (scan->interface() == intf) {
@ -2142,12 +2145,14 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
bind(L_found_method);
// Got a hit.
int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
// scan_temp[-scan_step] points to the vtable offset we need
ito_offset -= scan_step;
lduw(scan_temp, ito_offset, scan_temp);
ld_ptr(recv_klass, scan_temp, method_result);
if (return_method) {
// Got a hit.
int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
// scan_temp[-scan_step] points to the vtable offset we need
ito_offset -= scan_step;
lduw(scan_temp, ito_offset, scan_temp);
ld_ptr(recv_klass, scan_temp, method_result);
}
if (did_save) {
Label L_done;

View File

@ -1290,7 +1290,8 @@ public:
RegisterOrConstant itable_index,
Register method_result,
Register temp_reg, Register temp2_reg,
Label& no_such_interface);
Label& no_such_interface,
bool return_method = true);
// virtual method calling
void lookup_virtual_method(Register recv_klass,

View File

@ -1079,7 +1079,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
Label ok, ok2;
__ brx(Assembler::equal, false, Assembler::pt, ok);
__ delayed()->ld_ptr(G5_method, CompiledICHolder::holder_method_offset(), G5_method);
__ delayed()->ld_ptr(G5_method, CompiledICHolder::holder_metadata_offset(), G5_method);
__ jump_to(ic_miss, G3_scratch);
__ delayed()->nop();

View File

@ -3173,15 +3173,15 @@ void TemplateTable::invokeinterface(int byte_no) {
assert(byte_no == f1_byte, "use this argument");
const Register Rinterface = G1_scratch;
const Register Rmethod = Lscratch;
const Register Rret = G3_scratch;
const Register Rindex = Lscratch;
const Register O0_recv = O0;
const Register O1_flags = O1;
const Register O2_Klass = O2;
const Register Rscratch = G4_scratch;
assert_different_registers(Rscratch, G5_method);
prepare_invoke(byte_no, Rinterface, Rret, Rindex, O0_recv, O1_flags);
prepare_invoke(byte_no, Rinterface, Rret, Rmethod, O0_recv, O1_flags);
// get receiver klass
__ null_check(O0_recv, oopDesc::klass_offset_in_bytes());
@ -3201,55 +3201,40 @@ void TemplateTable::invokeinterface(int byte_no) {
__ bind(notMethod);
Register Rtemp = O1_flags;
Label L_no_such_interface;
// Receiver subtype check against REFC.
__ lookup_interface_method(// inputs: rec. class, interface, itable index
O2_Klass, Rinterface, noreg,
// outputs: temp reg1, temp reg2, temp reg3
G5_method, Rscratch, Rtemp,
L_no_such_interface,
/*return_method=*/false);
__ profile_virtual_call(O2_Klass, O4);
//
// find entry point to call
//
// compute start of first itableOffsetEntry (which is at end of vtable)
const int base = in_bytes(Klass::vtable_start_offset());
Label search;
Register Rtemp = O1_flags;
// Get declaring interface class from method
__ ld_ptr(Rmethod, Method::const_offset(), Rinterface);
__ ld_ptr(Rinterface, ConstMethod::constants_offset(), Rinterface);
__ ld_ptr(Rinterface, ConstantPool::pool_holder_offset_in_bytes(), Rinterface);
__ ld(O2_Klass, in_bytes(Klass::vtable_length_offset()), Rtemp);
__ sll(Rtemp, LogBytesPerWord, Rtemp); // Rscratch *= 4;
if (Assembler::is_simm13(base)) {
__ add(Rtemp, base, Rtemp);
} else {
__ set(base, Rscratch);
__ add(Rscratch, Rtemp, Rtemp);
}
__ add(O2_Klass, Rtemp, Rscratch);
// Get itable index from method
const Register Rindex = G5_method;
__ ld(Rmethod, Method::itable_index_offset(), Rindex);
__ sub(Rindex, Method::itable_index_max, Rindex);
__ neg(Rindex);
__ bind(search);
__ ld_ptr(Rscratch, itableOffsetEntry::interface_offset_in_bytes(), Rtemp);
{
Label ok;
// Check that entry is non-null. Null entries are probably a bytecode
// problem. If the interface isn't implemented by the receiver class,
// the VM should throw IncompatibleClassChangeError. linkResolver checks
// this too but that's only if the entry isn't already resolved, so we
// need to check again.
__ br_notnull_short( Rtemp, Assembler::pt, ok);
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
__ should_not_reach_here();
__ bind(ok);
}
__ cmp(Rinterface, Rtemp);
__ brx(Assembler::notEqual, true, Assembler::pn, search);
__ delayed()->add(Rscratch, itableOffsetEntry::size() * wordSize, Rscratch);
// entry found and Rscratch points to it
__ ld(Rscratch, itableOffsetEntry::offset_offset_in_bytes(), Rscratch);
assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust instruction below");
__ sll(Rindex, exact_log2(itableMethodEntry::size() * wordSize), Rindex); // Rindex *= 8;
__ add(Rscratch, Rindex, Rscratch);
__ ld_ptr(O2_Klass, Rscratch, G5_method);
__ lookup_interface_method(// inputs: rec. class, interface, itable index
O2_Klass, Rinterface, Rindex,
// outputs: method, scan temp reg, temp reg
G5_method, Rscratch, Rtemp,
L_no_such_interface);
// Check for abstract method error.
{
@ -3266,6 +3251,10 @@ void TemplateTable::invokeinterface(int byte_no) {
__ profile_arguments_type(G5_method, Rcall, Gargs, true);
__ profile_called_method(G5_method, Rscratch);
__ call_from_interpreter(Rcall, Gargs, Rret);
__ bind(L_no_such_interface);
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
__ should_not_reach_here();
}
void TemplateTable::invokehandle(int byte_no) {

View File

@ -27,6 +27,7 @@
#include "code/vtableStubs.hpp"
#include "interp_masm_sparc.hpp"
#include "memory/resourceArea.hpp"
#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@ -140,7 +141,8 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
MacroAssembler* masm = new MacroAssembler(&cb);
Register G3_Klass = G3_scratch;
Register G5_interface = G5; // Passed in as an argument
Register G5_icholder = G5; // Passed in as an argument
Register G4_interface = G4_scratch;
Label search;
// Entry arguments:
@ -164,14 +166,26 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
}
#endif /* PRODUCT */
Label throw_icce;
Label L_no_such_interface;
Register L5_method = L5;
// Receiver subtype check against REFC.
__ ld_ptr(G5_icholder, CompiledICHolder::holder_klass_offset(), G4_interface);
__ lookup_interface_method(// inputs: rec. class, interface, itable index
G3_Klass, G5_interface, itable_index,
G3_Klass, G4_interface, itable_index,
// outputs: scan temp. reg1, scan temp. reg2
L5_method, L2, L3,
L_no_such_interface,
/*return_method=*/ false);
// Get Method* and entrypoint for compiler
__ ld_ptr(G5_icholder, CompiledICHolder::holder_metadata_offset(), G4_interface);
__ lookup_interface_method(// inputs: rec. class, interface, itable index
G3_Klass, G4_interface, itable_index,
// outputs: method, scan temp. reg
L5_method, L2, L3,
throw_icce);
L_no_such_interface);
#ifndef PRODUCT
if (DebugVtables) {
@ -197,7 +211,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ JMP(G3_scratch, 0);
__ delayed()->nop();
__ bind(throw_icce);
__ bind(L_no_such_interface);
AddressLiteral icce(StubRoutines::throw_IncompatibleClassChangeError_entry());
__ jump_to(icce, G3_scratch);
__ delayed()->restore();
@ -232,7 +246,7 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
return basic + slop;
} else {
const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord +
const int basic = (48 LP64_ONLY(+ 6)) * BytesPerInstWord +
// shift;add for load_klass (only shift with zero heap based)
(UseCompressedClassPointers ?
MacroAssembler::instr_size_for_decode_klass_not_null() : 0);

View File

@ -5733,8 +5733,13 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
RegisterOrConstant itable_index,
Register method_result,
Register scan_temp,
Label& L_no_such_interface) {
assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
Label& L_no_such_interface,
bool return_method) {
assert_different_registers(recv_klass, intf_klass, scan_temp);
assert_different_registers(method_result, intf_klass, scan_temp);
assert(recv_klass != method_result || !return_method,
"recv_klass can be destroyed when method isn't needed");
assert(itable_index.is_constant() || itable_index.as_register() == method_result,
"caller must use same register for non-constant itable index as for method");
@ -5751,9 +5756,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
// %%% Could store the aligned, prescaled offset in the klassoop.
lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base));
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off));
if (return_method) {
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off));
}
// for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
// if (scan->interface() == intf) {
@ -5787,9 +5794,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
bind(found_method);
// Got a hit.
movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes()));
movptr(method_result, Address(recv_klass, scan_temp, Address::times_1));
if (return_method) {
// Got a hit.
movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes()));
movptr(method_result, Address(recv_klass, scan_temp, Address::times_1));
}
}

View File

@ -538,7 +538,8 @@ class MacroAssembler: public Assembler {
RegisterOrConstant itable_index,
Register method_result,
Register scan_temp,
Label& no_such_interface);
Label& no_such_interface,
bool return_method = true);
// virtual method calling
void lookup_virtual_method(Register recv_klass,

View File

@ -952,7 +952,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
Label missed;
__ movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes()));
__ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset()));
__ movptr(rbx, Address(holder, CompiledICHolder::holder_method_offset()));
__ movptr(rbx, Address(holder, CompiledICHolder::holder_metadata_offset()));
__ jcc(Assembler::notEqual, missed);
// Method might have been compiled since the call site was patched to
// interpreted if that is the case treat it as a miss so we can get

View File

@ -942,7 +942,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
{
__ load_klass(temp, receiver);
__ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset()));
__ movptr(rbx, Address(holder, CompiledICHolder::holder_method_offset()));
__ movptr(rbx, Address(holder, CompiledICHolder::holder_metadata_offset()));
__ jcc(Assembler::equal, ok);
__ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));

View File

@ -3695,11 +3695,11 @@ void TemplateTable::fast_invokevfinal(int byte_no) {
void TemplateTable::invokeinterface(int byte_no) {
transition(vtos, vtos);
assert(byte_no == f1_byte, "use this argument");
prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 itable index
prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 Method*
rcx, rdx); // recv, flags
// rax: interface klass (from f1)
// rbx: itable index (from f2)
// rax: reference klass (from f1)
// rbx: method (from f2)
// rcx: receiver
// rdx: flags
@ -3721,10 +3721,28 @@ void TemplateTable::invokeinterface(int byte_no) {
__ null_check(rcx, oopDesc::klass_offset_in_bytes());
__ load_klass(rdx, rcx);
Label no_such_interface, no_such_method;
// Receiver subtype check against REFC.
// Superklass in rax. Subklass in rdx. Blows rcx, rdi.
__ lookup_interface_method(// inputs: rec. class, interface, itable index
rdx, rax, noreg,
// outputs: scan temp. reg, scan temp. reg
rbcp, rlocals,
no_such_interface,
/*return_method=*/false);
// profile this call
__ restore_bcp(); // rbcp was destroyed by receiver type check
__ profile_virtual_call(rdx, rbcp, rlocals);
Label no_such_interface, no_such_method;
// Get declaring interface class from method, and itable index
__ movptr(rax, Address(rbx, Method::const_offset()));
__ movptr(rax, Address(rax, ConstMethod::constants_offset()));
__ movptr(rax, Address(rax, ConstantPool::pool_holder_offset_in_bytes()));
__ movl(rbx, Address(rbx, Method::itable_index_offset()));
__ subl(rbx, Method::itable_index_max);
__ negl(rbx);
__ lookup_interface_method(// inputs: rec. class, interface, itable index
rdx, rax, rbx,

View File

@ -27,6 +27,7 @@
#include "code/vtableStubs.hpp"
#include "interp_masm_x86.hpp"
#include "memory/resourceArea.hpp"
#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@ -147,7 +148,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
MacroAssembler* masm = new MacroAssembler(&cb);
// Entry arguments:
// rax,: Interface
// rax: CompiledICHolder
// rcx: Receiver
#ifndef PRODUCT
@ -155,25 +156,42 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
}
#endif /* PRODUCT */
// get receiver (need to skip return address on top of stack)
assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx");
// get receiver klass (also an implicit null-check)
address npe_addr = __ pc();
__ movptr(rsi, Address(rcx, oopDesc::klass_offset_in_bytes()));
// Most registers are in use; we'll use rax, rbx, rsi, rdi
// (If we need to make rsi, rdi callee-save, do a push/pop here.)
const Register method = rbx;
Label throw_icce;
const Register recv_klass_reg = rsi;
const Register holder_klass_reg = rax; // declaring interface klass (DECC)
const Register resolved_klass_reg = rbx; // resolved interface klass (REFC)
const Register temp_reg = rdi;
// Get Method* and entrypoint for compiler
const Register icholder_reg = rax;
__ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
__ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
Label L_no_such_interface;
// get receiver klass (also an implicit null-check)
address npe_addr = __ pc();
assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx");
__ load_klass(recv_klass_reg, rcx);
// Receiver subtype check against REFC.
// Destroys recv_klass_reg value.
__ lookup_interface_method(// inputs: rec. class, interface
recv_klass_reg, resolved_klass_reg, noreg,
// outputs: scan temp. reg1, scan temp. reg2
recv_klass_reg, temp_reg,
L_no_such_interface,
/*return_method=*/false);
// Get selected method from declaring class and itable index
const Register method = rbx;
__ load_klass(recv_klass_reg, rcx); // restore recv_klass_reg
__ lookup_interface_method(// inputs: rec. class, interface, itable index
rsi, rax, itable_index,
recv_klass_reg, holder_klass_reg, itable_index,
// outputs: method, scan temp. reg
method, rdi,
throw_icce);
method, temp_reg,
L_no_such_interface);
// method (rbx): Method*
// rcx: receiver
@ -193,9 +211,10 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
address ame_addr = __ pc();
__ jmp(Address(method, Method::from_compiled_offset()));
__ bind(throw_icce);
__ bind(L_no_such_interface);
__ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
masm->flush();
__ flush();
if (PrintMiscellaneous && (WizardMode || Verbose)) {
tty->print_cr("itable #%d at " PTR_FORMAT "[%d] left over: %d",
@ -220,7 +239,7 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0);
} else {
// Itable stub size
return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0);
return (DebugVtables ? 256 : 110) + (CountCompiledCalls ? 6 : 0);
}
// In order to tune these parameters, run the JVM with VM options
// +PrintMiscellaneous and +WizardMode to see information about

View File

@ -27,6 +27,7 @@
#include "code/vtableStubs.hpp"
#include "interp_masm_x86.hpp"
#include "memory/resourceArea.hpp"
#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
@ -147,36 +148,50 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
#endif
// Entry arguments:
// rax: Interface
// rax: CompiledICHolder
// j_rarg0: Receiver
// Free registers (non-args) are rax (interface), rbx
// get receiver (need to skip return address on top of stack)
assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0");
// get receiver klass (also an implicit null-check)
address npe_addr = __ pc();
// Most registers are in use; we'll use rax, rbx, r10, r11
// (various calling sequences use r[cd]x, r[sd]i, r[89]; stay away from them)
__ load_klass(r10, j_rarg0);
const Register recv_klass_reg = r10;
const Register holder_klass_reg = rax; // declaring interface klass (DECC)
const Register resolved_klass_reg = rbx; // resolved interface klass (REFC)
const Register temp_reg = r11;
Label L_no_such_interface;
const Register icholder_reg = rax;
__ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
__ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
// get receiver klass (also an implicit null-check)
assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0");
address npe_addr = __ pc();
__ load_klass(recv_klass_reg, j_rarg0);
// Receiver subtype check against REFC.
// Destroys recv_klass_reg value.
__ lookup_interface_method(// inputs: rec. class, interface
recv_klass_reg, resolved_klass_reg, noreg,
// outputs: scan temp. reg1, scan temp. reg2
recv_klass_reg, temp_reg,
L_no_such_interface,
/*return_method=*/false);
// Get selected method from declaring class and itable index
const Register method = rbx;
__ load_klass(recv_klass_reg, j_rarg0); // restore recv_klass_reg
__ lookup_interface_method(// inputs: rec. class, interface, itable index
recv_klass_reg, holder_klass_reg, itable_index,
// outputs: method, scan temp. reg
method, temp_reg,
L_no_such_interface);
// If we take a trap while this arg is on the stack we will not
// be able to walk the stack properly. This is not an issue except
// when there are mistakes in this assembly code that could generate
// a spurious fault. Ask me how I know...
const Register method = rbx;
Label throw_icce;
// Get Method* and entrypoint for compiler
__ lookup_interface_method(// inputs: rec. class, interface, itable index
r10, rax, itable_index,
// outputs: method, scan temp. reg
method, r11,
throw_icce);
// method (rbx): Method*
// j_rarg0: receiver
@ -197,7 +212,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
address ame_addr = __ pc();
__ jmp(Address(method, Method::from_compiled_offset()));
__ bind(throw_icce);
__ bind(L_no_such_interface);
__ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
__ flush();
@ -224,8 +239,8 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
(UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
} else {
// Itable stub size
return (DebugVtables ? 512 : 74) + (CountCompiledCalls ? 13 : 0) +
(UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
return (DebugVtables ? 512 : 140) + (CountCompiledCalls ? 13 : 0) +
(UseCompressedClassPointers ? 2 * MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
}
// In order to tune these parameters, run the JVM with VM options
// +PrintMiscellaneous and +WizardMode to see information about

View File

@ -183,3 +183,9 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
return NULL;
}
}
#ifndef PRODUCT
void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
// This is just a stub.
}
#endif //PRODUCT

View File

@ -40,10 +40,10 @@ public class CompiledICHolder extends VMObject {
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("CompiledICHolder");
holderMethod = new MetadataField(type.getAddressField("_holder_method"), 0);
holderKlass = new MetadataField(type.getAddressField("_holder_klass"), 0);
headerSize = type.getSize();
Type type = db.lookupType("CompiledICHolder");
holderMetadata = new MetadataField(type.getAddressField("_holder_metadata"), 0);
holderKlass = new MetadataField(type.getAddressField("_holder_klass"), 0);
headerSize = type.getSize();
}
public CompiledICHolder(Address addr) {
@ -55,12 +55,12 @@ public class CompiledICHolder extends VMObject {
private static long headerSize;
// Fields
private static MetadataField holderMethod;
private static MetadataField holderMetadata;
private static MetadataField holderKlass;
// Accessors for declared fields
public Method getHolderMethod() { return (Method) holderMethod.getValue(this); }
public Klass getHolderKlass() { return (Klass) holderKlass.getValue(this); }
public Metadata getHolderMetadata() { return (Metadata) holderMetadata.getValue(this); }
public Klass getHolderKlass() { return (Klass) holderKlass.getValue(this); }
public void printValueOn(PrintStream tty) {
tty.print("CompiledICHolder");

View File

@ -273,7 +273,7 @@ void AOTCompiledMethod::metadata_do(void f(Metadata*)) {
CompiledIC *ic = CompiledIC_at(&iter);
if (ic->is_icholder_call()) {
CompiledICHolder* cichk = ic->cached_icholder();
f(cichk->holder_method());
f(cichk->holder_metadata());
f(cichk->holder_klass());
} else {
// Get Klass* or NULL (if value is -1) from GOT cell of virtual call PLT stub.

View File

@ -230,10 +230,13 @@ bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecod
#ifdef ASSERT
int index = call_info->resolved_method()->itable_index();
assert(index == itable_index, "CallInfo pre-computes this");
#endif //ASSERT
InstanceKlass* k = call_info->resolved_method()->method_holder();
assert(k->verify_itable_index(itable_index), "sanity check");
InlineCacheBuffer::create_transition_stub(this, k, entry);
#endif //ASSERT
CompiledICHolder* holder = new CompiledICHolder(call_info->resolved_method()->method_holder(),
call_info->resolved_klass()());
holder->claim();
InlineCacheBuffer::create_transition_stub(this, holder, entry);
} else {
assert(call_info->call_kind() == CallInfo::vtable_call, "either itable or vtable");
// Can be different than selected_method->vtable_index(), due to package-private etc.
@ -517,7 +520,14 @@ void CompiledIC::compute_monomorphic_entry(const methodHandle& method,
bool CompiledIC::is_icholder_entry(address entry) {
CodeBlob* cb = CodeCache::find_blob_unsafe(entry);
return (cb != NULL && cb->is_adapter_blob());
if (cb != NULL && cb->is_adapter_blob()) {
return true;
}
// itable stubs also use CompiledICHolder
if (VtableStubs::is_entry_point(entry) && VtableStubs::stub_containing(entry)->is_itable_stub()) {
return true;
}
return false;
}
bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm) {

View File

@ -45,11 +45,11 @@
// \ / \ /
// [4] \ / [4] \->-/
// \->- Megamorphic -<-/
// (Method*)
// (CompiledICHolder*)
//
// The text in paranteses () refere to the value of the inline cache receiver (mov instruction)
// The text in parentheses () refers to the value of the inline cache receiver (mov instruction)
//
// The numbers in square brackets refere to the kind of transition:
// The numbers in square brackets refer to the kind of transition:
// [1]: Initial fixup. Receiver it found from debug information
// [2]: Compilation of a method
// [3]: Recompilation of a method (note: only entry is changed. The Klass* must stay the same)

View File

@ -417,8 +417,7 @@ void CompiledMethod::clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClos
// yet be marked below. (We check this further below).
CompiledICHolder* cichk_oop = ic->cached_icholder();
if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) &&
cichk_oop->holder_klass()->is_loader_alive(is_alive)) {
if (cichk_oop->is_loader_alive(is_alive)) {
return;
}
} else {

View File

@ -1577,7 +1577,7 @@ void nmethod::metadata_do(void f(Metadata*)) {
CompiledIC *ic = CompiledIC_at(&iter);
if (ic->is_icholder_call()) {
CompiledICHolder* cichk = ic->cached_icholder();
f(cichk->holder_method());
f(cichk->holder_metadata());
f(cichk->holder_klass());
} else {
Metadata* ic_oop = ic->cached_metadata();

View File

@ -2538,13 +2538,35 @@ run:
// this could definitely be cleaned up QQQ
Method* callee;
Klass* iclass = cache->f1_as_klass();
// InstanceKlass* interface = (InstanceKlass*) iclass;
Method *interface_method = cache->f2_as_interface_method();
InstanceKlass* iclass = interface_method->method_holder();
// get receiver
int parms = cache->parameter_size();
oop rcvr = STACK_OBJECT(-parms);
CHECK_NULL(rcvr);
InstanceKlass* int2 = (InstanceKlass*) rcvr->klass();
// Receiver subtype check against resolved interface klass (REFC).
{
Klass* refc = cache->f1_as_klass();
itableOffsetEntry* scan;
for (scan = (itableOffsetEntry*) int2->start_of_itable();
scan->interface_klass() != NULL;
scan++) {
if (scan->interface_klass() == refc) {
break;
}
}
// Check that the entry is non-null. A null entry means
// that the receiver class doesn't implement the
// interface, and wasn't the same as when the caller was
// compiled.
if (scan->interface_klass() == NULL) {
VM_JAVA_ERROR(vmSymbols::java_lang_IncompatibleClassChangeError(), "", note_no_trap);
}
}
itableOffsetEntry* ki = (itableOffsetEntry*) int2->start_of_itable();
int i;
for ( i = 0 ; i < int2->itable_length() ; i++, ki++ ) {
@ -2556,7 +2578,8 @@ run:
if (i == int2->itable_length()) {
VM_JAVA_ERROR(vmSymbols::java_lang_IncompatibleClassChangeError(), "", note_no_trap);
}
int mindex = cache->f2_as_index();
int mindex = interface_method->itable_index();
itableMethodEntry* im = ki->first_method_entry(rcvr->klass());
callee = im[mindex].method();
if (callee == NULL) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -795,7 +795,7 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte
// it is not an interface. The receiver for invokespecial calls within interface
// methods must be checked for every call.
InstanceKlass* sender = pool->pool_holder();
sender = sender->is_anonymous() ? sender->host_klass() : sender;
sender = sender->has_host_klass() ? sender->host_klass() : sender;
switch (info.call_kind()) {
case CallInfo::direct_call:
@ -813,6 +813,7 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte
case CallInfo::itable_call:
cp_cache_entry->set_itable_call(
bytecode,
info.resolved_klass(),
info.resolved_method(),
info.itable_index());
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -1061,11 +1061,7 @@ void LinkResolver::resolve_special_call(CallInfo& result,
const LinkInfo& link_info,
TRAPS) {
methodHandle resolved_method = linktime_resolve_special_method(link_info, CHECK);
runtime_resolve_special_method(result, resolved_method,
link_info.resolved_klass(),
link_info.current_klass(),
recv,
link_info.check_access(), CHECK);
runtime_resolve_special_method(result, link_info, resolved_method, recv, CHECK);
}
// throws linktime exceptions
@ -1148,11 +1144,11 @@ methodHandle LinkResolver::linktime_resolve_special_method(const LinkInfo& link_
// throws runtime exceptions
void LinkResolver::runtime_resolve_special_method(CallInfo& result,
const LinkInfo& link_info,
const methodHandle& resolved_method,
KlassHandle resolved_klass,
KlassHandle current_klass,
Handle recv,
bool check_access, TRAPS) {
Handle recv, TRAPS) {
KlassHandle resolved_klass = link_info.resolved_klass();
// resolved method is selected method unless we have an old-style lookup
// for a superclass method
@ -1160,12 +1156,13 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result,
// no checks for shadowing
methodHandle sel_method(THREAD, resolved_method());
if (check_access &&
if (link_info.check_access() &&
// check if the method is not <init>
resolved_method->name() != vmSymbols::object_initializer_name()) {
// check if this is an old-style super call and do a new lookup if so
// check if this is an old-style super call and do a new lookup if so
// a) check if ACC_SUPER flag is set for the current class
KlassHandle current_klass = link_info.current_klass();
if ((current_klass->is_super() || !AllowNonVirtualCalls) &&
// b) check if the class of the resolved_klass is a superclass
// (not supertype in order to exclude interface classes) of the current class.
@ -1185,6 +1182,9 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result,
Method::name_and_sig_as_C_string(resolved_klass(),
resolved_method->name(),
resolved_method->signature()));
// check loader constraints if found a different method
} else if (sel_method() != resolved_method()) {
check_method_loader_constraints(link_info, sel_method, "method", CHECK);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -227,11 +227,10 @@ class LinkResolver: AllStatic {
static methodHandle linktime_resolve_interface_method (const LinkInfo& link_info, TRAPS);
static void runtime_resolve_special_method (CallInfo& result,
const LinkInfo& link_info,
const methodHandle& resolved_method,
KlassHandle resolved_klass,
KlassHandle current_klass,
Handle recv,
bool check_access, TRAPS);
Handle recv, TRAPS);
static void runtime_resolve_virtual_method (CallInfo& result,
const methodHandle& resolved_method,
KlassHandle resolved_klass,

View File

@ -32,8 +32,8 @@ volatile int CompiledICHolder::_live_count;
volatile int CompiledICHolder::_live_not_claimed_count;
CompiledICHolder::CompiledICHolder(Method* method, Klass* klass)
: _holder_method(method), _holder_klass(klass) {
CompiledICHolder::CompiledICHolder(Metadata* metadata, Klass* klass)
: _holder_metadata(metadata), _holder_klass(klass) {
#ifdef ASSERT
Atomic::inc(&_live_count);
Atomic::inc(&_live_not_claimed_count);
@ -47,12 +47,28 @@ CompiledICHolder::~CompiledICHolder() {
}
#endif // ASSERT
bool CompiledICHolder::is_loader_alive(BoolObjectClosure* is_alive) {
if (_holder_metadata->is_method()) {
if (!((Method*)_holder_metadata)->method_holder()->is_loader_alive(is_alive)) {
return false;
}
} else if (_holder_metadata->is_klass()) {
if (!((Klass*)_holder_metadata)->is_loader_alive(is_alive)) {
return false;
}
}
if (!_holder_klass->is_loader_alive(is_alive)) {
return false;
}
return true;
}
// Printing
void CompiledICHolder::print_on(outputStream* st) const {
st->print("%s", internal_name());
st->print(" - method: "); holder_method()->print_value_on(st); st->cr();
st->print(" - klass: "); holder_klass()->print_value_on(st); st->cr();
st->print(" - metadata: "); holder_metadata()->print_value_on(st); st->cr();
st->print(" - klass: "); holder_klass()->print_value_on(st); st->cr();
}
void CompiledICHolder::print_value_on(outputStream* st) const {
@ -63,7 +79,7 @@ void CompiledICHolder::print_value_on(outputStream* st) const {
// Verification
void CompiledICHolder::verify_on(outputStream* st) {
guarantee(holder_method()->is_method(), "should be method");
guarantee(holder_metadata()->is_method() || holder_metadata()->is_klass(), "should be method or klass");
guarantee(holder_klass()->is_klass(), "should be klass");
}

View File

@ -29,8 +29,9 @@
#include "utilities/macros.hpp"
// A CompiledICHolder* is a helper object for the inline cache implementation.
// It holds an intermediate value (method+klass pair) used when converting from
// compiled to an interpreted call.
// It holds:
// (1) (method+klass pair) when converting from compiled to an interpreted call
// (2) (klass+klass pair) when calling itable stub from megamorphic compiled call
//
// These are always allocated in the C heap and are freed during a
// safepoint by the ICBuffer logic. It's unsafe to free them earlier
@ -45,32 +46,33 @@ class CompiledICHolder : public CHeapObj<mtCompiler> {
static volatile int _live_not_claimed_count; // allocated but not yet in use so not
// reachable by iterating over nmethods
Method* _holder_method;
Metadata* _holder_metadata;
Klass* _holder_klass; // to avoid name conflict with oopDesc::_klass
CompiledICHolder* _next;
public:
// Constructor
CompiledICHolder(Method* method, Klass* klass);
CompiledICHolder(Metadata* metadata, Klass* klass);
~CompiledICHolder() NOT_DEBUG_RETURN;
static int live_count() { return _live_count; }
static int live_not_claimed_count() { return _live_not_claimed_count; }
// accessors
Method* holder_method() const { return _holder_method; }
Klass* holder_klass() const { return _holder_klass; }
Metadata* holder_metadata() const { return _holder_metadata; }
void set_holder_method(Method* m) { _holder_method = m; }
void set_holder_klass(Klass* k) { _holder_klass = k; }
void set_holder_metadata(Metadata* m) { _holder_metadata = m; }
void set_holder_klass(Klass* k) { _holder_klass = k; }
// interpreter support (offsets in bytes)
static int holder_method_offset() { return offset_of(CompiledICHolder, _holder_method); }
static int holder_metadata_offset() { return offset_of(CompiledICHolder, _holder_metadata); }
static int holder_klass_offset() { return offset_of(CompiledICHolder, _holder_klass); }
CompiledICHolder* next() { return _next; }
void set_next(CompiledICHolder* n) { _next = n; }
bool is_loader_alive(BoolObjectClosure* is_alive);
// Verify
void verify_on(outputStream* st);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -958,7 +958,7 @@ class SymbolHashMap: public CHeapObj<mtSymbol> {
delete(cur);
}
}
delete _buckets;
FREE_C_HEAP_ARRAY(SymbolHashMapBucket, _buckets);
}
}; // End SymbolHashMap class

View File

@ -255,14 +255,16 @@ void ConstantPoolCacheEntry::set_vtable_call(Bytecodes::Code invoke_code, method
set_direct_or_vtable_call(invoke_code, method, index, false);
}
void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, const methodHandle& method, int index) {
void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code,
KlassHandle referenced_klass,
const methodHandle& method, int index) {
assert(method->method_holder()->verify_itable_index(index), "");
assert(invoke_code == Bytecodes::_invokeinterface, "");
InstanceKlass* interf = method->method_holder();
assert(interf->is_interface(), "must be an interface");
assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here");
set_f1(interf);
set_f2(index);
set_f1(referenced_klass());
set_f2((intx)method());
set_method_flags(as_TosState(method->result_type()),
0, // no option bits
method()->size_of_parameters());
@ -434,10 +436,23 @@ oop ConstantPoolCacheEntry::method_type_if_resolved(const constantPoolHandle& cp
#if INCLUDE_JVMTI
void log_adjust(const char* entry_type, Method* old_method, Method* new_method, bool* trace_name_printed) {
if (log_is_enabled(Info, redefine, class, update)) {
ResourceMark rm;
if (!(*trace_name_printed)) {
log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
*trace_name_printed = true;
}
log_debug(redefine, class, update, constantpool)
("cpc %s entry update: %s(%s)", entry_type, new_method->name()->as_C_string(), new_method->signature()->as_C_string());
}
}
// RedefineClasses() API support:
// If this ConstantPoolCacheEntry refers to old_method then update it
// to refer to new_method.
bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
void ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
Method* new_method, bool * trace_name_printed) {
if (is_vfinal()) {
@ -446,63 +461,35 @@ bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
// match old_method so need an update
// NOTE: can't use set_f2_as_vfinal_method as it asserts on different values
_f2 = (intptr_t)new_method;
if (log_is_enabled(Info, redefine, class, update)) {
ResourceMark rm;
if (!(*trace_name_printed)) {
log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
*trace_name_printed = true;
}
log_debug(redefine, class, update, constantpool)
("cpc vf-entry update: %s(%s)", new_method->name()->as_C_string(), new_method->signature()->as_C_string());
}
return true;
log_adjust("vfinal", old_method, new_method, trace_name_printed);
}
// f1() is not used with virtual entries so bail out
return false;
return;
}
if (_f1 == NULL) {
// NULL f1() means this is a virtual entry so bail out
// We are assuming that the vtable index does not need change.
return false;
}
assert (_f1 != NULL, "should not call with uninteresting entry");
if (_f1 == old_method) {
if (!(_f1->is_method())) {
// _f1 is a Klass* for an interface, _f2 is the method
if (f2_as_interface_method() == old_method) {
_f2 = (intptr_t)new_method;
log_adjust("interface", old_method, new_method, trace_name_printed);
}
} else if (_f1 == old_method) {
_f1 = new_method;
if (log_is_enabled(Info, redefine, class, update)) {
ResourceMark rm;
if (!(*trace_name_printed)) {
log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
*trace_name_printed = true;
}
log_debug(redefine, class, update, constantpool)
("cpc entry update: %s(%s)", new_method->name()->as_C_string(), new_method->signature()->as_C_string());
}
return true;
log_adjust("special, static or dynamic", old_method, new_method, trace_name_printed);
}
return false;
}
// a constant pool cache entry should never contain old or obsolete methods
bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() {
if (is_vfinal()) {
// virtual and final so _f2 contains method ptr instead of vtable index
Metadata* f2 = (Metadata*)_f2;
// Return false if _f2 refers to an old or an obsolete method.
// _f2 == NULL || !_f2->is_method() are just as unexpected here.
return (f2 != NULL NOT_PRODUCT(&& f2->is_valid()) && f2->is_method() &&
!((Method*)f2)->is_old() && !((Method*)f2)->is_obsolete());
} else if (_f1 == NULL ||
(NOT_PRODUCT(_f1->is_valid() &&) !_f1->is_method())) {
// _f1 == NULL || !_f1->is_method() are OK here
Method* m = get_interesting_method_entry(NULL);
// return false if m refers to a non-deleted old or obsolete method
if (m != NULL) {
assert(m->is_valid() && m->is_method(), "m is a valid method");
return !m->is_old() && !m->is_obsolete(); // old is always set for old and obsolete
} else {
return true;
}
// return false if _f1 refers to a non-deleted old or obsolete method
return (NOT_PRODUCT(_f1->is_valid() &&) _f1->is_method() &&
(f1_as_method()->is_deleted() ||
(!f1_as_method()->is_old() && !f1_as_method()->is_obsolete())));
}
Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) {
@ -519,10 +506,11 @@ Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) {
return NULL;
} else {
if (!(_f1->is_method())) {
// _f1 can also contain a Klass* for an interface
return NULL;
// _f1 is a Klass* for an interface
m = f2_as_interface_method();
} else {
m = f1_as_method();
}
m = f1_as_method();
}
assert(m != NULL && m->is_method(), "sanity check");
if (m == NULL || !m->is_method() || (k != NULL && m->method_holder() != k)) {

View File

@ -249,6 +249,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
void set_itable_call(
Bytecodes::Code invoke_code, // the bytecode used; must be invokeinterface
KlassHandle referenced_klass, // the referenced klass in the InterfaceMethodref
const methodHandle& method, // the resolved interface method
int itable_index // index into itable for the method
);
@ -345,6 +346,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
bool is_f1_null() const { Metadata* f1 = f1_ord(); return f1 == NULL; } // classifies a CPC entry as unbound
int f2_as_index() const { assert(!is_vfinal(), ""); return (int) _f2; }
Method* f2_as_vfinal_method() const { assert(is_vfinal(), ""); return (Method*)_f2; }
Method* f2_as_interface_method() const { assert(bytecode_1() == Bytecodes::_invokeinterface, ""); return (Method*)_f2; }
int field_index() const { assert(is_field_entry(), ""); return (_flags & field_index_mask); }
int parameter_size() const { assert(is_method_entry(), ""); return (_flags & parameter_size_mask); }
bool is_volatile() const { return (_flags & (1 << is_volatile_shift)) != 0; }
@ -377,7 +379,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
// trace_name_printed is set to true if the current call has
// printed the klass name so that other routines in the adjust_*
// group don't print the klass name.
bool adjust_method_entry(Method* old_method, Method* new_method,
void adjust_method_entry(Method* old_method, Method* new_method,
bool* trace_name_printed);
bool check_no_old_or_obsolete_entries();
Method* get_interesting_method_entry(Klass* k);

View File

@ -625,9 +625,11 @@ class InstanceKlass: public Klass {
InstanceKlass* host_klass() const {
InstanceKlass** hk = adr_host_klass();
if (hk == NULL) {
assert(!is_anonymous(), "Anonymous classes have host klasses");
return NULL;
} else {
assert(*hk != NULL, "host klass should always be set if the address is not null");
assert(is_anonymous(), "Only anonymous classes have host klasses");
return *hk;
}
}
@ -639,6 +641,9 @@ class InstanceKlass: public Klass {
*addr = host;
}
}
bool has_host_klass() const {
return adr_host_klass() != NULL;
}
bool is_anonymous() const {
return (_misc_flags & _misc_is_anonymous) != 0;
}

View File

@ -1173,7 +1173,6 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass
Array<Method*>* methods = InstanceKlass::cast(interf_h())->methods();
int nof_methods = methods->length();
HandleMark hm;
assert(nof_methods > 0, "at least one method must exist for interface to be in vtable");
Handle interface_loader (THREAD, InstanceKlass::cast(interf_h())->class_loader());
int ime_count = method_count_for_interface(interf_h());
@ -1350,8 +1349,10 @@ void visit_all_interfaces(Array<Klass*>* transitive_intf, InterfaceVisiterClosur
}
}
// Only count interfaces with at least one method
if (method_count > 0) {
// Visit all interfaces which either have any methods or can participate in receiver type check.
// We do not bother to count methods in transitive interfaces, although that would allow us to skip
// this step in the rare case of a zero-method interface extending another zero-method interface.
if (method_count > 0 || InstanceKlass::cast(intf)->transitive_interfaces()->length() > 0) {
blk->doit(intf, method_count);
}
}

View File

@ -700,6 +700,7 @@ class Method : public Metadata {
static ByteSize from_interpreted_offset() { return byte_offset_of(Method, _from_interpreted_entry ); }
static ByteSize interpreter_entry_offset() { return byte_offset_of(Method, _i2i_entry ); }
static ByteSize signature_handler_offset() { return in_ByteSize(sizeof(Method) + wordSize); }
static ByteSize itable_index_offset() { return byte_offset_of(Method, _vtable_index ); }
// for code generation
static int method_data_offset_in_bytes() { return offset_of(Method, _method_data); }

View File

@ -2839,7 +2839,7 @@ jni_Get##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start,
EntryProbe; \
DT_VOID_RETURN_MARK(Get##Result##ArrayRegion); \
typeArrayOop src = typeArrayOop(JNIHandles::resolve_non_null(array)); \
if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)src->length())) { \
if (start < 0 || len < 0 || (start > src->length() - len)) { \
THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \
} else { \
if (len > 0) { \
@ -2889,7 +2889,7 @@ jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start,
EntryProbe; \
DT_VOID_RETURN_MARK(Set##Result##ArrayRegion); \
typeArrayOop dst = typeArrayOop(JNIHandles::resolve_non_null(array)); \
if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)dst->length())) { \
if (start < 0 || len < 0 || (start > dst->length() - len)) { \
THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \
} else { \
if (len > 0) { \
@ -3126,7 +3126,7 @@ JNI_ENTRY(void, jni_GetStringRegion(JNIEnv *env, jstring string, jsize start, js
DT_VOID_RETURN_MARK(GetStringRegion);
oop s = JNIHandles::resolve_non_null(string);
int s_len = java_lang_String::length(s);
if (start < 0 || len < 0 || start + len > s_len) {
if (start < 0 || len < 0 || start > s_len - len) {
THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException());
} else {
if (len > 0) {
@ -3152,7 +3152,7 @@ JNI_ENTRY(void, jni_GetStringUTFRegion(JNIEnv *env, jstring string, jsize start,
DT_VOID_RETURN_MARK(GetStringUTFRegion);
oop s = JNIHandles::resolve_non_null(string);
int s_len = java_lang_String::length(s);
if (start < 0 || len < 0 || start + len > s_len) {
if (start < 0 || len < 0 || start > s_len - len) {
THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException());
} else {
//%note jni_7

View File

@ -230,7 +230,7 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
nonstatic_field(ArrayKlass, _dimension, int) \
volatile_nonstatic_field(ArrayKlass, _higher_dimension, Klass*) \
volatile_nonstatic_field(ArrayKlass, _lower_dimension, Klass*) \
nonstatic_field(CompiledICHolder, _holder_method, Method*) \
nonstatic_field(CompiledICHolder, _holder_metadata, Metadata*) \
nonstatic_field(CompiledICHolder, _holder_klass, Klass*) \
nonstatic_field(ConstantPool, _tags, Array<u1>*) \
nonstatic_field(ConstantPool, _cache, ConstantPoolCache*) \

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "code/vtableStubs.hpp"
#include "runtime/interfaceSupport.hpp"
#include "unittest.hpp"
TEST_VM(code, vtableStubs) {
// Should be in VM to use locks
ThreadInVMfromNative ThreadInVMfromNative(JavaThread::current());
VtableStubs::find_vtable_stub(0); // min vtable index
for (int i = 0; i < 15; i++) {
VtableStubs::find_vtable_stub((1 << i) - 1);
VtableStubs::find_vtable_stub((1 << i));
}
VtableStubs::find_vtable_stub((1 << 15) - 1); // max vtable index
}
TEST_VM(code, itableStubs) {
// Should be in VM to use locks
ThreadInVMfromNative ThreadInVMfromNative(JavaThread::current());
VtableStubs::find_itable_stub(0); // min itable index
for (int i = 0; i < 15; i++) {
VtableStubs::find_itable_stub((1 << i) - 1);
VtableStubs::find_itable_stub((1 << i));
}
VtableStubs::find_itable_stub((1 << 15) - 1); // max itable index
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8174962
* @summary Redefine class with interface method call
* @library /test/lib
* @modules java.base/jdk.internal.misc
* @modules java.compiler
* java.instrument
* jdk.jartool/sun.tools.jar
* @run main RedefineClassHelper
* @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+update*=trace RedefineInterfaceCall
*/
import static jdk.test.lib.Asserts.assertEquals;
interface I1 { default int m() { return 0; } }
interface I2 extends I1 {}
public class RedefineInterfaceCall {
public static class C implements I2 {
public int test(I2 i) {
return i.m(); // invokeinterface cpCacheEntry
}
}
static String newI1 =
"interface I1 { default int m() { return 1; } }";
static String newC =
"public class RedefineInterfaceCall$C implements I2 { " +
" public int test(I2 i) { " +
" return i.m(); " +
" } " +
"} ";
static int test(I2 i) {
return i.m(); // invokeinterface cpCacheEntry
}
public static void main(String[] args) throws Exception {
C c = new C();
assertEquals(test(c), 0);
assertEquals(c.test(c), 0);
RedefineClassHelper.redefineClass(C.class, newC);
assertEquals(c.test(c), 0);
RedefineClassHelper.redefineClass(I1.class, newI1);
assertEquals(test(c), 1);
assertEquals(c.test(c), 1);
RedefineClassHelper.redefineClass(C.class, newC);
assertEquals(c.test(c), 1);
}
}

View File

@ -62,8 +62,8 @@ public class TransformTestCommon {
String parent, String child)
throws Exception {
String parentSharedMatch = parent + " source: shared objects file";
String childSharedMatch = child + " source: shared objects file";
String parentSharedMatch = " " + parent + " source: shared objects file";
String childSharedMatch = " " + child + " source: shared objects file";
if (entry.isParentExpectedShared)
out.shouldContain(parentSharedMatch);

View File

@ -80,8 +80,8 @@ ifneq ($(MAN_DIR), )
endif
LEGAL_NOTICES := \
$(SUPPORT_OUTPUTDIR)/modules_legal/java.base \
$(call FindModuleLegalDirs, $(MODULE)) \
$(call uniq, $(SUPPORT_OUTPUTDIR)/modules_legal/java.base \
$(call FindModuleLegalDirs, $(MODULE))) \
#
LEGAL_NOTICES_PATH := $(call PathList, $(LEGAL_NOTICES))

View File

@ -39,8 +39,6 @@ include MakeBase.gmk
# revisions of all repos will be stored in a file in the top dir, which is then
# used when creating the tracker file.
STORED_SOURCE_REVISION := $(TOPDIR)/.src-rev
# Are we using mercurial?
ifneq ($(and $(HG), $(wildcard $(TOPDIR)/.hg)), )
@ -108,7 +106,15 @@ else
$(call LogInfo, No mercurial configuration present$(COMMA) not updating .src-rev)
$(SOURCE_REVISION_TRACKER): $(STORED_SOURCE_REVISION)
$(install-file)
$(call MakeDir, $(@D))
$(RM) $@
# Only include revisions for repos that are included in the current
# source set.
for r in `cat $<`; do \
if [ -d "$(TOPDIR)/`$(ECHO) $$r | $(CUT) -d':' -f1`" ]; then \
$(PRINTF) "$$r " >> $@; \
fi; \
done
create-source-revision-tracker: $(SOURCE_REVISION_TRACKER)
else

View File

@ -342,11 +342,25 @@ endif # HAS_FILE_FUNCTION
# the build was created from
SOURCE_REVISION_TRACKER := $(SUPPORT_OUTPUTDIR)/src-rev/source-revision-tracker
# Locate all hg repositories included in the forest, as absolute paths
# A cache of the mercurial information which can be dropped in the top of the
# source tree for inclusion in a source bundle.
STORED_SOURCE_REVISION := $(TOPDIR)/.src-rev
# Locate all hg repositories included in the forest, as absolute paths. Use .hg
# dirs if present, otherwise parse the .src-rev file and match dirs.
FindAllReposAbs = \
$(strip $(sort $(dir $(filter-out $(SRC_ROOT)/build/%, $(wildcard \
$(addprefix $(SRC_ROOT)/, .hg */.hg */*/.hg */*/*/.hg) \
)))))
$(if $(and $(HG), $(wildcard $(TOPDIR)/.hg)), \
$(strip $(sort $(dir $(filter-out $(SRC_ROOT)/build/%, $(wildcard \
$(addprefix $(SRC_ROOT)/, .hg */.hg */*/.hg */*/*/.hg)))))) \
, \
$(if $(wildcard $(STORED_SOURCE_REVISION)), \
$(strip $(foreach r, $(call ReadFile, $(STORED_SOURCE_REVISION)), \
$(wildcard $(TOPDIR)/$(firstword $(subst :,$(SPACE),$r))/) \
)) \
, \
$(error No mercurial or .src-rev available, cannot list repositories) \
) \
)
# Locate all hg repositories included in the forest, as relative paths
FindAllReposRel = \

View File

@ -397,8 +397,10 @@ LEGAL_SUBDIRS += share/legal
# $1 - Module to find legal dirs for
FindModuleLegalDirs = \
$(strip $(wildcard \
$(addsuffix /$(strip $1), $(IMPORT_MODULES_LEGAL)) \
$(foreach sub, $(LEGAL_SUBDIRS), $(addsuffix /$(strip $1)/$(sub), $(TOP_SRC_DIRS)))))
$(addsuffix /$(strip $1), $(SUPPORT_OUTPUTDIR)/modules_legal \
$(IMPORT_MODULES_LEGAL)) \
$(foreach sub, $(LEGAL_SUBDIRS), $(addsuffix /$(strip $1)/$(sub), $(TOP_SRC_DIRS))) \
))
################################################################################