mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-18 10:04:42 +02:00
Merge
This commit is contained in:
commit
eb5804b42e
330 changed files with 6804 additions and 3666 deletions
1
.hgtags
1
.hgtags
|
@ -465,3 +465,4 @@ d8c634b016c628622c9abbdc6bf50509e5dedbec jdk-10+35
|
||||||
4f830b447edf04fb4a52151a5ad44d9bb60723cd jdk-10+37
|
4f830b447edf04fb4a52151a5ad44d9bb60723cd jdk-10+37
|
||||||
e569e83139fdfbecfeb3cd9014d560917787f158 jdk-10+38
|
e569e83139fdfbecfeb3cd9014d560917787f158 jdk-10+38
|
||||||
5b834ec962366e00d4445352a999a3ac14e26f64 jdk-10+39
|
5b834ec962366e00d4445352a999a3ac14e26f64 jdk-10+39
|
||||||
|
860326263d1f6a83996d7da0f4c66806ae4aa1eb jdk-10+40
|
||||||
|
|
|
@ -902,6 +902,9 @@ VERSION_PATCH
|
||||||
VERSION_UPDATE
|
VERSION_UPDATE
|
||||||
VERSION_INTERIM
|
VERSION_INTERIM
|
||||||
VERSION_FEATURE
|
VERSION_FEATURE
|
||||||
|
VENDOR_URL_VM_BUG
|
||||||
|
VENDOR_URL_BUG
|
||||||
|
VENDOR_URL
|
||||||
COMPANY_NAME
|
COMPANY_NAME
|
||||||
MACOSX_BUNDLE_ID_BASE
|
MACOSX_BUNDLE_ID_BASE
|
||||||
MACOSX_BUNDLE_NAME_BASE
|
MACOSX_BUNDLE_NAME_BASE
|
||||||
|
@ -1150,6 +1153,9 @@ with_version_major
|
||||||
with_version_minor
|
with_version_minor
|
||||||
with_version_security
|
with_version_security
|
||||||
with_vendor_name
|
with_vendor_name
|
||||||
|
with_vendor_url
|
||||||
|
with_vendor_bug_url
|
||||||
|
with_vendor_vm_bug_url
|
||||||
with_version_string
|
with_version_string
|
||||||
with_version_pre
|
with_version_pre
|
||||||
with_version_opt
|
with_version_opt
|
||||||
|
@ -2074,7 +2080,16 @@ Optional Packages:
|
||||||
compatibility and is ignored
|
compatibility and is ignored
|
||||||
--with-version-security Deprecated. Option is kept for backwards
|
--with-version-security Deprecated. Option is kept for backwards
|
||||||
compatibility and is ignored
|
compatibility and is ignored
|
||||||
--with-vendor-name Set vendor name [not specified]
|
--with-vendor-name Set vendor name. Among others, used to set the
|
||||||
|
'java.vendor' and 'java.vm.vendor' system
|
||||||
|
properties. [not specified]
|
||||||
|
--with-vendor-url Set the 'java.vendor.url' system property [not
|
||||||
|
specified]
|
||||||
|
--with-vendor-bug-url Set the 'java.vendor.url.bug' system property [not
|
||||||
|
specified]
|
||||||
|
--with-vendor-vm-bug-url
|
||||||
|
Sets the bug URL which will be displayed when the VM
|
||||||
|
crashes [not specified]
|
||||||
--with-version-string Set version string [calculated]
|
--with-version-string Set version string [calculated]
|
||||||
--with-version-pre Set the base part of the version 'PRE' field
|
--with-version-pre Set the base part of the version 'PRE' field
|
||||||
(pre-release identifier) ['internal']
|
(pre-release identifier) ['internal']
|
||||||
|
@ -5176,7 +5191,7 @@ VS_SDK_PLATFORM_NAME_2013=
|
||||||
#CUSTOM_AUTOCONF_INCLUDE
|
#CUSTOM_AUTOCONF_INCLUDE
|
||||||
|
|
||||||
# Do not change or remove the following line, it is needed for consistency checks:
|
# Do not change or remove the following line, it is needed for consistency checks:
|
||||||
DATE_WHEN_GENERATED=1513805283
|
DATE_WHEN_GENERATED=1516225089
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
|
@ -25072,12 +25087,62 @@ fi
|
||||||
if test "x$with_vendor_name" = xyes; then
|
if test "x$with_vendor_name" = xyes; then
|
||||||
as_fn_error $? "--with-vendor-name must have a value" "$LINENO" 5
|
as_fn_error $? "--with-vendor-name must have a value" "$LINENO" 5
|
||||||
elif ! [[ $with_vendor_name =~ ^[[:print:]]*$ ]] ; then
|
elif ! [[ $with_vendor_name =~ ^[[:print:]]*$ ]] ; then
|
||||||
as_fn_error $? "--with--vendor-name contains non-printing characters: $with_vendor_name" "$LINENO" 5
|
as_fn_error $? "--with-vendor-name contains non-printing characters: $with_vendor_name" "$LINENO" 5
|
||||||
else
|
elif test "x$with_vendor_name" != x; then
|
||||||
|
# Only set COMPANY_NAME if '--with-vendor-name' was used and is not empty.
|
||||||
|
# Otherwise we will use the value from "version-numbers" included above.
|
||||||
COMPANY_NAME="$with_vendor_name"
|
COMPANY_NAME="$with_vendor_name"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# The vendor URL, if any
|
||||||
|
|
||||||
|
# Check whether --with-vendor-url was given.
|
||||||
|
if test "${with_vendor_url+set}" = set; then :
|
||||||
|
withval=$with_vendor_url;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$with_vendor_url" = xyes; then
|
||||||
|
as_fn_error $? "--with-vendor-url must have a value" "$LINENO" 5
|
||||||
|
elif ! [[ $with_vendor_url =~ ^[[:print:]]*$ ]] ; then
|
||||||
|
as_fn_error $? "--with-vendor-url contains non-printing characters: $with_vendor_url" "$LINENO" 5
|
||||||
|
else
|
||||||
|
VENDOR_URL="$with_vendor_url"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# The vendor bug URL, if any
|
||||||
|
|
||||||
|
# Check whether --with-vendor-bug-url was given.
|
||||||
|
if test "${with_vendor_bug_url+set}" = set; then :
|
||||||
|
withval=$with_vendor_bug_url;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$with_vendor_bug_url" = xyes; then
|
||||||
|
as_fn_error $? "--with-vendor-bug-url must have a value" "$LINENO" 5
|
||||||
|
elif ! [[ $with_vendor_bug_url =~ ^[[:print:]]*$ ]] ; then
|
||||||
|
as_fn_error $? "--with-vendor-bug-url contains non-printing characters: $with_vendor_bug_url" "$LINENO" 5
|
||||||
|
else
|
||||||
|
VENDOR_URL_BUG="$with_vendor_bug_url"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# The vendor VM bug URL, if any
|
||||||
|
|
||||||
|
# Check whether --with-vendor-vm-bug-url was given.
|
||||||
|
if test "${with_vendor_vm_bug_url+set}" = set; then :
|
||||||
|
withval=$with_vendor_vm_bug_url;
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x$with_vendor_vm_bug_url" = xyes; then
|
||||||
|
as_fn_error $? "--with-vendor-vm-bug-url must have a value" "$LINENO" 5
|
||||||
|
elif ! [[ $with_vendor_vm_bug_url =~ ^[[:print:]]*$ ]] ; then
|
||||||
|
as_fn_error $? "--with-vendor-vm-bug-url contains non-printing characters: $with_vendor_vm_bug_url" "$LINENO" 5
|
||||||
|
else
|
||||||
|
VENDOR_URL_VM_BUG="$with_vendor_vm_bug_url"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Override version from arguments
|
# Override version from arguments
|
||||||
|
|
||||||
# If --with-version-string is set, process it first. It is possible to
|
# If --with-version-string is set, process it first. It is possible to
|
||||||
|
|
|
@ -80,16 +80,55 @@ AC_DEFUN_ONCE([JDKVER_SETUP_JDK_VERSION_NUMBERS],
|
||||||
|
|
||||||
# The vendor name, if any
|
# The vendor name, if any
|
||||||
AC_ARG_WITH(vendor-name, [AS_HELP_STRING([--with-vendor-name],
|
AC_ARG_WITH(vendor-name, [AS_HELP_STRING([--with-vendor-name],
|
||||||
[Set vendor name @<:@not specified@:>@])])
|
[Set vendor name. Among others, used to set the 'java.vendor'
|
||||||
|
and 'java.vm.vendor' system properties. @<:@not specified@:>@])])
|
||||||
if test "x$with_vendor_name" = xyes; then
|
if test "x$with_vendor_name" = xyes; then
|
||||||
AC_MSG_ERROR([--with-vendor-name must have a value])
|
AC_MSG_ERROR([--with-vendor-name must have a value])
|
||||||
elif [ ! [[ $with_vendor_name =~ ^[[:print:]]*$ ]] ]; then
|
elif [ ! [[ $with_vendor_name =~ ^[[:print:]]*$ ]] ]; then
|
||||||
AC_MSG_ERROR([--with--vendor-name contains non-printing characters: $with_vendor_name])
|
AC_MSG_ERROR([--with-vendor-name contains non-printing characters: $with_vendor_name])
|
||||||
else
|
elif test "x$with_vendor_name" != x; then
|
||||||
|
# Only set COMPANY_NAME if '--with-vendor-name' was used and is not empty.
|
||||||
|
# Otherwise we will use the value from "version-numbers" included above.
|
||||||
COMPANY_NAME="$with_vendor_name"
|
COMPANY_NAME="$with_vendor_name"
|
||||||
fi
|
fi
|
||||||
AC_SUBST(COMPANY_NAME)
|
AC_SUBST(COMPANY_NAME)
|
||||||
|
|
||||||
|
# The vendor URL, if any
|
||||||
|
AC_ARG_WITH(vendor-url, [AS_HELP_STRING([--with-vendor-url],
|
||||||
|
[Set the 'java.vendor.url' system property @<:@not specified@:>@])])
|
||||||
|
if test "x$with_vendor_url" = xyes; then
|
||||||
|
AC_MSG_ERROR([--with-vendor-url must have a value])
|
||||||
|
elif [ ! [[ $with_vendor_url =~ ^[[:print:]]*$ ]] ]; then
|
||||||
|
AC_MSG_ERROR([--with-vendor-url contains non-printing characters: $with_vendor_url])
|
||||||
|
else
|
||||||
|
VENDOR_URL="$with_vendor_url"
|
||||||
|
fi
|
||||||
|
AC_SUBST(VENDOR_URL)
|
||||||
|
|
||||||
|
# The vendor bug URL, if any
|
||||||
|
AC_ARG_WITH(vendor-bug-url, [AS_HELP_STRING([--with-vendor-bug-url],
|
||||||
|
[Set the 'java.vendor.url.bug' system property @<:@not specified@:>@])])
|
||||||
|
if test "x$with_vendor_bug_url" = xyes; then
|
||||||
|
AC_MSG_ERROR([--with-vendor-bug-url must have a value])
|
||||||
|
elif [ ! [[ $with_vendor_bug_url =~ ^[[:print:]]*$ ]] ]; then
|
||||||
|
AC_MSG_ERROR([--with-vendor-bug-url contains non-printing characters: $with_vendor_bug_url])
|
||||||
|
else
|
||||||
|
VENDOR_URL_BUG="$with_vendor_bug_url"
|
||||||
|
fi
|
||||||
|
AC_SUBST(VENDOR_URL_BUG)
|
||||||
|
|
||||||
|
# The vendor VM bug URL, if any
|
||||||
|
AC_ARG_WITH(vendor-vm-bug-url, [AS_HELP_STRING([--with-vendor-vm-bug-url],
|
||||||
|
[Sets the bug URL which will be displayed when the VM crashes @<:@not specified@:>@])])
|
||||||
|
if test "x$with_vendor_vm_bug_url" = xyes; then
|
||||||
|
AC_MSG_ERROR([--with-vendor-vm-bug-url must have a value])
|
||||||
|
elif [ ! [[ $with_vendor_vm_bug_url =~ ^[[:print:]]*$ ]] ]; then
|
||||||
|
AC_MSG_ERROR([--with-vendor-vm-bug-url contains non-printing characters: $with_vendor_vm_bug_url])
|
||||||
|
else
|
||||||
|
VENDOR_URL_VM_BUG="$with_vendor_vm_bug_url"
|
||||||
|
fi
|
||||||
|
AC_SUBST(VENDOR_URL_VM_BUG)
|
||||||
|
|
||||||
# Override version from arguments
|
# Override version from arguments
|
||||||
|
|
||||||
# If --with-version-string is set, process it first. It is possible to
|
# If --with-version-string is set, process it first. It is possible to
|
||||||
|
|
|
@ -142,6 +142,20 @@ IMPORT_MODULES_MAKE:=@IMPORT_MODULES_MAKE@
|
||||||
|
|
||||||
COPYRIGHT_YEAR:=@COPYRIGHT_YEAR@
|
COPYRIGHT_YEAR:=@COPYRIGHT_YEAR@
|
||||||
|
|
||||||
|
# Platform naming variables
|
||||||
|
LAUNCHER_NAME:=@LAUNCHER_NAME@
|
||||||
|
PRODUCT_NAME:=@PRODUCT_NAME@
|
||||||
|
PRODUCT_SUFFIX:=@PRODUCT_SUFFIX@
|
||||||
|
JDK_RC_PLATFORM_NAME:=@JDK_RC_PLATFORM_NAME@
|
||||||
|
COMPANY_NAME:=@COMPANY_NAME@
|
||||||
|
HOTSPOT_VM_DISTRO:=@HOTSPOT_VM_DISTRO@
|
||||||
|
MACOSX_BUNDLE_NAME_BASE=@MACOSX_BUNDLE_NAME_BASE@
|
||||||
|
MACOSX_BUNDLE_ID_BASE=@MACOSX_BUNDLE_ID_BASE@
|
||||||
|
USERNAME:=@USERNAME@
|
||||||
|
VENDOR_URL:=@VENDOR_URL@
|
||||||
|
VENDOR_URL_BUG:=@VENDOR_URL_BUG@
|
||||||
|
VENDOR_URL_VM_BUG:=@VENDOR_URL_VM_BUG@
|
||||||
|
|
||||||
# New (JEP-223) version information
|
# New (JEP-223) version information
|
||||||
|
|
||||||
## Building blocks of the version string
|
## Building blocks of the version string
|
||||||
|
@ -201,16 +215,30 @@ VERSION_CFLAGS := \
|
||||||
-DVERSION_CLASSFILE_MINOR=$(VERSION_CLASSFILE_MINOR) \
|
-DVERSION_CLASSFILE_MINOR=$(VERSION_CLASSFILE_MINOR) \
|
||||||
#
|
#
|
||||||
|
|
||||||
# Platform naming variables
|
ifneq ($(COMPANY_NAME),)
|
||||||
LAUNCHER_NAME:=@LAUNCHER_NAME@
|
# COMPANY_NAME is set to "N/A" in $AUTOCONF_DIR/version-numbers by default,
|
||||||
PRODUCT_NAME:=@PRODUCT_NAME@
|
# but can be customized with the '--with-vendor-name' configure option.
|
||||||
PRODUCT_SUFFIX:=@PRODUCT_SUFFIX@
|
# Only export "VENDOR" to the build if COMPANY_NAME contains a real value.
|
||||||
JDK_RC_PLATFORM_NAME:=@JDK_RC_PLATFORM_NAME@
|
# Otherwise the default value for VENDOR, which is used to set the "java.vendor"
|
||||||
COMPANY_NAME:=@COMPANY_NAME@
|
# and "java.vm.vendor" properties is hard-coded into the source code (i.e. in
|
||||||
HOTSPOT_VM_DISTRO:=@HOTSPOT_VM_DISTRO@
|
# System.c in the jdk for "vm.vendor" and vm_version.cpp in the VM for "java.vm.vendor")
|
||||||
MACOSX_BUNDLE_NAME_BASE=@MACOSX_BUNDLE_NAME_BASE@
|
ifneq ($(COMPANY_NAME), N/A)
|
||||||
MACOSX_BUNDLE_ID_BASE=@MACOSX_BUNDLE_ID_BASE@
|
VERSION_CFLAGS += -DVENDOR='"$(COMPANY_NAME)"'
|
||||||
USERNAME:=@USERNAME@
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Only export VENDOR_URL, VENDOR_URL_BUG and VENDOR_VM_URL_BUG to the build if
|
||||||
|
# they are not empty. Otherwise, default values which are defined in the sources
|
||||||
|
# will be used.
|
||||||
|
ifneq ($(VENDOR_URL),)
|
||||||
|
VERSION_CFLAGS += -DVENDOR_URL='"$(VENDOR_URL)"'
|
||||||
|
endif
|
||||||
|
ifneq ($(VENDOR_URL_BUG),)
|
||||||
|
VERSION_CFLAGS += -DVENDOR_URL_BUG='"$(VENDOR_URL_BUG)"'
|
||||||
|
endif
|
||||||
|
ifneq ($(VENDOR_URL_VM_BUG),)
|
||||||
|
VERSION_CFLAGS += -DVENDOR_URL_VM_BUG='"$(VENDOR_URL_VM_BUG)"'
|
||||||
|
endif
|
||||||
|
|
||||||
# Different naming strings generated from the above information.
|
# Different naming strings generated from the above information.
|
||||||
RUNTIME_NAME=$(PRODUCT_NAME) $(PRODUCT_SUFFIX)
|
RUNTIME_NAME=$(PRODUCT_NAME) $(PRODUCT_SUFFIX)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -869,7 +869,6 @@ JDWP "Java(tm) Debug Wire Protocol"
|
||||||
"section in "
|
"section in "
|
||||||
"<cite>The Java™ Virtual Machine Specification</cite>. "
|
"<cite>The Java™ Virtual Machine Specification</cite>. "
|
||||||
"Since JDWP version 1.5."
|
"Since JDWP version 1.5."
|
||||||
"<p>
|
|
||||||
(Out
|
(Out
|
||||||
(referenceType refType "The reference type ID.")
|
(referenceType refType "The reference type ID.")
|
||||||
)
|
)
|
||||||
|
@ -2723,7 +2722,6 @@ JDWP "Java(tm) Debug Wire Protocol"
|
||||||
"<P>"
|
"<P>"
|
||||||
"The events that are grouped in a composite event are restricted in the "
|
"The events that are grouped in a composite event are restricted in the "
|
||||||
"following ways: "
|
"following ways: "
|
||||||
"<P>"
|
|
||||||
"<UL>"
|
"<UL>"
|
||||||
"<LI>Only with other thread start events for the same thread:"
|
"<LI>Only with other thread start events for the same thread:"
|
||||||
" <UL>"
|
" <UL>"
|
||||||
|
|
|
@ -222,6 +222,7 @@ $(eval $(call SetupNativeCompilation, BUILD_LIBJVM, \
|
||||||
CFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
|
CFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
|
||||||
CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
|
CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \
|
||||||
vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
|
vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
|
||||||
|
arguments.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \
|
||||||
DISABLED_WARNINGS_clang := tautological-compare, \
|
DISABLED_WARNINGS_clang := tautological-compare, \
|
||||||
DISABLED_WARNINGS_xlc := 1540-0216 1540-0198 1540-1090 1540-1639 \
|
DISABLED_WARNINGS_xlc := 1540-0216 1540-0198 1540-1090 1540-1639 \
|
||||||
1540-1088 1500-010, \
|
1540-1088 1500-010, \
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -30,8 +30,8 @@ import java.io.*;
|
||||||
class AbstractCommandNode extends AbstractNamedNode {
|
class AbstractCommandNode extends AbstractNamedNode {
|
||||||
|
|
||||||
void document(PrintWriter writer) {
|
void document(PrintWriter writer) {
|
||||||
writer.println("<h5><a name=\"" + context.whereC + "\">" + name +
|
writer.println("<h5 id=\"" + context.whereC + "\">" + name +
|
||||||
" Command</a> (" + nameNode.value() + ")</h5>");
|
" Command (" + nameNode.value() + ")</h5>");
|
||||||
writer.println(comment());
|
writer.println(comment());
|
||||||
writer.println("<dl>");
|
writer.println("<dl>");
|
||||||
for (Node node : components) {
|
for (Node node : components) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -62,8 +62,8 @@ abstract class AbstractNamedNode extends Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
void document(PrintWriter writer) {
|
void document(PrintWriter writer) {
|
||||||
writer.println("<h4><a name=" + name + ">" + name +
|
writer.println("<h4 id=\"" + name + "\">" + name +
|
||||||
" Command Set</a></h4>");
|
" Command Set</h4>");
|
||||||
for (Node node : components) {
|
for (Node node : components) {
|
||||||
node.document(writer);
|
node.document(writer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -43,11 +43,11 @@ abstract class AbstractTypeListNode extends AbstractNamedNode {
|
||||||
if (components.isEmpty()) {
|
if (components.isEmpty()) {
|
||||||
writer.println("<dd>(None)");
|
writer.println("<dd>(None)");
|
||||||
} else {
|
} else {
|
||||||
writer.println("<dd><table border=1 cellpadding=3 cellspacing=0 width=\"90%\" summary=\"\"><tr>");
|
writer.println("<dd><table><tr>");
|
||||||
for (int i = maxStructIndent; i > 0; --i) {
|
for (int i = maxStructIndent; i > 0; --i) {
|
||||||
writer.print("<th width=\"4%\">");
|
writer.print("<th style=\"width: 4%\">");
|
||||||
}
|
}
|
||||||
writer.println("<th width=\"15%\"><th width=\"65%\">");
|
writer.println("<th style=\"width: 15%\"><th style=\"width: 65%\">");
|
||||||
writer.println("");
|
writer.println("");
|
||||||
for (Node node : components) {
|
for (Node node : components) {
|
||||||
node.document(writer);
|
node.document(writer);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -38,8 +38,8 @@ class CommandSetNode extends AbstractNamedNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
void document(PrintWriter writer) {
|
void document(PrintWriter writer) {
|
||||||
writer.println("<h4><a name=\"" + context.whereC + "\">" + name +
|
writer.println("<h4 id=\"" + context.whereC + "\">" + name +
|
||||||
" Command Set</a> (" +
|
" Command Set (" +
|
||||||
nameNode.value() + ")</h4>");
|
nameNode.value() + ")</h4>");
|
||||||
writer.println(comment());
|
writer.println(comment());
|
||||||
for (Node node : components) {
|
for (Node node : components) {
|
||||||
|
@ -51,11 +51,13 @@ class CommandSetNode extends AbstractNamedNode {
|
||||||
writer.print("<li><a href=\"#" + context.whereC + "\">");
|
writer.print("<li><a href=\"#" + context.whereC + "\">");
|
||||||
writer.println(name() + "</a> Command Set (" +
|
writer.println(name() + "</a> Command Set (" +
|
||||||
nameNode.value() + ")");
|
nameNode.value() + ")");
|
||||||
writer.println("<ul>");
|
if (components.size() > 0) {
|
||||||
for (Node node : components) {
|
writer.println("<ul>");
|
||||||
node.documentIndex(writer);
|
for (Node node : components) {
|
||||||
|
node.documentIndex(writer);
|
||||||
|
}
|
||||||
|
writer.println("</ul>");
|
||||||
}
|
}
|
||||||
writer.println("</ul>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void genJavaClassSpecifics(PrintWriter writer, int depth) {
|
void genJavaClassSpecifics(PrintWriter writer, int depth) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -54,15 +54,15 @@ class ConstantSetNode extends AbstractNamedNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
void document(PrintWriter writer) {
|
void document(PrintWriter writer) {
|
||||||
writer.println("<h4><a name=\"" + context.whereC + "\">" + name +
|
writer.println("<h4 id=\"" + context.whereC + "\">" + name +
|
||||||
" Constants</a></h4>");
|
" Constants</h4>");
|
||||||
writer.println(comment());
|
writer.println(comment());
|
||||||
writer.println("<dd><table border=1 cellpadding=3 cellspacing=0 width=\"90%\" summary=\"\"><tr>");
|
writer.println("<table><tr>");
|
||||||
writer.println("<th width=\"20%\"><th width=\"5%\"><th width=\"65%\">");
|
writer.println("<th style=\"width: 20%\"><th style=\"width: 5%\"><th style=\"width: 65%\">");
|
||||||
ConstantNode n;
|
ConstantNode n;
|
||||||
for (Node node : components) {
|
for (Node node : components) {
|
||||||
n = (ConstantNode)node;
|
n = (ConstantNode)node;
|
||||||
writer.println("<a NAME=\"" + name + "_" + n.name + "\"></a>");
|
writer.println("<span id=\"" + name + "_" + n.name + "\"></span>");
|
||||||
n.document(writer);
|
n.document(writer);
|
||||||
}
|
}
|
||||||
writer.println("</table>");
|
writer.println("</table>");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -43,7 +43,7 @@ class ErrorSetNode extends AbstractSimpleNode {
|
||||||
if (components.isEmpty()) {
|
if (components.isEmpty()) {
|
||||||
writer.println("<dd>(None)");
|
writer.println("<dd>(None)");
|
||||||
} else {
|
} else {
|
||||||
writer.println("<dd><table border=1 cellpadding=3 cellspacing=0 width=\"90%\" summary=\"\">");
|
writer.println("<dd><table>");
|
||||||
for (Node node : components) {
|
for (Node node : components) {
|
||||||
node.document(writer);
|
node.document(writer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -41,11 +41,22 @@ class RootNode extends AbstractNamedNode {
|
||||||
|
|
||||||
void document(PrintWriter writer) {
|
void document(PrintWriter writer) {
|
||||||
writer.println("<!DOCTYPE html>");
|
writer.println("<!DOCTYPE html>");
|
||||||
writer.println("<html><head><title>" + comment() + "</title></head>");
|
writer.println("<html lang=\"en\">");
|
||||||
writer.println("<body bgcolor=\"white\">");
|
writer.println("<head>");
|
||||||
|
writer.println("<meta charset=\"utf-8\"/>");
|
||||||
|
writer.println("<title>" + comment() + "</title>");
|
||||||
|
writer.println("<style>");
|
||||||
|
writer.println("body {background-color:white;}");
|
||||||
|
writer.println("table {border: 1px solid grey; border-spacing:0px; border-collapse: separate; width: 90%;}");
|
||||||
|
writer.println("td, th {padding: 3px; border: 1px solid black;}");
|
||||||
|
writer.println("</style>");
|
||||||
|
writer.println("</head>");
|
||||||
|
writer.println("<body>");
|
||||||
|
writer.println("<ul>");
|
||||||
for (Node node : components) {
|
for (Node node : components) {
|
||||||
node.documentIndex(writer);
|
node.documentIndex(writer);
|
||||||
}
|
}
|
||||||
|
writer.println("</ul>");
|
||||||
for (Node node : components) {
|
for (Node node : components) {
|
||||||
node.document(writer);
|
node.document(writer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ $(eval $(call IncludeCustomExtension, test/JtregNativeHotspot.gmk))
|
||||||
# Add more directories here when needed.
|
# Add more directories here when needed.
|
||||||
BUILD_HOTSPOT_JTREG_NATIVE_SRC += \
|
BUILD_HOTSPOT_JTREG_NATIVE_SRC += \
|
||||||
$(TOPDIR)/test/hotspot/jtreg/gc/g1/TestJNIWeakG1 \
|
$(TOPDIR)/test/hotspot/jtreg/gc/g1/TestJNIWeakG1 \
|
||||||
|
$(TOPDIR)/test/hotspot/jtreg/gc/stress/TestJNIBlockFullGC \
|
||||||
$(TOPDIR)/test/hotspot/jtreg/gc/stress/gclocker \
|
$(TOPDIR)/test/hotspot/jtreg/gc/stress/gclocker \
|
||||||
$(TOPDIR)/test/hotspot/jtreg/gc/cslocker \
|
$(TOPDIR)/test/hotspot/jtreg/gc/cslocker \
|
||||||
$(TOPDIR)/test/hotspot/jtreg/native_sanity \
|
$(TOPDIR)/test/hotspot/jtreg/native_sanity \
|
||||||
|
|
|
@ -2295,23 +2295,32 @@ public:
|
||||||
rf(Vn, 5), rf(Rd, 0);
|
rf(Vn, 5), rf(Rd, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INSN(NAME, opc, opc2) \
|
#define INSN(NAME, opc, opc2, isSHR) \
|
||||||
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int shift){ \
|
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, int shift){ \
|
||||||
starti; \
|
starti; \
|
||||||
/* The encodings for the immh:immb fields (bits 22:16) are \
|
/* The encodings for the immh:immb fields (bits 22:16) in *SHR are \
|
||||||
* 0001 xxx 8B/16B, shift = xxx \
|
* 0001 xxx 8B/16B, shift = 16 - UInt(immh:immb) \
|
||||||
* 001x xxx 4H/8H, shift = xxxx \
|
* 001x xxx 4H/8H, shift = 32 - UInt(immh:immb) \
|
||||||
* 01xx xxx 2S/4S, shift = xxxxx \
|
* 01xx xxx 2S/4S, shift = 64 - UInt(immh:immb) \
|
||||||
* 1xxx xxx 1D/2D, shift = xxxxxx (1D is RESERVED) \
|
* 1xxx xxx 1D/2D, shift = 128 - UInt(immh:immb) \
|
||||||
|
* (1D is RESERVED) \
|
||||||
|
* for SHL shift is calculated as: \
|
||||||
|
* 0001 xxx 8B/16B, shift = UInt(immh:immb) - 8 \
|
||||||
|
* 001x xxx 4H/8H, shift = UInt(immh:immb) - 16 \
|
||||||
|
* 01xx xxx 2S/4S, shift = UInt(immh:immb) - 32 \
|
||||||
|
* 1xxx xxx 1D/2D, shift = UInt(immh:immb) - 64 \
|
||||||
|
* (1D is RESERVED) \
|
||||||
*/ \
|
*/ \
|
||||||
assert((1 << ((T>>1)+3)) > shift, "Invalid Shift value"); \
|
assert((1 << ((T>>1)+3)) > shift, "Invalid Shift value"); \
|
||||||
|
int cVal = (1 << (((T >> 1) + 3) + (isSHR ? 1 : 0))); \
|
||||||
|
int encodedShift = isSHR ? cVal - shift : cVal + shift; \
|
||||||
f(0, 31), f(T & 1, 30), f(opc, 29), f(0b011110, 28, 23), \
|
f(0, 31), f(T & 1, 30), f(opc, 29), f(0b011110, 28, 23), \
|
||||||
f((1 << ((T>>1)+3))|shift, 22, 16); f(opc2, 15, 10), rf(Vn, 5), rf(Vd, 0); \
|
f(encodedShift, 22, 16); f(opc2, 15, 10), rf(Vn, 5), rf(Vd, 0); \
|
||||||
}
|
}
|
||||||
|
|
||||||
INSN(shl, 0, 0b010101);
|
INSN(shl, 0, 0b010101, /* isSHR = */ false);
|
||||||
INSN(sshr, 0, 0b000001);
|
INSN(sshr, 0, 0b000001, /* isSHR = */ true);
|
||||||
INSN(ushr, 1, 0b000001);
|
INSN(ushr, 1, 0b000001, /* isSHR = */ true);
|
||||||
|
|
||||||
#undef INSN
|
#undef INSN
|
||||||
|
|
||||||
|
|
|
@ -774,7 +774,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||||
__ load_klass(rscratch1, receiver);
|
__ load_klass(rscratch1, receiver);
|
||||||
__ ldr(tmp, Address(holder, CompiledICHolder::holder_klass_offset()));
|
__ ldr(tmp, Address(holder, CompiledICHolder::holder_klass_offset()));
|
||||||
__ cmp(rscratch1, tmp);
|
__ cmp(rscratch1, tmp);
|
||||||
__ ldr(rmethod, Address(holder, CompiledICHolder::holder_method_offset()));
|
__ ldr(rmethod, Address(holder, CompiledICHolder::holder_metadata_offset()));
|
||||||
__ br(Assembler::EQ, ok);
|
__ br(Assembler::EQ, ok);
|
||||||
__ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
|
__ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
|
||||||
|
|
||||||
|
|
|
@ -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 success, the result will be in method_result, and execution falls through.
|
||||||
// On failure, execution transfers to the given label.
|
// On failure, execution transfers to the given label.
|
||||||
void MacroAssembler::lookup_interface_method(Register Rklass,
|
void MacroAssembler::lookup_interface_method(Register Rklass,
|
||||||
Register Rinterf,
|
Register Rintf,
|
||||||
Register Rindex,
|
RegisterOrConstant itable_index,
|
||||||
Register method_result,
|
Register method_result,
|
||||||
Register temp_reg1,
|
Register Rscan,
|
||||||
Register temp_reg2,
|
Register Rtmp,
|
||||||
Label& L_no_such_interface) {
|
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)
|
// Compute start of first itableOffsetEntry (which is at the end of the vtable)
|
||||||
const int base = in_bytes(Klass::vtable_start_offset());
|
const int base = in_bytes(Klass::vtable_start_offset());
|
||||||
const int scale = exact_log2(vtableEntry::size_in_bytes());
|
const int scale = exact_log2(vtableEntry::size_in_bytes());
|
||||||
ldr_s32(temp_reg2, Address(Rklass, Klass::vtable_length_offset())); // Get length of vtable
|
ldr_s32(Rtmp, Address(Rklass, Klass::vtable_length_offset())); // Get length of vtable
|
||||||
add(Ritable, Rklass, base);
|
add(Rscan, Rklass, base);
|
||||||
add(Ritable, Ritable, AsmOperand(temp_reg2, lsl, scale));
|
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);
|
#ifdef AARCH64
|
||||||
add(Ritable, Ritable, itableOffsetEntry::size() * HeapWordSize);
|
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);
|
if (method_result != noreg) {
|
||||||
|
// Interface found at previous position of Rscan, now load the method
|
||||||
// Check that the entry is non-null. A null entry means that the receiver
|
ldr_s32(Rtmp, Address(Rscan, itableOffsetEntry::offset_offset_in_bytes() - entry_size));
|
||||||
// class doesn't implement the interface, and wasn't the same as the
|
if (itable_index.is_register()) {
|
||||||
// receiver class checked when the interface was resolved.
|
add(Rtmp, Rtmp, Rklass); // Add offset to Klass*
|
||||||
|
assert(itableMethodEntry::size() * HeapWordSize == wordSize, "adjust the scaling in the code below");
|
||||||
ldr(temp_reg2, Address(Ritable, itableOffsetEntry::interface_offset_in_bytes()));
|
assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust the offset in the code below");
|
||||||
cbz(temp_reg2, L_no_such_interface);
|
ldr(method_result, Address::indexed_ptr(Rtmp, itable_index.as_register()));
|
||||||
|
} else {
|
||||||
cmp(Rinterf, temp_reg2);
|
int method_offset = itableMethodEntry::size() * HeapWordSize * itable_index.as_constant() +
|
||||||
b(search, ne);
|
itableMethodEntry::method_offset_in_bytes();
|
||||||
|
add_slow(method_result, Rklass, method_offset);
|
||||||
ldr_s32(temp_reg2, Address(Ritable, itableOffsetEntry::offset_offset_in_bytes()));
|
ldr(method_result, Address(method_result, Rtmp));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
|
|
|
@ -1316,7 +1316,7 @@ public:
|
||||||
|
|
||||||
void lookup_interface_method(Register recv_klass,
|
void lookup_interface_method(Register recv_klass,
|
||||||
Register intf_klass,
|
Register intf_klass,
|
||||||
Register itable_index,
|
RegisterOrConstant itable_index,
|
||||||
Register method_result,
|
Register method_result,
|
||||||
Register temp_reg1,
|
Register temp_reg1,
|
||||||
Register temp_reg2,
|
Register temp_reg2,
|
||||||
|
|
|
@ -984,7 +984,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||||
|
|
||||||
__ load_klass(receiver_klass, receiver);
|
__ load_klass(receiver_klass, receiver);
|
||||||
__ ldr(holder_klass, Address(Ricklass, CompiledICHolder::holder_klass_offset()));
|
__ 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);
|
__ cmp(receiver_klass, holder_klass);
|
||||||
|
|
||||||
#ifdef AARCH64
|
#ifdef AARCH64
|
||||||
|
|
|
@ -4198,7 +4198,7 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
const Register Rflags = R3_tmp;
|
const Register Rflags = R3_tmp;
|
||||||
const Register Rklass = 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
|
// Special case of invokeinterface called for virtual method of
|
||||||
// java.lang.Object. See cpCacheOop.cpp for details.
|
// java.lang.Object. See cpCacheOop.cpp for details.
|
||||||
|
@ -4207,56 +4207,39 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
Label notMethod;
|
Label notMethod;
|
||||||
__ tbz(Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift, notMethod);
|
__ tbz(Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift, notMethod);
|
||||||
|
|
||||||
__ mov(Rmethod, Rindex);
|
|
||||||
invokevirtual_helper(Rmethod, Rrecv, Rflags);
|
invokevirtual_helper(Rmethod, Rrecv, Rflags);
|
||||||
__ bind(notMethod);
|
__ bind(notMethod);
|
||||||
|
|
||||||
// Get receiver klass into Rklass - also a null check
|
// Get receiver klass into Rklass - also a null check
|
||||||
__ load_klass(Rklass, Rrecv);
|
__ 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 this call
|
||||||
__ profile_virtual_call(R0_tmp, Rklass);
|
__ profile_virtual_call(R0_tmp, Rklass);
|
||||||
|
|
||||||
// Compute start of first itableOffsetEntry (which is at the end of the vtable)
|
// Get declaring interface class from method
|
||||||
const int base = in_bytes(Klass::vtable_start_offset());
|
__ ldr(Rtemp, Address(Rmethod, Method::const_offset()));
|
||||||
assert(vtableEntry::size() == 1, "adjust the scaling in the code below");
|
__ ldr(Rtemp, Address(Rtemp, ConstMethod::constants_offset()));
|
||||||
__ ldr_s32(Rtemp, Address(Rklass, Klass::vtable_length_offset())); // Get length of vtable
|
__ ldr(Rinterf, Address(Rtemp, ConstantPool::pool_holder_offset_in_bytes()));
|
||||||
__ add(Ritable, Rklass, base);
|
|
||||||
__ add(Ritable, Ritable, AsmOperand(Rtemp, lsl, LogBytesPerWord));
|
|
||||||
|
|
||||||
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);
|
__ lookup_interface_method(// inputs: rec. class, interface
|
||||||
|
Rklass, Rinterf, Rindex,
|
||||||
__ bind(search);
|
// outputs: scan temp. reg1, scan temp. reg2
|
||||||
__ add(Ritable, Ritable, itableOffsetEntry::size() * HeapWordSize);
|
Rmethod, Ritable, Rtemp,
|
||||||
|
no_such_interface);
|
||||||
__ 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));
|
|
||||||
|
|
||||||
// Rmethod: Method* to call
|
// Rmethod: Method* to call
|
||||||
|
|
||||||
|
@ -4278,6 +4261,13 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
|
|
||||||
// do the call
|
// do the call
|
||||||
__ jump_from_interpreted(Rmethod);
|
__ 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) {
|
void TemplateTable::invokehandle(int byte_no) {
|
||||||
|
@ -4345,7 +4335,6 @@ void TemplateTable::_new() {
|
||||||
Label done;
|
Label done;
|
||||||
Label initialize_header;
|
Label initialize_header;
|
||||||
Label initialize_object; // including clearing the fields
|
Label initialize_object; // including clearing the fields
|
||||||
Label allocate_shared;
|
|
||||||
|
|
||||||
const bool allow_shared_alloc =
|
const bool allow_shared_alloc =
|
||||||
Universe::heap()->supports_inline_contig_alloc();
|
Universe::heap()->supports_inline_contig_alloc();
|
||||||
|
@ -4390,13 +4379,19 @@ void TemplateTable::_new() {
|
||||||
// Klass::_lh_instance_slow_path_bit is really a bit mask, not bit number
|
// Klass::_lh_instance_slow_path_bit is really a bit mask, not bit number
|
||||||
__ tbnz(Rsize, exact_log2(Klass::_lh_instance_slow_path_bit), slow_case);
|
__ tbnz(Rsize, exact_log2(Klass::_lh_instance_slow_path_bit), slow_case);
|
||||||
|
|
||||||
|
// Allocate the instance:
|
||||||
|
// If TLAB is enabled:
|
||||||
|
// Try to allocate in the TLAB.
|
||||||
|
// If fails, go to the slow path.
|
||||||
|
// Else If inline contiguous allocations are enabled:
|
||||||
|
// Try to allocate in eden.
|
||||||
|
// If fails due to heap end, go to slow path.
|
||||||
//
|
//
|
||||||
// Allocate the instance
|
// If TLAB is enabled OR inline contiguous is enabled:
|
||||||
// 1) Try to allocate in the TLAB
|
// Initialize the allocation.
|
||||||
// 2) if fail and the object is large allocate in the shared Eden
|
// Exit.
|
||||||
// 3) if the above fails (or is not applicable), go to a slow case
|
//
|
||||||
// (creates a new TLAB, etc.)
|
// Go to slow path.
|
||||||
|
|
||||||
if (UseTLAB) {
|
if (UseTLAB) {
|
||||||
const Register Rtlab_top = R1_tmp;
|
const Register Rtlab_top = R1_tmp;
|
||||||
const Register Rtlab_end = R2_tmp;
|
const Register Rtlab_end = R2_tmp;
|
||||||
|
@ -4406,7 +4401,7 @@ void TemplateTable::_new() {
|
||||||
__ ldr(Rtlab_end, Address(Rthread, in_bytes(JavaThread::tlab_end_offset())));
|
__ ldr(Rtlab_end, Address(Rthread, in_bytes(JavaThread::tlab_end_offset())));
|
||||||
__ add(Rtlab_top, Robj, Rsize);
|
__ add(Rtlab_top, Robj, Rsize);
|
||||||
__ cmp(Rtlab_top, Rtlab_end);
|
__ cmp(Rtlab_top, Rtlab_end);
|
||||||
__ b(allow_shared_alloc ? allocate_shared : slow_case, hi);
|
__ b(slow_case, hi);
|
||||||
__ str(Rtlab_top, Address(Rthread, JavaThread::tlab_top_offset()));
|
__ str(Rtlab_top, Address(Rthread, JavaThread::tlab_top_offset()));
|
||||||
if (ZeroTLAB) {
|
if (ZeroTLAB) {
|
||||||
// the fields have been already cleared
|
// the fields have been already cleared
|
||||||
|
@ -4415,45 +4410,43 @@ void TemplateTable::_new() {
|
||||||
// initialize both the header and fields
|
// initialize both the header and fields
|
||||||
__ b(initialize_object);
|
__ b(initialize_object);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
// Allocation in the shared Eden, if allowed.
|
||||||
|
if (allow_shared_alloc) {
|
||||||
|
const Register Rheap_top_addr = R2_tmp;
|
||||||
|
const Register Rheap_top = R5_tmp;
|
||||||
|
const Register Rheap_end = Rtemp;
|
||||||
|
assert_different_registers(Robj, Rklass, Rsize, Rheap_top_addr, Rheap_top, Rheap_end, LR);
|
||||||
|
|
||||||
// Allocation in the shared Eden, if allowed.
|
// heap_end now (re)loaded in the loop since also used as a scratch register in the CAS
|
||||||
if (allow_shared_alloc) {
|
__ ldr_literal(Rheap_top_addr, Lheap_top_addr);
|
||||||
__ bind(allocate_shared);
|
|
||||||
|
|
||||||
const Register Rheap_top_addr = R2_tmp;
|
Label retry;
|
||||||
const Register Rheap_top = R5_tmp;
|
__ bind(retry);
|
||||||
const Register Rheap_end = Rtemp;
|
|
||||||
assert_different_registers(Robj, Rklass, Rsize, Rheap_top_addr, Rheap_top, Rheap_end, LR);
|
|
||||||
|
|
||||||
// heap_end now (re)loaded in the loop since also used as a scratch register in the CAS
|
|
||||||
__ ldr_literal(Rheap_top_addr, Lheap_top_addr);
|
|
||||||
|
|
||||||
Label retry;
|
|
||||||
__ bind(retry);
|
|
||||||
|
|
||||||
#ifdef AARCH64
|
#ifdef AARCH64
|
||||||
__ ldxr(Robj, Rheap_top_addr);
|
__ ldxr(Robj, Rheap_top_addr);
|
||||||
#else
|
#else
|
||||||
__ ldr(Robj, Address(Rheap_top_addr));
|
__ ldr(Robj, Address(Rheap_top_addr));
|
||||||
#endif // AARCH64
|
#endif // AARCH64
|
||||||
|
|
||||||
__ ldr(Rheap_end, Address(Rheap_top_addr, (intptr_t)Universe::heap()->end_addr()-(intptr_t)Universe::heap()->top_addr()));
|
__ ldr(Rheap_end, Address(Rheap_top_addr, (intptr_t)Universe::heap()->end_addr()-(intptr_t)Universe::heap()->top_addr()));
|
||||||
__ add(Rheap_top, Robj, Rsize);
|
__ add(Rheap_top, Robj, Rsize);
|
||||||
__ cmp(Rheap_top, Rheap_end);
|
__ cmp(Rheap_top, Rheap_end);
|
||||||
__ b(slow_case, hi);
|
__ b(slow_case, hi);
|
||||||
|
|
||||||
// Update heap top atomically.
|
// Update heap top atomically.
|
||||||
// If someone beats us on the allocation, try again, otherwise continue.
|
// If someone beats us on the allocation, try again, otherwise continue.
|
||||||
#ifdef AARCH64
|
#ifdef AARCH64
|
||||||
__ stxr(Rtemp2, Rheap_top, Rheap_top_addr);
|
__ stxr(Rtemp2, Rheap_top, Rheap_top_addr);
|
||||||
__ cbnz_w(Rtemp2, retry);
|
__ cbnz_w(Rtemp2, retry);
|
||||||
#else
|
#else
|
||||||
__ atomic_cas_bool(Robj, Rheap_top, Rheap_top_addr, 0, Rheap_end/*scratched*/);
|
__ atomic_cas_bool(Robj, Rheap_top, Rheap_top_addr, 0, Rheap_end/*scratched*/);
|
||||||
__ b(retry, ne);
|
__ b(retry, ne);
|
||||||
#endif // AARCH64
|
#endif // AARCH64
|
||||||
|
|
||||||
__ incr_allocated_bytes(Rsize, Rtemp);
|
__ incr_allocated_bytes(Rsize, Rtemp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UseTLAB || allow_shared_alloc) {
|
if (UseTLAB || allow_shared_alloc) {
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "interp_masm_arm.hpp"
|
#include "interp_masm_arm.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/klassVtable.hpp"
|
#include "oops/klassVtable.hpp"
|
||||||
#include "runtime/sharedRuntime.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
|
// R0-R3 / R0-R7 registers hold the arguments and cannot be spoiled
|
||||||
const Register Rclass = AARCH64_ONLY(R9) NOT_AARCH64(R4);
|
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 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)
|
// Calculate the start of itable (itable goes after vtable)
|
||||||
const int scale = exact_log2(vtableEntry::size_in_bytes());
|
const int scale = exact_log2(vtableEntry::size_in_bytes());
|
||||||
address npe_addr = __ pc();
|
address npe_addr = __ pc();
|
||||||
__ load_klass(Rclass, R0);
|
__ load_klass(Rclass, R0);
|
||||||
__ ldr_s32(Rlength, Address(Rclass, Klass::vtable_length_offset()));
|
|
||||||
|
|
||||||
__ add(Rscan, Rclass, in_bytes(Klass::vtable_start_offset()));
|
Label L_no_such_interface;
|
||||||
__ add(Rscan, Rscan, AsmOperand(Rlength, lsl, scale));
|
|
||||||
|
|
||||||
// Search through the itable for an interface equal to incoming Ricklass
|
// Receiver subtype check against REFC.
|
||||||
// itable looks like [intface][offset][intface][offset][intface][offset]
|
__ ldr(Rintf, Address(Ricklass, CompiledICHolder::holder_klass_offset()));
|
||||||
const int entry_size = itableOffsetEntry::size() * HeapWordSize;
|
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
||||||
assert(itableOffsetEntry::interface_offset_in_bytes() == 0, "not added for convenience");
|
Rclass, Rintf, noreg,
|
||||||
|
// outputs: temp reg1, temp reg2
|
||||||
|
noreg, Rscan, Rtemp,
|
||||||
|
L_no_such_interface);
|
||||||
|
|
||||||
Label loop;
|
// Get Method* and entry point for compiler
|
||||||
__ bind(loop);
|
__ ldr(Rintf, Address(Ricklass, CompiledICHolder::holder_metadata_offset()));
|
||||||
__ ldr(tmp, Address(Rscan, entry_size, post_indexed));
|
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
||||||
#ifdef AARCH64
|
Rclass, Rintf, itable_index,
|
||||||
Label found;
|
// outputs: temp reg1, temp reg2, temp reg3
|
||||||
__ cmp(tmp, Ricklass);
|
Rmethod, Rscan, Rtemp,
|
||||||
__ b(found, eq);
|
L_no_such_interface);
|
||||||
__ 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));
|
|
||||||
|
|
||||||
address ame_addr = __ pc();
|
address ame_addr = __ pc();
|
||||||
|
|
||||||
#ifdef AARCH64
|
#ifdef AARCH64
|
||||||
__ ldr(tmp, Address(Rmethod, Method::from_compiled_offset()));
|
__ ldr(Rtemp, Address(Rmethod, Method::from_compiled_offset()));
|
||||||
__ br(tmp);
|
__ br(Rtemp);
|
||||||
#else
|
#else
|
||||||
__ ldr(PC, Address(Rmethod, Method::from_compiled_offset()));
|
__ ldr(PC, Address(Rmethod, Method::from_compiled_offset()));
|
||||||
#endif // AARCH64
|
#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();
|
masm->flush();
|
||||||
|
|
||||||
if (PrintMiscellaneous && (WizardMode || Verbose)) {
|
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);
|
instr_count = NOT_AARCH64(4) AARCH64_ONLY(5);
|
||||||
} else {
|
} else {
|
||||||
// itable stub size
|
// itable stub size
|
||||||
instr_count = NOT_AARCH64(20) AARCH64_ONLY(20);
|
instr_count = NOT_AARCH64(31) AARCH64_ONLY(31);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef AARCH64
|
#ifdef AARCH64
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -34,8 +34,8 @@
|
||||||
#include "runtime/basicLock.hpp"
|
#include "runtime/basicLock.hpp"
|
||||||
#include "runtime/biasedLocking.hpp"
|
#include "runtime/biasedLocking.hpp"
|
||||||
#include "runtime/os.hpp"
|
#include "runtime/os.hpp"
|
||||||
#include "runtime/stubRoutines.hpp"
|
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
|
#include "runtime/stubRoutines.hpp"
|
||||||
#include "utilities/align.hpp"
|
#include "utilities/align.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -33,36 +33,36 @@
|
||||||
// (see c1_globals.hpp)
|
// (see c1_globals.hpp)
|
||||||
|
|
||||||
#ifndef TIERED
|
#ifndef TIERED
|
||||||
define_pd_global(bool, BackgroundCompilation, true );
|
define_pd_global(bool, BackgroundCompilation, true);
|
||||||
define_pd_global(bool, CICompileOSR, true );
|
define_pd_global(bool, CICompileOSR, true);
|
||||||
define_pd_global(bool, InlineIntrinsics, true );
|
define_pd_global(bool, InlineIntrinsics, true);
|
||||||
define_pd_global(bool, PreferInterpreterNativeStubs, false);
|
define_pd_global(bool, PreferInterpreterNativeStubs, false);
|
||||||
define_pd_global(bool, ProfileTraps, false);
|
define_pd_global(bool, ProfileTraps, false);
|
||||||
define_pd_global(bool, UseOnStackReplacement, true );
|
define_pd_global(bool, UseOnStackReplacement, true);
|
||||||
define_pd_global(bool, TieredCompilation, false);
|
define_pd_global(bool, TieredCompilation, false);
|
||||||
define_pd_global(intx, CompileThreshold, 1000 );
|
define_pd_global(intx, CompileThreshold, 1000);
|
||||||
|
|
||||||
define_pd_global(intx, OnStackReplacePercentage, 1400 );
|
define_pd_global(intx, OnStackReplacePercentage, 1400);
|
||||||
define_pd_global(bool, UseTLAB, true );
|
define_pd_global(bool, UseTLAB, true);
|
||||||
define_pd_global(bool, ProfileInterpreter, false);
|
define_pd_global(bool, ProfileInterpreter, false);
|
||||||
define_pd_global(intx, FreqInlineSize, 325 );
|
define_pd_global(intx, FreqInlineSize, 325 );
|
||||||
define_pd_global(bool, ResizeTLAB, true );
|
define_pd_global(bool, ResizeTLAB, true);
|
||||||
define_pd_global(intx, ReservedCodeCacheSize, 32*M );
|
define_pd_global(uintx, ReservedCodeCacheSize, 32*M);
|
||||||
define_pd_global(intx, CodeCacheExpansionSize, 32*K );
|
define_pd_global(uintx, CodeCacheExpansionSize, 32*K);
|
||||||
define_pd_global(uintx,CodeCacheMinBlockLength, 1);
|
define_pd_global(uintx, CodeCacheMinBlockLength, 1);
|
||||||
define_pd_global(uintx,MetaspaceSize, 12*M );
|
define_pd_global(size_t, MetaspaceSize, 12*M);
|
||||||
define_pd_global(bool, NeverActAsServerClassMachine, true );
|
define_pd_global(bool, NeverActAsServerClassMachine, true);
|
||||||
define_pd_global(intx, NewSizeThreadIncrease, 16*K );
|
define_pd_global(size_t, NewSizeThreadIncrease, 16*K);
|
||||||
define_pd_global(uint64_t,MaxRAM, 1ULL*G);
|
define_pd_global(uint64_t, MaxRAM, 1ULL*G);
|
||||||
define_pd_global(intx, InitialCodeCacheSize, 160*K);
|
define_pd_global(uintx, InitialCodeCacheSize, 160*K);
|
||||||
#endif // !TIERED
|
#endif // !TIERED
|
||||||
|
|
||||||
define_pd_global(bool, UseTypeProfile, false);
|
define_pd_global(bool, UseTypeProfile, false);
|
||||||
define_pd_global(bool, RoundFPResults, false);
|
define_pd_global(bool, RoundFPResults, false);
|
||||||
|
|
||||||
define_pd_global(bool, LIRFillDelaySlots, false);
|
define_pd_global(bool, LIRFillDelaySlots, false);
|
||||||
define_pd_global(bool, OptimizeSinglePrecision, false);
|
define_pd_global(bool, OptimizeSinglePrecision, false);
|
||||||
define_pd_global(bool, CSEArrayLength, true );
|
define_pd_global(bool, CSEArrayLength, true);
|
||||||
define_pd_global(bool, TwoOperandLIRForm, false);
|
define_pd_global(bool, TwoOperandLIRForm, false);
|
||||||
|
|
||||||
#endif // CPU_PPC_VM_C1_GLOBALS_PPC_HPP
|
#endif // CPU_PPC_VM_C1_GLOBALS_PPC_HPP
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -39,7 +39,7 @@ define_pd_global(bool, PreferInterpreterNativeStubs, false);
|
||||||
define_pd_global(bool, ProfileTraps, true);
|
define_pd_global(bool, ProfileTraps, true);
|
||||||
define_pd_global(bool, UseOnStackReplacement, true);
|
define_pd_global(bool, UseOnStackReplacement, true);
|
||||||
define_pd_global(bool, ProfileInterpreter, true);
|
define_pd_global(bool, ProfileInterpreter, true);
|
||||||
define_pd_global(bool, TieredCompilation, true);
|
define_pd_global(bool, TieredCompilation, trueInTiered);
|
||||||
define_pd_global(intx, CompileThreshold, 10000);
|
define_pd_global(intx, CompileThreshold, 10000);
|
||||||
|
|
||||||
define_pd_global(intx, OnStackReplacePercentage, 140);
|
define_pd_global(intx, OnStackReplacePercentage, 140);
|
||||||
|
@ -78,27 +78,27 @@ define_pd_global(bool, SuperWordLoopUnrollAnalysis, false);
|
||||||
// x.f = 0
|
// x.f = 0
|
||||||
// loc = x.f
|
// loc = x.f
|
||||||
// NullCheck loc
|
// NullCheck loc
|
||||||
define_pd_global(bool, OptoScheduling, false);
|
define_pd_global(bool, OptoScheduling, false);
|
||||||
define_pd_global(bool, IdealizeClearArrayNode, true);
|
define_pd_global(bool, IdealizeClearArrayNode, true);
|
||||||
|
|
||||||
define_pd_global(intx, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize
|
define_pd_global(uintx, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize
|
||||||
define_pd_global(intx, ReservedCodeCacheSize, 256*M);
|
define_pd_global(uintx, ReservedCodeCacheSize, 256*M);
|
||||||
define_pd_global(intx, NonProfiledCodeHeapSize, 125*M);
|
define_pd_global(uintx, NonProfiledCodeHeapSize, 125*M);
|
||||||
define_pd_global(intx, ProfiledCodeHeapSize, 126*M);
|
define_pd_global(uintx, ProfiledCodeHeapSize, 126*M);
|
||||||
define_pd_global(intx, NonNMethodCodeHeapSize, 5*M );
|
define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M );
|
||||||
define_pd_global(intx, CodeCacheExpansionSize, 64*K);
|
define_pd_global(uintx, CodeCacheExpansionSize, 64*K);
|
||||||
|
|
||||||
// Ergonomics related flags
|
// Ergonomics related flags
|
||||||
define_pd_global(uint64_t, MaxRAM, 4ULL*G);
|
define_pd_global(uint64_t, MaxRAM, 128ULL*G);
|
||||||
define_pd_global(uintx, CodeCacheMinBlockLength, 4);
|
define_pd_global(uintx, CodeCacheMinBlockLength, 4);
|
||||||
define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K);
|
define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K);
|
||||||
|
|
||||||
define_pd_global(bool, TrapBasedRangeChecks, true);
|
define_pd_global(bool, TrapBasedRangeChecks, true);
|
||||||
|
|
||||||
// Heap related flags
|
// Heap related flags
|
||||||
define_pd_global(size_t, MetaspaceSize, ScaleForWordSize(16*M));
|
define_pd_global(size_t, MetaspaceSize, ScaleForWordSize(16*M));
|
||||||
|
|
||||||
// Ergonomics related flags
|
// Ergonomics related flags
|
||||||
define_pd_global(bool, NeverActAsServerClassMachine, false);
|
define_pd_global(bool, NeverActAsServerClassMachine, false);
|
||||||
|
|
||||||
#endif // CPU_PPC_VM_C2_GLOBALS_PPC_HPP
|
#endif // CPU_PPC_VM_C2_GLOBALS_PPC_HPP
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -29,11 +29,11 @@
|
||||||
#include "runtime/globals.hpp"
|
#include "runtime/globals.hpp"
|
||||||
#include "utilities/debug.hpp"
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
// processor dependent initialization for ppc
|
// Processor dependent initialization of C2 compiler for ppc.
|
||||||
|
|
||||||
void Compile::pd_compiler2_init() {
|
void Compile::pd_compiler2_init() {
|
||||||
|
|
||||||
// Power7 and later
|
// Power7 and later.
|
||||||
if (PowerArchitecturePPC64 > 6) {
|
if (PowerArchitecturePPC64 > 6) {
|
||||||
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
|
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
|
||||||
FLAG_SET_ERGO(bool, UsePopCountInstruction, true);
|
FLAG_SET_ERGO(bool, UsePopCountInstruction, true);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -86,14 +86,14 @@ define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong);
|
||||||
define_pd_global(bool, ThreadLocalHandshakes, true);
|
define_pd_global(bool, ThreadLocalHandshakes, true);
|
||||||
|
|
||||||
// Platform dependent flag handling: flags only defined on this platform.
|
// Platform dependent flag handling: flags only defined on this platform.
|
||||||
#define ARCH_FLAGS(develop, \
|
#define ARCH_FLAGS(develop, \
|
||||||
product, \
|
product, \
|
||||||
diagnostic, \
|
diagnostic, \
|
||||||
experimental, \
|
experimental, \
|
||||||
notproduct, \
|
notproduct, \
|
||||||
range, \
|
range, \
|
||||||
constraint, \
|
constraint, \
|
||||||
writeable) \
|
writeable) \
|
||||||
\
|
\
|
||||||
product(uintx, PowerArchitecturePPC64, 0, \
|
product(uintx, PowerArchitecturePPC64, 0, \
|
||||||
"CPU Version: x for PowerX. Currently recognizes Power5 to " \
|
"CPU Version: x for PowerX. Currently recognizes Power5 to " \
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -24,7 +24,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "assembler_ppc.inline.hpp"
|
|
||||||
#include "runtime/icache.hpp"
|
#include "runtime/icache.hpp"
|
||||||
|
|
||||||
// Use inline assembler to implement icache flush.
|
// Use inline assembler to implement icache flush.
|
||||||
|
@ -32,7 +31,7 @@ int ICache::ppc64_flush_icache(address start, int lines, int magic) {
|
||||||
address end = start + (unsigned int)lines*ICache::line_size;
|
address end = start + (unsigned int)lines*ICache::line_size;
|
||||||
assert(start <= end, "flush_icache parms");
|
assert(start <= end, "flush_icache parms");
|
||||||
|
|
||||||
// store modified cache lines from data cache
|
// Store modified cache lines from data cache.
|
||||||
for (address a = start; a < end; a += ICache::line_size) {
|
for (address a = start; a < end; a += ICache::line_size) {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
"dcbst 0, %0 \n"
|
"dcbst 0, %0 \n"
|
||||||
|
@ -48,7 +47,7 @@ int ICache::ppc64_flush_icache(address start, int lines, int magic) {
|
||||||
:
|
:
|
||||||
: "memory");
|
: "memory");
|
||||||
|
|
||||||
// invalidate respective cache lines in instruction cache
|
// Invalidate respective cache lines in instruction cache.
|
||||||
for (address a = start; a < end; a += ICache::line_size) {
|
for (address a = start; a < end; a += ICache::line_size) {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
"icbi 0, %0 \n"
|
"icbi 0, %0 \n"
|
||||||
|
@ -57,7 +56,7 @@ int ICache::ppc64_flush_icache(address start, int lines, int magic) {
|
||||||
: "memory");
|
: "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
// discard fetched instructions
|
// Discard fetched instructions.
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
"isync \n"
|
"isync \n"
|
||||||
:
|
:
|
||||||
|
@ -71,6 +70,8 @@ void ICacheStubGenerator::generate_icache_flush(ICache::flush_icache_stub_t* flu
|
||||||
|
|
||||||
*flush_icache_stub = (ICache::flush_icache_stub_t)ICache::ppc64_flush_icache;
|
*flush_icache_stub = (ICache::flush_icache_stub_t)ICache::ppc64_flush_icache;
|
||||||
|
|
||||||
// First call to flush itself
|
// First call to flush itself.
|
||||||
|
// Pointless since we call C, but it is expected to get
|
||||||
|
// executed during VM_Version::determine_features().
|
||||||
ICache::invalidate_range((address)(*flush_icache_stub), 0);
|
ICache::invalidate_range((address)(*flush_icache_stub), 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -32,6 +32,10 @@
|
||||||
#include "runtime/safepointMechanism.hpp"
|
#include "runtime/safepointMechanism.hpp"
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
|
|
||||||
|
// Implementation of InterpreterMacroAssembler.
|
||||||
|
|
||||||
|
// This file specializes the assembler with interpreter-specific macros.
|
||||||
|
|
||||||
#ifdef PRODUCT
|
#ifdef PRODUCT
|
||||||
#define BLOCK_COMMENT(str) // nothing
|
#define BLOCK_COMMENT(str) // nothing
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2013 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "assembler_ppc.inline.hpp"
|
#include "asm/assembler.inline.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "prims/jniFastGetField.hpp"
|
#include "prims/jniFastGetField.hpp"
|
||||||
#include "prims/jvm_misc.hpp"
|
#include "prims/jvm_misc.hpp"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2017, SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2017, SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
|
@ -1788,11 +1788,10 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
RegisterOrConstant itable_index,
|
RegisterOrConstant itable_index,
|
||||||
Register method_result,
|
Register method_result,
|
||||||
Register scan_temp,
|
Register scan_temp,
|
||||||
Register sethi_temp,
|
Register temp2,
|
||||||
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_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).
|
// Compute start of first itableOffsetEntry (which is at the end of the vtable).
|
||||||
int vtable_base = in_bytes(Klass::vtable_start_offset());
|
int vtable_base = in_bytes(Klass::vtable_start_offset());
|
||||||
|
@ -1810,15 +1809,17 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
add(scan_temp, recv_klass, scan_temp);
|
add(scan_temp, recv_klass, scan_temp);
|
||||||
|
|
||||||
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
|
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
|
||||||
if (itable_index.is_register()) {
|
if (return_method) {
|
||||||
Register itable_offset = itable_index.as_register();
|
if (itable_index.is_register()) {
|
||||||
sldi(itable_offset, itable_offset, logMEsize);
|
Register itable_offset = itable_index.as_register();
|
||||||
if (itentry_off) addi(itable_offset, itable_offset, itentry_off);
|
sldi(method_result, itable_offset, logMEsize);
|
||||||
add(recv_klass, itable_offset, recv_klass);
|
if (itentry_off) { addi(method_result, method_result, itentry_off); }
|
||||||
} else {
|
add(method_result, method_result, recv_klass);
|
||||||
long itable_offset = (long)itable_index.as_constant();
|
} else {
|
||||||
load_const_optimized(sethi_temp, (itable_offset<<logMEsize)+itentry_off); // static address, no relocation
|
long itable_offset = (long)itable_index.as_constant();
|
||||||
add(recv_klass, sethi_temp, recv_klass);
|
// 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) {
|
// for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
|
||||||
|
@ -1831,12 +1832,12 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
for (int peel = 1; peel >= 0; peel--) {
|
for (int peel = 1; peel >= 0; peel--) {
|
||||||
// %%%% Could load both offset and interface in one ldx, if they were
|
// %%%% Could load both offset and interface in one ldx, if they were
|
||||||
// in the opposite order. This would save a load.
|
// 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
|
// Check that this entry is non-null. A null entry means that
|
||||||
// the receiver class doesn't implement the interface, and wasn't the
|
// the receiver class doesn't implement the interface, and wasn't the
|
||||||
// same as when the caller was compiled.
|
// same as when the caller was compiled.
|
||||||
cmpd(CCR0, method_result, intf_klass);
|
cmpd(CCR0, temp2, intf_klass);
|
||||||
|
|
||||||
if (peel) {
|
if (peel) {
|
||||||
beq(CCR0, found_method);
|
beq(CCR0, found_method);
|
||||||
|
@ -1849,7 +1850,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
|
|
||||||
bind(search);
|
bind(search);
|
||||||
|
|
||||||
cmpdi(CCR0, method_result, 0);
|
cmpdi(CCR0, temp2, 0);
|
||||||
beq(CCR0, L_no_such_interface);
|
beq(CCR0, L_no_such_interface);
|
||||||
addi(scan_temp, scan_temp, scan_step);
|
addi(scan_temp, scan_temp, scan_step);
|
||||||
}
|
}
|
||||||
|
@ -1857,9 +1858,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
bind(found_method);
|
bind(found_method);
|
||||||
|
|
||||||
// Got a hit.
|
// Got a hit.
|
||||||
int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
|
if (return_method) {
|
||||||
lwz(scan_temp, ito_offset, scan_temp);
|
int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
|
||||||
ldx(method_result, scan_temp, recv_klass);
|
lwz(scan_temp, ito_offset, scan_temp);
|
||||||
|
ldx(method_result, scan_temp, method_result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual method calling
|
// virtual method calling
|
||||||
|
@ -2880,10 +2883,6 @@ void MacroAssembler::compiler_fast_lock_object(ConditionRegister flag, Register
|
||||||
//assert(ObjectMonitor::recursions_size_in_bytes() == 8, "unexpected size");
|
//assert(ObjectMonitor::recursions_size_in_bytes() == 8, "unexpected size");
|
||||||
asm_assert_mem8_is_zero(ObjectMonitor::recursions_offset_in_bytes(), temp,
|
asm_assert_mem8_is_zero(ObjectMonitor::recursions_offset_in_bytes(), temp,
|
||||||
"monitor->_recursions should be 0", -1);
|
"monitor->_recursions should be 0", -1);
|
||||||
// Invariant 2: OwnerIsThread shouldn't be 0.
|
|
||||||
//assert(ObjectMonitor::OwnerIsThread_size_in_bytes() == 4, "unexpected size");
|
|
||||||
//asm_assert_mem4_isnot_zero(ObjectMonitor::OwnerIsThread_offset_in_bytes(), temp,
|
|
||||||
// "monitor->OwnerIsThread shouldn't be 0", -1);
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#if INCLUDE_RTM_OPT
|
#if INCLUDE_RTM_OPT
|
||||||
|
|
|
@ -519,7 +519,8 @@ class MacroAssembler: public Assembler {
|
||||||
RegisterOrConstant itable_index,
|
RegisterOrConstant itable_index,
|
||||||
Register method_result,
|
Register method_result,
|
||||||
Register temp_reg, Register temp2_reg,
|
Register temp_reg, Register temp2_reg,
|
||||||
Label& no_such_interface);
|
Label& no_such_interface,
|
||||||
|
bool return_method = true);
|
||||||
|
|
||||||
// virtual method calling
|
// virtual method calling
|
||||||
void lookup_virtual_method(Register recv_klass,
|
void lookup_virtual_method(Register recv_klass,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,7 +26,6 @@
|
||||||
#ifndef CPU_PPC_VM_NATIVEINST_PPC_HPP
|
#ifndef CPU_PPC_VM_NATIVEINST_PPC_HPP
|
||||||
#define CPU_PPC_VM_NATIVEINST_PPC_HPP
|
#define CPU_PPC_VM_NATIVEINST_PPC_HPP
|
||||||
|
|
||||||
#include "asm/assembler.hpp"
|
|
||||||
#include "asm/macroAssembler.hpp"
|
#include "asm/macroAssembler.hpp"
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
#include "runtime/icache.hpp"
|
#include "runtime/icache.hpp"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
#include "asm/assembler.inline.hpp"
|
|
||||||
#include "asm/macroAssembler.inline.hpp"
|
#include "asm/macroAssembler.inline.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/vmreg.hpp"
|
#include "code/vmreg.hpp"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -1188,7 +1188,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||||
// Argument is valid and klass is as expected, continue.
|
// Argument is valid and klass is as expected, continue.
|
||||||
|
|
||||||
// Extract method from inline cache, verified entry point needs it.
|
// 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");
|
assert(R19_method == ic, "the inline cache register is dead here");
|
||||||
|
|
||||||
__ ld(code, method_(code));
|
__ ld(code, method_(code));
|
||||||
|
@ -1912,8 +1912,8 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||||
// - *_slot_offset Indicates offset from SP in number of stack slots.
|
// - *_slot_offset Indicates offset from SP in number of stack slots.
|
||||||
// - *_offset Indicates offset from SP in bytes.
|
// - *_offset Indicates offset from SP in bytes.
|
||||||
|
|
||||||
int stack_slots = c_calling_convention(out_sig_bt, out_regs, out_regs2, total_c_args) // 1+2)
|
int stack_slots = c_calling_convention(out_sig_bt, out_regs, out_regs2, total_c_args) + // 1+2)
|
||||||
+ SharedRuntime::out_preserve_stack_slots(); // See c_calling_convention.
|
SharedRuntime::out_preserve_stack_slots(); // See c_calling_convention.
|
||||||
|
|
||||||
// Now the space for the inbound oop handle area.
|
// Now the space for the inbound oop handle area.
|
||||||
int total_save_slots = num_java_iarg_registers * VMRegImpl::slots_per_word;
|
int total_save_slots = num_java_iarg_registers * VMRegImpl::slots_per_word;
|
||||||
|
@ -2044,7 +2044,8 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||||
OopMap *oop_map = new OopMap(stack_slots * 2, 0 /* arg_slots*/);
|
OopMap *oop_map = new OopMap(stack_slots * 2, 0 /* arg_slots*/);
|
||||||
|
|
||||||
if (is_critical_native) {
|
if (is_critical_native) {
|
||||||
check_needs_gc_for_critical_native(masm, stack_slots, total_in_args, oop_handle_slot_offset, oop_maps, in_regs, in_sig_bt, r_temp_1);
|
check_needs_gc_for_critical_native(masm, stack_slots, total_in_args, oop_handle_slot_offset,
|
||||||
|
oop_maps, in_regs, in_sig_bt, r_temp_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move arguments from register/stack to register/stack.
|
// Move arguments from register/stack to register/stack.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2017, SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2017, SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
|
@ -40,6 +40,10 @@
|
||||||
#include "runtime/thread.inline.hpp"
|
#include "runtime/thread.inline.hpp"
|
||||||
#include "utilities/align.hpp"
|
#include "utilities/align.hpp"
|
||||||
|
|
||||||
|
// Declaration and definition of StubGenerator (no .hpp file).
|
||||||
|
// For a more detailed description of the stub routine structure
|
||||||
|
// see the comment in stubRoutines.hpp.
|
||||||
|
|
||||||
#define __ _masm->
|
#define __ _masm->
|
||||||
|
|
||||||
#ifdef PRODUCT
|
#ifdef PRODUCT
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2017, SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2017, SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
#include "asm/macroAssembler.inline.hpp"
|
#include "asm/macroAssembler.inline.hpp"
|
||||||
#include "runtime/stubRoutines.hpp"
|
#include "runtime/stubRoutines.hpp"
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2015, 2017, SAP SE. All rights reserved.
|
* Copyright (c) 2015, 2017, SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
|
@ -582,25 +582,6 @@ address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(con
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
// Call special ClassCastException constructor taking object to cast
|
|
||||||
// and target class as arguments.
|
|
||||||
address TemplateInterpreterGenerator::generate_ClassCastException_verbose_handler() {
|
|
||||||
address entry = __ pc();
|
|
||||||
|
|
||||||
// Expression stack must be empty before entering the VM if an
|
|
||||||
// exception happened.
|
|
||||||
__ empty_expression_stack();
|
|
||||||
|
|
||||||
// Thread will be loaded to R3_ARG1.
|
|
||||||
// Target class oop is in register R5_ARG3 by convention!
|
|
||||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_ClassCastException_verbose), R17_tos, R5_ARG3);
|
|
||||||
// Above call must not return here since exception pending.
|
|
||||||
DEBUG_ONLY(__ should_not_reach_here();)
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
|
address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
|
||||||
address entry = __ pc();
|
address entry = __ pc();
|
||||||
// Expression stack must be empty before entering the VM if an
|
// Expression stack must be empty before entering the VM if an
|
||||||
|
@ -1896,7 +1877,6 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method entry for static native methods:
|
* Method entry for static native methods:
|
||||||
* int java.util.zip.CRC32.updateBytes( int crc, byte[] b, int off, int len)
|
* int java.util.zip.CRC32.updateBytes( int crc, byte[] b, int off, int len)
|
||||||
|
|
|
@ -3486,11 +3486,11 @@ void TemplateTable::invokestatic(int byte_no) {
|
||||||
void TemplateTable::invokeinterface_object_method(Register Rrecv_klass,
|
void TemplateTable::invokeinterface_object_method(Register Rrecv_klass,
|
||||||
Register Rret,
|
Register Rret,
|
||||||
Register Rflags,
|
Register Rflags,
|
||||||
Register Rindex,
|
Register Rmethod,
|
||||||
Register Rtemp1,
|
Register Rtemp1,
|
||||||
Register Rtemp2) {
|
Register Rtemp2) {
|
||||||
|
|
||||||
assert_different_registers(Rindex, Rret, Rrecv_klass, Rflags, Rtemp1, Rtemp2);
|
assert_different_registers(Rmethod, Rret, Rrecv_klass, Rflags, Rtemp1, Rtemp2);
|
||||||
Label LnotFinal;
|
Label LnotFinal;
|
||||||
|
|
||||||
// Check for vfinal.
|
// Check for vfinal.
|
||||||
|
@ -3502,14 +3502,14 @@ void TemplateTable::invokeinterface_object_method(Register Rrecv_klass,
|
||||||
// Final call case.
|
// Final call case.
|
||||||
__ profile_final_call(Rtemp1, Rscratch);
|
__ profile_final_call(Rtemp1, Rscratch);
|
||||||
// Argument and return type profiling.
|
// 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.
|
// 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.
|
// Non-final callc case.
|
||||||
__ bind(LnotFinal);
|
__ bind(LnotFinal);
|
||||||
__ profile_virtual_call(Rrecv_klass, Rtemp1, Rscratch, false);
|
__ 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) {
|
void TemplateTable::invokeinterface(int byte_no) {
|
||||||
|
@ -3518,58 +3518,61 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
|
|
||||||
const Register Rscratch1 = R11_scratch1,
|
const Register Rscratch1 = R11_scratch1,
|
||||||
Rscratch2 = R12_scratch2,
|
Rscratch2 = R12_scratch2,
|
||||||
Rscratch3 = R9_ARG7,
|
Rmethod = R6_ARG4,
|
||||||
Rscratch4 = R10_ARG8,
|
Rmethod2 = R9_ARG7,
|
||||||
Rtable_addr = Rscratch2,
|
|
||||||
Rinterface_klass = R5_ARG3,
|
Rinterface_klass = R5_ARG3,
|
||||||
Rret_type = R8_ARG6,
|
Rret_addr = R8_ARG6,
|
||||||
Rret_addr = Rret_type,
|
Rindex = R10_ARG8,
|
||||||
Rindex = R6_ARG4,
|
Rreceiver = R3_ARG1,
|
||||||
Rreceiver = R4_ARG2,
|
Rrecv_klass = R4_ARG2,
|
||||||
Rrecv_klass = Rreceiver,
|
|
||||||
Rflags = R7_ARG5;
|
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.
|
// 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);
|
__ load_klass(Rrecv_klass, Rreceiver);
|
||||||
|
|
||||||
// Check corner case object method.
|
// Check corner case object method.
|
||||||
Label LobjectMethod;
|
Label LobjectMethod, L_no_such_interface, Lthrow_ame;
|
||||||
|
|
||||||
__ testbitdi(CCR0, R0, Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift);
|
__ testbitdi(CCR0, R0, Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift);
|
||||||
__ btrue(CCR0, LobjectMethod);
|
__ 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);
|
__ profile_virtual_call(Rrecv_klass, Rscratch1, Rscratch2, false);
|
||||||
|
|
||||||
// Find entry point to call.
|
// 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);
|
__ beq(CCR0, Lthrow_ame);
|
||||||
// Found entry. Jump off!
|
// Found entry. Jump off!
|
||||||
// Argument and return type profiling.
|
// Argument and return type profiling.
|
||||||
__ profile_arguments_type(Rindex, Rscratch1, Rscratch2, true);
|
__ profile_arguments_type(Rmethod2, Rscratch1, Rscratch2, true);
|
||||||
__ call_from_interpreter(Rindex, Rret_addr, Rscratch1, Rscratch2);
|
//__ profile_called_method(Rindex, Rscratch1);
|
||||||
|
__ call_from_interpreter(Rmethod2, Rret_addr, Rscratch1, Rscratch2);
|
||||||
|
|
||||||
// Vtable entry was NULL => Throw abstract method error.
|
// Vtable entry was NULL => Throw abstract method error.
|
||||||
__ bind(Lthrow_ame);
|
__ bind(Lthrow_ame);
|
||||||
__ mr(Rrecv_klass, Rscratch4);
|
|
||||||
__ mr(Rindex, Rscratch3);
|
|
||||||
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
|
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
|
||||||
|
|
||||||
// Interface was not found => Throw incompatible class change error.
|
// Interface was not found => Throw incompatible class change error.
|
||||||
__ bind(Lthrow_icc);
|
__ bind(L_no_such_interface);
|
||||||
__ mr(Rrecv_klass, Rscratch4);
|
|
||||||
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
|
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||||
|
DEBUG_ONLY( __ should_not_reach_here(); )
|
||||||
__ should_not_reach_here();
|
|
||||||
|
|
||||||
// Special case of invokeinterface called for virtual method of
|
// Special case of invokeinterface called for virtual method of
|
||||||
// java.lang.Object. See ConstantPoolCacheEntry::set_method() for details:
|
// java.lang.Object. See ConstantPoolCacheEntry::set_method() for details:
|
||||||
|
@ -3577,7 +3580,7 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
// to handle this corner case. This code isn't produced by javac, but could
|
// to handle this corner case. This code isn't produced by javac, but could
|
||||||
// be produced by another compliant java compiler.
|
// be produced by another compliant java compiler.
|
||||||
__ bind(LobjectMethod);
|
__ 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) {
|
void TemplateTable::invokedynamic(int byte_no) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "interp_masm_ppc.hpp"
|
#include "interp_masm_ppc.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/klassVtable.hpp"
|
#include "oops/klassVtable.hpp"
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
|
@ -55,17 +56,22 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||||
// PPC port: use fixed size.
|
// PPC port: use fixed size.
|
||||||
const int code_length = VtableStub::pd_code_size_limit(true);
|
const int code_length = VtableStub::pd_code_size_limit(true);
|
||||||
VtableStub* s = new (code_length) VtableStub(true, vtable_index);
|
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;
|
ResourceMark rm;
|
||||||
CodeBuffer cb(s->entry_point(), code_length);
|
CodeBuffer cb(s->entry_point(), code_length);
|
||||||
MacroAssembler* masm = new MacroAssembler(&cb);
|
MacroAssembler* masm = new MacroAssembler(&cb);
|
||||||
address start_pc;
|
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (CountCompiledCalls) {
|
if (CountCompiledCalls) {
|
||||||
__ load_const(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr());
|
int offs = __ load_const_optimized(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr(), R12_scratch2, true);
|
||||||
__ lwz(R12_scratch2, 0, R11_scratch1);
|
__ lwz(R12_scratch2, offs, R11_scratch1);
|
||||||
__ addi(R12_scratch2, R12_scratch2, 1);
|
__ addi(R12_scratch2, R12_scratch2, 1);
|
||||||
__ stw(R12_scratch2, 0, R11_scratch1);
|
__ stw(R12_scratch2, offs, R11_scratch1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -116,6 +122,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||||
__ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method);
|
__ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method);
|
||||||
__ mtctr(R12_scratch2);
|
__ mtctr(R12_scratch2);
|
||||||
__ bctr();
|
__ bctr();
|
||||||
|
|
||||||
masm->flush();
|
masm->flush();
|
||||||
|
|
||||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||||
|
@ -125,10 +132,16 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||||
// PPC port: use fixed size.
|
// PPC port: use fixed size.
|
||||||
const int code_length = VtableStub::pd_code_size_limit(false);
|
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;
|
ResourceMark rm;
|
||||||
CodeBuffer cb(s->entry_point(), code_length);
|
CodeBuffer cb(s->entry_point(), code_length);
|
||||||
MacroAssembler* masm = new MacroAssembler(&cb);
|
MacroAssembler* masm = new MacroAssembler(&cb);
|
||||||
|
@ -136,10 +149,10 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (CountCompiledCalls) {
|
if (CountCompiledCalls) {
|
||||||
__ load_const(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr());
|
int offs = __ load_const_optimized(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr(), R12_scratch2, true);
|
||||||
__ lwz(R12_scratch2, 0, R11_scratch1);
|
__ lwz(R12_scratch2, offs, R11_scratch1);
|
||||||
__ addi(R12_scratch2, R12_scratch2, 1);
|
__ addi(R12_scratch2, R12_scratch2, 1);
|
||||||
__ stw(R12_scratch2, 0, R11_scratch1);
|
__ stw(R12_scratch2, offs, R11_scratch1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -148,62 +161,28 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||||
// Entry arguments:
|
// Entry arguments:
|
||||||
// R19_method: Interface
|
// R19_method: Interface
|
||||||
// R3_ARG1: Receiver
|
// R3_ARG1: Receiver
|
||||||
//
|
|
||||||
|
|
||||||
const Register rcvr_klass = R11_scratch1;
|
Label L_no_such_interface;
|
||||||
const Register vtable_len = R12_scratch2;
|
const Register rcvr_klass = R11_scratch1,
|
||||||
const Register itable_entry_addr = R21_tmp1;
|
interface = R12_scratch2,
|
||||||
const Register itable_interface = R22_tmp2;
|
tmp1 = R21_tmp1,
|
||||||
|
tmp2 = R22_tmp2;
|
||||||
|
|
||||||
// Get receiver klass.
|
|
||||||
|
|
||||||
// We might implicit NULL fault here.
|
|
||||||
address npe_addr = __ pc(); // npe = null pointer exception
|
address npe_addr = __ pc(); // npe = null pointer exception
|
||||||
__ null_check(R3_ARG1, oopDesc::klass_offset_in_bytes(), /*implicit only*/NULL);
|
__ null_check(R3_ARG1, oopDesc::klass_offset_in_bytes(), /*implicit only*/NULL);
|
||||||
__ load_klass(rcvr_klass, R3_ARG1);
|
__ load_klass(rcvr_klass, R3_ARG1);
|
||||||
|
|
||||||
BLOCK_COMMENT("Load start of itable entries into itable_entry.");
|
// Receiver subtype check against REFC.
|
||||||
__ lwz(vtable_len, in_bytes(Klass::vtable_length_offset()), rcvr_klass);
|
__ ld(interface, CompiledICHolder::holder_klass_offset(), R19_method);
|
||||||
__ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes()));
|
__ lookup_interface_method(rcvr_klass, interface, noreg,
|
||||||
__ add(itable_entry_addr, vtable_len, rcvr_klass);
|
R0, tmp1, tmp2,
|
||||||
|
L_no_such_interface, /*return_method=*/ false);
|
||||||
|
|
||||||
// Loop over all itable entries until desired interfaceOop(Rinterface) found.
|
// Get Method* and entrypoint for compiler
|
||||||
BLOCK_COMMENT("Increment itable_entry_addr in loop.");
|
__ ld(interface, CompiledICHolder::holder_metadata_offset(), R19_method);
|
||||||
const int vtable_base_offset = in_bytes(Klass::vtable_start_offset());
|
__ lookup_interface_method(rcvr_klass, interface, itable_index,
|
||||||
__ addi(itable_entry_addr, itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes());
|
R19_method, tmp1, tmp2,
|
||||||
|
L_no_such_interface, /*return_method=*/ true);
|
||||||
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);
|
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (DebugVtables) {
|
if (DebugVtables) {
|
||||||
|
@ -219,7 +198,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||||
address ame_addr = __ pc(); // ame = abstract method error
|
address ame_addr = __ pc(); // ame = abstract method error
|
||||||
|
|
||||||
// Must do an explicit check if implicit checks are disabled.
|
// 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);
|
__ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method);
|
||||||
__ mtctr(R12_scratch2);
|
__ mtctr(R12_scratch2);
|
||||||
__ bctr();
|
__ 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
|
// We force resolving of the call site by jumping to the "handle
|
||||||
// wrong method" stub, and so let the interpreter runtime do all the
|
// wrong method" stub, and so let the interpreter runtime do all the
|
||||||
// dirty work.
|
// dirty work.
|
||||||
__ bind(throw_icce);
|
__ bind(L_no_such_interface);
|
||||||
__ load_const(R11_scratch1, SharedRuntime::get_handle_wrong_method_stub());
|
__ load_const_optimized(R11_scratch1, SharedRuntime::get_handle_wrong_method_stub(), R12_scratch2);
|
||||||
__ mtctr(R11_scratch1);
|
__ mtctr(R11_scratch1);
|
||||||
__ bctr();
|
__ bctr();
|
||||||
|
|
||||||
|
@ -245,14 +224,15 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||||
int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
|
int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
|
||||||
if (DebugVtables || CountCompiledCalls || VerifyOops) {
|
if (DebugVtables || CountCompiledCalls || VerifyOops) {
|
||||||
return 1000;
|
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() {
|
int VtableStub::pd_code_alignment() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2016, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -42,11 +42,6 @@ class Bytes: AllStatic {
|
||||||
//
|
//
|
||||||
// In short, it makes no sense on z/Architecture to piecemeal get or put unaligned data.
|
// In short, it makes no sense on z/Architecture to piecemeal get or put unaligned data.
|
||||||
|
|
||||||
// Only swap on little endian machines => suffix `_le'.
|
|
||||||
static inline u2 swap_u2_le(u2 x) { return x; }
|
|
||||||
static inline u4 swap_u4_le(u4 x) { return x; }
|
|
||||||
static inline u8 swap_u8_le(u8 x) { return x; }
|
|
||||||
|
|
||||||
static inline u2 get_native_u2(address p) { return *(u2*)p; }
|
static inline u2 get_native_u2(address p) { return *(u2*)p; }
|
||||||
static inline u4 get_native_u4(address p) { return *(u4*)p; }
|
static inline u4 get_native_u4(address p) { return *(u4*)p; }
|
||||||
static inline u8 get_native_u8(address p) { return *(u8*)p; }
|
static inline u8 get_native_u8(address p) { return *(u8*)p; }
|
||||||
|
@ -55,7 +50,8 @@ class Bytes: AllStatic {
|
||||||
static inline void put_native_u4(address p, u4 x) { *(u4*)p = x; }
|
static inline void put_native_u4(address p, u4 x) { *(u4*)p = x; }
|
||||||
static inline void put_native_u8(address p, u8 x) { *(u8*)p = x; }
|
static inline void put_native_u8(address p, u8 x) { *(u8*)p = x; }
|
||||||
|
|
||||||
#include "bytes_linux_s390.inline.hpp"
|
// The following header contains the implementations of swap_u2, swap_u4, and swap_u8.
|
||||||
|
#include OS_CPU_HEADER_INLINE(bytes)
|
||||||
|
|
||||||
// Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering)
|
// Efficient reading and writing of unaligned unsigned data in Java byte ordering (i.e. big-endian ordering)
|
||||||
static inline u2 get_Java_u2(address p) { return get_native_u2(p); }
|
static inline u2 get_Java_u2(address p) { return get_native_u2(p); }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2016, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -48,7 +48,7 @@ define_pd_global(bool, UseTLAB, true);
|
||||||
define_pd_global(bool, ProfileInterpreter, false);
|
define_pd_global(bool, ProfileInterpreter, false);
|
||||||
define_pd_global(intx, FreqInlineSize, 325);
|
define_pd_global(intx, FreqInlineSize, 325);
|
||||||
define_pd_global(bool, ResizeTLAB, true);
|
define_pd_global(bool, ResizeTLAB, true);
|
||||||
define_pd_global(intx, ReservedCodeCacheSize, 32*M);
|
define_pd_global(uintx, ReservedCodeCacheSize, 32*M);
|
||||||
define_pd_global(uintx, NonProfiledCodeHeapSize, 13*M);
|
define_pd_global(uintx, NonProfiledCodeHeapSize, 13*M);
|
||||||
define_pd_global(uintx, ProfiledCodeHeapSize, 14*M);
|
define_pd_global(uintx, ProfiledCodeHeapSize, 14*M);
|
||||||
define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M);
|
define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2016, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -58,7 +58,7 @@ define_pd_global(intx, LoopUnrollLimit, 60);
|
||||||
define_pd_global(intx, LoopPercentProfileLimit, 10);
|
define_pd_global(intx, LoopPercentProfileLimit, 10);
|
||||||
define_pd_global(intx, MinJumpTableSize, 18);
|
define_pd_global(intx, MinJumpTableSize, 18);
|
||||||
|
|
||||||
// Peephole and CISC spilling both break the graph, and so makes the
|
// Peephole and CISC spilling both break the graph, and so make the
|
||||||
// scheduler sick.
|
// scheduler sick.
|
||||||
define_pd_global(bool, OptoPeephole, false);
|
define_pd_global(bool, OptoPeephole, false);
|
||||||
define_pd_global(bool, UseCISCSpill, true);
|
define_pd_global(bool, UseCISCSpill, true);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016, 2017 SAP SE. All rights reserved.
|
* Copyright (c) 2016, 2018 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -87,7 +87,14 @@ define_pd_global(intx, InitArrayShortSize, 1*BytesPerLong);
|
||||||
|
|
||||||
define_pd_global(bool, ThreadLocalHandshakes, true);
|
define_pd_global(bool, ThreadLocalHandshakes, true);
|
||||||
|
|
||||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint, writeable) \
|
#define ARCH_FLAGS(develop, \
|
||||||
|
product, \
|
||||||
|
diagnostic, \
|
||||||
|
experimental, \
|
||||||
|
notproduct, \
|
||||||
|
range, \
|
||||||
|
constraint, \
|
||||||
|
writeable) \
|
||||||
\
|
\
|
||||||
/* Reoptimize code-sequences of calls at runtime, e.g. replace an */ \
|
/* Reoptimize code-sequences of calls at runtime, e.g. replace an */ \
|
||||||
/* indirect call by a direct call. */ \
|
/* indirect call by a direct call. */ \
|
||||||
|
|
|
@ -2806,8 +2806,8 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
RegisterOrConstant itable_index,
|
RegisterOrConstant itable_index,
|
||||||
Register method_result,
|
Register method_result,
|
||||||
Register temp1_reg,
|
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 vtable_len = temp1_reg; // Used to compute itable_entry_addr.
|
||||||
const Register itable_entry_addr = Z_R1_scratch;
|
const Register itable_entry_addr = Z_R1_scratch;
|
||||||
|
@ -2842,38 +2842,36 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
z_brne(search);
|
z_brne(search);
|
||||||
|
|
||||||
// Entry found and itable_entry_addr points to it, get offset of vtable for interface.
|
// 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() -
|
// Compute itableMethodEntry and get method and entry point
|
||||||
itableOffsetEntry::interface_offset_in_bytes()) -
|
// we use addressing with index and displacement, since the formula
|
||||||
itable_offset_search_inc;
|
// 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
|
if (itable_index.is_register()) {
|
||||||
// we use addressing with index and displacement, since the formula
|
// Compute the method's offset in that register, for the formula, see the
|
||||||
// for computing the entry's offset has a fixed and a dynamic part,
|
// else-clause below.
|
||||||
// the latter depending on the matched interface entry and on the case,
|
z_sllg(itable_offset, itable_index.as_register(), exact_log2(itableMethodEntry::size() * wordSize));
|
||||||
// that the itable index has been passed as a register, not a constant value.
|
z_agf(itable_offset, vtable_offset_offset, itable_entry_addr);
|
||||||
int method_offset = itableMethodEntry::method_offset_in_bytes();
|
} else {
|
||||||
// Fixed part (displacement), common operand.
|
// Displacement increases.
|
||||||
Register itable_offset; // Dynamic part (index register).
|
method_offset += itableMethodEntry::size() * wordSize * itable_index.as_constant();
|
||||||
|
|
||||||
if (itable_index.is_register()) {
|
// Load index from itable.
|
||||||
// Compute the method's offset in that register, for the formula, see the
|
z_llgf(itable_offset, vtable_offset_offset, itable_entry_addr);
|
||||||
// else-clause below.
|
}
|
||||||
itable_offset = itable_index.as_register();
|
|
||||||
|
|
||||||
z_sllg(itable_offset, itable_offset, exact_log2(itableMethodEntry::size() * wordSize));
|
// Finally load the method's oop.
|
||||||
z_agf(itable_offset, vtable_offset_offset, itable_entry_addr);
|
z_lg(method_result, method_offset, itable_offset, recv_klass);
|
||||||
} 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);
|
|
||||||
BLOCK_COMMENT("} lookup_interface_method");
|
BLOCK_COMMENT("} lookup_interface_method");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -671,8 +671,8 @@ class MacroAssembler: public Assembler {
|
||||||
RegisterOrConstant itable_index,
|
RegisterOrConstant itable_index,
|
||||||
Register method_result,
|
Register method_result,
|
||||||
Register temp1_reg,
|
Register temp1_reg,
|
||||||
Register temp2_reg,
|
Label& no_such_interface,
|
||||||
Label& no_such_interface);
|
bool return_method = true);
|
||||||
|
|
||||||
// virtual method calling
|
// virtual method calling
|
||||||
void lookup_virtual_method(Register recv_klass,
|
void lookup_virtual_method(Register recv_klass,
|
||||||
|
|
|
@ -498,7 +498,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
|
||||||
Label L_no_such_interface;
|
Label L_no_such_interface;
|
||||||
__ lookup_interface_method(temp1_recv_klass, temp3_intf,
|
__ lookup_interface_method(temp1_recv_klass, temp3_intf,
|
||||||
// Note: next two args must be the same:
|
// Note: next two args must be the same:
|
||||||
Z_index, Z_method, temp2, noreg,
|
Z_index, Z_method, temp2,
|
||||||
L_no_such_interface);
|
L_no_such_interface);
|
||||||
jump_from_method_handle(_masm, Z_method, temp2, Z_R0, for_compiler_entry);
|
jump_from_method_handle(_masm, Z_method, temp2, Z_R0, for_compiler_entry);
|
||||||
|
|
||||||
|
|
|
@ -2660,9 +2660,9 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||||
Label skip_fixup;
|
Label skip_fixup;
|
||||||
{
|
{
|
||||||
Label ic_miss;
|
Label ic_miss;
|
||||||
const int klass_offset = oopDesc::klass_offset_in_bytes();
|
const int klass_offset = oopDesc::klass_offset_in_bytes();
|
||||||
const int holder_klass_offset = CompiledICHolder::holder_klass_offset();
|
const int holder_klass_offset = CompiledICHolder::holder_klass_offset();
|
||||||
const int holder_method_offset = CompiledICHolder::holder_method_offset();
|
const int holder_metadata_offset = CompiledICHolder::holder_metadata_offset();
|
||||||
|
|
||||||
// Out-of-line call to ic_miss handler.
|
// Out-of-line call to ic_miss handler.
|
||||||
__ call_ic_miss_handler(ic_miss, 0x11, 0, Z_R1_scratch);
|
__ call_ic_miss_handler(ic_miss, 0x11, 0, Z_R1_scratch);
|
||||||
|
@ -2691,7 +2691,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||||
// This def MUST MATCH code in gen_c2i_adapter!
|
// This def MUST MATCH code in gen_c2i_adapter!
|
||||||
const Register code = Z_R11;
|
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));
|
__ load_and_test_long(Z_R0, method_(code));
|
||||||
__ z_brne(ic_miss); // Cache miss: call runtime to handle this.
|
__ z_brne(ic_miss); // Cache miss: call runtime to handle this.
|
||||||
|
|
||||||
|
|
|
@ -3557,66 +3557,67 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
transition(vtos, vtos);
|
transition(vtos, vtos);
|
||||||
|
|
||||||
assert(byte_no == f1_byte, "use this argument");
|
assert(byte_no == f1_byte, "use this argument");
|
||||||
Register interface = Z_tos;
|
Register klass = Z_ARG2,
|
||||||
Register index = Z_ARG3;
|
method = Z_ARG3,
|
||||||
Register receiver = Z_tmp_1;
|
interface = Z_ARG4,
|
||||||
Register flags = Z_ARG5;
|
flags = Z_ARG5,
|
||||||
|
receiver = Z_tmp_1;
|
||||||
|
|
||||||
BLOCK_COMMENT("invokeinterface {");
|
BLOCK_COMMENT("invokeinterface {");
|
||||||
|
|
||||||
// Destroys Z_ARG1 and Z_ARG2, thus use Z_ARG4 and copy afterwards.
|
prepare_invoke(byte_no, interface, method, // Get f1 klassOop, f2 itable index.
|
||||||
prepare_invoke(byte_no, Z_ARG4, index, // Get f1 klassOop, f2 itable index.
|
|
||||||
receiver, flags);
|
receiver, flags);
|
||||||
|
|
||||||
// Z_R14 (== Z_bytecode) : return entry
|
// Z_R14 (== Z_bytecode) : return entry
|
||||||
|
|
||||||
__ z_lgr(interface, Z_ARG4);
|
|
||||||
|
|
||||||
// Special case of invokeinterface called for virtual method of
|
// Special case of invokeinterface called for virtual method of
|
||||||
// java.lang.Object. See cpCacheOop.cpp for details.
|
// java.lang.Object. See cpCacheOop.cpp for details.
|
||||||
// This code isn't produced by javac, but could be produced by
|
// This code isn't produced by javac, but could be produced by
|
||||||
// another compliant java compiler.
|
// another compliant java compiler.
|
||||||
Label notMethod;
|
NearLabel notMethod, no_such_interface, no_such_method;
|
||||||
__ testbit(flags, ConstantPoolCacheEntry::is_forced_virtual_shift);
|
__ testbit(flags, ConstantPoolCacheEntry::is_forced_virtual_shift);
|
||||||
__ z_brz(notMethod);
|
__ z_brz(notMethod);
|
||||||
invokevirtual_helper(index, receiver, flags);
|
invokevirtual_helper(method, receiver, flags);
|
||||||
__ bind(notMethod);
|
__ bind(notMethod);
|
||||||
|
|
||||||
// Get receiver klass into klass - also a null check.
|
// Get receiver klass into klass - also a null check.
|
||||||
Register klass = flags;
|
|
||||||
|
|
||||||
__ restore_locals();
|
__ restore_locals();
|
||||||
__ load_klass(klass, receiver);
|
__ load_klass(klass, receiver);
|
||||||
|
|
||||||
|
__ lookup_interface_method(klass, interface, noreg, noreg, /*temp*/Z_ARG1,
|
||||||
|
no_such_interface, /*return_method=*/false);
|
||||||
|
|
||||||
// Profile this call.
|
// 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;
|
// Find entry point to call.
|
||||||
Register method = Z_tmp_2;
|
|
||||||
|
|
||||||
// TK 2010-08-24: save the index to Z_ARG4. needed in case of an error
|
// Get declaring interface class from method
|
||||||
// in throw_AbstractMethodErrorByTemplateTable
|
__ z_lg(interface, Address(method, Method::const_offset()));
|
||||||
__ z_lgr(Z_ARG4, index);
|
__ z_lg(interface, Address(interface, ConstMethod::constants_offset()));
|
||||||
// TK 2011-03-24: copy also klass because it could be changed in
|
__ z_lg(interface, Address(interface, ConstantPool::pool_holder_offset_in_bytes()));
|
||||||
// lookup_interface_method
|
|
||||||
__ z_lgr(Z_ARG2, klass);
|
// Get itable index from method
|
||||||
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
Register index = receiver,
|
||||||
klass, interface, index,
|
method2 = flags;
|
||||||
// outputs: method, scan temp. reg
|
__ z_lgf(index, Address(method, Method::itable_index_offset()));
|
||||||
method, Z_tmp_2, Z_R1_scratch,
|
__ z_aghi(index, -Method::itable_index_max);
|
||||||
no_such_interface);
|
__ z_lcgr(index, index);
|
||||||
|
|
||||||
|
__ lookup_interface_method(klass, interface, index, method2, Z_tmp_2,
|
||||||
|
no_such_interface);
|
||||||
|
|
||||||
// Check for abstract method error.
|
// Check for abstract method error.
|
||||||
// Note: This should be done more efficiently via a throw_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
|
// interpreter entry point and a conditional jump to it in case of a null
|
||||||
// method.
|
// method.
|
||||||
__ compareU64_and_branch(method, (intptr_t) 0,
|
__ compareU64_and_branch(method2, (intptr_t) 0,
|
||||||
Assembler::bcondZero, no_such_method);
|
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.
|
// Do the call.
|
||||||
__ jump_from_interpreted(method, Z_ARG5);
|
__ jump_from_interpreted(method2, Z_tmp_2);
|
||||||
__ should_not_reach_here();
|
__ should_not_reach_here();
|
||||||
|
|
||||||
// exception handling code follows...
|
// exception handling code follows...
|
||||||
|
@ -3628,12 +3629,8 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
// Throw exception.
|
// Throw exception.
|
||||||
__ restore_bcp(); // Bcp must be correct for exception handler (was destroyed).
|
__ restore_bcp(); // Bcp must be correct for exception handler (was destroyed).
|
||||||
__ restore_locals(); // Make sure locals pointer is correct as well (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,
|
__ call_VM(noreg,
|
||||||
CAST_FROM_FN_PTR(address,
|
CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
|
||||||
InterpreterRuntime::throw_AbstractMethodError),
|
|
||||||
Z_ARG2, interface, Z_ARG4);
|
|
||||||
// The call_VM checks for exception, so we should never return here.
|
// The call_VM checks for exception, so we should never return here.
|
||||||
__ should_not_reach_here();
|
__ should_not_reach_here();
|
||||||
|
|
||||||
|
@ -3642,12 +3639,8 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
// Throw exception.
|
// Throw exception.
|
||||||
__ restore_bcp(); // Bcp must be correct for exception handler (was destroyed).
|
__ restore_bcp(); // Bcp must be correct for exception handler (was destroyed).
|
||||||
__ restore_locals(); // Make sure locals pointer is correct as well (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,
|
__ call_VM(noreg,
|
||||||
CAST_FROM_FN_PTR(address,
|
CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||||
InterpreterRuntime::throw_IncompatibleClassChangeError),
|
|
||||||
Z_ARG2, interface);
|
|
||||||
// The call_VM checks for exception, so we should never return here.
|
// The call_VM checks for exception, so we should never return here.
|
||||||
__ should_not_reach_here();
|
__ should_not_reach_here();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016 SAP SE. All rights reserved.
|
* Copyright (c) 2016, 2017 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "interp_masm_s390.hpp"
|
#include "interp_masm_s390.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/klassVtable.hpp"
|
#include "oops/klassVtable.hpp"
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
|
@ -57,7 +58,6 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
CodeBuffer cb(s->entry_point(), code_length);
|
CodeBuffer cb(s->entry_point(), code_length);
|
||||||
MacroAssembler *masm = new MacroAssembler(&cb);
|
MacroAssembler *masm = new MacroAssembler(&cb);
|
||||||
address start_pc;
|
|
||||||
int padding_bytes = 0;
|
int padding_bytes = 0;
|
||||||
|
|
||||||
#if (!defined(PRODUCT) && defined(COMPILER2))
|
#if (!defined(PRODUCT) && defined(COMPILER2))
|
||||||
|
@ -144,9 +144,9 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||||
return s;
|
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);
|
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.
|
if (s == NULL) { // Indicates OOM in the code cache.
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,6 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
CodeBuffer cb(s->entry_point(), code_length);
|
CodeBuffer cb(s->entry_point(), code_length);
|
||||||
MacroAssembler *masm = new MacroAssembler(&cb);
|
MacroAssembler *masm = new MacroAssembler(&cb);
|
||||||
address start_pc;
|
|
||||||
int padding_bytes = 0;
|
int padding_bytes = 0;
|
||||||
|
|
||||||
#if (!defined(PRODUCT) && defined(COMPILER2))
|
#if (!defined(PRODUCT) && defined(COMPILER2))
|
||||||
|
@ -174,11 +173,9 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||||
// Entry arguments:
|
// Entry arguments:
|
||||||
// Z_method: Interface
|
// Z_method: Interface
|
||||||
// Z_ARG1: Receiver
|
// Z_ARG1: Receiver
|
||||||
const Register rcvr_klass = Z_tmp_1; // Used to compute itable_entry_addr.
|
NearLabel no_such_interface;
|
||||||
// Use extra reg to avoid re-load.
|
const Register rcvr_klass = Z_tmp_1,
|
||||||
const Register vtable_len = Z_tmp_2; // Used to compute itable_entry_addr.
|
interface = Z_tmp_2;
|
||||||
const Register itable_entry_addr = Z_R1_scratch;
|
|
||||||
const Register itable_interface = Z_R0_scratch;
|
|
||||||
|
|
||||||
// Get receiver klass.
|
// Get receiver klass.
|
||||||
// Must do an explicit check if implicit checks are disabled.
|
// 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());
|
__ null_check(Z_ARG1, Z_R1_scratch, oopDesc::klass_offset_in_bytes());
|
||||||
__ load_klass(rcvr_klass, Z_ARG1);
|
__ load_klass(rcvr_klass, Z_ARG1);
|
||||||
|
|
||||||
// Load start of itable entries into itable_entry.
|
// Receiver subtype check against REFC.
|
||||||
__ z_llgf(vtable_len, Address(rcvr_klass, Klass::vtable_length_offset()));
|
__ z_lg(interface, Address(Z_method, CompiledICHolder::holder_klass_offset()));
|
||||||
__ z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes()));
|
__ 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.
|
// Get Method* and entrypoint for compiler
|
||||||
const int vtable_base_offset = in_bytes(Klass::vtable_start_offset());
|
__ z_lg(interface, Address(Z_method, CompiledICHolder::holder_metadata_offset()));
|
||||||
// Count unused bytes.
|
__ lookup_interface_method(rcvr_klass, interface, itable_index,
|
||||||
start_pc = __ pc();
|
Z_method, Z_R1, no_such_interface, /*return_method=*/ true);
|
||||||
__ 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);
|
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (DebugVtables) {
|
if (DebugVtables) {
|
||||||
|
@ -244,13 +206,13 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
|
||||||
address ame_addr = __ pc();
|
address ame_addr = __ pc();
|
||||||
// Must do an explicit check if implicit checks are disabled.
|
// Must do an explicit check if implicit checks are disabled.
|
||||||
if (!ImplicitNullChecks) {
|
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_lg(Z_R1_scratch, in_bytes(Method::from_compiled_offset()), Z_method);
|
||||||
__ z_br(Z_R1_scratch);
|
__ z_br(Z_R1_scratch);
|
||||||
|
|
||||||
// Handle IncompatibleClassChangeError in itable stubs.
|
// Handle IncompatibleClassChangeError in itable stubs.
|
||||||
__ bind(throw_icce);
|
__ bind(no_such_interface);
|
||||||
// Count unused bytes
|
// Count unused bytes
|
||||||
// worst case actual size
|
// worst case actual size
|
||||||
// We force resolving of the call site by jumping to
|
// 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) {
|
if (CountCompiledCalls) {
|
||||||
size += 6 * 4;
|
size += 6 * 4;
|
||||||
}
|
}
|
||||||
if (is_vtable_stub) {
|
size += is_vtable_stub ? 36 : 140;
|
||||||
size += 52;
|
if (UseCompressedClassPointers) {
|
||||||
} else {
|
size += MacroAssembler::instr_size_for_decode_klass_not_null();
|
||||||
size += 104;
|
|
||||||
}
|
}
|
||||||
if (Universe::narrow_klass_base() != NULL) {
|
if (!ImplicitNullChecks) {
|
||||||
size += 16; // A guess.
|
size += 36;
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2058,9 +2058,10 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
Register method_result,
|
Register method_result,
|
||||||
Register scan_temp,
|
Register scan_temp,
|
||||||
Register sethi_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_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");
|
"caller must use same register for non-constant itable index as for method");
|
||||||
|
|
||||||
Label L_no_such_interface_restore;
|
Label L_no_such_interface_restore;
|
||||||
|
@ -2092,11 +2093,13 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
add(scan_temp, itb_offset, scan_temp);
|
add(scan_temp, itb_offset, scan_temp);
|
||||||
add(recv_klass, scan_temp, scan_temp);
|
add(recv_klass, scan_temp, scan_temp);
|
||||||
|
|
||||||
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
|
if (return_method) {
|
||||||
RegisterOrConstant itable_offset = itable_index;
|
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
|
||||||
itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset);
|
RegisterOrConstant itable_offset = itable_index;
|
||||||
itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset);
|
itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset);
|
||||||
add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass);
|
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) {
|
// for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
|
||||||
// if (scan->interface() == intf) {
|
// if (scan->interface() == intf) {
|
||||||
|
@ -2131,12 +2134,14 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
|
|
||||||
bind(L_found_method);
|
bind(L_found_method);
|
||||||
|
|
||||||
// Got a hit.
|
if (return_method) {
|
||||||
int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
|
// Got a hit.
|
||||||
// scan_temp[-scan_step] points to the vtable offset we need
|
int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
|
||||||
ito_offset -= scan_step;
|
// scan_temp[-scan_step] points to the vtable offset we need
|
||||||
lduw(scan_temp, ito_offset, scan_temp);
|
ito_offset -= scan_step;
|
||||||
ld_ptr(recv_klass, scan_temp, method_result);
|
lduw(scan_temp, ito_offset, scan_temp);
|
||||||
|
ld_ptr(recv_klass, scan_temp, method_result);
|
||||||
|
}
|
||||||
|
|
||||||
if (did_save) {
|
if (did_save) {
|
||||||
Label L_done;
|
Label L_done;
|
||||||
|
|
|
@ -1277,7 +1277,8 @@ public:
|
||||||
RegisterOrConstant itable_index,
|
RegisterOrConstant itable_index,
|
||||||
Register method_result,
|
Register method_result,
|
||||||
Register temp_reg, Register temp2_reg,
|
Register temp_reg, Register temp2_reg,
|
||||||
Label& no_such_interface);
|
Label& no_such_interface,
|
||||||
|
bool return_method = true);
|
||||||
|
|
||||||
// virtual method calling
|
// virtual method calling
|
||||||
void lookup_virtual_method(Register recv_klass,
|
void lookup_virtual_method(Register recv_klass,
|
||||||
|
|
|
@ -904,7 +904,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||||
|
|
||||||
Label ok, ok2;
|
Label ok, ok2;
|
||||||
__ brx(Assembler::equal, false, Assembler::pt, ok);
|
__ 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);
|
__ jump_to(ic_miss, G3_scratch);
|
||||||
__ delayed()->nop();
|
__ delayed()->nop();
|
||||||
|
|
||||||
|
|
|
@ -3081,15 +3081,15 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
assert(byte_no == f1_byte, "use this argument");
|
assert(byte_no == f1_byte, "use this argument");
|
||||||
|
|
||||||
const Register Rinterface = G1_scratch;
|
const Register Rinterface = G1_scratch;
|
||||||
|
const Register Rmethod = Lscratch;
|
||||||
const Register Rret = G3_scratch;
|
const Register Rret = G3_scratch;
|
||||||
const Register Rindex = Lscratch;
|
|
||||||
const Register O0_recv = O0;
|
const Register O0_recv = O0;
|
||||||
const Register O1_flags = O1;
|
const Register O1_flags = O1;
|
||||||
const Register O2_Klass = O2;
|
const Register O2_Klass = O2;
|
||||||
const Register Rscratch = G4_scratch;
|
const Register Rscratch = G4_scratch;
|
||||||
assert_different_registers(Rscratch, G5_method);
|
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
|
// get receiver klass
|
||||||
__ null_check(O0_recv, oopDesc::klass_offset_in_bytes());
|
__ null_check(O0_recv, oopDesc::klass_offset_in_bytes());
|
||||||
|
@ -3109,55 +3109,40 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
|
|
||||||
__ bind(notMethod);
|
__ 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);
|
__ profile_virtual_call(O2_Klass, O4);
|
||||||
|
|
||||||
//
|
//
|
||||||
// find entry point to call
|
// find entry point to call
|
||||||
//
|
//
|
||||||
|
|
||||||
// compute start of first itableOffsetEntry (which is at end of vtable)
|
// Get declaring interface class from method
|
||||||
const int base = in_bytes(Klass::vtable_start_offset());
|
__ ld_ptr(Rmethod, Method::const_offset(), Rinterface);
|
||||||
Label search;
|
__ ld_ptr(Rinterface, ConstMethod::constants_offset(), Rinterface);
|
||||||
Register Rtemp = O1_flags;
|
__ ld_ptr(Rinterface, ConstantPool::pool_holder_offset_in_bytes(), Rinterface);
|
||||||
|
|
||||||
__ ld(O2_Klass, in_bytes(Klass::vtable_length_offset()), Rtemp);
|
// Get itable index from method
|
||||||
__ sll(Rtemp, LogBytesPerWord, Rtemp); // Rscratch *= 4;
|
const Register Rindex = G5_method;
|
||||||
if (Assembler::is_simm13(base)) {
|
__ ld(Rmethod, Method::itable_index_offset(), Rindex);
|
||||||
__ add(Rtemp, base, Rtemp);
|
__ sub(Rindex, Method::itable_index_max, Rindex);
|
||||||
} else {
|
__ neg(Rindex);
|
||||||
__ set(base, Rscratch);
|
|
||||||
__ add(Rscratch, Rtemp, Rtemp);
|
|
||||||
}
|
|
||||||
__ add(O2_Klass, Rtemp, Rscratch);
|
|
||||||
|
|
||||||
__ bind(search);
|
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
||||||
|
O2_Klass, Rinterface, Rindex,
|
||||||
__ ld_ptr(Rscratch, itableOffsetEntry::interface_offset_in_bytes(), Rtemp);
|
// outputs: method, scan temp reg, temp reg
|
||||||
{
|
G5_method, Rscratch, Rtemp,
|
||||||
Label ok;
|
L_no_such_interface);
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// Check for abstract method error.
|
// Check for abstract method error.
|
||||||
{
|
{
|
||||||
|
@ -3174,6 +3159,10 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
__ profile_arguments_type(G5_method, Rcall, Gargs, true);
|
__ profile_arguments_type(G5_method, Rcall, Gargs, true);
|
||||||
__ profile_called_method(G5_method, Rscratch);
|
__ profile_called_method(G5_method, Rscratch);
|
||||||
__ call_from_interpreter(Rcall, Gargs, Rret);
|
__ 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) {
|
void TemplateTable::invokehandle(int byte_no) {
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "interp_masm_sparc.hpp"
|
#include "interp_masm_sparc.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/klassVtable.hpp"
|
#include "oops/klassVtable.hpp"
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
|
@ -140,7 +141,8 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||||
MacroAssembler* masm = new MacroAssembler(&cb);
|
MacroAssembler* masm = new MacroAssembler(&cb);
|
||||||
|
|
||||||
Register G3_Klass = G3_scratch;
|
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;
|
Label search;
|
||||||
|
|
||||||
// Entry arguments:
|
// Entry arguments:
|
||||||
|
@ -164,14 +166,26 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||||
}
|
}
|
||||||
#endif /* PRODUCT */
|
#endif /* PRODUCT */
|
||||||
|
|
||||||
Label throw_icce;
|
Label L_no_such_interface;
|
||||||
|
|
||||||
Register L5_method = L5;
|
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
|
__ 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
|
// outputs: method, scan temp. reg
|
||||||
L5_method, L2, L3,
|
L5_method, L2, L3,
|
||||||
throw_icce);
|
L_no_such_interface);
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (DebugVtables) {
|
if (DebugVtables) {
|
||||||
|
@ -197,7 +211,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||||
__ JMP(G3_scratch, 0);
|
__ JMP(G3_scratch, 0);
|
||||||
__ delayed()->nop();
|
__ delayed()->nop();
|
||||||
|
|
||||||
__ bind(throw_icce);
|
__ bind(L_no_such_interface);
|
||||||
AddressLiteral icce(StubRoutines::throw_IncompatibleClassChangeError_entry());
|
AddressLiteral icce(StubRoutines::throw_IncompatibleClassChangeError_entry());
|
||||||
__ jump_to(icce, G3_scratch);
|
__ jump_to(icce, G3_scratch);
|
||||||
__ delayed()->restore();
|
__ 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);
|
MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
|
||||||
return basic + slop;
|
return basic + slop;
|
||||||
} else {
|
} else {
|
||||||
const int basic = 34 * BytesPerInstWord +
|
const int basic = 54 * BytesPerInstWord +
|
||||||
// shift;add for load_klass (only shift with zero heap based)
|
// shift;add for load_klass (only shift with zero heap based)
|
||||||
(UseCompressedClassPointers ?
|
(UseCompressedClassPointers ?
|
||||||
MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
|
MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
|
||||||
|
|
|
@ -5809,8 +5809,13 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
RegisterOrConstant itable_index,
|
RegisterOrConstant itable_index,
|
||||||
Register method_result,
|
Register method_result,
|
||||||
Register scan_temp,
|
Register scan_temp,
|
||||||
Label& L_no_such_interface) {
|
Label& L_no_such_interface,
|
||||||
assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
|
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,
|
assert(itable_index.is_constant() || itable_index.as_register() == method_result,
|
||||||
"caller must use same register for non-constant itable index as for method");
|
"caller must use same register for non-constant itable index as for method");
|
||||||
|
|
||||||
|
@ -5827,9 +5832,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
// %%% Could store the aligned, prescaled offset in the klassoop.
|
// %%% Could store the aligned, prescaled offset in the klassoop.
|
||||||
lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base));
|
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.
|
if (return_method) {
|
||||||
assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
|
// Adjust recv_klass by scaled itable_index, so we can free itable_index.
|
||||||
lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off));
|
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) {
|
// for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
|
||||||
// if (scan->interface() == intf) {
|
// if (scan->interface() == intf) {
|
||||||
|
@ -5863,9 +5870,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
|
||||||
|
|
||||||
bind(found_method);
|
bind(found_method);
|
||||||
|
|
||||||
// Got a hit.
|
if (return_method) {
|
||||||
movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes()));
|
// Got a hit.
|
||||||
movptr(method_result, Address(recv_klass, scan_temp, Address::times_1));
|
movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes()));
|
||||||
|
movptr(method_result, Address(recv_klass, scan_temp, Address::times_1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -544,7 +544,8 @@ class MacroAssembler: public Assembler {
|
||||||
RegisterOrConstant itable_index,
|
RegisterOrConstant itable_index,
|
||||||
Register method_result,
|
Register method_result,
|
||||||
Register scan_temp,
|
Register scan_temp,
|
||||||
Label& no_such_interface);
|
Label& no_such_interface,
|
||||||
|
bool return_method = true);
|
||||||
|
|
||||||
// virtual method calling
|
// virtual method calling
|
||||||
void lookup_virtual_method(Register recv_klass,
|
void lookup_virtual_method(Register recv_klass,
|
||||||
|
|
|
@ -957,7 +957,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||||
Label missed;
|
Label missed;
|
||||||
__ movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes()));
|
__ movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes()));
|
||||||
__ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset()));
|
__ 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);
|
__ jcc(Assembler::notEqual, missed);
|
||||||
// Method might have been compiled since the call site was patched to
|
// 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
|
// interpreted if that is the case treat it as a miss so we can get
|
||||||
|
|
|
@ -949,7 +949,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||||
{
|
{
|
||||||
__ load_klass(temp, receiver);
|
__ load_klass(temp, receiver);
|
||||||
__ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset()));
|
__ 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);
|
__ jcc(Assembler::equal, ok);
|
||||||
__ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
|
__ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
|
||||||
|
|
||||||
|
|
|
@ -3712,11 +3712,11 @@ void TemplateTable::fast_invokevfinal(int byte_no) {
|
||||||
void TemplateTable::invokeinterface(int byte_no) {
|
void TemplateTable::invokeinterface(int byte_no) {
|
||||||
transition(vtos, vtos);
|
transition(vtos, vtos);
|
||||||
assert(byte_no == f1_byte, "use this argument");
|
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
|
rcx, rdx); // recv, flags
|
||||||
|
|
||||||
// rax: interface klass (from f1)
|
// rax: reference klass (from f1)
|
||||||
// rbx: itable index (from f2)
|
// rbx: method (from f2)
|
||||||
// rcx: receiver
|
// rcx: receiver
|
||||||
// rdx: flags
|
// rdx: flags
|
||||||
|
|
||||||
|
@ -3738,10 +3738,28 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
__ null_check(rcx, oopDesc::klass_offset_in_bytes());
|
__ null_check(rcx, oopDesc::klass_offset_in_bytes());
|
||||||
__ load_klass(rdx, rcx);
|
__ 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
|
// profile this call
|
||||||
|
__ restore_bcp(); // rbcp was destroyed by receiver type check
|
||||||
__ profile_virtual_call(rdx, rbcp, rlocals);
|
__ 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
|
__ lookup_interface_method(// inputs: rec. class, interface, itable index
|
||||||
rdx, rax, rbx,
|
rdx, rax, rbx,
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "interp_masm_x86.hpp"
|
#include "interp_masm_x86.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/klassVtable.hpp"
|
#include "oops/klassVtable.hpp"
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
|
@ -147,7 +148,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||||
MacroAssembler* masm = new MacroAssembler(&cb);
|
MacroAssembler* masm = new MacroAssembler(&cb);
|
||||||
|
|
||||||
// Entry arguments:
|
// Entry arguments:
|
||||||
// rax,: Interface
|
// rax: CompiledICHolder
|
||||||
// rcx: Receiver
|
// rcx: Receiver
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -155,25 +156,42 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||||
__ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
|
__ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
|
||||||
}
|
}
|
||||||
#endif /* PRODUCT */
|
#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
|
// 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.)
|
// (If we need to make rsi, rdi callee-save, do a push/pop here.)
|
||||||
const Register method = rbx;
|
const Register recv_klass_reg = rsi;
|
||||||
Label throw_icce;
|
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
|
__ 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
|
// outputs: method, scan temp. reg
|
||||||
method, rdi,
|
method, temp_reg,
|
||||||
throw_icce);
|
L_no_such_interface);
|
||||||
|
|
||||||
// method (rbx): Method*
|
// method (rbx): Method*
|
||||||
// rcx: receiver
|
// rcx: receiver
|
||||||
|
@ -193,9 +211,10 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||||
address ame_addr = __ pc();
|
address ame_addr = __ pc();
|
||||||
__ jmp(Address(method, Method::from_compiled_offset()));
|
__ jmp(Address(method, Method::from_compiled_offset()));
|
||||||
|
|
||||||
__ bind(throw_icce);
|
__ bind(L_no_such_interface);
|
||||||
__ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
|
__ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
|
||||||
masm->flush();
|
|
||||||
|
__ flush();
|
||||||
|
|
||||||
if (PrintMiscellaneous && (WizardMode || Verbose)) {
|
if (PrintMiscellaneous && (WizardMode || Verbose)) {
|
||||||
tty->print_cr("itable #%d at " PTR_FORMAT "[%d] left over: %d",
|
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);
|
return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0);
|
||||||
} else {
|
} else {
|
||||||
// Itable stub size
|
// 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
|
// In order to tune these parameters, run the JVM with VM options
|
||||||
// +PrintMiscellaneous and +WizardMode to see information about
|
// +PrintMiscellaneous and +WizardMode to see information about
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "code/vtableStubs.hpp"
|
#include "code/vtableStubs.hpp"
|
||||||
#include "interp_masm_x86.hpp"
|
#include "interp_masm_x86.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "oops/compiledICHolder.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/klassVtable.hpp"
|
#include "oops/klassVtable.hpp"
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
|
@ -147,36 +148,50 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Entry arguments:
|
// Entry arguments:
|
||||||
// rax: Interface
|
// rax: CompiledICHolder
|
||||||
// j_rarg0: Receiver
|
// 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
|
// 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)
|
// (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
|
// 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
|
// be able to walk the stack properly. This is not an issue except
|
||||||
// when there are mistakes in this assembly code that could generate
|
// when there are mistakes in this assembly code that could generate
|
||||||
// a spurious fault. Ask me how I know...
|
// 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*
|
// method (rbx): Method*
|
||||||
// j_rarg0: receiver
|
// j_rarg0: receiver
|
||||||
|
|
||||||
|
@ -197,7 +212,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||||
address ame_addr = __ pc();
|
address ame_addr = __ pc();
|
||||||
__ jmp(Address(method, Method::from_compiled_offset()));
|
__ jmp(Address(method, Method::from_compiled_offset()));
|
||||||
|
|
||||||
__ bind(throw_icce);
|
__ bind(L_no_such_interface);
|
||||||
__ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
|
__ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
|
||||||
|
|
||||||
__ flush();
|
__ 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);
|
(UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
|
||||||
} else {
|
} else {
|
||||||
// Itable stub size
|
// Itable stub size
|
||||||
return (DebugVtables ? 512 : 74) + (CountCompiledCalls ? 13 : 0) +
|
return (DebugVtables ? 512 : 140) + (CountCompiledCalls ? 13 : 0) +
|
||||||
(UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
|
(UseCompressedClassPointers ? 2 * MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
|
||||||
}
|
}
|
||||||
// In order to tune these parameters, run the JVM with VM options
|
// In order to tune these parameters, run the JVM with VM options
|
||||||
// +PrintMiscellaneous and +WizardMode to see information about
|
// +PrintMiscellaneous and +WizardMode to see information about
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2017 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
|
@ -1723,7 +1723,7 @@ void os::signal_notify(int sig) {
|
||||||
local_sem_post();
|
local_sem_post();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_pending_signals(bool wait) {
|
static int check_pending_signals() {
|
||||||
Atomic::store(0, &sigint_count);
|
Atomic::store(0, &sigint_count);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (int i = 0; i < NSIG + 1; i++) {
|
for (int i = 0; i < NSIG + 1; i++) {
|
||||||
|
@ -1732,9 +1732,6 @@ static int check_pending_signals(bool wait) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!wait) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
JavaThread *thread = JavaThread::current();
|
JavaThread *thread = JavaThread::current();
|
||||||
ThreadBlockInVM tbivm(thread);
|
ThreadBlockInVM tbivm(thread);
|
||||||
|
|
||||||
|
@ -1763,12 +1760,8 @@ static int check_pending_signals(bool wait) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int os::signal_lookup() {
|
|
||||||
return check_pending_signals(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
int os::signal_wait() {
|
int os::signal_wait() {
|
||||||
return check_pending_signals(true);
|
return check_pending_signals();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -52,13 +52,13 @@
|
||||||
#include "runtime/orderAccess.inline.hpp"
|
#include "runtime/orderAccess.inline.hpp"
|
||||||
#include "runtime/osThread.hpp"
|
#include "runtime/osThread.hpp"
|
||||||
#include "runtime/perfMemory.hpp"
|
#include "runtime/perfMemory.hpp"
|
||||||
|
#include "runtime/semaphore.hpp"
|
||||||
#include "runtime/sharedRuntime.hpp"
|
#include "runtime/sharedRuntime.hpp"
|
||||||
#include "runtime/statSampler.hpp"
|
#include "runtime/statSampler.hpp"
|
||||||
#include "runtime/stubRoutines.hpp"
|
#include "runtime/stubRoutines.hpp"
|
||||||
#include "runtime/thread.inline.hpp"
|
#include "runtime/thread.inline.hpp"
|
||||||
#include "runtime/threadCritical.hpp"
|
#include "runtime/threadCritical.hpp"
|
||||||
#include "runtime/timer.hpp"
|
#include "runtime/timer.hpp"
|
||||||
#include "semaphore_bsd.hpp"
|
|
||||||
#include "services/attachListener.hpp"
|
#include "services/attachListener.hpp"
|
||||||
#include "services/memTracker.hpp"
|
#include "services/memTracker.hpp"
|
||||||
#include "services/runtimeService.hpp"
|
#include "services/runtimeService.hpp"
|
||||||
|
@ -91,7 +91,6 @@
|
||||||
# include <time.h>
|
# include <time.h>
|
||||||
# include <pwd.h>
|
# include <pwd.h>
|
||||||
# include <poll.h>
|
# include <poll.h>
|
||||||
# include <semaphore.h>
|
|
||||||
# include <fcntl.h>
|
# include <fcntl.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# include <sys/param.h>
|
# include <sys/param.h>
|
||||||
|
@ -1829,135 +1828,28 @@ int os::sigexitnum_pd() {
|
||||||
|
|
||||||
// a counter for each possible signal value
|
// a counter for each possible signal value
|
||||||
static volatile jint pending_signals[NSIG+1] = { 0 };
|
static volatile jint pending_signals[NSIG+1] = { 0 };
|
||||||
|
static Semaphore* sig_sem = NULL;
|
||||||
// Bsd(POSIX) specific hand shaking semaphore.
|
|
||||||
#ifdef __APPLE__
|
|
||||||
typedef semaphore_t os_semaphore_t;
|
|
||||||
|
|
||||||
#define SEM_INIT(sem, value) semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, value)
|
|
||||||
#define SEM_WAIT(sem) semaphore_wait(sem)
|
|
||||||
#define SEM_POST(sem) semaphore_signal(sem)
|
|
||||||
#define SEM_DESTROY(sem) semaphore_destroy(mach_task_self(), sem)
|
|
||||||
#else
|
|
||||||
typedef sem_t os_semaphore_t;
|
|
||||||
|
|
||||||
#define SEM_INIT(sem, value) sem_init(&sem, 0, value)
|
|
||||||
#define SEM_WAIT(sem) sem_wait(&sem)
|
|
||||||
#define SEM_POST(sem) sem_post(&sem)
|
|
||||||
#define SEM_DESTROY(sem) sem_destroy(&sem)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
// OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used.
|
|
||||||
|
|
||||||
static const char* sem_init_strerror(kern_return_t value) {
|
|
||||||
switch (value) {
|
|
||||||
case KERN_INVALID_ARGUMENT: return "Invalid argument";
|
|
||||||
case KERN_RESOURCE_SHORTAGE: return "Resource shortage";
|
|
||||||
default: return "Unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OSXSemaphore::OSXSemaphore(uint value) {
|
|
||||||
kern_return_t ret = SEM_INIT(_semaphore, value);
|
|
||||||
|
|
||||||
guarantee(ret == KERN_SUCCESS, "Failed to create semaphore: %s", sem_init_strerror(ret));
|
|
||||||
}
|
|
||||||
|
|
||||||
OSXSemaphore::~OSXSemaphore() {
|
|
||||||
SEM_DESTROY(_semaphore);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSXSemaphore::signal(uint count) {
|
|
||||||
for (uint i = 0; i < count; i++) {
|
|
||||||
kern_return_t ret = SEM_POST(_semaphore);
|
|
||||||
|
|
||||||
assert(ret == KERN_SUCCESS, "Failed to signal semaphore");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSXSemaphore::wait() {
|
|
||||||
kern_return_t ret;
|
|
||||||
while ((ret = SEM_WAIT(_semaphore)) == KERN_ABORTED) {
|
|
||||||
// Semaphore was interrupted. Retry.
|
|
||||||
}
|
|
||||||
assert(ret == KERN_SUCCESS, "Failed to wait on semaphore");
|
|
||||||
}
|
|
||||||
|
|
||||||
jlong OSXSemaphore::currenttime() {
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OSXSemaphore::trywait() {
|
|
||||||
return timedwait(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OSXSemaphore::timedwait(unsigned int sec, int nsec) {
|
|
||||||
kern_return_t kr = KERN_ABORTED;
|
|
||||||
mach_timespec_t waitspec;
|
|
||||||
waitspec.tv_sec = sec;
|
|
||||||
waitspec.tv_nsec = nsec;
|
|
||||||
|
|
||||||
jlong starttime = currenttime();
|
|
||||||
|
|
||||||
kr = semaphore_timedwait(_semaphore, waitspec);
|
|
||||||
while (kr == KERN_ABORTED) {
|
|
||||||
jlong totalwait = (sec * NANOSECS_PER_SEC) + nsec;
|
|
||||||
|
|
||||||
jlong current = currenttime();
|
|
||||||
jlong passedtime = current - starttime;
|
|
||||||
|
|
||||||
if (passedtime >= totalwait) {
|
|
||||||
waitspec.tv_sec = 0;
|
|
||||||
waitspec.tv_nsec = 0;
|
|
||||||
} else {
|
|
||||||
jlong waittime = totalwait - (current - starttime);
|
|
||||||
waitspec.tv_sec = waittime / NANOSECS_PER_SEC;
|
|
||||||
waitspec.tv_nsec = waittime % NANOSECS_PER_SEC;
|
|
||||||
}
|
|
||||||
|
|
||||||
kr = semaphore_timedwait(_semaphore, waitspec);
|
|
||||||
}
|
|
||||||
|
|
||||||
return kr == KERN_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
// Use POSIX implementation of semaphores.
|
|
||||||
|
|
||||||
struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
|
|
||||||
struct timespec ts;
|
|
||||||
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
|
|
||||||
|
|
||||||
return ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __APPLE__
|
|
||||||
|
|
||||||
static os_semaphore_t sig_sem;
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
static OSXSemaphore sr_semaphore;
|
|
||||||
#else
|
|
||||||
static PosixSemaphore sr_semaphore;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void os::signal_init_pd() {
|
void os::signal_init_pd() {
|
||||||
// Initialize signal structures
|
// Initialize signal structures
|
||||||
::memset((void*)pending_signals, 0, sizeof(pending_signals));
|
::memset((void*)pending_signals, 0, sizeof(pending_signals));
|
||||||
|
|
||||||
// Initialize signal semaphore
|
// Initialize signal semaphore
|
||||||
::SEM_INIT(sig_sem, 0);
|
sig_sem = new Semaphore();
|
||||||
}
|
}
|
||||||
|
|
||||||
void os::signal_notify(int sig) {
|
void os::signal_notify(int sig) {
|
||||||
Atomic::inc(&pending_signals[sig]);
|
if (sig_sem != NULL) {
|
||||||
::SEM_POST(sig_sem);
|
Atomic::inc(&pending_signals[sig]);
|
||||||
|
sig_sem->signal();
|
||||||
|
} else {
|
||||||
|
// Signal thread is not created with ReduceSignalUsage and signal_init_pd
|
||||||
|
// initialization isn't called.
|
||||||
|
assert(ReduceSignalUsage, "signal semaphore should be created");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_pending_signals(bool wait) {
|
static int check_pending_signals() {
|
||||||
Atomic::store(0, &sigint_count);
|
Atomic::store(0, &sigint_count);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (int i = 0; i < NSIG + 1; i++) {
|
for (int i = 0; i < NSIG + 1; i++) {
|
||||||
|
@ -1966,9 +1858,6 @@ static int check_pending_signals(bool wait) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!wait) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
JavaThread *thread = JavaThread::current();
|
JavaThread *thread = JavaThread::current();
|
||||||
ThreadBlockInVM tbivm(thread);
|
ThreadBlockInVM tbivm(thread);
|
||||||
|
|
||||||
|
@ -1976,7 +1865,7 @@ static int check_pending_signals(bool wait) {
|
||||||
do {
|
do {
|
||||||
thread->set_suspend_equivalent();
|
thread->set_suspend_equivalent();
|
||||||
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
|
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
|
||||||
::SEM_WAIT(sig_sem);
|
sig_sem->wait();
|
||||||
|
|
||||||
// were we externally suspended while we were waiting?
|
// were we externally suspended while we were waiting?
|
||||||
threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
|
threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
|
||||||
|
@ -1985,7 +1874,7 @@ static int check_pending_signals(bool wait) {
|
||||||
// another thread suspended us. We don't want to continue running
|
// another thread suspended us. We don't want to continue running
|
||||||
// while suspended because that would surprise the thread that
|
// while suspended because that would surprise the thread that
|
||||||
// suspended us.
|
// suspended us.
|
||||||
::SEM_POST(sig_sem);
|
sig_sem->signal();
|
||||||
|
|
||||||
thread->java_suspend_self();
|
thread->java_suspend_self();
|
||||||
}
|
}
|
||||||
|
@ -1993,12 +1882,8 @@ static int check_pending_signals(bool wait) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int os::signal_lookup() {
|
|
||||||
return check_pending_signals(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
int os::signal_wait() {
|
int os::signal_wait() {
|
||||||
return check_pending_signals(true);
|
return check_pending_signals();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -2663,6 +2548,12 @@ static void suspend_save_context(OSThread *osthread, siginfo_t* siginfo, ucontex
|
||||||
//
|
//
|
||||||
// Currently only ever called on the VMThread or JavaThread
|
// Currently only ever called on the VMThread or JavaThread
|
||||||
//
|
//
|
||||||
|
#ifdef __APPLE__
|
||||||
|
static OSXSemaphore sr_semaphore;
|
||||||
|
#else
|
||||||
|
static PosixSemaphore sr_semaphore;
|
||||||
|
#endif
|
||||||
|
|
||||||
static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) {
|
static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) {
|
||||||
// Save and restore errno to avoid confusing native code with EINTR
|
// Save and restore errno to avoid confusing native code with EINTR
|
||||||
// after sigsuspend.
|
// after sigsuspend.
|
||||||
|
|
107
src/hotspot/os/bsd/semaphore_bsd.cpp
Normal file
107
src/hotspot/os/bsd/semaphore_bsd.cpp
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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/precompiled.hpp"
|
||||||
|
#include "semaphore_bsd.hpp"
|
||||||
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
// OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used.
|
||||||
|
|
||||||
|
static const char* sem_init_strerror(kern_return_t value) {
|
||||||
|
switch (value) {
|
||||||
|
case KERN_INVALID_ARGUMENT: return "Invalid argument";
|
||||||
|
case KERN_RESOURCE_SHORTAGE: return "Resource shortage";
|
||||||
|
default: return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OSXSemaphore::OSXSemaphore(uint value) {
|
||||||
|
kern_return_t ret = semaphore_create(mach_task_self(), &_semaphore, SYNC_POLICY_FIFO, value);
|
||||||
|
|
||||||
|
guarantee(ret == KERN_SUCCESS, "Failed to create semaphore: %s", sem_init_strerror(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
OSXSemaphore::~OSXSemaphore() {
|
||||||
|
semaphore_destroy(mach_task_self(), _semaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSXSemaphore::signal(uint count) {
|
||||||
|
for (uint i = 0; i < count; i++) {
|
||||||
|
kern_return_t ret = semaphore_signal(_semaphore);
|
||||||
|
|
||||||
|
assert(ret == KERN_SUCCESS, "Failed to signal semaphore");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OSXSemaphore::wait() {
|
||||||
|
kern_return_t ret;
|
||||||
|
while ((ret = semaphore_wait(_semaphore)) == KERN_ABORTED) {
|
||||||
|
// Semaphore was interrupted. Retry.
|
||||||
|
}
|
||||||
|
assert(ret == KERN_SUCCESS, "Failed to wait on semaphore");
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t OSXSemaphore::currenttime() {
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OSXSemaphore::trywait() {
|
||||||
|
return timedwait(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OSXSemaphore::timedwait(unsigned int sec, int nsec) {
|
||||||
|
kern_return_t kr = KERN_ABORTED;
|
||||||
|
mach_timespec_t waitspec;
|
||||||
|
waitspec.tv_sec = sec;
|
||||||
|
waitspec.tv_nsec = nsec;
|
||||||
|
|
||||||
|
int64_t starttime = currenttime();
|
||||||
|
|
||||||
|
kr = semaphore_timedwait(_semaphore, waitspec);
|
||||||
|
while (kr == KERN_ABORTED) {
|
||||||
|
int64_t totalwait = (sec * NANOSECS_PER_SEC) + nsec;
|
||||||
|
|
||||||
|
int64_t current = currenttime();
|
||||||
|
int64_t passedtime = current - starttime;
|
||||||
|
|
||||||
|
if (passedtime >= totalwait) {
|
||||||
|
waitspec.tv_sec = 0;
|
||||||
|
waitspec.tv_nsec = 0;
|
||||||
|
} else {
|
||||||
|
int64_t waittime = totalwait - (current - starttime);
|
||||||
|
waitspec.tv_sec = waittime / NANOSECS_PER_SEC;
|
||||||
|
waitspec.tv_nsec = waittime % NANOSECS_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
kr = semaphore_timedwait(_semaphore, waitspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return kr == KERN_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif // __APPLE__
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -53,7 +53,7 @@ class OSXSemaphore : public CHeapObj<mtInternal>{
|
||||||
bool timedwait(unsigned int sec, int nsec);
|
bool timedwait(unsigned int sec, int nsec);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static jlong currenttime();
|
static int64_t currenttime();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef OSXSemaphore SemaphoreImpl;
|
typedef OSXSemaphore SemaphoreImpl;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -95,7 +95,6 @@
|
||||||
# include <sys/wait.h>
|
# include <sys/wait.h>
|
||||||
# include <pwd.h>
|
# include <pwd.h>
|
||||||
# include <poll.h>
|
# include <poll.h>
|
||||||
# include <semaphore.h>
|
|
||||||
# include <fcntl.h>
|
# include <fcntl.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
# include <syscall.h>
|
# include <syscall.h>
|
||||||
|
@ -2479,11 +2478,11 @@ void* os::user_handler() {
|
||||||
return CAST_FROM_FN_PTR(void*, UserHandler);
|
return CAST_FROM_FN_PTR(void*, UserHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
|
static struct timespec create_semaphore_timespec(unsigned int sec, int nsec) {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
// Semaphore's are always associated with CLOCK_REALTIME
|
// Semaphore's are always associated with CLOCK_REALTIME
|
||||||
os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
|
os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
// see unpackTime for discussion on overflow checking
|
// see os_posix.cpp for discussion on overflow checking
|
||||||
if (sec >= MAX_SECS) {
|
if (sec >= MAX_SECS) {
|
||||||
ts.tv_sec += MAX_SECS;
|
ts.tv_sec += MAX_SECS;
|
||||||
ts.tv_nsec = 0;
|
ts.tv_nsec = 0;
|
||||||
|
@ -2535,7 +2534,7 @@ int os::sigexitnum_pd() {
|
||||||
static volatile jint pending_signals[NSIG+1] = { 0 };
|
static volatile jint pending_signals[NSIG+1] = { 0 };
|
||||||
|
|
||||||
// Linux(POSIX) specific hand shaking semaphore.
|
// Linux(POSIX) specific hand shaking semaphore.
|
||||||
static sem_t sig_sem;
|
static Semaphore* sig_sem = NULL;
|
||||||
static PosixSemaphore sr_semaphore;
|
static PosixSemaphore sr_semaphore;
|
||||||
|
|
||||||
void os::signal_init_pd() {
|
void os::signal_init_pd() {
|
||||||
|
@ -2543,15 +2542,21 @@ void os::signal_init_pd() {
|
||||||
::memset((void*)pending_signals, 0, sizeof(pending_signals));
|
::memset((void*)pending_signals, 0, sizeof(pending_signals));
|
||||||
|
|
||||||
// Initialize signal semaphore
|
// Initialize signal semaphore
|
||||||
::sem_init(&sig_sem, 0, 0);
|
sig_sem = new Semaphore();
|
||||||
}
|
}
|
||||||
|
|
||||||
void os::signal_notify(int sig) {
|
void os::signal_notify(int sig) {
|
||||||
Atomic::inc(&pending_signals[sig]);
|
if (sig_sem != NULL) {
|
||||||
::sem_post(&sig_sem);
|
Atomic::inc(&pending_signals[sig]);
|
||||||
|
sig_sem->signal();
|
||||||
|
} else {
|
||||||
|
// Signal thread is not created with ReduceSignalUsage and signal_init_pd
|
||||||
|
// initialization isn't called.
|
||||||
|
assert(ReduceSignalUsage, "signal semaphore should be created");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_pending_signals(bool wait) {
|
static int check_pending_signals() {
|
||||||
Atomic::store(0, &sigint_count);
|
Atomic::store(0, &sigint_count);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (int i = 0; i < NSIG + 1; i++) {
|
for (int i = 0; i < NSIG + 1; i++) {
|
||||||
|
@ -2560,9 +2565,6 @@ static int check_pending_signals(bool wait) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!wait) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
JavaThread *thread = JavaThread::current();
|
JavaThread *thread = JavaThread::current();
|
||||||
ThreadBlockInVM tbivm(thread);
|
ThreadBlockInVM tbivm(thread);
|
||||||
|
|
||||||
|
@ -2570,7 +2572,7 @@ static int check_pending_signals(bool wait) {
|
||||||
do {
|
do {
|
||||||
thread->set_suspend_equivalent();
|
thread->set_suspend_equivalent();
|
||||||
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
|
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
|
||||||
::sem_wait(&sig_sem);
|
sig_sem->wait();
|
||||||
|
|
||||||
// were we externally suspended while we were waiting?
|
// were we externally suspended while we were waiting?
|
||||||
threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
|
threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
|
||||||
|
@ -2579,7 +2581,7 @@ static int check_pending_signals(bool wait) {
|
||||||
// another thread suspended us. We don't want to continue running
|
// another thread suspended us. We don't want to continue running
|
||||||
// while suspended because that would surprise the thread that
|
// while suspended because that would surprise the thread that
|
||||||
// suspended us.
|
// suspended us.
|
||||||
::sem_post(&sig_sem);
|
sig_sem->signal();
|
||||||
|
|
||||||
thread->java_suspend_self();
|
thread->java_suspend_self();
|
||||||
}
|
}
|
||||||
|
@ -2587,12 +2589,8 @@ static int check_pending_signals(bool wait) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int os::signal_lookup() {
|
|
||||||
return check_pending_signals(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
int os::signal_wait() {
|
int os::signal_wait() {
|
||||||
return check_pending_signals(true);
|
return check_pending_signals();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -4317,7 +4315,7 @@ static bool do_suspend(OSThread* osthread) {
|
||||||
|
|
||||||
// managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
|
// managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
|
||||||
while (true) {
|
while (true) {
|
||||||
if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) {
|
if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2 * NANOSECS_PER_MILLISEC))) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// timeout
|
// timeout
|
||||||
|
@ -4351,7 +4349,7 @@ static void do_resume(OSThread* osthread) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (sr_notify(osthread) == 0) {
|
if (sr_notify(osthread) == 0) {
|
||||||
if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) {
|
if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2 * NANOSECS_PER_MILLISEC))) {
|
||||||
if (osthread->sr.is_running()) {
|
if (osthread->sr.is_running()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -31,14 +31,8 @@
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
#include "utilities/vmError.hpp"
|
#include "utilities/vmError.hpp"
|
||||||
|
|
||||||
#ifndef __APPLE__
|
|
||||||
// POSIX unamed semaphores are not supported on OS X.
|
|
||||||
#include "semaphore_posix.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <semaphore.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
@ -1499,67 +1493,6 @@ void os::ThreadCrashProtection::check_crash_protection(int sig,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// POSIX unamed semaphores are not supported on OS X.
|
|
||||||
#ifndef __APPLE__
|
|
||||||
|
|
||||||
PosixSemaphore::PosixSemaphore(uint value) {
|
|
||||||
int ret = sem_init(&_semaphore, 0, value);
|
|
||||||
|
|
||||||
guarantee_with_errno(ret == 0, "Failed to initialize semaphore");
|
|
||||||
}
|
|
||||||
|
|
||||||
PosixSemaphore::~PosixSemaphore() {
|
|
||||||
sem_destroy(&_semaphore);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PosixSemaphore::signal(uint count) {
|
|
||||||
for (uint i = 0; i < count; i++) {
|
|
||||||
int ret = sem_post(&_semaphore);
|
|
||||||
|
|
||||||
assert_with_errno(ret == 0, "sem_post failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PosixSemaphore::wait() {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
do {
|
|
||||||
ret = sem_wait(&_semaphore);
|
|
||||||
} while (ret != 0 && errno == EINTR);
|
|
||||||
|
|
||||||
assert_with_errno(ret == 0, "sem_wait failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PosixSemaphore::trywait() {
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
do {
|
|
||||||
ret = sem_trywait(&_semaphore);
|
|
||||||
} while (ret != 0 && errno == EINTR);
|
|
||||||
|
|
||||||
assert_with_errno(ret == 0 || errno == EAGAIN, "trywait failed");
|
|
||||||
|
|
||||||
return ret == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PosixSemaphore::timedwait(struct timespec ts) {
|
|
||||||
while (true) {
|
|
||||||
int result = sem_timedwait(&_semaphore, &ts);
|
|
||||||
if (result == 0) {
|
|
||||||
return true;
|
|
||||||
} else if (errno == EINTR) {
|
|
||||||
continue;
|
|
||||||
} else if (errno == ETIMEDOUT) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
assert_with_errno(false, "timedwait failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __APPLE__
|
|
||||||
|
|
||||||
|
|
||||||
// Shared pthread_mutex/cond based PlatformEvent implementation.
|
// Shared pthread_mutex/cond based PlatformEvent implementation.
|
||||||
// Not currently usable by Solaris.
|
// Not currently usable by Solaris.
|
||||||
|
|
98
src/hotspot/os/posix/semaphore_posix.cpp
Normal file
98
src/hotspot/os/posix/semaphore_posix.cpp
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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/precompiled.hpp"
|
||||||
|
#ifndef __APPLE__
|
||||||
|
#include "runtime/os.hpp"
|
||||||
|
// POSIX unamed semaphores are not supported on OS X.
|
||||||
|
#include "semaphore_posix.hpp"
|
||||||
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
#define check_with_errno(check_type, cond, msg) \
|
||||||
|
do { \
|
||||||
|
int err = errno; \
|
||||||
|
check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err), \
|
||||||
|
os::errno_name(err)); \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
#define assert_with_errno(cond, msg) check_with_errno(assert, cond, msg)
|
||||||
|
#define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg)
|
||||||
|
|
||||||
|
PosixSemaphore::PosixSemaphore(uint value) {
|
||||||
|
int ret = sem_init(&_semaphore, 0, value);
|
||||||
|
|
||||||
|
guarantee_with_errno(ret == 0, "Failed to initialize semaphore");
|
||||||
|
}
|
||||||
|
|
||||||
|
PosixSemaphore::~PosixSemaphore() {
|
||||||
|
sem_destroy(&_semaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PosixSemaphore::signal(uint count) {
|
||||||
|
for (uint i = 0; i < count; i++) {
|
||||||
|
int ret = sem_post(&_semaphore);
|
||||||
|
|
||||||
|
assert_with_errno(ret == 0, "sem_post failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PosixSemaphore::wait() {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = sem_wait(&_semaphore);
|
||||||
|
} while (ret != 0 && errno == EINTR);
|
||||||
|
|
||||||
|
assert_with_errno(ret == 0, "sem_wait failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PosixSemaphore::trywait() {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = sem_trywait(&_semaphore);
|
||||||
|
} while (ret != 0 && errno == EINTR);
|
||||||
|
|
||||||
|
assert_with_errno(ret == 0 || errno == EAGAIN, "trywait failed");
|
||||||
|
|
||||||
|
return ret == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PosixSemaphore::timedwait(struct timespec ts) {
|
||||||
|
while (true) {
|
||||||
|
int result = sem_timedwait(&_semaphore, &ts);
|
||||||
|
if (result == 0) {
|
||||||
|
return true;
|
||||||
|
} else if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
} else if (errno == ETIMEDOUT) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
assert_with_errno(false, "timedwait failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // __APPLE__
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -45,15 +45,7 @@ class PosixSemaphore : public CHeapObj<mtInternal> {
|
||||||
void wait();
|
void wait();
|
||||||
|
|
||||||
bool trywait();
|
bool trywait();
|
||||||
bool timedwait(unsigned int sec, int nsec) {
|
|
||||||
return timedwait(create_timespec(sec, nsec));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool timedwait(struct timespec ts);
|
bool timedwait(struct timespec ts);
|
||||||
|
|
||||||
// OS specific implementation to create a timespec suitable for semaphores.
|
|
||||||
struct timespec create_timespec(unsigned int set, int nsec);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef PosixSemaphore SemaphoreImpl;
|
typedef PosixSemaphore SemaphoreImpl;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -2062,7 +2062,7 @@ void* os::user_handler() {
|
||||||
return CAST_FROM_FN_PTR(void*, UserHandler);
|
return CAST_FROM_FN_PTR(void*, UserHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
|
static struct timespec create_semaphore_timespec(unsigned int sec, int nsec) {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
|
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
|
||||||
|
|
||||||
|
@ -2100,7 +2100,7 @@ static int Sigexit = 0;
|
||||||
static jint *pending_signals = NULL;
|
static jint *pending_signals = NULL;
|
||||||
static int *preinstalled_sigs = NULL;
|
static int *preinstalled_sigs = NULL;
|
||||||
static struct sigaction *chainedsigactions = NULL;
|
static struct sigaction *chainedsigactions = NULL;
|
||||||
static sema_t sig_sem;
|
static Semaphore* sig_sem = NULL;
|
||||||
typedef int (*version_getting_t)();
|
typedef int (*version_getting_t)();
|
||||||
version_getting_t os::Solaris::get_libjsig_version = NULL;
|
version_getting_t os::Solaris::get_libjsig_version = NULL;
|
||||||
|
|
||||||
|
@ -2115,6 +2115,7 @@ void os::Solaris::init_signal_mem() {
|
||||||
Sigexit = Maxsignum+1;
|
Sigexit = Maxsignum+1;
|
||||||
assert(Maxsignum >0, "Unable to obtain max signal number");
|
assert(Maxsignum >0, "Unable to obtain max signal number");
|
||||||
|
|
||||||
|
// Initialize signal structures
|
||||||
// pending_signals has one int per signal
|
// pending_signals has one int per signal
|
||||||
// The additional signal is for SIGEXIT - exit signal to signal_thread
|
// The additional signal is for SIGEXIT - exit signal to signal_thread
|
||||||
pending_signals = (jint *)os::malloc(sizeof(jint) * (Sigexit+1), mtInternal);
|
pending_signals = (jint *)os::malloc(sizeof(jint) * (Sigexit+1), mtInternal);
|
||||||
|
@ -2132,21 +2133,22 @@ void os::Solaris::init_signal_mem() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void os::signal_init_pd() {
|
void os::signal_init_pd() {
|
||||||
int ret;
|
// Initialize signal semaphore
|
||||||
|
sig_sem = new Semaphore();
|
||||||
ret = ::sema_init(&sig_sem, 0, NULL, NULL);
|
|
||||||
assert(ret == 0, "sema_init() failed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void os::signal_notify(int signal_number) {
|
void os::signal_notify(int sig) {
|
||||||
int ret;
|
if (sig_sem != NULL) {
|
||||||
|
Atomic::inc(&pending_signals[sig]);
|
||||||
Atomic::inc(&pending_signals[signal_number]);
|
sig_sem->signal();
|
||||||
ret = ::sema_post(&sig_sem);
|
} else {
|
||||||
assert(ret == 0, "sema_post() failed");
|
// Signal thread is not created with ReduceSignalUsage and signal_init_pd
|
||||||
|
// initialization isn't called.
|
||||||
|
assert(ReduceSignalUsage, "signal semaphore should be created");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_pending_signals(bool wait_for_signal) {
|
static int check_pending_signals() {
|
||||||
int ret;
|
int ret;
|
||||||
while (true) {
|
while (true) {
|
||||||
for (int i = 0; i < Sigexit + 1; i++) {
|
for (int i = 0; i < Sigexit + 1; i++) {
|
||||||
|
@ -2155,19 +2157,13 @@ static int check_pending_signals(bool wait_for_signal) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!wait_for_signal) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
JavaThread *thread = JavaThread::current();
|
JavaThread *thread = JavaThread::current();
|
||||||
ThreadBlockInVM tbivm(thread);
|
ThreadBlockInVM tbivm(thread);
|
||||||
|
|
||||||
bool threadIsSuspended;
|
bool threadIsSuspended;
|
||||||
do {
|
do {
|
||||||
thread->set_suspend_equivalent();
|
thread->set_suspend_equivalent();
|
||||||
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
|
sig_sem->wait();
|
||||||
while ((ret = ::sema_wait(&sig_sem)) == EINTR)
|
|
||||||
;
|
|
||||||
assert(ret == 0, "sema_wait() failed");
|
|
||||||
|
|
||||||
// were we externally suspended while we were waiting?
|
// were we externally suspended while we were waiting?
|
||||||
threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
|
threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
|
||||||
|
@ -2176,8 +2172,7 @@ static int check_pending_signals(bool wait_for_signal) {
|
||||||
// another thread suspended us. We don't want to continue running
|
// another thread suspended us. We don't want to continue running
|
||||||
// while suspended because that would surprise the thread that
|
// while suspended because that would surprise the thread that
|
||||||
// suspended us.
|
// suspended us.
|
||||||
ret = ::sema_post(&sig_sem);
|
sig_sem->signal();
|
||||||
assert(ret == 0, "sema_post() failed");
|
|
||||||
|
|
||||||
thread->java_suspend_self();
|
thread->java_suspend_self();
|
||||||
}
|
}
|
||||||
|
@ -2185,12 +2180,8 @@ static int check_pending_signals(bool wait_for_signal) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int os::signal_lookup() {
|
|
||||||
return check_pending_signals(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
int os::signal_wait() {
|
int os::signal_wait() {
|
||||||
return check_pending_signals(true);
|
return check_pending_signals();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -3599,7 +3590,7 @@ static bool do_suspend(OSThread* osthread) {
|
||||||
|
|
||||||
// managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
|
// managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
|
||||||
while (true) {
|
while (true) {
|
||||||
if (sr_semaphore.timedwait(0, 2000 * NANOSECS_PER_MILLISEC)) {
|
if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2000 * NANOSECS_PER_MILLISEC))) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// timeout
|
// timeout
|
||||||
|
@ -3633,7 +3624,7 @@ static void do_resume(OSThread* osthread) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (sr_notify(osthread) == 0) {
|
if (sr_notify(osthread) == 0) {
|
||||||
if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) {
|
if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2 * NANOSECS_PER_MILLISEC))) {
|
||||||
if (osthread->sr.is_running()) {
|
if (osthread->sr.is_running()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -62,7 +62,6 @@
|
||||||
#include "runtime/threadCritical.hpp"
|
#include "runtime/threadCritical.hpp"
|
||||||
#include "runtime/timer.hpp"
|
#include "runtime/timer.hpp"
|
||||||
#include "runtime/vm_version.hpp"
|
#include "runtime/vm_version.hpp"
|
||||||
#include "semaphore_windows.hpp"
|
|
||||||
#include "services/attachListener.hpp"
|
#include "services/attachListener.hpp"
|
||||||
#include "services/memTracker.hpp"
|
#include "services/memTracker.hpp"
|
||||||
#include "services/runtimeService.hpp"
|
#include "services/runtimeService.hpp"
|
||||||
|
@ -1845,36 +1844,6 @@ int os::get_last_error() {
|
||||||
return (int)error;
|
return (int)error;
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowsSemaphore::WindowsSemaphore(uint value) {
|
|
||||||
_semaphore = ::CreateSemaphore(NULL, value, LONG_MAX, NULL);
|
|
||||||
|
|
||||||
guarantee(_semaphore != NULL, "CreateSemaphore failed with error code: %lu", GetLastError());
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowsSemaphore::~WindowsSemaphore() {
|
|
||||||
::CloseHandle(_semaphore);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowsSemaphore::signal(uint count) {
|
|
||||||
if (count > 0) {
|
|
||||||
BOOL ret = ::ReleaseSemaphore(_semaphore, count, NULL);
|
|
||||||
|
|
||||||
assert(ret != 0, "ReleaseSemaphore failed with error code: %lu", GetLastError());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowsSemaphore::wait() {
|
|
||||||
DWORD ret = ::WaitForSingleObject(_semaphore, INFINITE);
|
|
||||||
assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
|
|
||||||
assert(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WindowsSemaphore::trywait() {
|
|
||||||
DWORD ret = ::WaitForSingleObject(_semaphore, 0);
|
|
||||||
assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
|
|
||||||
return ret == WAIT_OBJECT_0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sun.misc.Signal
|
// sun.misc.Signal
|
||||||
// NOTE that this is a workaround for an apparent kernel bug where if
|
// NOTE that this is a workaround for an apparent kernel bug where if
|
||||||
// a signal handler for SIGBREAK is installed then that signal handler
|
// a signal handler for SIGBREAK is installed then that signal handler
|
||||||
|
@ -1966,13 +1935,14 @@ int os::sigexitnum_pd() {
|
||||||
|
|
||||||
// a counter for each possible signal value, including signal_thread exit signal
|
// a counter for each possible signal value, including signal_thread exit signal
|
||||||
static volatile jint pending_signals[NSIG+1] = { 0 };
|
static volatile jint pending_signals[NSIG+1] = { 0 };
|
||||||
static HANDLE sig_sem = NULL;
|
static Semaphore* sig_sem = NULL;
|
||||||
|
|
||||||
void os::signal_init_pd() {
|
void os::signal_init_pd() {
|
||||||
// Initialize signal structures
|
// Initialize signal structures
|
||||||
memset((void*)pending_signals, 0, sizeof(pending_signals));
|
memset((void*)pending_signals, 0, sizeof(pending_signals));
|
||||||
|
|
||||||
sig_sem = ::CreateSemaphore(NULL, 0, NSIG+1, NULL);
|
// Initialize signal semaphore
|
||||||
|
sig_sem = new Semaphore();
|
||||||
|
|
||||||
// Programs embedding the VM do not want it to attempt to receive
|
// Programs embedding the VM do not want it to attempt to receive
|
||||||
// events like CTRL_LOGOFF_EVENT, which are used to implement the
|
// events like CTRL_LOGOFF_EVENT, which are used to implement the
|
||||||
|
@ -1994,17 +1964,18 @@ void os::signal_init_pd() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void os::signal_notify(int signal_number) {
|
void os::signal_notify(int sig) {
|
||||||
BOOL ret;
|
|
||||||
if (sig_sem != NULL) {
|
if (sig_sem != NULL) {
|
||||||
Atomic::inc(&pending_signals[signal_number]);
|
Atomic::inc(&pending_signals[sig]);
|
||||||
ret = ::ReleaseSemaphore(sig_sem, 1, NULL);
|
sig_sem->signal();
|
||||||
assert(ret != 0, "ReleaseSemaphore() failed");
|
} else {
|
||||||
|
// Signal thread is not created with ReduceSignalUsage and signal_init_pd
|
||||||
|
// initialization isn't called.
|
||||||
|
assert(ReduceSignalUsage, "signal semaphore should be created");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_pending_signals(bool wait_for_signal) {
|
static int check_pending_signals() {
|
||||||
DWORD ret;
|
|
||||||
while (true) {
|
while (true) {
|
||||||
for (int i = 0; i < NSIG + 1; i++) {
|
for (int i = 0; i < NSIG + 1; i++) {
|
||||||
jint n = pending_signals[i];
|
jint n = pending_signals[i];
|
||||||
|
@ -2012,10 +1983,6 @@ static int check_pending_signals(bool wait_for_signal) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!wait_for_signal) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
JavaThread *thread = JavaThread::current();
|
JavaThread *thread = JavaThread::current();
|
||||||
|
|
||||||
ThreadBlockInVM tbivm(thread);
|
ThreadBlockInVM tbivm(thread);
|
||||||
|
@ -2024,8 +1991,7 @@ static int check_pending_signals(bool wait_for_signal) {
|
||||||
do {
|
do {
|
||||||
thread->set_suspend_equivalent();
|
thread->set_suspend_equivalent();
|
||||||
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
|
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
|
||||||
ret = ::WaitForSingleObject(sig_sem, INFINITE);
|
sig_sem->wait();
|
||||||
assert(ret == WAIT_OBJECT_0, "WaitForSingleObject() failed");
|
|
||||||
|
|
||||||
// were we externally suspended while we were waiting?
|
// were we externally suspended while we were waiting?
|
||||||
threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
|
threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
|
||||||
|
@ -2034,8 +2000,7 @@ static int check_pending_signals(bool wait_for_signal) {
|
||||||
// another thread suspended us. We don't want to continue running
|
// another thread suspended us. We don't want to continue running
|
||||||
// while suspended because that would surprise the thread that
|
// while suspended because that would surprise the thread that
|
||||||
// suspended us.
|
// suspended us.
|
||||||
ret = ::ReleaseSemaphore(sig_sem, 1, NULL);
|
sig_sem->signal();
|
||||||
assert(ret != 0, "ReleaseSemaphore() failed");
|
|
||||||
|
|
||||||
thread->java_suspend_self();
|
thread->java_suspend_self();
|
||||||
}
|
}
|
||||||
|
@ -2043,12 +2008,8 @@ static int check_pending_signals(bool wait_for_signal) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int os::signal_lookup() {
|
|
||||||
return check_pending_signals(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
int os::signal_wait() {
|
int os::signal_wait() {
|
||||||
return check_pending_signals(true);
|
return check_pending_signals();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implicit OS exception handling
|
// Implicit OS exception handling
|
||||||
|
@ -4394,13 +4355,49 @@ FILE* os::open(int fd, const char* mode) {
|
||||||
|
|
||||||
// Is a (classpath) directory empty?
|
// Is a (classpath) directory empty?
|
||||||
bool os::dir_is_empty(const char* path) {
|
bool os::dir_is_empty(const char* path) {
|
||||||
WIN32_FIND_DATA fd;
|
char* search_path = (char*)os::malloc(strlen(path) + 3, mtInternal);
|
||||||
HANDLE f = FindFirstFile(path, &fd);
|
if (search_path == NULL) {
|
||||||
if (f == INVALID_HANDLE_VALUE) {
|
errno = ENOMEM;
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
FindClose(f);
|
strcpy(search_path, path);
|
||||||
return false;
|
// Append "*", or possibly "\\*", to path
|
||||||
|
if (path[1] == ':' &&
|
||||||
|
(path[2] == '\0' ||
|
||||||
|
(path[2] == '\\' && path[3] == '\0'))) {
|
||||||
|
// No '\\' needed for cases like "Z:" or "Z:\"
|
||||||
|
strcat(search_path, "*");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
strcat(search_path, "\\*");
|
||||||
|
}
|
||||||
|
errno_t err = ERROR_SUCCESS;
|
||||||
|
wchar_t* wpath = create_unc_path(search_path, err);
|
||||||
|
if (err != ERROR_SUCCESS) {
|
||||||
|
if (wpath != NULL) {
|
||||||
|
destroy_unc_path(wpath);
|
||||||
|
}
|
||||||
|
os::free(search_path);
|
||||||
|
errno = err;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
WIN32_FIND_DATAW fd;
|
||||||
|
HANDLE f = ::FindFirstFileW(wpath, &fd);
|
||||||
|
destroy_unc_path(wpath);
|
||||||
|
bool is_empty = true;
|
||||||
|
if (f != INVALID_HANDLE_VALUE) {
|
||||||
|
while (is_empty && ::FindNextFileW(f, &fd)) {
|
||||||
|
// An empty directory contains only the current directory file
|
||||||
|
// and the previous directory file.
|
||||||
|
if ((wcscmp(fd.cFileName, L".") != 0) &&
|
||||||
|
(wcscmp(fd.cFileName, L"..") != 0)) {
|
||||||
|
is_empty = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FindClose(f);
|
||||||
|
}
|
||||||
|
os::free(search_path);
|
||||||
|
return is_empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create binary file, rewriting existing file if required
|
// create binary file, rewriting existing file if required
|
||||||
|
|
60
src/hotspot/os/windows/semaphore_windows.cpp
Normal file
60
src/hotspot/os/windows/semaphore_windows.cpp
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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 "semaphore_windows.hpp"
|
||||||
|
#include "utilities/debug.hpp"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
WindowsSemaphore::WindowsSemaphore(uint value) {
|
||||||
|
_semaphore = ::CreateSemaphore(NULL, value, LONG_MAX, NULL);
|
||||||
|
|
||||||
|
guarantee(_semaphore != NULL, "CreateSemaphore failed with error code: %lu", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowsSemaphore::~WindowsSemaphore() {
|
||||||
|
::CloseHandle(_semaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowsSemaphore::signal(uint count) {
|
||||||
|
if (count > 0) {
|
||||||
|
BOOL ret = ::ReleaseSemaphore(_semaphore, count, NULL);
|
||||||
|
|
||||||
|
assert(ret != 0, "ReleaseSemaphore failed with error code: %lu", GetLastError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowsSemaphore::wait() {
|
||||||
|
DWORD ret = ::WaitForSingleObject(_semaphore, INFINITE);
|
||||||
|
assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
|
||||||
|
assert(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WindowsSemaphore::trywait() {
|
||||||
|
DWORD ret = ::WaitForSingleObject(_semaphore, 0);
|
||||||
|
assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
|
||||||
|
return ret == WAIT_OBJECT_0;
|
||||||
|
}
|
|
@ -270,7 +270,7 @@ void AOTCompiledMethod::metadata_do(void f(Metadata*)) {
|
||||||
CompiledIC *ic = CompiledIC_at(&iter);
|
CompiledIC *ic = CompiledIC_at(&iter);
|
||||||
if (ic->is_icholder_call()) {
|
if (ic->is_icholder_call()) {
|
||||||
CompiledICHolder* cichk = ic->cached_icholder();
|
CompiledICHolder* cichk = ic->cached_icholder();
|
||||||
f(cichk->holder_method());
|
f(cichk->holder_metadata());
|
||||||
f(cichk->holder_klass());
|
f(cichk->holder_klass());
|
||||||
} else {
|
} else {
|
||||||
// Get Klass* or NULL (if value is -1) from GOT cell of virtual call PLT stub.
|
// Get Klass* or NULL (if value is -1) from GOT cell of virtual call PLT stub.
|
||||||
|
|
|
@ -34,35 +34,12 @@
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "oops/fieldStreams.hpp"
|
#include "oops/fieldStreams.hpp"
|
||||||
#include "runtime/fieldDescriptor.hpp"
|
#include "runtime/fieldDescriptor.hpp"
|
||||||
#if INCLUDE_ALL_GCS
|
|
||||||
# include "gc/g1/g1SATBCardTableModRefBS.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ciInstanceKlass
|
// ciInstanceKlass
|
||||||
//
|
//
|
||||||
// This class represents a Klass* in the HotSpot virtual machine
|
// This class represents a Klass* in the HotSpot virtual machine
|
||||||
// whose Klass part in an InstanceKlass.
|
// whose Klass part in an InstanceKlass.
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// ensure_metadata_alive
|
|
||||||
//
|
|
||||||
// Ensure that the metadata wrapped by the ciMetadata is kept alive by GC.
|
|
||||||
// This is primarily useful for metadata which is considered as weak roots
|
|
||||||
// by the GC but need to be strong roots if reachable from a current compilation.
|
|
||||||
// InstanceKlass are created for both weak and strong metadata. Ensuring this metadata
|
|
||||||
// alive covers the cases where there are weak roots without performance cost.
|
|
||||||
//
|
|
||||||
static void ensure_metadata_alive(oop metadata_holder) {
|
|
||||||
#if INCLUDE_ALL_GCS
|
|
||||||
if (!UseG1GC) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (metadata_holder != NULL) {
|
|
||||||
G1SATBCardTableModRefBS::enqueue(metadata_holder);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciInstanceKlass::ciInstanceKlass
|
// ciInstanceKlass::ciInstanceKlass
|
||||||
|
@ -88,8 +65,12 @@ ciInstanceKlass::ciInstanceKlass(Klass* k) :
|
||||||
_has_injected_fields = -1;
|
_has_injected_fields = -1;
|
||||||
_implementor = NULL; // we will fill these lazily
|
_implementor = NULL; // we will fill these lazily
|
||||||
|
|
||||||
oop holder = ik->klass_holder();
|
// Ensure that the metadata wrapped by the ciMetadata is kept alive by GC.
|
||||||
ensure_metadata_alive(holder);
|
// This is primarily useful for metadata which is considered as weak roots
|
||||||
|
// by the GC but need to be strong roots if reachable from a current compilation.
|
||||||
|
// InstanceKlass are created for both weak and strong metadata. Ensuring this metadata
|
||||||
|
// alive covers the cases where there are weak roots without performance cost.
|
||||||
|
oop holder = ik->klass_holder_phantom();
|
||||||
if (ik->is_anonymous()) {
|
if (ik->is_anonymous()) {
|
||||||
// Though ciInstanceKlass records class loader oop, it's not enough to keep
|
// Though ciInstanceKlass records class loader oop, it's not enough to keep
|
||||||
// VM anonymous classes alive (loader == NULL). Klass holder should be used instead.
|
// VM anonymous classes alive (loader == NULL). Klass holder should be used instead.
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
#include "memory/metaspaceShared.hpp"
|
#include "memory/metaspaceShared.hpp"
|
||||||
#include "memory/oopFactory.hpp"
|
#include "memory/oopFactory.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "oops/access.inline.hpp"
|
||||||
#include "oops/objArrayOop.inline.hpp"
|
#include "oops/objArrayOop.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "runtime/atomic.hpp"
|
#include "runtime/atomic.hpp"
|
||||||
|
@ -75,9 +76,6 @@
|
||||||
#include "utilities/growableArray.hpp"
|
#include "utilities/growableArray.hpp"
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
#include "utilities/ostream.hpp"
|
#include "utilities/ostream.hpp"
|
||||||
#if INCLUDE_ALL_GCS
|
|
||||||
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
|
|
||||||
#endif // INCLUDE_ALL_GCS
|
|
||||||
#if INCLUDE_TRACE
|
#if INCLUDE_TRACE
|
||||||
#include "trace/tracing.hpp"
|
#include "trace/tracing.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
@ -759,18 +757,9 @@ void ClassLoaderData::remove_handle(OopHandle h) {
|
||||||
oop* ptr = h.ptr_raw();
|
oop* ptr = h.ptr_raw();
|
||||||
if (ptr != NULL) {
|
if (ptr != NULL) {
|
||||||
assert(_handles.contains(ptr), "Got unexpected handle " PTR_FORMAT, p2i(ptr));
|
assert(_handles.contains(ptr), "Got unexpected handle " PTR_FORMAT, p2i(ptr));
|
||||||
#if INCLUDE_ALL_GCS
|
// This root is not walked in safepoints, and hence requires an appropriate
|
||||||
// This barrier is used by G1 to remember the old oop values, so
|
// decorator that e.g. maintains the SATB invariant in SATB collectors.
|
||||||
// that we don't forget any objects that were live at the snapshot at
|
RootAccess<IN_CONCURRENT_ROOT>::oop_store(ptr, oop(NULL));
|
||||||
// the beginning.
|
|
||||||
if (UseG1GC) {
|
|
||||||
oop obj = *ptr;
|
|
||||||
if (obj != NULL) {
|
|
||||||
G1SATBCardTableModRefBS::enqueue(obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
*ptr = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -217,6 +217,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||||
friend class ClassLoaderDataGraphKlassIteratorAtomic;
|
friend class ClassLoaderDataGraphKlassIteratorAtomic;
|
||||||
friend class ClassLoaderDataGraphKlassIteratorStatic;
|
friend class ClassLoaderDataGraphKlassIteratorStatic;
|
||||||
friend class ClassLoaderDataGraphMetaspaceIterator;
|
friend class ClassLoaderDataGraphMetaspaceIterator;
|
||||||
|
friend class InstanceKlass;
|
||||||
friend class MetaDataFactory;
|
friend class MetaDataFactory;
|
||||||
friend class Method;
|
friend class Method;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -33,6 +33,8 @@
|
||||||
#include "code/dependencyContext.hpp"
|
#include "code/dependencyContext.hpp"
|
||||||
#include "code/pcDesc.hpp"
|
#include "code/pcDesc.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
|
#include "logging/logStream.hpp"
|
||||||
#include "memory/oopFactory.hpp"
|
#include "memory/oopFactory.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "memory/universe.inline.hpp"
|
#include "memory/universe.inline.hpp"
|
||||||
|
@ -104,52 +106,59 @@ InjectedField* JavaClasses::get_injected(Symbol* class_name, int* field_count) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool find_field(InstanceKlass* ik,
|
|
||||||
Symbol* name_symbol, Symbol* signature_symbol,
|
|
||||||
fieldDescriptor* fd,
|
|
||||||
bool is_static = false, bool allow_super = false) {
|
|
||||||
if (allow_super || is_static) {
|
|
||||||
return ik->find_field(name_symbol, signature_symbol, is_static, fd) != NULL;
|
|
||||||
} else {
|
|
||||||
return ik->find_local_field(name_symbol, signature_symbol, fd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helpful routine for computing field offsets at run time rather than hardcoding them
|
// Helpful routine for computing field offsets at run time rather than hardcoding them
|
||||||
static void
|
// Finds local fields only, including static fields. Static field offsets are from the
|
||||||
compute_offset(int &dest_offset,
|
// beginning of the mirror.
|
||||||
Klass* klass, Symbol* name_symbol, Symbol* signature_symbol,
|
static void compute_offset(int &dest_offset,
|
||||||
bool is_static = false, bool allow_super = false) {
|
InstanceKlass* ik, Symbol* name_symbol, Symbol* signature_symbol,
|
||||||
|
bool is_static = false) {
|
||||||
fieldDescriptor fd;
|
fieldDescriptor fd;
|
||||||
InstanceKlass* ik = InstanceKlass::cast(klass);
|
if (ik == NULL) {
|
||||||
if (!find_field(ik, name_symbol, signature_symbol, &fd, is_static, allow_super)) {
|
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string());
|
log_error(class)("Mismatch JDK version for field: %s type: %s", name_symbol->as_C_string(), signature_symbol->as_C_string());
|
||||||
|
vm_exit_during_initialization("Invalid layout of preloaded class");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ik->find_local_field(name_symbol, signature_symbol, &fd) || fd.is_static() != is_static) {
|
||||||
|
ResourceMark rm;
|
||||||
|
log_error(class)("Invalid layout of %s field: %s type: %s", ik->external_name(),
|
||||||
|
name_symbol->as_C_string(), signature_symbol->as_C_string());
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
ik->print();
|
// Prints all fields and offsets
|
||||||
tty->print_cr("all fields:");
|
Log(class) lt;
|
||||||
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
|
LogStream ls(lt.error());
|
||||||
tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int());
|
ik->print_on(&ls);
|
||||||
}
|
|
||||||
#endif //PRODUCT
|
#endif //PRODUCT
|
||||||
vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:class+load=info to see the origin of the problem class");
|
vm_exit_during_initialization("Invalid layout of preloaded class: use -Xlog:class+load=info to see the origin of the problem class");
|
||||||
}
|
}
|
||||||
dest_offset = fd.offset();
|
dest_offset = fd.offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Overloading to pass name as a string.
|
||||||
|
static void compute_offset(int& dest_offset, InstanceKlass* ik,
|
||||||
|
const char* name_string, Symbol* signature_symbol,
|
||||||
|
bool is_static = false) {
|
||||||
|
TempNewSymbol name = SymbolTable::probe(name_string, (int)strlen(name_string));
|
||||||
|
if (name == NULL) {
|
||||||
|
ResourceMark rm;
|
||||||
|
log_error(class)("Name %s should be in the SymbolTable since its class is loaded", name_string);
|
||||||
|
vm_exit_during_initialization("Invalid layout of preloaded class", ik->external_name());
|
||||||
|
}
|
||||||
|
compute_offset(dest_offset, ik, name, signature_symbol, is_static);
|
||||||
|
}
|
||||||
|
|
||||||
// Same as above but for "optional" offsets that might not be present in certain JDK versions
|
// Same as above but for "optional" offsets that might not be present in certain JDK versions
|
||||||
|
// Old versions should be cleaned out since Hotspot only supports the current JDK, and this
|
||||||
|
// function should be removed.
|
||||||
static void
|
static void
|
||||||
compute_optional_offset(int& dest_offset,
|
compute_optional_offset(int& dest_offset,
|
||||||
Klass* klass, Symbol* name_symbol, Symbol* signature_symbol,
|
InstanceKlass* ik, Symbol* name_symbol, Symbol* signature_symbol) {
|
||||||
bool allow_super = false) {
|
|
||||||
fieldDescriptor fd;
|
fieldDescriptor fd;
|
||||||
InstanceKlass* ik = InstanceKlass::cast(klass);
|
if (ik->find_local_field(name_symbol, signature_symbol, &fd)) {
|
||||||
if (find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) {
|
|
||||||
dest_offset = fd.offset();
|
dest_offset = fd.offset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int java_lang_String::value_offset = 0;
|
int java_lang_String::value_offset = 0;
|
||||||
int java_lang_String::hash_offset = 0;
|
int java_lang_String::hash_offset = 0;
|
||||||
int java_lang_String::coder_offset = 0;
|
int java_lang_String::coder_offset = 0;
|
||||||
|
@ -163,10 +172,10 @@ bool java_lang_String::is_instance(oop obj) {
|
||||||
void java_lang_String::compute_offsets() {
|
void java_lang_String::compute_offsets() {
|
||||||
assert(!initialized, "offsets should be initialized only once");
|
assert(!initialized, "offsets should be initialized only once");
|
||||||
|
|
||||||
Klass* k = SystemDictionary::String_klass();
|
InstanceKlass* k = SystemDictionary::String_klass();
|
||||||
compute_offset(value_offset, k, vmSymbols::value_name(), vmSymbols::byte_array_signature());
|
compute_offset(value_offset, k, vmSymbols::value_name(), vmSymbols::byte_array_signature());
|
||||||
compute_offset(hash_offset, k, vmSymbols::hash_name(), vmSymbols::int_signature());
|
compute_offset(hash_offset, k, "hash", vmSymbols::int_signature());
|
||||||
compute_offset(coder_offset, k, vmSymbols::coder_name(), vmSymbols::byte_signature());
|
compute_offset(coder_offset, k, "coder", vmSymbols::byte_signature());
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
@ -619,12 +628,12 @@ char* java_lang_String::as_utf8_string(oop java_string, int start, int len, char
|
||||||
bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
|
bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
|
||||||
assert(java_string->klass() == SystemDictionary::String_klass(),
|
assert(java_string->klass() == SystemDictionary::String_klass(),
|
||||||
"must be java_string");
|
"must be java_string");
|
||||||
typeArrayOop value = java_lang_String::value(java_string);
|
typeArrayOop value = java_lang_String::value_no_keepalive(java_string);
|
||||||
int length = java_lang_String::length(java_string);
|
int length = java_lang_String::length(java_string);
|
||||||
if (length != len) {
|
if (length != len) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool is_latin1 = java_lang_String::is_latin1(java_string);
|
bool is_latin1 = java_lang_String::is_latin1(java_string);
|
||||||
if (!is_latin1) {
|
if (!is_latin1) {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
if (value->char_at(i) != chars[i]) {
|
if (value->char_at(i) != chars[i]) {
|
||||||
|
@ -646,12 +655,12 @@ bool java_lang_String::equals(oop str1, oop str2) {
|
||||||
"must be java String");
|
"must be java String");
|
||||||
assert(str2->klass() == SystemDictionary::String_klass(),
|
assert(str2->klass() == SystemDictionary::String_klass(),
|
||||||
"must be java String");
|
"must be java String");
|
||||||
typeArrayOop value1 = java_lang_String::value(str1);
|
typeArrayOop value1 = java_lang_String::value_no_keepalive(str1);
|
||||||
int length1 = java_lang_String::length(str1);
|
int length1 = java_lang_String::length(value1);
|
||||||
bool is_latin1 = java_lang_String::is_latin1(str1);
|
bool is_latin1 = java_lang_String::is_latin1(str1);
|
||||||
typeArrayOop value2 = java_lang_String::value(str2);
|
typeArrayOop value2 = java_lang_String::value_no_keepalive(str2);
|
||||||
int length2 = java_lang_String::length(str2);
|
int length2 = java_lang_String::length(value2);
|
||||||
bool is_latin2 = java_lang_String::is_latin1(str2);
|
bool is_latin2 = java_lang_String::is_latin1(str2);
|
||||||
|
|
||||||
if ((length1 != length2) || (is_latin1 != is_latin2)) {
|
if ((length1 != length2) || (is_latin1 != is_latin2)) {
|
||||||
// Strings of different size or with different
|
// Strings of different size or with different
|
||||||
|
@ -659,7 +668,7 @@ bool java_lang_String::equals(oop str1, oop str2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int blength1 = value1->length();
|
int blength1 = value1->length();
|
||||||
for (int i = 0; i < value1->length(); i++) {
|
for (int i = 0; i < blength1; i++) {
|
||||||
if (value1->byte_at(i) != value2->byte_at(i)) {
|
if (value1->byte_at(i) != value2->byte_at(i)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -669,7 +678,7 @@ bool java_lang_String::equals(oop str1, oop str2) {
|
||||||
|
|
||||||
void java_lang_String::print(oop java_string, outputStream* st) {
|
void java_lang_String::print(oop java_string, outputStream* st) {
|
||||||
assert(java_string->klass() == SystemDictionary::String_klass(), "must be java_string");
|
assert(java_string->klass() == SystemDictionary::String_klass(), "must be java_string");
|
||||||
typeArrayOop value = java_lang_String::value(java_string);
|
typeArrayOop value = java_lang_String::value_no_keepalive(java_string);
|
||||||
|
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
// This can happen if, e.g., printing a String
|
// This can happen if, e.g., printing a String
|
||||||
|
@ -1161,25 +1170,11 @@ void java_lang_Class::compute_offsets() {
|
||||||
assert(!offsets_computed, "offsets should be initialized only once");
|
assert(!offsets_computed, "offsets should be initialized only once");
|
||||||
offsets_computed = true;
|
offsets_computed = true;
|
||||||
|
|
||||||
Klass* k = SystemDictionary::Class_klass();
|
InstanceKlass* k = SystemDictionary::Class_klass();
|
||||||
// The classRedefinedCount field is only present starting in 1.5,
|
compute_offset(classRedefinedCount_offset, k, "classRedefinedCount", vmSymbols::int_signature());
|
||||||
// so don't go fatal.
|
compute_offset(_class_loader_offset, k, "classLoader", vmSymbols::classloader_signature());
|
||||||
compute_optional_offset(classRedefinedCount_offset,
|
compute_offset(_component_mirror_offset, k, "componentType", vmSymbols::class_signature());
|
||||||
k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
|
compute_offset(_module_offset, k, "module", vmSymbols::module_signature());
|
||||||
|
|
||||||
// Needs to be optional because the old build runs Queens during bootstrapping
|
|
||||||
// and jdk8-9 doesn't have coordinated pushes yet.
|
|
||||||
compute_optional_offset(_class_loader_offset,
|
|
||||||
k, vmSymbols::classLoader_name(),
|
|
||||||
vmSymbols::classloader_signature());
|
|
||||||
|
|
||||||
compute_offset(_component_mirror_offset,
|
|
||||||
k, vmSymbols::componentType_name(),
|
|
||||||
vmSymbols::class_signature());
|
|
||||||
|
|
||||||
compute_offset(_module_offset,
|
|
||||||
k, vmSymbols::module_name(),
|
|
||||||
vmSymbols::module_signature());
|
|
||||||
|
|
||||||
// Init lock is a C union with component_mirror. Only instanceKlass mirrors have
|
// Init lock is a C union with component_mirror. Only instanceKlass mirrors have
|
||||||
// init_lock and only ArrayKlass mirrors have component_mirror. Since both are oops
|
// init_lock and only ArrayKlass mirrors have component_mirror. Since both are oops
|
||||||
|
@ -1234,24 +1229,22 @@ int java_lang_Thread::_park_event_offset = 0 ;
|
||||||
void java_lang_Thread::compute_offsets() {
|
void java_lang_Thread::compute_offsets() {
|
||||||
assert(_group_offset == 0, "offsets should be initialized only once");
|
assert(_group_offset == 0, "offsets should be initialized only once");
|
||||||
|
|
||||||
Klass* k = SystemDictionary::Thread_klass();
|
InstanceKlass* k = SystemDictionary::Thread_klass();
|
||||||
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature());
|
compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature());
|
||||||
compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature());
|
compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(),
|
||||||
compute_offset(_inheritedAccessControlContext_offset, k, vmSymbols::inheritedAccessControlContext_name(), vmSymbols::accesscontrolcontext_signature());
|
vmSymbols::classloader_signature());
|
||||||
|
compute_offset(_inheritedAccessControlContext_offset, k, vmSymbols::inheritedAccessControlContext_name(),
|
||||||
|
vmSymbols::accesscontrolcontext_signature());
|
||||||
compute_offset(_priority_offset, k, vmSymbols::priority_name(), vmSymbols::int_signature());
|
compute_offset(_priority_offset, k, vmSymbols::priority_name(), vmSymbols::int_signature());
|
||||||
compute_offset(_daemon_offset, k, vmSymbols::daemon_name(), vmSymbols::bool_signature());
|
compute_offset(_daemon_offset, k, vmSymbols::daemon_name(), vmSymbols::bool_signature());
|
||||||
compute_offset(_eetop_offset, k, vmSymbols::eetop_name(), vmSymbols::long_signature());
|
compute_offset(_eetop_offset, k, "eetop", vmSymbols::long_signature());
|
||||||
compute_offset(_stillborn_offset, k, vmSymbols::stillborn_name(), vmSymbols::bool_signature());
|
compute_offset(_stillborn_offset, k, "stillborn", vmSymbols::bool_signature());
|
||||||
// The stackSize field is only present starting in 1.4, so don't go fatal.
|
compute_offset(_stackSize_offset, k, "stackSize", vmSymbols::long_signature());
|
||||||
compute_optional_offset(_stackSize_offset, k, vmSymbols::stackSize_name(), vmSymbols::long_signature());
|
compute_offset(_tid_offset, k, "tid", vmSymbols::long_signature());
|
||||||
// The tid and thread_status fields are only present starting in 1.5, so don't go fatal.
|
compute_offset(_thread_status_offset, k, "threadStatus", vmSymbols::int_signature());
|
||||||
compute_optional_offset(_tid_offset, k, vmSymbols::thread_id_name(), vmSymbols::long_signature());
|
compute_offset(_park_blocker_offset, k, "parkBlocker", vmSymbols::object_signature());
|
||||||
compute_optional_offset(_thread_status_offset, k, vmSymbols::thread_status_name(), vmSymbols::int_signature());
|
compute_offset(_park_event_offset, k, "nativeParkEventPointer", vmSymbols::long_signature());
|
||||||
// The parkBlocker field is only present starting in 1.6, so don't go fatal.
|
|
||||||
compute_optional_offset(_park_blocker_offset, k, vmSymbols::park_blocker_name(), vmSymbols::object_signature());
|
|
||||||
compute_optional_offset(_park_event_offset, k, vmSymbols::park_event_name(),
|
|
||||||
vmSymbols::long_signature());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1486,7 +1479,7 @@ bool java_lang_ThreadGroup::is_daemon(oop java_thread_group) {
|
||||||
void java_lang_ThreadGroup::compute_offsets() {
|
void java_lang_ThreadGroup::compute_offsets() {
|
||||||
assert(_parent_offset == 0, "offsets should be initialized only once");
|
assert(_parent_offset == 0, "offsets should be initialized only once");
|
||||||
|
|
||||||
Klass* k = SystemDictionary::ThreadGroup_klass();
|
InstanceKlass* k = SystemDictionary::ThreadGroup_klass();
|
||||||
|
|
||||||
compute_offset(_parent_offset, k, vmSymbols::parent_name(), vmSymbols::threadgroup_signature());
|
compute_offset(_parent_offset, k, vmSymbols::parent_name(), vmSymbols::threadgroup_signature());
|
||||||
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
|
@ -1501,8 +1494,13 @@ void java_lang_ThreadGroup::compute_offsets() {
|
||||||
|
|
||||||
|
|
||||||
void java_lang_Throwable::compute_offsets() {
|
void java_lang_Throwable::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::Throwable_klass();
|
InstanceKlass* k = SystemDictionary::Throwable_klass();
|
||||||
compute_offset(depth_offset, k, vmSymbols::depth_name(), vmSymbols::int_signature());
|
compute_offset(backtrace_offset, k, "backtrace", vmSymbols::object_signature());
|
||||||
|
compute_offset(detailMessage_offset, k, "detailMessage", vmSymbols::string_signature());
|
||||||
|
compute_offset(stackTrace_offset, k, "stackTrace", vmSymbols::java_lang_StackTraceElement_array());
|
||||||
|
compute_offset(depth_offset, k, "depth", vmSymbols::int_signature());
|
||||||
|
compute_offset(static_unassigned_stacktrace_offset, k, "UNASSIGNED_STACK", vmSymbols::java_lang_StackTraceElement_array(),
|
||||||
|
/*is_static*/true);
|
||||||
}
|
}
|
||||||
|
|
||||||
oop java_lang_Throwable::unassigned_stacktrace() {
|
oop java_lang_Throwable::unassigned_stacktrace() {
|
||||||
|
@ -2270,23 +2268,23 @@ void java_lang_StackFrameInfo::to_stack_trace_element(Handle stackFrame, Handle
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_StackFrameInfo::compute_offsets() {
|
void java_lang_StackFrameInfo::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::StackFrameInfo_klass();
|
InstanceKlass* k = SystemDictionary::StackFrameInfo_klass();
|
||||||
compute_offset(_memberName_offset, k, vmSymbols::memberName_name(), vmSymbols::object_signature());
|
compute_offset(_memberName_offset, k, "memberName", vmSymbols::object_signature());
|
||||||
compute_offset(_bci_offset, k, vmSymbols::bci_name(), vmSymbols::short_signature());
|
compute_offset(_bci_offset, k, "bci", vmSymbols::short_signature());
|
||||||
STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_LiveStackFrameInfo::compute_offsets() {
|
void java_lang_LiveStackFrameInfo::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::LiveStackFrameInfo_klass();
|
InstanceKlass* k = SystemDictionary::LiveStackFrameInfo_klass();
|
||||||
compute_offset(_monitors_offset, k, vmSymbols::monitors_name(), vmSymbols::object_array_signature());
|
compute_offset(_monitors_offset, k, "monitors", vmSymbols::object_array_signature());
|
||||||
compute_offset(_locals_offset, k, vmSymbols::locals_name(), vmSymbols::object_array_signature());
|
compute_offset(_locals_offset, k, "locals", vmSymbols::object_array_signature());
|
||||||
compute_offset(_operands_offset, k, vmSymbols::operands_name(), vmSymbols::object_array_signature());
|
compute_offset(_operands_offset, k, "operands", vmSymbols::object_array_signature());
|
||||||
compute_offset(_mode_offset, k, vmSymbols::mode_name(), vmSymbols::int_signature());
|
compute_offset(_mode_offset, k, "mode", vmSymbols::int_signature());
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_reflect_AccessibleObject::compute_offsets() {
|
void java_lang_reflect_AccessibleObject::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::reflect_AccessibleObject_klass();
|
InstanceKlass* k = SystemDictionary::reflect_AccessibleObject_klass();
|
||||||
compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature());
|
compute_offset(override_offset, k, "override", vmSymbols::bool_signature());
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean java_lang_reflect_AccessibleObject::override(oop reflect) {
|
jboolean java_lang_reflect_AccessibleObject::override(oop reflect) {
|
||||||
|
@ -2300,7 +2298,7 @@ void java_lang_reflect_AccessibleObject::set_override(oop reflect, jboolean valu
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_reflect_Method::compute_offsets() {
|
void java_lang_reflect_Method::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::reflect_Method_klass();
|
InstanceKlass* k = SystemDictionary::reflect_Method_klass();
|
||||||
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||||
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
compute_offset(returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_signature());
|
compute_offset(returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_signature());
|
||||||
|
@ -2481,7 +2479,7 @@ void java_lang_reflect_Method::set_type_annotations(oop method, oop value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_reflect_Constructor::compute_offsets() {
|
void java_lang_reflect_Constructor::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::reflect_Constructor_klass();
|
InstanceKlass* k = SystemDictionary::reflect_Constructor_klass();
|
||||||
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||||
compute_offset(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature());
|
compute_offset(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature());
|
||||||
compute_offset(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature());
|
compute_offset(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature());
|
||||||
|
@ -2623,7 +2621,7 @@ void java_lang_reflect_Constructor::set_type_annotations(oop constructor, oop va
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_reflect_Field::compute_offsets() {
|
void java_lang_reflect_Field::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::reflect_Field_klass();
|
InstanceKlass* k = SystemDictionary::reflect_Field_klass();
|
||||||
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||||
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
compute_offset(type_offset, k, vmSymbols::type_name(), vmSymbols::class_signature());
|
compute_offset(type_offset, k, vmSymbols::type_name(), vmSymbols::class_signature());
|
||||||
|
@ -2747,22 +2745,17 @@ void java_lang_reflect_Field::set_type_annotations(oop field, oop value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void reflect_ConstantPool::compute_offsets() {
|
void reflect_ConstantPool::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::reflect_ConstantPool_klass();
|
InstanceKlass* k = SystemDictionary::reflect_ConstantPool_klass();
|
||||||
// This null test can be removed post beta
|
// The field is called ConstantPool* in the sun.reflect.ConstantPool class.
|
||||||
if (k != NULL) {
|
compute_offset(_oop_offset, k, "constantPoolOop", vmSymbols::object_signature());
|
||||||
// The field is called ConstantPool* in the sun.reflect.ConstantPool class.
|
|
||||||
compute_offset(_oop_offset, k, vmSymbols::ConstantPool_name(), vmSymbols::object_signature());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_reflect_Parameter::compute_offsets() {
|
void java_lang_reflect_Parameter::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::reflect_Parameter_klass();
|
InstanceKlass* k = SystemDictionary::reflect_Parameter_klass();
|
||||||
if(NULL != k) {
|
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
compute_offset(modifiers_offset, k, vmSymbols::modifiers_name(), vmSymbols::int_signature());
|
||||||
compute_offset(modifiers_offset, k, vmSymbols::modifiers_name(), vmSymbols::int_signature());
|
compute_offset(index_offset, k, vmSymbols::index_name(), vmSymbols::int_signature());
|
||||||
compute_offset(index_offset, k, vmSymbols::index_name(), vmSymbols::int_signature());
|
compute_offset(executable_offset, k, vmSymbols::executable_name(), vmSymbols::executable_signature());
|
||||||
compute_offset(executable_offset, k, vmSymbols::executable_name(), vmSymbols::executable_signature());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle java_lang_reflect_Parameter::create(TRAPS) {
|
Handle java_lang_reflect_Parameter::create(TRAPS) {
|
||||||
|
@ -2836,12 +2829,10 @@ Handle java_lang_Module::create(Handle loader, Handle module_name, TRAPS) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_Module::compute_offsets() {
|
void java_lang_Module::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::Module_klass();
|
InstanceKlass* k = SystemDictionary::Module_klass();
|
||||||
if(NULL != k) {
|
compute_offset(loader_offset, k, vmSymbols::loader_name(), vmSymbols::classloader_signature());
|
||||||
compute_offset(loader_offset, k, vmSymbols::loader_name(), vmSymbols::classloader_signature());
|
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
MODULE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
||||||
MODULE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2921,12 +2912,8 @@ ConstantPool* reflect_ConstantPool::get_cp(oop reflect) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() {
|
void reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass();
|
InstanceKlass* k = SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass();
|
||||||
// This null test can be removed post beta
|
compute_offset(_base_offset, k, "base", vmSymbols::object_signature());
|
||||||
if (k != NULL) {
|
|
||||||
compute_offset(_base_offset, k,
|
|
||||||
vmSymbols::base_name(), vmSymbols::object_signature());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
oop java_lang_boxing_object::initialize_and_allocate(BasicType type, TRAPS) {
|
oop java_lang_boxing_object::initialize_and_allocate(BasicType type, TRAPS) {
|
||||||
|
@ -3084,6 +3071,13 @@ bool java_lang_ref_Reference::is_referent_field(oop obj, ptrdiff_t offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support for java_lang_ref_SoftReference
|
// Support for java_lang_ref_SoftReference
|
||||||
|
//
|
||||||
|
|
||||||
|
void java_lang_ref_SoftReference::compute_offsets() {
|
||||||
|
InstanceKlass* k = SystemDictionary::SoftReference_klass();
|
||||||
|
compute_offset(timestamp_offset, k, "timestamp", vmSymbols::long_signature());
|
||||||
|
compute_offset(static_clock_offset, k, "clock", vmSymbols::long_signature(), true);
|
||||||
|
}
|
||||||
|
|
||||||
jlong java_lang_ref_SoftReference::timestamp(oop ref) {
|
jlong java_lang_ref_SoftReference::timestamp(oop ref) {
|
||||||
return ref->long_field(timestamp_offset);
|
return ref->long_field(timestamp_offset);
|
||||||
|
@ -3113,10 +3107,8 @@ oop java_lang_invoke_DirectMethodHandle::member(oop dmh) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_invoke_DirectMethodHandle::compute_offsets() {
|
void java_lang_invoke_DirectMethodHandle::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::DirectMethodHandle_klass();
|
InstanceKlass* k = SystemDictionary::DirectMethodHandle_klass();
|
||||||
if (k != NULL) {
|
compute_offset(_member_offset, k, "member", vmSymbols::java_lang_invoke_MemberName_signature());
|
||||||
compute_offset(_member_offset, k, vmSymbols::member_name(), vmSymbols::java_lang_invoke_MemberName_signature());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support for java_lang_invoke_MethodHandle
|
// Support for java_lang_invoke_MethodHandle
|
||||||
|
@ -3137,16 +3129,13 @@ int java_lang_invoke_ResolvedMethodName::_vmholder_offset;
|
||||||
int java_lang_invoke_LambdaForm::_vmentry_offset;
|
int java_lang_invoke_LambdaForm::_vmentry_offset;
|
||||||
|
|
||||||
void java_lang_invoke_MethodHandle::compute_offsets() {
|
void java_lang_invoke_MethodHandle::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::MethodHandle_klass();
|
InstanceKlass* k = SystemDictionary::MethodHandle_klass();
|
||||||
if (k != NULL) {
|
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature());
|
||||||
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature());
|
compute_offset(_form_offset, k, "form", vmSymbols::java_lang_invoke_LambdaForm_signature());
|
||||||
compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_lang_invoke_LambdaForm_signature());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_invoke_MemberName::compute_offsets() {
|
void java_lang_invoke_MemberName::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::MemberName_klass();
|
InstanceKlass* k = SystemDictionary::MemberName_klass();
|
||||||
assert (k != NULL, "jdk mismatch");
|
|
||||||
compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||||
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature());
|
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature());
|
||||||
|
@ -3156,15 +3145,15 @@ void java_lang_invoke_MemberName::compute_offsets() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_invoke_ResolvedMethodName::compute_offsets() {
|
void java_lang_invoke_ResolvedMethodName::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::ResolvedMethodName_klass();
|
InstanceKlass* k = SystemDictionary::ResolvedMethodName_klass();
|
||||||
assert(k != NULL, "jdk mismatch");
|
assert(k != NULL, "jdk mismatch");
|
||||||
RESOLVEDMETHOD_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
RESOLVEDMETHOD_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_invoke_LambdaForm::compute_offsets() {
|
void java_lang_invoke_LambdaForm::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::LambdaForm_klass();
|
InstanceKlass* k = SystemDictionary::LambdaForm_klass();
|
||||||
assert (k != NULL, "jdk mismatch");
|
assert (k != NULL, "jdk mismatch");
|
||||||
compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::java_lang_invoke_MemberName_signature());
|
compute_offset(_vmentry_offset, k, "vmentry", vmSymbols::java_lang_invoke_MemberName_signature());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool java_lang_invoke_LambdaForm::is_instance(oop obj) {
|
bool java_lang_invoke_LambdaForm::is_instance(oop obj) {
|
||||||
|
@ -3305,11 +3294,9 @@ int java_lang_invoke_MethodType::_rtype_offset;
|
||||||
int java_lang_invoke_MethodType::_ptypes_offset;
|
int java_lang_invoke_MethodType::_ptypes_offset;
|
||||||
|
|
||||||
void java_lang_invoke_MethodType::compute_offsets() {
|
void java_lang_invoke_MethodType::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::MethodType_klass();
|
InstanceKlass* k = SystemDictionary::MethodType_klass();
|
||||||
if (k != NULL) {
|
compute_offset(_rtype_offset, k, "rtype", vmSymbols::class_signature());
|
||||||
compute_offset(_rtype_offset, k, vmSymbols::rtype_name(), vmSymbols::class_signature());
|
compute_offset(_ptypes_offset, k, "ptypes", vmSymbols::class_array_signature());
|
||||||
compute_offset(_ptypes_offset, k, vmSymbols::ptypes_name(), vmSymbols::class_array_signature());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_lang_invoke_MethodType::print_signature(oop mt, outputStream* st) {
|
void java_lang_invoke_MethodType::print_signature(oop mt, outputStream* st) {
|
||||||
|
@ -3392,12 +3379,10 @@ int java_lang_invoke_CallSite::_target_offset;
|
||||||
int java_lang_invoke_CallSite::_context_offset;
|
int java_lang_invoke_CallSite::_context_offset;
|
||||||
|
|
||||||
void java_lang_invoke_CallSite::compute_offsets() {
|
void java_lang_invoke_CallSite::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::CallSite_klass();
|
InstanceKlass* k = SystemDictionary::CallSite_klass();
|
||||||
if (k != NULL) {
|
compute_offset(_target_offset, k, "target", vmSymbols::java_lang_invoke_MethodHandle_signature());
|
||||||
compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature());
|
compute_offset(_context_offset, k, "context",
|
||||||
compute_offset(_context_offset, k, vmSymbols::context_name(),
|
vmSymbols::java_lang_invoke_MethodHandleNatives_CallSiteContext_signature());
|
||||||
vmSymbols::java_lang_invoke_MethodHandleNatives_CallSiteContext_signature());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
oop java_lang_invoke_CallSite::context(oop call_site) {
|
oop java_lang_invoke_CallSite::context(oop call_site) {
|
||||||
|
@ -3412,10 +3397,8 @@ oop java_lang_invoke_CallSite::context(oop call_site) {
|
||||||
int java_lang_invoke_MethodHandleNatives_CallSiteContext::_vmdependencies_offset;
|
int java_lang_invoke_MethodHandleNatives_CallSiteContext::_vmdependencies_offset;
|
||||||
|
|
||||||
void java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets() {
|
void java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::Context_klass();
|
InstanceKlass* k = SystemDictionary::Context_klass();
|
||||||
if (k != NULL) {
|
CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
||||||
CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DependencyContext java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(oop call_site) {
|
DependencyContext java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(oop call_site) {
|
||||||
|
@ -3434,28 +3417,12 @@ int java_security_AccessControlContext::_isAuthorized_offset = -1;
|
||||||
|
|
||||||
void java_security_AccessControlContext::compute_offsets() {
|
void java_security_AccessControlContext::compute_offsets() {
|
||||||
assert(_isPrivileged_offset == 0, "offsets should be initialized only once");
|
assert(_isPrivileged_offset == 0, "offsets should be initialized only once");
|
||||||
fieldDescriptor fd;
|
InstanceKlass* k = SystemDictionary::AccessControlContext_klass();
|
||||||
InstanceKlass* ik = SystemDictionary::AccessControlContext_klass();
|
|
||||||
|
|
||||||
if (!ik->find_local_field(vmSymbols::context_name(), vmSymbols::protectiondomain_signature(), &fd)) {
|
compute_offset(_context_offset, k, "context", vmSymbols::protectiondomain_signature());
|
||||||
fatal("Invalid layout of java.security.AccessControlContext");
|
compute_offset(_privilegedContext_offset, k, "privilegedContext", vmSymbols::accesscontrolcontext_signature());
|
||||||
}
|
compute_offset(_isPrivileged_offset, k, "isPrivileged", vmSymbols::bool_signature());
|
||||||
_context_offset = fd.offset();
|
compute_offset(_isAuthorized_offset, k, "isAuthorized", vmSymbols::bool_signature());
|
||||||
|
|
||||||
if (!ik->find_local_field(vmSymbols::privilegedContext_name(), vmSymbols::accesscontrolcontext_signature(), &fd)) {
|
|
||||||
fatal("Invalid layout of java.security.AccessControlContext");
|
|
||||||
}
|
|
||||||
_privilegedContext_offset = fd.offset();
|
|
||||||
|
|
||||||
if (!ik->find_local_field(vmSymbols::isPrivileged_name(), vmSymbols::bool_signature(), &fd)) {
|
|
||||||
fatal("Invalid layout of java.security.AccessControlContext");
|
|
||||||
}
|
|
||||||
_isPrivileged_offset = fd.offset();
|
|
||||||
|
|
||||||
// The offset may not be present for bootstrapping with older JDK.
|
|
||||||
if (ik->find_local_field(vmSymbols::isAuthorized_name(), vmSymbols::bool_signature(), &fd)) {
|
|
||||||
_isAuthorized_offset = fd.offset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3504,16 +3471,17 @@ void java_lang_ClassLoader::compute_offsets() {
|
||||||
assert(!offsets_computed, "offsets should be initialized only once");
|
assert(!offsets_computed, "offsets should be initialized only once");
|
||||||
offsets_computed = true;
|
offsets_computed = true;
|
||||||
|
|
||||||
// The field indicating parallelCapable (parallelLockMap) is only present starting in 7,
|
InstanceKlass* k1 = SystemDictionary::ClassLoader_klass();
|
||||||
Klass* k1 = SystemDictionary::ClassLoader_klass();
|
compute_offset(parallelCapable_offset,
|
||||||
compute_optional_offset(parallelCapable_offset,
|
k1, "parallelLockMap", vmSymbols::concurrenthashmap_signature());
|
||||||
k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
|
|
||||||
|
|
||||||
compute_offset(name_offset,
|
compute_offset(name_offset,
|
||||||
k1, vmSymbols::name_name(), vmSymbols::string_signature());
|
k1, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
|
|
||||||
compute_offset(unnamedModule_offset,
|
compute_offset(unnamedModule_offset,
|
||||||
k1, vmSymbols::unnamedModule_name(), vmSymbols::module_signature());
|
k1, "unnamedModule", vmSymbols::module_signature());
|
||||||
|
|
||||||
|
compute_offset(parent_offset, k1, "parent", vmSymbols::classloader_signature());
|
||||||
|
|
||||||
CLASSLOADER_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
CLASSLOADER_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
|
||||||
}
|
}
|
||||||
|
@ -3600,19 +3568,18 @@ oop java_lang_ClassLoader::unnamedModule(oop loader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support for java_lang_System
|
// Support for java_lang_System
|
||||||
int java_lang_System::in_offset_in_bytes() {
|
//
|
||||||
return (InstanceMirrorKlass::offset_of_static_fields() + static_in_offset);
|
void java_lang_System::compute_offsets() {
|
||||||
|
InstanceKlass* k = SystemDictionary::System_klass();
|
||||||
|
compute_offset(static_in_offset, k, "in", vmSymbols::input_stream_signature(), true);
|
||||||
|
compute_offset(static_out_offset, k, "out", vmSymbols::print_stream_signature(), true);
|
||||||
|
compute_offset(static_err_offset, k, "err", vmSymbols::print_stream_signature(), true);
|
||||||
|
compute_offset(static_security_offset, k, "security", vmSymbols::security_manager_signature(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int java_lang_System::in_offset_in_bytes() { return static_in_offset; }
|
||||||
int java_lang_System::out_offset_in_bytes() {
|
int java_lang_System::out_offset_in_bytes() { return static_out_offset; }
|
||||||
return (InstanceMirrorKlass::offset_of_static_fields() + static_out_offset);
|
int java_lang_System::err_offset_in_bytes() { return static_err_offset; }
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int java_lang_System::err_offset_in_bytes() {
|
|
||||||
return (InstanceMirrorKlass::offset_of_static_fields() + static_err_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool java_lang_System::has_security_manager() {
|
bool java_lang_System::has_security_manager() {
|
||||||
|
@ -3682,7 +3649,6 @@ int java_lang_ref_Reference::referent_offset;
|
||||||
int java_lang_ref_Reference::queue_offset;
|
int java_lang_ref_Reference::queue_offset;
|
||||||
int java_lang_ref_Reference::next_offset;
|
int java_lang_ref_Reference::next_offset;
|
||||||
int java_lang_ref_Reference::discovered_offset;
|
int java_lang_ref_Reference::discovered_offset;
|
||||||
int java_lang_ref_Reference::number_of_fake_oop_fields;
|
|
||||||
int java_lang_ref_SoftReference::timestamp_offset;
|
int java_lang_ref_SoftReference::timestamp_offset;
|
||||||
int java_lang_ref_SoftReference::static_clock_offset;
|
int java_lang_ref_SoftReference::static_clock_offset;
|
||||||
int java_lang_ClassLoader::parent_offset;
|
int java_lang_ClassLoader::parent_offset;
|
||||||
|
@ -3717,6 +3683,17 @@ int reflect_UnsafeStaticFieldAccessorImpl::_base_offset;
|
||||||
|
|
||||||
|
|
||||||
// Support for java_lang_StackTraceElement
|
// Support for java_lang_StackTraceElement
|
||||||
|
void java_lang_StackTraceElement::compute_offsets() {
|
||||||
|
InstanceKlass* k = SystemDictionary::StackTraceElement_klass();
|
||||||
|
compute_offset(declaringClassObject_offset, k, "declaringClassObject", vmSymbols::class_signature());
|
||||||
|
compute_offset(classLoaderName_offset, k, "classLoaderName", vmSymbols::string_signature());
|
||||||
|
compute_offset(moduleName_offset, k, "moduleName", vmSymbols::string_signature());
|
||||||
|
compute_offset(moduleVersion_offset, k, "moduleVersion", vmSymbols::string_signature());
|
||||||
|
compute_offset(declaringClass_offset, k, "declaringClass", vmSymbols::string_signature());
|
||||||
|
compute_offset(methodName_offset, k, "methodName", vmSymbols::string_signature());
|
||||||
|
compute_offset(fileName_offset, k, "fileName", vmSymbols::string_signature());
|
||||||
|
compute_offset(lineNumber_offset, k, "lineNumber", vmSymbols::int_signature());
|
||||||
|
}
|
||||||
|
|
||||||
void java_lang_StackTraceElement::set_fileName(oop element, oop value) {
|
void java_lang_StackTraceElement::set_fileName(oop element, oop value) {
|
||||||
element->obj_field_put(fileName_offset, value);
|
element->obj_field_put(fileName_offset, value);
|
||||||
|
@ -3776,6 +3753,16 @@ void java_lang_LiveStackFrameInfo::set_mode(oop element, int value) {
|
||||||
|
|
||||||
// Support for java Assertions - java_lang_AssertionStatusDirectives.
|
// Support for java Assertions - java_lang_AssertionStatusDirectives.
|
||||||
|
|
||||||
|
void java_lang_AssertionStatusDirectives::compute_offsets() {
|
||||||
|
InstanceKlass* k = SystemDictionary::AssertionStatusDirectives_klass();
|
||||||
|
compute_offset(classes_offset, k, "classes", vmSymbols::string_array_signature());
|
||||||
|
compute_offset(classEnabled_offset, k, "classEnabled", vmSymbols::bool_array_signature());
|
||||||
|
compute_offset(packages_offset, k, "packages", vmSymbols::string_array_signature());
|
||||||
|
compute_offset(packageEnabled_offset, k, "packageEnabled", vmSymbols::bool_array_signature());
|
||||||
|
compute_offset(deflt_offset, k, "deflt", vmSymbols::bool_signature());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void java_lang_AssertionStatusDirectives::set_classes(oop o, oop val) {
|
void java_lang_AssertionStatusDirectives::set_classes(oop o, oop val) {
|
||||||
o->obj_field_put(classes_offset, val);
|
o->obj_field_put(classes_offset, val);
|
||||||
}
|
}
|
||||||
|
@ -3804,18 +3791,18 @@ int java_nio_Buffer::limit_offset() {
|
||||||
|
|
||||||
|
|
||||||
void java_nio_Buffer::compute_offsets() {
|
void java_nio_Buffer::compute_offsets() {
|
||||||
Klass* k = SystemDictionary::nio_Buffer_klass();
|
InstanceKlass* k = SystemDictionary::nio_Buffer_klass();
|
||||||
assert(k != NULL, "must be loaded in 1.4+");
|
assert(k != NULL, "must be loaded in 1.4+");
|
||||||
compute_offset(_limit_offset, k, vmSymbols::limit_name(), vmSymbols::int_signature());
|
compute_offset(_limit_offset, k, "limit", vmSymbols::int_signature());
|
||||||
}
|
}
|
||||||
|
|
||||||
void java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(TRAPS) {
|
void java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(TRAPS) {
|
||||||
if (_owner_offset != 0) return;
|
if (_owner_offset != 0) return;
|
||||||
|
|
||||||
SystemDictionary::load_abstract_ownable_synchronizer_klass(CHECK);
|
SystemDictionary::load_abstract_ownable_synchronizer_klass(CHECK);
|
||||||
Klass* k = SystemDictionary::abstract_ownable_synchronizer_klass();
|
InstanceKlass* k = SystemDictionary::abstract_ownable_synchronizer_klass();
|
||||||
compute_offset(_owner_offset, k,
|
compute_offset(_owner_offset, k,
|
||||||
vmSymbols::exclusive_owner_thread_name(), vmSymbols::thread_signature());
|
"exclusiveOwnerThread", vmSymbols::thread_signature());
|
||||||
}
|
}
|
||||||
|
|
||||||
oop java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(oop obj) {
|
oop java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(oop obj) {
|
||||||
|
@ -3823,71 +3810,37 @@ oop java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(
|
||||||
return obj->obj_field(_owner_offset);
|
return obj->obj_field(_owner_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int member_offset(int hardcoded_offset) {
|
||||||
|
return (hardcoded_offset * heapOopSize) + instanceOopDesc::base_offset_in_bytes();
|
||||||
|
}
|
||||||
|
|
||||||
// Compute hard-coded offsets
|
// Compute hard-coded offsets
|
||||||
// Invoked before SystemDictionary::initialize, so pre-loaded classes
|
// Invoked before SystemDictionary::initialize, so pre-loaded classes
|
||||||
// are not available to determine the offset_of_static_fields.
|
// are not available to determine the offset_of_static_fields.
|
||||||
void JavaClasses::compute_hard_coded_offsets() {
|
void JavaClasses::compute_hard_coded_offsets() {
|
||||||
const int x = heapOopSize;
|
|
||||||
const int header = instanceOopDesc::base_offset_in_bytes();
|
|
||||||
|
|
||||||
// Throwable Class
|
|
||||||
java_lang_Throwable::backtrace_offset = java_lang_Throwable::hc_backtrace_offset * x + header;
|
|
||||||
java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header;
|
|
||||||
java_lang_Throwable::stackTrace_offset = java_lang_Throwable::hc_stackTrace_offset * x + header;
|
|
||||||
java_lang_Throwable::static_unassigned_stacktrace_offset = java_lang_Throwable::hc_static_unassigned_stacktrace_offset * x;
|
|
||||||
|
|
||||||
// java_lang_boxing_object
|
// java_lang_boxing_object
|
||||||
java_lang_boxing_object::value_offset = java_lang_boxing_object::hc_value_offset + header;
|
java_lang_boxing_object::value_offset = member_offset(java_lang_boxing_object::hc_value_offset);
|
||||||
java_lang_boxing_object::long_value_offset = align_up((java_lang_boxing_object::hc_value_offset + header), BytesPerLong);
|
java_lang_boxing_object::long_value_offset = align_up(member_offset(java_lang_boxing_object::hc_value_offset), BytesPerLong);
|
||||||
|
|
||||||
// java_lang_ref_Reference:
|
|
||||||
java_lang_ref_Reference::referent_offset = java_lang_ref_Reference::hc_referent_offset * x + header;
|
|
||||||
java_lang_ref_Reference::queue_offset = java_lang_ref_Reference::hc_queue_offset * x + header;
|
|
||||||
java_lang_ref_Reference::next_offset = java_lang_ref_Reference::hc_next_offset * x + header;
|
|
||||||
java_lang_ref_Reference::discovered_offset = java_lang_ref_Reference::hc_discovered_offset * x + header;
|
|
||||||
// Artificial fields for java_lang_ref_Reference
|
|
||||||
// The first field is for the discovered field added in 1.4
|
|
||||||
java_lang_ref_Reference::number_of_fake_oop_fields = 1;
|
|
||||||
|
|
||||||
// java_lang_ref_SoftReference Class
|
|
||||||
java_lang_ref_SoftReference::timestamp_offset = align_up((java_lang_ref_SoftReference::hc_timestamp_offset * x + header), BytesPerLong);
|
|
||||||
// Don't multiply static fields because they are always in wordSize units
|
|
||||||
java_lang_ref_SoftReference::static_clock_offset = java_lang_ref_SoftReference::hc_static_clock_offset * x;
|
|
||||||
|
|
||||||
// java_lang_ClassLoader
|
|
||||||
java_lang_ClassLoader::parent_offset = java_lang_ClassLoader::hc_parent_offset * x + header;
|
|
||||||
|
|
||||||
// java_lang_System
|
|
||||||
java_lang_System::static_in_offset = java_lang_System::hc_static_in_offset * x;
|
|
||||||
java_lang_System::static_out_offset = java_lang_System::hc_static_out_offset * x;
|
|
||||||
java_lang_System::static_err_offset = java_lang_System::hc_static_err_offset * x;
|
|
||||||
java_lang_System::static_security_offset = java_lang_System::hc_static_security_offset * x;
|
|
||||||
|
|
||||||
// java_lang_StackTraceElement
|
|
||||||
java_lang_StackTraceElement::declaringClassObject_offset = java_lang_StackTraceElement::hc_declaringClassObject_offset * x + header;
|
|
||||||
java_lang_StackTraceElement::classLoaderName_offset = java_lang_StackTraceElement::hc_classLoaderName_offset * x + header;
|
|
||||||
java_lang_StackTraceElement::moduleName_offset = java_lang_StackTraceElement::hc_moduleName_offset * x + header;
|
|
||||||
java_lang_StackTraceElement::moduleVersion_offset = java_lang_StackTraceElement::hc_moduleVersion_offset * x + header;
|
|
||||||
java_lang_StackTraceElement::declaringClass_offset = java_lang_StackTraceElement::hc_declaringClass_offset * x + header;
|
|
||||||
java_lang_StackTraceElement::methodName_offset = java_lang_StackTraceElement::hc_methodName_offset * x + header;
|
|
||||||
java_lang_StackTraceElement::fileName_offset = java_lang_StackTraceElement::hc_fileName_offset * x + header;
|
|
||||||
java_lang_StackTraceElement::lineNumber_offset = java_lang_StackTraceElement::hc_lineNumber_offset * x + header;
|
|
||||||
java_lang_AssertionStatusDirectives::classes_offset = java_lang_AssertionStatusDirectives::hc_classes_offset * x + header;
|
|
||||||
java_lang_AssertionStatusDirectives::classEnabled_offset = java_lang_AssertionStatusDirectives::hc_classEnabled_offset * x + header;
|
|
||||||
java_lang_AssertionStatusDirectives::packages_offset = java_lang_AssertionStatusDirectives::hc_packages_offset * x + header;
|
|
||||||
java_lang_AssertionStatusDirectives::packageEnabled_offset = java_lang_AssertionStatusDirectives::hc_packageEnabled_offset * x + header;
|
|
||||||
java_lang_AssertionStatusDirectives::deflt_offset = java_lang_AssertionStatusDirectives::hc_deflt_offset * x + header;
|
|
||||||
|
|
||||||
|
// java_lang_ref_Reference
|
||||||
|
java_lang_ref_Reference::referent_offset = member_offset(java_lang_ref_Reference::hc_referent_offset);
|
||||||
|
java_lang_ref_Reference::queue_offset = member_offset(java_lang_ref_Reference::hc_queue_offset);
|
||||||
|
java_lang_ref_Reference::next_offset = member_offset(java_lang_ref_Reference::hc_next_offset);
|
||||||
|
java_lang_ref_Reference::discovered_offset = member_offset(java_lang_ref_Reference::hc_discovered_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Compute non-hard-coded field offsets of all the classes in this file
|
// Compute non-hard-coded field offsets of all the classes in this file
|
||||||
void JavaClasses::compute_offsets() {
|
void JavaClasses::compute_offsets() {
|
||||||
// java_lang_Class::compute_offsets was called earlier in bootstrap
|
// java_lang_Class::compute_offsets was called earlier in bootstrap
|
||||||
|
java_lang_System::compute_offsets();
|
||||||
java_lang_ClassLoader::compute_offsets();
|
java_lang_ClassLoader::compute_offsets();
|
||||||
java_lang_Throwable::compute_offsets();
|
java_lang_Throwable::compute_offsets();
|
||||||
java_lang_Thread::compute_offsets();
|
java_lang_Thread::compute_offsets();
|
||||||
java_lang_ThreadGroup::compute_offsets();
|
java_lang_ThreadGroup::compute_offsets();
|
||||||
|
java_lang_AssertionStatusDirectives::compute_offsets();
|
||||||
|
java_lang_ref_SoftReference::compute_offsets();
|
||||||
java_lang_invoke_MethodHandle::compute_offsets();
|
java_lang_invoke_MethodHandle::compute_offsets();
|
||||||
java_lang_invoke_DirectMethodHandle::compute_offsets();
|
java_lang_invoke_DirectMethodHandle::compute_offsets();
|
||||||
java_lang_invoke_MemberName::compute_offsets();
|
java_lang_invoke_MemberName::compute_offsets();
|
||||||
|
@ -3910,6 +3863,7 @@ void JavaClasses::compute_offsets() {
|
||||||
reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
|
reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
|
||||||
java_lang_reflect_Parameter::compute_offsets();
|
java_lang_reflect_Parameter::compute_offsets();
|
||||||
java_lang_Module::compute_offsets();
|
java_lang_Module::compute_offsets();
|
||||||
|
java_lang_StackTraceElement::compute_offsets();
|
||||||
java_lang_StackFrameInfo::compute_offsets();
|
java_lang_StackFrameInfo::compute_offsets();
|
||||||
java_lang_LiveStackFrameInfo::compute_offsets();
|
java_lang_LiveStackFrameInfo::compute_offsets();
|
||||||
|
|
||||||
|
@ -3947,62 +3901,6 @@ bool JavaClasses::check_offset(const char *klass_name, int hardcoded_offset, con
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool JavaClasses::check_static_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) {
|
|
||||||
EXCEPTION_MARK;
|
|
||||||
fieldDescriptor fd;
|
|
||||||
TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH);
|
|
||||||
Klass* k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH);
|
|
||||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
|
||||||
TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH);
|
|
||||||
TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig, CATCH);
|
|
||||||
if (!ik->find_local_field(f_name, f_sig, &fd)) {
|
|
||||||
tty->print_cr("Static field %s.%s not found", klass_name, field_name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!fd.is_static()) {
|
|
||||||
tty->print_cr("Static field %s.%s appears to be nonstatic", klass_name, field_name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (fd.offset() == hardcoded_offset + InstanceMirrorKlass::offset_of_static_fields()) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
tty->print_cr("Offset of static field %s.%s is hardcoded as %d but should really be %d.", klass_name, field_name, hardcoded_offset, fd.offset() - InstanceMirrorKlass::offset_of_static_fields());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool JavaClasses::check_constant(const char *klass_name, int hardcoded_constant, const char *field_name, const char* field_sig) {
|
|
||||||
EXCEPTION_MARK;
|
|
||||||
fieldDescriptor fd;
|
|
||||||
TempNewSymbol klass_sym = SymbolTable::new_symbol(klass_name, CATCH);
|
|
||||||
Klass* k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH);
|
|
||||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
|
||||||
TempNewSymbol f_name = SymbolTable::new_symbol(field_name, CATCH);
|
|
||||||
TempNewSymbol f_sig = SymbolTable::new_symbol(field_sig, CATCH);
|
|
||||||
if (!ik->find_local_field(f_name, f_sig, &fd)) {
|
|
||||||
tty->print_cr("Static field %s.%s not found", klass_name, field_name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!fd.is_static() || !fd.has_initial_value()) {
|
|
||||||
tty->print_cr("Static field %s.%s appears to be non-constant", klass_name, field_name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!fd.initial_value_tag().is_int()) {
|
|
||||||
tty->print_cr("Static field %s.%s is not an int", klass_name, field_name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
jint field_value = fd.int_initial_value();
|
|
||||||
if (field_value == hardcoded_constant) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
tty->print_cr("Constant value of static field %s.%s is hardcoded as %d but should really be %d.", klass_name, field_name, hardcoded_constant, field_value);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Check the hard-coded field offsets of all the classes in this file
|
// Check the hard-coded field offsets of all the classes in this file
|
||||||
|
|
||||||
void JavaClasses::check_offsets() {
|
void JavaClasses::check_offsets() {
|
||||||
|
@ -4014,31 +3912,6 @@ void JavaClasses::check_offsets() {
|
||||||
#define CHECK_LONG_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \
|
#define CHECK_LONG_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \
|
||||||
valid &= check_offset(klass_name, cpp_klass_name :: long_ ## field_name ## _offset, #field_name, field_sig)
|
valid &= check_offset(klass_name, cpp_klass_name :: long_ ## field_name ## _offset, #field_name, field_sig)
|
||||||
|
|
||||||
#define CHECK_STATIC_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \
|
|
||||||
valid &= check_static_offset(klass_name, cpp_klass_name :: static_ ## field_name ## _offset, #field_name, field_sig)
|
|
||||||
|
|
||||||
#define CHECK_CONSTANT(klass_name, cpp_klass_name, field_name, field_sig) \
|
|
||||||
valid &= check_constant(klass_name, cpp_klass_name :: field_name, #field_name, field_sig)
|
|
||||||
|
|
||||||
// java.lang.String
|
|
||||||
|
|
||||||
CHECK_OFFSET("java/lang/String", java_lang_String, value, "[B");
|
|
||||||
CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
|
|
||||||
CHECK_OFFSET("java/lang/String", java_lang_String, coder, "B");
|
|
||||||
|
|
||||||
// java.lang.Class
|
|
||||||
|
|
||||||
// Fake fields
|
|
||||||
// CHECK_OFFSET("java/lang/Class", java_lang_Class, klass); // %%% this needs to be checked
|
|
||||||
// CHECK_OFFSET("java/lang/Class", java_lang_Class, array_klass); // %%% this needs to be checked
|
|
||||||
|
|
||||||
// java.lang.Throwable
|
|
||||||
|
|
||||||
CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, backtrace, "Ljava/lang/Object;");
|
|
||||||
CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, detailMessage, "Ljava/lang/String;");
|
|
||||||
CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, stackTrace, "[Ljava/lang/StackTraceElement;");
|
|
||||||
CHECK_OFFSET("java/lang/Throwable", java_lang_Throwable, depth, "I");
|
|
||||||
|
|
||||||
// Boxed primitive objects (java_lang_boxing_object)
|
// Boxed primitive objects (java_lang_boxing_object)
|
||||||
|
|
||||||
CHECK_OFFSET("java/lang/Boolean", java_lang_boxing_object, value, "Z");
|
CHECK_OFFSET("java/lang/Boolean", java_lang_boxing_object, value, "Z");
|
||||||
|
@ -4050,28 +3923,6 @@ void JavaClasses::check_offsets() {
|
||||||
CHECK_OFFSET("java/lang/Integer", java_lang_boxing_object, value, "I");
|
CHECK_OFFSET("java/lang/Integer", java_lang_boxing_object, value, "I");
|
||||||
CHECK_LONG_OFFSET("java/lang/Long", java_lang_boxing_object, value, "J");
|
CHECK_LONG_OFFSET("java/lang/Long", java_lang_boxing_object, value, "J");
|
||||||
|
|
||||||
// java.lang.ClassLoader
|
|
||||||
|
|
||||||
CHECK_OFFSET("java/lang/ClassLoader", java_lang_ClassLoader, parent, "Ljava/lang/ClassLoader;");
|
|
||||||
|
|
||||||
// java.lang.System
|
|
||||||
|
|
||||||
CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, in, "Ljava/io/InputStream;");
|
|
||||||
CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, out, "Ljava/io/PrintStream;");
|
|
||||||
CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, err, "Ljava/io/PrintStream;");
|
|
||||||
CHECK_STATIC_OFFSET("java/lang/System", java_lang_System, security, "Ljava/lang/SecurityManager;");
|
|
||||||
|
|
||||||
// java.lang.StackTraceElement
|
|
||||||
|
|
||||||
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, declaringClassObject, "Ljava/lang/Class;");
|
|
||||||
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, classLoaderName, "Ljava/lang/String;");
|
|
||||||
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, moduleName, "Ljava/lang/String;");
|
|
||||||
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, moduleVersion, "Ljava/lang/String;");
|
|
||||||
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, declaringClass, "Ljava/lang/String;");
|
|
||||||
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, methodName, "Ljava/lang/String;");
|
|
||||||
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, fileName, "Ljava/lang/String;");
|
|
||||||
CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, lineNumber, "I");
|
|
||||||
|
|
||||||
// java.lang.ref.Reference
|
// java.lang.ref.Reference
|
||||||
|
|
||||||
CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, referent, "Ljava/lang/Object;");
|
CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, referent, "Ljava/lang/Object;");
|
||||||
|
@ -4080,28 +3931,6 @@ void JavaClasses::check_offsets() {
|
||||||
// Fake field
|
// Fake field
|
||||||
//CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, discovered, "Ljava/lang/ref/Reference;");
|
//CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, discovered, "Ljava/lang/ref/Reference;");
|
||||||
|
|
||||||
// java.lang.ref.SoftReference
|
|
||||||
|
|
||||||
CHECK_OFFSET("java/lang/ref/SoftReference", java_lang_ref_SoftReference, timestamp, "J");
|
|
||||||
CHECK_STATIC_OFFSET("java/lang/ref/SoftReference", java_lang_ref_SoftReference, clock, "J");
|
|
||||||
|
|
||||||
// java.lang.AssertionStatusDirectives
|
|
||||||
//
|
|
||||||
// The CheckAssertionStatusDirectives boolean can be removed from here and
|
|
||||||
// globals.hpp after the AssertionStatusDirectives class has been integrated
|
|
||||||
// into merlin "for some time." Without it, the vm will fail with early
|
|
||||||
// merlin builds.
|
|
||||||
|
|
||||||
if (CheckAssertionStatusDirectives) {
|
|
||||||
const char* nm = "java/lang/AssertionStatusDirectives";
|
|
||||||
const char* sig = "[Ljava/lang/String;";
|
|
||||||
CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, classes, sig);
|
|
||||||
CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, classEnabled, "[Z");
|
|
||||||
CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, packages, sig);
|
|
||||||
CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, packageEnabled, "[Z");
|
|
||||||
CHECK_OFFSET(nm, java_lang_AssertionStatusDirectives, deflt, "Z");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid) vm_exit_during_initialization("Hard-coded field offset verification failed");
|
if (!valid) vm_exit_during_initialization("Hard-coded field offset verification failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -102,6 +102,7 @@ class java_lang_String : AllStatic {
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
static inline typeArrayOop value(oop java_string);
|
static inline typeArrayOop value(oop java_string);
|
||||||
|
static inline typeArrayOop value_no_keepalive(oop java_string);
|
||||||
static inline unsigned int hash(oop java_string);
|
static inline unsigned int hash(oop java_string);
|
||||||
static inline bool is_latin1(oop java_string);
|
static inline bool is_latin1(oop java_string);
|
||||||
static inline int length(oop java_string);
|
static inline int length(oop java_string);
|
||||||
|
@ -444,9 +445,6 @@ class java_lang_Throwable: AllStatic {
|
||||||
hc_cause_offset = 2, // New since 1.4
|
hc_cause_offset = 2, // New since 1.4
|
||||||
hc_stackTrace_offset = 3 // New since 1.4
|
hc_stackTrace_offset = 3 // New since 1.4
|
||||||
};
|
};
|
||||||
enum {
|
|
||||||
hc_static_unassigned_stacktrace_offset = 0 // New since 1.7
|
|
||||||
};
|
|
||||||
// Trace constants
|
// Trace constants
|
||||||
enum {
|
enum {
|
||||||
trace_methods_offset = 0,
|
trace_methods_offset = 0,
|
||||||
|
@ -878,7 +876,6 @@ class java_lang_ref_Reference: AllStatic {
|
||||||
static int queue_offset;
|
static int queue_offset;
|
||||||
static int next_offset;
|
static int next_offset;
|
||||||
static int discovered_offset;
|
static int discovered_offset;
|
||||||
static int number_of_fake_oop_fields;
|
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
static inline oop referent(oop ref);
|
static inline oop referent(oop ref);
|
||||||
|
@ -902,14 +899,6 @@ class java_lang_ref_Reference: AllStatic {
|
||||||
|
|
||||||
class java_lang_ref_SoftReference: public java_lang_ref_Reference {
|
class java_lang_ref_SoftReference: public java_lang_ref_Reference {
|
||||||
public:
|
public:
|
||||||
enum {
|
|
||||||
// The timestamp is a long field and may need to be adjusted for alignment.
|
|
||||||
hc_timestamp_offset = hc_discovered_offset + 1
|
|
||||||
};
|
|
||||||
enum {
|
|
||||||
hc_static_clock_offset = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static int timestamp_offset;
|
static int timestamp_offset;
|
||||||
static int static_clock_offset;
|
static int static_clock_offset;
|
||||||
|
|
||||||
|
@ -919,6 +908,8 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference {
|
||||||
// Accessors for statics
|
// Accessors for statics
|
||||||
static jlong clock();
|
static jlong clock();
|
||||||
static void set_clock(jlong value);
|
static void set_clock(jlong value);
|
||||||
|
|
||||||
|
static void compute_offsets();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Interface to java.lang.invoke.MethodHandle objects
|
// Interface to java.lang.invoke.MethodHandle objects
|
||||||
|
@ -1228,10 +1219,6 @@ class java_security_AccessControlContext: AllStatic {
|
||||||
|
|
||||||
class java_lang_ClassLoader : AllStatic {
|
class java_lang_ClassLoader : AllStatic {
|
||||||
private:
|
private:
|
||||||
// The fake offsets are added by the class loader when java.lang.Class is loaded
|
|
||||||
enum {
|
|
||||||
hc_parent_offset = 0
|
|
||||||
};
|
|
||||||
static int _loader_data_offset;
|
static int _loader_data_offset;
|
||||||
static bool offsets_computed;
|
static bool offsets_computed;
|
||||||
static int parent_offset;
|
static int parent_offset;
|
||||||
|
@ -1279,13 +1266,6 @@ class java_lang_ClassLoader : AllStatic {
|
||||||
|
|
||||||
class java_lang_System : AllStatic {
|
class java_lang_System : AllStatic {
|
||||||
private:
|
private:
|
||||||
enum {
|
|
||||||
hc_static_in_offset = 0,
|
|
||||||
hc_static_out_offset = 1,
|
|
||||||
hc_static_err_offset = 2,
|
|
||||||
hc_static_security_offset = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
static int static_in_offset;
|
static int static_in_offset;
|
||||||
static int static_out_offset;
|
static int static_out_offset;
|
||||||
static int static_err_offset;
|
static int static_err_offset;
|
||||||
|
@ -1298,6 +1278,8 @@ class java_lang_System : AllStatic {
|
||||||
|
|
||||||
static bool has_security_manager();
|
static bool has_security_manager();
|
||||||
|
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
friend class JavaClasses;
|
friend class JavaClasses;
|
||||||
};
|
};
|
||||||
|
@ -1307,17 +1289,6 @@ class java_lang_System : AllStatic {
|
||||||
|
|
||||||
class java_lang_StackTraceElement: AllStatic {
|
class java_lang_StackTraceElement: AllStatic {
|
||||||
private:
|
private:
|
||||||
enum {
|
|
||||||
hc_declaringClassObject_offset = 0,
|
|
||||||
hc_classLoaderName_offset = 1,
|
|
||||||
hc_moduleName_offset = 2,
|
|
||||||
hc_moduleVersion_offset = 3,
|
|
||||||
hc_declaringClass_offset = 4,
|
|
||||||
hc_methodName_offset = 5,
|
|
||||||
hc_fileName_offset = 6,
|
|
||||||
hc_lineNumber_offset = 7
|
|
||||||
};
|
|
||||||
|
|
||||||
static int declaringClassObject_offset;
|
static int declaringClassObject_offset;
|
||||||
static int classLoaderName_offset;
|
static int classLoaderName_offset;
|
||||||
static int moduleName_offset;
|
static int moduleName_offset;
|
||||||
|
@ -1344,6 +1315,8 @@ class java_lang_StackTraceElement: AllStatic {
|
||||||
static void fill_in(Handle element, InstanceKlass* holder, const methodHandle& method,
|
static void fill_in(Handle element, InstanceKlass* holder, const methodHandle& method,
|
||||||
int version, int bci, Symbol* name, TRAPS);
|
int version, int bci, Symbol* name, TRAPS);
|
||||||
|
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
friend class JavaClasses;
|
friend class JavaClasses;
|
||||||
};
|
};
|
||||||
|
@ -1416,14 +1389,6 @@ class java_lang_LiveStackFrameInfo: AllStatic {
|
||||||
|
|
||||||
class java_lang_AssertionStatusDirectives: AllStatic {
|
class java_lang_AssertionStatusDirectives: AllStatic {
|
||||||
private:
|
private:
|
||||||
enum {
|
|
||||||
hc_classes_offset,
|
|
||||||
hc_classEnabled_offset,
|
|
||||||
hc_packages_offset,
|
|
||||||
hc_packageEnabled_offset,
|
|
||||||
hc_deflt_offset
|
|
||||||
};
|
|
||||||
|
|
||||||
static int classes_offset;
|
static int classes_offset;
|
||||||
static int classEnabled_offset;
|
static int classEnabled_offset;
|
||||||
static int packages_offset;
|
static int packages_offset;
|
||||||
|
@ -1437,6 +1402,9 @@ class java_lang_AssertionStatusDirectives: AllStatic {
|
||||||
static void set_packages(oop obj, oop val);
|
static void set_packages(oop obj, oop val);
|
||||||
static void set_packageEnabled(oop obj, oop val);
|
static void set_packageEnabled(oop obj, oop val);
|
||||||
static void set_deflt(oop obj, bool val);
|
static void set_deflt(oop obj, bool val);
|
||||||
|
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
// Debugging
|
// Debugging
|
||||||
friend class JavaClasses;
|
friend class JavaClasses;
|
||||||
};
|
};
|
||||||
|
@ -1508,9 +1476,6 @@ class JavaClasses : AllStatic {
|
||||||
static InjectedField _injected_fields[];
|
static InjectedField _injected_fields[];
|
||||||
|
|
||||||
static bool check_offset(const char *klass_name, int offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0;
|
static bool check_offset(const char *klass_name, int offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0;
|
||||||
static bool check_static_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0;
|
|
||||||
static bool check_constant(const char *klass_name, int constant, const char *field_name, const char* field_sig) PRODUCT_RETURN0;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum InjectedFieldID {
|
enum InjectedFieldID {
|
||||||
ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD_ENUM)
|
ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD_ENUM)
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#define SHARE_VM_CLASSFILE_JAVACLASSES_INLINE_HPP
|
#define SHARE_VM_CLASSFILE_JAVACLASSES_INLINE_HPP
|
||||||
|
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
|
#include "oops/access.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "oops/oopsHierarchy.hpp"
|
#include "oops/oopsHierarchy.hpp"
|
||||||
|
|
||||||
|
@ -53,6 +54,11 @@ typeArrayOop java_lang_String::value(oop java_string) {
|
||||||
assert(is_instance(java_string), "must be java_string");
|
assert(is_instance(java_string), "must be java_string");
|
||||||
return (typeArrayOop) java_string->obj_field(value_offset);
|
return (typeArrayOop) java_string->obj_field(value_offset);
|
||||||
}
|
}
|
||||||
|
typeArrayOop java_lang_String::value_no_keepalive(oop java_string) {
|
||||||
|
assert(initialized && (value_offset > 0), "Must be initialized");
|
||||||
|
assert(is_instance(java_string), "must be java_string");
|
||||||
|
return (typeArrayOop) java_string->obj_field_access<AS_NO_KEEPALIVE>(value_offset);
|
||||||
|
}
|
||||||
unsigned int java_lang_String::hash(oop java_string) {
|
unsigned int java_lang_String::hash(oop java_string) {
|
||||||
assert(initialized && (hash_offset > 0), "Must be initialized");
|
assert(initialized && (hash_offset > 0), "Must be initialized");
|
||||||
assert(is_instance(java_string), "must be java_string");
|
assert(is_instance(java_string), "must be java_string");
|
||||||
|
@ -68,11 +74,11 @@ bool java_lang_String::is_latin1(oop java_string) {
|
||||||
int java_lang_String::length(oop java_string) {
|
int java_lang_String::length(oop java_string) {
|
||||||
assert(initialized, "Must be initialized");
|
assert(initialized, "Must be initialized");
|
||||||
assert(is_instance(java_string), "must be java_string");
|
assert(is_instance(java_string), "must be java_string");
|
||||||
typeArrayOop value_array = ((typeArrayOop)java_string->obj_field(value_offset));
|
typeArrayOop value = java_lang_String::value_no_keepalive(java_string);
|
||||||
if (value_array == NULL) {
|
if (value == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int arr_length = value_array->length();
|
int arr_length = value->length();
|
||||||
if (!is_latin1(java_string)) {
|
if (!is_latin1(java_string)) {
|
||||||
assert((arr_length & 1) == 0, "should be even for UTF16 string");
|
assert((arr_length & 1) == 0, "should be even for UTF16 string");
|
||||||
arr_length >>= 1; // convert number of bytes to number of elements
|
arr_length >>= 1; // convert number of bytes to number of elements
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "memory/filemap.hpp"
|
#include "memory/filemap.hpp"
|
||||||
#include "memory/metaspaceShared.hpp"
|
#include "memory/metaspaceShared.hpp"
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "oops/access.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "runtime/atomic.hpp"
|
#include "runtime/atomic.hpp"
|
||||||
#include "runtime/mutexLocker.hpp"
|
#include "runtime/mutexLocker.hpp"
|
||||||
|
@ -43,7 +44,6 @@
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
#if INCLUDE_ALL_GCS
|
#if INCLUDE_ALL_GCS
|
||||||
#include "gc/g1/g1CollectedHeap.hpp"
|
#include "gc/g1/g1CollectedHeap.hpp"
|
||||||
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
|
|
||||||
#include "gc/g1/g1StringDedup.hpp"
|
#include "gc/g1/g1StringDedup.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -124,6 +124,22 @@ unsigned int StringTable::hash_string(oop string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oop StringTable::string_object(HashtableEntry<oop, mtSymbol>* entry) {
|
||||||
|
return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(entry->literal_addr());
|
||||||
|
}
|
||||||
|
|
||||||
|
oop StringTable::string_object_no_keepalive(HashtableEntry<oop, mtSymbol>* entry) {
|
||||||
|
// The AS_NO_KEEPALIVE peeks at the oop without keeping it alive.
|
||||||
|
// This is *very dangerous* in general but is okay in this specific
|
||||||
|
// case. The subsequent oop_load keeps the oop alive if it it matched
|
||||||
|
// the jchar* string.
|
||||||
|
return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(entry->literal_addr());
|
||||||
|
}
|
||||||
|
|
||||||
|
void StringTable::set_string_object(HashtableEntry<oop, mtSymbol>* entry, oop string) {
|
||||||
|
RootAccess<ON_PHANTOM_OOP_REF>::oop_store(entry->literal_addr(), string);
|
||||||
|
}
|
||||||
|
|
||||||
oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
|
oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
|
||||||
assert(hash == java_lang_String::hash_code(name, len),
|
assert(hash == java_lang_String::hash_code(name, len),
|
||||||
"hash must be computed using java_lang_String::hash_code");
|
"hash must be computed using java_lang_String::hash_code");
|
||||||
|
@ -131,13 +147,16 @@ oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
|
||||||
}
|
}
|
||||||
|
|
||||||
oop StringTable::lookup_in_main_table(int index, jchar* name,
|
oop StringTable::lookup_in_main_table(int index, jchar* name,
|
||||||
int len, unsigned int hash) {
|
int len, unsigned int hash) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
|
for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
|
||||||
count++;
|
count++;
|
||||||
if (l->hash() == hash) {
|
if (l->hash() == hash) {
|
||||||
if (java_lang_String::equals(l->literal(), name, len)) {
|
if (java_lang_String::equals(string_object_no_keepalive(l), name, len)) {
|
||||||
return l->literal();
|
// We must perform a new load with string_object() that keeps the string
|
||||||
|
// alive as we must expose the oop as strongly reachable when exiting
|
||||||
|
// this context, in case the oop gets published.
|
||||||
|
return string_object(l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,18 +211,6 @@ oop StringTable::lookup(Symbol* symbol) {
|
||||||
return lookup(chars, length);
|
return lookup(chars, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the GC that this string was looked up in the StringTable.
|
|
||||||
static void ensure_string_alive(oop string) {
|
|
||||||
// A lookup in the StringTable could return an object that was previously
|
|
||||||
// considered dead. The SATB part of G1 needs to get notified about this
|
|
||||||
// potential resurrection, otherwise the marking might not find the object.
|
|
||||||
#if INCLUDE_ALL_GCS
|
|
||||||
if (UseG1GC && string != NULL) {
|
|
||||||
G1SATBCardTableModRefBS::enqueue(string);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
oop StringTable::lookup(jchar* name, int len) {
|
oop StringTable::lookup(jchar* name, int len) {
|
||||||
// shared table always uses java_lang_String::hash_code
|
// shared table always uses java_lang_String::hash_code
|
||||||
unsigned int hash = java_lang_String::hash_code(name, len);
|
unsigned int hash = java_lang_String::hash_code(name, len);
|
||||||
|
@ -217,8 +224,6 @@ oop StringTable::lookup(jchar* name, int len) {
|
||||||
int index = the_table()->hash_to_index(hash);
|
int index = the_table()->hash_to_index(hash);
|
||||||
string = the_table()->lookup_in_main_table(index, name, len, hash);
|
string = the_table()->lookup_in_main_table(index, name, len, hash);
|
||||||
|
|
||||||
ensure_string_alive(string);
|
|
||||||
|
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,9 +243,6 @@ oop StringTable::intern(Handle string_or_null, jchar* name,
|
||||||
|
|
||||||
// Found
|
// Found
|
||||||
if (found_string != NULL) {
|
if (found_string != NULL) {
|
||||||
if (found_string != string_or_null()) {
|
|
||||||
ensure_string_alive(found_string);
|
|
||||||
}
|
|
||||||
return found_string;
|
return found_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,10 +278,6 @@ oop StringTable::intern(Handle string_or_null, jchar* name,
|
||||||
hashValue, CHECK_NULL);
|
hashValue, CHECK_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (added_or_found != string()) {
|
|
||||||
ensure_string_alive(added_or_found);
|
|
||||||
}
|
|
||||||
|
|
||||||
return added_or_found;
|
return added_or_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,9 +386,9 @@ void StringTable::buckets_unlink_or_oops_do(BoolObjectClosure* is_alive, OopClos
|
||||||
while (entry != NULL) {
|
while (entry != NULL) {
|
||||||
assert(!entry->is_shared(), "CDS not used for the StringTable");
|
assert(!entry->is_shared(), "CDS not used for the StringTable");
|
||||||
|
|
||||||
if (is_alive->do_object_b(entry->literal())) {
|
if (is_alive->do_object_b(string_object_no_keepalive(entry))) {
|
||||||
if (f != NULL) {
|
if (f != NULL) {
|
||||||
f->do_oop((oop*)entry->literal_addr());
|
f->do_oop(entry->literal_addr());
|
||||||
}
|
}
|
||||||
p = entry->next_addr();
|
p = entry->next_addr();
|
||||||
} else {
|
} else {
|
||||||
|
@ -429,7 +427,7 @@ void StringTable::verify() {
|
||||||
for (int i = 0; i < the_table()->table_size(); ++i) {
|
for (int i = 0; i < the_table()->table_size(); ++i) {
|
||||||
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
|
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
|
||||||
for ( ; p != NULL; p = p->next()) {
|
for ( ; p != NULL; p = p->next()) {
|
||||||
oop s = p->literal();
|
oop s = string_object_no_keepalive(p);
|
||||||
guarantee(s != NULL, "interned string is NULL");
|
guarantee(s != NULL, "interned string is NULL");
|
||||||
unsigned int h = hash_string(s);
|
unsigned int h = hash_string(s);
|
||||||
guarantee(p->hash() == h, "broken hash in string table entry");
|
guarantee(p->hash() == h, "broken hash in string table entry");
|
||||||
|
@ -448,10 +446,10 @@ void StringTable::dump(outputStream* st, bool verbose) {
|
||||||
for (int i = 0; i < the_table()->table_size(); ++i) {
|
for (int i = 0; i < the_table()->table_size(); ++i) {
|
||||||
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
|
HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
|
||||||
for ( ; p != NULL; p = p->next()) {
|
for ( ; p != NULL; p = p->next()) {
|
||||||
oop s = p->literal();
|
oop s = string_object_no_keepalive(p);
|
||||||
typeArrayOop value = java_lang_String::value(s);
|
typeArrayOop value = java_lang_String::value_no_keepalive(s);
|
||||||
int length = java_lang_String::length(s);
|
int length = java_lang_String::length(s);
|
||||||
bool is_latin1 = java_lang_String::is_latin1(s);
|
bool is_latin1 = java_lang_String::is_latin1(s);
|
||||||
|
|
||||||
if (length <= 0) {
|
if (length <= 0) {
|
||||||
st->print("%d: ", length);
|
st->print("%d: ", length);
|
||||||
|
@ -484,8 +482,8 @@ StringTable::VerifyRetTypes StringTable::compare_entries(
|
||||||
HashtableEntry<oop, mtSymbol>* e_ptr2) {
|
HashtableEntry<oop, mtSymbol>* e_ptr2) {
|
||||||
// These entries are sanity checked by verify_and_compare_entries()
|
// These entries are sanity checked by verify_and_compare_entries()
|
||||||
// before this function is called.
|
// before this function is called.
|
||||||
oop str1 = e_ptr1->literal();
|
oop str1 = string_object_no_keepalive(e_ptr1);
|
||||||
oop str2 = e_ptr2->literal();
|
oop str2 = string_object_no_keepalive(e_ptr2);
|
||||||
|
|
||||||
if (str1 == str2) {
|
if (str1 == str2) {
|
||||||
tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") "
|
tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") "
|
||||||
|
@ -505,12 +503,12 @@ StringTable::VerifyRetTypes StringTable::compare_entries(
|
||||||
}
|
}
|
||||||
|
|
||||||
StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt,
|
StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt,
|
||||||
HashtableEntry<oop, mtSymbol>* e_ptr,
|
HashtableEntry<oop, mtSymbol>* e_ptr,
|
||||||
StringTable::VerifyMesgModes mesg_mode) {
|
StringTable::VerifyMesgModes mesg_mode) {
|
||||||
|
|
||||||
VerifyRetTypes ret = _verify_pass; // be optimistic
|
VerifyRetTypes ret = _verify_pass; // be optimistic
|
||||||
|
|
||||||
oop str = e_ptr->literal();
|
oop str = string_object_no_keepalive(e_ptr);
|
||||||
if (str == NULL) {
|
if (str == NULL) {
|
||||||
if (mesg_mode == _verify_with_mesgs) {
|
if (mesg_mode == _verify_with_mesgs) {
|
||||||
tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt,
|
tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt,
|
||||||
|
@ -684,7 +682,7 @@ oop StringTable::create_archived_string(oop s, Thread* THREAD) {
|
||||||
assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
|
assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
|
||||||
|
|
||||||
oop new_s = NULL;
|
oop new_s = NULL;
|
||||||
typeArrayOop v = java_lang_String::value(s);
|
typeArrayOop v = java_lang_String::value_no_keepalive(s);
|
||||||
typeArrayOop new_v = (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD);
|
typeArrayOop new_v = (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD);
|
||||||
if (new_v == NULL) {
|
if (new_v == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -708,7 +706,7 @@ bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space,
|
||||||
for (int i = 0; i < the_table()->table_size(); ++i) {
|
for (int i = 0; i < the_table()->table_size(); ++i) {
|
||||||
HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i);
|
HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i);
|
||||||
for ( ; bucket != NULL; bucket = bucket->next()) {
|
for ( ; bucket != NULL; bucket = bucket->next()) {
|
||||||
oop s = bucket->literal();
|
oop s = string_object_no_keepalive(bucket);
|
||||||
unsigned int hash = java_lang_String::hash_code(s);
|
unsigned int hash = java_lang_String::hash_code(s);
|
||||||
if (hash == 0) {
|
if (hash == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -721,7 +719,7 @@ bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space,
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the archived string in bucket
|
// set the archived string in bucket
|
||||||
bucket->set_literal(new_s);
|
set_string_object(bucket, new_s);
|
||||||
|
|
||||||
// add to the compact table
|
// add to the compact table
|
||||||
writer->add(hash, new_s);
|
writer->add(hash, new_s);
|
||||||
|
@ -763,4 +761,3 @@ void StringTable::shared_oops_do(OopClosure* f) {
|
||||||
_shared_table.oops_do(f);
|
_shared_table.oops_do(f);
|
||||||
}
|
}
|
||||||
#endif //INCLUDE_CDS_JAVA_HEAP
|
#endif //INCLUDE_CDS_JAVA_HEAP
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,13 @@ private:
|
||||||
static unsigned int hash_string(oop string);
|
static unsigned int hash_string(oop string);
|
||||||
static unsigned int alt_hash_string(const jchar* s, int len);
|
static unsigned int alt_hash_string(const jchar* s, int len);
|
||||||
|
|
||||||
|
// Accessors for the string roots in the hashtable entries.
|
||||||
|
// Use string_object_no_keepalive() only when the value is not returned
|
||||||
|
// outside of a scope where a thread transition is possible.
|
||||||
|
static oop string_object(HashtableEntry<oop, mtSymbol>* entry);
|
||||||
|
static oop string_object_no_keepalive(HashtableEntry<oop, mtSymbol>* entry);
|
||||||
|
static void set_string_object(HashtableEntry<oop, mtSymbol>* entry, oop string);
|
||||||
|
|
||||||
StringTable() : RehashableHashtable<oop, mtSymbol>((int)StringTableSize,
|
StringTable() : RehashableHashtable<oop, mtSymbol>((int)StringTableSize,
|
||||||
sizeof (HashtableEntry<oop, mtSymbol>)) {}
|
sizeof (HashtableEntry<oop, mtSymbol>)) {}
|
||||||
|
|
||||||
|
|
|
@ -2775,7 +2775,17 @@ Handle SystemDictionary::link_method_handle_constant(Klass* caller,
|
||||||
java_lang_invoke_MemberName::set_name (mname(), name_str());
|
java_lang_invoke_MemberName::set_name (mname(), name_str());
|
||||||
java_lang_invoke_MemberName::set_type (mname(), signature_str());
|
java_lang_invoke_MemberName::set_type (mname(), signature_str());
|
||||||
java_lang_invoke_MemberName::set_flags(mname(), MethodHandles::ref_kind_to_flags(ref_kind));
|
java_lang_invoke_MemberName::set_flags(mname(), MethodHandles::ref_kind_to_flags(ref_kind));
|
||||||
MethodHandles::resolve_MemberName(mname, caller, CHECK_(empty));
|
|
||||||
|
if (ref_kind == JVM_REF_invokeVirtual &&
|
||||||
|
callee->name() == vmSymbols::java_lang_invoke_MethodHandle() &&
|
||||||
|
(name == vmSymbols::invoke_name() || name == vmSymbols::invokeExact_name())) {
|
||||||
|
// Skip resolution for j.l.i.MethodHandle.invoke()/invokeExact().
|
||||||
|
// They are public signature polymorphic methods, but require appendix argument
|
||||||
|
// which MemberName resolution doesn't handle. There's special logic on JDK side to handle them
|
||||||
|
// (see MethodHandles.linkMethodHandleConstant() and MethodHandles.findVirtualForMH()).
|
||||||
|
} else {
|
||||||
|
MethodHandles::resolve_MemberName(mname, caller, CHECK_(empty));
|
||||||
|
}
|
||||||
|
|
||||||
// After method/field resolution succeeded, it's safe to resolve MH signature as well.
|
// After method/field resolution succeeded, it's safe to resolve MH signature as well.
|
||||||
Handle type = MethodHandles::resolve_MemberName_type(mname, caller, CHECK_(empty));
|
Handle type = MethodHandles::resolve_MemberName_type(mname, caller, CHECK_(empty));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -173,6 +173,7 @@ class GCTimer;
|
||||||
do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre ) \
|
do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre ) \
|
||||||
/* Note: MethodHandle must be first, and VolatileCallSite last in group */ \
|
/* Note: MethodHandle must be first, and VolatileCallSite last in group */ \
|
||||||
\
|
\
|
||||||
|
do_klass(AssertionStatusDirectives_klass, java_lang_AssertionStatusDirectives, Pre ) \
|
||||||
do_klass(StringBuffer_klass, java_lang_StringBuffer, Pre ) \
|
do_klass(StringBuffer_klass, java_lang_StringBuffer, Pre ) \
|
||||||
do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \
|
do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \
|
||||||
do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe, Pre ) \
|
do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe, Pre ) \
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -251,7 +251,6 @@
|
||||||
template(compiledLambdaForm_name, "<compiledLambdaForm>") /*fake name*/ \
|
template(compiledLambdaForm_name, "<compiledLambdaForm>") /*fake name*/ \
|
||||||
template(star_name, "*") /*not really a name*/ \
|
template(star_name, "*") /*not really a name*/ \
|
||||||
template(invoke_name, "invoke") \
|
template(invoke_name, "invoke") \
|
||||||
template(override_name, "override") \
|
|
||||||
template(parameterTypes_name, "parameterTypes") \
|
template(parameterTypes_name, "parameterTypes") \
|
||||||
template(returnType_name, "returnType") \
|
template(returnType_name, "returnType") \
|
||||||
template(signature_name, "signature") \
|
template(signature_name, "signature") \
|
||||||
|
@ -265,7 +264,6 @@
|
||||||
template(parameter_annotations_name, "parameterAnnotations") \
|
template(parameter_annotations_name, "parameterAnnotations") \
|
||||||
template(annotation_default_name, "annotationDefault") \
|
template(annotation_default_name, "annotationDefault") \
|
||||||
template(reflect_ConstantPool, "jdk/internal/reflect/ConstantPool") \
|
template(reflect_ConstantPool, "jdk/internal/reflect/ConstantPool") \
|
||||||
template(ConstantPool_name, "constantPoolOop") \
|
|
||||||
template(reflect_UnsafeStaticFieldAccessorImpl, "jdk/internal/reflect/UnsafeStaticFieldAccessorImpl")\
|
template(reflect_UnsafeStaticFieldAccessorImpl, "jdk/internal/reflect/UnsafeStaticFieldAccessorImpl")\
|
||||||
template(base_name, "base") \
|
template(base_name, "base") \
|
||||||
/* Type Annotations (JDK 8 and above) */ \
|
/* Type Annotations (JDK 8 and above) */ \
|
||||||
|
@ -304,6 +302,7 @@
|
||||||
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \
|
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \
|
||||||
template(findMethodHandleType_name, "findMethodHandleType") \
|
template(findMethodHandleType_name, "findMethodHandleType") \
|
||||||
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
|
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
|
||||||
|
template(invokeExact_name, "invokeExact") \
|
||||||
template(linkMethodHandleConstant_name, "linkMethodHandleConstant") \
|
template(linkMethodHandleConstant_name, "linkMethodHandleConstant") \
|
||||||
template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \
|
template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \
|
||||||
template(linkMethod_name, "linkMethod") \
|
template(linkMethod_name, "linkMethod") \
|
||||||
|
@ -340,8 +339,6 @@
|
||||||
template(stillborn_name, "stillborn") \
|
template(stillborn_name, "stillborn") \
|
||||||
template(group_name, "group") \
|
template(group_name, "group") \
|
||||||
template(daemon_name, "daemon") \
|
template(daemon_name, "daemon") \
|
||||||
template(eetop_name, "eetop") \
|
|
||||||
template(thread_status_name, "threadStatus") \
|
|
||||||
template(run_method_name, "run") \
|
template(run_method_name, "run") \
|
||||||
template(exit_method_name, "exit") \
|
template(exit_method_name, "exit") \
|
||||||
template(add_method_name, "add") \
|
template(add_method_name, "add") \
|
||||||
|
@ -375,34 +372,21 @@
|
||||||
template(fillInStackTrace_name, "fillInStackTrace") \
|
template(fillInStackTrace_name, "fillInStackTrace") \
|
||||||
template(getCause_name, "getCause") \
|
template(getCause_name, "getCause") \
|
||||||
template(initCause_name, "initCause") \
|
template(initCause_name, "initCause") \
|
||||||
template(depth_name, "depth") \
|
|
||||||
template(setProperty_name, "setProperty") \
|
template(setProperty_name, "setProperty") \
|
||||||
template(getProperty_name, "getProperty") \
|
template(getProperty_name, "getProperty") \
|
||||||
template(context_name, "context") \
|
template(context_name, "context") \
|
||||||
template(privilegedContext_name, "privilegedContext") \
|
|
||||||
template(contextClassLoader_name, "contextClassLoader") \
|
template(contextClassLoader_name, "contextClassLoader") \
|
||||||
template(inheritedAccessControlContext_name, "inheritedAccessControlContext") \
|
template(inheritedAccessControlContext_name, "inheritedAccessControlContext") \
|
||||||
template(isPrivileged_name, "isPrivileged") \
|
|
||||||
template(isAuthorized_name, "isAuthorized") \
|
|
||||||
template(getClassContext_name, "getClassContext") \
|
template(getClassContext_name, "getClassContext") \
|
||||||
template(wait_name, "wait") \
|
template(wait_name, "wait") \
|
||||||
template(checkPackageAccess_name, "checkPackageAccess") \
|
template(checkPackageAccess_name, "checkPackageAccess") \
|
||||||
template(stackSize_name, "stackSize") \
|
|
||||||
template(thread_id_name, "tid") \
|
|
||||||
template(newInstance0_name, "newInstance0") \
|
template(newInstance0_name, "newInstance0") \
|
||||||
template(limit_name, "limit") \
|
|
||||||
template(member_name, "member") \
|
|
||||||
template(forName_name, "forName") \
|
template(forName_name, "forName") \
|
||||||
template(forName0_name, "forName0") \
|
template(forName0_name, "forName0") \
|
||||||
template(isJavaIdentifierStart_name, "isJavaIdentifierStart") \
|
template(isJavaIdentifierStart_name, "isJavaIdentifierStart") \
|
||||||
template(isJavaIdentifierPart_name, "isJavaIdentifierPart") \
|
template(isJavaIdentifierPart_name, "isJavaIdentifierPart") \
|
||||||
template(exclusive_owner_thread_name, "exclusiveOwnerThread") \
|
|
||||||
template(park_blocker_name, "parkBlocker") \
|
|
||||||
template(park_event_name, "nativeParkEventPointer") \
|
|
||||||
template(cache_field_name, "cache") \
|
template(cache_field_name, "cache") \
|
||||||
template(value_name, "value") \
|
template(value_name, "value") \
|
||||||
template(hash_name, "hash") \
|
|
||||||
template(coder_name, "coder") \
|
|
||||||
template(compact_strings_name, "COMPACT_STRINGS") \
|
template(compact_strings_name, "COMPACT_STRINGS") \
|
||||||
template(numberOfLeadingZeros_name, "numberOfLeadingZeros") \
|
template(numberOfLeadingZeros_name, "numberOfLeadingZeros") \
|
||||||
template(numberOfTrailingZeros_name, "numberOfTrailingZeros") \
|
template(numberOfTrailingZeros_name, "numberOfTrailingZeros") \
|
||||||
|
@ -419,27 +403,17 @@
|
||||||
template(method_name, "method") \
|
template(method_name, "method") \
|
||||||
template(vmindex_name, "vmindex") \
|
template(vmindex_name, "vmindex") \
|
||||||
template(vmcount_name, "vmcount") \
|
template(vmcount_name, "vmcount") \
|
||||||
template(vmentry_name, "vmentry") \
|
|
||||||
template(flags_name, "flags") \
|
template(flags_name, "flags") \
|
||||||
template(rtype_name, "rtype") \
|
|
||||||
template(ptypes_name, "ptypes") \
|
|
||||||
template(form_name, "form") \
|
|
||||||
template(basicType_name, "basicType") \
|
template(basicType_name, "basicType") \
|
||||||
template(append_name, "append") \
|
template(append_name, "append") \
|
||||||
template(klass_name, "klass") \
|
template(klass_name, "klass") \
|
||||||
template(array_klass_name, "array_klass") \
|
template(array_klass_name, "array_klass") \
|
||||||
template(memberName_name, "memberName") \
|
|
||||||
template(mid_name, "mid") \
|
template(mid_name, "mid") \
|
||||||
template(cpref_name, "cpref") \
|
template(cpref_name, "cpref") \
|
||||||
template(version_name, "version") \
|
template(version_name, "version") \
|
||||||
template(bci_name, "bci") \
|
|
||||||
template(methodName_name, "methodName") \
|
template(methodName_name, "methodName") \
|
||||||
template(fileName_name, "fileName") \
|
template(fileName_name, "fileName") \
|
||||||
template(lineNumber_name, "lineNumber") \
|
template(lineNumber_name, "lineNumber") \
|
||||||
template(monitors_name, "monitors") \
|
|
||||||
template(locals_name, "locals") \
|
|
||||||
template(operands_name, "operands") \
|
|
||||||
template(mode_name, "mode") \
|
|
||||||
template(oop_size_name, "oop_size") \
|
template(oop_size_name, "oop_size") \
|
||||||
template(static_oop_field_count_name, "static_oop_field_count") \
|
template(static_oop_field_count_name, "static_oop_field_count") \
|
||||||
template(protection_domain_name, "protection_domain") \
|
template(protection_domain_name, "protection_domain") \
|
||||||
|
@ -447,9 +421,11 @@
|
||||||
template(loader_data_name, "loader_data") \
|
template(loader_data_name, "loader_data") \
|
||||||
template(vmdependencies_name, "vmdependencies") \
|
template(vmdependencies_name, "vmdependencies") \
|
||||||
template(loader_name, "loader") \
|
template(loader_name, "loader") \
|
||||||
template(module_name, "module") \
|
|
||||||
template(getModule_name, "getModule") \
|
template(getModule_name, "getModule") \
|
||||||
template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \
|
template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \
|
||||||
|
template(input_stream_signature, "Ljava/io/InputStream;") \
|
||||||
|
template(print_stream_signature, "Ljava/io/PrintStream;") \
|
||||||
|
template(security_manager_signature, "Ljava/lang/SecurityManager;") \
|
||||||
template(definePackage_name, "definePackage") \
|
template(definePackage_name, "definePackage") \
|
||||||
template(definePackage_signature, "(Ljava/lang/String;Ljava/lang/Module;)Ljava/lang/Package;") \
|
template(definePackage_signature, "(Ljava/lang/String;Ljava/lang/Module;)Ljava/lang/Package;") \
|
||||||
template(defineOrCheckPackage_name, "defineOrCheckPackage") \
|
template(defineOrCheckPackage_name, "defineOrCheckPackage") \
|
||||||
|
@ -498,6 +474,7 @@
|
||||||
template(short_signature, "S") \
|
template(short_signature, "S") \
|
||||||
template(bool_signature, "Z") \
|
template(bool_signature, "Z") \
|
||||||
template(void_signature, "V") \
|
template(void_signature, "V") \
|
||||||
|
template(bool_array_signature, "[Z") \
|
||||||
template(byte_array_signature, "[B") \
|
template(byte_array_signature, "[B") \
|
||||||
template(char_array_signature, "[C") \
|
template(char_array_signature, "[C") \
|
||||||
template(int_array_signature, "[I") \
|
template(int_array_signature, "[I") \
|
||||||
|
@ -552,6 +529,7 @@
|
||||||
template(object_array_signature, "[Ljava/lang/Object;") \
|
template(object_array_signature, "[Ljava/lang/Object;") \
|
||||||
template(class_signature, "Ljava/lang/Class;") \
|
template(class_signature, "Ljava/lang/Class;") \
|
||||||
template(string_signature, "Ljava/lang/String;") \
|
template(string_signature, "Ljava/lang/String;") \
|
||||||
|
template(string_array_signature, "[Ljava/lang/String;") \
|
||||||
template(reference_signature, "Ljava/lang/ref/Reference;") \
|
template(reference_signature, "Ljava/lang/ref/Reference;") \
|
||||||
template(sun_misc_Cleaner_signature, "Lsun/misc/Cleaner;") \
|
template(sun_misc_Cleaner_signature, "Lsun/misc/Cleaner;") \
|
||||||
template(executable_signature, "Ljava/lang/reflect/Executable;") \
|
template(executable_signature, "Ljava/lang/reflect/Executable;") \
|
||||||
|
@ -578,12 +556,6 @@
|
||||||
/* used by ClassFormatError when class name is not known yet */ \
|
/* used by ClassFormatError when class name is not known yet */ \
|
||||||
template(unknown_class_name, "<Unknown>") \
|
template(unknown_class_name, "<Unknown>") \
|
||||||
\
|
\
|
||||||
/* used to identify class loaders handling parallel class loading */ \
|
|
||||||
template(parallelCapable_name, "parallelLockMap") \
|
|
||||||
\
|
|
||||||
/* used to return a class loader's unnamed module */ \
|
|
||||||
template(unnamedModule_name, "unnamedModule") \
|
|
||||||
\
|
|
||||||
/* JVM monitoring and management support */ \
|
/* JVM monitoring and management support */ \
|
||||||
template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \
|
template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \
|
||||||
template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \
|
template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \
|
||||||
|
|
|
@ -230,10 +230,13 @@ bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecod
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
int index = call_info->resolved_method()->itable_index();
|
int index = call_info->resolved_method()->itable_index();
|
||||||
assert(index == itable_index, "CallInfo pre-computes this");
|
assert(index == itable_index, "CallInfo pre-computes this");
|
||||||
#endif //ASSERT
|
|
||||||
InstanceKlass* k = call_info->resolved_method()->method_holder();
|
InstanceKlass* k = call_info->resolved_method()->method_holder();
|
||||||
assert(k->verify_itable_index(itable_index), "sanity check");
|
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 {
|
} else {
|
||||||
assert(call_info->call_kind() == CallInfo::vtable_call, "either itable or vtable");
|
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.
|
// 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) {
|
bool CompiledIC::is_icholder_entry(address entry) {
|
||||||
CodeBlob* cb = CodeCache::find_blob_unsafe(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) {
|
bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm) {
|
||||||
|
|
|
@ -45,11 +45,11 @@
|
||||||
// \ / \ /
|
// \ / \ /
|
||||||
// [4] \ / [4] \->-/
|
// [4] \ / [4] \->-/
|
||||||
// \->- Megamorphic -<-/
|
// \->- 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
|
// [1]: Initial fixup. Receiver it found from debug information
|
||||||
// [2]: Compilation of a method
|
// [2]: Compilation of a method
|
||||||
// [3]: Recompilation of a method (note: only entry is changed. The Klass* must stay the same)
|
// [3]: Recompilation of a method (note: only entry is changed. The Klass* must stay the same)
|
||||||
|
|
|
@ -404,8 +404,7 @@ void CompiledMethod::clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClos
|
||||||
// yet be marked below. (We check this further below).
|
// yet be marked below. (We check this further below).
|
||||||
CompiledICHolder* cichk_oop = ic->cached_icholder();
|
CompiledICHolder* cichk_oop = ic->cached_icholder();
|
||||||
|
|
||||||
if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) &&
|
if (cichk_oop->is_loader_alive(is_alive)) {
|
||||||
cichk_oop->holder_klass()->is_loader_alive(is_alive)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -241,8 +241,18 @@ class Dependencies: public ResourceObj {
|
||||||
bool is_object() const { assert(is_valid(), "oops"); return _id < 0; }
|
bool is_object() const { assert(is_valid(), "oops"); return _id < 0; }
|
||||||
|
|
||||||
Metadata* as_metadata(OopRecorder* rec) const { assert(is_metadata(), "oops"); return rec->metadata_at(index()); }
|
Metadata* as_metadata(OopRecorder* rec) const { assert(is_metadata(), "oops"); return rec->metadata_at(index()); }
|
||||||
Klass* as_klass(OopRecorder* rec) const { assert(as_metadata(rec)->is_klass(), "oops"); return (Klass*) as_metadata(rec); }
|
Klass* as_klass(OopRecorder* rec) const {
|
||||||
Method* as_method(OopRecorder* rec) const { assert(as_metadata(rec)->is_method(), "oops"); return (Method*) as_metadata(rec); }
|
Metadata* m = as_metadata(rec);
|
||||||
|
assert(m != NULL, "as_metadata returned NULL");
|
||||||
|
assert(m->is_klass(), "oops");
|
||||||
|
return (Klass*) m;
|
||||||
|
}
|
||||||
|
Method* as_method(OopRecorder* rec) const {
|
||||||
|
Metadata* m = as_metadata(rec);
|
||||||
|
assert(m != NULL, "as_metadata returned NULL");
|
||||||
|
assert(m->is_method(), "oops");
|
||||||
|
return (Method*) m;
|
||||||
|
}
|
||||||
jobject as_object(OopRecorder* rec) const { assert(is_object(), "oops"); return rec->oop_at(index()); }
|
jobject as_object(OopRecorder* rec) const { assert(is_object(), "oops"); return rec->oop_at(index()); }
|
||||||
};
|
};
|
||||||
#endif // INCLUDE_JVMCI
|
#endif // INCLUDE_JVMCI
|
||||||
|
|
|
@ -1547,7 +1547,7 @@ void nmethod::metadata_do(void f(Metadata*)) {
|
||||||
CompiledIC *ic = CompiledIC_at(&iter);
|
CompiledIC *ic = CompiledIC_at(&iter);
|
||||||
if (ic->is_icholder_call()) {
|
if (ic->is_icholder_call()) {
|
||||||
CompiledICHolder* cichk = ic->cached_icholder();
|
CompiledICHolder* cichk = ic->cached_icholder();
|
||||||
f(cichk->holder_method());
|
f(cichk->holder_metadata());
|
||||||
f(cichk->holder_klass());
|
f(cichk->holder_klass());
|
||||||
} else {
|
} else {
|
||||||
Metadata* ic_oop = ic->cached_metadata();
|
Metadata* ic_oop = ic->cached_metadata();
|
||||||
|
|
|
@ -445,9 +445,7 @@ HeapWord* G1CollectedHeap::allocate_new_tlab(size_t word_size) {
|
||||||
assert_heap_not_locked_and_not_at_safepoint();
|
assert_heap_not_locked_and_not_at_safepoint();
|
||||||
assert(!is_humongous(word_size), "we do not allow humongous TLABs");
|
assert(!is_humongous(word_size), "we do not allow humongous TLABs");
|
||||||
|
|
||||||
uint dummy_gc_count_before;
|
return attempt_allocation(word_size);
|
||||||
uint dummy_gclocker_retry_count = 0;
|
|
||||||
return attempt_allocation(word_size, &dummy_gc_count_before, &dummy_gclocker_retry_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapWord*
|
HeapWord*
|
||||||
|
@ -455,62 +453,16 @@ G1CollectedHeap::mem_allocate(size_t word_size,
|
||||||
bool* gc_overhead_limit_was_exceeded) {
|
bool* gc_overhead_limit_was_exceeded) {
|
||||||
assert_heap_not_locked_and_not_at_safepoint();
|
assert_heap_not_locked_and_not_at_safepoint();
|
||||||
|
|
||||||
// Loop until the allocation is satisfied, or unsatisfied after GC.
|
if (is_humongous(word_size)) {
|
||||||
for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) {
|
return attempt_allocation_humongous(word_size);
|
||||||
uint gc_count_before;
|
|
||||||
|
|
||||||
HeapWord* result = NULL;
|
|
||||||
if (!is_humongous(word_size)) {
|
|
||||||
result = attempt_allocation(word_size, &gc_count_before, &gclocker_retry_count);
|
|
||||||
} else {
|
|
||||||
result = attempt_allocation_humongous(word_size, &gc_count_before, &gclocker_retry_count);
|
|
||||||
}
|
|
||||||
if (result != NULL) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the garbage collection operation...
|
|
||||||
VM_G1CollectForAllocation op(gc_count_before, word_size);
|
|
||||||
op.set_allocation_context(AllocationContext::current());
|
|
||||||
|
|
||||||
// ...and get the VM thread to execute it.
|
|
||||||
VMThread::execute(&op);
|
|
||||||
|
|
||||||
if (op.prologue_succeeded() && op.pause_succeeded()) {
|
|
||||||
// If the operation was successful we'll return the result even
|
|
||||||
// if it is NULL. If the allocation attempt failed immediately
|
|
||||||
// after a Full GC, it's unlikely we'll be able to allocate now.
|
|
||||||
HeapWord* result = op.result();
|
|
||||||
if (result != NULL && !is_humongous(word_size)) {
|
|
||||||
// Allocations that take place on VM operations do not do any
|
|
||||||
// card dirtying and we have to do it here. We only have to do
|
|
||||||
// this for non-humongous allocations, though.
|
|
||||||
dirty_young_block(result, word_size);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
if (gclocker_retry_count > GCLockerRetryAllocationCount) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
assert(op.result() == NULL,
|
|
||||||
"the result should be NULL if the VM op did not succeed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Give a warning if we seem to be looping forever.
|
|
||||||
if ((QueuedAllocationWarningCount > 0) &&
|
|
||||||
(try_count % QueuedAllocationWarningCount == 0)) {
|
|
||||||
log_warning(gc)("G1CollectedHeap::mem_allocate retries %d times", try_count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return attempt_allocation(word_size);
|
||||||
ShouldNotReachHere();
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
|
HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
|
||||||
AllocationContext_t context,
|
AllocationContext_t context) {
|
||||||
uint* gc_count_before_ret,
|
ResourceMark rm; // For retrieving the thread names in log messages.
|
||||||
uint* gclocker_retry_count_ret) {
|
|
||||||
// Make sure you read the note in attempt_allocation_humongous().
|
// Make sure you read the note in attempt_allocation_humongous().
|
||||||
|
|
||||||
assert_heap_not_locked_and_not_at_safepoint();
|
assert_heap_not_locked_and_not_at_safepoint();
|
||||||
|
@ -525,7 +477,7 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
|
||||||
// fails to perform the allocation. b) is the only case when we'll
|
// fails to perform the allocation. b) is the only case when we'll
|
||||||
// return NULL.
|
// return NULL.
|
||||||
HeapWord* result = NULL;
|
HeapWord* result = NULL;
|
||||||
for (int try_count = 1; /* we'll return */; try_count += 1) {
|
for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) {
|
||||||
bool should_try_gc;
|
bool should_try_gc;
|
||||||
uint gc_count_before;
|
uint gc_count_before;
|
||||||
|
|
||||||
|
@ -536,30 +488,23 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GCLocker::is_active_and_needs_gc()) {
|
// If the GCLocker is active and we are bound for a GC, try expanding young gen.
|
||||||
if (g1_policy()->can_expand_young_list()) {
|
// This is different to when only GCLocker::needs_gc() is set: try to avoid
|
||||||
// No need for an ergo verbose message here,
|
// waiting because the GCLocker is active to not wait too long.
|
||||||
// can_expand_young_list() does this when it returns true.
|
if (GCLocker::is_active_and_needs_gc() && g1_policy()->can_expand_young_list()) {
|
||||||
result = _allocator->attempt_allocation_force(word_size, context);
|
// No need for an ergo message here, can_expand_young_list() does this when
|
||||||
if (result != NULL) {
|
// it returns true.
|
||||||
return result;
|
result = _allocator->attempt_allocation_force(word_size, context);
|
||||||
}
|
if (result != NULL) {
|
||||||
}
|
return result;
|
||||||
should_try_gc = false;
|
|
||||||
} else {
|
|
||||||
// The GCLocker may not be active but the GCLocker initiated
|
|
||||||
// GC may not yet have been performed (GCLocker::needs_gc()
|
|
||||||
// returns true). In this case we do not try this GC and
|
|
||||||
// wait until the GCLocker initiated GC is performed, and
|
|
||||||
// then retry the allocation.
|
|
||||||
if (GCLocker::needs_gc()) {
|
|
||||||
should_try_gc = false;
|
|
||||||
} else {
|
|
||||||
// Read the GC count while still holding the Heap_lock.
|
|
||||||
gc_count_before = total_collections();
|
|
||||||
should_try_gc = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Only try a GC if the GCLocker does not signal the need for a GC. Wait until
|
||||||
|
// the GCLocker initiated GC has been performed and then retry. This includes
|
||||||
|
// the case when the GC Locker is not active but has not been performed.
|
||||||
|
should_try_gc = !GCLocker::needs_gc();
|
||||||
|
// Read the GC count while still holding the Heap_lock.
|
||||||
|
gc_count_before = total_collections();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (should_try_gc) {
|
if (should_try_gc) {
|
||||||
|
@ -568,28 +513,33 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
|
||||||
GCCause::_g1_inc_collection_pause);
|
GCCause::_g1_inc_collection_pause);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
assert(succeeded, "only way to get back a non-NULL result");
|
assert(succeeded, "only way to get back a non-NULL result");
|
||||||
|
log_trace(gc, alloc)("%s: Successfully scheduled collection returning " PTR_FORMAT,
|
||||||
|
Thread::current()->name(), p2i(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (succeeded) {
|
if (succeeded) {
|
||||||
// If we get here we successfully scheduled a collection which
|
// We successfully scheduled a collection which failed to allocate. No
|
||||||
// failed to allocate. No point in trying to allocate
|
// point in trying to allocate further. We'll just return NULL.
|
||||||
// further. We'll just return NULL.
|
log_trace(gc, alloc)("%s: Successfully scheduled collection failing to allocate "
|
||||||
MutexLockerEx x(Heap_lock);
|
SIZE_FORMAT " words", Thread::current()->name(), word_size);
|
||||||
*gc_count_before_ret = total_collections();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating " SIZE_FORMAT " words",
|
||||||
|
Thread::current()->name(), word_size);
|
||||||
} else {
|
} else {
|
||||||
if (*gclocker_retry_count_ret > GCLockerRetryAllocationCount) {
|
// Failed to schedule a collection.
|
||||||
MutexLockerEx x(Heap_lock);
|
if (gclocker_retry_count > GCLockerRetryAllocationCount) {
|
||||||
*gc_count_before_ret = total_collections();
|
log_warning(gc, alloc)("%s: Retried waiting for GCLocker too often allocating "
|
||||||
|
SIZE_FORMAT " words", Thread::current()->name(), word_size);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
log_trace(gc, alloc)("%s: Stall until clear", Thread::current()->name());
|
||||||
// The GCLocker is either active or the GCLocker initiated
|
// The GCLocker is either active or the GCLocker initiated
|
||||||
// GC has not yet been performed. Stall until it is and
|
// GC has not yet been performed. Stall until it is and
|
||||||
// then retry the allocation.
|
// then retry the allocation.
|
||||||
GCLocker::stall_until_clear();
|
GCLocker::stall_until_clear();
|
||||||
(*gclocker_retry_count_ret) += 1;
|
gclocker_retry_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can reach here if we were unsuccessful in scheduling a
|
// We can reach here if we were unsuccessful in scheduling a
|
||||||
|
@ -600,6 +550,7 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
|
||||||
// first attempt (without holding the Heap_lock) here and the
|
// first attempt (without holding the Heap_lock) here and the
|
||||||
// follow-on attempt will be at the start of the next loop
|
// follow-on attempt will be at the start of the next loop
|
||||||
// iteration (after taking the Heap_lock).
|
// iteration (after taking the Heap_lock).
|
||||||
|
|
||||||
result = _allocator->attempt_allocation(word_size, context);
|
result = _allocator->attempt_allocation(word_size, context);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -608,8 +559,8 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size,
|
||||||
// Give a warning if we seem to be looping forever.
|
// Give a warning if we seem to be looping forever.
|
||||||
if ((QueuedAllocationWarningCount > 0) &&
|
if ((QueuedAllocationWarningCount > 0) &&
|
||||||
(try_count % QueuedAllocationWarningCount == 0)) {
|
(try_count % QueuedAllocationWarningCount == 0)) {
|
||||||
log_warning(gc)("G1CollectedHeap::attempt_allocation_slow() "
|
log_warning(gc, alloc)("%s: Retried allocation %u times for " SIZE_FORMAT " words",
|
||||||
"retries %d times", try_count);
|
Thread::current()->name(), try_count, word_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -830,9 +781,7 @@ void G1CollectedHeap::fill_archive_regions(MemRegion* ranges, size_t count) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size,
|
inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size) {
|
||||||
uint* gc_count_before_ret,
|
|
||||||
uint* gclocker_retry_count_ret) {
|
|
||||||
assert_heap_not_locked_and_not_at_safepoint();
|
assert_heap_not_locked_and_not_at_safepoint();
|
||||||
assert(!is_humongous(word_size), "attempt_allocation() should not "
|
assert(!is_humongous(word_size), "attempt_allocation() should not "
|
||||||
"be called for humongous allocation requests");
|
"be called for humongous allocation requests");
|
||||||
|
@ -841,10 +790,7 @@ inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size,
|
||||||
HeapWord* result = _allocator->attempt_allocation(word_size, context);
|
HeapWord* result = _allocator->attempt_allocation(word_size, context);
|
||||||
|
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
result = attempt_allocation_slow(word_size,
|
result = attempt_allocation_slow(word_size, context);
|
||||||
context,
|
|
||||||
gc_count_before_ret,
|
|
||||||
gclocker_retry_count_ret);
|
|
||||||
}
|
}
|
||||||
assert_heap_not_locked();
|
assert_heap_not_locked();
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
|
@ -925,9 +871,9 @@ void G1CollectedHeap::dealloc_archive_regions(MemRegion* ranges, size_t count) {
|
||||||
decrease_used(size_used);
|
decrease_used(size_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
|
HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) {
|
||||||
uint* gc_count_before_ret,
|
ResourceMark rm; // For retrieving the thread names in log messages.
|
||||||
uint* gclocker_retry_count_ret) {
|
|
||||||
// The structure of this method has a lot of similarities to
|
// The structure of this method has a lot of similarities to
|
||||||
// attempt_allocation_slow(). The reason these two were not merged
|
// attempt_allocation_slow(). The reason these two were not merged
|
||||||
// into a single one is that such a method would require several "if
|
// into a single one is that such a method would require several "if
|
||||||
|
@ -958,10 +904,11 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
|
||||||
// fails to perform the allocation. b) is the only case when we'll
|
// fails to perform the allocation. b) is the only case when we'll
|
||||||
// return NULL.
|
// return NULL.
|
||||||
HeapWord* result = NULL;
|
HeapWord* result = NULL;
|
||||||
for (int try_count = 1; /* we'll return */; try_count += 1) {
|
for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) {
|
||||||
bool should_try_gc;
|
bool should_try_gc;
|
||||||
uint gc_count_before;
|
uint gc_count_before;
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
MutexLockerEx x(Heap_lock);
|
MutexLockerEx x(Heap_lock);
|
||||||
|
|
||||||
|
@ -975,69 +922,63 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GCLocker::is_active_and_needs_gc()) {
|
// Only try a GC if the GCLocker does not signal the need for a GC. Wait until
|
||||||
should_try_gc = false;
|
// the GCLocker initiated GC has been performed and then retry. This includes
|
||||||
} else {
|
// the case when the GC Locker is not active but has not been performed.
|
||||||
// The GCLocker may not be active but the GCLocker initiated
|
should_try_gc = !GCLocker::needs_gc();
|
||||||
// GC may not yet have been performed (GCLocker::needs_gc()
|
// Read the GC count while still holding the Heap_lock.
|
||||||
// returns true). In this case we do not try this GC and
|
gc_count_before = total_collections();
|
||||||
// wait until the GCLocker initiated GC is performed, and
|
|
||||||
// then retry the allocation.
|
|
||||||
if (GCLocker::needs_gc()) {
|
|
||||||
should_try_gc = false;
|
|
||||||
} else {
|
|
||||||
// Read the GC count while still holding the Heap_lock.
|
|
||||||
gc_count_before = total_collections();
|
|
||||||
should_try_gc = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (should_try_gc) {
|
if (should_try_gc) {
|
||||||
// If we failed to allocate the humongous object, we should try to
|
|
||||||
// do a collection pause (if we're allowed) in case it reclaims
|
|
||||||
// enough space for the allocation to succeed after the pause.
|
|
||||||
|
|
||||||
bool succeeded;
|
bool succeeded;
|
||||||
result = do_collection_pause(word_size, gc_count_before, &succeeded,
|
result = do_collection_pause(word_size, gc_count_before, &succeeded,
|
||||||
GCCause::_g1_humongous_allocation);
|
GCCause::_g1_humongous_allocation);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
assert(succeeded, "only way to get back a non-NULL result");
|
assert(succeeded, "only way to get back a non-NULL result");
|
||||||
|
log_trace(gc, alloc)("%s: Successfully scheduled collection returning " PTR_FORMAT,
|
||||||
|
Thread::current()->name(), p2i(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (succeeded) {
|
if (succeeded) {
|
||||||
// If we get here we successfully scheduled a collection which
|
// We successfully scheduled a collection which failed to allocate. No
|
||||||
// failed to allocate. No point in trying to allocate
|
// point in trying to allocate further. We'll just return NULL.
|
||||||
// further. We'll just return NULL.
|
log_trace(gc, alloc)("%s: Successfully scheduled collection failing to allocate "
|
||||||
MutexLockerEx x(Heap_lock);
|
SIZE_FORMAT " words", Thread::current()->name(), word_size);
|
||||||
*gc_count_before_ret = total_collections();
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating " SIZE_FORMAT "",
|
||||||
|
Thread::current()->name(), word_size);
|
||||||
} else {
|
} else {
|
||||||
if (*gclocker_retry_count_ret > GCLockerRetryAllocationCount) {
|
// Failed to schedule a collection.
|
||||||
MutexLockerEx x(Heap_lock);
|
if (gclocker_retry_count > GCLockerRetryAllocationCount) {
|
||||||
*gc_count_before_ret = total_collections();
|
log_warning(gc, alloc)("%s: Retried waiting for GCLocker too often allocating "
|
||||||
|
SIZE_FORMAT " words", Thread::current()->name(), word_size);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
log_trace(gc, alloc)("%s: Stall until clear", Thread::current()->name());
|
||||||
// The GCLocker is either active or the GCLocker initiated
|
// The GCLocker is either active or the GCLocker initiated
|
||||||
// GC has not yet been performed. Stall until it is and
|
// GC has not yet been performed. Stall until it is and
|
||||||
// then retry the allocation.
|
// then retry the allocation.
|
||||||
GCLocker::stall_until_clear();
|
GCLocker::stall_until_clear();
|
||||||
(*gclocker_retry_count_ret) += 1;
|
gclocker_retry_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// We can reach here if we were unsuccessful in scheduling a
|
// We can reach here if we were unsuccessful in scheduling a
|
||||||
// collection (because another thread beat us to it) or if we were
|
// collection (because another thread beat us to it) or if we were
|
||||||
// stalled due to the GC locker. In either can we should retry the
|
// stalled due to the GC locker. In either can we should retry the
|
||||||
// allocation attempt in case another thread successfully
|
// allocation attempt in case another thread successfully
|
||||||
// performed a collection and reclaimed enough space. Give a
|
// performed a collection and reclaimed enough space.
|
||||||
// warning if we seem to be looping forever.
|
// Humongous object allocation always needs a lock, so we wait for the retry
|
||||||
|
// in the next iteration of the loop, unlike for the regular iteration case.
|
||||||
|
// Give a warning if we seem to be looping forever.
|
||||||
|
|
||||||
if ((QueuedAllocationWarningCount > 0) &&
|
if ((QueuedAllocationWarningCount > 0) &&
|
||||||
(try_count % QueuedAllocationWarningCount == 0)) {
|
(try_count % QueuedAllocationWarningCount == 0)) {
|
||||||
log_warning(gc)("G1CollectedHeap::attempt_allocation_humongous() "
|
log_warning(gc, alloc)("%s: Retried allocation %u times for " SIZE_FORMAT " words",
|
||||||
"retries %d times", try_count);
|
Thread::current()->name(), try_count, word_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1339,7 +1280,6 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size,
|
||||||
context,
|
context,
|
||||||
expect_null_mutator_alloc_region);
|
expect_null_mutator_alloc_region);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
assert(*gc_succeeded, "sanity");
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1349,7 +1289,6 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size,
|
||||||
// do something smarter than full collection to satisfy a failed alloc.)
|
// do something smarter than full collection to satisfy a failed alloc.)
|
||||||
result = expand_and_allocate(word_size, context);
|
result = expand_and_allocate(word_size, context);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
assert(*gc_succeeded, "sanity");
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1401,7 +1340,6 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation(size_t word_size,
|
||||||
succeeded);
|
succeeded);
|
||||||
|
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
assert(*succeeded, "sanity");
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1412,7 +1350,6 @@ HeapWord* G1CollectedHeap::satisfy_failed_allocation(size_t word_size,
|
||||||
// space available is large enough for the allocation, then a more
|
// space available is large enough for the allocation, then a more
|
||||||
// complete compaction phase than we've tried so far might be
|
// complete compaction phase than we've tried so far might be
|
||||||
// appropriate.
|
// appropriate.
|
||||||
assert(*succeeded, "sanity");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2147,7 +2084,7 @@ void G1CollectedHeap::increment_old_marking_cycles_completed(bool concurrent) {
|
||||||
// This notify_all() will ensure that a thread that called
|
// This notify_all() will ensure that a thread that called
|
||||||
// System.gc() with (with ExplicitGCInvokesConcurrent set or not)
|
// System.gc() with (with ExplicitGCInvokesConcurrent set or not)
|
||||||
// and it's waiting for a full GC to finish will be woken up. It is
|
// and it's waiting for a full GC to finish will be woken up. It is
|
||||||
// waiting in VM_G1IncCollectionPause::doit_epilogue().
|
// waiting in VM_G1CollectForAllocation::doit_epilogue().
|
||||||
FullGCCount_lock->notify_all();
|
FullGCCount_lock->notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2175,13 +2112,12 @@ void G1CollectedHeap::collect(GCCause::Cause cause) {
|
||||||
// Schedule an initial-mark evacuation pause that will start a
|
// Schedule an initial-mark evacuation pause that will start a
|
||||||
// concurrent cycle. We're setting word_size to 0 which means that
|
// concurrent cycle. We're setting word_size to 0 which means that
|
||||||
// we are not requesting a post-GC allocation.
|
// we are not requesting a post-GC allocation.
|
||||||
VM_G1IncCollectionPause op(gc_count_before,
|
VM_G1CollectForAllocation op(0, /* word_size */
|
||||||
0, /* word_size */
|
gc_count_before,
|
||||||
true, /* should_initiate_conc_mark */
|
cause,
|
||||||
g1_policy()->max_pause_time_ms(),
|
true, /* should_initiate_conc_mark */
|
||||||
cause);
|
g1_policy()->max_pause_time_ms(),
|
||||||
op.set_allocation_context(AllocationContext::current());
|
AllocationContext::current());
|
||||||
|
|
||||||
VMThread::execute(&op);
|
VMThread::execute(&op);
|
||||||
if (!op.pause_succeeded()) {
|
if (!op.pause_succeeded()) {
|
||||||
if (old_marking_count_before == _old_marking_cycles_started) {
|
if (old_marking_count_before == _old_marking_cycles_started) {
|
||||||
|
@ -2204,11 +2140,12 @@ void G1CollectedHeap::collect(GCCause::Cause cause) {
|
||||||
|
|
||||||
// Schedule a standard evacuation pause. We're setting word_size
|
// Schedule a standard evacuation pause. We're setting word_size
|
||||||
// to 0 which means that we are not requesting a post-GC allocation.
|
// to 0 which means that we are not requesting a post-GC allocation.
|
||||||
VM_G1IncCollectionPause op(gc_count_before,
|
VM_G1CollectForAllocation op(0, /* word_size */
|
||||||
0, /* word_size */
|
gc_count_before,
|
||||||
false, /* should_initiate_conc_mark */
|
cause,
|
||||||
g1_policy()->max_pause_time_ms(),
|
false, /* should_initiate_conc_mark */
|
||||||
cause);
|
g1_policy()->max_pause_time_ms(),
|
||||||
|
AllocationContext::current());
|
||||||
VMThread::execute(&op);
|
VMThread::execute(&op);
|
||||||
} else {
|
} else {
|
||||||
// Schedule a Full GC.
|
// Schedule a Full GC.
|
||||||
|
@ -2619,13 +2556,12 @@ HeapWord* G1CollectedHeap::do_collection_pause(size_t word_size,
|
||||||
bool* succeeded,
|
bool* succeeded,
|
||||||
GCCause::Cause gc_cause) {
|
GCCause::Cause gc_cause) {
|
||||||
assert_heap_not_locked_and_not_at_safepoint();
|
assert_heap_not_locked_and_not_at_safepoint();
|
||||||
VM_G1IncCollectionPause op(gc_count_before,
|
VM_G1CollectForAllocation op(word_size,
|
||||||
word_size,
|
gc_count_before,
|
||||||
false, /* should_initiate_conc_mark */
|
gc_cause,
|
||||||
g1_policy()->max_pause_time_ms(),
|
false, /* should_initiate_conc_mark */
|
||||||
gc_cause);
|
g1_policy()->max_pause_time_ms(),
|
||||||
|
AllocationContext::current());
|
||||||
op.set_allocation_context(AllocationContext::current());
|
|
||||||
VMThread::execute(&op);
|
VMThread::execute(&op);
|
||||||
|
|
||||||
HeapWord* result = op.result();
|
HeapWord* result = op.result();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -125,7 +125,6 @@ class G1CollectedHeap : public CollectedHeap {
|
||||||
friend class VM_CollectForMetadataAllocation;
|
friend class VM_CollectForMetadataAllocation;
|
||||||
friend class VM_G1CollectForAllocation;
|
friend class VM_G1CollectForAllocation;
|
||||||
friend class VM_G1CollectFull;
|
friend class VM_G1CollectFull;
|
||||||
friend class VM_G1IncCollectionPause;
|
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class MutatorAllocRegion;
|
friend class MutatorAllocRegion;
|
||||||
friend class G1FullCollector;
|
friend class G1FullCollector;
|
||||||
|
@ -454,35 +453,20 @@ protected:
|
||||||
virtual HeapWord* mem_allocate(size_t word_size,
|
virtual HeapWord* mem_allocate(size_t word_size,
|
||||||
bool* gc_overhead_limit_was_exceeded);
|
bool* gc_overhead_limit_was_exceeded);
|
||||||
|
|
||||||
// The following three methods take a gc_count_before_ret
|
|
||||||
// parameter which is used to return the GC count if the method
|
|
||||||
// returns NULL. Given that we are required to read the GC count
|
|
||||||
// while holding the Heap_lock, and these paths will take the
|
|
||||||
// Heap_lock at some point, it's easier to get them to read the GC
|
|
||||||
// count while holding the Heap_lock before they return NULL instead
|
|
||||||
// of the caller (namely: mem_allocate()) having to also take the
|
|
||||||
// Heap_lock just to read the GC count.
|
|
||||||
|
|
||||||
// First-level mutator allocation attempt: try to allocate out of
|
// First-level mutator allocation attempt: try to allocate out of
|
||||||
// the mutator alloc region without taking the Heap_lock. This
|
// the mutator alloc region without taking the Heap_lock. This
|
||||||
// should only be used for non-humongous allocations.
|
// should only be used for non-humongous allocations.
|
||||||
inline HeapWord* attempt_allocation(size_t word_size,
|
inline HeapWord* attempt_allocation(size_t word_size);
|
||||||
uint* gc_count_before_ret,
|
|
||||||
uint* gclocker_retry_count_ret);
|
|
||||||
|
|
||||||
// Second-level mutator allocation attempt: take the Heap_lock and
|
// Second-level mutator allocation attempt: take the Heap_lock and
|
||||||
// retry the allocation attempt, potentially scheduling a GC
|
// retry the allocation attempt, potentially scheduling a GC
|
||||||
// pause. This should only be used for non-humongous allocations.
|
// pause. This should only be used for non-humongous allocations.
|
||||||
HeapWord* attempt_allocation_slow(size_t word_size,
|
HeapWord* attempt_allocation_slow(size_t word_size,
|
||||||
AllocationContext_t context,
|
AllocationContext_t context);
|
||||||
uint* gc_count_before_ret,
|
|
||||||
uint* gclocker_retry_count_ret);
|
|
||||||
|
|
||||||
// Takes the Heap_lock and attempts a humongous allocation. It can
|
// Takes the Heap_lock and attempts a humongous allocation. It can
|
||||||
// potentially schedule a GC pause.
|
// potentially schedule a GC pause.
|
||||||
HeapWord* attempt_allocation_humongous(size_t word_size,
|
HeapWord* attempt_allocation_humongous(size_t word_size);
|
||||||
uint* gc_count_before_ret,
|
|
||||||
uint* gclocker_retry_count_ret);
|
|
||||||
|
|
||||||
// Allocation attempt that should be called during safepoints (e.g.,
|
// Allocation attempt that should be called during safepoints (e.g.,
|
||||||
// at the end of a successful GC). expect_null_mutator_alloc_region
|
// at the end of a successful GC). expect_null_mutator_alloc_region
|
||||||
|
@ -1078,6 +1062,11 @@ public:
|
||||||
return _hrm.available() == 0;
|
return _hrm.available() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns whether there are any regions left in the heap for allocation.
|
||||||
|
bool has_regions_left_for_allocation() const {
|
||||||
|
return !is_maximal_no_gc() || num_free_regions() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
// The current number of regions in the heap.
|
// The current number of regions in the heap.
|
||||||
uint num_regions() const { return _hrm.length(); }
|
uint num_regions() const { return _hrm.length(); }
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "gc/g1/heapRegion.inline.hpp"
|
#include "gc/g1/heapRegion.inline.hpp"
|
||||||
#include "gc/g1/heapRegionRemSet.hpp"
|
#include "gc/g1/heapRegionRemSet.hpp"
|
||||||
#include "memory/iterator.inline.hpp"
|
#include "memory/iterator.inline.hpp"
|
||||||
|
#include "oops/access.inline.hpp"
|
||||||
#include "runtime/prefetch.inline.hpp"
|
#include "runtime/prefetch.inline.hpp"
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -87,13 +88,13 @@ inline void G1ScanEvacuatedObjClosure::do_oop_nv(T* p) {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void G1CMOopClosure::do_oop_nv(T* p) {
|
inline void G1CMOopClosure::do_oop_nv(T* p) {
|
||||||
oop obj = oopDesc::load_decode_heap_oop(p);
|
oop obj = RawAccess<MO_VOLATILE>::oop_load(p);
|
||||||
_task->deal_with_reference(obj);
|
_task->deal_with_reference(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void G1RootRegionScanClosure::do_oop_nv(T* p) {
|
inline void G1RootRegionScanClosure::do_oop_nv(T* p) {
|
||||||
T heap_oop = oopDesc::load_heap_oop(p);
|
T heap_oop = RawAccess<MO_VOLATILE>::oop_load(p);
|
||||||
if (oopDesc::is_null(heap_oop)) {
|
if (oopDesc::is_null(heap_oop)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -124,7 +125,7 @@ inline static void check_obj_during_refinement(T* p, oop const obj) {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void G1ConcurrentRefineOopClosure::do_oop_nv(T* p) {
|
inline void G1ConcurrentRefineOopClosure::do_oop_nv(T* p) {
|
||||||
T o = oopDesc::load_heap_oop(p);
|
T o = RawAccess<MO_VOLATILE>::oop_load(p);
|
||||||
if (oopDesc::is_null(o)) {
|
if (oopDesc::is_null(o)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
#include "gc/shared/accessBarrierSupport.inline.hpp"
|
#include "gc/shared/accessBarrierSupport.inline.hpp"
|
||||||
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
|
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
|
||||||
|
|
||||||
template <DecoratorSet decorators, typename T>
|
template <DecoratorSet decorators, typename T>
|
||||||
inline void G1SATBCardTableModRefBS::write_ref_field_pre(T* field) {
|
inline void G1SATBCardTableModRefBS::write_ref_field_pre(T* field) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -33,34 +33,21 @@
|
||||||
#include "gc/shared/isGCActiveMark.hpp"
|
#include "gc/shared/isGCActiveMark.hpp"
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
|
|
||||||
VM_G1CollectForAllocation::VM_G1CollectForAllocation(uint gc_count_before,
|
|
||||||
size_t word_size)
|
|
||||||
: VM_G1OperationWithAllocRequest(gc_count_before, word_size,
|
|
||||||
GCCause::_allocation_failure) {
|
|
||||||
guarantee(word_size != 0, "An allocation should always be requested with this operation.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void VM_G1CollectForAllocation::doit() {
|
|
||||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
|
||||||
GCCauseSetter x(g1h, _gc_cause);
|
|
||||||
|
|
||||||
_result = g1h->satisfy_failed_allocation(_word_size, allocation_context(), &_pause_succeeded);
|
|
||||||
assert(_result == NULL || _pause_succeeded,
|
|
||||||
"if we get back a result, the pause should have succeeded");
|
|
||||||
}
|
|
||||||
|
|
||||||
void VM_G1CollectFull::doit() {
|
void VM_G1CollectFull::doit() {
|
||||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||||
GCCauseSetter x(g1h, _gc_cause);
|
GCCauseSetter x(g1h, _gc_cause);
|
||||||
g1h->do_full_collection(false /* clear_all_soft_refs */);
|
g1h->do_full_collection(false /* clear_all_soft_refs */);
|
||||||
}
|
}
|
||||||
|
|
||||||
VM_G1IncCollectionPause::VM_G1IncCollectionPause(uint gc_count_before,
|
VM_G1CollectForAllocation::VM_G1CollectForAllocation(size_t word_size,
|
||||||
size_t word_size,
|
uint gc_count_before,
|
||||||
bool should_initiate_conc_mark,
|
GCCause::Cause gc_cause,
|
||||||
double target_pause_time_ms,
|
bool should_initiate_conc_mark,
|
||||||
GCCause::Cause gc_cause)
|
double target_pause_time_ms,
|
||||||
: VM_G1OperationWithAllocRequest(gc_count_before, word_size, gc_cause),
|
AllocationContext_t allocation_context)
|
||||||
|
: VM_CollectForAllocation(word_size, gc_count_before, gc_cause),
|
||||||
|
_pause_succeeded(false),
|
||||||
|
_allocation_context(allocation_context),
|
||||||
_should_initiate_conc_mark(should_initiate_conc_mark),
|
_should_initiate_conc_mark(should_initiate_conc_mark),
|
||||||
_target_pause_time_ms(target_pause_time_ms),
|
_target_pause_time_ms(target_pause_time_ms),
|
||||||
_should_retry_gc(false),
|
_should_retry_gc(false),
|
||||||
|
@ -71,8 +58,8 @@ VM_G1IncCollectionPause::VM_G1IncCollectionPause(uint gc_count_before,
|
||||||
_gc_cause = gc_cause;
|
_gc_cause = gc_cause;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VM_G1IncCollectionPause::doit_prologue() {
|
bool VM_G1CollectForAllocation::doit_prologue() {
|
||||||
bool res = VM_G1OperationWithAllocRequest::doit_prologue();
|
bool res = VM_CollectForAllocation::doit_prologue();
|
||||||
if (!res) {
|
if (!res) {
|
||||||
if (_should_initiate_conc_mark) {
|
if (_should_initiate_conc_mark) {
|
||||||
// The prologue can fail for a couple of reasons. The first is that another GC
|
// The prologue can fail for a couple of reasons. The first is that another GC
|
||||||
|
@ -87,7 +74,7 @@ bool VM_G1IncCollectionPause::doit_prologue() {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM_G1IncCollectionPause::doit() {
|
void VM_G1CollectForAllocation::doit() {
|
||||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||||
assert(!_should_initiate_conc_mark || g1h->should_do_concurrent_full_gc(_gc_cause),
|
assert(!_should_initiate_conc_mark || g1h->should_do_concurrent_full_gc(_gc_cause),
|
||||||
"only a GC locker, a System.gc(), stats update, whitebox, or a hum allocation induced GC should start a cycle");
|
"only a GC locker, a System.gc(), stats update, whitebox, or a hum allocation induced GC should start a cycle");
|
||||||
|
@ -95,7 +82,7 @@ void VM_G1IncCollectionPause::doit() {
|
||||||
if (_word_size > 0) {
|
if (_word_size > 0) {
|
||||||
// An allocation has been requested. So, try to do that first.
|
// An allocation has been requested. So, try to do that first.
|
||||||
_result = g1h->attempt_allocation_at_safepoint(_word_size,
|
_result = g1h->attempt_allocation_at_safepoint(_word_size,
|
||||||
allocation_context(),
|
_allocation_context,
|
||||||
false /* expect_null_cur_alloc_region */);
|
false /* expect_null_cur_alloc_region */);
|
||||||
if (_result != NULL) {
|
if (_result != NULL) {
|
||||||
// If we can successfully allocate before we actually do the
|
// If we can successfully allocate before we actually do the
|
||||||
|
@ -144,27 +131,38 @@ void VM_G1IncCollectionPause::doit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_pause_succeeded =
|
// Try a partial collection of some kind.
|
||||||
g1h->do_collection_pause_at_safepoint(_target_pause_time_ms);
|
_pause_succeeded = g1h->do_collection_pause_at_safepoint(_target_pause_time_ms);
|
||||||
if (_pause_succeeded && _word_size > 0) {
|
|
||||||
// An allocation had been requested.
|
if (_pause_succeeded) {
|
||||||
_result = g1h->attempt_allocation_at_safepoint(_word_size,
|
if (_word_size > 0) {
|
||||||
allocation_context(),
|
// An allocation had been requested. Do it, eventually trying a stronger
|
||||||
true /* expect_null_cur_alloc_region */);
|
// kind of GC.
|
||||||
|
_result = g1h->satisfy_failed_allocation(_word_size, _allocation_context, &_pause_succeeded);
|
||||||
|
} else {
|
||||||
|
bool should_upgrade_to_full = !g1h->should_do_concurrent_full_gc(_gc_cause) &&
|
||||||
|
!g1h->has_regions_left_for_allocation();
|
||||||
|
if (should_upgrade_to_full) {
|
||||||
|
// There has been a request to perform a GC to free some space. We have no
|
||||||
|
// information on how much memory has been asked for. In case there are
|
||||||
|
// absolutely no regions left to allocate into, do a maximally compacting full GC.
|
||||||
|
log_info(gc, ergo)("Attempting maximally compacting collection");
|
||||||
|
_pause_succeeded = g1h->do_full_collection(false, /* explicit gc */
|
||||||
|
true /* clear_all_soft_refs */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
guarantee(_pause_succeeded, "Elevated collections during the safepoint must always succeed.");
|
||||||
} else {
|
} else {
|
||||||
assert(_result == NULL, "invariant");
|
assert(_result == NULL, "invariant");
|
||||||
if (!_pause_succeeded) {
|
// The only reason for the pause to not be successful is that, the GC locker is
|
||||||
// Another possible reason reason for the pause to not be successful
|
// active (or has become active since the prologue was executed). In this case
|
||||||
// is that, again, the GC locker is active (and has become active
|
// we should retry the pause after waiting for the GC locker to become inactive.
|
||||||
// since the prologue was executed). In this case we should retry
|
_should_retry_gc = true;
|
||||||
// the pause after waiting for the GC locker to become inactive.
|
|
||||||
_should_retry_gc = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM_G1IncCollectionPause::doit_epilogue() {
|
void VM_G1CollectForAllocation::doit_epilogue() {
|
||||||
VM_G1OperationWithAllocRequest::doit_epilogue();
|
VM_CollectForAllocation::doit_epilogue();
|
||||||
|
|
||||||
// If the pause was initiated by a System.gc() and
|
// If the pause was initiated by a System.gc() and
|
||||||
// +ExplicitGCInvokesConcurrent, we have to wait here for the cycle
|
// +ExplicitGCInvokesConcurrent, we have to wait here for the cycle
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -32,26 +32,8 @@
|
||||||
// VM_operations for the G1 collector.
|
// VM_operations for the G1 collector.
|
||||||
// VM_GC_Operation:
|
// VM_GC_Operation:
|
||||||
// - VM_CGC_Operation
|
// - VM_CGC_Operation
|
||||||
|
// - VM_G1CollectForAllocation
|
||||||
// - VM_G1CollectFull
|
// - VM_G1CollectFull
|
||||||
// - VM_G1OperationWithAllocRequest
|
|
||||||
// - VM_G1CollectForAllocation
|
|
||||||
// - VM_G1IncCollectionPause
|
|
||||||
|
|
||||||
class VM_G1OperationWithAllocRequest : public VM_CollectForAllocation {
|
|
||||||
protected:
|
|
||||||
bool _pause_succeeded;
|
|
||||||
AllocationContext_t _allocation_context;
|
|
||||||
|
|
||||||
public:
|
|
||||||
VM_G1OperationWithAllocRequest(uint gc_count_before,
|
|
||||||
size_t word_size,
|
|
||||||
GCCause::Cause gc_cause)
|
|
||||||
: VM_CollectForAllocation(word_size, gc_count_before, gc_cause),
|
|
||||||
_pause_succeeded(false) {}
|
|
||||||
bool pause_succeeded() { return _pause_succeeded; }
|
|
||||||
void set_allocation_context(AllocationContext_t context) { _allocation_context = context; }
|
|
||||||
AllocationContext_t allocation_context() { return _allocation_context; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class VM_G1CollectFull: public VM_GC_Operation {
|
class VM_G1CollectFull: public VM_GC_Operation {
|
||||||
public:
|
public:
|
||||||
|
@ -62,41 +44,35 @@ public:
|
||||||
virtual VMOp_Type type() const { return VMOp_G1CollectFull; }
|
virtual VMOp_Type type() const { return VMOp_G1CollectFull; }
|
||||||
virtual void doit();
|
virtual void doit();
|
||||||
virtual const char* name() const {
|
virtual const char* name() const {
|
||||||
return "full garbage-first collection";
|
return "G1 Full collection";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class VM_G1CollectForAllocation: public VM_G1OperationWithAllocRequest {
|
class VM_G1CollectForAllocation: public VM_CollectForAllocation {
|
||||||
public:
|
|
||||||
VM_G1CollectForAllocation(uint gc_count_before,
|
|
||||||
size_t word_size);
|
|
||||||
virtual VMOp_Type type() const { return VMOp_G1CollectForAllocation; }
|
|
||||||
virtual void doit();
|
|
||||||
virtual const char* name() const {
|
|
||||||
return "garbage-first collection to satisfy allocation";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class VM_G1IncCollectionPause: public VM_G1OperationWithAllocRequest {
|
|
||||||
private:
|
private:
|
||||||
|
bool _pause_succeeded;
|
||||||
|
AllocationContext_t _allocation_context;
|
||||||
|
|
||||||
bool _should_initiate_conc_mark;
|
bool _should_initiate_conc_mark;
|
||||||
bool _should_retry_gc;
|
bool _should_retry_gc;
|
||||||
double _target_pause_time_ms;
|
double _target_pause_time_ms;
|
||||||
uint _old_marking_cycles_completed_before;
|
uint _old_marking_cycles_completed_before;
|
||||||
public:
|
public:
|
||||||
VM_G1IncCollectionPause(uint gc_count_before,
|
VM_G1CollectForAllocation(size_t word_size,
|
||||||
size_t word_size,
|
uint gc_count_before,
|
||||||
bool should_initiate_conc_mark,
|
GCCause::Cause gc_cause,
|
||||||
double target_pause_time_ms,
|
bool should_initiate_conc_mark,
|
||||||
GCCause::Cause gc_cause);
|
double target_pause_time_ms,
|
||||||
virtual VMOp_Type type() const { return VMOp_G1IncCollectionPause; }
|
AllocationContext_t allocation_context);
|
||||||
|
virtual VMOp_Type type() const { return VMOp_G1CollectForAllocation; }
|
||||||
virtual bool doit_prologue();
|
virtual bool doit_prologue();
|
||||||
virtual void doit();
|
virtual void doit();
|
||||||
virtual void doit_epilogue();
|
virtual void doit_epilogue();
|
||||||
virtual const char* name() const {
|
virtual const char* name() const {
|
||||||
return "garbage-first incremental collection pause";
|
return "G1 collect for allocation";
|
||||||
}
|
}
|
||||||
bool should_retry_gc() const { return _should_retry_gc; }
|
bool should_retry_gc() const { return _should_retry_gc; }
|
||||||
|
bool pause_succeeded() { return _pause_succeeded; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Concurrent GC stop-the-world operations such as remark and cleanup;
|
// Concurrent GC stop-the-world operations such as remark and cleanup;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -147,9 +147,8 @@ public:
|
||||||
// 3) Provide specializations for BarrierSet::GetName and BarrierSet::GetType.
|
// 3) Provide specializations for BarrierSet::GetName and BarrierSet::GetType.
|
||||||
template <DecoratorSet decorators, typename BarrierSetT>
|
template <DecoratorSet decorators, typename BarrierSetT>
|
||||||
class AccessBarrier: protected RawAccessBarrier<decorators> {
|
class AccessBarrier: protected RawAccessBarrier<decorators> {
|
||||||
protected:
|
private:
|
||||||
typedef RawAccessBarrier<decorators> Raw;
|
typedef RawAccessBarrier<decorators> Raw;
|
||||||
typedef typename BarrierSetT::template AccessBarrier<decorators> CRTPAccessBarrier;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Primitive heap accesses. These accessors get resolved when
|
// Primitive heap accesses. These accessors get resolved when
|
||||||
|
|
|
@ -804,7 +804,7 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte
|
||||||
// it is not an interface. The receiver for invokespecial calls within interface
|
// it is not an interface. The receiver for invokespecial calls within interface
|
||||||
// methods must be checked for every call.
|
// methods must be checked for every call.
|
||||||
InstanceKlass* sender = pool->pool_holder();
|
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()) {
|
switch (info.call_kind()) {
|
||||||
case CallInfo::direct_call:
|
case CallInfo::direct_call:
|
||||||
|
@ -822,6 +822,7 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte
|
||||||
case CallInfo::itable_call:
|
case CallInfo::itable_call:
|
||||||
cp_cache_entry->set_itable_call(
|
cp_cache_entry->set_itable_call(
|
||||||
bytecode,
|
bytecode,
|
||||||
|
info.resolved_klass(),
|
||||||
info.resolved_method(),
|
info.resolved_method(),
|
||||||
info.itable_index());
|
info.itable_index());
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -1433,6 +1433,7 @@ C2V_VMENTRY(jobject, getNextStackFrame, (JNIEnv*, jobject compilerToVM, jobject
|
||||||
Deoptimization::reassign_fields(fst.current(), fst.register_map(), scope->objects(), realloc_failures, false);
|
Deoptimization::reassign_fields(fst.current(), fst.register_map(), scope->objects(), realloc_failures, false);
|
||||||
|
|
||||||
GrowableArray<ScopeValue*>* local_values = scope->locals();
|
GrowableArray<ScopeValue*>* local_values = scope->locals();
|
||||||
|
assert(local_values != NULL, "NULL locals");
|
||||||
typeArrayOop array_oop = oopFactory::new_boolArray(local_values->length(), CHECK_NULL);
|
typeArrayOop array_oop = oopFactory::new_boolArray(local_values->length(), CHECK_NULL);
|
||||||
typeArrayHandle array(THREAD, array_oop);
|
typeArrayHandle array(THREAD, array_oop);
|
||||||
for (int i = 0; i < local_values->length(); i++) {
|
for (int i = 0; i < local_values->length(); i++) {
|
||||||
|
@ -1660,7 +1661,6 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv*, jobject, jobject hs_frame
|
||||||
|
|
||||||
GrowableArray<ScopeValue*>* scopeLocals = cvf->scope()->locals();
|
GrowableArray<ScopeValue*>* scopeLocals = cvf->scope()->locals();
|
||||||
StackValueCollection* locals = cvf->locals();
|
StackValueCollection* locals = cvf->locals();
|
||||||
|
|
||||||
if (locals != NULL) {
|
if (locals != NULL) {
|
||||||
for (int i2 = 0; i2 < locals->size(); i2++) {
|
for (int i2 = 0; i2 < locals->size(); i2++) {
|
||||||
StackValue* var = locals->at(i2);
|
StackValue* var = locals->at(i2);
|
||||||
|
@ -1671,6 +1671,27 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv*, jobject, jobject hs_frame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GrowableArray<ScopeValue*>* scopeExpressions = cvf->scope()->expressions();
|
||||||
|
StackValueCollection* expressions = cvf->expressions();
|
||||||
|
if (expressions != NULL) {
|
||||||
|
for (int i2 = 0; i2 < expressions->size(); i2++) {
|
||||||
|
StackValue* var = expressions->at(i2);
|
||||||
|
if (var->type() == T_OBJECT && scopeExpressions->at(i2)->is_object()) {
|
||||||
|
jvalue val;
|
||||||
|
val.l = (jobject) expressions->at(i2)->get_obj()();
|
||||||
|
cvf->update_stack(T_OBJECT, i2, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GrowableArray<MonitorValue*>* scopeMonitors = cvf->scope()->monitors();
|
||||||
|
GrowableArray<MonitorInfo*>* monitors = cvf->monitors();
|
||||||
|
if (monitors != NULL) {
|
||||||
|
for (int i2 = 0; i2 < monitors->length(); i2++) {
|
||||||
|
cvf->update_monitor(i2, monitors->at(i2));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// all locals are materialized by now
|
// all locals are materialized by now
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -351,7 +351,7 @@ class name : AllStatic {
|
||||||
static type name() { \
|
static type name() { \
|
||||||
assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
|
assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
|
||||||
InstanceKlass* ik = klassName::klass(); \
|
InstanceKlass* ik = klassName::klass(); \
|
||||||
address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
|
address addr = ik->static_field_addr(_##name##_offset); \
|
||||||
oop result = HeapAccess<>::oop_load((HeapWord*)addr); \
|
oop result = HeapAccess<>::oop_load((HeapWord*)addr); \
|
||||||
return type(result); \
|
return type(result); \
|
||||||
} \
|
} \
|
||||||
|
@ -359,7 +359,7 @@ class name : AllStatic {
|
||||||
assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
|
assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
|
||||||
assert(klassName::klass() != NULL, "Class not yet loaded: " #klassName); \
|
assert(klassName::klass() != NULL, "Class not yet loaded: " #klassName); \
|
||||||
InstanceKlass* ik = klassName::klass(); \
|
InstanceKlass* ik = klassName::klass(); \
|
||||||
address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
|
address addr = ik->static_field_addr(_##name##_offset); \
|
||||||
HeapAccess<>::oop_store((HeapWord*)addr, x); \
|
HeapAccess<>::oop_store((HeapWord*)addr, x); \
|
||||||
}
|
}
|
||||||
#define STATIC_PRIMITIVE_FIELD(klassName, name, jtypename) \
|
#define STATIC_PRIMITIVE_FIELD(klassName, name, jtypename) \
|
||||||
|
@ -367,13 +367,13 @@ class name : AllStatic {
|
||||||
static jtypename name() { \
|
static jtypename name() { \
|
||||||
assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
|
assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
|
||||||
InstanceKlass* ik = klassName::klass(); \
|
InstanceKlass* ik = klassName::klass(); \
|
||||||
address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
|
address addr = ik->static_field_addr(_##name##_offset); \
|
||||||
return HeapAccess<>::load((jtypename*)addr); \
|
return HeapAccess<>::load((jtypename*)addr); \
|
||||||
} \
|
} \
|
||||||
static void set_##name(jtypename x) { \
|
static void set_##name(jtypename x) { \
|
||||||
assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
|
assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \
|
||||||
InstanceKlass* ik = klassName::klass(); \
|
InstanceKlass* ik = klassName::klass(); \
|
||||||
address addr = ik->static_field_addr(_##name##_offset - InstanceMirrorKlass::offset_of_static_fields()); \
|
address addr = ik->static_field_addr(_##name##_offset); \
|
||||||
HeapAccess<>::store((jtypename*)addr, x); \
|
HeapAccess<>::store((jtypename*)addr, x); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -342,7 +342,7 @@ class Access: public AllStatic {
|
||||||
template <DecoratorSet expected_mo_decorators>
|
template <DecoratorSet expected_mo_decorators>
|
||||||
static void verify_primitive_decorators() {
|
static void verify_primitive_decorators() {
|
||||||
const DecoratorSet primitive_decorators = (AS_DECORATOR_MASK ^ AS_NO_KEEPALIVE) | IN_HEAP |
|
const DecoratorSet primitive_decorators = (AS_DECORATOR_MASK ^ AS_NO_KEEPALIVE) | IN_HEAP |
|
||||||
IN_HEAP_ARRAY | MO_DECORATOR_MASK;
|
IN_HEAP_ARRAY;
|
||||||
verify_decorators<expected_mo_decorators | primitive_decorators>();
|
verify_decorators<expected_mo_decorators | primitive_decorators>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,7 +350,7 @@ class Access: public AllStatic {
|
||||||
static void verify_oop_decorators() {
|
static void verify_oop_decorators() {
|
||||||
const DecoratorSet oop_decorators = AS_DECORATOR_MASK | IN_DECORATOR_MASK |
|
const DecoratorSet oop_decorators = AS_DECORATOR_MASK | IN_DECORATOR_MASK |
|
||||||
(ON_DECORATOR_MASK ^ ON_UNKNOWN_OOP_REF) | // no unknown oop refs outside of the heap
|
(ON_DECORATOR_MASK ^ ON_UNKNOWN_OOP_REF) | // no unknown oop refs outside of the heap
|
||||||
OOP_DECORATOR_MASK | MO_DECORATOR_MASK;
|
OOP_DECORATOR_MASK;
|
||||||
verify_decorators<expected_mo_decorators | oop_decorators>();
|
verify_decorators<expected_mo_decorators | oop_decorators>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,8 +358,7 @@ class Access: public AllStatic {
|
||||||
static void verify_heap_oop_decorators() {
|
static void verify_heap_oop_decorators() {
|
||||||
const DecoratorSet heap_oop_decorators = AS_DECORATOR_MASK | ON_DECORATOR_MASK |
|
const DecoratorSet heap_oop_decorators = AS_DECORATOR_MASK | ON_DECORATOR_MASK |
|
||||||
OOP_DECORATOR_MASK | (IN_DECORATOR_MASK ^
|
OOP_DECORATOR_MASK | (IN_DECORATOR_MASK ^
|
||||||
(IN_ROOT ^ IN_CONCURRENT_ROOT)) | // no root accesses in the heap
|
(IN_ROOT | IN_CONCURRENT_ROOT)); // no root accesses in the heap
|
||||||
MO_DECORATOR_MASK;
|
|
||||||
verify_decorators<expected_mo_decorators | heap_oop_decorators>();
|
verify_decorators<expected_mo_decorators | heap_oop_decorators>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue