OpenJDK / jdk / jdk
changeset 48648:371c6d66d2ec
Merge
author | prr |
---|---|
date | Fri, 19 Jan 2018 09:32:10 -0800 |
parents | e4b03365ddbf 01094f78d990 |
children | 6a014a1e8d2b 9f728dd46c56 |
files | src/java.xml/share/classes/com/sun/org/apache/xalan/internal/utils/FactoryImpl.java |
diffstat | 331 files changed, 6871 insertions(+), 3733 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Thu Jan 18 11:22:28 2018 +0530 +++ b/.hgtags Fri Jan 19 09:32:10 2018 -0800 @@ -465,3 +465,4 @@ 4f830b447edf04fb4a52151a5ad44d9bb60723cd jdk-10+37 e569e83139fdfbecfeb3cd9014d560917787f158 jdk-10+38 5b834ec962366e00d4445352a999a3ac14e26f64 jdk-10+39 +860326263d1f6a83996d7da0f4c66806ae4aa1eb jdk-10+40
--- a/make/autoconf/generated-configure.sh Thu Jan 18 11:22:28 2018 +0530 +++ b/make/autoconf/generated-configure.sh Fri Jan 19 09:32:10 2018 -0800 @@ -902,6 +902,9 @@ VERSION_UPDATE VERSION_INTERIM VERSION_FEATURE +VENDOR_URL_VM_BUG +VENDOR_URL_BUG +VENDOR_URL COMPANY_NAME MACOSX_BUNDLE_ID_BASE MACOSX_BUNDLE_NAME_BASE @@ -1150,6 +1153,9 @@ with_version_minor with_version_security with_vendor_name +with_vendor_url +with_vendor_bug_url +with_vendor_vm_bug_url with_version_string with_version_pre with_version_opt @@ -2074,7 +2080,16 @@ compatibility and is ignored --with-version-security Deprecated. Option is kept for backwards 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-pre Set the base part of the version 'PRE' field (pre-release identifier) ['internal'] @@ -5176,7 +5191,7 @@ #CUSTOM_AUTOCONF_INCLUDE # 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 @@ if test "x$with_vendor_name" = xyes; then as_fn_error $? "--with-vendor-name must have a value" "$LINENO" 5 elif ! [[ $with_vendor_name =~ ^[[:print:]]*$ ]] ; then - as_fn_error $? "--with--vendor-name contains non-printing characters: $with_vendor_name" "$LINENO" 5 - else + as_fn_error $? "--with-vendor-name contains non-printing characters: $with_vendor_name" "$LINENO" 5 + 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" 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 # If --with-version-string is set, process it first. It is possible to
--- a/make/autoconf/jdk-version.m4 Thu Jan 18 11:22:28 2018 +0530 +++ b/make/autoconf/jdk-version.m4 Fri Jan 19 09:32:10 2018 -0800 @@ -80,16 +80,55 @@ # The vendor name, if any 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 AC_MSG_ERROR([--with-vendor-name must have a value]) elif [ ! [[ $with_vendor_name =~ ^[[:print:]]*$ ]] ]; then - AC_MSG_ERROR([--with--vendor-name contains non-printing characters: $with_vendor_name]) - else + AC_MSG_ERROR([--with-vendor-name contains non-printing characters: $with_vendor_name]) + 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" fi 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 # If --with-version-string is set, process it first. It is possible to
--- a/make/autoconf/spec.gmk.in Thu Jan 18 11:22:28 2018 +0530 +++ b/make/autoconf/spec.gmk.in Fri Jan 19 09:32:10 2018 -0800 @@ -142,6 +142,20 @@ 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 ## Building blocks of the version string @@ -201,16 +215,30 @@ -DVERSION_CLASSFILE_MINOR=$(VERSION_CLASSFILE_MINOR) \ # -# 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@ +ifneq ($(COMPANY_NAME),) + # COMPANY_NAME is set to "N/A" in $AUTOCONF_DIR/version-numbers by default, + # but can be customized with the '--with-vendor-name' configure option. + # Only export "VENDOR" to the build if COMPANY_NAME contains a real value. + # Otherwise the default value for VENDOR, which is used to set the "java.vendor" + # and "java.vm.vendor" properties is hard-coded into the source code (i.e. in + # System.c in the jdk for "vm.vendor" and vm_version.cpp in the VM for "java.vm.vendor") + ifneq ($(COMPANY_NAME), N/A) + VERSION_CFLAGS += -DVENDOR='"$(COMPANY_NAME)"' + 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. RUNTIME_NAME=$(PRODUCT_NAME) $(PRODUCT_SUFFIX)
--- a/make/data/jdwp/jdwp.spec Thu Jan 18 11:22:28 2018 +0530 +++ b/make/data/jdwp/jdwp.spec Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -869,7 +869,6 @@ "section in " "<cite>The Java™ Virtual Machine Specification</cite>. " "Since JDWP version 1.5." - "<p> (Out (referenceType refType "The reference type ID.") ) @@ -2723,7 +2722,6 @@ "<P>" "The events that are grouped in a composite event are restricted in the " "following ways: " - "<P>" "<UL>" "<LI>Only with other thread start events for the same thread:" " <UL>"
--- a/make/hotspot/lib/CompileJvm.gmk Thu Jan 18 11:22:28 2018 +0530 +++ b/make/hotspot/lib/CompileJvm.gmk Fri Jan 19 09:32:10 2018 -0800 @@ -222,6 +222,7 @@ CFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \ CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \ vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \ + arguments.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \ DISABLED_WARNINGS_clang := tautological-compare, \ DISABLED_WARNINGS_xlc := 1540-0216 1540-0198 1540-1090 1540-1639 \ 1540-1088 1500-010, \
--- a/make/jdk/src/classes/build/tools/jdwpgen/AbstractCommandNode.java Thu Jan 18 11:22:28 2018 +0530 +++ b/make/jdk/src/classes/build/tools/jdwpgen/AbstractCommandNode.java Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -30,8 +30,8 @@ class AbstractCommandNode extends AbstractNamedNode { void document(PrintWriter writer) { - writer.println("<h5><a name=\"" + context.whereC + "\">" + name + - " Command</a> (" + nameNode.value() + ")</h5>"); + writer.println("<h5 id=\"" + context.whereC + "\">" + name + + " Command (" + nameNode.value() + ")</h5>"); writer.println(comment()); writer.println("<dl>"); for (Node node : components) {
--- a/make/jdk/src/classes/build/tools/jdwpgen/AbstractNamedNode.java Thu Jan 18 11:22:28 2018 +0530 +++ b/make/jdk/src/classes/build/tools/jdwpgen/AbstractNamedNode.java Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -62,8 +62,8 @@ } void document(PrintWriter writer) { - writer.println("<h4><a name=" + name + ">" + name + - " Command Set</a></h4>"); + writer.println("<h4 id=\"" + name + "\">" + name + + " Command Set</h4>"); for (Node node : components) { node.document(writer); }
--- a/make/jdk/src/classes/build/tools/jdwpgen/AbstractTypeListNode.java Thu Jan 18 11:22:28 2018 +0530 +++ b/make/jdk/src/classes/build/tools/jdwpgen/AbstractTypeListNode.java Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -43,11 +43,11 @@ if (components.isEmpty()) { writer.println("<dd>(None)"); } 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) { - 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(""); for (Node node : components) { node.document(writer);
--- a/make/jdk/src/classes/build/tools/jdwpgen/CommandSetNode.java Thu Jan 18 11:22:28 2018 +0530 +++ b/make/jdk/src/classes/build/tools/jdwpgen/CommandSetNode.java Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -38,8 +38,8 @@ } void document(PrintWriter writer) { - writer.println("<h4><a name=\"" + context.whereC + "\">" + name + - " Command Set</a> (" + + writer.println("<h4 id=\"" + context.whereC + "\">" + name + + " Command Set (" + nameNode.value() + ")</h4>"); writer.println(comment()); for (Node node : components) { @@ -51,11 +51,13 @@ writer.print("<li><a href=\"#" + context.whereC + "\">"); writer.println(name() + "</a> Command Set (" + nameNode.value() + ")"); - writer.println("<ul>"); - for (Node node : components) { - node.documentIndex(writer); + if (components.size() > 0) { + writer.println("<ul>"); + for (Node node : components) { + node.documentIndex(writer); + } + writer.println("</ul>"); } - writer.println("</ul>"); } void genJavaClassSpecifics(PrintWriter writer, int depth) {
--- a/make/jdk/src/classes/build/tools/jdwpgen/ConstantSetNode.java Thu Jan 18 11:22:28 2018 +0530 +++ b/make/jdk/src/classes/build/tools/jdwpgen/ConstantSetNode.java Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -54,15 +54,15 @@ } void document(PrintWriter writer) { - writer.println("<h4><a name=\"" + context.whereC + "\">" + name + - " Constants</a></h4>"); + writer.println("<h4 id=\"" + context.whereC + "\">" + name + + " Constants</h4>"); writer.println(comment()); - writer.println("<dd><table border=1 cellpadding=3 cellspacing=0 width=\"90%\" summary=\"\"><tr>"); - writer.println("<th width=\"20%\"><th width=\"5%\"><th width=\"65%\">"); + writer.println("<table><tr>"); + writer.println("<th style=\"width: 20%\"><th style=\"width: 5%\"><th style=\"width: 65%\">"); ConstantNode n; for (Node node : components) { n = (ConstantNode)node; - writer.println("<a NAME=\"" + name + "_" + n.name + "\"></a>"); + writer.println("<span id=\"" + name + "_" + n.name + "\"></span>"); n.document(writer); } writer.println("</table>");
--- a/make/jdk/src/classes/build/tools/jdwpgen/ErrorSetNode.java Thu Jan 18 11:22:28 2018 +0530 +++ b/make/jdk/src/classes/build/tools/jdwpgen/ErrorSetNode.java Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ if (components.isEmpty()) { writer.println("<dd>(None)"); } else { - writer.println("<dd><table border=1 cellpadding=3 cellspacing=0 width=\"90%\" summary=\"\">"); + writer.println("<dd><table>"); for (Node node : components) { node.document(writer); }
--- a/make/jdk/src/classes/build/tools/jdwpgen/RootNode.java Thu Jan 18 11:22:28 2018 +0530 +++ b/make/jdk/src/classes/build/tools/jdwpgen/RootNode.java Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -41,11 +41,22 @@ void document(PrintWriter writer) { writer.println("<!DOCTYPE html>"); - writer.println("<html><head><title>" + comment() + "</title></head>"); - writer.println("<body bgcolor=\"white\">"); + writer.println("<html lang=\"en\">"); + 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) { node.documentIndex(writer); } + writer.println("</ul>"); for (Node node : components) { node.document(writer); }
--- a/make/test/JtregNativeHotspot.gmk Thu Jan 18 11:22:28 2018 +0530 +++ b/make/test/JtregNativeHotspot.gmk Fri Jan 19 09:32:10 2018 -0800 @@ -44,6 +44,7 @@ # Add more directories here when needed. BUILD_HOTSPOT_JTREG_NATIVE_SRC += \ $(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/cslocker \ $(TOPDIR)/test/hotspot/jtreg/native_sanity \
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -2295,23 +2295,32 @@ 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){ \ starti; \ - /* The encodings for the immh:immb fields (bits 22:16) are \ - * 0001 xxx 8B/16B, shift = xxx \ - * 001x xxx 4H/8H, shift = xxxx \ - * 01xx xxx 2S/4S, shift = xxxxx \ - * 1xxx xxx 1D/2D, shift = xxxxxx (1D is RESERVED) \ + /* The encodings for the immh:immb fields (bits 22:16) in *SHR are \ + * 0001 xxx 8B/16B, shift = 16 - UInt(immh:immb) \ + * 001x xxx 4H/8H, shift = 32 - UInt(immh:immb) \ + * 01xx xxx 2S/4S, shift = 64 - UInt(immh:immb) \ + * 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"); \ + 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((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(sshr, 0, 0b000001); - INSN(ushr, 1, 0b000001); + INSN(shl, 0, 0b010101, /* isSHR = */ false); + INSN(sshr, 0, 0b000001, /* isSHR = */ true); + INSN(ushr, 1, 0b000001, /* isSHR = */ true); #undef INSN
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -774,7 +774,7 @@ __ load_klass(rscratch1, receiver); __ ldr(tmp, Address(holder, CompiledICHolder::holder_klass_offset())); __ cmp(rscratch1, tmp); - __ ldr(rmethod, Address(holder, CompiledICHolder::holder_method_offset())); + __ ldr(rmethod, Address(holder, CompiledICHolder::holder_metadata_offset())); __ br(Assembler::EQ, ok); __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
--- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -2475,49 +2475,65 @@ // On success, the result will be in method_result, and execution falls through. // On failure, execution transfers to the given label. void MacroAssembler::lookup_interface_method(Register Rklass, - Register Rinterf, - Register Rindex, + Register Rintf, + RegisterOrConstant itable_index, Register method_result, - Register temp_reg1, - Register temp_reg2, + Register Rscan, + Register Rtmp, Label& L_no_such_interface) { - assert_different_registers(Rklass, Rinterf, temp_reg1, temp_reg2, Rindex); - - Register Ritable = temp_reg1; + assert_different_registers(Rklass, Rintf, Rscan, Rtmp); + + const int entry_size = itableOffsetEntry::size() * HeapWordSize; + assert(itableOffsetEntry::interface_offset_in_bytes() == 0, "not added for convenience"); // Compute start of first itableOffsetEntry (which is at the end of the vtable) const int base = in_bytes(Klass::vtable_start_offset()); const int scale = exact_log2(vtableEntry::size_in_bytes()); - ldr_s32(temp_reg2, Address(Rklass, Klass::vtable_length_offset())); // Get length of vtable - add(Ritable, Rklass, base); - add(Ritable, Ritable, AsmOperand(temp_reg2, lsl, scale)); - - Label entry, search; - - b(entry); - - bind(search); - add(Ritable, Ritable, itableOffsetEntry::size() * HeapWordSize); - - bind(entry); - - // Check that the entry is non-null. A null entry means that the receiver - // class doesn't implement the interface, and wasn't the same as the - // receiver class checked when the interface was resolved. - - ldr(temp_reg2, Address(Ritable, itableOffsetEntry::interface_offset_in_bytes())); - cbz(temp_reg2, L_no_such_interface); - - cmp(Rinterf, temp_reg2); - b(search, ne); - - ldr_s32(temp_reg2, Address(Ritable, itableOffsetEntry::offset_offset_in_bytes())); - add(temp_reg2, temp_reg2, Rklass); // Add offset to Klass* - assert(itableMethodEntry::size() * HeapWordSize == wordSize, "adjust the scaling in the code below"); - assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust the offset in the code below"); - - ldr(method_result, Address::indexed_ptr(temp_reg2, Rindex)); + ldr_s32(Rtmp, Address(Rklass, Klass::vtable_length_offset())); // Get length of vtable + add(Rscan, Rklass, base); + add(Rscan, Rscan, AsmOperand(Rtmp, lsl, scale)); + + // Search through the itable for an interface equal to incoming Rintf + // itable looks like [intface][offset][intface][offset][intface][offset] + + 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 + +#ifdef AARCH64 + b(L_no_such_interface); + bind(found); +#else + // CF == 0 means we reached the end of itable without finding icklass + b(L_no_such_interface, cc); +#endif // !AARCH64 + + if (method_result != noreg) { + // Interface found at previous position of Rscan, now load the method + ldr_s32(Rtmp, Address(Rscan, itableOffsetEntry::offset_offset_in_bytes() - entry_size)); + if (itable_index.is_register()) { + add(Rtmp, Rtmp, Rklass); // Add offset to Klass* + assert(itableMethodEntry::size() * HeapWordSize == wordSize, "adjust the scaling in the code below"); + assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust the offset in the code below"); + ldr(method_result, Address::indexed_ptr(Rtmp, itable_index.as_register())); + } else { + int method_offset = itableMethodEntry::size() * HeapWordSize * itable_index.as_constant() + + itableMethodEntry::method_offset_in_bytes(); + add_slow(method_result, Rklass, method_offset); + ldr(method_result, Address(method_result, Rtmp)); + } + } } #ifdef COMPILER2
--- a/src/hotspot/cpu/arm/macroAssembler_arm.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/arm/macroAssembler_arm.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1316,7 +1316,7 @@ void lookup_interface_method(Register recv_klass, Register intf_klass, - Register itable_index, + RegisterOrConstant itable_index, Register method_result, Register temp_reg1, Register temp_reg2,
--- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -984,7 +984,7 @@ __ load_klass(receiver_klass, receiver); __ ldr(holder_klass, Address(Ricklass, CompiledICHolder::holder_klass_offset())); - __ ldr(Rmethod, Address(Ricklass, CompiledICHolder::holder_method_offset())); + __ ldr(Rmethod, Address(Ricklass, CompiledICHolder::holder_metadata_offset())); __ cmp(receiver_klass, holder_klass); #ifdef AARCH64
--- a/src/hotspot/cpu/arm/templateTable_arm.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/arm/templateTable_arm.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -4198,7 +4198,7 @@ const Register Rflags = R3_tmp; const Register Rklass = R3_tmp; - prepare_invoke(byte_no, Rinterf, Rindex, Rrecv, Rflags); + prepare_invoke(byte_no, Rinterf, Rmethod, Rrecv, Rflags); // Special case of invokeinterface called for virtual method of // java.lang.Object. See cpCacheOop.cpp for details. @@ -4207,56 +4207,39 @@ Label notMethod; __ tbz(Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift, notMethod); - __ mov(Rmethod, Rindex); invokevirtual_helper(Rmethod, Rrecv, Rflags); __ bind(notMethod); // Get receiver klass into Rklass - also a null check __ load_klass(Rklass, Rrecv); + Label no_such_interface; + + // Receiver subtype check against REFC. + __ lookup_interface_method(// inputs: rec. class, interface + Rklass, Rinterf, noreg, + // outputs: scan temp. reg1, scan temp. reg2 + noreg, Ritable, Rtemp, + no_such_interface); + // profile this call __ profile_virtual_call(R0_tmp, Rklass); - // Compute start of first itableOffsetEntry (which is at the end of the vtable) - const int base = in_bytes(Klass::vtable_start_offset()); - assert(vtableEntry::size() == 1, "adjust the scaling in the code below"); - __ ldr_s32(Rtemp, Address(Rklass, Klass::vtable_length_offset())); // Get length of vtable - __ add(Ritable, Rklass, base); - __ add(Ritable, Ritable, AsmOperand(Rtemp, lsl, LogBytesPerWord)); - - Label entry, search, interface_ok; - - __ b(entry); - - __ bind(search); - __ add(Ritable, Ritable, itableOffsetEntry::size() * HeapWordSize); - - __ bind(entry); - - // Check that the entry is non-null. A null entry means that the receiver - // class doesn't implement the interface, and wasn't the same as the - // receiver class checked when the interface was resolved. - - __ ldr(Rtemp, Address(Ritable, itableOffsetEntry::interface_offset_in_bytes())); - __ cbnz(Rtemp, interface_ok); - - // throw exception - __ call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::throw_IncompatibleClassChangeError)); - - // the call_VM checks for exception, so we should never return here. - __ should_not_reach_here(); - - __ bind(interface_ok); - - __ cmp(Rinterf, Rtemp); - __ b(search, ne); - - __ ldr_s32(Rtemp, Address(Ritable, itableOffsetEntry::offset_offset_in_bytes())); - __ add(Rtemp, Rtemp, Rklass); // Add offset to Klass* - assert(itableMethodEntry::size() == 1, "adjust the scaling in the code below"); - - __ ldr(Rmethod, Address::indexed_ptr(Rtemp, Rindex)); + // Get declaring interface class from method + __ ldr(Rtemp, Address(Rmethod, Method::const_offset())); + __ ldr(Rtemp, Address(Rtemp, ConstMethod::constants_offset())); + __ ldr(Rinterf, Address(Rtemp, ConstantPool::pool_holder_offset_in_bytes())); + + // 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); + + __ lookup_interface_method(// inputs: rec. class, interface + Rklass, Rinterf, Rindex, + // outputs: scan temp. reg1, scan temp. reg2 + Rmethod, Ritable, Rtemp, + no_such_interface); // Rmethod: Method* to call @@ -4278,6 +4261,13 @@ // do the call __ jump_from_interpreted(Rmethod); + + // throw exception + __ bind(no_such_interface); + __ restore_method(); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError)); + // the call_VM checks for exception, so we should never return here. + __ should_not_reach_here(); } void TemplateTable::invokehandle(int byte_no) { @@ -4345,7 +4335,6 @@ Label done; Label initialize_header; Label initialize_object; // including clearing the fields - Label allocate_shared; const bool allow_shared_alloc = Universe::heap()->supports_inline_contig_alloc(); @@ -4390,13 +4379,19 @@ // 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); + // 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 - // 1) Try to allocate in the TLAB - // 2) if fail and the object is large allocate in the shared Eden - // 3) if the above fails (or is not applicable), go to a slow case - // (creates a new TLAB, etc.) - + // If TLAB is enabled OR inline contiguous is enabled: + // Initialize the allocation. + // Exit. + // + // Go to slow path. if (UseTLAB) { const Register Rtlab_top = R1_tmp; const Register Rtlab_end = R2_tmp; @@ -4406,7 +4401,7 @@ __ ldr(Rtlab_end, Address(Rthread, in_bytes(JavaThread::tlab_end_offset()))); __ add(Rtlab_top, Robj, Rsize); __ 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())); if (ZeroTLAB) { // the fields have been already cleared @@ -4415,45 +4410,43 @@ // initialize both the header and fields __ b(initialize_object); } - } - - // Allocation in the shared Eden, if allowed. - if (allow_shared_alloc) { - __ bind(allocate_shared); - - 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); - - // 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); + } 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); + + // 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 - __ ldxr(Robj, Rheap_top_addr); + __ ldxr(Robj, Rheap_top_addr); #else - __ ldr(Robj, Address(Rheap_top_addr)); + __ ldr(Robj, Address(Rheap_top_addr)); #endif // AARCH64 - __ ldr(Rheap_end, Address(Rheap_top_addr, (intptr_t)Universe::heap()->end_addr()-(intptr_t)Universe::heap()->top_addr())); - __ add(Rheap_top, Robj, Rsize); - __ cmp(Rheap_top, Rheap_end); - __ b(slow_case, hi); - - // Update heap top atomically. - // If someone beats us on the allocation, try again, otherwise continue. + __ ldr(Rheap_end, Address(Rheap_top_addr, (intptr_t)Universe::heap()->end_addr()-(intptr_t)Universe::heap()->top_addr())); + __ add(Rheap_top, Robj, Rsize); + __ cmp(Rheap_top, Rheap_end); + __ b(slow_case, hi); + + // Update heap top atomically. + // If someone beats us on the allocation, try again, otherwise continue. #ifdef AARCH64 - __ stxr(Rtemp2, Rheap_top, Rheap_top_addr); - __ cbnz_w(Rtemp2, retry); + __ stxr(Rtemp2, Rheap_top, Rheap_top_addr); + __ cbnz_w(Rtemp2, retry); #else - __ atomic_cas_bool(Robj, Rheap_top, Rheap_top_addr, 0, Rheap_end/*scratched*/); - __ b(retry, ne); + __ atomic_cas_bool(Robj, Rheap_top, Rheap_top_addr, 0, Rheap_end/*scratched*/); + __ b(retry, ne); #endif // AARCH64 - __ incr_allocated_bytes(Rsize, Rtemp); + __ incr_allocated_bytes(Rsize, Rtemp); + } } if (UseTLAB || allow_shared_alloc) {
--- a/src/hotspot/cpu/arm/vtableStubs_arm.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/arm/vtableStubs_arm.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -28,6 +28,7 @@ #include "code/vtableStubs.hpp" #include "interp_masm_arm.hpp" #include "memory/resourceArea.hpp" +#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klassVtable.hpp" #include "runtime/sharedRuntime.hpp" @@ -118,67 +119,48 @@ // R0-R3 / R0-R7 registers hold the arguments and cannot be spoiled const Register Rclass = AARCH64_ONLY(R9) NOT_AARCH64(R4); - const Register Rlength = AARCH64_ONLY(R10) NOT_AARCH64(R5); + const Register Rintf = AARCH64_ONLY(R10) NOT_AARCH64(R5); const Register Rscan = AARCH64_ONLY(R11) NOT_AARCH64(R6); - const Register tmp = Rtemp; - assert_different_registers(Ricklass, Rclass, Rlength, Rscan, tmp); + assert_different_registers(Ricklass, Rclass, Rintf, Rscan, Rtemp); // Calculate the start of itable (itable goes after vtable) const int scale = exact_log2(vtableEntry::size_in_bytes()); address npe_addr = __ pc(); __ load_klass(Rclass, R0); - __ ldr_s32(Rlength, Address(Rclass, Klass::vtable_length_offset())); - __ add(Rscan, Rclass, in_bytes(Klass::vtable_start_offset())); - __ add(Rscan, Rscan, AsmOperand(Rlength, lsl, scale)); + Label L_no_such_interface; - // Search through the itable for an interface equal to incoming Ricklass - // itable looks like [intface][offset][intface][offset][intface][offset] - const int entry_size = itableOffsetEntry::size() * HeapWordSize; - assert(itableOffsetEntry::interface_offset_in_bytes() == 0, "not added for convenience"); + // Receiver subtype check against REFC. + __ ldr(Rintf, Address(Ricklass, CompiledICHolder::holder_klass_offset())); + __ lookup_interface_method(// inputs: rec. class, interface, itable index + Rclass, Rintf, noreg, + // outputs: temp reg1, temp reg2 + noreg, Rscan, Rtemp, + L_no_such_interface); - Label loop; - __ bind(loop); - __ ldr(tmp, Address(Rscan, entry_size, post_indexed)); -#ifdef AARCH64 - Label found; - __ cmp(tmp, Ricklass); - __ b(found, eq); - __ cbnz(tmp, loop); -#else - __ cmp(tmp, Ricklass); // set ZF and CF if interface is found - __ cmn(tmp, 0, ne); // check if tmp == 0 and clear CF if it is - __ b(loop, ne); -#endif // AARCH64 - - assert(StubRoutines::throw_IncompatibleClassChangeError_entry() != NULL, "Check initialization order"); -#ifdef AARCH64 - __ jump(StubRoutines::throw_IncompatibleClassChangeError_entry(), relocInfo::runtime_call_type, tmp); - __ bind(found); -#else - // CF == 0 means we reached the end of itable without finding icklass - __ jump(StubRoutines::throw_IncompatibleClassChangeError_entry(), relocInfo::runtime_call_type, noreg, cc); -#endif // !AARCH64 - - // Interface found at previous position of Rscan, now load the method oop - __ ldr_s32(tmp, Address(Rscan, itableOffsetEntry::offset_offset_in_bytes() - entry_size)); - { - const int method_offset = itableMethodEntry::size() * HeapWordSize * itable_index + - itableMethodEntry::method_offset_in_bytes(); - __ add_slow(Rmethod, Rclass, method_offset); - } - __ ldr(Rmethod, Address(Rmethod, tmp)); + // Get Method* and entry point for compiler + __ ldr(Rintf, Address(Ricklass, CompiledICHolder::holder_metadata_offset())); + __ lookup_interface_method(// inputs: rec. class, interface, itable index + Rclass, Rintf, itable_index, + // outputs: temp reg1, temp reg2, temp reg3 + Rmethod, Rscan, Rtemp, + L_no_such_interface); address ame_addr = __ pc(); #ifdef AARCH64 - __ ldr(tmp, Address(Rmethod, Method::from_compiled_offset())); - __ br(tmp); + __ ldr(Rtemp, Address(Rmethod, Method::from_compiled_offset())); + __ br(Rtemp); #else __ ldr(PC, Address(Rmethod, Method::from_compiled_offset())); #endif // AARCH64 + __ bind(L_no_such_interface); + + assert(StubRoutines::throw_IncompatibleClassChangeError_entry() != NULL, "check initialization order"); + __ jump(StubRoutines::throw_IncompatibleClassChangeError_entry(), relocInfo::runtime_call_type, Rtemp); + masm->flush(); if (PrintMiscellaneous && (WizardMode || Verbose)) { @@ -205,7 +187,7 @@ instr_count = NOT_AARCH64(4) AARCH64_ONLY(5); } else { // itable stub size - instr_count = NOT_AARCH64(20) AARCH64_ONLY(20); + instr_count = NOT_AARCH64(31) AARCH64_ONLY(31); } #ifdef AARCH64
--- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,8 +34,8 @@ #include "runtime/basicLock.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/os.hpp" +#include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#include "runtime/sharedRuntime.hpp" #include "utilities/align.hpp"
--- a/src/hotspot/cpu/ppc/c1_globals_ppc.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/c1_globals_ppc.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,36 +33,36 @@ // (see c1_globals.hpp) #ifndef TIERED -define_pd_global(bool, BackgroundCompilation, true ); -define_pd_global(bool, CICompileOSR, true ); -define_pd_global(bool, InlineIntrinsics, true ); -define_pd_global(bool, PreferInterpreterNativeStubs, false); -define_pd_global(bool, ProfileTraps, false); -define_pd_global(bool, UseOnStackReplacement, true ); -define_pd_global(bool, TieredCompilation, false); -define_pd_global(intx, CompileThreshold, 1000 ); +define_pd_global(bool, BackgroundCompilation, true); +define_pd_global(bool, CICompileOSR, true); +define_pd_global(bool, InlineIntrinsics, true); +define_pd_global(bool, PreferInterpreterNativeStubs, false); +define_pd_global(bool, ProfileTraps, false); +define_pd_global(bool, UseOnStackReplacement, true); +define_pd_global(bool, TieredCompilation, false); +define_pd_global(intx, CompileThreshold, 1000); -define_pd_global(intx, OnStackReplacePercentage, 1400 ); -define_pd_global(bool, UseTLAB, true ); -define_pd_global(bool, ProfileInterpreter, false); -define_pd_global(intx, FreqInlineSize, 325 ); -define_pd_global(bool, ResizeTLAB, true ); -define_pd_global(intx, ReservedCodeCacheSize, 32*M ); -define_pd_global(intx, CodeCacheExpansionSize, 32*K ); -define_pd_global(uintx,CodeCacheMinBlockLength, 1); -define_pd_global(uintx,MetaspaceSize, 12*M ); -define_pd_global(bool, NeverActAsServerClassMachine, true ); -define_pd_global(intx, NewSizeThreadIncrease, 16*K ); -define_pd_global(uint64_t,MaxRAM, 1ULL*G); -define_pd_global(intx, InitialCodeCacheSize, 160*K); +define_pd_global(intx, OnStackReplacePercentage, 1400); +define_pd_global(bool, UseTLAB, true); +define_pd_global(bool, ProfileInterpreter, false); +define_pd_global(intx, FreqInlineSize, 325 ); +define_pd_global(bool, ResizeTLAB, true); +define_pd_global(uintx, ReservedCodeCacheSize, 32*M); +define_pd_global(uintx, CodeCacheExpansionSize, 32*K); +define_pd_global(uintx, CodeCacheMinBlockLength, 1); +define_pd_global(size_t, MetaspaceSize, 12*M); +define_pd_global(bool, NeverActAsServerClassMachine, true); +define_pd_global(size_t, NewSizeThreadIncrease, 16*K); +define_pd_global(uint64_t, MaxRAM, 1ULL*G); +define_pd_global(uintx, InitialCodeCacheSize, 160*K); #endif // !TIERED -define_pd_global(bool, UseTypeProfile, false); -define_pd_global(bool, RoundFPResults, false); +define_pd_global(bool, UseTypeProfile, false); +define_pd_global(bool, RoundFPResults, false); -define_pd_global(bool, LIRFillDelaySlots, false); -define_pd_global(bool, OptimizeSinglePrecision, false); -define_pd_global(bool, CSEArrayLength, true ); -define_pd_global(bool, TwoOperandLIRForm, false); +define_pd_global(bool, LIRFillDelaySlots, false); +define_pd_global(bool, OptimizeSinglePrecision, false); +define_pd_global(bool, CSEArrayLength, true); +define_pd_global(bool, TwoOperandLIRForm, false); #endif // CPU_PPC_VM_C1_GLOBALS_PPC_HPP
--- a/src/hotspot/cpu/ppc/c2_globals_ppc.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/c2_globals_ppc.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ define_pd_global(bool, ProfileTraps, true); define_pd_global(bool, UseOnStackReplacement, 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, OnStackReplacePercentage, 140); @@ -78,27 +78,27 @@ // x.f = 0 // loc = x.f // NullCheck loc -define_pd_global(bool, OptoScheduling, false); -define_pd_global(bool, IdealizeClearArrayNode, true); +define_pd_global(bool, OptoScheduling, false); +define_pd_global(bool, IdealizeClearArrayNode, true); -define_pd_global(intx, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize -define_pd_global(intx, ReservedCodeCacheSize, 256*M); -define_pd_global(intx, NonProfiledCodeHeapSize, 125*M); -define_pd_global(intx, ProfiledCodeHeapSize, 126*M); -define_pd_global(intx, NonNMethodCodeHeapSize, 5*M ); -define_pd_global(intx, CodeCacheExpansionSize, 64*K); +define_pd_global(uintx, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize +define_pd_global(uintx, ReservedCodeCacheSize, 256*M); +define_pd_global(uintx, NonProfiledCodeHeapSize, 125*M); +define_pd_global(uintx, ProfiledCodeHeapSize, 126*M); +define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M ); +define_pd_global(uintx, CodeCacheExpansionSize, 64*K); // Ergonomics related flags -define_pd_global(uint64_t, MaxRAM, 4ULL*G); -define_pd_global(uintx, CodeCacheMinBlockLength, 4); -define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(uint64_t, MaxRAM, 128ULL*G); +define_pd_global(uintx, CodeCacheMinBlockLength, 4); +define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); -define_pd_global(bool, TrapBasedRangeChecks, true); +define_pd_global(bool, TrapBasedRangeChecks, true); // Heap related flags -define_pd_global(size_t, MetaspaceSize, ScaleForWordSize(16*M)); +define_pd_global(size_t, MetaspaceSize, ScaleForWordSize(16*M)); // Ergonomics related flags -define_pd_global(bool, NeverActAsServerClassMachine, false); +define_pd_global(bool, NeverActAsServerClassMachine, false); #endif // CPU_PPC_VM_C2_GLOBALS_PPC_HPP
--- a/src/hotspot/cpu/ppc/c2_init_ppc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/c2_init_ppc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,11 +29,11 @@ #include "runtime/globals.hpp" #include "utilities/debug.hpp" -// processor dependent initialization for ppc +// Processor dependent initialization of C2 compiler for ppc. void Compile::pd_compiler2_init() { - // Power7 and later + // Power7 and later. if (PowerArchitecturePPC64 > 6) { if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { FLAG_SET_ERGO(bool, UsePopCountInstruction, true);
--- a/src/hotspot/cpu/ppc/globals_ppc.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/globals_ppc.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 SAP SE. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,14 +86,14 @@ define_pd_global(bool, ThreadLocalHandshakes, true); // Platform dependent flag handling: flags only defined on this platform. -#define ARCH_FLAGS(develop, \ - product, \ - diagnostic, \ +#define ARCH_FLAGS(develop, \ + product, \ + diagnostic, \ experimental, \ - notproduct, \ - range, \ - constraint, \ - writeable) \ + notproduct, \ + range, \ + constraint, \ + writeable) \ \ product(uintx, PowerArchitecturePPC64, 0, \ "CPU Version: x for PowerX. Currently recognizes Power5 to " \
--- a/src/hotspot/cpu/ppc/icache_ppc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/icache_ppc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 SAP SE. All rights reserved. + * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ */ #include "precompiled.hpp" -#include "assembler_ppc.inline.hpp" #include "runtime/icache.hpp" // Use inline assembler to implement icache flush. @@ -32,7 +31,7 @@ address end = start + (unsigned int)lines*ICache::line_size; 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) { __asm__ __volatile__( "dcbst 0, %0 \n" @@ -48,7 +47,7 @@ : : "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) { __asm__ __volatile__( "icbi 0, %0 \n" @@ -57,7 +56,7 @@ : "memory"); } - // discard fetched instructions + // Discard fetched instructions. __asm__ __volatile__( "isync \n" : @@ -71,6 +70,8 @@ *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); }
--- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 SAP SE. All rights reserved. + * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,10 @@ #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" +// Implementation of InterpreterMacroAssembler. + +// This file specializes the assembler with interpreter-specific macros. + #ifdef PRODUCT #define BLOCK_COMMENT(str) // nothing #else
--- a/src/hotspot/cpu/ppc/jniFastGetField_ppc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/jniFastGetField_ppc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 SAP SE. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ */ #include "precompiled.hpp" -#include "assembler_ppc.inline.hpp" +#include "asm/assembler.inline.hpp" #include "memory/resourceArea.hpp" #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp"
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1788,11 +1788,10 @@ RegisterOrConstant itable_index, Register method_result, Register scan_temp, - Register sethi_temp, - Label& L_no_such_interface) { + Register temp2, + Label& L_no_such_interface, + bool return_method) { assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); - assert(itable_index.is_constant() || itable_index.as_register() == method_result, - "caller must use same register for non-constant itable index as for method"); // Compute start of first itableOffsetEntry (which is at the end of the vtable). int vtable_base = in_bytes(Klass::vtable_start_offset()); @@ -1810,15 +1809,17 @@ add(scan_temp, recv_klass, scan_temp); // Adjust recv_klass by scaled itable_index, so we can free itable_index. - if (itable_index.is_register()) { - Register itable_offset = itable_index.as_register(); - sldi(itable_offset, itable_offset, logMEsize); - if (itentry_off) addi(itable_offset, itable_offset, itentry_off); - add(recv_klass, itable_offset, recv_klass); - } else { - long itable_offset = (long)itable_index.as_constant(); - load_const_optimized(sethi_temp, (itable_offset<<logMEsize)+itentry_off); // static address, no relocation - add(recv_klass, sethi_temp, recv_klass); + if (return_method) { + if (itable_index.is_register()) { + Register itable_offset = itable_index.as_register(); + sldi(method_result, itable_offset, logMEsize); + if (itentry_off) { addi(method_result, method_result, itentry_off); } + add(method_result, method_result, recv_klass); + } else { + long itable_offset = (long)itable_index.as_constant(); + // static address, no relocation + add_const_optimized(method_result, recv_klass, (itable_offset << logMEsize) + itentry_off, temp2); + } } // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { @@ -1831,12 +1832,12 @@ for (int peel = 1; peel >= 0; peel--) { // %%%% Could load both offset and interface in one ldx, if they were // in the opposite order. This would save a load. - ld(method_result, itableOffsetEntry::interface_offset_in_bytes(), scan_temp); + ld(temp2, itableOffsetEntry::interface_offset_in_bytes(), scan_temp); // Check that this entry is non-null. A null entry means that // the receiver class doesn't implement the interface, and wasn't the // same as when the caller was compiled. - cmpd(CCR0, method_result, intf_klass); + cmpd(CCR0, temp2, intf_klass); if (peel) { beq(CCR0, found_method); @@ -1849,7 +1850,7 @@ bind(search); - cmpdi(CCR0, method_result, 0); + cmpdi(CCR0, temp2, 0); beq(CCR0, L_no_such_interface); addi(scan_temp, scan_temp, scan_step); } @@ -1857,9 +1858,11 @@ bind(found_method); // Got a hit. - int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); - lwz(scan_temp, ito_offset, scan_temp); - ldx(method_result, scan_temp, recv_klass); + if (return_method) { + int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); + lwz(scan_temp, ito_offset, scan_temp); + ldx(method_result, scan_temp, method_result); + } } // virtual method calling @@ -2880,10 +2883,6 @@ //assert(ObjectMonitor::recursions_size_in_bytes() == 8, "unexpected size"); asm_assert_mem8_is_zero(ObjectMonitor::recursions_offset_in_bytes(), temp, "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 #if INCLUDE_RTM_OPT
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -519,7 +519,8 @@ RegisterOrConstant itable_index, Register method_result, Register temp_reg, Register temp2_reg, - Label& no_such_interface); + Label& no_such_interface, + bool return_method = true); // virtual method calling void lookup_virtual_method(Register recv_klass,
--- a/src/hotspot/cpu/ppc/nativeInst_ppc.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/nativeInst_ppc.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ #ifndef CPU_PPC_VM_NATIVEINST_PPC_HPP #define CPU_PPC_VM_NATIVEINST_PPC_HPP -#include "asm/assembler.hpp" #include "asm/macroAssembler.hpp" #include "memory/allocation.hpp" #include "runtime/icache.hpp"
--- a/src/hotspot/cpu/ppc/runtime_ppc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/runtime_ppc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ #include "precompiled.hpp" #ifdef COMPILER2 -#include "asm/assembler.inline.hpp" #include "asm/macroAssembler.inline.hpp" #include "classfile/systemDictionary.hpp" #include "code/vmreg.hpp"
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 SAP SE. All rights reserved. + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1188,7 +1188,7 @@ // Argument is valid and klass is as expected, continue. // Extract method from inline cache, verified entry point needs it. - __ ld(R19_method, CompiledICHolder::holder_method_offset(), ic); + __ ld(R19_method, CompiledICHolder::holder_metadata_offset(), ic); assert(R19_method == ic, "the inline cache register is dead here"); __ ld(code, method_(code)); @@ -1912,8 +1912,8 @@ // - *_slot_offset Indicates offset from SP in number of stack slots. // - *_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) - + SharedRuntime::out_preserve_stack_slots(); // See c_calling_convention. + 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. // Now the space for the inbound oop handle area. int total_save_slots = num_java_iarg_registers * VMRegImpl::slots_per_word; @@ -2044,7 +2044,8 @@ OopMap *oop_map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); 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.
--- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -40,6 +40,10 @@ #include "runtime/thread.inline.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-> #ifdef PRODUCT
--- a/src/hotspot/cpu/ppc/stubRoutines_ppc_64.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/stubRoutines_ppc_64.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -23,6 +23,7 @@ * */ +#include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "runtime/stubRoutines.hpp"
--- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -582,25 +582,6 @@ 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 entry = __ pc(); // Expression stack must be empty before entering the VM if an @@ -1896,7 +1877,6 @@ return NULL; } - /** * Method entry for static native methods: * int java.util.zip.CRC32.updateBytes( int crc, byte[] b, int off, int len)
--- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -3486,11 +3486,11 @@ void TemplateTable::invokeinterface_object_method(Register Rrecv_klass, Register Rret, Register Rflags, - Register Rindex, + Register Rmethod, Register Rtemp1, Register Rtemp2) { - assert_different_registers(Rindex, Rret, Rrecv_klass, Rflags, Rtemp1, Rtemp2); + assert_different_registers(Rmethod, Rret, Rrecv_klass, Rflags, Rtemp1, Rtemp2); Label LnotFinal; // Check for vfinal. @@ -3502,14 +3502,14 @@ // Final call case. __ profile_final_call(Rtemp1, Rscratch); // Argument and return type profiling. - __ profile_arguments_type(Rindex, Rscratch, Rrecv_klass /* scratch */, true); + __ profile_arguments_type(Rmethod, Rscratch, Rrecv_klass /* scratch */, true); // Do the final call - the index (f2) contains the method. - __ call_from_interpreter(Rindex, Rret, Rscratch, Rrecv_klass /* scratch */); + __ call_from_interpreter(Rmethod, Rret, Rscratch, Rrecv_klass /* scratch */); // Non-final callc case. __ bind(LnotFinal); __ profile_virtual_call(Rrecv_klass, Rtemp1, Rscratch, false); - generate_vtable_call(Rrecv_klass, Rindex, Rret, Rscratch); + generate_vtable_call(Rrecv_klass, Rmethod, Rret, Rscratch); } void TemplateTable::invokeinterface(int byte_no) { @@ -3518,58 +3518,61 @@ const Register Rscratch1 = R11_scratch1, Rscratch2 = R12_scratch2, - Rscratch3 = R9_ARG7, - Rscratch4 = R10_ARG8, - Rtable_addr = Rscratch2, + Rmethod = R6_ARG4, + Rmethod2 = R9_ARG7, Rinterface_klass = R5_ARG3, - Rret_type = R8_ARG6, - Rret_addr = Rret_type, - Rindex = R6_ARG4, - Rreceiver = R4_ARG2, - Rrecv_klass = Rreceiver, + Rret_addr = R8_ARG6, + Rindex = R10_ARG8, + Rreceiver = R3_ARG1, + Rrecv_klass = R4_ARG2, Rflags = R7_ARG5; - prepare_invoke(byte_no, Rinterface_klass, Rret_addr, Rindex, Rreceiver, Rflags, Rscratch1); + prepare_invoke(byte_no, Rinterface_klass, Rret_addr, Rmethod, Rreceiver, Rflags, Rscratch1); // Get receiver klass. - __ null_check_throw(Rreceiver, oopDesc::klass_offset_in_bytes(), Rscratch3); + __ null_check_throw(Rreceiver, oopDesc::klass_offset_in_bytes(), Rscratch2); __ load_klass(Rrecv_klass, Rreceiver); // Check corner case object method. - Label LobjectMethod; - + Label LobjectMethod, L_no_such_interface, Lthrow_ame; __ testbitdi(CCR0, R0, Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift); __ btrue(CCR0, LobjectMethod); - // Fallthrough: The normal invokeinterface case. + __ lookup_interface_method(Rrecv_klass, Rinterface_klass, noreg, noreg, Rscratch1, Rscratch2, + L_no_such_interface, /*return_method=*/false); + __ profile_virtual_call(Rrecv_klass, Rscratch1, Rscratch2, false); // Find entry point to call. - Label Lthrow_icc, Lthrow_ame; - // Result will be returned in Rindex. - __ mr(Rscratch4, Rrecv_klass); - __ mr(Rscratch3, Rindex); - __ lookup_interface_method(Rrecv_klass, Rinterface_klass, Rindex, Rindex, Rscratch1, Rscratch2, Lthrow_icc); - - __ cmpdi(CCR0, Rindex, 0); + + // Get declaring interface class from method + __ ld(Rinterface_klass, in_bytes(Method::const_offset()), Rmethod); + __ ld(Rinterface_klass, in_bytes(ConstMethod::constants_offset()), Rinterface_klass); + __ ld(Rinterface_klass, ConstantPool::pool_holder_offset_in_bytes(), Rinterface_klass); + + // Get itable index from method + __ lwa(Rindex, in_bytes(Method::itable_index_offset()), Rmethod); + __ subfic(Rindex, Rindex, Method::itable_index_max); + + __ lookup_interface_method(Rrecv_klass, Rinterface_klass, Rindex, Rmethod2, Rscratch1, Rscratch2, + L_no_such_interface); + + __ cmpdi(CCR0, Rmethod2, 0); __ beq(CCR0, Lthrow_ame); // Found entry. Jump off! // Argument and return type profiling. - __ profile_arguments_type(Rindex, Rscratch1, Rscratch2, true); - __ call_from_interpreter(Rindex, Rret_addr, Rscratch1, Rscratch2); + __ profile_arguments_type(Rmethod2, Rscratch1, Rscratch2, true); + //__ profile_called_method(Rindex, Rscratch1); + __ call_from_interpreter(Rmethod2, Rret_addr, Rscratch1, Rscratch2); // Vtable entry was NULL => Throw abstract method error. __ bind(Lthrow_ame); - __ mr(Rrecv_klass, Rscratch4); - __ mr(Rindex, Rscratch3); call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); // Interface was not found => Throw incompatible class change error. - __ bind(Lthrow_icc); - __ mr(Rrecv_klass, Rscratch4); + __ bind(L_no_such_interface); call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError)); - - __ should_not_reach_here(); + DEBUG_ONLY( __ should_not_reach_here(); ) // Special case of invokeinterface called for virtual method of // java.lang.Object. See ConstantPoolCacheEntry::set_method() for details: @@ -3577,7 +3580,7 @@ // to handle this corner case. This code isn't produced by javac, but could // be produced by another compliant java compiler. __ bind(LobjectMethod); - invokeinterface_object_method(Rrecv_klass, Rret_addr, Rflags, Rindex, Rscratch1, Rscratch2); + invokeinterface_object_method(Rrecv_klass, Rret_addr, Rflags, Rmethod, Rscratch1, Rscratch2); } void TemplateTable::invokedynamic(int byte_no) {
--- a/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/ppc/vtableStubs_ppc_64.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "code/vtableStubs.hpp" #include "interp_masm_ppc.hpp" #include "memory/resourceArea.hpp" +#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klassVtable.hpp" #include "runtime/sharedRuntime.hpp" @@ -55,17 +56,22 @@ // PPC port: use fixed size. const int code_length = VtableStub::pd_code_size_limit(true); VtableStub* s = new (code_length) VtableStub(true, vtable_index); + + // Can be NULL if there is no free space in the code cache. + if (s == NULL) { + return NULL; + } + ResourceMark rm; CodeBuffer cb(s->entry_point(), code_length); MacroAssembler* masm = new MacroAssembler(&cb); - address start_pc; #ifndef PRODUCT if (CountCompiledCalls) { - __ load_const(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr()); - __ lwz(R12_scratch2, 0, R11_scratch1); + int offs = __ load_const_optimized(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr(), R12_scratch2, true); + __ lwz(R12_scratch2, offs, R11_scratch1); __ addi(R12_scratch2, R12_scratch2, 1); - __ stw(R12_scratch2, 0, R11_scratch1); + __ stw(R12_scratch2, offs, R11_scratch1); } #endif @@ -116,6 +122,7 @@ __ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method); __ mtctr(R12_scratch2); __ bctr(); + masm->flush(); guarantee(__ pc() <= s->code_end(), "overflowed buffer"); @@ -125,10 +132,16 @@ return s; } -VtableStub* VtableStubs::create_itable_stub(int vtable_index) { +VtableStub* VtableStubs::create_itable_stub(int itable_index) { // PPC port: use fixed size. const int code_length = VtableStub::pd_code_size_limit(false); - VtableStub* s = new (code_length) VtableStub(false, vtable_index); + VtableStub* s = new (code_length) VtableStub(false, itable_index); + + // Can be NULL if there is no free space in the code cache. + if (s == NULL) { + return NULL; + } + ResourceMark rm; CodeBuffer cb(s->entry_point(), code_length); MacroAssembler* masm = new MacroAssembler(&cb); @@ -136,10 +149,10 @@ #ifndef PRODUCT if (CountCompiledCalls) { - __ load_const(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr()); - __ lwz(R12_scratch2, 0, R11_scratch1); + int offs = __ load_const_optimized(R11_scratch1, SharedRuntime::nof_megamorphic_calls_addr(), R12_scratch2, true); + __ lwz(R12_scratch2, offs, R11_scratch1); __ addi(R12_scratch2, R12_scratch2, 1); - __ stw(R12_scratch2, 0, R11_scratch1); + __ stw(R12_scratch2, offs, R11_scratch1); } #endif @@ -148,62 +161,28 @@ // Entry arguments: // R19_method: Interface // R3_ARG1: Receiver - // - const Register rcvr_klass = R11_scratch1; - const Register vtable_len = R12_scratch2; - const Register itable_entry_addr = R21_tmp1; - const Register itable_interface = R22_tmp2; + Label L_no_such_interface; + const Register rcvr_klass = R11_scratch1, + interface = R12_scratch2, + tmp1 = R21_tmp1, + tmp2 = R22_tmp2; - // Get receiver klass. - - // We might implicit NULL fault here. address npe_addr = __ pc(); // npe = null pointer exception __ null_check(R3_ARG1, oopDesc::klass_offset_in_bytes(), /*implicit only*/NULL); __ load_klass(rcvr_klass, R3_ARG1); - BLOCK_COMMENT("Load start of itable entries into itable_entry."); - __ lwz(vtable_len, in_bytes(Klass::vtable_length_offset()), rcvr_klass); - __ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes())); - __ add(itable_entry_addr, vtable_len, rcvr_klass); + // Receiver subtype check against REFC. + __ ld(interface, CompiledICHolder::holder_klass_offset(), R19_method); + __ lookup_interface_method(rcvr_klass, interface, noreg, + R0, tmp1, tmp2, + L_no_such_interface, /*return_method=*/ false); - // Loop over all itable entries until desired interfaceOop(Rinterface) found. - BLOCK_COMMENT("Increment itable_entry_addr in loop."); - const int vtable_base_offset = in_bytes(Klass::vtable_start_offset()); - __ addi(itable_entry_addr, itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes()); - - const int itable_offset_search_inc = itableOffsetEntry::size() * wordSize; - Label search; - __ bind(search); - __ ld(itable_interface, 0, itable_entry_addr); - - // Handle IncompatibleClassChangeError in itable stubs. - // If the entry is NULL then we've reached the end of the table - // without finding the expected interface, so throw an exception. - BLOCK_COMMENT("Handle IncompatibleClassChangeError in itable stubs."); - Label throw_icce; - __ cmpdi(CCR1, itable_interface, 0); - __ cmpd(CCR0, itable_interface, R19_method); - __ addi(itable_entry_addr, itable_entry_addr, itable_offset_search_inc); - __ beq(CCR1, throw_icce); - __ bne(CCR0, search); - - // Entry found and itable_entry_addr points to it, get offset of vtable for interface. - - const Register vtable_offset = R12_scratch2; - const Register itable_method = R11_scratch1; - - const int vtable_offset_offset = (itableOffsetEntry::offset_offset_in_bytes() - - itableOffsetEntry::interface_offset_in_bytes()) - - itable_offset_search_inc; - __ lwz(vtable_offset, vtable_offset_offset, itable_entry_addr); - - // Compute itableMethodEntry and get method and entry point for compiler. - const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + - itableMethodEntry::method_offset_in_bytes(); - - __ add(itable_method, rcvr_klass, vtable_offset); - __ ld(R19_method, method_offset, itable_method); + // Get Method* and entrypoint for compiler + __ ld(interface, CompiledICHolder::holder_metadata_offset(), R19_method); + __ lookup_interface_method(rcvr_klass, interface, itable_index, + R19_method, tmp1, tmp2, + L_no_such_interface, /*return_method=*/ true); #ifndef PRODUCT if (DebugVtables) { @@ -219,7 +198,7 @@ address ame_addr = __ pc(); // ame = abstract method error // Must do an explicit check if implicit checks are disabled. - __ null_check(R19_method, in_bytes(Method::from_compiled_offset()), &throw_icce); + __ null_check(R19_method, in_bytes(Method::from_compiled_offset()), &L_no_such_interface); __ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method); __ mtctr(R12_scratch2); __ bctr(); @@ -229,8 +208,8 @@ // We force resolving of the call site by jumping to the "handle // wrong method" stub, and so let the interpreter runtime do all the // dirty work. - __ bind(throw_icce); - __ load_const(R11_scratch1, SharedRuntime::get_handle_wrong_method_stub()); + __ bind(L_no_such_interface); + __ load_const_optimized(R11_scratch1, SharedRuntime::get_handle_wrong_method_stub(), R12_scratch2); __ mtctr(R11_scratch1); __ bctr(); @@ -245,14 +224,15 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) { if (DebugVtables || CountCompiledCalls || VerifyOops) { return 1000; - } else { - int decode_klass_size = MacroAssembler::instr_size_for_decode_klass_not_null(); - if (is_vtable_stub) { - return 20 + decode_klass_size + 8 + 8; // Plain + cOops + Traps + safety - } else { - return 96 + decode_klass_size + 12 + 8; // Plain + cOops + Traps + safety - } } + int size = is_vtable_stub ? 20 + 8 : 164 + 20; // Plain + safety + if (UseCompressedClassPointers) { + size += MacroAssembler::instr_size_for_decode_klass_not_null(); + } + if (!ImplicitNullChecks || !os::zero_page_read_protected()) { + size += is_vtable_stub ? 8 : 12; + } + return size; } int VtableStub::pd_code_alignment() {
--- a/src/hotspot/cpu/s390/bytes_s390.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/s390/bytes_s390.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,11 +42,6 @@ // // 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 u4 get_native_u4(address p) { return *(u4*)p; } static inline u8 get_native_u8(address p) { return *(u8*)p; } @@ -55,7 +50,8 @@ 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; } -#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) static inline u2 get_Java_u2(address p) { return get_native_u2(p); }
--- a/src/hotspot/cpu/s390/c1_globals_s390.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/s390/c1_globals_s390.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,7 @@ define_pd_global(bool, ProfileInterpreter, false); define_pd_global(intx, FreqInlineSize, 325); 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, ProfiledCodeHeapSize, 14*M); define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M);
--- a/src/hotspot/cpu/s390/c2_globals_s390.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/s390/c2_globals_s390.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ define_pd_global(intx, LoopPercentProfileLimit, 10); 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. define_pd_global(bool, OptoPeephole, false); define_pd_global(bool, UseCISCSpill, true);
--- a/src/hotspot/cpu/s390/globals_s390.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/s390/globals_s390.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* * 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. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,14 @@ 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 */ \ /* indirect call by a direct call. */ \
--- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -2806,8 +2806,8 @@ RegisterOrConstant itable_index, Register method_result, Register temp1_reg, - Register temp2_reg, - Label& no_such_interface) { + Label& no_such_interface, + bool return_method) { const Register vtable_len = temp1_reg; // Used to compute itable_entry_addr. const Register itable_entry_addr = Z_R1_scratch; @@ -2842,38 +2842,36 @@ z_brne(search); // Entry found and itable_entry_addr points to it, get offset of vtable for interface. - - const int vtable_offset_offset = (itableOffsetEntry::offset_offset_in_bytes() - - itableOffsetEntry::interface_offset_in_bytes()) - - itable_offset_search_inc; - - // Compute itableMethodEntry and get method and entry point - // we use addressing with index and displacement, since the formula - // for computing the entry's offset has a fixed and a dynamic part, - // the latter depending on the matched interface entry and on the case, - // that the itable index has been passed as a register, not a constant value. - int method_offset = itableMethodEntry::method_offset_in_bytes(); - // Fixed part (displacement), common operand. - Register itable_offset; // Dynamic part (index register). - - if (itable_index.is_register()) { - // Compute the method's offset in that register, for the formula, see the - // else-clause below. - itable_offset = itable_index.as_register(); - - z_sllg(itable_offset, itable_offset, exact_log2(itableMethodEntry::size() * wordSize)); - z_agf(itable_offset, vtable_offset_offset, itable_entry_addr); - } else { - itable_offset = Z_R1_scratch; - // Displacement increases. - method_offset += itableMethodEntry::size() * wordSize * itable_index.as_constant(); - - // Load index from itable. - z_llgf(itable_offset, vtable_offset_offset, itable_entry_addr); - } - - // Finally load the method's oop. - z_lg(method_result, method_offset, itable_offset, recv_klass); + if (return_method) { + const int vtable_offset_offset = (itableOffsetEntry::offset_offset_in_bytes() - + itableOffsetEntry::interface_offset_in_bytes()) - + itable_offset_search_inc; + + // Compute itableMethodEntry and get method and entry point + // we use addressing with index and displacement, since the formula + // for computing the entry's offset has a fixed and a dynamic part, + // the latter depending on the matched interface entry and on the case, + // that the itable index has been passed as a register, not a constant value. + int method_offset = itableMethodEntry::method_offset_in_bytes(); + // Fixed part (displacement), common operand. + Register itable_offset = method_result; // Dynamic part (index register). + + if (itable_index.is_register()) { + // Compute the method's offset in that register, for the formula, see the + // else-clause below. + z_sllg(itable_offset, itable_index.as_register(), exact_log2(itableMethodEntry::size() * wordSize)); + z_agf(itable_offset, vtable_offset_offset, itable_entry_addr); + } else { + // Displacement increases. + method_offset += itableMethodEntry::size() * wordSize * itable_index.as_constant(); + + // 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"); }
--- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -671,8 +671,8 @@ RegisterOrConstant itable_index, Register method_result, Register temp1_reg, - Register temp2_reg, - Label& no_such_interface); + Label& no_such_interface, + bool return_method = true); // virtual method calling void lookup_virtual_method(Register recv_klass,
--- a/src/hotspot/cpu/s390/methodHandles_s390.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/s390/methodHandles_s390.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -498,7 +498,7 @@ Label L_no_such_interface; __ lookup_interface_method(temp1_recv_klass, temp3_intf, // Note: next two args must be the same: - Z_index, Z_method, temp2, noreg, + Z_index, Z_method, temp2, L_no_such_interface); jump_from_method_handle(_masm, Z_method, temp2, Z_R0, for_compiler_entry);
--- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -2660,9 +2660,9 @@ Label skip_fixup; { Label ic_miss; - const int klass_offset = oopDesc::klass_offset_in_bytes(); - const int holder_klass_offset = CompiledICHolder::holder_klass_offset(); - const int holder_method_offset = CompiledICHolder::holder_method_offset(); + const int klass_offset = oopDesc::klass_offset_in_bytes(); + const int holder_klass_offset = CompiledICHolder::holder_klass_offset(); + const int holder_metadata_offset = CompiledICHolder::holder_metadata_offset(); // Out-of-line call to ic_miss handler. __ call_ic_miss_handler(ic_miss, 0x11, 0, Z_R1_scratch); @@ -2691,7 +2691,7 @@ // This def MUST MATCH code in gen_c2i_adapter! const Register code = Z_R11; - __ z_lg(Z_method, holder_method_offset, Z_method); + __ z_lg(Z_method, holder_metadata_offset, Z_method); __ load_and_test_long(Z_R0, method_(code)); __ z_brne(ic_miss); // Cache miss: call runtime to handle this.
--- a/src/hotspot/cpu/s390/templateTable_s390.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/s390/templateTable_s390.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -3557,66 +3557,67 @@ transition(vtos, vtos); assert(byte_no == f1_byte, "use this argument"); - Register interface = Z_tos; - Register index = Z_ARG3; - Register receiver = Z_tmp_1; - Register flags = Z_ARG5; + Register klass = Z_ARG2, + method = Z_ARG3, + interface = Z_ARG4, + flags = Z_ARG5, + receiver = Z_tmp_1; BLOCK_COMMENT("invokeinterface {"); - // Destroys Z_ARG1 and Z_ARG2, thus use Z_ARG4 and copy afterwards. - prepare_invoke(byte_no, Z_ARG4, index, // Get f1 klassOop, f2 itable index. + prepare_invoke(byte_no, interface, method, // Get f1 klassOop, f2 itable index. receiver, flags); // Z_R14 (== Z_bytecode) : return entry - __ z_lgr(interface, Z_ARG4); - // Special case of invokeinterface called for virtual method of // java.lang.Object. See cpCacheOop.cpp for details. // This code isn't produced by javac, but could be produced by // another compliant java compiler. - Label notMethod; + NearLabel notMethod, no_such_interface, no_such_method; __ testbit(flags, ConstantPoolCacheEntry::is_forced_virtual_shift); __ z_brz(notMethod); - invokevirtual_helper(index, receiver, flags); + invokevirtual_helper(method, receiver, flags); __ bind(notMethod); // Get receiver klass into klass - also a null check. - Register klass = flags; - __ restore_locals(); __ load_klass(klass, receiver); + __ lookup_interface_method(klass, interface, noreg, noreg, /*temp*/Z_ARG1, + no_such_interface, /*return_method=*/false); + // Profile this call. - __ profile_virtual_call(klass, Z_ARG2/*mdp*/, Z_ARG4/*scratch*/); - - NearLabel no_such_interface, no_such_method; - Register method = Z_tmp_2; - - // TK 2010-08-24: save the index to Z_ARG4. needed in case of an error - // in throw_AbstractMethodErrorByTemplateTable - __ z_lgr(Z_ARG4, index); - // TK 2011-03-24: copy also klass because it could be changed in - // lookup_interface_method - __ z_lgr(Z_ARG2, klass); - __ lookup_interface_method(// inputs: rec. class, interface, itable index - klass, interface, index, - // outputs: method, scan temp. reg - method, Z_tmp_2, Z_R1_scratch, - no_such_interface); + __ profile_virtual_call(klass, Z_ARG1/*mdp*/, flags/*scratch*/); + + // Find entry point to call. + + // Get declaring interface class from method + __ z_lg(interface, Address(method, Method::const_offset())); + __ z_lg(interface, Address(interface, ConstMethod::constants_offset())); + __ z_lg(interface, Address(interface, ConstantPool::pool_holder_offset_in_bytes())); + + // Get itable index from method + Register index = receiver, + method2 = flags; + __ z_lgf(index, Address(method, Method::itable_index_offset())); + __ z_aghi(index, -Method::itable_index_max); + __ z_lcgr(index, index); + + __ lookup_interface_method(klass, interface, index, method2, Z_tmp_2, + no_such_interface); // Check for abstract method error. // Note: This should be done more efficiently via a throw_abstract_method_error // interpreter entry point and a conditional jump to it in case of a null // method. - __ compareU64_and_branch(method, (intptr_t) 0, + __ compareU64_and_branch(method2, (intptr_t) 0, Assembler::bcondZero, no_such_method); - __ profile_arguments_type(Z_ARG3, method, Z_ARG5, true); + __ profile_arguments_type(Z_tmp_1, method2, Z_tmp_2, true); // Do the call. - __ jump_from_interpreted(method, Z_ARG5); + __ jump_from_interpreted(method2, Z_tmp_2); __ should_not_reach_here(); // exception handling code follows... @@ -3628,12 +3629,8 @@ // Throw exception. __ restore_bcp(); // Bcp must be correct for exception handler (was destroyed). __ restore_locals(); // Make sure locals pointer is correct as well (was destroyed). - // TK 2010-08-24: Call throw_AbstractMethodErrorByTemplateTable now with the - // relevant information for generating a better error message __ call_VM(noreg, - CAST_FROM_FN_PTR(address, - InterpreterRuntime::throw_AbstractMethodError), - Z_ARG2, interface, Z_ARG4); + CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); // The call_VM checks for exception, so we should never return here. __ should_not_reach_here(); @@ -3642,12 +3639,8 @@ // Throw exception. __ restore_bcp(); // Bcp must be correct for exception handler (was destroyed). __ restore_locals(); // Make sure locals pointer is correct as well (was destroyed). - // TK 2010-08-24: Call throw_IncompatibleClassChangeErrorByTemplateTable now with the - // relevant information for generating a better error message __ call_VM(noreg, - CAST_FROM_FN_PTR(address, - InterpreterRuntime::throw_IncompatibleClassChangeError), - Z_ARG2, interface); + CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError)); // The call_VM checks for exception, so we should never return here. __ should_not_reach_here();
--- a/src/hotspot/cpu/s390/vtableStubs_s390.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/s390/vtableStubs_s390.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "code/vtableStubs.hpp" #include "interp_masm_s390.hpp" #include "memory/resourceArea.hpp" +#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klassVtable.hpp" #include "runtime/sharedRuntime.hpp" @@ -57,7 +58,6 @@ ResourceMark rm; CodeBuffer cb(s->entry_point(), code_length); MacroAssembler *masm = new MacroAssembler(&cb); - address start_pc; int padding_bytes = 0; #if (!defined(PRODUCT) && defined(COMPILER2)) @@ -144,9 +144,9 @@ return s; } -VtableStub* VtableStubs::create_itable_stub(int vtable_index) { +VtableStub* VtableStubs::create_itable_stub(int itable_index) { const int code_length = VtableStub::pd_code_size_limit(false); - VtableStub *s = new(code_length) VtableStub(false, vtable_index); + VtableStub *s = new(code_length) VtableStub(false, itable_index); if (s == NULL) { // Indicates OOM in the code cache. return NULL; } @@ -154,7 +154,6 @@ ResourceMark rm; CodeBuffer cb(s->entry_point(), code_length); MacroAssembler *masm = new MacroAssembler(&cb); - address start_pc; int padding_bytes = 0; #if (!defined(PRODUCT) && defined(COMPILER2)) @@ -174,11 +173,9 @@ // Entry arguments: // Z_method: Interface // Z_ARG1: Receiver - const Register rcvr_klass = Z_tmp_1; // Used to compute itable_entry_addr. - // Use extra reg to avoid re-load. - const Register vtable_len = Z_tmp_2; // Used to compute itable_entry_addr. - const Register itable_entry_addr = Z_R1_scratch; - const Register itable_interface = Z_R0_scratch; + NearLabel no_such_interface; + const Register rcvr_klass = Z_tmp_1, + interface = Z_tmp_2; // Get receiver klass. // Must do an explicit check if implicit checks are disabled. @@ -186,50 +183,15 @@ __ null_check(Z_ARG1, Z_R1_scratch, oopDesc::klass_offset_in_bytes()); __ load_klass(rcvr_klass, Z_ARG1); - // Load start of itable entries into itable_entry. - __ z_llgf(vtable_len, Address(rcvr_klass, Klass::vtable_length_offset())); - __ z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes())); + // Receiver subtype check against REFC. + __ z_lg(interface, Address(Z_method, CompiledICHolder::holder_klass_offset())); + __ lookup_interface_method(rcvr_klass, interface, noreg, + noreg, Z_R1, no_such_interface, /*return_method=*/ false); - // Loop over all itable entries until desired interfaceOop(Rinterface) found. - const int vtable_base_offset = in_bytes(Klass::vtable_start_offset()); - // Count unused bytes. - start_pc = __ pc(); - __ add2reg_with_index(itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(), rcvr_klass, vtable_len); - padding_bytes += 20 - (__ pc() - start_pc); - - const int itable_offset_search_inc = itableOffsetEntry::size() * wordSize; - Label search; - __ bind(search); - - // Handle IncompatibleClassChangeError in itable stubs. - // If the entry is NULL then we've reached the end of the table - // without finding the expected interface, so throw an exception. - NearLabel throw_icce; - __ load_and_test_long(itable_interface, Address(itable_entry_addr)); - __ z_bre(throw_icce); // Throw the exception out-of-line. - // Count unused bytes. - start_pc = __ pc(); - __ add2reg(itable_entry_addr, itable_offset_search_inc); - padding_bytes += 20 - (__ pc() - start_pc); - __ z_cgr(itable_interface, Z_method); - __ z_brne(search); - - // Entry found. Itable_entry_addr points to the subsequent entry (itable_offset_search_inc too far). - // Get offset of vtable for interface. - - const Register vtable_offset = Z_R1_scratch; - const Register itable_method = rcvr_klass; // Calculated before. - - const int vtable_offset_offset = (itableOffsetEntry::offset_offset_in_bytes() - - itableOffsetEntry::interface_offset_in_bytes()) - - itable_offset_search_inc; - __ z_llgf(vtable_offset, vtable_offset_offset, itable_entry_addr); - - // Compute itableMethodEntry and get method and entry point for compiler. - const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + - itableMethodEntry::method_offset_in_bytes(); - - __ z_lg(Z_method, method_offset, vtable_offset, itable_method); + // Get Method* and entrypoint for compiler + __ z_lg(interface, Address(Z_method, CompiledICHolder::holder_metadata_offset())); + __ lookup_interface_method(rcvr_klass, interface, itable_index, + Z_method, Z_R1, no_such_interface, /*return_method=*/ true); #ifndef PRODUCT if (DebugVtables) { @@ -244,13 +206,13 @@ address ame_addr = __ pc(); // Must do an explicit check if implicit checks are disabled. if (!ImplicitNullChecks) { - __ compare64_and_branch(Z_method, (intptr_t) 0, Assembler::bcondEqual, throw_icce); + __ compare64_and_branch(Z_method, (intptr_t) 0, Assembler::bcondEqual, no_such_interface); } __ z_lg(Z_R1_scratch, in_bytes(Method::from_compiled_offset()), Z_method); __ z_br(Z_R1_scratch); // Handle IncompatibleClassChangeError in itable stubs. - __ bind(throw_icce); + __ bind(no_such_interface); // Count unused bytes // worst case actual size // We force resolving of the call site by jumping to @@ -273,13 +235,12 @@ if (CountCompiledCalls) { size += 6 * 4; } - if (is_vtable_stub) { - size += 52; - } else { - size += 104; + size += is_vtable_stub ? 36 : 140; + if (UseCompressedClassPointers) { + size += MacroAssembler::instr_size_for_decode_klass_not_null(); } - if (Universe::narrow_klass_base() != NULL) { - size += 16; // A guess. + if (!ImplicitNullChecks) { + size += 36; } return size; }
--- a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -2058,9 +2058,10 @@ Register method_result, Register scan_temp, Register sethi_temp, - Label& L_no_such_interface) { + Label& L_no_such_interface, + bool return_method) { assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); - assert(itable_index.is_constant() || itable_index.as_register() == method_result, + assert(!return_method || itable_index.is_constant() || itable_index.as_register() == method_result, "caller must use same register for non-constant itable index as for method"); Label L_no_such_interface_restore; @@ -2092,11 +2093,13 @@ add(scan_temp, itb_offset, scan_temp); add(recv_klass, scan_temp, scan_temp); - // Adjust recv_klass by scaled itable_index, so we can free itable_index. - RegisterOrConstant itable_offset = itable_index; - itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset); - itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset); - add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass); + if (return_method) { + // Adjust recv_klass by scaled itable_index, so we can free itable_index. + RegisterOrConstant itable_offset = itable_index; + itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset); + itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset); + add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass); + } // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { // if (scan->interface() == intf) { @@ -2131,12 +2134,14 @@ bind(L_found_method); - // Got a hit. - int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); - // scan_temp[-scan_step] points to the vtable offset we need - ito_offset -= scan_step; - lduw(scan_temp, ito_offset, scan_temp); - ld_ptr(recv_klass, scan_temp, method_result); + if (return_method) { + // Got a hit. + int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); + // scan_temp[-scan_step] points to the vtable offset we need + ito_offset -= scan_step; + lduw(scan_temp, ito_offset, scan_temp); + ld_ptr(recv_klass, scan_temp, method_result); + } if (did_save) { Label L_done;
--- a/src/hotspot/cpu/sparc/macroAssembler_sparc.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1277,7 +1277,8 @@ RegisterOrConstant itable_index, Register method_result, Register temp_reg, Register temp2_reg, - Label& no_such_interface); + Label& no_such_interface, + bool return_method = true); // virtual method calling void lookup_virtual_method(Register recv_klass,
--- a/src/hotspot/cpu/sparc/sharedRuntime_sparc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/sparc/sharedRuntime_sparc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -904,7 +904,7 @@ Label ok, ok2; __ brx(Assembler::equal, false, Assembler::pt, ok); - __ delayed()->ld_ptr(G5_method, CompiledICHolder::holder_method_offset(), G5_method); + __ delayed()->ld_ptr(G5_method, CompiledICHolder::holder_metadata_offset(), G5_method); __ jump_to(ic_miss, G3_scratch); __ delayed()->nop();
--- a/src/hotspot/cpu/sparc/templateTable_sparc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/sparc/templateTable_sparc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -3081,15 +3081,15 @@ assert(byte_no == f1_byte, "use this argument"); const Register Rinterface = G1_scratch; + const Register Rmethod = Lscratch; const Register Rret = G3_scratch; - const Register Rindex = Lscratch; const Register O0_recv = O0; const Register O1_flags = O1; const Register O2_Klass = O2; const Register Rscratch = G4_scratch; assert_different_registers(Rscratch, G5_method); - prepare_invoke(byte_no, Rinterface, Rret, Rindex, O0_recv, O1_flags); + prepare_invoke(byte_no, Rinterface, Rret, Rmethod, O0_recv, O1_flags); // get receiver klass __ null_check(O0_recv, oopDesc::klass_offset_in_bytes()); @@ -3109,55 +3109,40 @@ __ bind(notMethod); + Register Rtemp = O1_flags; + + Label L_no_such_interface; + + // Receiver subtype check against REFC. + __ lookup_interface_method(// inputs: rec. class, interface, itable index + O2_Klass, Rinterface, noreg, + // outputs: temp reg1, temp reg2, temp reg3 + G5_method, Rscratch, Rtemp, + L_no_such_interface, + /*return_method=*/false); + __ profile_virtual_call(O2_Klass, O4); // // find entry point to call // - // compute start of first itableOffsetEntry (which is at end of vtable) - const int base = in_bytes(Klass::vtable_start_offset()); - Label search; - Register Rtemp = O1_flags; - - __ ld(O2_Klass, in_bytes(Klass::vtable_length_offset()), Rtemp); - __ sll(Rtemp, LogBytesPerWord, Rtemp); // Rscratch *= 4; - if (Assembler::is_simm13(base)) { - __ add(Rtemp, base, Rtemp); - } else { - __ set(base, Rscratch); - __ add(Rscratch, Rtemp, Rtemp); - } - __ add(O2_Klass, Rtemp, Rscratch); - - __ bind(search); - - __ ld_ptr(Rscratch, itableOffsetEntry::interface_offset_in_bytes(), Rtemp); - { - Label ok; - - // Check that entry is non-null. Null entries are probably a bytecode - // problem. If the interface isn't implemented by the receiver class, - // the VM should throw IncompatibleClassChangeError. linkResolver checks - // this too but that's only if the entry isn't already resolved, so we - // need to check again. - __ br_notnull_short( Rtemp, Assembler::pt, ok); - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError)); - __ should_not_reach_here(); - __ bind(ok); - } - - __ cmp(Rinterface, Rtemp); - __ brx(Assembler::notEqual, true, Assembler::pn, search); - __ delayed()->add(Rscratch, itableOffsetEntry::size() * wordSize, Rscratch); - - // entry found and Rscratch points to it - __ ld(Rscratch, itableOffsetEntry::offset_offset_in_bytes(), Rscratch); - - assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust instruction below"); - __ sll(Rindex, exact_log2(itableMethodEntry::size() * wordSize), Rindex); // Rindex *= 8; - __ add(Rscratch, Rindex, Rscratch); - __ ld_ptr(O2_Klass, Rscratch, G5_method); + // Get declaring interface class from method + __ ld_ptr(Rmethod, Method::const_offset(), Rinterface); + __ ld_ptr(Rinterface, ConstMethod::constants_offset(), Rinterface); + __ ld_ptr(Rinterface, ConstantPool::pool_holder_offset_in_bytes(), Rinterface); + + // Get itable index from method + const Register Rindex = G5_method; + __ ld(Rmethod, Method::itable_index_offset(), Rindex); + __ sub(Rindex, Method::itable_index_max, Rindex); + __ neg(Rindex); + + __ lookup_interface_method(// inputs: rec. class, interface, itable index + O2_Klass, Rinterface, Rindex, + // outputs: method, scan temp reg, temp reg + G5_method, Rscratch, Rtemp, + L_no_such_interface); // Check for abstract method error. { @@ -3174,6 +3159,10 @@ __ profile_arguments_type(G5_method, Rcall, Gargs, true); __ profile_called_method(G5_method, Rscratch); __ call_from_interpreter(Rcall, Gargs, Rret); + + __ bind(L_no_such_interface); + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError)); + __ should_not_reach_here(); } void TemplateTable::invokehandle(int byte_no) {
--- a/src/hotspot/cpu/sparc/vtableStubs_sparc.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/sparc/vtableStubs_sparc.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -27,6 +27,7 @@ #include "code/vtableStubs.hpp" #include "interp_masm_sparc.hpp" #include "memory/resourceArea.hpp" +#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klassVtable.hpp" #include "runtime/sharedRuntime.hpp" @@ -140,7 +141,8 @@ MacroAssembler* masm = new MacroAssembler(&cb); Register G3_Klass = G3_scratch; - Register G5_interface = G5; // Passed in as an argument + Register G5_icholder = G5; // Passed in as an argument + Register G4_interface = G4_scratch; Label search; // Entry arguments: @@ -164,14 +166,26 @@ } #endif /* PRODUCT */ - Label throw_icce; + Label L_no_such_interface; Register L5_method = L5; + + // Receiver subtype check against REFC. + __ ld_ptr(G5_icholder, CompiledICHolder::holder_klass_offset(), G4_interface); __ lookup_interface_method(// inputs: rec. class, interface, itable index - G3_Klass, G5_interface, itable_index, + G3_Klass, G4_interface, itable_index, + // outputs: scan temp. reg1, scan temp. reg2 + L5_method, L2, L3, + L_no_such_interface, + /*return_method=*/ false); + + // Get Method* and entrypoint for compiler + __ ld_ptr(G5_icholder, CompiledICHolder::holder_metadata_offset(), G4_interface); + __ lookup_interface_method(// inputs: rec. class, interface, itable index + G3_Klass, G4_interface, itable_index, // outputs: method, scan temp. reg L5_method, L2, L3, - throw_icce); + L_no_such_interface); #ifndef PRODUCT if (DebugVtables) { @@ -197,7 +211,7 @@ __ JMP(G3_scratch, 0); __ delayed()->nop(); - __ bind(throw_icce); + __ bind(L_no_such_interface); AddressLiteral icce(StubRoutines::throw_IncompatibleClassChangeError_entry()); __ jump_to(icce, G3_scratch); __ delayed()->restore(); @@ -232,7 +246,7 @@ MacroAssembler::instr_size_for_decode_klass_not_null() : 0); return basic + slop; } else { - const int basic = 34 * BytesPerInstWord + + const int basic = 54 * BytesPerInstWord + // shift;add for load_klass (only shift with zero heap based) (UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -5809,8 +5809,13 @@ RegisterOrConstant itable_index, Register method_result, Register scan_temp, - Label& L_no_such_interface) { - assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); + Label& L_no_such_interface, + bool return_method) { + assert_different_registers(recv_klass, intf_klass, scan_temp); + assert_different_registers(method_result, intf_klass, scan_temp); + assert(recv_klass != method_result || !return_method, + "recv_klass can be destroyed when method isn't needed"); + assert(itable_index.is_constant() || itable_index.as_register() == method_result, "caller must use same register for non-constant itable index as for method"); @@ -5827,9 +5832,11 @@ // %%% Could store the aligned, prescaled offset in the klassoop. lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base)); - // Adjust recv_klass by scaled itable_index, so we can free itable_index. - assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); - lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off)); + if (return_method) { + // Adjust recv_klass by scaled itable_index, so we can free itable_index. + assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); + lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off)); + } // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { // if (scan->interface() == intf) { @@ -5863,9 +5870,11 @@ bind(found_method); - // Got a hit. - movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); - movptr(method_result, Address(recv_klass, scan_temp, Address::times_1)); + if (return_method) { + // Got a hit. + movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes())); + movptr(method_result, Address(recv_klass, scan_temp, Address::times_1)); + } }
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -544,7 +544,8 @@ RegisterOrConstant itable_index, Register method_result, Register scan_temp, - Label& no_such_interface); + Label& no_such_interface, + bool return_method = true); // virtual method calling void lookup_virtual_method(Register recv_klass,
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -957,7 +957,7 @@ Label missed; __ movptr(temp, Address(receiver, oopDesc::klass_offset_in_bytes())); __ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset())); - __ movptr(rbx, Address(holder, CompiledICHolder::holder_method_offset())); + __ movptr(rbx, Address(holder, CompiledICHolder::holder_metadata_offset())); __ jcc(Assembler::notEqual, missed); // Method might have been compiled since the call site was patched to // interpreted if that is the case treat it as a miss so we can get
--- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -949,7 +949,7 @@ { __ load_klass(temp, receiver); __ cmpptr(temp, Address(holder, CompiledICHolder::holder_klass_offset())); - __ movptr(rbx, Address(holder, CompiledICHolder::holder_method_offset())); + __ movptr(rbx, Address(holder, CompiledICHolder::holder_metadata_offset())); __ jcc(Assembler::equal, ok); __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
--- a/src/hotspot/cpu/x86/templateTable_x86.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/x86/templateTable_x86.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -3712,11 +3712,11 @@ void TemplateTable::invokeinterface(int byte_no) { transition(vtos, vtos); assert(byte_no == f1_byte, "use this argument"); - prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 itable index + prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 Method* rcx, rdx); // recv, flags - // rax: interface klass (from f1) - // rbx: itable index (from f2) + // rax: reference klass (from f1) + // rbx: method (from f2) // rcx: receiver // rdx: flags @@ -3738,10 +3738,28 @@ __ null_check(rcx, oopDesc::klass_offset_in_bytes()); __ load_klass(rdx, rcx); + Label no_such_interface, no_such_method; + + // Receiver subtype check against REFC. + // Superklass in rax. Subklass in rdx. Blows rcx, rdi. + __ lookup_interface_method(// inputs: rec. class, interface, itable index + rdx, rax, noreg, + // outputs: scan temp. reg, scan temp. reg + rbcp, rlocals, + no_such_interface, + /*return_method=*/false); + // profile this call + __ restore_bcp(); // rbcp was destroyed by receiver type check __ profile_virtual_call(rdx, rbcp, rlocals); - Label no_such_interface, no_such_method; + // Get declaring interface class from method, and itable index + __ movptr(rax, Address(rbx, Method::const_offset())); + __ movptr(rax, Address(rax, ConstMethod::constants_offset())); + __ movptr(rax, Address(rax, ConstantPool::pool_holder_offset_in_bytes())); + __ movl(rbx, Address(rbx, Method::itable_index_offset())); + __ subl(rbx, Method::itable_index_max); + __ negl(rbx); __ lookup_interface_method(// inputs: rec. class, interface, itable index rdx, rax, rbx,
--- a/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/x86/vtableStubs_x86_32.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -27,6 +27,7 @@ #include "code/vtableStubs.hpp" #include "interp_masm_x86.hpp" #include "memory/resourceArea.hpp" +#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klassVtable.hpp" #include "runtime/sharedRuntime.hpp" @@ -147,7 +148,7 @@ MacroAssembler* masm = new MacroAssembler(&cb); // Entry arguments: - // rax,: Interface + // rax: CompiledICHolder // rcx: Receiver #ifndef PRODUCT @@ -155,25 +156,42 @@ __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); } #endif /* PRODUCT */ - // get receiver (need to skip return address on top of stack) - assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx"); + // Most registers are in use; we'll use rax, rbx, rsi, rdi + // (If we need to make rsi, rdi callee-save, do a push/pop here.) + const Register recv_klass_reg = rsi; + const Register holder_klass_reg = rax; // declaring interface klass (DECC) + const Register resolved_klass_reg = rbx; // resolved interface klass (REFC) + const Register temp_reg = rdi; + + 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(); - __ movptr(rsi, Address(rcx, oopDesc::klass_offset_in_bytes())); + assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx"); + __ load_klass(recv_klass_reg, rcx); - // 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.) + // 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; - Label throw_icce; - - // Get Method* and entrypoint for compiler + __ load_klass(recv_klass_reg, rcx); // restore recv_klass_reg __ lookup_interface_method(// inputs: rec. class, interface, itable index - rsi, rax, itable_index, + recv_klass_reg, holder_klass_reg, itable_index, // outputs: method, scan temp. reg - method, rdi, - throw_icce); + method, temp_reg, + L_no_such_interface); // method (rbx): Method* // rcx: receiver @@ -193,9 +211,10 @@ address ame_addr = __ pc(); __ jmp(Address(method, Method::from_compiled_offset())); - __ bind(throw_icce); + __ bind(L_no_such_interface); __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); - masm->flush(); + + __ flush(); if (PrintMiscellaneous && (WizardMode || Verbose)) { tty->print_cr("itable #%d at " PTR_FORMAT "[%d] left over: %d", @@ -220,7 +239,7 @@ return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0); } else { // Itable stub size - return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0); + return (DebugVtables ? 256 : 110) + (CountCompiledCalls ? 6 : 0); } // In order to tune these parameters, run the JVM with VM options // +PrintMiscellaneous and +WizardMode to see information about
--- a/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/cpu/x86/vtableStubs_x86_64.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -27,6 +27,7 @@ #include "code/vtableStubs.hpp" #include "interp_masm_x86.hpp" #include "memory/resourceArea.hpp" +#include "oops/compiledICHolder.hpp" #include "oops/instanceKlass.hpp" #include "oops/klassVtable.hpp" #include "runtime/sharedRuntime.hpp" @@ -147,36 +148,50 @@ #endif // Entry arguments: - // rax: Interface + // rax: CompiledICHolder // j_rarg0: Receiver - // Free registers (non-args) are rax (interface), rbx - - // get receiver (need to skip return address on top of stack) - - assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); - // get receiver klass (also an implicit null-check) - address npe_addr = __ pc(); - // Most registers are in use; we'll use rax, rbx, r10, r11 // (various calling sequences use r[cd]x, r[sd]i, r[89]; stay away from them) - __ load_klass(r10, j_rarg0); + const Register recv_klass_reg = r10; + const Register holder_klass_reg = rax; // declaring interface klass (DECC) + const Register resolved_klass_reg = rbx; // resolved interface klass (REFC) + const Register temp_reg = r11; + + Label L_no_such_interface; + + const Register icholder_reg = rax; + __ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); + __ movptr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); + + // get receiver klass (also an implicit null-check) + assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); + address npe_addr = __ pc(); + __ load_klass(recv_klass_reg, j_rarg0); + + // Receiver subtype check against REFC. + // Destroys recv_klass_reg value. + __ lookup_interface_method(// inputs: rec. class, interface + recv_klass_reg, resolved_klass_reg, noreg, + // outputs: scan temp. reg1, scan temp. reg2 + recv_klass_reg, temp_reg, + L_no_such_interface, + /*return_method=*/false); + + // Get selected method from declaring class and itable index + const Register method = rbx; + __ load_klass(recv_klass_reg, j_rarg0); // restore recv_klass_reg + __ lookup_interface_method(// inputs: rec. class, interface, itable index + recv_klass_reg, holder_klass_reg, itable_index, + // outputs: method, scan temp. reg + method, temp_reg, + L_no_such_interface); // If we take a trap while this arg is on the stack we will not // be able to walk the stack properly. This is not an issue except // when there are mistakes in this assembly code that could generate // a spurious fault. Ask me how I know... - const Register method = rbx; - Label throw_icce; - - // Get Method* and entrypoint for compiler - __ lookup_interface_method(// inputs: rec. class, interface, itable index - r10, rax, itable_index, - // outputs: method, scan temp. reg - method, r11, - throw_icce); - // method (rbx): Method* // j_rarg0: receiver @@ -197,7 +212,7 @@ address ame_addr = __ pc(); __ jmp(Address(method, Method::from_compiled_offset())); - __ bind(throw_icce); + __ bind(L_no_such_interface); __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry())); __ flush(); @@ -224,8 +239,8 @@ (UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0); } else { // Itable stub size - return (DebugVtables ? 512 : 74) + (CountCompiledCalls ? 13 : 0) + - (UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0); + return (DebugVtables ? 512 : 140) + (CountCompiledCalls ? 13 : 0) + + (UseCompressedClassPointers ? 2 * MacroAssembler::instr_size_for_decode_klass_not_null() : 0); } // In order to tune these parameters, run the JVM with VM options // +PrintMiscellaneous and +WizardMode to see information about
--- a/src/hotspot/os/aix/os_aix.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/os/aix/os_aix.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1723,7 +1723,7 @@ local_sem_post(); } -static int check_pending_signals(bool wait) { +static int check_pending_signals() { Atomic::store(0, &sigint_count); for (;;) { for (int i = 0; i < NSIG + 1; i++) { @@ -1732,9 +1732,6 @@ return i; } } - if (!wait) { - return -1; - } JavaThread *thread = JavaThread::current(); ThreadBlockInVM tbivm(thread); @@ -1763,12 +1760,8 @@ } } -int os::signal_lookup() { - return check_pending_signals(false); -} - int os::signal_wait() { - return check_pending_signals(true); + return check_pending_signals(); } ////////////////////////////////////////////////////////////////////////////////
--- a/src/hotspot/os/bsd/os_bsd.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/os/bsd/os_bsd.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -52,13 +52,13 @@ #include "runtime/orderAccess.inline.hpp" #include "runtime/osThread.hpp" #include "runtime/perfMemory.hpp" +#include "runtime/semaphore.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/statSampler.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" #include "runtime/threadCritical.hpp" #include "runtime/timer.hpp" -#include "semaphore_bsd.hpp" #include "services/attachListener.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" @@ -91,7 +91,6 @@ # include <time.h> # include <pwd.h> # include <poll.h> -# include <semaphore.h> # include <fcntl.h> # include <string.h> # include <sys/param.h> @@ -1829,135 +1828,28 @@ // a counter for each possible signal value static volatile jint pending_signals[NSIG+1] = { 0 }; - -// 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 +static Semaphore* sig_sem = NULL; void os::signal_init_pd() { // Initialize signal structures ::memset((void*)pending_signals, 0, sizeof(pending_signals)); // Initialize signal semaphore - ::SEM_INIT(sig_sem, 0); + sig_sem = new Semaphore(); } void os::signal_notify(int sig) { - Atomic::inc(&pending_signals[sig]); - ::SEM_POST(sig_sem); + if (sig_sem != NULL) { + 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); for (;;) { for (int i = 0; i < NSIG + 1; i++) { @@ -1966,9 +1858,6 @@ return i; } } - if (!wait) { - return -1; - } JavaThread *thread = JavaThread::current(); ThreadBlockInVM tbivm(thread); @@ -1976,7 +1865,7 @@ do { thread->set_suspend_equivalent(); // 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? threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); @@ -1985,7 +1874,7 @@ // another thread suspended us. We don't want to continue running // while suspended because that would surprise the thread that // suspended us. - ::SEM_POST(sig_sem); + sig_sem->signal(); thread->java_suspend_self(); } @@ -1993,12 +1882,8 @@ } } -int os::signal_lookup() { - return check_pending_signals(false); -} - int os::signal_wait() { - return check_pending_signals(true); + return check_pending_signals(); } //////////////////////////////////////////////////////////////////////////////// @@ -2663,6 +2548,12 @@ // // 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) { // Save and restore errno to avoid confusing native code with EINTR // after sigsuspend.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/os/bsd/semaphore_bsd.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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__
--- a/src/hotspot/os/bsd/semaphore_bsd.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/os/bsd/semaphore_bsd.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ bool timedwait(unsigned int sec, int nsec); private: - static jlong currenttime(); + static int64_t currenttime(); }; typedef OSXSemaphore SemaphoreImpl;
--- a/src/hotspot/os/linux/os_linux.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/os/linux/os_linux.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -95,7 +95,6 @@ # include <sys/wait.h> # include <pwd.h> # include <poll.h> -# include <semaphore.h> # include <fcntl.h> # include <string.h> # include <syscall.h> @@ -2479,11 +2478,11 @@ 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; // Semaphore's are always associated with CLOCK_REALTIME 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) { ts.tv_sec += MAX_SECS; ts.tv_nsec = 0; @@ -2535,7 +2534,7 @@ static volatile jint pending_signals[NSIG+1] = { 0 }; // Linux(POSIX) specific hand shaking semaphore. -static sem_t sig_sem; +static Semaphore* sig_sem = NULL; static PosixSemaphore sr_semaphore; void os::signal_init_pd() { @@ -2543,15 +2542,21 @@ ::memset((void*)pending_signals, 0, sizeof(pending_signals)); // Initialize signal semaphore - ::sem_init(&sig_sem, 0, 0); + sig_sem = new Semaphore(); } void os::signal_notify(int sig) { - Atomic::inc(&pending_signals[sig]); - ::sem_post(&sig_sem); -} - -static int check_pending_signals(bool wait) { + if (sig_sem != NULL) { + 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() { Atomic::store(0, &sigint_count); for (;;) { for (int i = 0; i < NSIG + 1; i++) { @@ -2560,9 +2565,6 @@ return i; } } - if (!wait) { - return -1; - } JavaThread *thread = JavaThread::current(); ThreadBlockInVM tbivm(thread); @@ -2570,7 +2572,7 @@ do { thread->set_suspend_equivalent(); // 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? threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); @@ -2579,7 +2581,7 @@ // another thread suspended us. We don't want to continue running // while suspended because that would surprise the thread that // suspended us. - ::sem_post(&sig_sem); + sig_sem->signal(); thread->java_suspend_self(); } @@ -2587,12 +2589,8 @@ } } -int os::signal_lookup() { - return check_pending_signals(false); -} - int os::signal_wait() { - return check_pending_signals(true); + return check_pending_signals(); } //////////////////////////////////////////////////////////////////////////////// @@ -4317,7 +4315,7 @@ // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED while (true) { - if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { + if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2 * NANOSECS_PER_MILLISEC))) { break; } else { // timeout @@ -4351,7 +4349,7 @@ while (true) { 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()) { return; }
--- a/src/hotspot/os/posix/os_posix.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/os/posix/os_posix.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -31,14 +31,8 @@ #include "utilities/macros.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 <pthread.h> -#include <semaphore.h> #include <signal.h> #include <sys/mman.h> #include <sys/resource.h> @@ -1499,67 +1493,6 @@ } } -// 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. // Not currently usable by Solaris.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/os/posix/semaphore_posix.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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__ +
--- a/src/hotspot/os/posix/semaphore_posix.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/os/posix/semaphore_posix.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -45,15 +45,7 @@ void wait(); bool trywait(); - bool timedwait(unsigned int sec, int nsec) { - return timedwait(create_timespec(sec, nsec)); - } - - private: 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;
--- a/src/hotspot/os/solaris/os_solaris.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/os/solaris/os_solaris.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -2062,7 +2062,7 @@ 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; unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); @@ -2100,7 +2100,7 @@ static jint *pending_signals = NULL; static int *preinstalled_sigs = NULL; static struct sigaction *chainedsigactions = NULL; -static sema_t sig_sem; +static Semaphore* sig_sem = NULL; typedef int (*version_getting_t)(); version_getting_t os::Solaris::get_libjsig_version = NULL; @@ -2115,6 +2115,7 @@ Sigexit = Maxsignum+1; assert(Maxsignum >0, "Unable to obtain max signal number"); + // Initialize signal structures // pending_signals has one int per signal // The additional signal is for SIGEXIT - exit signal to signal_thread pending_signals = (jint *)os::malloc(sizeof(jint) * (Sigexit+1), mtInternal); @@ -2132,21 +2133,22 @@ } void os::signal_init_pd() { - int ret; - - ret = ::sema_init(&sig_sem, 0, NULL, NULL); - assert(ret == 0, "sema_init() failed"); -} - -void os::signal_notify(int signal_number) { - int ret; - - Atomic::inc(&pending_signals[signal_number]); - ret = ::sema_post(&sig_sem); - assert(ret == 0, "sema_post() failed"); -} - -static int check_pending_signals(bool wait_for_signal) { + // Initialize signal semaphore + sig_sem = new Semaphore(); +} + +void os::signal_notify(int sig) { + if (sig_sem != NULL) { + 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() { int ret; while (true) { for (int i = 0; i < Sigexit + 1; i++) { @@ -2155,19 +2157,13 @@ return i; } } - if (!wait_for_signal) { - return -1; - } JavaThread *thread = JavaThread::current(); ThreadBlockInVM tbivm(thread); bool threadIsSuspended; do { thread->set_suspend_equivalent(); - // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() - while ((ret = ::sema_wait(&sig_sem)) == EINTR) - ; - assert(ret == 0, "sema_wait() failed"); + sig_sem->wait(); // were we externally suspended while we were waiting? threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); @@ -2176,8 +2172,7 @@ // another thread suspended us. We don't want to continue running // while suspended because that would surprise the thread that // suspended us. - ret = ::sema_post(&sig_sem); - assert(ret == 0, "sema_post() failed"); + sig_sem->signal(); thread->java_suspend_self(); } @@ -2185,12 +2180,8 @@ } } -int os::signal_lookup() { - return check_pending_signals(false); -} - int os::signal_wait() { - return check_pending_signals(true); + return check_pending_signals(); } //////////////////////////////////////////////////////////////////////////////// @@ -3599,7 +3590,7 @@ // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED while (true) { - if (sr_semaphore.timedwait(0, 2000 * NANOSECS_PER_MILLISEC)) { + if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2000 * NANOSECS_PER_MILLISEC))) { break; } else { // timeout @@ -3633,7 +3624,7 @@ while (true) { 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()) { return; }
--- a/src/hotspot/os/windows/os_windows.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/os/windows/os_windows.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,6 @@ #include "runtime/threadCritical.hpp" #include "runtime/timer.hpp" #include "runtime/vm_version.hpp" -#include "semaphore_windows.hpp" #include "services/attachListener.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" @@ -1845,36 +1844,6 @@ 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 // NOTE that this is a workaround for an apparent kernel bug where if // a signal handler for SIGBREAK is installed then that signal handler @@ -1966,13 +1935,14 @@ // a counter for each possible signal value, including signal_thread exit signal static volatile jint pending_signals[NSIG+1] = { 0 }; -static HANDLE sig_sem = NULL; +static Semaphore* sig_sem = NULL; void os::signal_init_pd() { // Initialize signal structures 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 // events like CTRL_LOGOFF_EVENT, which are used to implement the @@ -1994,17 +1964,18 @@ } } -void os::signal_notify(int signal_number) { - BOOL ret; +void os::signal_notify(int sig) { if (sig_sem != NULL) { - Atomic::inc(&pending_signals[signal_number]); - ret = ::ReleaseSemaphore(sig_sem, 1, NULL); - assert(ret != 0, "ReleaseSemaphore() failed"); - } -} - -static int check_pending_signals(bool wait_for_signal) { - DWORD ret; + 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() { while (true) { for (int i = 0; i < NSIG + 1; i++) { jint n = pending_signals[i]; @@ -2012,10 +1983,6 @@ return i; } } - if (!wait_for_signal) { - return -1; - } - JavaThread *thread = JavaThread::current(); ThreadBlockInVM tbivm(thread); @@ -2024,8 +1991,7 @@ do { thread->set_suspend_equivalent(); // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() - ret = ::WaitForSingleObject(sig_sem, INFINITE); - assert(ret == WAIT_OBJECT_0, "WaitForSingleObject() failed"); + sig_sem->wait(); // were we externally suspended while we were waiting? threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); @@ -2034,8 +2000,7 @@ // another thread suspended us. We don't want to continue running // while suspended because that would surprise the thread that // suspended us. - ret = ::ReleaseSemaphore(sig_sem, 1, NULL); - assert(ret != 0, "ReleaseSemaphore() failed"); + sig_sem->signal(); thread->java_suspend_self(); } @@ -2043,12 +2008,8 @@ } } -int os::signal_lookup() { - return check_pending_signals(false); -} - int os::signal_wait() { - return check_pending_signals(true); + return check_pending_signals(); } // Implicit OS exception handling @@ -4394,13 +4355,49 @@ // Is a (classpath) directory empty? bool os::dir_is_empty(const char* path) { - WIN32_FIND_DATA fd; - HANDLE f = FindFirstFile(path, &fd); - if (f == INVALID_HANDLE_VALUE) { - return true; - } - FindClose(f); - return false; + char* search_path = (char*)os::malloc(strlen(path) + 3, mtInternal); + if (search_path == NULL) { + errno = ENOMEM; + return false; + } + strcpy(search_path, path); + // 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hotspot/os/windows/semaphore_windows.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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; +}
--- a/src/hotspot/share/aot/aotCompiledMethod.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/aot/aotCompiledMethod.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -270,7 +270,7 @@ CompiledIC *ic = CompiledIC_at(&iter); if (ic->is_icholder_call()) { CompiledICHolder* cichk = ic->cached_icholder(); - f(cichk->holder_method()); + f(cichk->holder_metadata()); f(cichk->holder_klass()); } else { // Get Klass* or NULL (if value is -1) from GOT cell of virtual call PLT stub.
--- a/src/hotspot/share/ci/ciInstanceKlass.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/ci/ciInstanceKlass.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -34,35 +34,12 @@ #include "oops/oop.inline.hpp" #include "oops/fieldStreams.hpp" #include "runtime/fieldDescriptor.hpp" -#if INCLUDE_ALL_GCS -# include "gc/g1/g1SATBCardTableModRefBS.hpp" -#endif // ciInstanceKlass // // This class represents a Klass* in the HotSpot virtual machine // 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 @@ -88,8 +65,12 @@ _has_injected_fields = -1; _implementor = NULL; // we will fill these lazily - oop holder = ik->klass_holder(); - ensure_metadata_alive(holder); + // 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. + oop holder = ik->klass_holder_phantom(); if (ik->is_anonymous()) { // Though ciInstanceKlass records class loader oop, it's not enough to keep // VM anonymous classes alive (loader == NULL). Klass holder should be used instead.
--- a/src/hotspot/share/classfile/classLoaderData.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/classfile/classLoaderData.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -63,6 +63,7 @@ #include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" +#include "oops/access.inline.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" @@ -75,9 +76,6 @@ #include "utilities/growableArray.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1SATBCardTableModRefBS.hpp" -#endif // INCLUDE_ALL_GCS #if INCLUDE_TRACE #include "trace/tracing.hpp" #endif @@ -759,18 +757,9 @@ oop* ptr = h.ptr_raw(); if (ptr != NULL) { assert(_handles.contains(ptr), "Got unexpected handle " PTR_FORMAT, p2i(ptr)); -#if INCLUDE_ALL_GCS - // This barrier is used by G1 to remember the old oop values, so - // that we don't forget any objects that were live at the snapshot at - // the beginning. - if (UseG1GC) { - oop obj = *ptr; - if (obj != NULL) { - G1SATBCardTableModRefBS::enqueue(obj); - } - } -#endif - *ptr = NULL; + // This root is not walked in safepoints, and hence requires an appropriate + // decorator that e.g. maintains the SATB invariant in SATB collectors. + RootAccess<IN_CONCURRENT_ROOT>::oop_store(ptr, oop(NULL)); } }
--- a/src/hotspot/share/classfile/classLoaderData.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/classfile/classLoaderData.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -217,6 +217,7 @@ friend class ClassLoaderDataGraphKlassIteratorAtomic; friend class ClassLoaderDataGraphKlassIteratorStatic; friend class ClassLoaderDataGraphMetaspaceIterator; + friend class InstanceKlass; friend class MetaDataFactory; friend class Method;
--- a/src/hotspot/share/classfile/javaClasses.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/classfile/javaClasses.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,8 @@ #include "code/dependencyContext.hpp" #include "code/pcDesc.hpp" #include "interpreter/interpreter.hpp" +#include "logging/log.hpp" +#include "logging/logStream.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" @@ -104,52 +106,59 @@ } -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 +// Finds local fields only, including static fields. Static field offsets are from the +// beginning of the mirror. +static void compute_offset(int &dest_offset, + InstanceKlass* ik, Symbol* name_symbol, Symbol* signature_symbol, + bool is_static = false) { + fieldDescriptor fd; + if (ik == NULL) { + ResourceMark rm; + 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"); } -} - -// Helpful routine for computing field offsets at run time rather than hardcoding them -static void -compute_offset(int &dest_offset, - Klass* klass, Symbol* name_symbol, Symbol* signature_symbol, - bool is_static = false, bool allow_super = false) { - fieldDescriptor fd; - InstanceKlass* ik = InstanceKlass::cast(klass); - if (!find_field(ik, name_symbol, signature_symbol, &fd, is_static, allow_super)) { + + if (!ik->find_local_field(name_symbol, signature_symbol, &fd) || fd.is_static() != is_static) { ResourceMark rm; - tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string()); + 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 - ik->print(); - tty->print_cr("all fields:"); - for (AllFieldStream fs(ik); !fs.done(); fs.next()) { - tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int()); - } + // Prints all fields and offsets + Log(class) lt; + LogStream ls(lt.error()); + ik->print_on(&ls); #endif //PRODUCT 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(); } +// 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 +// Old versions should be cleaned out since Hotspot only supports the current JDK, and this +// function should be removed. static void compute_optional_offset(int& dest_offset, - Klass* klass, Symbol* name_symbol, Symbol* signature_symbol, - bool allow_super = false) { + InstanceKlass* ik, Symbol* name_symbol, Symbol* signature_symbol) { fieldDescriptor fd; - InstanceKlass* ik = InstanceKlass::cast(klass); - if (find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) { + if (ik->find_local_field(name_symbol, signature_symbol, &fd)) { dest_offset = fd.offset(); } } - int java_lang_String::value_offset = 0; int java_lang_String::hash_offset = 0; int java_lang_String::coder_offset = 0; @@ -163,10 +172,10 @@ void java_lang_String::compute_offsets() { 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(hash_offset, k, vmSymbols::hash_name(), vmSymbols::int_signature()); - compute_offset(coder_offset, k, vmSymbols::coder_name(), vmSymbols::byte_signature()); + compute_offset(hash_offset, k, "hash", vmSymbols::int_signature()); + compute_offset(coder_offset, k, "coder", vmSymbols::byte_signature()); initialized = true; } @@ -619,12 +628,12 @@ bool java_lang_String::equals(oop java_string, jchar* chars, int len) { assert(java_string->klass() == SystemDictionary::String_klass(), "must be java_string"); - typeArrayOop value = java_lang_String::value(java_string); - int length = java_lang_String::length(java_string); + typeArrayOop value = java_lang_String::value_no_keepalive(java_string); + int length = java_lang_String::length(java_string); if (length != len) { 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) { for (int i = 0; i < len; i++) { if (value->char_at(i) != chars[i]) { @@ -646,12 +655,12 @@ "must be java String"); assert(str2->klass() == SystemDictionary::String_klass(), "must be java String"); - typeArrayOop value1 = java_lang_String::value(str1); - int length1 = java_lang_String::length(str1); - bool is_latin1 = java_lang_String::is_latin1(str1); - typeArrayOop value2 = java_lang_String::value(str2); - int length2 = java_lang_String::length(str2); - bool is_latin2 = java_lang_String::is_latin1(str2); + typeArrayOop value1 = java_lang_String::value_no_keepalive(str1); + int length1 = java_lang_String::length(value1); + bool is_latin1 = java_lang_String::is_latin1(str1); + typeArrayOop value2 = java_lang_String::value_no_keepalive(str2); + int length2 = java_lang_String::length(value2); + bool is_latin2 = java_lang_String::is_latin1(str2); if ((length1 != length2) || (is_latin1 != is_latin2)) { // Strings of different size or with different @@ -659,7 +668,7 @@ return false; } 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)) { return false; } @@ -669,7 +678,7 @@ void java_lang_String::print(oop java_string, outputStream* st) { 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) { // This can happen if, e.g., printing a String @@ -1161,25 +1170,11 @@ assert(!offsets_computed, "offsets should be initialized only once"); offsets_computed = true; - Klass* k = SystemDictionary::Class_klass(); - // The classRedefinedCount field is only present starting in 1.5, - // so don't go fatal. - compute_optional_offset(classRedefinedCount_offset, - k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_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()); + InstanceKlass* k = SystemDictionary::Class_klass(); + compute_offset(classRedefinedCount_offset, k, "classRedefinedCount", vmSymbols::int_signature()); + compute_offset(_class_loader_offset, k, "classLoader", vmSymbols::classloader_signature()); + compute_offset(_component_mirror_offset, k, "componentType", vmSymbols::class_signature()); + compute_offset(_module_offset, k, "module", vmSymbols::module_signature()); // 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 @@ -1234,24 +1229,22 @@ void java_lang_Thread::compute_offsets() { 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(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature()); - compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature()); - compute_offset(_inheritedAccessControlContext_offset, k, vmSymbols::inheritedAccessControlContext_name(), vmSymbols::accesscontrolcontext_signature()); + compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), + 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(_daemon_offset, k, vmSymbols::daemon_name(), vmSymbols::bool_signature()); - compute_offset(_eetop_offset, k, vmSymbols::eetop_name(), vmSymbols::long_signature()); - compute_offset(_stillborn_offset, k, vmSymbols::stillborn_name(), vmSymbols::bool_signature()); - // The stackSize field is only present starting in 1.4, so don't go fatal. - compute_optional_offset(_stackSize_offset, k, vmSymbols::stackSize_name(), vmSymbols::long_signature()); - // The tid and thread_status fields are only present starting in 1.5, so don't go fatal. - compute_optional_offset(_tid_offset, k, vmSymbols::thread_id_name(), vmSymbols::long_signature()); - compute_optional_offset(_thread_status_offset, k, vmSymbols::thread_status_name(), vmSymbols::int_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()); + compute_offset(_eetop_offset, k, "eetop", vmSymbols::long_signature()); + compute_offset(_stillborn_offset, k, "stillborn", vmSymbols::bool_signature()); + compute_offset(_stackSize_offset, k, "stackSize", vmSymbols::long_signature()); + compute_offset(_tid_offset, k, "tid", vmSymbols::long_signature()); + compute_offset(_thread_status_offset, k, "threadStatus", vmSymbols::int_signature()); + compute_offset(_park_blocker_offset, k, "parkBlocker", vmSymbols::object_signature()); + compute_offset(_park_event_offset, k, "nativeParkEventPointer", vmSymbols::long_signature()); } @@ -1486,7 +1479,7 @@ void java_lang_ThreadGroup::compute_offsets() { 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(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); @@ -1501,8 +1494,13 @@ void java_lang_Throwable::compute_offsets() { - Klass* k = SystemDictionary::Throwable_klass(); - compute_offset(depth_offset, k, vmSymbols::depth_name(), vmSymbols::int_signature()); + InstanceKlass* k = SystemDictionary::Throwable_klass(); + 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() { @@ -2270,23 +2268,23 @@ } void java_lang_StackFrameInfo::compute_offsets() { - Klass* k = SystemDictionary::StackFrameInfo_klass(); - compute_offset(_memberName_offset, k, vmSymbols::memberName_name(), vmSymbols::object_signature()); - compute_offset(_bci_offset, k, vmSymbols::bci_name(), vmSymbols::short_signature()); + InstanceKlass* k = SystemDictionary::StackFrameInfo_klass(); + compute_offset(_memberName_offset, k, "memberName", vmSymbols::object_signature()); + compute_offset(_bci_offset, k, "bci", vmSymbols::short_signature()); STACKFRAMEINFO_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } void java_lang_LiveStackFrameInfo::compute_offsets() { - Klass* k = SystemDictionary::LiveStackFrameInfo_klass(); - compute_offset(_monitors_offset, k, vmSymbols::monitors_name(), vmSymbols::object_array_signature()); - compute_offset(_locals_offset, k, vmSymbols::locals_name(), vmSymbols::object_array_signature()); - compute_offset(_operands_offset, k, vmSymbols::operands_name(), vmSymbols::object_array_signature()); - compute_offset(_mode_offset, k, vmSymbols::mode_name(), vmSymbols::int_signature()); + InstanceKlass* k = SystemDictionary::LiveStackFrameInfo_klass(); + compute_offset(_monitors_offset, k, "monitors", vmSymbols::object_array_signature()); + compute_offset(_locals_offset, k, "locals", vmSymbols::object_array_signature()); + compute_offset(_operands_offset, k, "operands", vmSymbols::object_array_signature()); + compute_offset(_mode_offset, k, "mode", vmSymbols::int_signature()); } void java_lang_reflect_AccessibleObject::compute_offsets() { - Klass* k = SystemDictionary::reflect_AccessibleObject_klass(); - compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature()); + InstanceKlass* k = SystemDictionary::reflect_AccessibleObject_klass(); + compute_offset(override_offset, k, "override", vmSymbols::bool_signature()); } jboolean java_lang_reflect_AccessibleObject::override(oop reflect) { @@ -2300,7 +2298,7 @@ } 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(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); compute_offset(returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_signature()); @@ -2481,7 +2479,7 @@ } 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(parameterTypes_offset, k, vmSymbols::parameterTypes_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_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(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); compute_offset(type_offset, k, vmSymbols::type_name(), vmSymbols::class_signature()); @@ -2747,22 +2745,17 @@ } void reflect_ConstantPool::compute_offsets() { - Klass* k = SystemDictionary::reflect_ConstantPool_klass(); - // This null test can be removed post beta - if (k != NULL) { - // The field is called ConstantPool* in the sun.reflect.ConstantPool class. - compute_offset(_oop_offset, k, vmSymbols::ConstantPool_name(), vmSymbols::object_signature()); - } + InstanceKlass* k = SystemDictionary::reflect_ConstantPool_klass(); + // The field is called ConstantPool* in the sun.reflect.ConstantPool class. + compute_offset(_oop_offset, k, "constantPoolOop", vmSymbols::object_signature()); } void java_lang_reflect_Parameter::compute_offsets() { - Klass* k = SystemDictionary::reflect_Parameter_klass(); - if(NULL != k) { - compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_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(executable_offset, k, vmSymbols::executable_name(), vmSymbols::executable_signature()); - } + InstanceKlass* k = SystemDictionary::reflect_Parameter_klass(); + compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_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(executable_offset, k, vmSymbols::executable_name(), vmSymbols::executable_signature()); } Handle java_lang_reflect_Parameter::create(TRAPS) { @@ -2836,12 +2829,10 @@ } void java_lang_Module::compute_offsets() { - Klass* k = SystemDictionary::Module_klass(); - if(NULL != k) { - compute_offset(loader_offset, k, vmSymbols::loader_name(), vmSymbols::classloader_signature()); - compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); - MODULE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); - } + InstanceKlass* k = SystemDictionary::Module_klass(); + compute_offset(loader_offset, k, vmSymbols::loader_name(), vmSymbols::classloader_signature()); + compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); + MODULE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } @@ -2921,12 +2912,8 @@ } void reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() { - Klass* k = SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass(); - // This null test can be removed post beta - if (k != NULL) { - compute_offset(_base_offset, k, - vmSymbols::base_name(), vmSymbols::object_signature()); - } + InstanceKlass* k = SystemDictionary::reflect_UnsafeStaticFieldAccessorImpl_klass(); + compute_offset(_base_offset, k, "base", vmSymbols::object_signature()); } oop java_lang_boxing_object::initialize_and_allocate(BasicType type, TRAPS) { @@ -3084,6 +3071,13 @@ } // 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) { return ref->long_field(timestamp_offset); @@ -3113,10 +3107,8 @@ } void java_lang_invoke_DirectMethodHandle::compute_offsets() { - Klass* k = SystemDictionary::DirectMethodHandle_klass(); - if (k != NULL) { - compute_offset(_member_offset, k, vmSymbols::member_name(), vmSymbols::java_lang_invoke_MemberName_signature()); - } + InstanceKlass* k = SystemDictionary::DirectMethodHandle_klass(); + compute_offset(_member_offset, k, "member", vmSymbols::java_lang_invoke_MemberName_signature()); } // Support for java_lang_invoke_MethodHandle @@ -3137,16 +3129,13 @@ int java_lang_invoke_LambdaForm::_vmentry_offset; void java_lang_invoke_MethodHandle::compute_offsets() { - Klass* k = SystemDictionary::MethodHandle_klass(); - if (k != NULL) { - compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature()); - compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_lang_invoke_LambdaForm_signature()); - } + InstanceKlass* k = SystemDictionary::MethodHandle_klass(); + 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()); } void java_lang_invoke_MemberName::compute_offsets() { - Klass* k = SystemDictionary::MemberName_klass(); - assert (k != NULL, "jdk mismatch"); + InstanceKlass* k = SystemDictionary::MemberName_klass(); compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature()); @@ -3156,15 +3145,15 @@ } void java_lang_invoke_ResolvedMethodName::compute_offsets() { - Klass* k = SystemDictionary::ResolvedMethodName_klass(); + InstanceKlass* k = SystemDictionary::ResolvedMethodName_klass(); assert(k != NULL, "jdk mismatch"); RESOLVEDMETHOD_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } void java_lang_invoke_LambdaForm::compute_offsets() { - Klass* k = SystemDictionary::LambdaForm_klass(); + InstanceKlass* k = SystemDictionary::LambdaForm_klass(); 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) { @@ -3305,11 +3294,9 @@ int java_lang_invoke_MethodType::_ptypes_offset; void java_lang_invoke_MethodType::compute_offsets() { - Klass* k = SystemDictionary::MethodType_klass(); - if (k != NULL) { - compute_offset(_rtype_offset, k, vmSymbols::rtype_name(), vmSymbols::class_signature()); - compute_offset(_ptypes_offset, k, vmSymbols::ptypes_name(), vmSymbols::class_array_signature()); - } + InstanceKlass* k = SystemDictionary::MethodType_klass(); + compute_offset(_rtype_offset, k, "rtype", vmSymbols::class_signature()); + compute_offset(_ptypes_offset, k, "ptypes", vmSymbols::class_array_signature()); } void java_lang_invoke_MethodType::print_signature(oop mt, outputStream* st) { @@ -3392,12 +3379,10 @@ int java_lang_invoke_CallSite::_context_offset; void java_lang_invoke_CallSite::compute_offsets() { - Klass* k = SystemDictionary::CallSite_klass(); - if (k != NULL) { - compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature()); - compute_offset(_context_offset, k, vmSymbols::context_name(), - vmSymbols::java_lang_invoke_MethodHandleNatives_CallSiteContext_signature()); - } + InstanceKlass* k = SystemDictionary::CallSite_klass(); + compute_offset(_target_offset, k, "target", vmSymbols::java_lang_invoke_MethodHandle_signature()); + compute_offset(_context_offset, k, "context", + vmSymbols::java_lang_invoke_MethodHandleNatives_CallSiteContext_signature()); } oop java_lang_invoke_CallSite::context(oop call_site) { @@ -3412,10 +3397,8 @@ int java_lang_invoke_MethodHandleNatives_CallSiteContext::_vmdependencies_offset; void java_lang_invoke_MethodHandleNatives_CallSiteContext::compute_offsets() { - Klass* k = SystemDictionary::Context_klass(); - if (k != NULL) { - CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); - } + InstanceKlass* k = SystemDictionary::Context_klass(); + CALLSITECONTEXT_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } DependencyContext java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(oop call_site) { @@ -3434,28 +3417,12 @@ void java_security_AccessControlContext::compute_offsets() { assert(_isPrivileged_offset == 0, "offsets should be initialized only once"); - fieldDescriptor fd; - InstanceKlass* ik = SystemDictionary::AccessControlContext_klass(); - - if (!ik->find_local_field(vmSymbols::context_name(), vmSymbols::protectiondomain_signature(), &fd)) { - fatal("Invalid layout of java.security.AccessControlContext"); - } - _context_offset = fd.offset(); - - 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(); - } + InstanceKlass* k = SystemDictionary::AccessControlContext_klass(); + + compute_offset(_context_offset, k, "context", vmSymbols::protectiondomain_signature()); + compute_offset(_privilegedContext_offset, k, "privilegedContext", vmSymbols::accesscontrolcontext_signature()); + compute_offset(_isPrivileged_offset, k, "isPrivileged", vmSymbols::bool_signature()); + compute_offset(_isAuthorized_offset, k, "isAuthorized", vmSymbols::bool_signature()); } @@ -3504,16 +3471,17 @@ assert(!offsets_computed, "offsets should be initialized only once"); offsets_computed = true; - // The field indicating parallelCapable (parallelLockMap) is only present starting in 7, - Klass* k1 = SystemDictionary::ClassLoader_klass(); - compute_optional_offset(parallelCapable_offset, - k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature()); + InstanceKlass* k1 = SystemDictionary::ClassLoader_klass(); + compute_offset(parallelCapable_offset, + k1, "parallelLockMap", vmSymbols::concurrenthashmap_signature()); compute_offset(name_offset, k1, vmSymbols::name_name(), vmSymbols::string_signature()); 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); } @@ -3600,19 +3568,18 @@ } // Support for java_lang_System -int java_lang_System::in_offset_in_bytes() { - return (InstanceMirrorKlass::offset_of_static_fields() + static_in_offset); -} - - -int java_lang_System::out_offset_in_bytes() { - return (InstanceMirrorKlass::offset_of_static_fields() + static_out_offset); -} - - -int java_lang_System::err_offset_in_bytes() { - return (InstanceMirrorKlass::offset_of_static_fields() + static_err_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() { return static_out_offset; } +int java_lang_System::err_offset_in_bytes() { return static_err_offset; } bool java_lang_System::has_security_manager() { @@ -3682,7 +3649,6 @@ int java_lang_ref_Reference::queue_offset; int java_lang_ref_Reference::next_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::static_clock_offset; int java_lang_ClassLoader::parent_offset; @@ -3717,6 +3683,17 @@ // 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) { element->obj_field_put(fileName_offset, value); @@ -3776,6 +3753,16 @@ // 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) { o->obj_field_put(classes_offset, val); } @@ -3804,18 +3791,18 @@ 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+"); - 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) { if (_owner_offset != 0) return; 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, - vmSymbols::exclusive_owner_thread_name(), vmSymbols::thread_signature()); + "exclusiveOwnerThread", vmSymbols::thread_signature()); } oop java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(oop obj) { @@ -3823,71 +3810,37 @@ 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 // Invoked before SystemDictionary::initialize, so pre-loaded classes // are not available to determine the offset_of_static_fields. 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::value_offset = java_lang_boxing_object::hc_value_offset + header; - java_lang_boxing_object::long_value_offset = align_up((java_lang_boxing_object::hc_value_offset + header), 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_boxing_object::value_offset = member_offset(java_lang_boxing_object::hc_value_offset); + 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 = 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 void JavaClasses::compute_offsets() { // java_lang_Class::compute_offsets was called earlier in bootstrap + java_lang_System::compute_offsets(); java_lang_ClassLoader::compute_offsets(); java_lang_Throwable::compute_offsets(); java_lang_Thread::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_DirectMethodHandle::compute_offsets(); java_lang_invoke_MemberName::compute_offsets(); @@ -3910,6 +3863,7 @@ reflect_UnsafeStaticFieldAccessorImpl::compute_offsets(); java_lang_reflect_Parameter::compute_offsets(); java_lang_Module::compute_offsets(); + java_lang_StackTraceElement::compute_offsets(); java_lang_StackFrameInfo::compute_offsets(); java_lang_LiveStackFrameInfo::compute_offsets(); @@ -3947,62 +3901,6 @@ } } - -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 void JavaClasses::check_offsets() { @@ -4014,31 +3912,6 @@ #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) -#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) CHECK_OFFSET("java/lang/Boolean", java_lang_boxing_object, value, "Z"); @@ -4050,28 +3923,6 @@ CHECK_OFFSET("java/lang/Integer", java_lang_boxing_object, value, "I"); 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 CHECK_OFFSET("java/lang/ref/Reference", java_lang_ref_Reference, referent, "Ljava/lang/Object;"); @@ -4080,28 +3931,6 @@ // Fake field //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"); }
--- a/src/hotspot/share/classfile/javaClasses.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/classfile/javaClasses.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -102,6 +102,7 @@ // Accessors 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 bool is_latin1(oop java_string); static inline int length(oop java_string); @@ -444,9 +445,6 @@ hc_cause_offset = 2, // 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 enum { trace_methods_offset = 0, @@ -878,7 +876,6 @@ static int queue_offset; static int next_offset; static int discovered_offset; - static int number_of_fake_oop_fields; // Accessors static inline oop referent(oop ref); @@ -902,14 +899,6 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference { 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 static_clock_offset; @@ -919,6 +908,8 @@ // Accessors for statics static jlong clock(); static void set_clock(jlong value); + + static void compute_offsets(); }; // Interface to java.lang.invoke.MethodHandle objects @@ -1228,10 +1219,6 @@ class java_lang_ClassLoader : AllStatic { 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 bool offsets_computed; static int parent_offset; @@ -1279,13 +1266,6 @@ class java_lang_System : AllStatic { 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_out_offset; static int static_err_offset; @@ -1298,6 +1278,8 @@ static bool has_security_manager(); + static void compute_offsets(); + // Debugging friend class JavaClasses; }; @@ -1307,17 +1289,6 @@ class java_lang_StackTraceElement: AllStatic { 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 classLoaderName_offset; static int moduleName_offset; @@ -1344,6 +1315,8 @@ static void fill_in(Handle element, InstanceKlass* holder, const methodHandle& method, int version, int bci, Symbol* name, TRAPS); + static void compute_offsets(); + // Debugging friend class JavaClasses; }; @@ -1416,14 +1389,6 @@ class java_lang_AssertionStatusDirectives: AllStatic { private: - enum { - hc_classes_offset, - hc_classEnabled_offset, - hc_packages_offset, - hc_packageEnabled_offset, - hc_deflt_offset - }; - static int classes_offset; static int classEnabled_offset; static int packages_offset; @@ -1437,6 +1402,9 @@ static void set_packages(oop obj, oop val); static void set_packageEnabled(oop obj, oop val); static void set_deflt(oop obj, bool val); + + static void compute_offsets(); + // Debugging friend class JavaClasses; }; @@ -1508,9 +1476,6 @@ 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_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: enum InjectedFieldID { ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD_ENUM)
--- a/src/hotspot/share/classfile/javaClasses.inline.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/classfile/javaClasses.inline.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -26,6 +26,7 @@ #define SHARE_VM_CLASSFILE_JAVACLASSES_INLINE_HPP #include "classfile/javaClasses.hpp" +#include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/oopsHierarchy.hpp" @@ -53,6 +54,11 @@ assert(is_instance(java_string), "must be java_string"); 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) { assert(initialized && (hash_offset > 0), "Must be initialized"); assert(is_instance(java_string), "must be java_string"); @@ -68,11 +74,11 @@ int java_lang_String::length(oop java_string) { assert(initialized, "Must be initialized"); assert(is_instance(java_string), "must be java_string"); - typeArrayOop value_array = ((typeArrayOop)java_string->obj_field(value_offset)); - if (value_array == NULL) { + typeArrayOop value = java_lang_String::value_no_keepalive(java_string); + if (value == NULL) { return 0; } - int arr_length = value_array->length(); + int arr_length = value->length(); if (!is_latin1(java_string)) { assert((arr_length & 1) == 0, "should be even for UTF16 string"); arr_length >>= 1; // convert number of bytes to number of elements
--- a/src/hotspot/share/classfile/stringTable.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/classfile/stringTable.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -35,6 +35,7 @@ #include "memory/filemap.hpp" #include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" +#include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/mutexLocker.hpp" @@ -43,7 +44,6 @@ #include "utilities/macros.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/g1CollectedHeap.hpp" -#include "gc/g1/g1SATBCardTableModRefBS.hpp" #include "gc/g1/g1StringDedup.hpp" #endif @@ -124,6 +124,22 @@ } } +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) { assert(hash == java_lang_String::hash_code(name, len), "hash must be computed using java_lang_String::hash_code"); @@ -131,13 +147,16 @@ } oop StringTable::lookup_in_main_table(int index, jchar* name, - int len, unsigned int hash) { + int len, unsigned int hash) { int count = 0; for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) { count++; if (l->hash() == hash) { - if (java_lang_String::equals(l->literal(), name, len)) { - return l->literal(); + if (java_lang_String::equals(string_object_no_keepalive(l), name, len)) { + // 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 @@ 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) { // shared table always uses java_lang_String::hash_code unsigned int hash = java_lang_String::hash_code(name, len); @@ -217,8 +224,6 @@ int index = the_table()->hash_to_index(hash); string = the_table()->lookup_in_main_table(index, name, len, hash); - ensure_string_alive(string); - return string; } @@ -238,9 +243,6 @@ // Found if (found_string != NULL) { - if (found_string != string_or_null()) { - ensure_string_alive(found_string); - } return found_string; } @@ -276,10 +278,6 @@ hashValue, CHECK_NULL); } - if (added_or_found != string()) { - ensure_string_alive(added_or_found); - } - return added_or_found; } @@ -388,9 +386,9 @@ while (entry != NULL) { 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) { - f->do_oop((oop*)entry->literal_addr()); + f->do_oop(entry->literal_addr()); } p = entry->next_addr(); } else { @@ -429,7 +427,7 @@ for (int i = 0; i < the_table()->table_size(); ++i) { HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i); for ( ; p != NULL; p = p->next()) { - oop s = p->literal(); + oop s = string_object_no_keepalive(p); guarantee(s != NULL, "interned string is NULL"); unsigned int h = hash_string(s); guarantee(p->hash() == h, "broken hash in string table entry"); @@ -448,10 +446,10 @@ for (int i = 0; i < the_table()->table_size(); ++i) { HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i); for ( ; p != NULL; p = p->next()) { - oop s = p->literal(); - typeArrayOop value = java_lang_String::value(s); - int length = java_lang_String::length(s); - bool is_latin1 = java_lang_String::is_latin1(s); + oop s = string_object_no_keepalive(p); + typeArrayOop value = java_lang_String::value_no_keepalive(s); + int length = java_lang_String::length(s); + bool is_latin1 = java_lang_String::is_latin1(s); if (length <= 0) { st->print("%d: ", length); @@ -484,8 +482,8 @@ HashtableEntry<oop, mtSymbol>* e_ptr2) { // These entries are sanity checked by verify_and_compare_entries() // before this function is called. - oop str1 = e_ptr1->literal(); - oop str2 = e_ptr2->literal(); + oop str1 = string_object_no_keepalive(e_ptr1); + oop str2 = string_object_no_keepalive(e_ptr2); if (str1 == str2) { tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") " @@ -505,12 +503,12 @@ } StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt, - HashtableEntry<oop, mtSymbol>* e_ptr, - StringTable::VerifyMesgModes mesg_mode) { + HashtableEntry<oop, mtSymbol>* e_ptr, + StringTable::VerifyMesgModes mesg_mode) { VerifyRetTypes ret = _verify_pass; // be optimistic - oop str = e_ptr->literal(); + oop str = string_object_no_keepalive(e_ptr); if (str == NULL) { if (mesg_mode == _verify_with_mesgs) { tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt, @@ -684,7 +682,7 @@ assert(DumpSharedSpaces, "this function is only used with -Xshare:dump"); 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); if (new_v == NULL) { return NULL; @@ -708,7 +706,7 @@ for (int i = 0; i < the_table()->table_size(); ++i) { HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i); 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); if (hash == 0) { continue; @@ -721,7 +719,7 @@ } // set the archived string in bucket - bucket->set_literal(new_s); + set_string_object(bucket, new_s); // add to the compact table writer->add(hash, new_s); @@ -763,4 +761,3 @@ _shared_table.oops_do(f); } #endif //INCLUDE_CDS_JAVA_HEAP -
--- a/src/hotspot/share/classfile/stringTable.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/classfile/stringTable.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -76,6 +76,13 @@ static unsigned int hash_string(oop string); 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, sizeof (HashtableEntry<oop, mtSymbol>)) {}
--- a/src/hotspot/share/classfile/systemDictionary.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/classfile/systemDictionary.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -2775,7 +2775,17 @@ java_lang_invoke_MemberName::set_name (mname(), name_str()); java_lang_invoke_MemberName::set_type (mname(), signature_str()); 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. Handle type = MethodHandles::resolve_MemberName_type(mname, caller, CHECK_(empty));
--- a/src/hotspot/share/classfile/systemDictionary.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/classfile/systemDictionary.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -173,6 +173,7 @@ do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre ) \ /* 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(StringBuilder_klass, java_lang_StringBuilder, Pre ) \ do_klass(internal_Unsafe_klass, jdk_internal_misc_Unsafe, Pre ) \
--- a/src/hotspot/share/classfile/vmSymbols.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/classfile/vmSymbols.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -251,7 +251,6 @@ template(compiledLambdaForm_name, "<compiledLambdaForm>") /*fake name*/ \ template(star_name, "*") /*not really a name*/ \ template(invoke_name, "invoke") \ - template(override_name, "override") \ template(parameterTypes_name, "parameterTypes") \ template(returnType_name, "returnType") \ template(signature_name, "signature") \ @@ -265,7 +264,6 @@ template(parameter_annotations_name, "parameterAnnotations") \ template(annotation_default_name, "annotationDefault") \ template(reflect_ConstantPool, "jdk/internal/reflect/ConstantPool") \ - template(ConstantPool_name, "constantPoolOop") \ template(reflect_UnsafeStaticFieldAccessorImpl, "jdk/internal/reflect/UnsafeStaticFieldAccessorImpl")\ template(base_name, "base") \ /* Type Annotations (JDK 8 and above) */ \ @@ -304,6 +302,7 @@ /* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \ template(findMethodHandleType_name, "findMethodHandleType") \ template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \ + template(invokeExact_name, "invokeExact") \ template(linkMethodHandleConstant_name, "linkMethodHandleConstant") \ template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \ template(linkMethod_name, "linkMethod") \ @@ -340,8 +339,6 @@ template(stillborn_name, "stillborn") \ template(group_name, "group") \ template(daemon_name, "daemon") \ - template(eetop_name, "eetop") \ - template(thread_status_name, "threadStatus") \ template(run_method_name, "run") \ template(exit_method_name, "exit") \ template(add_method_name, "add") \ @@ -375,34 +372,21 @@ template(fillInStackTrace_name, "fillInStackTrace") \ template(getCause_name, "getCause") \ template(initCause_name, "initCause") \ - template(depth_name, "depth") \ template(setProperty_name, "setProperty") \ template(getProperty_name, "getProperty") \ template(context_name, "context") \ - template(privilegedContext_name, "privilegedContext") \ template(contextClassLoader_name, "contextClassLoader") \ template(inheritedAccessControlContext_name, "inheritedAccessControlContext") \ - template(isPrivileged_name, "isPrivileged") \ - template(isAuthorized_name, "isAuthorized") \ template(getClassContext_name, "getClassContext") \ template(wait_name, "wait") \ template(checkPackageAccess_name, "checkPackageAccess") \ - template(stackSize_name, "stackSize") \ - template(thread_id_name, "tid") \ template(newInstance0_name, "newInstance0") \ - template(limit_name, "limit") \ - template(member_name, "member") \ template(forName_name, "forName") \ template(forName0_name, "forName0") \ template(isJavaIdentifierStart_name, "isJavaIdentifierStart") \ 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(value_name, "value") \ - template(hash_name, "hash") \ - template(coder_name, "coder") \ template(compact_strings_name, "COMPACT_STRINGS") \ template(numberOfLeadingZeros_name, "numberOfLeadingZeros") \ template(numberOfTrailingZeros_name, "numberOfTrailingZeros") \ @@ -419,27 +403,17 @@ template(method_name, "method") \ template(vmindex_name, "vmindex") \ template(vmcount_name, "vmcount") \ - template(vmentry_name, "vmentry") \ template(flags_name, "flags") \ - template(rtype_name, "rtype") \ - template(ptypes_name, "ptypes") \ - template(form_name, "form") \ template(basicType_name, "basicType") \ template(append_name, "append") \ template(klass_name, "klass") \ template(array_klass_name, "array_klass") \ - template(memberName_name, "memberName") \ template(mid_name, "mid") \ template(cpref_name, "cpref") \ template(version_name, "version") \ - template(bci_name, "bci") \ template(methodName_name, "methodName") \ template(fileName_name, "fileName") \ 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(static_oop_field_count_name, "static_oop_field_count") \ template(protection_domain_name, "protection_domain") \ @@ -447,9 +421,11 @@ template(loader_data_name, "loader_data") \ template(vmdependencies_name, "vmdependencies") \ template(loader_name, "loader") \ - template(module_name, "module") \ template(getModule_name, "getModule") \ 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_signature, "(Ljava/lang/String;Ljava/lang/Module;)Ljava/lang/Package;") \ template(defineOrCheckPackage_name, "defineOrCheckPackage") \ @@ -498,6 +474,7 @@ template(short_signature, "S") \ template(bool_signature, "Z") \ template(void_signature, "V") \ + template(bool_array_signature, "[Z") \ template(byte_array_signature, "[B") \ template(char_array_signature, "[C") \ template(int_array_signature, "[I") \ @@ -552,6 +529,7 @@ template(object_array_signature, "[Ljava/lang/Object;") \ template(class_signature, "Ljava/lang/Class;") \ template(string_signature, "Ljava/lang/String;") \ + template(string_array_signature, "[Ljava/lang/String;") \ template(reference_signature, "Ljava/lang/ref/Reference;") \ template(sun_misc_Cleaner_signature, "Lsun/misc/Cleaner;") \ template(executable_signature, "Ljava/lang/reflect/Executable;") \ @@ -578,12 +556,6 @@ /* used by ClassFormatError when class name is not known yet */ \ 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 */ \ template(java_lang_StackTraceElement_array, "[Ljava/lang/StackTraceElement;") \ template(java_lang_management_ThreadState, "java/lang/management/ThreadState") \
--- a/src/hotspot/share/code/compiledIC.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/code/compiledIC.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -230,10 +230,13 @@ #ifdef ASSERT int index = call_info->resolved_method()->itable_index(); assert(index == itable_index, "CallInfo pre-computes this"); -#endif //ASSERT InstanceKlass* k = call_info->resolved_method()->method_holder(); assert(k->verify_itable_index(itable_index), "sanity check"); - InlineCacheBuffer::create_transition_stub(this, k, entry); +#endif //ASSERT + CompiledICHolder* holder = new CompiledICHolder(call_info->resolved_method()->method_holder(), + call_info->resolved_klass()); + holder->claim(); + InlineCacheBuffer::create_transition_stub(this, holder, entry); } else { assert(call_info->call_kind() == CallInfo::vtable_call, "either itable or vtable"); // Can be different than selected_method->vtable_index(), due to package-private etc. @@ -517,7 +520,14 @@ bool CompiledIC::is_icholder_entry(address entry) { CodeBlob* cb = CodeCache::find_blob_unsafe(entry); - return (cb != NULL && cb->is_adapter_blob()); + if (cb != NULL && cb->is_adapter_blob()) { + return true; + } + // itable stubs also use CompiledICHolder + if (VtableStubs::is_entry_point(entry) && VtableStubs::stub_containing(entry)->is_itable_stub()) { + return true; + } + return false; } bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm) {
--- a/src/hotspot/share/code/compiledIC.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/code/compiledIC.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -45,11 +45,11 @@ // \ / \ / // [4] \ / [4] \->-/ // \->- Megamorphic -<-/ -// (Method*) +// (CompiledICHolder*) // -// The text in paranteses () refere to the value of the inline cache receiver (mov instruction) +// The text in parentheses () refers to the value of the inline cache receiver (mov instruction) // -// The numbers in square brackets refere to the kind of transition: +// The numbers in square brackets refer to the kind of transition: // [1]: Initial fixup. Receiver it found from debug information // [2]: Compilation of a method // [3]: Recompilation of a method (note: only entry is changed. The Klass* must stay the same)
--- a/src/hotspot/share/code/compiledMethod.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/code/compiledMethod.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -404,8 +404,7 @@ // yet be marked below. (We check this further below). CompiledICHolder* cichk_oop = ic->cached_icholder(); - if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) && - cichk_oop->holder_klass()->is_loader_alive(is_alive)) { + if (cichk_oop->is_loader_alive(is_alive)) { return; } } else {
--- a/src/hotspot/share/code/dependencies.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/code/dependencies.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -241,8 +241,18 @@ 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()); } - Klass* as_klass(OopRecorder* rec) const { assert(as_metadata(rec)->is_klass(), "oops"); return (Klass*) as_metadata(rec); } - Method* as_method(OopRecorder* rec) const { assert(as_metadata(rec)->is_method(), "oops"); return (Method*) as_metadata(rec); } + Klass* as_klass(OopRecorder* rec) const { + 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()); } }; #endif // INCLUDE_JVMCI
--- a/src/hotspot/share/code/nmethod.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/code/nmethod.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1547,7 +1547,7 @@ CompiledIC *ic = CompiledIC_at(&iter); if (ic->is_icholder_call()) { CompiledICHolder* cichk = ic->cached_icholder(); - f(cichk->holder_method()); + f(cichk->holder_metadata()); f(cichk->holder_klass()); } else { Metadata* ic_oop = ic->cached_metadata();
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -445,9 +445,7 @@ assert_heap_not_locked_and_not_at_safepoint(); assert(!is_humongous(word_size), "we do not allow humongous TLABs"); - uint dummy_gc_count_before; - uint dummy_gclocker_retry_count = 0; - return attempt_allocation(word_size, &dummy_gc_count_before, &dummy_gclocker_retry_count); + return attempt_allocation(word_size); } HeapWord* @@ -455,62 +453,16 @@ bool* gc_overhead_limit_was_exceeded) { assert_heap_not_locked_and_not_at_safepoint(); - // Loop until the allocation is satisfied, or unsatisfied after GC. - for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) { - 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); - } + if (is_humongous(word_size)) { + return attempt_allocation_humongous(word_size); } - - ShouldNotReachHere(); - return NULL; + return attempt_allocation(word_size); } HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size, - AllocationContext_t context, - uint* gc_count_before_ret, - uint* gclocker_retry_count_ret) { + AllocationContext_t context) { + ResourceMark rm; // For retrieving the thread names in log messages. + // Make sure you read the note in attempt_allocation_humongous(). assert_heap_not_locked_and_not_at_safepoint(); @@ -525,7 +477,7 @@ // fails to perform the allocation. b) is the only case when we'll // return 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; uint gc_count_before; @@ -536,30 +488,23 @@ return result; } - if (GCLocker::is_active_and_needs_gc()) { - if (g1_policy()->can_expand_young_list()) { - // No need for an ergo verbose message here, - // can_expand_young_list() does this when it returns true. - 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; + // If the GCLocker is active and we are bound for a GC, try expanding young gen. + // This is different to when only GCLocker::needs_gc() is set: try to avoid + // waiting because the GCLocker is active to not wait too long. + if (GCLocker::is_active_and_needs_gc() && g1_policy()->can_expand_young_list()) { + // No need for an ergo message here, can_expand_young_list() does this when + // it returns true. + result = _allocator->attempt_allocation_force(word_size, context); + if (result != NULL) { + return result; } } + // 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) { @@ -568,28 +513,33 @@ GCCause::_g1_inc_collection_pause); if (result != NULL) { 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; } if (succeeded) { - // If we get here we successfully scheduled a collection which - // failed to allocate. No point in trying to allocate - // further. We'll just return NULL. - MutexLockerEx x(Heap_lock); - *gc_count_before_ret = total_collections(); + // We successfully scheduled a collection which failed to allocate. No + // point in trying to allocate further. We'll just return NULL. + log_trace(gc, alloc)("%s: Successfully scheduled collection failing to allocate " + SIZE_FORMAT " words", Thread::current()->name(), word_size); return NULL; } + log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating " SIZE_FORMAT " words", + Thread::current()->name(), word_size); } else { - if (*gclocker_retry_count_ret > GCLockerRetryAllocationCount) { - MutexLockerEx x(Heap_lock); - *gc_count_before_ret = total_collections(); + // Failed to schedule a collection. + if (gclocker_retry_count > GCLockerRetryAllocationCount) { + log_warning(gc, alloc)("%s: Retried waiting for GCLocker too often allocating " + SIZE_FORMAT " words", Thread::current()->name(), word_size); return NULL; } + log_trace(gc, alloc)("%s: Stall until clear", Thread::current()->name()); // The GCLocker is either active or the GCLocker initiated // GC has not yet been performed. Stall until it is and // then retry the allocation. GCLocker::stall_until_clear(); - (*gclocker_retry_count_ret) += 1; + gclocker_retry_count += 1; } // We can reach here if we were unsuccessful in scheduling a @@ -600,6 +550,7 @@ // first attempt (without holding the Heap_lock) here and the // follow-on attempt will be at the start of the next loop // iteration (after taking the Heap_lock). + result = _allocator->attempt_allocation(word_size, context); if (result != NULL) { return result; @@ -608,8 +559,8 @@ // Give a warning if we seem to be looping forever. if ((QueuedAllocationWarningCount > 0) && (try_count % QueuedAllocationWarningCount == 0)) { - log_warning(gc)("G1CollectedHeap::attempt_allocation_slow() " - "retries %d times", try_count); + log_warning(gc, alloc)("%s: Retried allocation %u times for " SIZE_FORMAT " words", + Thread::current()->name(), try_count, word_size); } } @@ -830,9 +781,7 @@ } } -inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size, - uint* gc_count_before_ret, - uint* gclocker_retry_count_ret) { +inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size) { assert_heap_not_locked_and_not_at_safepoint(); assert(!is_humongous(word_size), "attempt_allocation() should not " "be called for humongous allocation requests"); @@ -841,10 +790,7 @@ HeapWord* result = _allocator->attempt_allocation(word_size, context); if (result == NULL) { - result = attempt_allocation_slow(word_size, - context, - gc_count_before_ret, - gclocker_retry_count_ret); + result = attempt_allocation_slow(word_size, context); } assert_heap_not_locked(); if (result != NULL) { @@ -925,9 +871,9 @@ decrease_used(size_used); } -HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size, - uint* gc_count_before_ret, - uint* gclocker_retry_count_ret) { +HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) { + ResourceMark rm; // For retrieving the thread names in log messages. + // The structure of this method has a lot of similarities to // attempt_allocation_slow(). The reason these two were not merged // into a single one is that such a method would require several "if @@ -958,10 +904,11 @@ // fails to perform the allocation. b) is the only case when we'll // return 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; uint gc_count_before; + { MutexLockerEx x(Heap_lock); @@ -975,69 +922,63 @@ return result; } - if (GCLocker::is_active_and_needs_gc()) { - 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 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; result = do_collection_pause(word_size, gc_count_before, &succeeded, GCCause::_g1_humongous_allocation); if (result != NULL) { 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; } if (succeeded) { - // If we get here we successfully scheduled a collection which - // failed to allocate. No point in trying to allocate - // further. We'll just return NULL. - MutexLockerEx x(Heap_lock); - *gc_count_before_ret = total_collections(); + // We successfully scheduled a collection which failed to allocate. No + // point in trying to allocate further. We'll just return NULL. + log_trace(gc, alloc)("%s: Successfully scheduled collection failing to allocate " + SIZE_FORMAT " words", Thread::current()->name(), word_size); return NULL; } + log_trace(gc, alloc)("%s: Unsuccessfully scheduled collection allocating " SIZE_FORMAT "", + Thread::current()->name(), word_size); } else { - if (*gclocker_retry_count_ret > GCLockerRetryAllocationCount) { - MutexLockerEx x(Heap_lock); - *gc_count_before_ret = total_collections(); + // Failed to schedule a collection. + if (gclocker_retry_count > GCLockerRetryAllocationCount) { + log_warning(gc, alloc)("%s: Retried waiting for GCLocker too often allocating " + SIZE_FORMAT " words", Thread::current()->name(), word_size); return NULL; } + log_trace(gc, alloc)("%s: Stall until clear", Thread::current()->name()); // The GCLocker is either active or the GCLocker initiated // GC has not yet been performed. Stall until it is and // then retry the allocation. GCLocker::stall_until_clear(); - (*gclocker_retry_count_ret) += 1; + gclocker_retry_count += 1; } + // We can reach here if we were unsuccessful in scheduling a // 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 // allocation attempt in case another thread successfully - // performed a collection and reclaimed enough space. Give a - // warning if we seem to be looping forever. + // performed a collection and reclaimed enough space. + // 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) && (try_count % QueuedAllocationWarningCount == 0)) { - log_warning(gc)("G1CollectedHeap::attempt_allocation_humongous() " - "retries %d times", try_count); + log_warning(gc, alloc)("%s: Retried allocation %u times for " SIZE_FORMAT " words", + Thread::current()->name(), try_count, word_size); } } @@ -1339,7 +1280,6 @@ context, expect_null_mutator_alloc_region); if (result != NULL) { - assert(*gc_succeeded, "sanity"); return result; } @@ -1349,7 +1289,6 @@ // do something smarter than full collection to satisfy a failed alloc.) result = expand_and_allocate(word_size, context); if (result != NULL) { - assert(*gc_succeeded, "sanity"); return result; } @@ -1401,7 +1340,6 @@ succeeded); if (result != NULL) { - assert(*succeeded, "sanity"); return result; } @@ -1412,7 +1350,6 @@ // space available is large enough for the allocation, then a more // complete compaction phase than we've tried so far might be // appropriate. - assert(*succeeded, "sanity"); return NULL; } @@ -2147,7 +2084,7 @@ // This notify_all() will ensure that a thread that called // System.gc() with (with ExplicitGCInvokesConcurrent set or not) // 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(); } @@ -2175,13 +2112,12 @@ // Schedule an initial-mark evacuation pause that will start a // concurrent cycle. We're setting word_size to 0 which means that // we are not requesting a post-GC allocation. - VM_G1IncCollectionPause op(gc_count_before, - 0, /* word_size */ - true, /* should_initiate_conc_mark */ - g1_policy()->max_pause_time_ms(), - cause); - op.set_allocation_context(AllocationContext::current()); - + VM_G1CollectForAllocation op(0, /* word_size */ + gc_count_before, + cause, + true, /* should_initiate_conc_mark */ + g1_policy()->max_pause_time_ms(), + AllocationContext::current()); VMThread::execute(&op); if (!op.pause_succeeded()) { if (old_marking_count_before == _old_marking_cycles_started) { @@ -2204,11 +2140,12 @@ // Schedule a standard evacuation pause. We're setting word_size // to 0 which means that we are not requesting a post-GC allocation. - VM_G1IncCollectionPause op(gc_count_before, - 0, /* word_size */ - false, /* should_initiate_conc_mark */ - g1_policy()->max_pause_time_ms(), - cause); + VM_G1CollectForAllocation op(0, /* word_size */ + gc_count_before, + cause, + false, /* should_initiate_conc_mark */ + g1_policy()->max_pause_time_ms(), + AllocationContext::current()); VMThread::execute(&op); } else { // Schedule a Full GC. @@ -2619,13 +2556,12 @@ bool* succeeded, GCCause::Cause gc_cause) { assert_heap_not_locked_and_not_at_safepoint(); - VM_G1IncCollectionPause op(gc_count_before, - word_size, - false, /* should_initiate_conc_mark */ - g1_policy()->max_pause_time_ms(), - gc_cause); - - op.set_allocation_context(AllocationContext::current()); + VM_G1CollectForAllocation op(word_size, + gc_count_before, + gc_cause, + false, /* should_initiate_conc_mark */ + g1_policy()->max_pause_time_ms(), + AllocationContext::current()); VMThread::execute(&op); HeapWord* result = op.result();
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -125,7 +125,6 @@ friend class VM_CollectForMetadataAllocation; friend class VM_G1CollectForAllocation; friend class VM_G1CollectFull; - friend class VM_G1IncCollectionPause; friend class VMStructs; friend class MutatorAllocRegion; friend class G1FullCollector; @@ -454,35 +453,20 @@ virtual HeapWord* mem_allocate(size_t word_size, 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 // the mutator alloc region without taking the Heap_lock. This // should only be used for non-humongous allocations. - inline HeapWord* attempt_allocation(size_t word_size, - uint* gc_count_before_ret, - uint* gclocker_retry_count_ret); + inline HeapWord* attempt_allocation(size_t word_size); // Second-level mutator allocation attempt: take the Heap_lock and // retry the allocation attempt, potentially scheduling a GC // pause. This should only be used for non-humongous allocations. HeapWord* attempt_allocation_slow(size_t word_size, - AllocationContext_t context, - uint* gc_count_before_ret, - uint* gclocker_retry_count_ret); + AllocationContext_t context); // Takes the Heap_lock and attempts a humongous allocation. It can // potentially schedule a GC pause. - HeapWord* attempt_allocation_humongous(size_t word_size, - uint* gc_count_before_ret, - uint* gclocker_retry_count_ret); + HeapWord* attempt_allocation_humongous(size_t word_size); // Allocation attempt that should be called during safepoints (e.g., // at the end of a successful GC). expect_null_mutator_alloc_region @@ -1078,6 +1062,11 @@ 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. uint num_regions() const { return _hrm.length(); }
--- a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -33,6 +33,7 @@ #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "memory/iterator.inline.hpp" +#include "oops/access.inline.hpp" #include "runtime/prefetch.inline.hpp" template <class T> @@ -87,13 +88,13 @@ template <class T> 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); } template <class T> 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)) { return; } @@ -124,7 +125,7 @@ template <class T> 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)) { return; }
--- a/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.inline.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/gc/g1/g1SATBCardTableModRefBS.inline.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * 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/g1/g1SATBCardTableModRefBS.hpp" -#include "oops/oop.inline.hpp" template <DecoratorSet decorators, typename T> inline void G1SATBCardTableModRefBS::write_ref_field_pre(T* field) {
--- a/src/hotspot/share/gc/g1/vm_operations_g1.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/gc/g1/vm_operations_g1.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -33,34 +33,21 @@ #include "gc/shared/isGCActiveMark.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() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); GCCauseSetter x(g1h, _gc_cause); g1h->do_full_collection(false /* clear_all_soft_refs */); } -VM_G1IncCollectionPause::VM_G1IncCollectionPause(uint gc_count_before, - size_t word_size, - bool should_initiate_conc_mark, - double target_pause_time_ms, - GCCause::Cause gc_cause) - : VM_G1OperationWithAllocRequest(gc_count_before, word_size, gc_cause), +VM_G1CollectForAllocation::VM_G1CollectForAllocation(size_t word_size, + uint gc_count_before, + GCCause::Cause gc_cause, + bool should_initiate_conc_mark, + double target_pause_time_ms, + 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), _target_pause_time_ms(target_pause_time_ms), _should_retry_gc(false), @@ -71,8 +58,8 @@ _gc_cause = gc_cause; } -bool VM_G1IncCollectionPause::doit_prologue() { - bool res = VM_G1OperationWithAllocRequest::doit_prologue(); +bool VM_G1CollectForAllocation::doit_prologue() { + bool res = VM_CollectForAllocation::doit_prologue(); if (!res) { if (_should_initiate_conc_mark) { // The prologue can fail for a couple of reasons. The first is that another GC @@ -87,7 +74,7 @@ return res; } -void VM_G1IncCollectionPause::doit() { +void VM_G1CollectForAllocation::doit() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); 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"); @@ -95,7 +82,7 @@ if (_word_size > 0) { // An allocation has been requested. So, try to do that first. _result = g1h->attempt_allocation_at_safepoint(_word_size, - allocation_context(), + _allocation_context, false /* expect_null_cur_alloc_region */); if (_result != NULL) { // If we can successfully allocate before we actually do the @@ -144,27 +131,38 @@ } } - _pause_succeeded = - g1h->do_collection_pause_at_safepoint(_target_pause_time_ms); - if (_pause_succeeded && _word_size > 0) { - // An allocation had been requested. - _result = g1h->attempt_allocation_at_safepoint(_word_size, - allocation_context(), - true /* expect_null_cur_alloc_region */); + // Try a partial collection of some kind. + _pause_succeeded = g1h->do_collection_pause_at_safepoint(_target_pause_time_ms); + + if (_pause_succeeded) { + if (_word_size > 0) { + // An allocation had been requested. Do it, eventually trying a stronger + // 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 { assert(_result == NULL, "invariant"); - if (!_pause_succeeded) { - // Another possible reason reason for the pause to not be successful - // is that, again, the GC locker is active (and has become active - // since the prologue was executed). In this case we should retry - // the pause after waiting for the GC locker to become inactive. - _should_retry_gc = true; - } + // The only reason for the pause to not be successful is that, the GC locker is + // active (or has become active since the prologue was executed). In this case + // we should retry the pause after waiting for the GC locker to become inactive. + _should_retry_gc = true; } } -void VM_G1IncCollectionPause::doit_epilogue() { - VM_G1OperationWithAllocRequest::doit_epilogue(); +void VM_G1CollectForAllocation::doit_epilogue() { + VM_CollectForAllocation::doit_epilogue(); // If the pause was initiated by a System.gc() and // +ExplicitGCInvokesConcurrent, we have to wait here for the cycle
--- a/src/hotspot/share/gc/g1/vm_operations_g1.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/gc/g1/vm_operations_g1.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -32,26 +32,8 @@ // VM_operations for the G1 collector. // VM_GC_Operation: // - VM_CGC_Operation +// - VM_G1CollectForAllocation // - 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 { public: @@ -62,41 +44,35 @@ virtual VMOp_Type type() const { return VMOp_G1CollectFull; } virtual void doit(); virtual const char* name() const { - return "full garbage-first collection"; + return "G1 Full collection"; } }; -class VM_G1CollectForAllocation: public VM_G1OperationWithAllocRequest { -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_G1CollectForAllocation: public VM_CollectForAllocation { +private: + bool _pause_succeeded; + AllocationContext_t _allocation_context; -class VM_G1IncCollectionPause: public VM_G1OperationWithAllocRequest { -private: bool _should_initiate_conc_mark; bool _should_retry_gc; double _target_pause_time_ms; uint _old_marking_cycles_completed_before; public: - VM_G1IncCollectionPause(uint gc_count_before, - size_t word_size, - bool should_initiate_conc_mark, - double target_pause_time_ms, - GCCause::Cause gc_cause); - virtual VMOp_Type type() const { return VMOp_G1IncCollectionPause; } + VM_G1CollectForAllocation(size_t word_size, + uint gc_count_before, + GCCause::Cause gc_cause, + bool should_initiate_conc_mark, + double target_pause_time_ms, + AllocationContext_t allocation_context); + virtual VMOp_Type type() const { return VMOp_G1CollectForAllocation; } virtual bool doit_prologue(); virtual void doit(); virtual void doit_epilogue(); 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 pause_succeeded() { return _pause_succeeded; } }; // Concurrent GC stop-the-world operations such as remark and cleanup;
--- a/src/hotspot/share/gc/shared/barrierSet.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/gc/shared/barrierSet.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -147,9 +147,8 @@ // 3) Provide specializations for BarrierSet::GetName and BarrierSet::GetType. template <DecoratorSet decorators, typename BarrierSetT> class AccessBarrier: protected RawAccessBarrier<decorators> { - protected: + private: typedef RawAccessBarrier<decorators> Raw; - typedef typename BarrierSetT::template AccessBarrier<decorators> CRTPAccessBarrier; public: // Primitive heap accesses. These accessors get resolved when
--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -804,7 +804,7 @@ // it is not an interface. The receiver for invokespecial calls within interface // methods must be checked for every call. InstanceKlass* sender = pool->pool_holder(); - sender = sender->is_anonymous() ? sender->host_klass() : sender; + sender = sender->has_host_klass() ? sender->host_klass() : sender; switch (info.call_kind()) { case CallInfo::direct_call: @@ -822,6 +822,7 @@ case CallInfo::itable_call: cp_cache_entry->set_itable_call( bytecode, + info.resolved_klass(), info.resolved_method(), info.itable_index()); break;
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -1433,6 +1433,7 @@ Deoptimization::reassign_fields(fst.current(), fst.register_map(), scope->objects(), realloc_failures, false); GrowableArray<ScopeValue*>* local_values = scope->locals(); + assert(local_values != NULL, "NULL locals"); typeArrayOop array_oop = oopFactory::new_boolArray(local_values->length(), CHECK_NULL); typeArrayHandle array(THREAD, array_oop); for (int i = 0; i < local_values->length(); i++) { @@ -1660,7 +1661,6 @@ GrowableArray<ScopeValue*>* scopeLocals = cvf->scope()->locals(); StackValueCollection* locals = cvf->locals(); - if (locals != NULL) { for (int i2 = 0; i2 < locals->size(); i2++) { StackValue* var = locals->at(i2); @@ -1671,6 +1671,27 @@ } } } + + 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
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -351,7 +351,7 @@ static type name() { \ assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \ 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); \ return type(result); \ } \ @@ -359,7 +359,7 @@ assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \ assert(klassName::klass() != NULL, "Class not yet loaded: " #klassName); \ 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); \ } #define STATIC_PRIMITIVE_FIELD(klassName, name, jtypename) \ @@ -367,13 +367,13 @@ static jtypename name() { \ assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \ 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); \ } \ static void set_##name(jtypename x) { \ assert(klassName::klass() != NULL && klassName::klass()->is_linked(), "Class not yet linked: " #klassName); \ 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); \ }
--- a/src/hotspot/share/oops/access.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/access.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -342,7 +342,7 @@ template <DecoratorSet expected_mo_decorators> static void verify_primitive_decorators() { 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>(); } @@ -350,7 +350,7 @@ static void verify_oop_decorators() { 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 - OOP_DECORATOR_MASK | MO_DECORATOR_MASK; + OOP_DECORATOR_MASK; verify_decorators<expected_mo_decorators | oop_decorators>(); } @@ -358,8 +358,7 @@ static void verify_heap_oop_decorators() { const DecoratorSet heap_oop_decorators = AS_DECORATOR_MASK | ON_DECORATOR_MASK | OOP_DECORATOR_MASK | (IN_DECORATOR_MASK ^ - (IN_ROOT ^ IN_CONCURRENT_ROOT)) | // no root accesses in the heap - MO_DECORATOR_MASK; + (IN_ROOT | IN_CONCURRENT_ROOT)); // no root accesses in the heap verify_decorators<expected_mo_decorators | heap_oop_decorators>(); }
--- a/src/hotspot/share/oops/access.inline.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/access.inline.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -491,11 +491,12 @@ // not possible. struct PreRuntimeDispatch: AllStatic { template<DecoratorSet decorators> - static bool can_hardwire_raw() { - return !HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value || // primitive access - !HasDecorator<decorators, INTERNAL_CONVERT_COMPRESSED_OOP>::value || // don't care about compressed oops (oop* address) - HasDecorator<decorators, INTERNAL_RT_USE_COMPRESSED_OOPS>::value; // we can infer we use compressed oops (narrowOop* address) - } + struct CanHardwireRaw: public IntegralConstant< + bool, + !HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value || // primitive access + !HasDecorator<decorators, INTERNAL_CONVERT_COMPRESSED_OOP>::value || // don't care about compressed oops (oop* address) + HasDecorator<decorators, INTERNAL_RT_USE_COMPRESSED_OOPS>::value> // we can infer we use compressed oops (narrowOop* address) + {}; static const DecoratorSet convert_compressed_oops = INTERNAL_RT_USE_COMPRESSED_OOPS | INTERNAL_CONVERT_COMPRESSED_OOP; @@ -507,16 +508,21 @@ template <DecoratorSet decorators, typename T> inline static typename EnableIf< - HasDecorator<decorators, AS_RAW>::value>::type + HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value>::type store(void* addr, T value) { typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; - if (can_hardwire_raw<decorators>()) { - if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { - Raw::oop_store(addr, value); - } else { - Raw::store(addr, value); - } - } else if (UseCompressedOops) { + if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { + Raw::oop_store(addr, value); + } else { + Raw::store(addr, value); + } + } + + template <DecoratorSet decorators, typename T> + inline static typename EnableIf< + HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value>::type + store(void* addr, T value) { + if (UseCompressedOops) { const DecoratorSet expanded_decorators = decorators | convert_compressed_oops; PreRuntimeDispatch::store<expanded_decorators>(addr, value); } else { @@ -558,16 +564,21 @@ template <DecoratorSet decorators, typename T> inline static typename EnableIf< - HasDecorator<decorators, AS_RAW>::value, T>::type + HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, T>::type load(void* addr) { typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; - if (can_hardwire_raw<decorators>()) { - if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { - return Raw::template oop_load<T>(addr); - } else { - return Raw::template load<T>(addr); - } - } else if (UseCompressedOops) { + if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { + return Raw::template oop_load<T>(addr); + } else { + return Raw::template load<T>(addr); + } + } + + template <DecoratorSet decorators, typename T> + inline static typename EnableIf< + HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, T>::type + load(void* addr) { + if (UseCompressedOops) { const DecoratorSet expanded_decorators = decorators | convert_compressed_oops; return PreRuntimeDispatch::load<expanded_decorators, T>(addr); } else { @@ -609,16 +620,21 @@ template <DecoratorSet decorators, typename T> inline static typename EnableIf< - HasDecorator<decorators, AS_RAW>::value, T>::type + HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, T>::type atomic_cmpxchg(T new_value, void* addr, T compare_value) { typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; - if (can_hardwire_raw<decorators>()) { - if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { - return Raw::oop_atomic_cmpxchg(new_value, addr, compare_value); - } else { - return Raw::atomic_cmpxchg(new_value, addr, compare_value); - } - } else if (UseCompressedOops) { + if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { + return Raw::oop_atomic_cmpxchg(new_value, addr, compare_value); + } else { + return Raw::atomic_cmpxchg(new_value, addr, compare_value); + } + } + + template <DecoratorSet decorators, typename T> + inline static typename EnableIf< + HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, T>::type + atomic_cmpxchg(T new_value, void* addr, T compare_value) { + if (UseCompressedOops) { const DecoratorSet expanded_decorators = decorators | convert_compressed_oops; return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(new_value, addr, compare_value); } else { @@ -661,16 +677,21 @@ template <DecoratorSet decorators, typename T> inline static typename EnableIf< - HasDecorator<decorators, AS_RAW>::value, T>::type + HasDecorator<decorators, AS_RAW>::value && CanHardwireRaw<decorators>::value, T>::type atomic_xchg(T new_value, void* addr) { typedef RawAccessBarrier<decorators & RAW_DECORATOR_MASK> Raw; - if (can_hardwire_raw<decorators>()) { - if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { - return Raw::oop_atomic_xchg(new_value, addr); - } else { - return Raw::atomic_xchg(new_value, addr); - } - } else if (UseCompressedOops) { + if (HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value) { + return Raw::oop_atomic_xchg(new_value, addr); + } else { + return Raw::atomic_xchg(new_value, addr); + } + } + + template <DecoratorSet decorators, typename T> + inline static typename EnableIf< + HasDecorator<decorators, AS_RAW>::value && !CanHardwireRaw<decorators>::value, T>::type + atomic_xchg(T new_value, void* addr) { + if (UseCompressedOops) { const DecoratorSet expanded_decorators = decorators | convert_compressed_oops; return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr); } else { @@ -798,6 +819,13 @@ } template <DecoratorSet decorators> + inline void store_reduce_types(narrowOop* addr, narrowOop value) { + const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | + INTERNAL_RT_USE_COMPRESSED_OOPS; + PreRuntimeDispatch::store<expanded_decorators>(addr, value); + } + + template <DecoratorSet decorators> inline void store_reduce_types(HeapWord* addr, oop value) { const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP; PreRuntimeDispatch::store<expanded_decorators>(addr, value); @@ -816,7 +844,16 @@ } template <DecoratorSet decorators> - inline oop atomic_cmpxchg_reduce_types(oop new_value, HeapWord* addr, oop compare_value) { + inline narrowOop atomic_cmpxchg_reduce_types(narrowOop new_value, narrowOop* addr, narrowOop compare_value) { + const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | + INTERNAL_RT_USE_COMPRESSED_OOPS; + return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(new_value, addr, compare_value); + } + + template <DecoratorSet decorators> + inline oop atomic_cmpxchg_reduce_types(oop new_value, + HeapWord* addr, + oop compare_value) { const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP; return PreRuntimeDispatch::atomic_cmpxchg<expanded_decorators>(new_value, addr, compare_value); } @@ -835,6 +872,13 @@ } template <DecoratorSet decorators> + inline narrowOop atomic_xchg_reduce_types(narrowOop new_value, narrowOop* addr) { + const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | + INTERNAL_RT_USE_COMPRESSED_OOPS; + return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr); + } + + template <DecoratorSet decorators> inline oop atomic_xchg_reduce_types(oop new_value, HeapWord* addr) { const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP; return PreRuntimeDispatch::atomic_xchg<expanded_decorators>(new_value, addr); @@ -846,9 +890,10 @@ } template <DecoratorSet decorators, typename T> - inline oop load_reduce_types(narrowOop* addr) { - const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | INTERNAL_RT_USE_COMPRESSED_OOPS; - return PreRuntimeDispatch::load<expanded_decorators, oop>(addr); + inline typename OopOrNarrowOop<T>::type load_reduce_types(narrowOop* addr) { + const DecoratorSet expanded_decorators = decorators | INTERNAL_CONVERT_COMPRESSED_OOP | + INTERNAL_RT_USE_COMPRESSED_OOPS; + return PreRuntimeDispatch::load<expanded_decorators, typename OopOrNarrowOop<T>::type>(addr); } template <DecoratorSet decorators, typename T>
--- a/src/hotspot/share/oops/accessBackend.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/accessBackend.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "metaprogramming/conditional.hpp" #include "metaprogramming/enableIf.hpp" #include "metaprogramming/integralConstant.hpp" +#include "metaprogramming/isSame.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" @@ -54,11 +55,11 @@ BARRIER_CLONE }; - template <DecoratorSet decorators> + template <DecoratorSet decorators, typename T> struct MustConvertCompressedOop: public IntegralConstant<bool, HasDecorator<decorators, INTERNAL_VALUE_IS_OOP>::value && - HasDecorator<decorators, INTERNAL_CONVERT_COMPRESSED_OOP>::value && - HasDecorator<decorators, INTERNAL_RT_USE_COMPRESSED_OOPS>::value> {}; + IsSame<typename HeapOopType<decorators>::type, narrowOop>::value && + IsSame<T, oop>::value> {}; // This metafunction returns an appropriate oop type if the value is oop-like // and otherwise returns the same type T. @@ -172,13 +173,13 @@ // Only encode if INTERNAL_VALUE_IS_OOP template <DecoratorSet idecorators, typename T> static inline typename EnableIf< - AccessInternal::MustConvertCompressedOop<idecorators>::value, + AccessInternal::MustConvertCompressedOop<idecorators, T>::value, typename HeapOopType<idecorators>::type>::type encode_internal(T value); template <DecoratorSet idecorators, typename T> static inline typename EnableIf< - !AccessInternal::MustConvertCompressedOop<idecorators>::value, T>::type + !AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type encode_internal(T value) { return value; } @@ -192,12 +193,12 @@ // Only decode if INTERNAL_VALUE_IS_OOP template <DecoratorSet idecorators, typename T> static inline typename EnableIf< - AccessInternal::MustConvertCompressedOop<idecorators>::value, T>::type + AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type decode_internal(typename HeapOopType<idecorators>::type value); template <DecoratorSet idecorators, typename T> static inline typename EnableIf< - !AccessInternal::MustConvertCompressedOop<idecorators>::value, T>::type + !AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type decode_internal(T value) { return value; }
--- a/src/hotspot/share/oops/accessBackend.inline.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/accessBackend.inline.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ template <DecoratorSet decorators> template <DecoratorSet idecorators, typename T> inline typename EnableIf< - AccessInternal::MustConvertCompressedOop<idecorators>::value, T>::type + AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type RawAccessBarrier<decorators>::decode_internal(typename HeapOopType<idecorators>::type value) { if (HasDecorator<decorators, OOP_NOT_NULL>::value) { return oopDesc::decode_heap_oop_not_null(value); @@ -44,7 +44,7 @@ template <DecoratorSet decorators> template <DecoratorSet idecorators, typename T> inline typename EnableIf< - AccessInternal::MustConvertCompressedOop<idecorators>::value, + AccessInternal::MustConvertCompressedOop<idecorators, T>::value, typename HeapOopType<idecorators>::type>::type RawAccessBarrier<decorators>::encode_internal(T value) { if (HasDecorator<decorators, OOP_NOT_NULL>::value) {
--- a/src/hotspot/share/oops/compiledICHolder.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/compiledICHolder.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -32,8 +32,8 @@ volatile int CompiledICHolder::_live_not_claimed_count; -CompiledICHolder::CompiledICHolder(Method* method, Klass* klass) - : _holder_method(method), _holder_klass(klass) { +CompiledICHolder::CompiledICHolder(Metadata* metadata, Klass* klass) + : _holder_metadata(metadata), _holder_klass(klass) { #ifdef ASSERT Atomic::inc(&_live_count); Atomic::inc(&_live_not_claimed_count); @@ -47,12 +47,28 @@ } #endif // ASSERT +bool CompiledICHolder::is_loader_alive(BoolObjectClosure* is_alive) { + if (_holder_metadata->is_method()) { + if (!((Method*)_holder_metadata)->method_holder()->is_loader_alive(is_alive)) { + return false; + } + } else if (_holder_metadata->is_klass()) { + if (!((Klass*)_holder_metadata)->is_loader_alive(is_alive)) { + return false; + } + } + if (!_holder_klass->is_loader_alive(is_alive)) { + return false; + } + return true; +} + // Printing void CompiledICHolder::print_on(outputStream* st) const { st->print("%s", internal_name()); - st->print(" - method: "); holder_method()->print_value_on(st); st->cr(); - st->print(" - klass: "); holder_klass()->print_value_on(st); st->cr(); + st->print(" - metadata: "); holder_metadata()->print_value_on(st); st->cr(); + st->print(" - klass: "); holder_klass()->print_value_on(st); st->cr(); } void CompiledICHolder::print_value_on(outputStream* st) const { @@ -63,7 +79,7 @@ // Verification void CompiledICHolder::verify_on(outputStream* st) { - guarantee(holder_method()->is_method(), "should be method"); + guarantee(holder_metadata()->is_method() || holder_metadata()->is_klass(), "should be method or klass"); guarantee(holder_klass()->is_klass(), "should be klass"); }
--- a/src/hotspot/share/oops/compiledICHolder.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/compiledICHolder.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -29,8 +29,9 @@ #include "utilities/macros.hpp" // A CompiledICHolder* is a helper object for the inline cache implementation. -// It holds an intermediate value (method+klass pair) used when converting from -// compiled to an interpreted call. +// It holds: +// (1) (method+klass pair) when converting from compiled to an interpreted call +// (2) (klass+klass pair) when calling itable stub from megamorphic compiled call // // These are always allocated in the C heap and are freed during a // safepoint by the ICBuffer logic. It's unsafe to free them earlier @@ -45,32 +46,33 @@ static volatile int _live_not_claimed_count; // allocated but not yet in use so not // reachable by iterating over nmethods - Method* _holder_method; + Metadata* _holder_metadata; Klass* _holder_klass; // to avoid name conflict with oopDesc::_klass CompiledICHolder* _next; public: // Constructor - CompiledICHolder(Method* method, Klass* klass); + CompiledICHolder(Metadata* metadata, Klass* klass); ~CompiledICHolder() NOT_DEBUG_RETURN; static int live_count() { return _live_count; } static int live_not_claimed_count() { return _live_not_claimed_count; } // accessors - Method* holder_method() const { return _holder_method; } Klass* holder_klass() const { return _holder_klass; } + Metadata* holder_metadata() const { return _holder_metadata; } - void set_holder_method(Method* m) { _holder_method = m; } - void set_holder_klass(Klass* k) { _holder_klass = k; } + void set_holder_metadata(Metadata* m) { _holder_metadata = m; } + void set_holder_klass(Klass* k) { _holder_klass = k; } - // interpreter support (offsets in bytes) - static int holder_method_offset() { return offset_of(CompiledICHolder, _holder_method); } + static int holder_metadata_offset() { return offset_of(CompiledICHolder, _holder_metadata); } static int holder_klass_offset() { return offset_of(CompiledICHolder, _holder_klass); } CompiledICHolder* next() { return _next; } void set_next(CompiledICHolder* n) { _next = n; } + bool is_loader_alive(BoolObjectClosure* is_alive); + // Verify void verify_on(outputStream* st);
--- a/src/hotspot/share/oops/constantPool.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/constantPool.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_OOPS_CONSTANTPOOLOOP_HPP #define SHARE_VM_OOPS_CONSTANTPOOLOOP_HPP +#include "memory/allocation.inline.hpp" #include "oops/arrayOop.hpp" #include "oops/cpCache.hpp" #include "oops/objArrayOop.hpp" @@ -1021,7 +1022,7 @@ delete(cur); } } - delete _buckets; + FREE_C_HEAP_ARRAY(SymbolHashMapBucket, _buckets); } }; // End SymbolHashMap class
--- a/src/hotspot/share/oops/cpCache.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/cpCache.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -278,14 +278,16 @@ set_direct_or_vtable_call(invoke_code, method, index, false); } -void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, const methodHandle& method, int index) { +void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, + Klass* referenced_klass, + const methodHandle& method, int index) { assert(method->method_holder()->verify_itable_index(index), ""); assert(invoke_code == Bytecodes::_invokeinterface, ""); InstanceKlass* interf = method->method_holder(); assert(interf->is_interface(), "must be an interface"); assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here"); - set_f1(interf); - set_f2(index); + set_f1(referenced_klass); + set_f2((intx)method()); set_method_flags(as_TosState(method->result_type()), 0, // no option bits method()->size_of_parameters()); @@ -514,10 +516,23 @@ #if INCLUDE_JVMTI + +void log_adjust(const char* entry_type, Method* old_method, Method* new_method, bool* trace_name_printed) { + if (log_is_enabled(Info, redefine, class, update)) { + ResourceMark rm; + if (!(*trace_name_printed)) { + log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); + *trace_name_printed = true; + } + log_debug(redefine, class, update, constantpool) + ("cpc %s entry update: %s(%s)", entry_type, new_method->name()->as_C_string(), new_method->signature()->as_C_string()); + } +} + // RedefineClasses() API support: // If this ConstantPoolCacheEntry refers to old_method then update it // to refer to new_method. -bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method, +void ConstantPoolCacheEntry::adjust_method_entry(Method* old_method, Method* new_method, bool * trace_name_printed) { if (is_vfinal()) { @@ -526,63 +541,35 @@ // match old_method so need an update // NOTE: can't use set_f2_as_vfinal_method as it asserts on different values _f2 = (intptr_t)new_method; - if (log_is_enabled(Info, redefine, class, update)) { - ResourceMark rm; - if (!(*trace_name_printed)) { - log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); - *trace_name_printed = true; - } - log_debug(redefine, class, update, constantpool) - ("cpc vf-entry update: %s(%s)", new_method->name()->as_C_string(), new_method->signature()->as_C_string()); - } - return true; + log_adjust("vfinal", old_method, new_method, trace_name_printed); } - - // f1() is not used with virtual entries so bail out - return false; + return; } - if (_f1 == NULL) { - // NULL f1() means this is a virtual entry so bail out - // We are assuming that the vtable index does not need change. - return false; + assert (_f1 != NULL, "should not call with uninteresting entry"); + + if (!(_f1->is_method())) { + // _f1 is a Klass* for an interface, _f2 is the method + if (f2_as_interface_method() == old_method) { + _f2 = (intptr_t)new_method; + log_adjust("interface", old_method, new_method, trace_name_printed); + } + } else if (_f1 == old_method) { + _f1 = new_method; + log_adjust("special, static or dynamic", old_method, new_method, trace_name_printed); } - - if (_f1 == old_method) { - _f1 = new_method; - if (log_is_enabled(Info, redefine, class, update)) { - ResourceMark rm; - if (!(*trace_name_printed)) { - log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); - *trace_name_printed = true; - } - log_debug(redefine, class, update, constantpool) - ("cpc entry update: %s(%s)", new_method->name()->as_C_string(), new_method->signature()->as_C_string()); - } - return true; - } - - return false; } // a constant pool cache entry should never contain old or obsolete methods bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() { - if (is_vfinal()) { - // virtual and final so _f2 contains method ptr instead of vtable index - Metadata* f2 = (Metadata*)_f2; - // Return false if _f2 refers to an old or an obsolete method. - // _f2 == NULL || !_f2->is_method() are just as unexpected here. - return (f2 != NULL NOT_PRODUCT(&& f2->is_valid()) && f2->is_method() && - !((Method*)f2)->is_old() && !((Method*)f2)->is_obsolete()); - } else if (_f1 == NULL || - (NOT_PRODUCT(_f1->is_valid() &&) !_f1->is_method())) { - // _f1 == NULL || !_f1->is_method() are OK here + Method* m = get_interesting_method_entry(NULL); + // return false if m refers to a non-deleted old or obsolete method + if (m != NULL) { + assert(m->is_valid() && m->is_method(), "m is a valid method"); + return !m->is_old() && !m->is_obsolete(); // old is always set for old and obsolete + } else { return true; } - // return false if _f1 refers to a non-deleted old or obsolete method - return (NOT_PRODUCT(_f1->is_valid() &&) _f1->is_method() && - (f1_as_method()->is_deleted() || - (!f1_as_method()->is_old() && !f1_as_method()->is_obsolete()))); } Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) { @@ -599,10 +586,11 @@ return NULL; } else { if (!(_f1->is_method())) { - // _f1 can also contain a Klass* for an interface - return NULL; + // _f1 is a Klass* for an interface + m = f2_as_interface_method(); + } else { + m = f1_as_method(); } - m = f1_as_method(); } assert(m != NULL && m->is_method(), "sanity check"); if (m == NULL || !m->is_method() || (k != NULL && m->method_holder() != k)) {
--- a/src/hotspot/share/oops/cpCache.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/cpCache.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -249,6 +249,7 @@ void set_itable_call( Bytecodes::Code invoke_code, // the bytecode used; must be invokeinterface + Klass* referenced_klass, // the referenced klass in the InterfaceMethodref const methodHandle& method, // the resolved interface method int itable_index // index into itable for the method ); @@ -352,6 +353,7 @@ bool is_f1_null() const { Metadata* f1 = f1_ord(); return f1 == NULL; } // classifies a CPC entry as unbound int f2_as_index() const { assert(!is_vfinal(), ""); return (int) _f2; } Method* f2_as_vfinal_method() const { assert(is_vfinal(), ""); return (Method*)_f2; } + Method* f2_as_interface_method() const { assert(bytecode_1() == Bytecodes::_invokeinterface, ""); return (Method*)_f2; } intx flags_ord() const { return (intx)OrderAccess::load_acquire(&_flags); } int field_index() const { assert(is_field_entry(), ""); return (_flags & field_index_mask); } int parameter_size() const { assert(is_method_entry(), ""); return (_flags & parameter_size_mask); } @@ -387,7 +389,7 @@ // trace_name_printed is set to true if the current call has // printed the klass name so that other routines in the adjust_* // group don't print the klass name. - bool adjust_method_entry(Method* old_method, Method* new_method, + void adjust_method_entry(Method* old_method, Method* new_method, bool* trace_name_printed); bool check_no_old_or_obsolete_entries(); Method* get_interesting_method_entry(Klass* k);
--- a/src/hotspot/share/oops/instanceKlass.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/instanceKlass.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -2265,7 +2265,8 @@ } address InstanceKlass::static_field_addr(int offset) { - return (address)(offset + InstanceMirrorKlass::offset_of_static_fields() + cast_from_oop<intptr_t>(java_mirror())); + assert(offset >= InstanceMirrorKlass::offset_of_static_fields(), "has already been adjusted"); + return (address)(offset + cast_from_oop<intptr_t>(java_mirror())); } @@ -3421,6 +3422,15 @@ } } +oop InstanceKlass::klass_holder_phantom() { + oop* addr; + if (is_anonymous()) { + addr = _java_mirror.ptr_raw(); + } else { + addr = &class_loader_data()->_class_loader; + } + return RootAccess<IN_CONCURRENT_ROOT | ON_PHANTOM_OOP_REF>::oop_load(addr); +} #ifdef ASSERT void InstanceKlass::set_init_state(ClassState state) {
--- a/src/hotspot/share/oops/instanceKlass.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/instanceKlass.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -609,9 +609,11 @@ InstanceKlass* host_klass() const { InstanceKlass** hk = adr_host_klass(); if (hk == NULL) { + assert(!is_anonymous(), "Anonymous classes have host klasses"); return NULL; } else { assert(*hk != NULL, "host klass should always be set if the address is not null"); + assert(is_anonymous(), "Only anonymous classes have host klasses"); return *hk; } } @@ -623,6 +625,9 @@ *addr = host; } } + bool has_host_klass() const { + return adr_host_klass() != NULL; + } bool is_anonymous() const { return (_misc_flags & _misc_is_anonymous) != 0; } @@ -640,6 +645,11 @@ return is_anonymous() ? java_mirror() : class_loader(); } + // Load the klass_holder as a phantom. This is useful when a weak Klass + // pointer has been "peeked" and then must be kept alive before it may + // be used safely. + oop klass_holder_phantom(); + bool is_contended() const { return (_misc_flags & _misc_is_contended) != 0; }
--- a/src/hotspot/share/oops/klassVtable.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/klassVtable.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1200,7 +1200,6 @@ Array<Method*>* methods = InstanceKlass::cast(interf)->methods(); int nof_methods = methods->length(); HandleMark hm; - assert(nof_methods > 0, "at least one method must exist for interface to be in vtable"); Handle interface_loader (THREAD, InstanceKlass::cast(interf)->class_loader()); int ime_count = method_count_for_interface(interf); @@ -1369,8 +1368,10 @@ } } - // Only count interfaces with at least one method - if (method_count > 0) { + // Visit all interfaces which either have any methods or can participate in receiver type check. + // We do not bother to count methods in transitive interfaces, although that would allow us to skip + // this step in the rare case of a zero-method interface extending another zero-method interface. + if (method_count > 0 || InstanceKlass::cast(intf)->transitive_interfaces()->length() > 0) { blk->doit(intf, method_count); } }
--- a/src/hotspot/share/oops/method.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/method.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -698,6 +698,7 @@ static ByteSize from_interpreted_offset() { return byte_offset_of(Method, _from_interpreted_entry ); } static ByteSize interpreter_entry_offset() { return byte_offset_of(Method, _i2i_entry ); } static ByteSize signature_handler_offset() { return in_ByteSize(sizeof(Method) + wordSize); } + static ByteSize itable_index_offset() { return byte_offset_of(Method, _vtable_index ); } // for code generation static int method_data_offset_in_bytes() { return offset_of(Method, _method_data); }
--- a/src/hotspot/share/oops/oop.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/oop.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -28,6 +28,7 @@ #include "gc/shared/specialized_oop_closures.hpp" #include "memory/iterator.hpp" #include "memory/memRegion.hpp" +#include "oops/access.hpp" #include "oops/metadata.hpp" #include "utilities/macros.hpp" @@ -178,6 +179,8 @@ static inline void encode_store_heap_oop(oop* p, oop v); // Access to fields in a instanceOop through these methods. + template <DecoratorSet decorator> + oop obj_field_access(int offset) const; oop obj_field(int offset) const; void obj_field_put(int offset, oop value); void obj_field_put_raw(int offset, oop value);
--- a/src/hotspot/share/oops/oop.inline.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/oops/oop.inline.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -326,7 +326,10 @@ *p = encode_heap_oop(v); } +template <DecoratorSet decorators> +inline oop oopDesc::obj_field_access(int offset) const { return HeapAccess<decorators>::oop_load_at(as_oop(), offset); } inline oop oopDesc::obj_field(int offset) const { return HeapAccess<>::oop_load_at(as_oop(), offset); } + inline void oopDesc::obj_field_put(int offset, oop value) { HeapAccess<>::oop_store_at(as_oop(), offset, value); } inline jbyte oopDesc::byte_field(int offset) const { return HeapAccess<>::load_at(as_oop(), offset); }
--- a/src/hotspot/share/opto/callnode.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/callnode.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, 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. * * This code is free software; you can redistribute it and/or modify it @@ -772,7 +772,7 @@ ciKlass* boxing_klass = t_oop->klass(); if (is_CallStaticJava() && as_CallStaticJava()->is_boxing_method()) { // Skip unrelated boxing methods. - Node* proj = proj_out(TypeFunc::Parms); + Node* proj = proj_out_or_null(TypeFunc::Parms); if ((proj == NULL) || (phase->type(proj)->is_instptr()->klass() != boxing_klass)) { return false; } @@ -784,7 +784,7 @@ } // May modify (by reflection) if an boxing object is passed // as argument or returned. - Node* proj = returns_pointer() ? proj_out(TypeFunc::Parms) : NULL; + Node* proj = returns_pointer() ? proj_out_or_null(TypeFunc::Parms) : NULL; if (proj != NULL) { const TypeInstPtr* inst_t = phase->type(proj)->isa_instptr(); if ((inst_t != NULL) && (!inst_t->klass_is_exact() || @@ -824,7 +824,7 @@ Node *CallNode::result_cast() { Node *cast = NULL; - Node *p = proj_out(TypeFunc::Parms); + Node *p = proj_out_or_null(TypeFunc::Parms); if (p == NULL) return NULL; @@ -1378,13 +1378,13 @@ PhaseIterGVN *igvn = phase->is_IterGVN(); // Unreachable fall through path (negative array length), // the allocation can only throw so disconnect it. - Node* proj = proj_out(TypeFunc::Control); + Node* proj = proj_out_or_null(TypeFunc::Control); Node* catchproj = NULL; if (proj != NULL) { for (DUIterator_Fast imax, i = proj->fast_outs(imax); i < imax; i++) { Node *cn = proj->fast_out(i); if (cn->is_Catch()) { - catchproj = cn->as_Multi()->proj_out(CatchProjNode::fall_through_index); + catchproj = cn->as_Multi()->proj_out_or_null(CatchProjNode::fall_through_index); break; } } @@ -1442,7 +1442,7 @@ // Create a cast which is control dependent on the initialization to // propagate the fact that the array length must be positive. length = new CastIINode(length, narrow_length_type); - length->set_req(0, initialization()->proj_out(0)); + length->set_req(0, initialization()->proj_out_or_null(0)); } }
--- a/src/hotspot/share/opto/cfgnode.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/cfgnode.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -2373,7 +2373,7 @@ if (can_reshape && !in(0)->is_Loop()) { // Dead code elimination can sometimes delete this projection so // if it's not there, there's nothing to do. - Node* fallthru = proj_out(0); + Node* fallthru = proj_out_or_null(0); if (fallthru != NULL) { phase->is_IterGVN()->replace_node(fallthru, in(0)); }
--- a/src/hotspot/share/opto/divnode.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/divnode.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, 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. * * This code is free software; you can redistribute it and/or modify it @@ -154,8 +154,8 @@ virtual bool is_CFG() const { return false; } virtual uint ideal_reg() const { return NotAMachineReg; } - ProjNode* div_proj() { return proj_out(div_proj_num); } - ProjNode* mod_proj() { return proj_out(mod_proj_num); } + ProjNode* div_proj() { return proj_out_or_null(div_proj_num); } + ProjNode* mod_proj() { return proj_out_or_null(mod_proj_num); } }; //------------------------------DivModINode---------------------------------------
--- a/src/hotspot/share/opto/escape.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/escape.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -366,7 +366,7 @@ delayed_worklist->push(n); // Check if a call returns an object. if ((n->as_Call()->returns_pointer() && - n->as_Call()->proj_out(TypeFunc::Parms) != NULL) || + n->as_Call()->proj_out_or_null(TypeFunc::Parms) != NULL) || (n->is_CallStaticJava() && n->as_CallStaticJava()->is_boxing_method())) { add_call_node(n->as_Call()); @@ -2674,7 +2674,7 @@ PhaseGVN* igvn = _igvn; const TypeOopPtr *toop = C->get_adr_type(alias_idx)->isa_oopptr(); bool is_instance = (toop != NULL) && toop->is_known_instance(); - Node *start_mem = C->start()->proj_out(TypeFunc::Memory); + Node *start_mem = C->start()->proj_out_or_null(TypeFunc::Memory); Node *prev = NULL; Node *result = orig_mem; while (prev != result) { @@ -3028,7 +3028,7 @@ // An allocation may have an Initialize which has raw stores. Scan // the users of the raw allocation result and push AddP users // on alloc_worklist. - Node *raw_result = alloc->proj_out(TypeFunc::Parms); + Node *raw_result = alloc->proj_out_or_null(TypeFunc::Parms); assert (raw_result != NULL, "must have an allocation result"); for (DUIterator_Fast imax, i = raw_result->fast_outs(imax); i < imax; i++) { Node *use = raw_result->fast_out(i); @@ -3219,7 +3219,7 @@ // we don't need to do anything, but the users must be pushed } else if (n->is_MemBar()) { // Initialize, MemBar nodes // we don't need to do anything, but the users must be pushed - n = n->as_MemBar()->proj_out(TypeFunc::Memory); + n = n->as_MemBar()->proj_out_or_null(TypeFunc::Memory); if (n == NULL) continue; } else if (n->Opcode() == Op_StrCompressedCopy ||
--- a/src/hotspot/share/opto/graphKit.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/graphKit.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -3754,7 +3754,7 @@ // Trace Allocate -> Proj[Parm] -> Initialize InitializeNode* AllocateNode::initialization() { - ProjNode* rawoop = proj_out(AllocateNode::RawAddress); + ProjNode* rawoop = proj_out_or_null(AllocateNode::RawAddress); if (rawoop == NULL) return NULL; for (DUIterator_Fast imax, i = rawoop->fast_outs(imax); i < imax; i++) { Node* init = rawoop->fast_out(i);
--- a/src/hotspot/share/opto/ifnode.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/ifnode.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -505,7 +505,7 @@ // Flip 1: If (Bool[<] CmpU(l, LoadRange)) ... // Flip 2: If (Bool[<=] CmpU(LoadRange, l)) ... - ProjNode* iftrap = proj_out(flip_test == 2 ? true : false); + ProjNode* iftrap = proj_out_or_null(flip_test == 2 ? true : false); return iftrap; } @@ -1195,14 +1195,17 @@ // Check that the If that is in between the 2 integer comparisons has // no side effect bool IfNode::is_side_effect_free_test(ProjNode* proj, PhaseIterGVN* igvn) { - if (proj != NULL && - proj->is_uncommon_trap_if_pattern(Deoptimization::Reason_none) && - proj->outcnt() <= 2) { + if (proj == NULL) { + return false; + } + CallStaticJavaNode* unc = proj->is_uncommon_trap_if_pattern(Deoptimization::Reason_none); + if (unc != NULL && proj->outcnt() <= 2) { if (proj->outcnt() == 1 || // Allow simple null check from LoadRange (is_cmp_with_loadrange(proj) && is_null_check(proj, igvn))) { CallStaticJavaNode* unc = proj->is_uncommon_trap_if_pattern(Deoptimization::Reason_none); CallStaticJavaNode* dom_unc = proj->in(0)->in(0)->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none); + assert(dom_unc != NULL, "is_uncommon_trap_if_pattern returned NULL"); // reroute_side_effect_free_unc changes the state of this // uncommon trap to restart execution at the previous @@ -1471,7 +1474,7 @@ // be skipped. For example, range check predicate has two checks // for lower and upper bounds. ProjNode* unc_proj = proj_out(1 - prev_dom->as_Proj()->_con)->as_Proj(); - if ((unc_proj != NULL) && (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) != NULL)) { + if (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) != NULL) { prev_dom = idom; }
--- a/src/hotspot/share/opto/library_call.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/library_call.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -1495,7 +1495,7 @@ // escape analysis can go from the MemBarStoreStoreNode to the // AllocateNode and eliminate the MemBarStoreStoreNode if possible // based on the escape status of the AllocateNode. - insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress)); + insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out_or_null(AllocateNode::RawAddress)); } if (compress) { set_result(_gvn.transform(count)); @@ -1589,7 +1589,7 @@ // escape analysis can go from the MemBarStoreStoreNode to the // AllocateNode and eliminate the MemBarStoreStoreNode if possible // based on the escape status of the AllocateNode. - insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress)); + insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out_or_null(AllocateNode::RawAddress)); } else { insert_mem_bar(Op_MemBarCPUOrder); } @@ -1675,7 +1675,7 @@ // escape analysis can go from the MemBarStoreStoreNode to the // AllocateNode and eliminate the MemBarStoreStoreNode if possible // based on the escape status of the AllocateNode. - insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress)); + insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out_or_null(AllocateNode::RawAddress)); } else { insert_mem_bar(Op_MemBarCPUOrder); } @@ -4722,7 +4722,7 @@ // escape analysis can go from the MemBarStoreStoreNode to the // AllocateNode and eliminate the MemBarStoreStoreNode if possible // based on the escape status of the AllocateNode. - insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress)); + insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out_or_null(AllocateNode::RawAddress)); } else { insert_mem_bar(Op_MemBarCPUOrder); } @@ -5031,7 +5031,7 @@ Node *mem = reset_memory(); set_all_memory(mem); alloc->set_req(TypeFunc::Memory, mem); - set_control(init->proj_out(TypeFunc::Control)); + set_control(init->proj_out_or_null(TypeFunc::Control)); set_i_o(callprojs.fallthrough_ioproj); // Update memory as done in GraphKit::set_output_for_allocation() @@ -5042,8 +5042,8 @@ } const TypePtr* telemref = ary_type->add_offset(Type::OffsetBot); int elemidx = C->get_alias_index(telemref); - set_memory(init->proj_out(TypeFunc::Memory), Compile::AliasIdxRaw); - set_memory(init->proj_out(TypeFunc::Memory), elemidx); + set_memory(init->proj_out_or_null(TypeFunc::Memory), Compile::AliasIdxRaw); + set_memory(init->proj_out_or_null(TypeFunc::Memory), elemidx); Node* allocx = _gvn.transform(alloc); assert(allocx == alloc, "where has the allocation gone?"); @@ -5360,7 +5360,7 @@ // to finish initializing the allocated object. if ((ctl->is_IfFalse() || ctl->is_IfTrue()) && ctl->in(0)->is_If()) { IfNode* iff = ctl->in(0)->as_If(); - Node* not_ctl = iff->proj_out(1 - ctl->as_Proj()->_con); + Node* not_ctl = iff->proj_out_or_null(1 - ctl->as_Proj()->_con); assert(not_ctl != NULL && not_ctl != ctl, "found alternate"); if (slow_region != NULL && slow_region->find_edge(not_ctl) >= 1) { ctl = iff->in(0); // This test feeds the known slow_region.
--- a/src/hotspot/share/opto/loopTransform.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/loopTransform.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -1017,7 +1017,6 @@ CountedLoopNode *main_head = loop->_head->as_CountedLoop(); assert( main_head->is_normal_loop(), "" ); CountedLoopEndNode *main_end = main_head->loopexit(); - guarantee(main_end != NULL, "no loop exit node"); assert( main_end->outcnt() == 2, "1 true, 1 false path only" ); Node *pre_header= main_head->in(LoopNode::EntryControl); @@ -1243,7 +1242,6 @@ // Find common pieces of the loop being guarded with pre & post loops CountedLoopNode *main_head = loop->_head->as_CountedLoop(); CountedLoopEndNode *main_end = main_head->loopexit(); - guarantee(main_end != NULL, "no loop exit node"); // diagnostic to show loop end is not properly formed assert(main_end->outcnt() == 2, "1 true, 1 false path only"); @@ -1293,7 +1291,6 @@ // Find common pieces of the loop being guarded with pre & post loops CountedLoopNode *main_head = loop->_head->as_CountedLoop(); CountedLoopEndNode *main_end = main_head->loopexit(); - guarantee(main_end != NULL, "no loop exit node"); // diagnostic to show loop end is not properly formed assert(main_end->outcnt() == 2, "1 true, 1 false path only"); @@ -1427,7 +1424,6 @@ assert(LoopUnrollLimit, ""); CountedLoopNode *loop_head = loop->_head->as_CountedLoop(); CountedLoopEndNode *loop_end = loop_head->loopexit(); - assert(loop_end, ""); #ifndef PRODUCT if (PrintOpto && VerifyLoopOptimizations) { tty->print("Unrolling "); @@ -2972,7 +2968,7 @@ } store = n; store_value = value; - } else if (n->is_If() && n != head->loopexit()) { + } else if (n->is_If() && n != head->loopexit_or_null()) { msg = "extra control flow"; msg_node = n; } @@ -3114,7 +3110,6 @@ ok.set(store->in(MemNode::Memory)->_idx); CountedLoopEndNode* loop_exit = head->loopexit(); - guarantee(loop_exit != NULL, "no loop exit node"); // Loop structure is ok ok.set(head->_idx); @@ -3204,7 +3199,7 @@ return false; } - Node* exit = head->loopexit()->proj_out(0); + Node* exit = head->loopexit()->proj_out_or_null(0); if (exit == NULL) { return false; } @@ -3280,8 +3275,8 @@ call->init_req(TypeFunc::Control, head->init_control()); call->init_req(TypeFunc::I_O, C->top()); // Does no I/O. call->init_req(TypeFunc::Memory, mem_phi->in(LoopNode::EntryControl)); - call->init_req(TypeFunc::ReturnAdr, C->start()->proj_out(TypeFunc::ReturnAdr)); - call->init_req(TypeFunc::FramePtr, C->start()->proj_out(TypeFunc::FramePtr)); + call->init_req(TypeFunc::ReturnAdr, C->start()->proj_out_or_null(TypeFunc::ReturnAdr)); + call->init_req(TypeFunc::FramePtr, C->start()->proj_out_or_null(TypeFunc::FramePtr)); _igvn.register_new_node_with_optimizer(call); result_ctrl = new ProjNode(call,TypeFunc::Control); _igvn.register_new_node_with_optimizer(result_ctrl);
--- a/src/hotspot/share/opto/loopnode.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/loopnode.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -68,11 +68,11 @@ bool LoopNode::is_valid_counted_loop() const { if (is_CountedLoop()) { CountedLoopNode* l = as_CountedLoop(); - CountedLoopEndNode* le = l->loopexit(); + CountedLoopEndNode* le = l->loopexit_or_null(); if (le != NULL && - le->proj_out(1 /* true */) == l->in(LoopNode::LoopBackControl)) { + le->proj_out_or_null(1 /* true */) == l->in(LoopNode::LoopBackControl)) { Node* phi = l->phi(); - Node* exit = le->proj_out(0 /* false */); + Node* exit = le->proj_out_or_null(0 /* false */); if (exit != NULL && exit->Opcode() == Op_IfFalse && phi != NULL && phi->is_Phi() && phi->in(LoopNode::LoopBackControl) == l->incr() && @@ -793,7 +793,7 @@ #ifdef ASSERT assert(l->is_valid_counted_loop(), "counted loop shape is messed up"); - assert(l == loop->_head && l->phi() == phi && l->loopexit() == lex, "" ); + assert(l == loop->_head && l->phi() == phi && l->loopexit_or_null() == lex, "" ); #endif #ifndef PRODUCT if (TraceLoopOpts) { @@ -917,7 +917,7 @@ } } CountedLoopEndNode* cle = inner_out->in(0)->as_CountedLoopEnd(); - assert(cle == inner->loopexit(), "mismatch"); + assert(cle == inner->loopexit_or_null(), "mismatch"); bool has_skeleton = outer_le->in(1)->bottom_type()->singleton() && outer_le->in(1)->bottom_type()->is_int()->get_con() == 0; if (has_skeleton) { assert(expect_skeleton == 1 || expect_skeleton == -1, "unexpected skeleton node"); @@ -1216,7 +1216,7 @@ if (le == NULL) { return NULL; } - Node* c = le->proj_out(false); + Node* c = le->proj_out_or_null(false); if (c == NULL) { return NULL; }
--- a/src/hotspot/share/opto/loopnode.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/loopnode.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, 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. * * This code is free software; you can redistribute it and/or modify it @@ -215,6 +215,7 @@ Node *init_control() const { return in(EntryControl); } Node *back_control() const { return in(LoopBackControl); } + CountedLoopEndNode *loopexit_or_null() const; CountedLoopEndNode *loopexit() const; Node *init_trip() const; Node *stride() const; @@ -342,7 +343,7 @@ return NULL; } Node *ln = iv_phi->in(0); - if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit() == this) { + if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit_or_null() == this) { return (CountedLoopNode*)ln; } return NULL; @@ -354,7 +355,7 @@ }; -inline CountedLoopEndNode *CountedLoopNode::loopexit() const { +inline CountedLoopEndNode *CountedLoopNode::loopexit_or_null() const { Node *bc = back_control(); if( bc == NULL ) return NULL; Node *le = bc->in(0); @@ -362,13 +363,18 @@ return NULL; return (CountedLoopEndNode*)le; } -inline Node *CountedLoopNode::init_trip() const { return loopexit() ? loopexit()->init_trip() : NULL; } -inline Node *CountedLoopNode::stride() const { return loopexit() ? loopexit()->stride() : NULL; } -inline int CountedLoopNode::stride_con() const { return loopexit() ? loopexit()->stride_con() : 0; } -inline bool CountedLoopNode::stride_is_con() const { return loopexit() && loopexit()->stride_is_con(); } -inline Node *CountedLoopNode::limit() const { return loopexit() ? loopexit()->limit() : NULL; } -inline Node *CountedLoopNode::incr() const { return loopexit() ? loopexit()->incr() : NULL; } -inline Node *CountedLoopNode::phi() const { return loopexit() ? loopexit()->phi() : NULL; } +inline CountedLoopEndNode *CountedLoopNode::loopexit() const { + CountedLoopEndNode* cle = loopexit_or_null(); + assert(cle != NULL, "loopexit is NULL"); + return cle; +} +inline Node *CountedLoopNode::init_trip() const { return loopexit_or_null() ? loopexit()->init_trip() : NULL; } +inline Node *CountedLoopNode::stride() const { return loopexit_or_null() ? loopexit()->stride() : NULL; } +inline int CountedLoopNode::stride_con() const { return loopexit_or_null() ? loopexit()->stride_con() : 0; } +inline bool CountedLoopNode::stride_is_con() const { return loopexit_or_null() && loopexit()->stride_is_con(); } +inline Node *CountedLoopNode::limit() const { return loopexit_or_null() ? loopexit()->limit() : NULL; } +inline Node *CountedLoopNode::incr() const { return loopexit_or_null() ? loopexit()->incr() : NULL; } +inline Node *CountedLoopNode::phi() const { return loopexit_or_null() ? loopexit()->phi() : NULL; } //------------------------------LoopLimitNode----------------------------- // Counted Loop limit node which represents exact final iterator value:
--- a/src/hotspot/share/opto/loopopts.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/loopopts.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -239,7 +239,7 @@ // Make control-dependent data Nodes on the live path (path that will remain // once the dominated IF is removed) become control-dependent on the // dominating projection. - Node* dp = iff->as_If()->proj_out(pop == Op_IfTrue); + Node* dp = iff->as_If()->proj_out_or_null(pop == Op_IfTrue); // Loop predicates may have depending checks which should not // be skipped. For example, range check predicate has two checks @@ -1731,7 +1731,7 @@ Node* sfpt = cl->outer_safepoint(); CountedLoopEndNode* cle = cl->loopexit(); CountedLoopNode* new_cl = old_new[cl->_idx]->as_CountedLoop(); - CountedLoopEndNode* new_cle = new_cl->as_CountedLoop()->loopexit(); + CountedLoopEndNode* new_cle = new_cl->as_CountedLoop()->loopexit_or_null(); Node* cle_out = cle->proj_out(false); Node* new_sfpt = NULL; @@ -1956,7 +1956,7 @@ if (head->is_strip_mined() && mode != IgnoreStripMined) { CountedLoopNode* cl = head->as_CountedLoop(); CountedLoopEndNode* cle = cl->loopexit(); - Node* cle_out = cle->proj_out(false); + Node* cle_out = cle->proj_out_or_null(false); if (use == cle_out) { IfNode* le = cl->outer_loop_end(); use = le->proj_out(false);
--- a/src/hotspot/share/opto/macro.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/macro.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -496,7 +496,7 @@ if (level <= 0) { return NULL; // Give up: phi tree too deep } - Node *start_mem = C->start()->proj_out(TypeFunc::Memory); + Node *start_mem = C->start()->proj_out_or_null(TypeFunc::Memory); Node *alloc_mem = alloc->in(TypeFunc::Memory); uint length = mem->req(); @@ -576,7 +576,7 @@ int alias_idx = C->get_alias_index(adr_t); int offset = adr_t->offset(); - Node *start_mem = C->start()->proj_out(TypeFunc::Memory); + Node *start_mem = C->start()->proj_out_or_null(TypeFunc::Memory); Node *alloc_ctrl = alloc->in(TypeFunc::Control); Node *alloc_mem = alloc->in(TypeFunc::Memory); Arena *a = Thread::current()->resource_area(); @@ -974,8 +974,8 @@ } static void disconnect_projections(MultiNode* n, PhaseIterGVN& igvn) { - Node* ctl_proj = n->proj_out(TypeFunc::Control); - Node* mem_proj = n->proj_out(TypeFunc::Memory); + Node* ctl_proj = n->proj_out_or_null(TypeFunc::Control); + Node* mem_proj = n->proj_out_or_null(TypeFunc::Memory); if (ctl_proj != NULL) { igvn.replace_node(ctl_proj, n->in(0)); } @@ -1086,12 +1086,12 @@ // Eliminate Initialize node. InitializeNode *init = use->as_Initialize(); assert(init->outcnt() <= 2, "only a control and memory projection expected"); - Node *ctrl_proj = init->proj_out(TypeFunc::Control); + Node *ctrl_proj = init->proj_out_or_null(TypeFunc::Control); if (ctrl_proj != NULL) { assert(init->in(TypeFunc::Control) == _fallthroughcatchproj, "allocation control projection"); _igvn.replace_node(ctrl_proj, _fallthroughcatchproj); } - Node *mem_proj = init->proj_out(TypeFunc::Memory); + Node *mem_proj = init->proj_out_or_null(TypeFunc::Memory); if (mem_proj != NULL) { Node *mem = init->in(TypeFunc::Memory); #ifdef ASSERT @@ -1198,7 +1198,7 @@ bool PhaseMacroExpand::eliminate_boxing_node(CallStaticJavaNode *boxing) { // EA should remove all uses of non-escaping boxing node. - if (!C->eliminate_boxing() || boxing->proj_out(TypeFunc::Parms) != NULL) { + if (!C->eliminate_boxing() || boxing->proj_out_or_null(TypeFunc::Parms) != NULL) { return false; } @@ -1580,8 +1580,8 @@ // before the InitializeNode happen before the storestore // barrier. - Node* init_ctrl = init->proj_out(TypeFunc::Control); - Node* init_mem = init->proj_out(TypeFunc::Memory); + Node* init_ctrl = init->proj_out_or_null(TypeFunc::Control); + Node* init_mem = init->proj_out_or_null(TypeFunc::Memory); MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot); transform_later(mb);
--- a/src/hotspot/share/opto/memnode.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/memnode.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -136,7 +136,7 @@ if (!(is_instance || is_boxed_value_load)) return mchain; // don't try to optimize non-instance types uint instance_id = t_oop->instance_id(); - Node *start_mem = phase->C->start()->proj_out(TypeFunc::Memory); + Node *start_mem = phase->C->start()->proj_out_or_null(TypeFunc::Memory); Node *prev = NULL; Node *result = mchain; while (prev != result) {
--- a/src/hotspot/share/opto/multnode.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/multnode.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -43,8 +43,8 @@ Node *MultiNode::match( const ProjNode *proj, const Matcher *m ) { return proj->clone(); } //------------------------------proj_out--------------------------------------- -// Get a named projection -ProjNode* MultiNode::proj_out(uint which_proj) const { +// Get a named projection or null if not found +ProjNode* MultiNode::proj_out_or_null(uint which_proj) const { assert((Opcode() != Op_If && Opcode() != Op_RangeCheck) || which_proj == (uint)true || which_proj == (uint)false, "must be 1 or 0"); assert((Opcode() != Op_If && Opcode() != Op_RangeCheck) || outcnt() == 2, "bad if #1"); for( DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++ ) { @@ -63,6 +63,13 @@ return NULL; } +// Get a named projection +ProjNode* MultiNode::proj_out(uint which_proj) const { + ProjNode* p = proj_out_or_null(which_proj); + assert(p != NULL, "named projection %u not found", which_proj); + return p; +} + //============================================================================= //------------------------------ProjNode--------------------------------------- uint ProjNode::hash() const { @@ -214,8 +221,6 @@ } ProjNode* other_proj = iff->proj_out(1-_con); - if (other_proj == NULL) // Should never happen, but make Parfait happy. - return NULL; CallStaticJavaNode* call = other_proj->is_uncommon_trap_proj(reason); if (call != NULL) { assert(reason == Deoptimization::Reason_none ||
--- a/src/hotspot/share/opto/multnode.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/multnode.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, 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. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,7 @@ virtual Node *match( const ProjNode *proj, const Matcher *m ); virtual uint ideal_reg() const { return NotAMachineReg; } ProjNode* proj_out(uint which_proj) const; // Get a named projection + ProjNode* proj_out_or_null(uint which_proj) const; };
--- a/src/hotspot/share/opto/phaseX.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/phaseX.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -1524,7 +1524,7 @@ // receiver to know when to enable the regular fall-through path // in addition to the NullPtrException path. if (use->is_CallDynamicJava() && n == use->in(TypeFunc::Parms)) { - Node* p = use->as_CallDynamicJava()->proj_out(TypeFunc::Control); + Node* p = use->as_CallDynamicJava()->proj_out_or_null(TypeFunc::Control); if (p != NULL) { add_users_to_worklist0(p); } @@ -1617,12 +1617,12 @@ if (use_op == Op_Allocate || use_op == Op_AllocateArray) { InitializeNode* init = use->as_Allocate()->initialization(); if (init != NULL) { - Node* imem = init->proj_out(TypeFunc::Memory); + Node* imem = init->proj_out_or_null(TypeFunc::Memory); if (imem != NULL) add_users_to_worklist0(imem); } } if (use_op == Op_Initialize) { - Node* imem = use->as_Initialize()->proj_out(TypeFunc::Memory); + Node* imem = use->as_Initialize()->proj_out_or_null(TypeFunc::Memory); if (imem != NULL) add_users_to_worklist0(imem); } // Loading the java mirror from a klass oop requires two loads and the type
--- a/src/hotspot/share/opto/stringopts.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/stringopts.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -362,11 +362,11 @@ // Eliminate Initialize node. assert(init->outcnt() <= 2, "only a control and memory projection expected"); assert(init->req() <= InitializeNode::RawStores, "no pending inits"); - Node *ctrl_proj = init->proj_out(TypeFunc::Control); + Node *ctrl_proj = init->proj_out_or_null(TypeFunc::Control); if (ctrl_proj != NULL) { C->gvn_replace_by(ctrl_proj, init->in(TypeFunc::Control)); } - Node *mem_proj = init->proj_out(TypeFunc::Memory); + Node *mem_proj = init->proj_out_or_null(TypeFunc::Memory); if (mem_proj != NULL) { Node *mem = init->in(TypeFunc::Memory); C->gvn_replace_by(mem_proj, mem); @@ -891,7 +891,7 @@ ctrl_path.push(cn); ctrl_path.push(cn->proj_out(0)); ctrl_path.push(cn->proj_out(0)->unique_out()); - Node* catchproj = cn->proj_out(0)->unique_out()->as_Catch()->proj_out(0); + Node* catchproj = cn->proj_out(0)->unique_out()->as_Catch()->proj_out_or_null(0); if (catchproj != NULL) { ctrl_path.push(catchproj); } @@ -1035,13 +1035,13 @@ // by calls in the region. _stringopts->_visited.Clear(); Node_List worklist; - Node* final_result = _end->proj_out(TypeFunc::Parms); + Node* final_result = _end->proj_out_or_null(TypeFunc::Parms); for (uint i = 0; i < _control.size(); i++) { CallNode* cnode = _control.at(i)->isa_Call(); if (cnode != NULL) { _stringopts->_visited.test_set(cnode->_idx); } - Node* result = cnode != NULL ? cnode->proj_out(TypeFunc::Parms) : NULL; + Node* result = cnode != NULL ? cnode->proj_out_or_null(TypeFunc::Parms) : NULL; if (result != NULL && result != final_result) { worklist.push(result); }
--- a/src/hotspot/share/opto/superword.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/opto/superword.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -190,7 +190,7 @@ int *ignored_loop_nodes = NEW_RESOURCE_ARRAY(int, ignored_size); Node_Stack nstack((int)ignored_size); CountedLoopNode *cl = lpt()->_head->as_CountedLoop(); - Node *cl_exit = cl->loopexit(); + Node *cl_exit = cl->loopexit_or_null(); int rpo_idx = _post_block.length(); assert(rpo_idx == 0, "post loop block is empty");
--- a/src/hotspot/share/prims/jni.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/prims/jni.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -2820,7 +2820,7 @@ EntryProbe; \ DT_VOID_RETURN_MARK(Get##Result##ArrayRegion); \ typeArrayOop src = typeArrayOop(JNIHandles::resolve_non_null(array)); \ - if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)src->length())) { \ + if (start < 0 || len < 0 || (start > src->length() - len)) { \ THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \ } else { \ if (len > 0) { \ @@ -2870,7 +2870,7 @@ EntryProbe; \ DT_VOID_RETURN_MARK(Set##Result##ArrayRegion); \ typeArrayOop dst = typeArrayOop(JNIHandles::resolve_non_null(array)); \ - if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)dst->length())) { \ + if (start < 0 || len < 0 || (start > dst->length() - len)) { \ THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \ } else { \ if (len > 0) { \ @@ -3106,7 +3106,7 @@ DT_VOID_RETURN_MARK(GetStringRegion); oop s = JNIHandles::resolve_non_null(string); int s_len = java_lang_String::length(s); - if (start < 0 || len < 0 || start + len > s_len) { + if (start < 0 || len < 0 || start > s_len - len) { THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException()); } else { if (len > 0) { @@ -3132,7 +3132,7 @@ DT_VOID_RETURN_MARK(GetStringUTFRegion); oop s = JNIHandles::resolve_non_null(string); int s_len = java_lang_String::length(s); - if (start < 0 || len < 0 || start + len > s_len) { + if (start < 0 || len < 0 || start > s_len - len) { THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException()); } else { //%note jni_7
--- a/src/hotspot/share/prims/jvmtiTagMap.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/prims/jvmtiTagMap.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -30,6 +30,7 @@ #include "code/codeCache.hpp" #include "jvmtifiles/jvmtiEnv.hpp" #include "memory/resourceArea.hpp" +#include "oops/access.inline.hpp" #include "oops/instanceMirrorKlass.hpp" #include "oops/objArrayKlass.hpp" #include "oops/objArrayOop.inline.hpp" @@ -52,10 +53,6 @@ #include "runtime/vm_operations.hpp" #include "services/serviceUtil.hpp" #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1SATBCardTableModRefBS.hpp" -#include "gc/parallel/parallelScavengeHeap.hpp" -#endif // INCLUDE_ALL_GCS // JvmtiTagHashmapEntry // @@ -78,22 +75,31 @@ } // constructor - JvmtiTagHashmapEntry(oop object, jlong tag) { init(object, tag); } + JvmtiTagHashmapEntry(oop object, jlong tag) { init(object, tag); } public: // accessor methods - inline oop object() const { return _object; } - inline oop* object_addr() { return &_object; } - inline jlong tag() const { return _tag; } + inline oop* object_addr() { return &_object; } + inline oop object() { return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(object_addr()); } + // Peek at the object without keeping it alive. The returned object must be + // kept alive using a normal access if it leaks out of a thread transition from VM. + inline oop object_peek() { + return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(object_addr()); + } + inline jlong tag() const { return _tag; } inline void set_tag(jlong tag) { assert(tag != 0, "can't be zero"); _tag = tag; } - inline JvmtiTagHashmapEntry* next() const { return _next; } - inline void set_next(JvmtiTagHashmapEntry* next) { _next = next; } + inline bool equals(oop object) { + return object == object_peek(); + } + + inline JvmtiTagHashmapEntry* next() const { return _next; } + inline void set_next(JvmtiTagHashmapEntry* next) { _next = next; } }; @@ -211,7 +217,7 @@ JvmtiTagHashmapEntry* entry = _table[i]; while (entry != NULL) { JvmtiTagHashmapEntry* next = entry->next(); - oop key = entry->object(); + oop key = entry->object_peek(); assert(key != NULL, "jni weak reference cleared!!"); unsigned int h = hash(key, new_size); JvmtiTagHashmapEntry* anchor = new_table[h]; @@ -304,7 +310,7 @@ unsigned int h = hash(key); JvmtiTagHashmapEntry* entry = _table[h]; while (entry != NULL) { - if (entry->object() == key) { + if (entry->equals(key)) { return entry; } entry = entry->next(); @@ -345,7 +351,7 @@ JvmtiTagHashmapEntry* entry = _table[h]; JvmtiTagHashmapEntry* prev = NULL; while (entry != NULL) { - if (key == entry->object()) { + if (entry->equals(key)) { break; } prev = entry; @@ -1535,16 +1541,12 @@ void do_entry(JvmtiTagHashmapEntry* entry) { for (int i=0; i<_tag_count; i++) { if (_tags[i] == entry->tag()) { + // The reference in this tag map could be the only (implicitly weak) + // reference to that object. If we hand it out, we need to keep it live wrt + // SATB marking similar to other j.l.ref.Reference referents. This is + // achieved by using a phantom load in the object() accessor. oop o = entry->object(); assert(o != NULL && Universe::heap()->is_in_reserved(o), "sanity check"); -#if INCLUDE_ALL_GCS - if (UseG1GC) { - // The reference in this tag map could be the only (implicitly weak) - // reference to that object. If we hand it out, we need to keep it live wrt - // SATB marking similar to other j.l.ref.Reference referents. - G1SATBCardTableModRefBS::enqueue(o); - } -#endif jobject ref = JNIHandles::make_local(JavaThread::current(), o); _object_results->append(ref); _tag_results->append((uint64_t)entry->tag()); @@ -3363,10 +3365,8 @@ while (entry != NULL) { JvmtiTagHashmapEntry* next = entry->next(); - oop* obj = entry->object_addr(); - // has object been GC'ed - if (!is_alive->do_object_b(entry->object())) { + if (!is_alive->do_object_b(entry->object_peek())) { // grab the tag jlong tag = entry->tag(); guarantee(tag != 0, "checking"); @@ -3384,7 +3384,7 @@ ++freed; } else { f->do_oop(entry->object_addr()); - oop new_oop = entry->object(); + oop new_oop = entry->object_peek(); // if the object has moved then re-hash it and move its // entry to its new location. @@ -3418,7 +3418,7 @@ // Re-add all the entries which were kept aside while (delayed_add != NULL) { JvmtiTagHashmapEntry* next = delayed_add->next(); - unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object(), size); + unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object_peek(), size); delayed_add->set_next(table[pos]); table[pos] = delayed_add; delayed_add = next;
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/prims/resolvedMethodTable.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "gc/shared/gcLocker.hpp" #include "memory/allocation.hpp" +#include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/method.hpp" #include "oops/symbol.hpp" @@ -33,24 +34,39 @@ #include "runtime/mutexLocker.hpp" #include "utilities/hashtable.inline.hpp" #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1SATBCardTableModRefBS.hpp" -#endif +oop ResolvedMethodEntry::object() { + return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(literal_addr()); +} + +oop ResolvedMethodEntry::object_no_keepalive() { + // The AS_NO_KEEPALIVE peeks at the oop without keeping it alive. + // This is dangerous in general but is okay if the loaded oop does + // not leak out past a thread transition where a safepoint can happen. + // A subsequent oop_load without AS_NO_KEEPALIVE (the object() accessor) + // keeps the oop alive before doing so. + return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(literal_addr()); +} + ResolvedMethodTable::ResolvedMethodTable() : Hashtable<oop, mtClass>(_table_size, sizeof(ResolvedMethodEntry)) { } oop ResolvedMethodTable::lookup(int index, unsigned int hash, Method* method) { for (ResolvedMethodEntry* p = bucket(index); p != NULL; p = p->next()) { if (p->hash() == hash) { - oop target = p->literal(); + + // Peek the object to check if it is the right target. + oop target = p->object_no_keepalive(); + // The method is in the table as a target already if (java_lang_invoke_ResolvedMethodName::vmtarget(target) == method) { ResourceMark rm; log_debug(membername, table) ("ResolvedMethod entry found for %s index %d", method->name_and_sig_as_C_string(), index); - return target; + // The object() accessor makes sure the target object is kept alive before + // leaking out. + return p->object(); } } } @@ -70,18 +86,6 @@ return lookup(index, hash, method); } -// Tell the GC that this oop was looked up in the table -static void ensure_oop_alive(oop mname) { - // A lookup in the ResolvedMethodTable 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 && mname != NULL) { - G1SATBCardTableModRefBS::enqueue(mname); - } -#endif -} - oop ResolvedMethodTable::basic_add(Method* method, oop rmethod_name) { assert_locked_or_safepoint(ResolvedMethodTable_lock); @@ -91,7 +95,6 @@ // One was added while aquiring the lock oop entry = lookup(index, hash, method); if (entry != NULL) { - ensure_oop_alive(entry); return entry; } @@ -100,14 +103,13 @@ ResourceMark rm; log_debug(membername, table) ("ResolvedMethod entry added for %s index %d", method->name_and_sig_as_C_string(), index); - return p->literal(); + return rmethod_name; } ResolvedMethodTable* ResolvedMethodTable::_the_table = NULL; oop ResolvedMethodTable::find_method(Method* method) { oop entry = _the_table->lookup(method); - ensure_oop_alive(entry); return entry; } @@ -147,12 +149,12 @@ ResolvedMethodEntry* entry = _the_table->bucket(i); while (entry != NULL) { _oops_counted++; - if (is_alive->do_object_b(entry->literal())) { + if (is_alive->do_object_b(entry->object_no_keepalive())) { p = entry->next_addr(); } else { _oops_removed++; if (log_is_enabled(Debug, membername, table)) { - Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(entry->literal()); + Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(entry->object_no_keepalive()); ResourceMark rm; log_debug(membername, table) ("ResolvedMethod entry removed for %s index %d", m->name_and_sig_as_C_string(), i); @@ -185,7 +187,7 @@ ResolvedMethodEntry* entry = bucket(i); while (entry != NULL) { tty->print("%d : ", i); - oop rmethod_name = entry->literal(); + oop rmethod_name = entry->object_no_keepalive(); rmethod_name->print(); Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(rmethod_name); m->print(); @@ -203,8 +205,7 @@ for (int i = 0; i < _the_table->table_size(); ++i) { ResolvedMethodEntry* entry = _the_table->bucket(i); while (entry != NULL) { - - oop mem_name = entry->literal(); + oop mem_name = entry->object_no_keepalive(); Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name); if (old_method->is_old()) {
--- a/src/hotspot/share/prims/resolvedMethodTable.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/prims/resolvedMethodTable.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -44,6 +44,9 @@ return (ResolvedMethodEntry**)HashtableEntry<oop, mtClass>::next_addr(); } + oop object(); + oop object_no_keepalive(); + void print_on(outputStream* st) const; };
--- a/src/hotspot/share/runtime/arguments.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/runtime/arguments.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,11 @@ #endif // Note: This is a special bug reporting site for the JVM -#define DEFAULT_VENDOR_URL_BUG "http://bugreport.java.com/bugreport/crash.jsp" +#ifdef VENDOR_URL_VM_BUG +# define DEFAULT_VENDOR_URL_BUG VENDOR_URL_VM_BUG +#else +# define DEFAULT_VENDOR_URL_BUG "http://bugreport.java.com/bugreport/crash.jsp" +#endif #define DEFAULT_JAVA_LAUNCHER "generic" char* Arguments::_jvm_flags_file = NULL; @@ -523,6 +527,7 @@ { "ConvertSleepToYield", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) }, { "ConvertYieldToSleep", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) }, { "MinSleepInterval", JDK_Version::jdk(9), JDK_Version::jdk(10), JDK_Version::jdk(11) }, + { "CheckAssertionStatusDirectives",JDK_Version::undefined(), JDK_Version::jdk(11), JDK_Version::jdk(12) }, { "PermSize", JDK_Version::undefined(), JDK_Version::jdk(8), JDK_Version::undefined() }, { "MaxPermSize", JDK_Version::undefined(), JDK_Version::jdk(8), JDK_Version::undefined() }, { "SharedReadWriteSize", JDK_Version::undefined(), JDK_Version::jdk(10), JDK_Version::undefined() },
--- a/src/hotspot/share/runtime/globals.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/runtime/globals.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -893,9 +893,6 @@ develop(bool, TraceJavaAssertions, false, \ "Trace java language assertions") \ \ - notproduct(bool, CheckAssertionStatusDirectives, false, \ - "Temporary - see javaClasses.cpp") \ - \ notproduct(bool, PrintMallocFree, false, \ "Trace calls to C heap malloc/free allocation") \ \
--- a/src/hotspot/share/runtime/init.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/runtime/init.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -131,6 +131,7 @@ InterfaceSupport_init(); SharedRuntime::generate_stubs(); universe2_init(); // dependent on codeCache_init and stubRoutines_init1 + javaClasses_init();// must happen after vtable initialization, before referenceProcessor_init referenceProcessor_init(); jni_handles_init(); #if INCLUDE_VM_STRUCTS @@ -150,7 +151,6 @@ if (!universe_post_init()) { return JNI_ERR; } - javaClasses_init(); // must happen after vtable initialization stubRoutines_init2(); // note: StubRoutines need 2-phase init MethodHandles::generate_adapters();
--- a/src/hotspot/share/runtime/os.hpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/runtime/os.hpp Fri Jan 19 09:32:10 2018 -0800 @@ -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. * * This code is free software; you can redistribute it and/or modify it @@ -778,7 +778,6 @@ static void* signal(int signal_number, void* handler); static void signal_raise(int signal_number); static int signal_wait(); - static int signal_lookup(); static void* user_handler(); static void terminate_signal_thread(); static int sigexitnum_pd();
--- a/src/hotspot/share/runtime/vframe_hp.cpp Thu Jan 18 11:22:28 2018 +0530 +++ b/src/hotspot/share/runtime/vframe_hp.cpp Fri Jan 19 09:32:10 2018 -0800 @@ -57,65 +57,23 @@ // There is one scv_list entry for every JVM stack state in use. int length = scv_list->length(); StackValueCollection* result = new StackValueCollection(length); - // In rare instances set_locals may have occurred in which case - // there are local values that are not described by the ScopeValue anymore - GrowableArray<jvmtiDeferredLocalVariable*>* deferred = NULL;